From 9b13ca5260b671904942fccaf25b5ed892a0860f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 6 Jun 2013 14:50:01 +0100 Subject: [PATCH 001/646] Added first FPA API functions. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 2 +- src/api/api_fpa.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++ src/api/z3.h | 1 + src/api/z3_fpa.h | 82 ++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 src/api/api_fpa.cpp create mode 100644 src/api/z3_fpa.h diff --git a/scripts/mk_project.py b/scripts/mk_project.py index e6e7d5dc8..e2bbd20ca 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -59,7 +59,7 @@ def init_project_def(): add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv') add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') add_lib('smtparser', ['portfolio'], 'parsers/smt') - API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h'] + API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_fpa.h'] add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure'], includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files) add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3') diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp new file mode 100644 index 000000000..8e8493d63 --- /dev/null +++ b/src/api/api_fpa.cpp @@ -0,0 +1,107 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + api_fpa.cpp + +Abstract: + + +Author: + + Christoph M. Wintersteiger (cwinter) 2013-06-05 + +Notes: + +--*/ +#include +#include"z3.h" +#include"api_log_macros.h" +#include"api_context.h" +#include"float_decl_plugin.h" + +extern "C" { + + Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rounding_mode_sort(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_sort r = of_sort(float_util(ctx->m()).mk_rm_sort()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(__in Z3_context c) + { + Z3_TRY; + LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_round_nearest_ties_to_even()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(__in Z3_context c) + { + Z3_TRY; + LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_round_nearest_ties_to_away()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c) + { + Z3_TRY; + LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_positive()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c) + { + Z3_TRY; + LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_negative()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c) + { + Z3_TRY; + LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_zero()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits) { + Z3_TRY; + LOG_Z3_mk_fpa_sort(c, ebits, sbits); + RESET_ERROR_CODE(); + if (ebits < 2 || sbits < 3) { + SET_ERROR_CODE(Z3_INVALID_ARG); + } + api::context * ctx = mk_c(c); + float_util fu(ctx->m()); + Z3_sort r = of_sort(fu.mk_float_sort(ebits, sbits)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + + +}; diff --git a/src/api/z3.h b/src/api/z3.h index db8becafd..2a56fa9a7 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -27,6 +27,7 @@ Notes: #include"z3_algebraic.h" #include"z3_polynomial.h" #include"z3_rcf.h" +#include"z3_fpa.h" #undef __in #undef __out diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h new file mode 100644 index 000000000..a3e61931b --- /dev/null +++ b/src/api/z3_fpa.h @@ -0,0 +1,82 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + z3_fpa.h + +Abstract: + + Additional APIs for floating-point arithmetic (FPA). + +Author: + + Christoph M. Wintersteiger (cwinter) 2013-06-05 + +Notes: + +--*/ +#ifndef _Z3_FPA_H_ +#define _Z3_FPA_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + /** + \brief Create a rounding mode sort. + + def_API('Z3_mk_fpa_rounding_mode_sort', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(__in Z3_context c); + + /** + \brief Create a numeral of rounding mode sort which represents the NearestTiesToEven rounding mode. + + def_API('Z3_mk_fpa_round_nearest_ties_to_even', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(__in Z3_context c); + + /** + \brief Create a numeral of rounding mode sort which represents the NearestTiesToAway rounding mode. + + def_API('Z3_mk_fpa_round_nearest_ties_to_away', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(__in Z3_context c); + + /** + \brief Create a numeral of rounding mode sort which represents the TowardPositive rounding mode. + + def_API('Z3_mk_fpa_round_toward_positive', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c); + + /** + \brief Create a numeral of rounding mode sort which represents the TowardNegative rounding mode. + + def_API('Z3_mk_fpa_round_toward_negative', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c); + + /** + \brief Create a numeral of rounding mode sort which represents the TowardZero rounding mode. + + def_API('Z3_mk_fpa_round_toward_zero', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c); + + + /** + \brief Create a floating point sort. + + def_API('Z3_mk_fpa_sort', SORT, (_in(CONTEXT), _in(UINT), _in(UINT))) + + \remark ebits must be larger than 1 and sbits must be larger than 2. + */ + Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits); + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif From 573ec293dc0fc6d9dc9408c832b62f55b4bfd909 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 7 Jun 2013 19:09:41 +0100 Subject: [PATCH 002/646] FPA: Added core C API. Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 253 +++++++++++++++++++++++++++++++++++- src/api/z3_fpa.h | 220 ++++++++++++++++++++++++++++++- src/ast/float_decl_plugin.h | 3 +- 3 files changed, 469 insertions(+), 7 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 8e8493d63..74030a0b0 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -33,7 +33,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(__in Z3_context c) + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); @@ -44,7 +44,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(__in Z3_context c) + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); @@ -55,7 +55,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c) + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); @@ -66,7 +66,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c) + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); @@ -77,7 +77,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c) + Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); @@ -102,6 +102,249 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_nan(Z3_context c, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_nan(c, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_nan(to_sort(s))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_inf(Z3_context c, Z3_sort s, Z3_bool negative) { + Z3_TRY; + LOG_Z3_mk_fpa_inf(c, s, negative); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util fu(ctx->m()); + Z3_ast r = of_ast(negative != 0 ? fu.mk_minus_inf(to_sort(s)) : fu.mk_plus_inf(to_sort(s))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_abs(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_abs(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_neg(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_neg(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_uminus(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_add(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_add(c, rm, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_sub(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_add(c, rm, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_mul(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_add(c, rm, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_div(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_add(c, rm, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_fma(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2, Z3_ast t3) { + Z3_TRY; + LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_fused_ma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_sqrt(Z3_context c, Z3_ast rm, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_sqrt(c, rm, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_sqrt(to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_rem(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_rem(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_rem(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_eq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_eq(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_float_eq(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_leq(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_le(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_lt(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_lt(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_lt(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_geq(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_ge(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_gt(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_gt(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_gt(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_is_normal(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_is_normal(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_is_normal(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_is_subnormal(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_is_subnormal(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_is_subnormal(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_is_zero(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_is_zero(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_is_zero(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_is_inf(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_is_inf(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_is_inf(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_is_nan(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_is_nan(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_is_nan(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_min(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_min(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_max(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_max(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_max(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_convert(Z3_context c, Z3_sort s, Z3_ast rm, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_convert(c, s, rm, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util fu(ctx->m()); + expr * args [2] = { to_expr(rm), to_expr(t) }; + Z3_ast r = of_ast(ctx->m().mk_app(fu.get_family_id(), OP_TO_FLOAT, + to_sort(s)->get_num_parameters(), to_sort(s)->get_parameters(), + 2, args)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } }; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index a3e61931b..c9feb0778 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -65,7 +65,6 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c); - /** \brief Create a floating point sort. @@ -74,7 +73,226 @@ extern "C" { \remark ebits must be larger than 1 and sbits must be larger than 2. */ Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits); + + /** + \brief Create a NaN of sort s. + + def_API('Z3_mk_fpa_nan', AST, (_in(CONTEXT),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_nan(__in Z3_context c, __in Z3_sort s); + + /** + \brief Create a floating point infinity of sort s. + + When \c negative is true, -Inf will be generated instead of +Inf. + + def_API('Z3_mk_fpa_inf', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) + */ + Z3_ast Z3_API Z3_mk_fpa_inf(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); + /** + \brief Floating-point absolute value + + t must have floating point sort. + + def_API('Z3_mk_fpa_abs', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_abs(__in Z3_context c, __in Z3_ast t); + + /** + \brief Floating-point negation + + t must have floating point sort. + + def_API('Z3_mk_fpa_neg', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_neg(__in Z3_context c, __in Z3_ast t); + + /** + \brief Floating-point addition + + rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_add', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_add(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point subtraction + + rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_sub', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_sub(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point multiplication + + rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_mul', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_mul(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point division + + The nodes rm must be of FPA rounding mode sort t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_div', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_div(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point fused multiply-add. + + The result is round((t1 * t2) + t3) + + rm must be of FPA rounding mode sort, t1, t2, and t3 must have floating point sort. + + def_API('Z3_mk_fpa_fma', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_fma(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t1, __in Z3_ast t2, __in Z3_ast t3); + + /** + \brief Floating-point square root + + rm must be of FPA rounding mode sort, t must have floating point sort. + + def_API('Z3_mk_fpa_sqrt', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_sqrt(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t); + + /** + \brief Floating-point remainder + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_rem', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_rem(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point equality + + Note that this is IEEE 754 equality (as opposed to SMT-LIB =). + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_eq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point less-than or equal + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_leq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_leq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point less-than + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_lt', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_lt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + + /** + \brief Floating-point greater-than or equal + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_geq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_geq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Floating-point greater-than + + t1 and t2 must have floating point sort. + + def_API('Z3_mk_fpa_gt', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_gt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Predicate indicating whether t is a normal floating point number + + t must have floating point sort. + + def_API('Z3_mk_fpa_is_normal', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_normal(__in Z3_context c, __in Z3_ast t); + + /** + \brief Predicate indicating whether t is a subnormal floating point number + + t must have floating point sort. + + def_API('Z3_mk_fpa_is_subnormal', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_subnormal(__in Z3_context c, __in Z3_ast t); + + /** + \brief Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. + + t must have floating point sort. + + def_API('Z3_mk_fpa_is_zero', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_zero(__in Z3_context c, __in Z3_ast t); + + /** + \brief Predicate indicating whether t is a floating point number representing +Inf or -Inf + + t must have floating point sort. + + def_API('Z3_mk_fpa_is_inf', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_inf(__in Z3_context c, __in Z3_ast t); + + /** + \brief Predicate indicating whether t is a NaN + + t must have floating point sort. + + def_API('Z3_mk_fpa_is_nan', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_nan(__in Z3_context c, __in Z3_ast t); + + /** + \brief Minimum of floating point numbers + + t1, t2 must have floating point sort. + + def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Maximum of floating point numbers + + t1, t2 must have floating point sort. + + def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Conversion of a floating point number to sort s. + + s must be a floating point sort, rm must have rounding mode sort, and t must have floating point sort. + + def_API('Z3_mk_fpa_convert', AST, (_in(CONTEXT),_in(SORT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); + #ifdef __cplusplus }; #endif // __cplusplus diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index f1b60a91b..deda7e045 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -178,6 +178,7 @@ public: family_id get_fid() const { return m_fid; } family_id get_family_id() const { return m_fid; } arith_util & au() { return m_a_util; } + float_decl_plugin & plugin() { return *m_plugin; } sort * mk_float_sort(unsigned ebits, unsigned sbits); sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); } @@ -211,7 +212,7 @@ public: bool is_nan(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nan(v); } bool is_plus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pinf(v); } - bool is_minus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); } + bool is_minus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); } bool is_zero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_zero(v); } bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } From ebbdff87577473d14c990e580118a42bc2c937fa Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 10 Jun 2013 15:53:24 +0100 Subject: [PATCH 003/646] doc bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/IntExpr.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/dotnet/IntExpr.cs b/src/api/dotnet/IntExpr.cs index 4c52ec79f..58bf1b973 100644 --- a/src/api/dotnet/IntExpr.cs +++ b/src/api/dotnet/IntExpr.cs @@ -1,5 +1,5 @@ /*++ -Copyright () 2012 Microsoft Corporation +Copyright (c) 2012 Microsoft Corporation Module Name: From a36a09e08171e7e0d0c00f1bab508a780b5bbae2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 10 Jun 2013 15:53:41 +0100 Subject: [PATCH 004/646] FPA API: minor fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 30 ++++++- src/api/z3_fpa.h | 191 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 194 insertions(+), 27 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 74030a0b0..cfb5a2624 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -122,6 +122,19 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } + + Z3_ast Z3_API Z3_mk_double(Z3_context c, double v, Z3_sort ty) { + Z3_TRY; + LOG_Z3_mk_double(c, v, ty); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util fu(ctx->m()); + mpf tmp; + fu.fm().set(tmp, fu.get_ebits(to_sort(ty)), fu.get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(fu.mk_value(tmp)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t) { Z3_TRY; @@ -223,9 +236,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_ast Z3_API Z3_mk_fpa_le(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; - LOG_Z3_mk_fpa_leq(c, t1, t2); + LOG_Z3_mk_fpa_le(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(float_util(ctx->m()).mk_le(to_expr(t1), to_expr(t2))); @@ -243,9 +256,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_ast Z3_API Z3_mk_fpa_ge(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; - LOG_Z3_mk_fpa_geq(c, t1, t2); + LOG_Z3_mk_fpa_ge(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(float_util(ctx->m()).mk_ge(to_expr(t1), to_expr(t2))); @@ -347,4 +360,13 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_to_ieee_bv(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(float_util(ctx->m()).mk_to_ieee_bv(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } }; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index c9feb0778..93268b821 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -25,6 +25,8 @@ extern "C" { /** \brief Create a rounding mode sort. + + \param c logical context. def_API('Z3_mk_fpa_rounding_mode_sort', SORT, (_in(CONTEXT),)) */ @@ -32,6 +34,8 @@ extern "C" { /** \brief Create a numeral of rounding mode sort which represents the NearestTiesToEven rounding mode. + + \param c logical context. def_API('Z3_mk_fpa_round_nearest_ties_to_even', AST, (_in(CONTEXT),)) */ @@ -39,6 +43,8 @@ extern "C" { /** \brief Create a numeral of rounding mode sort which represents the NearestTiesToAway rounding mode. + + \param c logical context. def_API('Z3_mk_fpa_round_nearest_ties_to_away', AST, (_in(CONTEXT),)) */ @@ -46,6 +52,8 @@ extern "C" { /** \brief Create a numeral of rounding mode sort which represents the TowardPositive rounding mode. + + \param c logical context. def_API('Z3_mk_fpa_round_toward_positive', AST, (_in(CONTEXT),)) */ @@ -54,28 +62,41 @@ extern "C" { /** \brief Create a numeral of rounding mode sort which represents the TowardNegative rounding mode. + \param c logical context. + def_API('Z3_mk_fpa_round_toward_negative', AST, (_in(CONTEXT),)) */ Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c); /** \brief Create a numeral of rounding mode sort which represents the TowardZero rounding mode. + + \param c logical context. def_API('Z3_mk_fpa_round_toward_zero', AST, (_in(CONTEXT),)) */ Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c); + + /** \brief Create a floating point sort. - - def_API('Z3_mk_fpa_sort', SORT, (_in(CONTEXT), _in(UINT), _in(UINT))) + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort', SORT, (_in(CONTEXT), _in(UINT), _in(UINT))) */ Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits); /** \brief Create a NaN of sort s. + + \param c logical context. + \param s target sort def_API('Z3_mk_fpa_nan', AST, (_in(CONTEXT),_in(SORT))) */ @@ -83,16 +104,41 @@ extern "C" { /** \brief Create a floating point infinity of sort s. + + \param c logical context. + \param s target sort + \param negative indicates whether the result should be negative When \c negative is true, -Inf will be generated instead of +Inf. def_API('Z3_mk_fpa_inf', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) */ Z3_ast Z3_API Z3_mk_fpa_inf(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); - + + /** + \brief Create a numeral of floating point sort. + + This function can be use to create numerals that fit in a double value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. + + \params c logical context. + \params v value. + \params ty sort. + + ty must be a floating point sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_double(__in Z3_context c, __in double v, __in Z3_sort ty); + /** \brief Floating-point absolute value + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_abs', AST, (_in(CONTEXT),_in(AST))) @@ -102,6 +148,9 @@ extern "C" { /** \brief Floating-point negation + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_neg', AST, (_in(CONTEXT),_in(AST))) @@ -111,7 +160,12 @@ extern "C" { /** \brief Floating-point addition - rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + \param c logical context. + \param rm rounding mode + \param t1 floating-point term. + \param t2 floating-point term. + + rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_add', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -120,7 +174,12 @@ extern "C" { /** \brief Floating-point subtraction - rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + \param c logical context. + \param rm rounding mode + \param t1 floating-point term. + \param t2 floating-point term. + + rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_sub', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -129,7 +188,12 @@ extern "C" { /** \brief Floating-point multiplication - rm must be of FPA rounding mode sort, t1 and t2 must have floating point sort. + \param c logical context. + \param rm rounding mode + \param t1 floating-point term. + \param t2 floating-point term. + + rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_mul', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -138,7 +202,12 @@ extern "C" { /** \brief Floating-point division - The nodes rm must be of FPA rounding mode sort t1 and t2 must have floating point sort. + \param c logical context. + \param rm rounding mode + \param t1 floating-point term. + \param t2 floating-point term. + + The nodes rm must be of FPA rounding mode sort t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_div', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -147,9 +216,14 @@ extern "C" { /** \brief Floating-point fused multiply-add. + \param c logical context. + \param rm rounding mode + \param t1 floating-point term. + \param t2 floating-point term. + The result is round((t1 * t2) + t3) - rm must be of FPA rounding mode sort, t1, t2, and t3 must have floating point sort. + rm must be of FPA rounding mode sort, t1, t2, and t3 must have the same floating point sort. def_API('Z3_mk_fpa_fma', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(AST))) */ @@ -158,6 +232,10 @@ extern "C" { /** \brief Floating-point square root + \param c logical context. + \param rm rounding mode + \param t floating-point term. + rm must be of FPA rounding mode sort, t must have floating point sort. def_API('Z3_mk_fpa_sqrt', AST, (_in(CONTEXT),_in(AST),_in(AST))) @@ -167,7 +245,11 @@ extern "C" { /** \brief Floating-point remainder - t1 and t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_rem', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ @@ -176,27 +258,39 @@ extern "C" { /** \brief Floating-point equality + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + Note that this is IEEE 754 equality (as opposed to SMT-LIB =). - t1 and t2 must have floating point sort. + t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_eq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point less-than or equal + \brief Floating-point less than or equal - t1 and t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1 and t2 must have the same floating point sort. - def_API('Z3_mk_fpa_leq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + def_API('Z3_mk_fpa_le', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_leq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + Z3_ast Z3_API Z3_mk_fpa_le(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** \brief Floating-point less-than - t1 and t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_lt', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ @@ -204,18 +298,26 @@ extern "C" { /** - \brief Floating-point greater-than or equal + \brief Floating-point greater than or equal - t1 and t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1 and t2 must have the same floating point sort. - def_API('Z3_mk_fpa_geq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + def_API('Z3_mk_fpa_ge', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_geq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + Z3_ast Z3_API Z3_mk_fpa_ge(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** \brief Floating-point greater-than - t1 and t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1 and t2 must have the same floating point sort. def_API('Z3_mk_fpa_gt', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ @@ -224,6 +326,9 @@ extern "C" { /** \brief Predicate indicating whether t is a normal floating point number + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_is_normal', AST, (_in(CONTEXT),_in(AST))) @@ -233,6 +338,9 @@ extern "C" { /** \brief Predicate indicating whether t is a subnormal floating point number + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_is_subnormal', AST, (_in(CONTEXT),_in(AST))) @@ -242,6 +350,9 @@ extern "C" { /** \brief Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_is_zero', AST, (_in(CONTEXT),_in(AST))) @@ -251,6 +362,9 @@ extern "C" { /** \brief Predicate indicating whether t is a floating point number representing +Inf or -Inf + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_is_inf', AST, (_in(CONTEXT),_in(AST))) @@ -260,6 +374,9 @@ extern "C" { /** \brief Predicate indicating whether t is a NaN + \param c logical context. + \param t floating-point term. + t must have floating point sort. def_API('Z3_mk_fpa_is_nan', AST, (_in(CONTEXT),_in(AST))) @@ -269,7 +386,11 @@ extern "C" { /** \brief Minimum of floating point numbers - t1, t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1, t2 must have the same floating point sort. def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ @@ -278,20 +399,44 @@ extern "C" { /** \brief Maximum of floating point numbers - t1, t2 must have floating point sort. + \param c logical context. + \param t1 floating-point term. + \param t2 floating-point term. + + t1, t2 must have the same floating point sort. def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Conversion of a floating point number to sort s. + \brief Conversion of a floating point number to another floating-point sort s. + + Produces a term that represents the conversion of a floating-point term t to a different + floating point sort s. If necessary, rounding according to rm is applied. + + \param c logical context. + \param s floating-point sort. + \param rm rounding mode. + \param t floating-point term. s must be a floating point sort, rm must have rounding mode sort, and t must have floating point sort. def_API('Z3_mk_fpa_convert', AST, (_in(CONTEXT),_in(SORT),_in(AST),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); + + /** + \brief Conversion of a floating point term to a bit-vector term in IEEE754 format. + + \param c logical context. + \param t floating-point term. + + t must have floating point sort. The size of the resulting bit-vector is automatically determined. + + def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); #ifdef __cplusplus }; From e14819c1b1eddbe05e7240e43543cd0d8cbf8889 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 10 Jun 2013 15:54:20 +0100 Subject: [PATCH 005/646] FPA: Added .NET API calls Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 365 +++++++++++++++++++++++++++++ src/api/dotnet/FPExpr.cs | 46 ++++ src/api/dotnet/FPNum.cs | 47 ++++ src/api/dotnet/FPRMExpr.cs | 46 ++++ src/api/dotnet/FPRMNum.cs | 47 ++++ src/api/dotnet/FPRMSort.cs | 43 ++++ src/api/dotnet/FPSort.cs | 43 ++++ src/api/dotnet/Microsoft.Z3.csproj | 8 +- 8 files changed, 644 insertions(+), 1 deletion(-) create mode 100644 src/api/dotnet/FPExpr.cs create mode 100644 src/api/dotnet/FPNum.cs create mode 100644 src/api/dotnet/FPRMExpr.cs create mode 100644 src/api/dotnet/FPRMNum.cs create mode 100644 src/api/dotnet/FPRMSort.cs create mode 100644 src/api/dotnet/FPSort.cs diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 68cca046e..1e9bd1323 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3428,6 +3428,371 @@ namespace Microsoft.Z3 } #endregion + #region Floating-Point Arithmetic + /// + /// Create a floating point rounding mode sort. + /// + public FPRMSort MkFPRMSort() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMSort(this); + } + + /// + /// Create a NearestTiesToEven rounding mode numeral. + /// + public FPRMNum MkFPRMNearestTiesToEven() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx)); + } + + /// + /// Create a NearestTiesToAway rounding mode numeral. + /// + public FPRMNum MkFPRMNearestTiesToAway() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); + } + + /// + /// Create a TowardPositive rounding mode numeral. + /// + public FPRMNum MkFPRMTowardPositive() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); + } + + /// + /// Create a TowardNegative rounding mode numeral. + /// + public FPRMNum MkFPRMTowardNegative() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); + } + + /// + /// Create a TowardZero rounding mode numeral. + /// + public FPRMNum MkFPRMTowardZero() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); + } + + /// + /// Create a floating point sort. + /// + /// exponent bits in the floating point sort. + /// significand bits in the floating point sort. + public FPSort MkFPSort(uint ebits, uint sbits) + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, ebits, sbits); + } + + /// + /// Create a floating point NaN numeral. + /// + /// A string representing the value in decimal notation. + /// floating point sort. + public FPNum MkFPNaN(double v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_nan(nCtx, s.NativeObject)); + } + + /// + /// Create a floating point Inf numeral. + /// + /// A string representing the value in decimal notation. + /// floating point sort. + /// indicates whether the result should be negative. + public FPNum MkFPInf(double v, FPSort s, bool negative) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_inf(nCtx, s.NativeObject, negative ? 1 : 0)); + } + + /// + /// Create a floating point numeral. + /// + /// A string representing the value in decimal notation. + /// floating point sort + public FPNum MkFP(double v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_double(this.nCtx, v, s.NativeObject)); + } + + /// + /// Floating-point absolute value + /// + /// floating point term + FPExpr MkFPAbs(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_abs(this.nCtx, t.NativeObject)); + } + + /// + /// Floating-point negation + /// + /// floating point term + FPExpr MkFPNeg(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_neg(this.nCtx, t.NativeObject)); + } + + /// + /// Floating-point addition + /// + /// rounding mode term + /// floating point term + /// floating point term + FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_add(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point subtraction + /// + /// rounding mode term + /// floating point term + /// floating point term + FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_sub(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point multiplication + /// + /// rounding mode term + /// floating point term + /// floating point term + FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_mul(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point division + /// + /// rounding mode term + /// floating point term + /// floating point term + FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_div(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point fused multiply-add + /// + /// + /// The result is round((t1 * t2) + t3) + /// + /// rounding mode term + /// floating point term + /// floating point term + /// floating point term + FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_fma(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject, t3.NativeObject)); + } + + /// + /// Floating-point square root + /// + /// floating point term + FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_sqrt(this.nCtx, rm.NativeObject, t.NativeObject)); + } + + /// + /// Floating-point remainder + /// + /// floating point term + /// floating point term + FPExpr MkFPRem(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_rem(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point equality + /// + /// + /// Note that this is IEEE 754 equality (as opposed to standard =). + /// + /// floating point term + /// floating point term + BoolExpr MkFPEq(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point less than or equal + /// + /// floating point term + /// floating point term + BoolExpr MkFPLe(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_le(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point less than + /// + /// floating point term + /// floating point term + BoolExpr MkFPLt(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_lt(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point greater than or equal + /// + /// floating point term + /// floating point term + BoolExpr MkFPGe(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_ge(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point greater than + /// + /// floating point term + /// floating point term + BoolExpr MkFPGt(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_gt(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Predicate indicating whether t is a normal floating point number + /// + /// floating point term + BoolExpr MkFPIsNormal(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_normal(this.nCtx, t.NativeObject)); + } + + /// + /// Predicate indicating whether t is a subnormal floating point number + /// + /// floating point term + BoolExpr MkFPIsSubnormal(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_subnormal(this.nCtx, t.NativeObject)); + } + + /// + /// Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. + /// + /// floating point term + BoolExpr MkFPIsZero(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_zero(this.nCtx, t.NativeObject)); + } + + /// + /// Predicate indicating whether t is a floating point number representing +Inf or -Inf + /// + /// floating point term + BoolExpr MkFPIsInf(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_inf(this.nCtx, t.NativeObject)); + } + + /// + /// Predicate indicating whether t is a NaN + /// + /// floating point term + BoolExpr MkFPIsNaN(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_nan(this.nCtx, t.NativeObject)); + } + + /// + /// Floating-point minimum + /// + /// floating point term + /// floating point term + FPExpr MkFPMin(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point maximium + /// + /// floating point term + /// floating point term + FPExpr MkFPMax(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Conversion of a floating point number to another floating-point sort s. + /// + /// + /// Produces a term that represents the conversion of a floating-point term t to a different + /// floating point sort s. If necessary, rounding according to rm is applied. + /// + /// floating point sort + /// floating point rounding mode term + /// floating point term + FPExpr MkFPConvert(FPSort s, FPRMExpr rm, FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_convert(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); + } + + /// + /// Conversion of a floating point term to a bit-vector term in IEEE754 format. + /// + /// + /// The size of the resulting bit-vector is automatically determined. + /// + /// floating point term + FPExpr MkFPToIEEEBV(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject)); + } + + #endregion #region Miscellaneous /// diff --git a/src/api/dotnet/FPExpr.cs b/src/api/dotnet/FPExpr.cs new file mode 100644 index 000000000..66b3fc10d --- /dev/null +++ b/src/api/dotnet/FPExpr.cs @@ -0,0 +1,46 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPExpr.cs + +Abstract: + + Z3 Managed API: Floating Point Expressions + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Floating Point Expressions + /// + public class FPExpr : Expr + { + #region Internal + internal protected FPExpr(Context ctx) + : base(ctx) + { + Contract.Requires(ctx != null); + } + internal FPExpr(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + #endregion + } +} diff --git a/src/api/dotnet/FPNum.cs b/src/api/dotnet/FPNum.cs new file mode 100644 index 000000000..044598e58 --- /dev/null +++ b/src/api/dotnet/FPNum.cs @@ -0,0 +1,47 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPNum.cs + +Abstract: + + Z3 Managed API: Floating Point Numerals + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +using System; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Floatiung Point Numerals + /// + [ContractVerification(true)] + public class FPNum : FPExpr + { + + #region Internal + internal FPNum(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + #endregion + + /// + /// Returns a string representation of the numeral. + /// + public override string ToString() + { + return Native.Z3_get_numeral_string(Context.nCtx, NativeObject); + } + } +} diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs new file mode 100644 index 000000000..fa43a346a --- /dev/null +++ b/src/api/dotnet/FPRMExpr.cs @@ -0,0 +1,46 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMExpr.cs + +Abstract: + + Z3 Managed API: Floating Point Expressions over Rounding Modes + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Floating Point Expressions + /// + public class FPRMExpr : Expr + { + #region Internal + internal protected FPRMExpr(Context ctx) + : base(ctx) + { + Contract.Requires(ctx != null); + } + internal FPRMExpr(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + #endregion + } +} diff --git a/src/api/dotnet/FPRMNum.cs b/src/api/dotnet/FPRMNum.cs new file mode 100644 index 000000000..eaf105718 --- /dev/null +++ b/src/api/dotnet/FPRMNum.cs @@ -0,0 +1,47 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMNum.cs + +Abstract: + + Z3 Managed API: Floating Point Rounding Mode Numerals + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +using System; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Floatiung Point Rounding Mode Numerals + /// + [ContractVerification(true)] + public class FPRMNum : FPRMExpr + { + + #region Internal + internal FPRMNum(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + #endregion + + /// + /// Returns a string representation of the numeral. + /// + public override string ToString() + { + return Native.Z3_get_numeral_string(Context.nCtx, NativeObject); + } + } +} diff --git a/src/api/dotnet/FPRMSort.cs b/src/api/dotnet/FPRMSort.cs new file mode 100644 index 000000000..23d454a65 --- /dev/null +++ b/src/api/dotnet/FPRMSort.cs @@ -0,0 +1,43 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMSort.cs + +Abstract: + + Z3 Managed API: Floating Point Rounding Mode Sorts + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ + +using System; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// A floating point rounding mode sort + /// + public class FPRMSort : Sort + { + #region Internal + internal FPRMSort(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + internal FPRMSort(Context ctx) + : base(ctx, Native.Z3_mk_fpa_rounding_mode_sort(ctx.nCtx)) + { + Contract.Requires(ctx != null); + } + #endregion + } +} \ No newline at end of file diff --git a/src/api/dotnet/FPSort.cs b/src/api/dotnet/FPSort.cs new file mode 100644 index 000000000..a79557ae6 --- /dev/null +++ b/src/api/dotnet/FPSort.cs @@ -0,0 +1,43 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPSort.cs + +Abstract: + + Z3 Managed API: Floating Point Sorts + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ + +using System; +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// A floating point sort + /// + public class FPSort : Sort + { + #region Internal + internal FPSort(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + internal FPSort(Context ctx, uint ebits, uint sbits) + : base(ctx, Native.Z3_mk_fpa_sort(ctx.nCtx, ebits, sbits)) + { + Contract.Requires(ctx != null); + } + #endregion + } +} diff --git a/src/api/dotnet/Microsoft.Z3.csproj b/src/api/dotnet/Microsoft.Z3.csproj index 9eb9eb660..083cd048f 100644 --- a/src/api/dotnet/Microsoft.Z3.csproj +++ b/src/api/dotnet/Microsoft.Z3.csproj @@ -341,6 +341,12 @@ + + + + + + @@ -399,4 +405,4 @@ --> - + \ No newline at end of file From a9840b291f2ce960910b7fec6209e74a8b02d665 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 10 Jun 2013 19:06:45 +0100 Subject: [PATCH 006/646] FPA API: Tied into rest of the API; added numeral/value handling through existing functions; added trivial .NET example. Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 12 ++++++ src/api/api_ast.cpp | 6 +++ src/api/api_context.cpp | 2 + src/api/api_context.h | 5 +++ src/api/api_fpa.cpp | 78 ++++++++++++++++++------------------- src/api/api_numeral.cpp | 35 ++++++++++++++--- src/api/dotnet/Expr.cs | 8 +++- src/api/z3_api.h | 2 + src/ast/float_decl_plugin.h | 8 ++-- 9 files changed, 104 insertions(+), 52 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 2085de296..c75553e7b 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2022,6 +2022,17 @@ namespace test_mapi // Console.WriteLine("{0}", ctx.MkEq(s1, t1)); } + public static void FloatingPointExample(Context ctx) + { + Console.WriteLine("FloatingPointExample"); + + FPSort s = ctx.MkFPSort(11, 53); + Console.WriteLine("Sort: {0}", s); + + FPNum n = (FPNum) ctx.MkNumeral("0.125", s); + Console.WriteLine("Numeral: {0}", n.ToString()); + } + static void Main(string[] args) { try @@ -2063,6 +2074,7 @@ namespace test_mapi FindSmallModelExample(ctx); SimplifierExample(ctx); FiniteDomainExample(ctx); + FloatingPointExample(ctx); } // These examples need proof generation turned on. diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 6855f6209..ccc2cbf88 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -647,6 +647,12 @@ extern "C" { else if (fid == mk_c(c)->get_datalog_fid() && k == datalog::DL_FINITE_SORT) { return Z3_FINITE_DOMAIN_SORT; } + else if (fid == mk_c(c)->get_fpa_fid() && k == FLOAT_SORT) { + return Z3_FLOATING_POINT_SORT; + } + else if (fid == mk_c(c)->get_fpa_fid() && k == ROUNDING_MODE_SORT) { + return Z3_FLOATING_POINT_ROUNDING_MODE_SORT; + } else { return Z3_UNKNOWN_SORT; } diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index cf179332a..f4314dcca 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -88,6 +88,7 @@ namespace api { m_arith_util(m()), m_bv_util(m()), m_datalog_util(m()), + m_float_util(m()), m_last_result(m()), m_ast_trail(m()), m_replay_stack() { @@ -112,6 +113,7 @@ namespace api { m_array_fid = m().mk_family_id("array"); m_dt_fid = m().mk_family_id("datatype"); m_datalog_fid = m().mk_family_id("datalog_relation"); + m_fpa_fid = m().mk_family_id("float"); m_dt_plugin = static_cast(m().get_plugin(m_dt_fid)); if (!m_user_ref_count) { diff --git a/src/api/api_context.h b/src/api/api_context.h index e0c95b07b..f409a4ece 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -27,6 +27,7 @@ Revision History: #include"bv_decl_plugin.h" #include"datatype_decl_plugin.h" #include"dl_decl_plugin.h" +#include"float_decl_plugin.h" #include"smt_kernel.h" #include"smt_params.h" #include"event_handler.h" @@ -56,6 +57,7 @@ namespace api { arith_util m_arith_util; bv_util m_bv_util; datalog::dl_decl_util m_datalog_util; + float_util m_float_util; // Support for old solver API smt_params m_fparams; @@ -75,6 +77,7 @@ namespace api { family_id m_bv_fid; family_id m_dt_fid; family_id m_datalog_fid; + family_id m_fpa_fid; datatype_decl_plugin * m_dt_plugin; std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world. @@ -115,12 +118,14 @@ namespace api { arith_util & autil() { return m_arith_util; } bv_util & bvutil() { return m_bv_util; } datalog::dl_decl_util & datalog_util() { return m_datalog_util; } + float_util & float_util() { return m_float_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; } + family_id get_fpa_fid() const { return m_fpa_fid; } datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; } Z3_error_code get_error_code() const { return m_error_code; } diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index cfb5a2624..278a0556a 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -28,7 +28,7 @@ extern "C" { LOG_Z3_mk_fpa_rounding_mode_sort(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_sort r = of_sort(float_util(ctx->m()).mk_rm_sort()); + Z3_sort r = of_sort(ctx->float_util().mk_rm_sort()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -39,7 +39,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_round_nearest_ties_to_even()); + Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_even()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -50,7 +50,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_round_nearest_ties_to_away()); + Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_away()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -61,7 +61,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_positive()); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -72,7 +72,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_negative()); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -83,7 +83,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_round_toward_zero()); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -95,9 +95,8 @@ extern "C" { if (ebits < 2 || sbits < 3) { SET_ERROR_CODE(Z3_INVALID_ARG); } - api::context * ctx = mk_c(c); - float_util fu(ctx->m()); - Z3_sort r = of_sort(fu.mk_float_sort(ebits, sbits)); + api::context * ctx = mk_c(c); + Z3_sort r = of_sort(ctx->float_util().mk_float_sort(ebits, sbits)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -107,7 +106,7 @@ extern "C" { LOG_Z3_mk_fpa_nan(c, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_nan(to_sort(s))); + Z3_ast r = of_ast(ctx->float_util().mk_nan(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -117,8 +116,7 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util fu(ctx->m()); - Z3_ast r = of_ast(negative != 0 ? fu.mk_minus_inf(to_sort(s)) : fu.mk_plus_inf(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_minus_inf(to_sort(s)) : ctx->float_util().mk_plus_inf(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -128,10 +126,9 @@ extern "C" { LOG_Z3_mk_double(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util fu(ctx->m()); - mpf tmp; - fu.fm().set(tmp, fu.get_ebits(to_sort(ty)), fu.get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(fu.mk_value(tmp)); + scoped_mpf tmp(ctx->float_util().fm()); + ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -141,7 +138,7 @@ extern "C" { LOG_Z3_mk_fpa_abs(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_abs(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_abs(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -151,7 +148,7 @@ extern "C" { LOG_Z3_mk_fpa_neg(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_uminus(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_uminus(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -161,7 +158,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -171,7 +168,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -181,7 +178,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -191,7 +188,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -201,7 +198,7 @@ extern "C" { LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_fused_ma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); + Z3_ast r = of_ast(ctx->float_util().mk_fused_ma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -211,7 +208,7 @@ extern "C" { LOG_Z3_mk_fpa_sqrt(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_sqrt(to_expr(rm), to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_sqrt(to_expr(rm), to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -221,7 +218,7 @@ extern "C" { LOG_Z3_mk_fpa_rem(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_rem(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_rem(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -231,7 +228,7 @@ extern "C" { LOG_Z3_mk_fpa_eq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_float_eq(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_float_eq(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -241,7 +238,7 @@ extern "C" { LOG_Z3_mk_fpa_le(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_le(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_le(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -251,7 +248,7 @@ extern "C" { LOG_Z3_mk_fpa_lt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_lt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_lt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -261,7 +258,7 @@ extern "C" { LOG_Z3_mk_fpa_ge(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_ge(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_ge(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -271,7 +268,7 @@ extern "C" { LOG_Z3_mk_fpa_gt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_gt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_gt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -281,7 +278,7 @@ extern "C" { LOG_Z3_mk_fpa_is_normal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_is_normal(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_is_normal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -291,7 +288,7 @@ extern "C" { LOG_Z3_mk_fpa_is_subnormal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_is_subnormal(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_is_subnormal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -301,7 +298,7 @@ extern "C" { LOG_Z3_mk_fpa_is_zero(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_is_zero(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_is_zero(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -311,7 +308,7 @@ extern "C" { LOG_Z3_mk_fpa_is_inf(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_is_inf(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_is_inf(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -321,7 +318,7 @@ extern "C" { LOG_Z3_mk_fpa_is_nan(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_is_nan(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_is_nan(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -331,7 +328,7 @@ extern "C" { LOG_Z3_mk_fpa_min(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_min(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_min(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -341,7 +338,7 @@ extern "C" { LOG_Z3_mk_fpa_max(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_max(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_max(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -350,10 +347,9 @@ extern "C" { Z3_TRY; LOG_Z3_mk_fpa_convert(c, s, rm, t); RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - float_util fu(ctx->m()); + api::context * ctx = mk_c(c); expr * args [2] = { to_expr(rm), to_expr(t) }; - Z3_ast r = of_ast(ctx->m().mk_app(fu.get_family_id(), OP_TO_FLOAT, + Z3_ast r = of_ast(ctx->m().mk_app(ctx->float_util().get_family_id(), OP_TO_FLOAT, to_sort(s)->get_num_parameters(), to_sort(s)->get_parameters(), 2, args)); RETURN_Z3(r); @@ -365,7 +361,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ieee_bv(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(float_util(ctx->m()).mk_to_ieee_bv(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_to_ieee_bv(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index d4a6587bc..6924afff3 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -23,13 +23,15 @@ Revision History: #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" #include"algebraic_numbers.h" +#include"float_decl_plugin.h" 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()) { + fid != mk_c(c)->get_datalog_fid() && + fid != mk_c(c)->get_fpa_fid()) { return false; } return true; @@ -69,7 +71,19 @@ extern "C" { } ++m; } - ast * a = mk_c(c)->mk_numeral_core(rational(n), to_sort(ty)); + ast * a = 0; + sort * _ty = to_sort(ty); + if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) + { + // avoid expanding floats into huge rationals. + float_util & fu = mk_c(c)->float_util(); + scoped_mpf t(fu.fm()); + fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n); + a = fu.mk_value(t); + mk_c(c)->save_ast_trail(a); + } + else + a = mk_c(c)->mk_numeral_core(rational(n), _ty); RETURN_Z3(of_ast(a)); Z3_CATCH_RETURN(0); } @@ -131,7 +145,8 @@ extern "C" { expr* e = to_expr(a); return mk_c(c)->autil().is_numeral(e) || - mk_c(c)->bvutil().is_numeral(e); + mk_c(c)->bvutil().is_numeral(e) || + mk_c(c)->float_util().is_value(e); Z3_CATCH_RETURN(Z3_FALSE); } @@ -155,7 +170,7 @@ extern "C" { 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); } @@ -172,8 +187,16 @@ extern "C" { return mk_c(c)->mk_external_string(r.to_string()); } else { - SET_ERROR_CODE(Z3_INVALID_ARG); - return ""; + // floats are separated from all others to avoid huge rationals. + float_util & fu = mk_c(c)->float_util(); + scoped_mpf tmp(fu.fm()); + if (mk_c(c)->float_util().is_numeral(to_expr(a), tmp)) { + return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); + } + else { + SET_ERROR_CODE(Z3_INVALID_ARG); + return ""; + } } Z3_CATCH_RETURN(""); } diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index b2927e2c3..367e62666 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1532,7 +1532,9 @@ namespace Microsoft.Z3 { case Z3_sort_kind.Z3_INT_SORT: return new IntNum(ctx, obj); case Z3_sort_kind.Z3_REAL_SORT: return new RatNum(ctx, obj); - case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj); + case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj); + case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); + case Z3_sort_kind.Z3_FLOATING_POINT_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj); } } @@ -1543,7 +1545,9 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_REAL_SORT: return new RealExpr(ctx, obj); case Z3_sort_kind.Z3_BV_SORT: return new BitVecExpr(ctx, obj); case Z3_sort_kind.Z3_ARRAY_SORT: return new ArrayExpr(ctx, obj); - case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj); + case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj); + case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPExpr(ctx, obj); + case Z3_sort_kind.Z3_FLOATING_POINT_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); } return new Expr(ctx, obj); diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 6d59cf650..a761c89eb 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -194,6 +194,8 @@ typedef enum Z3_DATATYPE_SORT, Z3_RELATION_SORT, Z3_FINITE_DOMAIN_SORT, + Z3_FLOATING_POINT_SORT, + Z3_FLOATING_POINT_ROUNDING_MODE_SORT, Z3_UNKNOWN_SORT = 1000 } Z3_sort_kind; diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index deda7e045..0b8349793 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -201,9 +201,11 @@ public: app * mk_minus_inf(sort * s) { return mk_minus_inf(get_ebits(s), get_sbits(s)); } app * mk_value(mpf const & v) { return m_plugin->mk_value(v); } - bool is_value(expr * n) { return m_plugin->is_value(n); } - bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); } - bool is_rm(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm(n, v); } + bool is_value(expr * n) const { return m_plugin->is_value(n); } + bool is_numeral(expr * n) const { return is_value(n); } + bool is_value(expr * n, mpf & v) const { return m_plugin->is_value(n, v); } + bool is_numeral(expr * n, mpf & v) const { return is_value(n, v); } + bool is_rm(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm(n, v); } app * mk_pzero(unsigned ebits, unsigned sbits); app * mk_nzero(unsigned ebits, unsigned sbits); From cc5081587fd7025eff92fa9a41540668b86a9e7d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 14 Jun 2013 12:00:10 +0100 Subject: [PATCH 007/646] FPA API: made FPA functions public Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 1e9bd1323..452018ae4 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3532,7 +3532,7 @@ namespace Microsoft.Z3 /// Floating-point absolute value /// /// floating point term - FPExpr MkFPAbs(FPExpr t) + public FPExpr MkFPAbs(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_abs(this.nCtx, t.NativeObject)); @@ -3542,7 +3542,7 @@ namespace Microsoft.Z3 /// Floating-point negation /// /// floating point term - FPExpr MkFPNeg(FPExpr t) + public FPExpr MkFPNeg(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_neg(this.nCtx, t.NativeObject)); @@ -3554,7 +3554,7 @@ namespace Microsoft.Z3 /// rounding mode term /// floating point term /// floating point term - FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) + public FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_add(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); @@ -3566,7 +3566,7 @@ namespace Microsoft.Z3 /// rounding mode term /// floating point term /// floating point term - FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) + public FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_sub(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); @@ -3578,7 +3578,7 @@ namespace Microsoft.Z3 /// rounding mode term /// floating point term /// floating point term - FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) + public FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_mul(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); @@ -3590,7 +3590,7 @@ namespace Microsoft.Z3 /// rounding mode term /// floating point term /// floating point term - FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) + public FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_div(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); @@ -3606,7 +3606,7 @@ namespace Microsoft.Z3 /// floating point term /// floating point term /// floating point term - FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) + public FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_fma(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject, t3.NativeObject)); @@ -3616,7 +3616,7 @@ namespace Microsoft.Z3 /// Floating-point square root /// /// floating point term - FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) + public FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_sqrt(this.nCtx, rm.NativeObject, t.NativeObject)); @@ -3627,7 +3627,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - FPExpr MkFPRem(FPExpr t1, FPExpr t2) + public FPExpr MkFPRem(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_rem(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3641,7 +3641,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - BoolExpr MkFPEq(FPExpr t1, FPExpr t2) + public BoolExpr MkFPEq(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3652,7 +3652,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - BoolExpr MkFPLe(FPExpr t1, FPExpr t2) + public BoolExpr MkFPLe(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_le(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3663,7 +3663,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - BoolExpr MkFPLt(FPExpr t1, FPExpr t2) + public BoolExpr MkFPLt(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_lt(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3674,7 +3674,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - BoolExpr MkFPGe(FPExpr t1, FPExpr t2) + public BoolExpr MkFPGe(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_ge(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3685,7 +3685,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - BoolExpr MkFPGt(FPExpr t1, FPExpr t2) + public BoolExpr MkFPGt(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_gt(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3695,7 +3695,7 @@ namespace Microsoft.Z3 /// Predicate indicating whether t is a normal floating point number /// /// floating point term - BoolExpr MkFPIsNormal(FPExpr t) + public BoolExpr MkFPIsNormal(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_normal(this.nCtx, t.NativeObject)); @@ -3705,7 +3705,7 @@ namespace Microsoft.Z3 /// Predicate indicating whether t is a subnormal floating point number /// /// floating point term - BoolExpr MkFPIsSubnormal(FPExpr t) + public BoolExpr MkFPIsSubnormal(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_subnormal(this.nCtx, t.NativeObject)); @@ -3715,7 +3715,7 @@ namespace Microsoft.Z3 /// Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. /// /// floating point term - BoolExpr MkFPIsZero(FPExpr t) + public BoolExpr MkFPIsZero(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_zero(this.nCtx, t.NativeObject)); @@ -3725,7 +3725,7 @@ namespace Microsoft.Z3 /// Predicate indicating whether t is a floating point number representing +Inf or -Inf /// /// floating point term - BoolExpr MkFPIsInf(FPExpr t) + public BoolExpr MkFPIsInf(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_inf(this.nCtx, t.NativeObject)); @@ -3735,7 +3735,7 @@ namespace Microsoft.Z3 /// Predicate indicating whether t is a NaN /// /// floating point term - BoolExpr MkFPIsNaN(FPExpr t) + public BoolExpr MkFPIsNaN(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_nan(this.nCtx, t.NativeObject)); @@ -3746,7 +3746,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - FPExpr MkFPMin(FPExpr t1, FPExpr t2) + public FPExpr MkFPMin(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3757,7 +3757,7 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - FPExpr MkFPMax(FPExpr t1, FPExpr t2) + public FPExpr MkFPMax(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject)); @@ -3773,7 +3773,7 @@ namespace Microsoft.Z3 /// floating point sort /// floating point rounding mode term /// floating point term - FPExpr MkFPConvert(FPSort s, FPRMExpr rm, FPExpr t) + public FPExpr MkFPConvert(FPSort s, FPRMExpr rm, FPExpr t) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_convert(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); @@ -3786,7 +3786,7 @@ namespace Microsoft.Z3 /// The size of the resulting bit-vector is automatically determined. /// /// floating point term - FPExpr MkFPToIEEEBV(FPExpr t) + public FPExpr MkFPToIEEEBV(FPExpr t) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject)); From 4af39b432cecc0fd3d3c1e4675154c4914ebad33 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 14 Jun 2013 12:25:43 +0100 Subject: [PATCH 008/646] FPA API: dotnet bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 452018ae4..7da54c5eb 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3499,7 +3499,7 @@ namespace Microsoft.Z3 /// /// A string representing the value in decimal notation. /// floating point sort. - public FPNum MkFPNaN(double v, FPSort s) + public FPNum MkFPNaN(FPSort s) { Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_nan(nCtx, s.NativeObject)); @@ -3511,7 +3511,7 @@ namespace Microsoft.Z3 /// A string representing the value in decimal notation. /// floating point sort. /// indicates whether the result should be negative. - public FPNum MkFPInf(double v, FPSort s, bool negative) + public FPNum MkFPInf(FPSort s, bool negative) { Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_inf(nCtx, s.NativeObject, negative ? 1 : 0)); From 165da842b7027e950d561363c23829aa74478896 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 14 Jun 2013 13:12:44 +0100 Subject: [PATCH 009/646] Numeral API: added floating-point numeral cases. Signed-off-by: Christoph M. Wintersteiger --- src/api/api_numeral.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 6924afff3..740fef2ac 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -58,6 +58,8 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } + sort * _ty = to_sort(ty); + bool is_float = mk_c(c)->float_util().is_float(_ty); std::string fixed_num; char const* m = n; while (*m) { @@ -65,14 +67,15 @@ extern "C" { ('/' == *m) || ('-' == *m) || (' ' == *m) || ('\n' == *m) || ('.' == *m) || ('e' == *m) || - ('E' == *m))) { + ('E' == *m) || + (('p' == *m) && is_float) || + (('P' == *m)) && is_float)) { SET_ERROR_CODE(Z3_PARSER_ERROR); return 0; } ++m; } - ast * a = 0; - sort * _ty = to_sort(ty); + ast * a = 0; if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) { // avoid expanding floats into huge rationals. From 8e497fbbaf06d179db93020d86c78e8479564aec Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 14 Jun 2013 13:13:14 +0100 Subject: [PATCH 010/646] Extended FPA dotnet example Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 92 +++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index c75553e7b..2f9d24fb1 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2029,8 +2029,46 @@ namespace test_mapi FPSort s = ctx.MkFPSort(11, 53); Console.WriteLine("Sort: {0}", s); - FPNum n = (FPNum) ctx.MkNumeral("0.125", s); - Console.WriteLine("Numeral: {0}", n.ToString()); + FPNum x = (FPNum)ctx.MkNumeral("-1e1", s); + Console.WriteLine("Numeral: {0}", x.ToString()); + + FPNum y = (FPNum)ctx.MkNumeral("-10", s); + Console.WriteLine("Numeral: {0}", y.ToString()); + + FPNum z = (FPNum)ctx.MkNumeral("-1.25p3", s); + Console.WriteLine("Numeral: {0}", z.ToString()); + + BoolExpr a = ctx.MkAnd(ctx.MkFPEq(x, y), ctx.MkFPEq(y, z)); + + Check(ctx, ctx.MkNot(a), Status.UNSATISFIABLE); + + x = ctx.MkFPNaN(s); + FPExpr c = (FPExpr)ctx.MkConst("y", s); + + // Note: We need to use a special solver for QF_FPA here; the + // general solver does not support FPA yet. + + Solver slvr = ctx.MkSolver("QF_FPA"); + slvr.Add(ctx.MkFPEq(x, c)); + if (slvr.Check() != Status.UNSATISFIABLE) // nothing is equal to NaN according to floating-point equality. + throw new TestFailedException(); + + slvr = ctx.MkSolver("QF_FPA"); + slvr.Add(ctx.MkEq(x, c)); // NaN is equal to NaN according to normal equality. + if (slvr.Check() != Status.SATISFIABLE) + throw new TestFailedException(); + + + x = (FPNum)ctx.MkNumeral("-1e1", s); + y = (FPNum)ctx.MkNumeral("-10", s); + FPExpr q = (FPExpr)ctx.MkConst("q", s); + FPNum mh = (FPNum)ctx.MkNumeral("100", s); + slvr = ctx.MkSolver("QF_FPA"); + // Let's prove -1e1 * -10 == +100 + slvr.Add(ctx.MkEq(ctx.MkFPMul(ctx.MkFPRMNearestTiesToAway(), x, y), q)); + slvr.Add(ctx.MkNot(ctx.MkFPEq(q, mh))); + if (slvr.Check() != Status.UNSATISFIABLE) + throw new TestFailedException(); } static void Main(string[] args) @@ -2050,30 +2088,30 @@ namespace test_mapi // These examples need model generation turned on. using (Context ctx = new Context(new Dictionary() { { "model", "true" } })) { - BasicTests(ctx); - CastingTest(ctx); - SudokuExample(ctx); - QuantifierExample1(ctx); - QuantifierExample2(ctx); - LogicExample(ctx); - ParOrExample(ctx); - FindModelExample1(ctx); - FindModelExample2(ctx); - PushPopExample1(ctx); - ArrayExample1(ctx); - ArrayExample3(ctx); - BitvectorExample1(ctx); - BitvectorExample2(ctx); - ParserExample1(ctx); - ParserExample2(ctx); - ParserExample4(ctx); - ParserExample5(ctx); - ITEExample(ctx); - EvalExample1(ctx); - EvalExample2(ctx); - FindSmallModelExample(ctx); - SimplifierExample(ctx); - FiniteDomainExample(ctx); + //BasicTests(ctx); + //CastingTest(ctx); + //SudokuExample(ctx); + //QuantifierExample1(ctx); + //QuantifierExample2(ctx); + //LogicExample(ctx); + //ParOrExample(ctx); + //FindModelExample1(ctx); + //FindModelExample2(ctx); + //PushPopExample1(ctx); + //ArrayExample1(ctx); + //ArrayExample3(ctx); + //BitvectorExample1(ctx); + //BitvectorExample2(ctx); + //ParserExample1(ctx); + //ParserExample2(ctx); + //ParserExample4(ctx); + //ParserExample5(ctx); + //ITEExample(ctx); + //EvalExample1(ctx); + //EvalExample2(ctx); + //FindSmallModelExample(ctx); + //SimplifierExample(ctx); + //FiniteDomainExample(ctx); FloatingPointExample(ctx); } @@ -2099,7 +2137,7 @@ namespace test_mapi { QuantifierExample3(ctx); QuantifierExample4(ctx); - } + } Log.Close(); if (Log.isOpen()) From f50016d8a1ab69ad729182f4c0d01e07bae340d6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 14 Jun 2013 13:18:33 +0100 Subject: [PATCH 011/646] bugfix in .NET example Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 2f9d24fb1..76624fa1c 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2088,30 +2088,30 @@ namespace test_mapi // These examples need model generation turned on. using (Context ctx = new Context(new Dictionary() { { "model", "true" } })) { - //BasicTests(ctx); - //CastingTest(ctx); - //SudokuExample(ctx); - //QuantifierExample1(ctx); - //QuantifierExample2(ctx); - //LogicExample(ctx); - //ParOrExample(ctx); - //FindModelExample1(ctx); - //FindModelExample2(ctx); - //PushPopExample1(ctx); - //ArrayExample1(ctx); - //ArrayExample3(ctx); - //BitvectorExample1(ctx); - //BitvectorExample2(ctx); - //ParserExample1(ctx); - //ParserExample2(ctx); - //ParserExample4(ctx); - //ParserExample5(ctx); - //ITEExample(ctx); - //EvalExample1(ctx); - //EvalExample2(ctx); - //FindSmallModelExample(ctx); - //SimplifierExample(ctx); - //FiniteDomainExample(ctx); + BasicTests(ctx); + CastingTest(ctx); + SudokuExample(ctx); + QuantifierExample1(ctx); + QuantifierExample2(ctx); + LogicExample(ctx); + ParOrExample(ctx); + FindModelExample1(ctx); + FindModelExample2(ctx); + PushPopExample1(ctx); + ArrayExample1(ctx); + ArrayExample3(ctx); + BitvectorExample1(ctx); + BitvectorExample2(ctx); + ParserExample1(ctx); + ParserExample2(ctx); + ParserExample4(ctx); + ParserExample5(ctx); + ITEExample(ctx); + EvalExample1(ctx); + EvalExample2(ctx); + FindSmallModelExample(ctx); + SimplifierExample(ctx); + FiniteDomainExample(ctx); FloatingPointExample(ctx); } From fa9a9d13cf0d41fdbf409109999b9d31a574655a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Jun 2013 12:13:02 +0100 Subject: [PATCH 012/646] FPA: avoid compiler warnings Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/fpa2bv_converter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_converter.cpp b/src/tactic/fpa/fpa2bv_converter.cpp index 234c343b8..ff24d1ceb 100644 --- a/src/tactic/fpa/fpa2bv_converter.cpp +++ b/src/tactic/fpa/fpa2bv_converter.cpp @@ -2437,7 +2437,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & t = m_bv_util.mk_bv_sub(t, lz); t = m_bv_util.mk_bv_sub(t, m_bv_util.mk_sign_extend(2, e_min)); expr_ref TINY(m); - TINY = m_bv_util.mk_sle(t, m_bv_util.mk_numeral(-1, ebits+2)); + TINY = m_bv_util.mk_sle(t, m_bv_util.mk_numeral((unsigned)-1, ebits+2)); TRACE("fpa2bv_dbg", tout << "TINY = " << mk_ismt2_pp(TINY, m) << std::endl;); SASSERT(is_well_sorted(m, TINY)); @@ -2481,7 +2481,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & m_simp.mk_ite(sigma_le_cap, sigma_neg, sigma_cap, sigma_neg_capped); dbg_decouple("fpa2bv_rnd_sigma_neg", sigma_neg); dbg_decouple("fpa2bv_rnd_sigma_neg_capped", sigma_neg_capped); - sigma_lt_zero = m_bv_util.mk_sle(sigma, m_bv_util.mk_numeral(-1, sigma_size)); + sigma_lt_zero = m_bv_util.mk_sle(sigma, m_bv_util.mk_numeral((unsigned)-1, sigma_size)); dbg_decouple("fpa2bv_rnd_sigma_lt_zero", sigma_lt_zero); sig_ext = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, sig_size)); From 87c6fc66d60b7d1c0e571a920b7ec9f9a0e8001f Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 11 Feb 2014 17:44:59 +0000 Subject: [PATCH 013/646] sls tactic default --- src/tactic/portfolio/smt_strategic_solver.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index ae79446e3..52b0a3c90 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,11 +37,13 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" +#include"sls_tactic.h" + tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - return mk_qfbv_tactic(m, p); + return mk_qfbv_sls_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") From 25378f7989a5d4f38a40e104a3c9727fce3c7b0f Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 18 Feb 2014 14:01:47 +0000 Subject: [PATCH 014/646] some extensions/modifications. versions added. --- src/tactic/portfolio/default_tactic.cpp | 3 +- src/tactic/sls/sls_evaluator.h | 4 +- src/tactic/sls/sls_tactic.cpp | 146 ++++++++++++-- src/tactic/sls/sls_tracker.h | 249 +++++++++++++++++++++--- versions/z3-crsat-0.01.txt | 12 ++ versions/z3-gsat-0.01.txt | 10 + versions/z3-gsat-res-0.01.txt | 10 + versions/z3-wsat-0.01.txt | 12 ++ versions/z3-wsat-0.01b.txt | 12 ++ versions/z3-wsat-0.01c.txt | 12 ++ versions/z3-wsat-0.01d.txt | 11 ++ versions/z3-wsat-0.01e.txt | 11 ++ versions/z3-wsat-0.02.txt | 13 ++ versions/z3-wsat-res-0.01.txt | 13 ++ 14 files changed, 470 insertions(+), 48 deletions(-) create mode 100644 versions/z3-crsat-0.01.txt create mode 100644 versions/z3-gsat-0.01.txt create mode 100644 versions/z3-gsat-res-0.01.txt create mode 100644 versions/z3-wsat-0.01.txt create mode 100644 versions/z3-wsat-0.01b.txt create mode 100644 versions/z3-wsat-0.01c.txt create mode 100644 versions/z3-wsat-0.01d.txt create mode 100644 versions/z3-wsat-0.01e.txt create mode 100644 versions/z3-wsat-0.02.txt create mode 100644 versions/z3-wsat-res-0.01.txt diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 9ecc16ecf..b28b7bec0 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -28,10 +28,11 @@ Notes: #include"probe_arith.h" #include"quant_tactics.h" #include"qffpa_tactic.h" +#include"sls_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 77ff50454..61305386e 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -584,8 +584,8 @@ public: run_update(cur_depth); } - void randomize_local(goal_ref const & g) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); + void randomize_local(goal_ref const & g, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); // Randomize _all_ candidates: diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index ea5d60668..c84e68730 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -35,6 +35,17 @@ Notes: #include"sls_tactic.h" #include"nnf_tactic.h" +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 30 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 +#define _VNS_ 0 +#define _WEIGHT_DIST_ 3 +#define _WEIGHT_DIST_FACTOR_ 0.1 + #include"sls_params.hpp" #include"sls_evaluator.h" #include"sls_tracker.h" @@ -257,7 +268,7 @@ class sls_tactic : public tactic { // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; @@ -303,6 +314,82 @@ class sls_tactic : public tactic { m_mpz_manager.del(new_value); } + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -372,22 +459,29 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - while (plateau_cnt < m_plateau_limit) { - + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif do { checkpoint(); old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); - +#endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; for (unsigned i = 0; i < g->size(); i++) { @@ -400,9 +494,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -441,6 +537,7 @@ class sls_tactic : public tactic { if (score >= 1.0) { // score could theoretically be imprecise. + // Andreas: Can it only be imprecise in one direction? bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -451,19 +548,30 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - if (score != old_score) + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - else { + } else { + m_stats.m_moves++; plateau_cnt++; - if (plateau_cnt < m_plateau_limit) { + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); - m_evaluator.randomize_local(g); + m_evaluator.randomize_local(g, m_stats.m_moves); //mk_random_move(g); score = top_score(g); - } + //} } } @@ -484,7 +592,8 @@ class sls_tactic : public tactic { do { checkpoint(); - if ((m_stats.m_restarts % 100) == 0) + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + //if ((m_stats.m_restarts % 100) == 0) report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); res = search(g); @@ -492,9 +601,12 @@ class sls_tactic : public tactic { if (res == l_undef) m_tracker.randomize(); } - while (res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - if (res == l_true) { + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -633,7 +745,13 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), +#if _CNF_ + // Andreas: We will probably never use this. CNF sucks. + mk_cnf_tactic(m, p)); +#else + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); +#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7fbafec60..1061bd90e 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -28,8 +28,8 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; - + mpz m_zero, m_one, m_two; + struct value_score { value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; ~value_score() { if (m) m->del(value); } @@ -249,12 +249,46 @@ public: } } - void initialize(goal_ref const & g) { + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } + + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; + m_constants_occ.insert_if_not_there(e, t); + find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); + expr_fast_mark1 visited; + quick_for_each_expr(ffd_proc, visited, e); + } + + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(proc, visited, e); +#endif for_each_expr(proc, visited, e); } @@ -262,6 +296,10 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(e); +#endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -382,8 +420,6 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } -#define _SCORE_AND_MIN - double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -400,30 +436,41 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - #ifdef _SCORE_AND_MIN - double min = 1.0; + // Andreas: Seems to have no effect. Probably it does not even occur. +#if _SCORE_AND_AVG_ + double sum = 0.0; + for (unsigned i = 0; i < a->get_num_args(); i++) + sum += get_score(args[i]); + res = sum / (double) a->get_num_args(); +#else + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; } res = min; - #else - double sum = 0.0; - for (unsigned i = 0; i < a->get_num_args(); i++) - sum += get_score(args[i]); - res = sum / (double) a->get_num_args(); - #endif +#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - double max = 0.0; + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. +#if _SCORE_OR_MUL_ + double inv = 1.0; + for (unsigned i = 0; i < a->get_num_args(); i++) { + double cur = get_score(args[i]); + inv *= (1.0 - get_score(args[i])); + } + res = 1.0 - inv; +#else + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; } res = max; +#endif } else if (m_manager.is_ite(n)) { SASSERT(!negated); @@ -468,7 +515,7 @@ public: } m_mpz_manager.machine_div(diff, m_two, diff); } - res = 1.0 - (hamming_distance / (double) bv_sz); + res = 1.0 - (hamming_distance / (double) bv_sz); #else rational r(diff); r /= m_powers(bv_sz); @@ -503,7 +550,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -564,7 +611,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -598,6 +645,20 @@ public: SASSERT(res >= 0.0 && res <= 1.0); +#if _WEIGHT_DIST_ + app * a = to_app(n); + family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) +#endif +#if _WEIGHT_DIST_ == 1 + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#elif _WEIGHT_DIST_ == 2 + res *= res; +#elif _WEIGHT_DIST_ == 3 + if (res < 1.0) res = 0.0; +#endif + + TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } @@ -647,7 +708,111 @@ public: NOT_IMPLEMENTED_YET(); } - ptr_vector & get_unsat_constants(goal_ref const & g) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + for (unsigned i = 0; i < sz; i++) { + expr * q = g->form(i); + if (m_mpz_manager.eq(get_value(q), m_one)) + continue; + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + return m_temp_constants; + } + + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } + + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. + if (!q) + return m_temp_constants; + + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + if (!q) + return m_temp_constants; + + return go_deeper(q); + } + + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { @@ -655,19 +820,41 @@ public: } else { m_temp_constants.reset(); - for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); - if (m_mpz_manager.eq(get_value(q), m_one)) - continue; - ptr_vector const & this_decls = m_constants_occ.find(q); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } +#if _FOCUS_ == 1 +#if _BFS_ == 3 + unsigned int pos = 0; + double max = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - return m_temp_constants; +#elif _BFS_ == 2 + unsigned int pos = 0; + double min = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } +#elif _BFS_ == 1 + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_walksat(g, sz, pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_crsat(g, sz, pos); +#else + return get_unsat_constants_gsat(g, sz); +#endif } } }; diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt new file mode 100644 index 000000000..49e1a1525 --- /dev/null +++ b/versions/z3-crsat-0.01.txt @@ -0,0 +1,12 @@ +More focused (_FOCUS_ == 2) WalkSAT version. +Variables are chosen among candidates in only one unsatisfied bit-vector term. +Flip rate slightly slower; probably due to larger hash-table and recursive formula structure. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 3 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt new file mode 100644 index 000000000..eb806a67f --- /dev/null +++ b/versions/z3-gsat-0.01.txt @@ -0,0 +1,10 @@ +Basic GSAT version. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 0 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt new file mode 100644 index 000000000..6a211f2bc --- /dev/null +++ b/versions/z3-gsat-res-0.01.txt @@ -0,0 +1,10 @@ +Basic GSAT version corresponding to Christoph's original code. +Restarts after 100 plateaus. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 0 +#define _RESTARTS_ 1 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt new file mode 100644 index 000000000..141193f76 --- /dev/null +++ b/versions/z3-wsat-0.01.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Flip rate increased by roughly 10%-300%. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt new file mode 100644 index 000000000..2c0c0e7ad --- /dev/null +++ b/versions/z3-wsat-0.01b.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0). +No restarts. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt new file mode 100644 index 000000000..223560e08 --- /dev/null +++ b/versions/z3-wsat-0.01c.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +AND is scored by average; OR is scored by inverse multiplication. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 1 +#define _SCORE_OR_MUL_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt new file mode 100644 index 000000000..072191370 --- /dev/null +++ b/versions/z3-wsat-0.01d.txt @@ -0,0 +1,11 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 2 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt new file mode 100644 index 000000000..b018c5e0d --- /dev/null +++ b/versions/z3-wsat-0.01e.txt @@ -0,0 +1,11 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 3 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt new file mode 100644 index 000000000..34dcb157c --- /dev/null +++ b/versions/z3-wsat-0.02.txt @@ -0,0 +1,13 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Score function reduced to 0/1. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 +#define _WEIGHTED_DIST_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt new file mode 100644 index 000000000..575180a59 --- /dev/null +++ b/versions/z3-wsat-res-0.01.txt @@ -0,0 +1,13 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Flip rate increased by roughly 10%-300% compared to GSAT. +Restarts after 100 plateaus. +Fps slightly decreased due to restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 1 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file From 853ce522ccda06788da56198d9c3808df4a6cd73 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 9 Mar 2014 15:42:51 +0000 Subject: [PATCH 015/646] plenty of new stuff --- src/sat/tactic/sat_tactic.cpp | 4 +- src/tactic/portfolio/default_tactic.cpp | 1 + src/tactic/portfolio/smt_strategic_solver.cpp | 1 + src/tactic/sls/sls_evaluator.h | 323 ++++++++- src/tactic/sls/sls_tactic.cpp | 661 ++++++++++++++++-- src/tactic/sls/sls_tracker.h | 345 ++++++++- versions/z3-wsat-0.01.txt | 4 +- versions/z3-wsat-0.01b.txt | 4 +- 8 files changed, 1235 insertions(+), 108 deletions(-) diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index d48994861..717bf7007 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -66,7 +66,9 @@ class sat_tactic : public tactic { CASSERT("sat_solver", m_solver.check_invariant()); IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream());); TRACE("sat_dimacs", m_solver.display_dimacs(tout);); - + //m_solver.display_dimacs(std::cerr); + //exit(0); + lbool r = m_solver.check(); if (r == l_false) { g->assert_expr(m.mk_false(), 0, 0); diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index b28b7bec0..53da9a159 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -33,6 +33,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), + // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 52b0a3c90..f63b4fd8c 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -43,6 +43,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") + // return mk_qfbv_tactic(m, p); return mk_qfbv_sls_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 61305386e..eec9524a9 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -34,6 +34,9 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; +#if _EARLY_PRUNE_ + vector > m_traversal_stack_bool; +#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -519,11 +522,15 @@ public: } } - void run_update(unsigned cur_depth) { + void run_serious_update(unsigned cur_depth) { // precondition: m_traversal_stack contains the entry point(s) expr_fast_mark1 visited; mpz new_value; +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -533,8 +540,92 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - m_tracker.set_score(cur, m_tracker.score(cur)); +#if _REAL_RS_ || _REAL_PBFS_ + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } +#endif + +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + void run_update(unsigned cur_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -569,8 +660,11 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } - +#if _REAL_RS_ || _REAL_PBFS_ + run_serious_update(max_depth); +#else run_update(max_depth); +#endif } void update(func_decl * fd, const mpz & new_value) { @@ -584,6 +678,196 @@ public: run_update(cur_depth); } + void serious_update(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + m_traversal_stack[cur_depth].push_back(ep); + + run_serious_update(cur_depth); + } + +#if _EARLY_PRUNE_ + unsigned run_update_bool_prune(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + void run_update_prune(unsigned max_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + + unsigned cur_depth = max_depth; + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); + // should always have uplinks ... + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + unsigned update_prune(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); + } +#endif + + void randomize_local(expr * e, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_constants(e); + + // Randomize _one_ candidate: + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + update(fd, temp); + m_mpz_manager.del(temp); + } + void randomize_local(goal_ref const & g, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); @@ -603,8 +887,37 @@ public: // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; - mpz temp = m_tracker.get_random(fd->get_range()); - update(fd, temp); +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + +#if _REAL_RS_ || _REAL_PBFS_ + serious_update(fd, temp); +#else + update(fd, temp); +#endif m_mpz_manager.del(temp); TRACE("sls", /*tout << "Randomization candidates: "; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index c84e68730..3d5e3e438 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -35,16 +35,102 @@ Notes: #include"sls_tactic.h" #include"nnf_tactic.h" -#define _CNF_ 0 -#define _BFS_ 1 +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 + +// do we use restarts? +// 0 = no, otherwise the value defines the maximum number of moves #define _RESTARTS_ 0 -#define _TIMELIMIT_ 30 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? #define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? #define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 -#define _WEIGHT_DIST_ 3 -#define _WEIGHT_DIST_FACTOR_ 0.1 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 0 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 0 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 0.01 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +#define _PROBABILISTIC_UCT_ 0 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 1 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 1 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 1 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 1 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) + InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) + InvalidConfiguration; +#endif + #include"sls_params.hpp" #include"sls_evaluator.h" @@ -57,12 +143,17 @@ class sls_tactic : public tactic { stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -92,7 +183,9 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : m_manager(m), @@ -174,13 +267,20 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - top_sum += m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + return top_sum / (double) sz; #endif } @@ -191,22 +291,54 @@ class sls_tactic : public tactic { return top_score(g); } - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else return top_score(g); +#endif } + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; + } +#endif + + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { - + #ifdef Z3DEBUG mpz old_value; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else double r = incremental_score(g, fd, temp); - +#endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl; ); @@ -214,6 +346,22 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); #endif +// if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // same as what_if, but only applied to the score of a specific atom, not the total score + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -224,7 +372,35 @@ class sls_tactic : public tactic { return false; } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + + } + + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + } + + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -261,59 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + if (m_stats.m_moves > 10000) + rnd_mv = 0; ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; - unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range()); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + mpz new_value; - m_evaluator.update(fd, new_value); + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; - m_mpz_manager.del(new_value); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } + + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -359,6 +549,7 @@ class sls_tactic : public tactic { SASSERT(check == score); } + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else @@ -390,9 +581,13 @@ class sls_tactic : public tactic { return new_score; } + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif unsigned bv_sz; double new_score = score; @@ -403,8 +598,12 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // first try to flip every bit - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { - // What would happen if we flipped bit #i ? +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -414,7 +613,8 @@ class sls_tactic : public tactic { } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -426,16 +626,99 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } - +#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif } // reset to what it was before double check = incremental_score(g, fd, old_value); - SASSERT(check == score); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; + } + + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -443,7 +726,150 @@ class sls_tactic : public tactic { return new_score; } - lbool search(goal_ref const & g) { + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + + m_old_values.reset(); + + return 0; + } + + // what_if version needed in the context of 2nd intensification try, combining local and global score + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // find_best_move version needed in the context of 2nd intensification try + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) + { + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; + } + + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; + } + + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -463,16 +889,48 @@ class sls_tactic : public tactic { #if _RESTARTS_ while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { + if (m_stats.m_moves == 5590) checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif old_score = score; new_const = (unsigned)-1; ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -525,9 +983,17 @@ class sls_tactic : public tactic { case MV_INC: m_stats.m_incs++; break; case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - score = incremental_score(g, fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif TRACE("sls", tout << "Score distribution:"; for (unsigned i = 0; i < g->size(); i++) @@ -535,9 +1001,10 @@ class sls_tactic : public tactic { tout << " TOP: " << score << std::endl; ); } - if (score >= 1.0) { + if (score >= 0.99999) { +// if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: Can it only be imprecise in one direction? + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -568,10 +1035,26 @@ class sls_tactic : public tactic { // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else m_evaluator.randomize_local(g, m_stats.m_moves); - //mk_random_move(g); +#endif + //mk_random_move(g); score = top_score(g); - //} + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } } } @@ -587,6 +1070,37 @@ class sls_tactic : public tactic { return; } + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif m_tracker.initialize(g); lbool res = l_undef; @@ -745,13 +1259,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), -#if _CNF_ - // Andreas: We will probably never use this. CNF sucks. - mk_cnf_tactic(m, p)); -#else // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); -#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1061bd90e..b26912e5c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -28,21 +28,32 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; + mpz m_zero, m_one, m_two; struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; +#if _EARLY_PRUNE_ + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; +#else + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; +#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; +#if _EARLY_PRUNE_ + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; +#endif unsigned distance; // max distance from any root + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; + touched = other.touched; return *this; } }; @@ -60,6 +71,20 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; +#if _UCT_ + unsigned m_touched; +#endif +#if _REAL_RS_ || _REAL_PBFS_ + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; +#endif +#if _CACHE_TOP_SCORE_ + double m_top_sum; +#endif +#if _WEIGHT_DIST_ == 4 + double m_weight_dist_factor; +#endif public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -79,6 +104,26 @@ public: m_mpz_manager.del(m_two); } +#if _WEIGHT_DIST_ == 4 + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } +#endif + +#if _CACHE_TOP_SCORE_ + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } + + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } + + inline double get_top_sum() { + return m_top_sum; + } +#endif + inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); m_mpz_manager.set(m_scores.find(n).value, r); @@ -123,6 +168,28 @@ public: return get_score(ep); } +#if _EARLY_PRUNE_ + inline void set_score_prune(expr * n, double score) { + SASSERT(m_scores.contains(n)); + m_scores.find(n).score_prune = score; + } + + inline double & get_score_prune(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).score_prune; + } + + inline unsigned has_pos_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_pos_occ; + } + + inline unsigned has_neg_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_neg_occ; + } +#endif + inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).distance; @@ -297,7 +364,7 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 +#if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); #endif ptr_vector t; @@ -310,8 +377,57 @@ public: calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); + +#if _REAL_RS_ || _REAL_PBFS_ + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); +#endif + +#if _EARLY_PRUNE_ + for (unsigned i = 0; i < sz; i++) + setup_occs(g->form(i)); +#endif + +#if _UCT_ + m_touched = 1; +#endif } +#if _REAL_RS_ || _REAL_PBFS_ + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } + + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } +#endif + void show_model(std::ostream & out) { unsigned sz = get_num_constants(); for (unsigned i = 0; i < sz; i++) { @@ -420,10 +536,45 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } +#if _EARLY_PRUNE_ + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } + else + NOT_IMPLEMENTED_YET(); + } +#endif + double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -488,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -648,6 +799,7 @@ public: #if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 @@ -656,13 +808,14 @@ public: res *= res; #elif _WEIGHT_DIST_ == 3 if (res < 1.0) res = 0.0; +#elif _WEIGHT_DIST_ == 4 + if (res < 1.0) res *= m_weight_dist_factor; #endif - TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -708,6 +861,44 @@ public: NOT_IMPLEMENTED_YET(); } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } + + ptr_vector & get_constants(expr * e) { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); @@ -743,7 +934,6 @@ public: // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { @@ -754,6 +944,19 @@ public: return m_temp_constants; } + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned j = 0; j < sz; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & go_deeper(expr * e) { if (m_manager.is_bool(e)) { if (m_manager.is_and(e)) { @@ -812,44 +1015,138 @@ public: return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 -#if _BFS_ == 3 - unsigned int pos = 0; - double max = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return m_temp_constants; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif + expr * e = g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = 0; - double min = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(g, sz, pos); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif return get_unsat_constants_crsat(g, sz, pos); #else diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt index 141193f76..fec38518d 100644 --- a/versions/z3-wsat-0.01.txt +++ b/versions/z3-wsat-0.01.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt index 2c0c0e7ad..8bcf2ffeb 100644 --- a/versions/z3-wsat-0.01b.txt +++ b/versions/z3-wsat-0.01b.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file From 5aa352fd16170df754cc8155e3b930cb452211b0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 09:40:01 +0000 Subject: [PATCH 016/646] removed tabs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_evaluator.h | 268 ++++++------- src/tactic/sls/sls_tactic.cpp | 572 ++++++++++++++-------------- src/tactic/sls/sls_tracker.h | 672 ++++++++++++++++----------------- 3 files changed, 756 insertions(+), 756 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index eec9524a9..cdb08038f 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -528,7 +528,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -542,33 +542,33 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) - { - if (m_mpz_manager.eq(new_value,m_one)) - m_tracker.make_assertion(cur); - else - m_tracker.break_assertion(cur); - } + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } #endif #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -596,7 +596,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -609,23 +609,23 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -661,7 +661,7 @@ public: if (cur_depth > max_depth) max_depth = cur_depth; } #if _REAL_RS_ || _REAL_PBFS_ - run_serious_update(max_depth); + run_serious_update(max_depth); #else run_update(max_depth); #endif @@ -693,27 +693,27 @@ public: unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { expr * cur = cur_depth_exprs[i]; - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - prune_score = m_tracker.get_score_prune(cur); + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); - if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -722,54 +722,54 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); + m_traversal_stack_bool[next_d].push_back(next); visited.mark(next); } } } - else - { - } - } + else + { + } + } - cur_depth_exprs.reset(); + cur_depth_exprs.reset(); cur_depth--; - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } - return pot_benefits; + return pot_benefits; } void run_update_prune(unsigned max_depth) { @@ -777,7 +777,7 @@ public: expr_fast_mark1 visited; mpz new_value; - unsigned cur_depth = max_depth; + unsigned cur_depth = max_depth; SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -787,7 +787,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // should always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -795,10 +795,10 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - if (m_manager.is_bool(next)) - m_traversal_stack_bool[max_depth].push_back(next); - else - m_traversal_stack[next_d].push_back(next); + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); visited.mark(next); } } @@ -817,23 +817,23 @@ public: expr * ep = m_tracker.get_entry_point(fd); unsigned cur_depth = m_tracker.get_distance(ep); - if (m_traversal_stack_bool.size() <= cur_depth) + if (m_traversal_stack_bool.size() <= cur_depth) m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune(cur_depth); + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); } #endif - void randomize_local(expr * e, unsigned int flip) { + void randomize_local(expr * e, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_constants(e); // Randomize _one_ candidate: @@ -841,30 +841,30 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif - update(fd, temp); + update(fd, temp); m_mpz_manager.del(temp); } @@ -889,34 +889,34 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif #if _REAL_RS_ || _REAL_PBFS_ - serious_update(fd, temp); + serious_update(fd, temp); #else - update(fd, temp); + update(fd, temp); #endif m_mpz_manager.del(temp); diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 3d5e3e438..fe871cefa 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -125,10 +125,10 @@ Notes: #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) - InvalidConfiguration; + InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; + InvalidConfiguration; #endif @@ -150,10 +150,10 @@ class sls_tactic : public tactic { m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -183,8 +183,8 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - ptr_vector m_old_values; - + ptr_vector m_old_values; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : @@ -267,18 +267,18 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); #if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); + m_tracker.set_top_sum(top_sum); #endif return top_sum / (double) sz; @@ -292,20 +292,20 @@ class sls_tactic : public tactic { } double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif } double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif @@ -314,18 +314,18 @@ class sls_tactic : public tactic { #if _EARLY_PRUNE_ double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) + if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(g); + return top_score(g); #endif - else - return 0.0; + else + return 0.0; } #endif - // checks whether the score outcome of a given move is better than the previous score + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { @@ -357,11 +357,11 @@ class sls_tactic : public tactic { return false; } - // same as what_if, but only applied to the score of a specific atom, not the total score + // same as what_if, but only applied to the score of a specific atom, not the total score bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -378,29 +378,29 @@ class sls_tactic : public tactic { m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); - } + } - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { mpz temp, mask, mask2; m_mpz_manager.mul(old_value, m_two, temp); m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); } void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { m_mpz_manager.div(old_value, m_two, result); } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -437,73 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; + if (m_stats.m_moves > 10000) + rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; + mpz new_value; - sort * srt = fd->get_range(); + sort * srt = fd->get_range(); if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { #if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + mt = MV_FLIP; #endif - unsigned bit = 0; + unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } - // will use VNS to ignore some possible moves and increase the flips per second + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -514,7 +514,7 @@ class sls_tactic : public tactic { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -536,12 +536,12 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } } // reset to what it was before @@ -549,12 +549,12 @@ class sls_tactic : public tactic { SASSERT(check == score); } - // we can either check the condition once in the beginning or check it repeatedly after every bit + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) #endif for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { func_decl * fd = to_evaluate[i]; @@ -563,30 +563,30 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } // reset to what it was before double check = incremental_score(g, fd, old_value); SASSERT(check == score); } - m_mpz_manager.del(old_value); + m_mpz_manager.del(old_value); m_mpz_manager.del(temp); return new_score; } - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; + mpz temp2; #endif unsigned bv_sz; double new_score = score; @@ -599,11 +599,11 @@ class sls_tactic : public tactic { // first try to flip every bit #if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { #endif - // What would happen if we flipped bit #i ? + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -614,7 +614,7 @@ class sls_tactic : public tactic { if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { #if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -660,7 +660,7 @@ class sls_tactic : public tactic { // reset to what it was before double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching + // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -669,17 +669,17 @@ class sls_tactic : public tactic { #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif - return new_score; + return new_score; } - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -718,7 +718,7 @@ class sls_tactic : public tactic { } // reset to what it was before - m_evaluator.update(fd, old_value); + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -726,37 +726,37 @@ class sls_tactic : public tactic { return new_score; } - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); #if _BFS_ - unsigned pos = m_stats.m_moves % sz; + unsigned pos = m_stats.m_moves % sz; #else - unsigned pos = m_tracker.get_random_uint(16) % sz; + unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); } else { m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -767,35 +767,35 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); } - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - m_old_values.reset(); + m_old_values.reset(); - return 0; - } + return 0; + } - // what_if version needed in the context of 2nd intensification try, combining local and global score + // what_if version needed in the context of 2nd intensification try, combining local and global score bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, double & best_score, mpz & best_value, unsigned i) { double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); + double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - if (new_score >= best_score) { + if (new_score >= best_score) { best_score = new_score; m_mpz_manager.set(best_value, temp); return true; @@ -804,17 +804,17 @@ class sls_tactic : public tactic { return false; } - // find_best_move version needed in the context of 2nd intensification try + // find_best_move version needed in the context of 2nd intensification try double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; + { + mpz old_value, temp; double best_score = 0; sort * srt = fd->get_range(); unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); what_if(g, e, fd, temp, best_score, best_value, i); } @@ -822,54 +822,54 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - return best_score; + return best_score; } - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); #if _BFS_ - unsigned new_const = m_stats.m_moves % sz; + unsigned new_const = m_stats.m_moves % sz; #else - unsigned new_const = m_tracker.get_random_uint(16) % sz; + unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - return 0; - } + return 0; + } - // main search loop - lbool search(goal_ref const & g) { + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -885,52 +885,52 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - // Andreas: Why do we only allow so few plateaus? + // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) + if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif #if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { #if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #elif _TYPE_RSTEP_ == 2 - mk_random_move(g); + mk_random_move(g); #endif score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } #endif old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -952,11 +952,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { - // Andreas: Why does randomizing not count as a move? (Now it does.) + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -984,15 +984,15 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; @@ -1004,7 +1004,7 @@ class sls_tactic : public tactic { if (score >= 0.99999) { // if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -1015,43 +1015,43 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - } else { - m_stats.m_moves++; + } else { + m_stats.m_moves++; plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); #if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); + handle_plateau(g, score); + //handle_plateau(g); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(g); + //mk_random_move(g); score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } @@ -1070,43 +1070,43 @@ class sls_tactic : public tactic { return; } - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif m_tracker.initialize(g); lbool res = l_undef; do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... //if ((m_stats.m_restarts % 100) == 0) report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); @@ -1115,12 +1115,12 @@ class sls_tactic : public tactic { if (res == l_undef) m_tracker.randomize(); } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); + report_tactic_progress("Number of flips:", m_stats.m_moves); if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1259,7 +1259,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index b26912e5c..006bbb888 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -29,31 +29,31 @@ class sls_tracker { unsigned m_random_bits; unsigned m_random_bits_cnt; mpz m_zero, m_one, m_two; - + struct value_score { #if _EARLY_PRUNE_ - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; #else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; #endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; #if _EARLY_PRUNE_ - double score_prune; - unsigned has_pos_occ; - unsigned has_neg_occ; + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; #endif unsigned distance; // max distance from any root - unsigned touched; + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; - touched = other.touched; + touched = other.touched; return *this; } }; @@ -72,18 +72,18 @@ private: ptr_vector m_temp_constants; occ_type m_constants_occ; #if _UCT_ - unsigned m_touched; + unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; + double m_weight_dist_factor; #endif public: @@ -105,23 +105,23 @@ public: } #if _WEIGHT_DIST_ == 4 - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } #endif #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { - m_top_sum += add - sub; - } + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } - inline void set_top_sum(double new_score) { - m_top_sum = new_score; - } + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } - inline double get_top_sum() { - return m_top_sum; - } + inline double get_top_sum() { + return m_top_sum; + } #endif inline void set_value(expr * n, const mpz & r) { @@ -174,20 +174,20 @@ public: m_scores.find(n).score_prune = score; } - inline double & get_score_prune(expr * n) { + inline double & get_score_prune(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).score_prune; } - inline unsigned has_pos_occ(expr * n) { + inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } - inline unsigned has_neg_occ(expr * n) { + inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -316,45 +316,45 @@ public: } } - void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(proc, visited, q); - } - } - for_each_expr(proc, visited, e); - } + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } - void initialize_recursive(expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(q); - } - } - ptr_vector t; + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } - void initialize(goal_ref const & g) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); + initialize_recursive(proc, visited, e); #endif for_each_expr(proc, visited, e); } @@ -363,9 +363,9 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); + initialize_recursive(e); #endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); @@ -379,53 +379,53 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); #if _REAL_RS_ || _REAL_PBFS_ - m_list_false = new expr*[sz]; + m_list_false = new expr*[sz]; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = 1; #endif } #if _REAL_RS_ || _REAL_PBFS_ - void make_assertion(expr * e) - { - if (m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) - { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - } -// printf("Going in %d\n", m_where_false.size()); - } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); - } + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } - void break_assertion(expr * e) - { - if (!m_where_false.contains(e)) - { - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); - } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); - } + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } #endif void show_model(std::ostream & out) { @@ -537,35 +537,35 @@ public: } #if _EARLY_PRUNE_ - void setup_occs(expr * n, bool negated = false) { - if (m_manager.is_bool(n)) - { - if (m_manager.is_and(n) || m_manager.is_or(n)) - { - SASSERT(!negated); - app * a = to_app(n); - expr * const * args = a->get_args(); - for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); - } - else if (m_manager.is_not(n)) - { - SASSERT(!negated); - app * a = to_app(n); - SASSERT(a->get_num_args() == 1); - expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); - setup_occs(child, true); - } - else - { - if (negated) - m_scores.find(n).has_neg_occ = 1; - else - m_scores.find(n).has_pos_occ = 1; - } - } + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } else NOT_IMPLEMENTED_YET(); } @@ -574,7 +574,7 @@ public: double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -587,14 +587,14 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. + // Andreas: Seems to have no effect. Probably it does not even occur. #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) sum += get_score(args[i]); res = sum / (double) a->get_num_args(); #else - double min = 1.0; + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; @@ -606,16 +606,16 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. #if _SCORE_OR_MUL_ - double inv = 1.0; + double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else - double max = 0.0; + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; @@ -639,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -701,7 +701,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -762,7 +762,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -797,25 +797,25 @@ public: SASSERT(res >= 0.0 && res <= 1.0); #if _WEIGHT_DIST_ - app * a = to_app(n); - family_id afid = a->get_family_id(); + app * a = to_app(n); + family_id afid = a->get_family_id(); - if (afid == m_bv_util.get_family_id()) + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; #elif _WEIGHT_DIST_ == 2 - res *= res; + res *= res; #elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; + if (res < 1.0) res = 0.0; #elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; + if (res < 1.0) res *= m_weight_dist_factor; #endif TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -861,34 +861,34 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } - ptr_vector & get_constants(expr * e) { + ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned i = 0; i < sz; i++) { @@ -897,9 +897,9 @@ public: m_temp_constants.push_back(fd); } return m_temp_constants; - } + } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -913,244 +913,244 @@ public: } } return m_temp_constants; - } + } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; + return q; } - return 0; - } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); + if (!q) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned j = 0; j < sz; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) - return m_temp_constants; + return m_temp_constants; - return go_deeper(q); - } + return go_deeper(q); + } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) - return m_temp_constants; - else - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 #if _UCT_ - unsigned pos = -1; - value_score vscore; + unsigned pos = -1; + value_score vscore; #if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } #else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - vscore = m_scores.find(e); + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); #elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } #endif - if (pos == static_cast(-1)) - return m_temp_constants; + if (pos == static_cast(-1)) + return m_temp_constants; #if _UCT_ == 1 - m_scores.find(g->form(pos)).touched++; - m_touched++; + m_scores.find(g->form(pos)).touched++; + m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = g->form(pos); + expr * e = g->form(pos); #elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; + unsigned int pos = -1; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; + unsigned int pos = -1; + double min = 2.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); #elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(e); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif - return get_unsat_constants_crsat(g, sz, pos); + return get_unsat_constants_crsat(g, sz, pos); #else - return get_unsat_constants_gsat(g, sz); + return get_unsat_constants_gsat(g, sz); #endif } } From 90245021b23f8402e13b4aa85f8ac5e629b7caf5 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 19 Mar 2014 11:49:44 +0000 Subject: [PATCH 017/646] Current version for relocating. --- src/tactic/sls/sls_evaluator.h | 298 +++++------ src/tactic/sls/sls_tactic.cpp | 842 ++++++++++++++++++----------- src/tactic/sls/sls_tracker.h | 947 +++++++++++++++++++++------------ 3 files changed, 1290 insertions(+), 797 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index eec9524a9..696d7664a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -78,7 +78,11 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_zero); break; } @@ -86,7 +90,11 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_one); break; } @@ -94,9 +102,16 @@ public: } case OP_NOT: { SASSERT(n_args == 1); +#if _DIRTY_UP_ + if (m_tracker.is_top_expr(args[0])) + m_mpz_manager.set(result, m_zero); + else + m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); +#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); - m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); + m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); +#endif break; } case OP_EQ: { @@ -528,7 +543,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -542,31 +557,34 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) - { - if (m_mpz_manager.eq(new_value,m_one)) - m_tracker.make_assertion(cur); - else - m_tracker.break_assertion(cur); - } + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } #endif #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif #endif if (m_tracker.has_uplinks(cur)) { @@ -596,7 +614,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -609,21 +627,23 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif #endif if (m_tracker.has_uplinks(cur)) { @@ -661,7 +681,7 @@ public: if (cur_depth > max_depth) max_depth = cur_depth; } #if _REAL_RS_ || _REAL_PBFS_ - run_serious_update(max_depth); + run_serious_update(max_depth); #else run_update(max_depth); #endif @@ -693,27 +713,28 @@ public: unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { expr * cur = cur_depth_exprs[i]; - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - prune_score = m_tracker.get_score_prune(cur); + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); - if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -722,54 +743,55 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); + m_traversal_stack_bool[next_d].push_back(next); visited.mark(next); } } } - else - { - } - } + else + { + } + } - cur_depth_exprs.reset(); + cur_depth_exprs.reset(); cur_depth--; - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } - return pot_benefits; + return pot_benefits; } void run_update_prune(unsigned max_depth) { @@ -777,7 +799,7 @@ public: expr_fast_mark1 visited; mpz new_value; - unsigned cur_depth = max_depth; + unsigned cur_depth = max_depth; SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -787,7 +809,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // should always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -795,10 +817,10 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - if (m_manager.is_bool(next)) - m_traversal_stack_bool[max_depth].push_back(next); - else - m_traversal_stack[next_d].push_back(next); + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); visited.mark(next); } } @@ -817,60 +839,23 @@ public: expr * ep = m_tracker.get_entry_point(fd); unsigned cur_depth = m_tracker.get_distance(ep); - if (m_traversal_stack_bool.size() <= cur_depth) + if (m_traversal_stack_bool.size() <= cur_depth) m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune(cur_depth); + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); } #endif - void randomize_local(expr * e, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_constants(e); - - // Randomize _one_ candidate: - unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); - func_decl * fd = unsat_constants[r]; -#if _PERC_CHANGE_ - sort * srt = fd->get_range(); - mpz temp; - - if (m_manager.is_bool(srt)) - m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); - - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } -#else - mpz temp = m_tracker.get_random(fd->get_range()); -#endif - update(fd, temp); - m_mpz_manager.del(temp); - } - - void randomize_local(goal_ref const & g, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); - + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: //// bool did_something = false; @@ -889,34 +874,34 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif #if _REAL_RS_ || _REAL_PBFS_ - serious_update(fd, temp); + serious_update(fd, temp); #else - update(fd, temp); + update(fd, temp); #endif m_mpz_manager.del(temp); @@ -927,6 +912,15 @@ public: tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + + } + + void randomize_local(expr * e) { + randomize_local(m_tracker.get_constants(e)); + } + + void randomize_local(goal_ref const & g, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(g, flip)); } }; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 3d5e3e438..ada0ec359 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -34,6 +34,8 @@ Notes: #include"propagate_values_tactic.h" #include"sls_tactic.h" #include"nnf_tactic.h" +#include"luby.h" +#include "ctx_simplify_tactic.h" // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score @@ -43,9 +45,23 @@ Notes: // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + // do we use restarts? -// 0 = no, otherwise the value defines the maximum number of moves -#define _RESTARTS_ 0 +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 // timelimit #define _TIMELIMIT_ 3600 @@ -66,38 +82,58 @@ Notes: // 2 = yes, by squaring it // 3 = yes, by setting it to zero // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 0 +#define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 #define _WEIGHT_DIST_FACTOR_ 0.25 +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + // do we use intensification steps in local minima? if so, how many? #define _INTENSIFICATION_ 0 #define _INTENSIFICATION_TRIES_ 0 +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 0 +#define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 0.01 +#define _UCT_CONSTANT_ 10.0 // is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score #define _PROBABILISTIC_UCT_ 0 +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 // shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 1 +#define _USE_MUL2DIV2_ 0 // shall we try multiplication by 3? -#define _USE_MUL3_ 1 +#define _USE_MUL3_ 0 // shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 1 +#define _USE_UNARY_MINUS_ 0 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 1 +#define _UNIFORM_RANDOM_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 @@ -124,13 +160,21 @@ Notes: #define _CACHE_TOP_SCORE_ 1 -#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) - InvalidConfiguration; +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) + InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; + InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) + InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) + InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) + InvalidConfiguration; #endif - #include"sls_params.hpp" #include"sls_evaluator.h" @@ -150,10 +194,10 @@ class sls_tactic : public tactic { m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -180,11 +224,12 @@ class sls_tactic : public tactic { sls_tracker m_tracker; sls_evaluator m_evaluator; + unsigned m_restart_limit; unsigned m_max_restarts; unsigned m_plateau_limit; - ptr_vector m_old_values; - + ptr_vector m_old_values; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : @@ -208,6 +253,41 @@ class sls_tactic : public tactic { m_mpz_manager.del(m_two); } + double get_restart_armin(unsigned cnt_restarts) + { + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow(_RESTART_CONST_ARMIN_, inner_id + 1); + } + + inline unsigned check_restart(unsigned curr_value) + { + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; + } + ast_manager & m() const { return m_manager; } void set_cancel(bool f) { m_cancel = f; } @@ -267,18 +347,18 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); #if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); + m_tracker.set_top_sum(top_sum); #endif return top_sum / (double) sz; @@ -292,20 +372,20 @@ class sls_tactic : public tactic { } double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif } double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif @@ -314,18 +394,18 @@ class sls_tactic : public tactic { #if _EARLY_PRUNE_ double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) + if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(g); + return top_score(g); #endif - else - return 0.0; + else + return 0.0; } #endif - // checks whether the score outcome of a given move is better than the previous score + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { @@ -357,11 +437,11 @@ class sls_tactic : public tactic { return false; } - // same as what_if, but only applied to the score of a specific atom, not the total score + // same as what_if, but only applied to the score of a specific atom, not the total score bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -378,29 +458,29 @@ class sls_tactic : public tactic { m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); - } + } - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { mpz temp, mask, mask2; m_mpz_manager.mul(old_value, m_two, temp); m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); } void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { m_mpz_manager.div(old_value, m_two, result); } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -435,75 +515,77 @@ class sls_tactic : public tactic { NOT_IMPLEMENTED_YET(); } - void mk_random_move(goal_ref const & g) { + void mk_random_move(ptr_vector & unsat_constants) + { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; + mpz new_value; - sort * srt = fd->get_range(); + sort * srt = fd->get_range(); if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { #if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + mt = MV_FLIP; #endif - unsigned bit = 0; + unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } - // will use VNS to ignore some possible moves and increase the flips per second + void mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); + } + + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -514,7 +596,7 @@ class sls_tactic : public tactic { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -536,12 +618,12 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } } // reset to what it was before @@ -549,12 +631,12 @@ class sls_tactic : public tactic { SASSERT(check == score); } - // we can either check the condition once in the beginning or check it repeatedly after every bit + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) #endif for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { func_decl * fd = to_evaluate[i]; @@ -563,30 +645,30 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } // reset to what it was before double check = incremental_score(g, fd, old_value); SASSERT(check == score); } - m_mpz_manager.del(old_value); + m_mpz_manager.del(old_value); m_mpz_manager.del(temp); return new_score; } - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; + mpz temp2; #endif unsigned bv_sz; double new_score = score; @@ -599,11 +681,11 @@ class sls_tactic : public tactic { // first try to flip every bit #if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { #endif - // What would happen if we flipped bit #i ? + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -614,7 +696,7 @@ class sls_tactic : public tactic { if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { #if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -660,7 +742,7 @@ class sls_tactic : public tactic { // reset to what it was before double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching + // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -669,17 +751,17 @@ class sls_tactic : public tactic { #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif - return new_score; + return new_score; } - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -718,7 +800,7 @@ class sls_tactic : public tactic { } // reset to what it was before - m_evaluator.update(fd, old_value); + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -726,37 +808,37 @@ class sls_tactic : public tactic { return new_score; } - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); #if _BFS_ - unsigned pos = m_stats.m_moves % sz; + unsigned pos = m_stats.m_moves % sz; #else - unsigned pos = m_tracker.get_random_uint(16) % sz; + unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); } else { m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -767,35 +849,35 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); } - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - m_old_values.reset(); + m_old_values.reset(); - return 0; - } + return 0; + } - // what_if version needed in the context of 2nd intensification try, combining local and global score + // what_if version needed in the context of 2nd intensification try, combining local and global score bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, double & best_score, mpz & best_value, unsigned i) { double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); + double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - if (new_score >= best_score) { + if (new_score >= best_score) { best_score = new_score; m_mpz_manager.set(best_value, temp); return true; @@ -804,17 +886,17 @@ class sls_tactic : public tactic { return false; } - // find_best_move version needed in the context of 2nd intensification try + // find_best_move version needed in the context of 2nd intensification try double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; + { + mpz old_value, temp; double best_score = 0; sort * srt = fd->get_range(); unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); what_if(g, e, fd, temp, best_score, best_value, i); } @@ -822,54 +904,178 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - return best_score; + return best_score; } - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); #if _BFS_ - unsigned new_const = m_stats.m_moves % sz; + unsigned new_const = m_stats.m_moves % sz; #else - unsigned new_const = m_tracker.get_random_uint(16) % sz; + unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - return 0; - } + return 0; + } - // main search loop - lbool search(goal_ref const & g) { + // main search loop + lbool search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + // main search loop + lbool search_old(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -885,52 +1091,52 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - // Andreas: Why do we only allow so few plateaus? + // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif #if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { #if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #elif _TYPE_RSTEP_ == 2 - mk_random_move(g); + mk_random_move(g); #endif score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } #endif old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -952,11 +1158,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { - // Andreas: Why does randomizing not count as a move? (Now it does.) + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -984,15 +1190,15 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; @@ -1004,7 +1210,7 @@ class sls_tactic : public tactic { if (score >= 0.99999) { // if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -1015,43 +1221,43 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - } else { - m_stats.m_moves++; + } else { + m_stats.m_moves++; plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); #if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); + handle_plateau(g, score); + //handle_plateau(g); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(g); + //mk_random_move(g); score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } @@ -1070,57 +1276,82 @@ class sls_tactic : public tactic { return; } - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif m_tracker.initialize(g); lbool res = l_undef; + m_restart_limit = _RESTART_LIMIT_; + do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... - //if ((m_stats.m_restarts % 100) == 0) - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); res = search(g); if (res == l_undef) - m_tracker.randomize(); + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1251,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // conservative gaussian elimination. gaussian_p.set_uint("gaussian_max_occs", 2); + params_ref ctx_p; + ctx_p.set_uint("max_depth", 32); + ctx_p.set_uint("max_steps", 5000000); return and_then(and_then(mk_simplify_tactic(m), mk_propagate_values_tactic(m), using_params(mk_solve_eqs_tactic(m), gaussian_p), @@ -1259,7 +1493,11 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? + // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? + //mk_ctx_simplify_tactic(m, ctx_p), + // Andreas: This one at least eliminates top level duplicates ... + mk_simplify_tactic(m), + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index b26912e5c..0aca1f59c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -29,31 +29,31 @@ class sls_tracker { unsigned m_random_bits; unsigned m_random_bits_cnt; mpz m_zero, m_one, m_two; - + struct value_score { #if _EARLY_PRUNE_ - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; #else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; #endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; #if _EARLY_PRUNE_ - double score_prune; - unsigned has_pos_occ; - unsigned has_neg_occ; + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; #endif unsigned distance; // max distance from any root - unsigned touched; + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; - touched = other.touched; + touched = other.touched; return *this; } }; @@ -65,6 +65,7 @@ private: typedef obj_map scores_type; typedef obj_map > uplinks_type; typedef obj_map > occ_type; + obj_hashtable m_top_expr; scores_type m_scores; uplinks_type m_uplinks; entry_point_type m_entry_points; @@ -72,18 +73,18 @@ private: ptr_vector m_temp_constants; occ_type m_constants_occ; #if _UCT_ - unsigned m_touched; + unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif -#if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ + double m_weight_dist_factor; #endif public: @@ -104,24 +105,24 @@ public: m_mpz_manager.del(m_two); } -#if _WEIGHT_DIST_ == 4 - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } #endif #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { - m_top_sum += add - sub; - } + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } - inline void set_top_sum(double new_score) { - m_top_sum = new_score; - } + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } - inline double get_top_sum() { - return m_top_sum; - } + inline double get_top_sum() { + return m_top_sum; + } #endif inline void set_value(expr * n, const mpz & r) { @@ -174,20 +175,20 @@ public: m_scores.find(n).score_prune = score; } - inline double & get_score_prune(expr * n) { + inline double & get_score_prune(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).score_prune; } - inline unsigned has_pos_occ(expr * n) { + inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } - inline unsigned has_neg_occ(expr * n) { + inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -213,11 +214,62 @@ public: return m_uplinks.contains(n); } + inline bool is_top_expr(expr * n) { + return m_top_expr.contains(n); + } + inline ptr_vector & get_uplinks(expr * n) { SASSERT(m_uplinks.contains(n)); return m_uplinks.find(n); } +#if _REAL_RS_ || _REAL_PBFS_ + void debug_real(goal_ref const & g, unsigned flip) + { + unsigned count = 0; + for (unsigned i = 0; i < g->size(); i++) + { + expr * e = g->form(i); + if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is unsat but not in unsat list\n", i); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + expr * q = m_list_false[pos]; + if (q != e) + { + printf("iteration %d: ", flip); + printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); + exit(4); + } + } + + if (m_mpz_manager.eq(get_value(e),m_zero)) + count++; + } + + // should be true now that duplicate assertions are removed + if (count != m_where_false.size()) + { + printf("iteration %d: ", flip); + printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); + exit(4); + } + } +#endif + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -316,45 +368,49 @@ public: } } - void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(proc, visited, q); - } - } - for_each_expr(proc, visited, e); - } + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } - void initialize_recursive(expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(q); - } - } - ptr_vector t; + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } - void initialize(goal_ref const & g) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + if (!m_top_expr.contains(e)) + m_top_expr.insert(e); + else + printf("this is already in ...\n"); + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); + initialize_recursive(proc, visited, e); #endif for_each_expr(proc, visited, e); } @@ -363,9 +419,9 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); + initialize_recursive(e); #endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); @@ -379,53 +435,61 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); #if _REAL_RS_ || _REAL_PBFS_ - m_list_false = new expr*[sz]; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + m_list_false = new expr*[sz]; + //for (unsigned i = 0; i < sz; i++) + //{ + // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + // break_assertion(g->form(i)); + //} #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; #endif } #if _REAL_RS_ || _REAL_PBFS_ - void make_assertion(expr * e) - { - if (m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) - { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - } + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); + } + //else + //printf("Erasing %d from %d to %d\n", e, pos); +// m_list_false[m_where_false.size()] = 0; // printf("Going in %d\n", m_where_false.size()); - } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); - } + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } - void break_assertion(expr * e) - { - if (!m_where_false.contains(e)) - { - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); - } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); - } + void break_assertion(expr * e) + { + //printf("I'm broken... that's still fine.\n"); + if (!m_where_false.contains(e)) + { + //printf("This however is not so cool...\n"); + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } #endif void show_model(std::ostream & out) { @@ -522,7 +586,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize() { + void randomize(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -534,38 +598,60 @@ public: } TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif + } + + void reset(goal_ref const & g) { + TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); + + for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { + mpz temp = m_zero; + set_value(it->m_value, temp); + m_mpz_manager.del(temp); + } + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif } #if _EARLY_PRUNE_ - void setup_occs(expr * n, bool negated = false) { - if (m_manager.is_bool(n)) - { - if (m_manager.is_and(n) || m_manager.is_or(n)) - { - SASSERT(!negated); - app * a = to_app(n); - expr * const * args = a->get_args(); - for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); - } - else if (m_manager.is_not(n)) - { - SASSERT(!negated); - app * a = to_app(n); - SASSERT(a->get_num_args() == 1); - expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); - setup_occs(child, true); - } - else - { - if (negated) - m_scores.find(n).has_neg_occ = 1; - else - m_scores.find(n).has_pos_occ = 1; - } - } + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } else NOT_IMPLEMENTED_YET(); } @@ -574,7 +660,7 @@ public: double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -587,16 +673,24 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. + // Andreas: Seems to have no effect. Probably it does not even occur. #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) +#if _DIRTY_UP_ + sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else sum += get_score(args[i]); +#endif res = sum / (double) a->get_num_args(); #else - double min = 1.0; + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur < min) min = cur; } res = min; @@ -606,18 +700,26 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. #if _SCORE_OR_MUL_ - double inv = 1.0; + double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else - double max = 0.0; + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur > max) max = cur; } res = max; @@ -639,7 +741,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -701,7 +803,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -762,7 +864,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -772,7 +874,11 @@ public: expr * child = a->get_arg(0); if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); +#if _DIRTY_UP_ + res = is_top_expr(child) ? 0.0 : score_bool(child, true); +#else res = score_bool(child, true); +#endif } else if (m_manager.is_distinct(n)) { app * a = to_app(n); @@ -797,25 +903,29 @@ public: SASSERT(res >= 0.0 && res <= 1.0); #if _WEIGHT_DIST_ - app * a = to_app(n); - family_id afid = a->get_family_id(); + app * a = to_app(n); + family_id afid = a->get_family_id(); - if (afid == m_bv_util.get_family_id()) + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#if _WEIGHT_TOGGLE_ + if (res < 1.0) res *= m_weight_dist_factor; +#else + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#endif #elif _WEIGHT_DIST_ == 2 - res *= res; + res *= res; #elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; + if (res < 1.0) res = 0.0; #elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; + if (res < 1.0) res *= m_weight_dist_factor; #endif TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -861,34 +971,34 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } - ptr_vector & get_constants(expr * e) { + ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned i = 0; i < sz; i++) { @@ -897,9 +1007,13 @@ public: m_temp_constants.push_back(fd); } return m_temp_constants; - } + } + + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + if (sz == 1) + return get_constants(); + m_temp_constants.reset(); - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -913,247 +1027,394 @@ public: } } return m_temp_constants; - } + } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; + return q; } - return 0; - } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); + if (!q) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e || m_temp_constants.size()) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned j = 0; j < sz; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) - return m_temp_constants; + return m_temp_constants; - return go_deeper(q); - } + return go_deeper(q); + } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) - return m_temp_constants; - else - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 #if _UCT_ - unsigned pos = -1; - value_score vscore; + unsigned pos = -1; + value_score vscore; #if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; #else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); -#elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } #endif - if (pos == static_cast(-1)) - return m_temp_constants; + if (pos == static_cast(-1)) + return m_temp_constants; #if _UCT_ == 1 - m_scores.find(g->form(pos)).touched++; - m_touched++; + m_scores.find(g->form(pos)).touched++; + m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = g->form(pos); + expr * e = g->form(pos); +// expr * e = m_list_false[pos]; #elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; + unsigned int pos = -1; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; + unsigned int pos = -1; + double min = 2.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); #elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(e); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif - return get_unsat_constants_crsat(g, sz, pos); + return get_unsat_constants_crsat(g, sz, pos); #else - return get_unsat_constants_gsat(g, sz); + return get_unsat_constants_gsat(g, sz); #endif } } + + + expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); + + if (sz == 1) + return g->form(0); + + m_temp_constants.reset(); +#if _FOCUS_ == 1 +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return 0; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif +// return m_list_false[pos]; + return g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 2 + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 1 + unsigned int pos = flip % sz; + return get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return0; + else + return m_list_false[flip % sz]; +#else + unsigned int pos = get_random_uint(16) % sz; + return get_unsat_assertion(g, sz, pos); +#endif + return g->form(pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % sz; +#else + unsigned int pos = get_random_uint(16) % sz; +#endif + return get_unsat_constants_crsat(g, sz, pos); +#endif + } }; #endif \ No newline at end of file From 3d6f8840c65071f186a4955665cbd4db16a53be6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:04:38 +0000 Subject: [PATCH 018/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 158 +++ src/tactic/sls/sls_engine.cpp | 1160 +++++++++++++++++ src/tactic/sls/sls_engine.h | 159 +++ src/tactic/sls/sls_evaluator.h | 3 + src/tactic/sls/sls_tactic.cpp | 1396 +-------------------- src/tactic/sls/sls_tracker.h | 10 +- 6 files changed, 1520 insertions(+), 1366 deletions(-) create mode 100644 src/tactic/sls/sls_compilation_settings.h create mode 100644 src/tactic/sls/sls_engine.cpp create mode 100644 src/tactic/sls/sls_engine.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h new file mode 100644 index 000000000..aea4787b0 --- /dev/null +++ b/src/tactic/sls/sls_compilation_settings.h @@ -0,0 +1,158 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_compilation_constants.h + +Abstract: + + Stochastic Local Search (SLS) compilation constants + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + + This file should go away completely once we have evaluated all options. + +--*/ +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom +#define _FOCUS_ 1 + +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + +// do we use restarts? +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? +#define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? +#define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained +#define _VNS_ 0 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 1 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 1 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 10.0 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score +#define _PROBABILISTIC_UCT_ 0 + +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 0 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 0 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 0 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 0 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) +InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) +InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) +InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) +InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) +InvalidConfiguration; +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp new file mode 100644 index 000000000..92471aad8 --- /dev/null +++ b/src/tactic/sls/sls_engine.cpp @@ -0,0 +1,1160 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + sls_engine.cpp + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#include + +#include"map.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"tactic.h" +#include"cooperate.h" +#include"luby.h" + +#include"sls_compilation_settings.h" +#include"sls_params.hpp" +#include"sls_engine.h" + + +sls_engine::sls_engine(ast_manager & m, params_ref const & p) : + m_manager(m), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) +{ + updt_params(p); +} + +sls_engine::~sls_engine() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); +} + +double sls_engine::get_restart_armin(unsigned cnt_restarts) +{ + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} + +void sls_engine::updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_plateau_limit = p.plateau_limit(); +} + +void sls_engine::checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); +} + +bool sls_engine::full_eval(goal_ref const & g, model & mdl) { + bool res = true; + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(g->form(i), o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; +} + +double sls_engine::top_score(goal_ref const & g) { +#if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl;); + return min; +#else + double top_sum = 0.0; + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); + } + + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " AVG: " << top_sum / (double)sz << std::endl;); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + + return top_sum / (double)sz; +#endif +} + +double sls_engine::rescore(goal_ref const & g) { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(g); +} + +double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif +} + +double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif +} + +double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +#if _EARLY_PRUNE_ + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; +#else + NOT_IMPLEMENTED_YET(); +#endif +} + +// checks whether the score outcome of a given move is better than the previous score +bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + +#ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); +#endif + +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else + double r = incremental_score(g, fd, temp); +#endif +#ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl;); + + m_mpz_manager.del(old_value); +#endif + + // if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +// same as what_if, but only applied to the score of a specific atom, not the total score +bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + +} + +// Andreas: do we really need all those temporary mpzs? +void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); +} + +void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); +} + +void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); +} + +void sls_engine::mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); +} + +void sls_engine::mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); +} + +void sls_engine::mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); +} + +void sls_engine::mk_random_move(ptr_vector & unsat_constants) +{ + unsigned rnd_mv = 0; + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + + mpz new_value; + + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type)rnd_mv; + + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); +} + +void sls_engine::mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +} + +// will use VNS to ignore some possible moves and increase the flips per second +double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + // we can either check the condition once in the beginning or check it repeatedly after every bit +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; +} + +// same as find_best_move but only considers the score of the current expression instead of the overall score +double sls_engine::find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// first try of intensification ... does not seem to be efficient +bool sls_engine::handle_plateau(goal_ref const & g) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back(&m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } + else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], *m_old_values[i]); + + m_old_values.reset(); + + return 0; +} + +// what_if version needed in the context of 2nd intensification try, combining local and global score +bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +// find_best_move version needed in the context of 2nd intensification try +double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +{ + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; +} + +// second try to use intensification ... also not very effective +bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; +} + +// main search loop +lbool sls_engine::search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +// main search loop +lbool sls_engine::search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { +#endif + do { + checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl;); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl;); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl;); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + } + + if (score >= 0.99999) { + // if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } + else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else + m_evaluator.randomize_local(g, m_stats.m_moves); +#endif + //mk_random_move(g); + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + m_produce_models = g->models_enabled(); + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; +} \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h new file mode 100644 index 000000000..878354c6d --- /dev/null +++ b/src/tactic/sls/sls_engine.h @@ -0,0 +1,159 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_engine.h + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#ifndef _SLS_ENGINE_H_ +#define _SLS_ENGINE_H_ + +#include"stopwatch.h" +#include"lbool.h" +#include"model_converter.h" + +#include"sls_compilation_settings.h" +#include"sls_tracker.h" +#include"sls_evaluator.h" + +class sls_engine { +public: + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + +protected: + ast_manager & m_manager; + stats m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + + unsigned m_restart_limit; + unsigned m_max_restarts; + unsigned m_plateau_limit; + + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + +public: + sls_engine(ast_manager & m, params_ref const & p); + ~sls_engine(); + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + void updt_params(params_ref const & _p); + + stats const & get_stats(void) { return m_stats; } + void reset_statistics(void) { m_stats.reset(); } + + bool full_eval(goal_ref const & g, model & mdl); + + + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result); + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + + + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); + + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); + + + lbool search(goal_ref const & g); + + void operator()(goal_ref const & g, model_converter_ref & mc); + +protected: + void checkpoint(); + lbool search_old(goal_ref const & g); + double get_restart_armin(unsigned cnt_restarts); + + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + + double top_score(goal_ref const & g); + double rescore(goal_ref const & g); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); +#endif + + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + void mk_random_move(ptr_vector & unsat_constants); + void mk_random_move(goal_ref const & g); + + bool handle_plateau(goal_ref const & g); + bool handle_plateau(goal_ref const & g, double old_score); + + inline unsigned check_restart(unsigned curr_value); +}; + +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 97860e3a2..8d2a7ba1d 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -20,6 +20,9 @@ Notes: #ifndef _SLS_EVALUATOR_H_ #define _SLS_EVALUATOR_H_ +#include"model_evaluator.h" + +#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 743ad00bc..0f157d3a6 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,1363 +16,31 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" -#include"luby.h" -#include "ctx_simplify_tactic.h" - -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick clause when randomizing in a plateau or use the current one? -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 - -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 - -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? -#define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) - InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) - InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) - InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) - InvalidConfiguration; -#endif +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; - - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_restart_limit; - unsigned m_max_restarts; - unsigned m_plateau_limit; - - ptr_vector m_old_values; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - double get_restart_armin(unsigned cnt_restarts) - { - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow(_RESTART_CONST_ARMIN_, inner_id + 1); - } - - inline unsigned check_restart(unsigned curr_value) - { - if (curr_value > m_restart_limit) - { -#if _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); -#elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 1 - if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; - else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; -#else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif - return 0; - } - return 1; - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - top_sum += m_tracker.get_score(e); - } - - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - -#if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); -#endif - - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; - } -#endif - - // checks whether the score outcome of a given move is better than the previous score - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - -#if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); -#else - double r = incremental_score(g, fd, temp); -#endif - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - -// if (r >= best_score) { - if (r > best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // same as what_if, but only applied to the score of a specific atom, not the total score - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.add(old_value, add_value, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - - } - - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - } - - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(ptr_vector & unsat_constants) - { - unsigned rnd_mv = 0; - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - - mpz new_value; - - sort * srt = fd->get_range(); - if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { -#if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; -#else - mt = MV_FLIP; -#endif - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } - - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } - - void mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); - } - - // will use VNS to ignore some possible moves and increase the flips per second - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } -#endif - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - return new_score; - } - - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - - m_old_values.reset(); - - return 0; - } - - // what_if version needed in the context of 2nd intensification try, combining local and global score - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // find_best_move version needed in the context of 2nd intensification try - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; - } - - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; - } - - // main search loop - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - unsigned plateau_cnt = 0; - - score = rescore(g); - unsigned sz = g->size(); -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - checkpoint(); - m_stats.m_moves++; - -#if _REAL_RS_ || _REAL_PBFS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } - continue; -#endif - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - old_score = score; - new_const = (unsigned)-1; - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - - if (new_const == static_cast(-1)) { - score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); - else -#endif -#if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); -#else - m_evaluator.randomize_local(to_evaluate); -#endif -#endif - -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } else { - func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - // main search loop - lbool search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 0.99999) { -// if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } - while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -1380,16 +48,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -1397,14 +65,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -1413,40 +80,41 @@ public: } virtual void cleanup() { - imp * d = m_imp; + sls_engine * d = m_engine; #pragma omp critical (tactic_cancel) { - d = m_imp; + d = m_engine; } dealloc(d); - d = alloc(imp, m, m_params, m_stats); + d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - m_imp = d; + m_engine = d; } } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + sls_engine::stats const & stats = m_engine->get_stats(); + double seconds = stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", stats.m_restarts); + st.update("sls full evals", stats.m_full_evals); + st.update("sls incr evals", stats.m_incr_evals); + st.update("sls incr evals/sec", stats.m_incr_evals / seconds); + st.update("sls FLIP moves", stats.m_flips); + st.update("sls INC moves", stats.m_incs); + st.update("sls DEC moves", stats.m_decs); + st.update("sls INV moves", stats.m_invs); + st.update("sls moves", stats.m_moves); + st.update("sls moves/sec", stats.m_moves / seconds); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 4d9c078b6..7d1d4c0f1 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,12 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"goal.h" +#include"model.h" + +#include"sls_compilation_settings.h" +#include"sls_powers.h" + class sls_tracker { ast_manager & m_manager; unsynch_mpz_manager & m_mpz_manager; @@ -1187,7 +1193,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif @@ -1335,7 +1341,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif From e3ae0ba0bd67b40944efc9afacc65d5eacc024d5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:26:05 +0000 Subject: [PATCH 019/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index aea4787b0..8e52596e0 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -18,6 +18,10 @@ Notes: This file should go away completely once we have evaluated all options. --*/ + +#ifndef _SLS_COMPILATION_SETTINGS_H_ +#define _SLS_COMPILATION_SETTINGS_H_ + // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score #define _BFS_ 0 @@ -155,4 +159,6 @@ InvalidConfiguration; #endif #if (_PERC_STICKY_ && !_FOCUS_) InvalidConfiguration; +#endif + #endif \ No newline at end of file From c615bc0c34fa3646e0312c89e5fd7f0ce51efbe7 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Thu, 20 Mar 2014 15:58:53 +0000 Subject: [PATCH 020/646] uct forget and minisat restarts added --- src/tactic/sls/sls_tactic.cpp | 31 +++++++++++++++++++++++-------- src/tactic/sls/sls_tracker.h | 22 ++++++++++++++++++++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 743ad00bc..b2b7035e0 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -49,7 +49,7 @@ Notes: #define _PERC_STICKY_ 0 // do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 +#define _DIRTY_UP_ 1 // do we use restarts? // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time @@ -58,10 +58,10 @@ Notes: #define _RESTART_LIMIT_ 10 // 0 = initialize with all zero, 1 initialize with random value #define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat #define _RESTART_SCHEME_ 1 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 +#define _RESTART_CONST_ARMIN_ 4.0 // timelimit #define _TIMELIMIT_ 3600 @@ -85,7 +85,7 @@ Notes: #define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 +#define _WEIGHT_DIST_FACTOR_ 0.5 // shall we toggle the weight after each restart? #define _WEIGHT_TOGGLE_ 0 @@ -104,7 +104,7 @@ Notes: #define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 +#define _UCT_CONSTANT_ 20.0 // is uct clause selection probabilistic similar to variable selection in sparrow? // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score @@ -116,9 +116,13 @@ Notes: // shall we reset _UCT_ touched values after restart? #define _UCT_RESET_ 0 +// do we gradually reduce the touched values of _UCT_? +#define _UCT_FORGET_ 0 +#define _UCT_FORGET_FACTOR_ 0.5 + // how shall we initialize the _UCT_ total touched counter? // 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 +#define _UCT_INIT_ 0 // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 @@ -265,7 +269,9 @@ class sls_tactic : public tactic { { if (curr_value > m_restart_limit) { -#if _RESTART_SCHEME_ == 4 +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; @@ -976,6 +982,11 @@ class sls_tactic : public tactic { checkpoint(); m_stats.m_moves++; +#if _UCT_FORGET_ + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + #if _REAL_RS_ || _REAL_PBFS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif @@ -1277,11 +1288,13 @@ class sls_tactic : public tactic { verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl; verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; @@ -1296,6 +1309,8 @@ class sls_tactic : public tactic { verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; @@ -1495,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), // Andreas: This one at least eliminates top level duplicates ... - mk_simplify_tactic(m), + //mk_simplify_tactic(m), // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 4d9c078b6..45e1719d2 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -270,6 +270,20 @@ public: } #endif + void uct_forget(goal_ref const & g) { + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < g->size(); i++) + { + e = g->form(i); + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } + } + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -1190,6 +1204,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1197,7 +1213,7 @@ public: if (pos == static_cast(-1)) return m_temp_constants; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 @@ -1338,6 +1354,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1345,7 +1363,7 @@ public: if (pos == static_cast(-1)) return 0; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 From 6f9a348f6398cecd0852f2d74d4d25ebb4d670fc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 26 Mar 2014 17:26:06 +0000 Subject: [PATCH 021/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 219 +++++++++++++++++++-------------- src/tactic/sls/sls_engine.h | 58 ++++----- src/tactic/sls/sls_evaluator.h | 4 +- src/tactic/sls/sls_tracker.h | 84 ++++++------- 4 files changed, 195 insertions(+), 170 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 92471aad8..9fa2cc263 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -74,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(goal_ref const & g, model & mdl) { +bool sls_engine::full_eval(model & mdl) { bool res = true; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(g->form(i), o, true)) + if (!mdl.eval(m_assertions[i], o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) { return res; } -double sls_engine::top_score(goal_ref const & g) { +double sls_engine::top_score() { #if 0 double min = m_tracker.get_score(g->form(0)); unsigned sz = g->size(); @@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) { return min; #else double top_sum = 0.0; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = m_assertions[i]; top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); + tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); #if _CACHE_TOP_SCORE_ @@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) { #endif } -double sls_engine::rescore(goal_ref const & g) { +double sls_engine::rescore() { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(g); + return top_score(); } -double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { #if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif else return 0.0; @@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); + double r = incremental_score_prune(fd, temp); #else - double r = incremental_score(g, fd, temp); + double r = incremental_score(fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd } // same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if_local( + expr * e, + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) +{ m_evaluator.update(fd, temp); double r = m_tracker.get_score(e); if (r >= best_score) { @@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +void sls_engine::mk_random_move() { + mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves)); } // will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move_vns( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; unsigned bv_sz, max_bv_sz = 0; double new_score = score; @@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; // try to flip lsb mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = 0; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } @@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector { mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } m_mpz_manager.del(old_value); @@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector } // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ mpz temp2; @@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } @@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; #if _USE_UNARY_MINUS_ @@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector & to_eva } // first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau(goal_ref const & g) +bool sls_engine::handle_plateau() { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned pos = m_stats.m_moves % sz; #else unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + expr * e = m_tracker.get_unsat_assertion(sz, pos); if (!e) return 0; @@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g) } // what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); +bool sls_engine::what_if( + expr * e, + func_decl * fd, + const mpz & temp, + double & best_score, + mpz & best_value, + unsigned i) +{ + double global_score = incremental_score(fd, temp); double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; @@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz } // find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i) { mpz old_value, temp; double best_score = 0; @@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); + what_if(e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); @@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl } // second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +bool sls_engine::handle_plateau(double old_score) { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned new_const = m_stats.m_moves % sz; #else unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const); if (!e) return 0; @@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) { - new_score = find_best_move_local(g, q, fd, new_value, i); + new_score = find_best_move_local(q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); + global_score = incremental_score(fd, new_value); local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) } // main search loop -lbool sls_engine::search(goal_ref const & g) { +lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) { move_type move; unsigned plateau_cnt = 0; - score = rescore(g); - unsigned sz = g->size(); + score = rescore(); + unsigned sz = m_assertions.size(); #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) { if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves); #endif if (!e) { @@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { @@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) { else #endif #if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #else m_evaluator.randomize_local(to_evaluate); #endif #endif #if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); + score = m_tracker.get_top_sum() / m_assertions.size(); #else score = top_score(g); #endif @@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _REAL_RS_ || _REAL_PBFS_ score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif } } @@ -840,18 +869,18 @@ bailout: } // main search loop -lbool sls_engine::search_old(goal_ref const & g) { +lbool sls_engine::search_old() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - score = rescore(g); + score = rescore(); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); unsigned plateau_cnt = 0; @@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) { old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves); if (!to_evaluate.size()) { res = l_true; @@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) { tout << to_evaluate[i]->get_name() << std::endl;); #if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + for (unsigned i = 0; i < m_assertions.size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl; }); TRACE("sls_max", m_tracker.show_model(tout); tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl;); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " << + m_tracker.get_score(m_assertions[i]) << std::endl;); // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } @@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) { } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); } @@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) { // score could theoretically be imprecise. // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); #if _INTENSIFICATION_ handle_plateau(g, score); - //handle_plateau(g); + //handle_plateau(); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #endif - //mk_random_move(g); - score = top_score(g); + //mk_random_move(); + score = top_score(); if (score >= 1.0) { bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; @@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { #if _WEIGHT_TOGGLE_ m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif - m_tracker.initialize(g); + m_tracker.initialize(m_assertions); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; @@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { checkpoint(); report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); + res = search(); if (res == l_undef) { #if _RESTART_INIT_ - m_tracker.randomize(g); + m_tracker.randomize(); #else - m_tracker.reset(g); + m_tracker.reset(m_assertions); #endif } } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 878354c6d..8458817b6 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -71,6 +71,7 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; + ptr_vector m_assertions; unsigned m_restart_limit; unsigned m_max_restarts; @@ -92,11 +93,12 @@ public: void updt_params(params_ref const & _p); + void assert_expr(expr * e) { m_assertions.push_back(e); } + stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(goal_ref const & g, model & mdl); - + bool full_eval(model & mdl); void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); @@ -104,54 +106,44 @@ public: void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - - - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); - - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); - - - lbool search(goal_ref const & g); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); - lbool search_old(goal_ref const & g); + lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - + bool what_if(expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(goal_ref const & g); - double rescore(goal_ref const & g); - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); #if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score_prune(func_decl * fd, const mpz & new_value); #endif - - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i); + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_vns(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(goal_ref const & g); + void mk_random_move(); - bool handle_plateau(goal_ref const & g); - bool handle_plateau(goal_ref const & g, double old_score); + bool handle_plateau(void); + bool handle_plateau(double old_score); inline unsigned check_restart(unsigned curr_value); }; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 8d2a7ba1d..0053763bb 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -922,8 +922,8 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(g, flip)); + void randomize_local(ptr_vector const & as, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(as, flip)); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 6ac054246..1b451e8fd 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,7 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"goal.h" +#include"bv_decl_plugin.h" #include"model.h" #include"sls_compilation_settings.h" @@ -365,12 +365,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -418,12 +418,12 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(goal_ref const & g) { + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); else @@ -438,7 +438,7 @@ public: visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); @@ -450,7 +450,7 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); @@ -465,11 +465,11 @@ public: #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(as[i]); #endif #if _UCT_ - m_touched = _UCT_INIT_ ? g->size() : 1; + m_touched = _UCT_INIT_ ? as.size() : 1; #endif } @@ -606,7 +606,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(goal_ref const & g) { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -620,13 +620,13 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } - void reset(goal_ref const & g) { + void reset(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -636,9 +636,9 @@ public: } #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } @@ -1029,13 +1029,13 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { if (sz == 1) return get_constants(); m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1049,22 +1049,22 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * get_unsat_assertion(ptr_vector const & as, unsigned sz, unsigned int pos) { for (unsigned i = pos; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } return 0; } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; @@ -1141,19 +1141,19 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); if (!q) return m_temp_constants; return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + ptr_vector & get_unsat_constants(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + if (m_mpz_manager.eq(get_value(as[0]), m_one)) return m_temp_constants; else return get_constants(); @@ -1202,7 +1202,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1220,12 +1220,12 @@ public: return m_temp_constants; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(as[pos]).touched = flip; #endif - expr * e = g->form(pos); + expr * e = as[pos]; // expr * e = m_list_false[pos]; #elif _BFS_ == 3 @@ -1304,11 +1304,11 @@ public: } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + expr * get_unsat_assertion(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) - return g->form(0); + return as[0]; m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1352,7 +1352,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1370,13 +1370,13 @@ public: return 0; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 m_scores.find(g->form(pos)).touched = flip; #endif // return m_list_false[pos]; - return g->form(pos); + return as[pos]; #elif _BFS_ == 3 unsigned int pos = -1; @@ -1430,7 +1430,7 @@ public: unsigned int pos = get_random_uint(16) % sz; return get_unsat_assertion(g, sz, pos); #endif - return g->form(pos); + return as[pos]; #elif _FOCUS_ == 2 #if _BFS_ unsigned int pos = flip % sz; From be2066a1a63158d2087fa9ee33d537c28dd52af5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:34:21 +0000 Subject: [PATCH 022/646] disabled old code --- src/tactic/sls/sls_engine.cpp | 4 +++- src/tactic/sls/sls_engine.h | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 9fa2cc263..cc06e4f78 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -868,6 +868,7 @@ bailout: return res; } +#if 0 // Old code. // main search loop lbool sls_engine::search_old() { lbool res = l_undef; @@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() { } } } +#endif bailout: m_mpz_manager.del(new_value); @@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value) return 0; } return 1; -} \ No newline at end of file +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8458817b6..5d4c9a0fc 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -114,7 +114,6 @@ public: protected: void checkpoint(); - lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, @@ -148,4 +147,4 @@ protected: inline unsigned check_restart(unsigned curr_value); }; -#endif \ No newline at end of file +#endif From c5e059211f5e1c919ab21714520d4f2434a50c07 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:37:04 +0000 Subject: [PATCH 023/646] bugfix --- src/tactic/sls/sls_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index cc06e4f78..10aaf6601 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() { } } } -#endif bailout: m_mpz_manager.del(new_value); return res; } +#endif void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { From 883762d54a7352997bb496a0d75e29d48df851f7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:27:06 +0000 Subject: [PATCH 024/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1b451e8fd..e29cebe90 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -276,13 +276,13 @@ public: } #endif - void uct_forget(goal_ref const & g) { + void uct_forget(ptr_vector & as) { expr * e; unsigned touched_old, touched_new; - for (unsigned i = 0; i < g->size(); i++) + for (unsigned i = 0; i < as.size(); i++) { - e = g->form(i); + e = as[i]; touched_old = m_scores.find(e).touched; touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); m_scores.find(e).touched = touched_new; From 176715aea07ed98b4fedf188cf2e1af1a3e4f624 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:28:40 +0000 Subject: [PATCH 025/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index e29cebe90..f5c77fc35 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"for_each_expr.h" #include"bv_decl_plugin.h" #include"model.h" From 8e5659ac4cf795ba2f375515cbb2a5c0874ec0c0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:30:15 +0000 Subject: [PATCH 026/646] compilation fixes Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_tracker.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 5d4c9a0fc..96041d09e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,6 +22,7 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" +#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index f5c77fc35..50d0e4188 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -21,6 +21,7 @@ Notes: #define _SLS_TRACKER_H_ #include"for_each_expr.h" +#include"ast_smt2_pp.h" #include"bv_decl_plugin.h" #include"model.h" From 24d662ba49a487517758e6e2e7489ffdf47075fb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 14:58:59 +0000 Subject: [PATCH 027/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 21 ++++++++++++--------- src/tactic/sls/sls_engine.h | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 10aaf6601..e7ee2abbd 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1069,6 +1069,16 @@ bailout: } #endif +void sls_engine::init_tracker() { +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(m_assertions); +} + void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { mc = 0; @@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); - + assert_expr(g->form(i)); verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; @@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(m_assertions); + init_tracker(); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 96041d09e..c56d6ec40 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -109,6 +109,8 @@ public: void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void init_tracker(void); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); From 0f5d2e010dd207b99c20696bef8eb0945d569be5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:26:52 +0000 Subject: [PATCH 028/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++---------------- src/tactic/sls/sls_engine.h | 1 + 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index e7ee2abbd..2b359608a 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + lbool res = operator()(); + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +lbool sls_engine::operator()() { init_tracker(); lbool res = l_undef; @@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout);); - } - g->reset(); - } - else - mc = 0; } unsigned sls_engine::check_restart(unsigned curr_value) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index c56d6ec40..c6e3af155 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -113,6 +113,7 @@ public: lbool search(void); + lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: From f8ee58b30122b53e5cd2fb9c346788c2c732f0f0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:28:02 +0000 Subject: [PATCH 029/646] bvsls bugfix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 2b359608a..dc4451bb5 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; } unsigned sls_engine::check_restart(unsigned curr_value) From ef1d8f2acc9aca562a83e55f89e8820b48c525d5 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 20 Apr 2014 16:38:49 +0100 Subject: [PATCH 030/646] Current version before integration ... --- src/tactic/sls/sls_compilation_settings.h | 36 +- src/tactic/sls/sls_engine.cpp | 348 ++++++++++++++++++-- src/tactic/sls/sls_engine.h | 12 +- src/tactic/sls/sls_evaluator.h | 146 ++++++++- src/tactic/sls/sls_tactic.cpp | 4 +- src/tactic/sls/sls_tracker.h | 379 +++++++++++++++++++++- src/tactic/smtlogics/qfbv_tactic.cpp | 28 ++ 7 files changed, 885 insertions(+), 68 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 4d8c83599..d2b899dd8 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -36,17 +36,21 @@ Notes: // do we use dirty unit propagation to get rid of nested top level assertions? #define _DIRTY_UP_ 0 +// shall we use additive weighting scheme? +#define _PAWS_ 5 +#define _PAWS_INIT_ 40 + // do we use restarts? // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 +#define _RESTARTS_ 1 // limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 +#define _RESTART_LIMIT_ 100 // 0 = initialize with all zero, 1 initialize with random value #define _RESTART_INIT_ 0 // 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat #define _RESTART_SCHEME_ 1 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 +#define _RESTART_CONST_ARMIN_ 2.0 // timelimit #define _TIMELIMIT_ 3600 @@ -61,6 +65,21 @@ Notes: // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 +// shall we check 2-bit flips in plateaus using Monte Carlo? +#define _VNS_MC_ 0 + +// how many 2-bit flips shall we try per bit? +#define _VNS_MC_TRIES_ 1 + +// shall we check another assertion if no improving step was found in the first one? +#define _VNS_REPICK_ 0 + +// what is the probability of doing so (percentage)? +#define _VNS_PERC_ 100 + +// do a decreasing move with percentage ... +#define _INSIST_PERC_ 0 + // do we reduce the score of unsatisfied literals? // 0 = no // 1 = yes, by multiplying it with some factor @@ -70,7 +89,7 @@ Notes: #define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 +#define _WEIGHT_DIST_FACTOR_ 0.5 // shall we toggle the weight after each restart? #define _WEIGHT_TOGGLE_ 0 @@ -82,14 +101,15 @@ Notes: // what is the percentage of random moves in plateaus (instead of full randomization)? #define _PERC_PLATEAU_MOVES_ 0 -// shall we repick clause when randomizing in a plateau or use the current one? +// shall we repick assertion when randomizing in a plateau or use the current one? +// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one #define _REPICK_ 1 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ #define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 +#define _UCT_CONSTANT_ 20.0 // is uct clause selection probabilistic similar to variable selection in sparrow? // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score @@ -103,11 +123,11 @@ Notes: // how shall we initialize the _UCT_ total touched counter? // 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 +#define _UCT_INIT_ 0 // do we gradually reduce the touched values of _UCT_? #define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.5 +#define _UCT_FORGET_FACTOR_ 0.9 // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 92471aad8..342e649af 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -169,6 +169,14 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c #endif } +double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune_new(fd, new_value)) + return (m_tracker.get_top_sum() / g->size()); + else + return 0.0; +} + // checks whether the score outcome of a given move is better than the previous score bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { @@ -190,8 +198,33 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd m_mpz_manager.del(old_value); #endif - // if (r >= best_score) { + //if (r >= best_score) { if (r > best_score) { + m_tracker.reset_equal_scores(); + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + /*else if (r == best_score) { + if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0) + { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + }*/ + + return false; +} + +bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + double r = incremental_score_prune_new(g, fd, temp); + + if (r >= best_score) { best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -426,39 +459,25 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector return new_score; } -// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; + unsigned bv_sz, max_bv_sz = 0; double new_score = score; - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); @@ -471,9 +490,121 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + for (unsigned j = 1; j < max_bv_sz; j++) + { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; +#if _INSIST_PERC_ + double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score; +#else + double new_score = score; +#endif + + m_tracker.reset_equal_scores(); + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { +// for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) { +// for (unsigned i = to_evaluate.size(); i-- > 0; ) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { +#else +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { +// for (unsigned j = bv_sz; j-- > 0; ) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + //if (m_tracker.get_random_uint(1)) + //if ((move != MV_FLIP) || (new_bit > j)) + //{ + //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) { + // new_bit = j; + // move = MV_FLIP; + //} + //} + //else + //{ + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + //} + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } #endif // try inverting mk_inv(bv_sz, old_value, temp); + //if (m_tracker.get_random_uint(1)) if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; @@ -514,6 +645,50 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif + + if ((new_score == score) && 1)// (m_tracker.get_random_uint(1))) + best_const = -1; + + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value) { + mpz old_value, temp, temp2; + unsigned bv_sz; + double new_score = score; + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { + mk_flip(srt, old_value, j, temp); + for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + { + unsigned k = m_tracker.get_random_uint(16) % bv_sz; + while (k == j) + k = m_tracker.get_random_uint(16) % bv_sz; + mk_flip(srt, temp, k, temp2); + what_if(g, fd, i, temp2, new_score, best_const, best_value); + } + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + m_mpz_manager.del(temp2); + return new_score; } @@ -725,6 +900,13 @@ lbool sls_engine::search(goal_ref const & g) { score = rescore(g); unsigned sz = g->size(); + + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -738,9 +920,18 @@ lbool sls_engine::search(goal_ref const & g) { #else while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #endif + //if (m_stats.m_stopwatch.get_current_seconds() > 10.0) + //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);} + checkpoint(); m_stats.m_moves++; +#if _UCT_FORGET_ + //if (m_stats.m_moves % sz == 0) + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + #if _REAL_RS_ || _REAL_PBFS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif @@ -757,6 +948,7 @@ lbool sls_engine::search(goal_ref const & g) { res = l_true; goto bailout; } + //ptr_vector & to_evaluate = m_tracker.get_unsat_constants_only(e); ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); #else ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); @@ -789,6 +981,8 @@ lbool sls_engine::search(goal_ref const & g) { #endif old_score = score; new_const = (unsigned)-1; + move = MV_FLIP; + new_bit = 0; #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); @@ -796,6 +990,60 @@ lbool sls_engine::search(goal_ref const & g) { score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); #endif +#if _VNS_MC_ > _VNS_REPICK_ +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#endif + +#if _VNS_MC_ < _VNS_REPICK_ +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#endif + +#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_ + if (new_const == static_cast(-1)) { + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); + else { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } + } +#endif + + if (new_const == static_cast(-1)) { score = old_score; plateau_cnt++; @@ -810,10 +1058,19 @@ lbool sls_engine::search(goal_ref const & g) { mk_random_move(to_evaluate); else #endif -#if _REPICK_ +#if _REPICK_ == 1 m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _REPICK_ == 2 + { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + m_evaluator.randomize_local(q); + else + m_evaluator.randomize_local(e); + } #else - m_evaluator.randomize_local(to_evaluate); + m_evaluator.randomize_local_n(g, to_evaluate); + //m_evaluator.randomize_local(to_evaluate); #endif #endif @@ -822,10 +1079,28 @@ lbool sls_engine::search(goal_ref const & g) { #else score = top_score(g); #endif + +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * q = g->form(i); + if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } + } +#endif + } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ score = serious_score(g, fd, new_value); #else score = incremental_score(g, fd, new_value); @@ -961,7 +1236,7 @@ lbool sls_engine::search_old(goal_ref const & g) { case MV_DIV2: m_stats.m_div2s++; break; } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ score = serious_score(g, fd, new_value); #else score = incremental_score(g, fd, new_value); @@ -1056,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; + verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; + verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; + verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; + verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl; + verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl; verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; @@ -1067,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; @@ -1136,7 +1420,9 @@ unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_limit) { -#if _RESTART_SCHEME_ == 4 +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; @@ -1144,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value) m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) + //if (m_stats.m_restarts % 3 == 2) m_restart_limit += _RESTART_LIMIT_; else m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; + //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_; #else m_restart_limit += _RESTART_LIMIT_; #endif diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 878354c6d..902c6b7a0 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -108,7 +108,13 @@ public: double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - + + double find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); + double find_best_move_local(expr * e, ptr_vector & to_evaluate, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); @@ -132,6 +138,10 @@ protected: bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); + bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value); + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 8d2a7ba1d..78f2cb79a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -575,7 +575,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -584,12 +584,13 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif #endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -634,7 +635,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -643,7 +644,7 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); @@ -683,7 +684,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ run_serious_update(max_depth); #else run_update(max_depth); @@ -729,14 +730,16 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) pot_benefits = 1; if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { @@ -771,7 +774,7 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); @@ -858,6 +861,104 @@ public: } #endif + unsigned run_update_bool_prune_new(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + unsigned update_prune_new(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune_new(cur_depth); + } + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: @@ -901,7 +1002,7 @@ public: mpz temp = m_tracker.get_random(fd->get_range()); #endif -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ serious_update(fd, temp); #else update(fd, temp); @@ -922,9 +1023,36 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { + void randomize_local(goal_ref const & g, unsigned int flip) { randomize_local(m_tracker.get_unsat_constants(g, flip)); } + + void randomize_local_n(goal_ref const & g, ptr_vector & unsat_constants) { + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; + sort * srt = fd->get_range(); + unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); + mpz max_val = m_tracker.get_random(srt); + update(fd, max_val); + double max_score = m_tracker.get_top_sum() / g->size(); + mpz temp_val; + double temp_score; + for (unsigned i = 1; i < 2; i++) + //for (unsigned i = 1; i < bv_sz; i++) + { + m_mpz_manager.set(temp_val, m_tracker.get_random(srt)); + update(fd, temp_val); + temp_score = m_tracker.get_top_sum() / g->size(); + if (temp_score > max_score) + { + m_mpz_manager.set(max_val, temp_val); + max_score = temp_score; + } + } + update(fd, max_val); + m_mpz_manager.del(temp_val); + m_mpz_manager.del(max_val); + } }; #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index a9b110224..7a9252fe2 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -161,14 +161,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { mk_max_bv_sharing_tactic(m), // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... + // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! //mk_simplify_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); +// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 6ac054246..87c90f1f8 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -86,12 +86,17 @@ private: obj_map m_where_false; expr** m_list_false; #endif +#if _PAWS_ + obj_map m_weights; + //obj_map m_weights; +#endif #if _CACHE_TOP_SCORE_ double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ double m_weight_dist_factor; #endif + unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -111,15 +116,52 @@ public: m_mpz_manager.del(m_two); } + unsigned get_formula_size() { + return m_scores.size(); + } + + double get_avg_bw(goal_ref const & g) { + double sum = 0.0; + unsigned count = 0; + + for (unsigned i = 0; i < g->size(); i++) + { + m_temp_constants.reset(); + ptr_vector const & this_decls = m_constants_occ.find(g->form(i)); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + m_temp_constants.push_back(fd); + sort * srt = fd->get_range(); + sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + count++; + } + } + + return sum / count; + } + #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ inline void set_weight_dist_factor(double val) { m_weight_dist_factor = val; } #endif + void reset_equal_scores() { + m_equal_scores = 1; + } + + unsigned inc_equal_scores() { + return ++m_equal_scores; + } + #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { + inline void adapt_top_sum(expr * e, double add, double sub) { +#if _PAWS_ + m_top_sum += m_weights.find(e) * (add - sub); +#else m_top_sum += add - sub; +#endif } inline void set_top_sum(double new_score) { @@ -276,6 +318,7 @@ public: } #endif +#if _UCT_ void uct_forget(goal_ref const & g) { expr * e; unsigned touched_old, touched_new; @@ -289,6 +332,7 @@ public: m_touched += touched_new - touched_old; } } +#endif void initialize(app * n) { // Build score table @@ -463,6 +507,15 @@ public: //} #endif +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * e = g->form(i); + if (!m_weights.contains(e)) + m_weights.insert(e, _PAWS_INIT_); + } +#endif + #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) setup_occs(g->form(i)); @@ -473,6 +526,30 @@ public: #endif } +#if _PAWS_ + void increase_weight(expr * e) + { + //printf("Increasing %d to", m_weights.find(e)); + m_weights.find(e)++; + //m_weights.find(e) *= 1.1; + //printf(" %d\n", m_weights.find(e)); + } + + void decrease_weight(expr * e) + { + unsigned old_weight = m_weights.find(e); + m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; + //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1; + //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e)); + } + + unsigned get_weight(expr * e) + //double get_weight(expr * e) + { + return m_weights.find(e); + } +#endif + #if _REAL_RS_ || _REAL_PBFS_ void make_assertion(expr * e) { @@ -763,6 +840,7 @@ public: const mpz & v1 = get_value(arg1); if (negated) { + //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -809,40 +887,209 @@ public: SASSERT(a->get_num_args() == 2); const mpz & x = get_value(a->get_arg(0)); const mpz & y = get_value(a->get_arg(1)); - unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); if (negated) { if (m_mpz_manager.gt(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy);*/ +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= rational(m_powers(bv_sz)); + double dbl = 1.0 - n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + m_mpz_manager.del(diff); +#endif + } + } + else { + if (m_mpz_manager.le(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); - } - } - else { - if (m_mpz_manager.le(x, y)) + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/ +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - else if (m_bv_util.is_bv_sle(n)) { // x <= y +/* else if (m_bv_util.is_bv_sle(n)) { // x <= y + app * a = to_app(n); + SASSERT(a->get_num_args() == 2); + const mpz & x = get_value(a->get_arg(0)); + const mpz & y = get_value(a->get_arg(1)); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + + mpz x_unsigned; + mpz y_unsigned; + const mpz & p = m_powers(bv_sz); + const mpz & p_half = m_powers(bv_sz-1); + if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } + if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); } + + if (negated) { + if (x_unsigned > y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy); + } + } + else { + if (x_unsigned <= y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2); + } + } + TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << + m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); + + m_mpz_manager.del(x_unsigned); + m_mpz_manager.del(y_unsigned); + }*/ + else if (m_bv_util.is_bv_sle(n)) { // x <= y app * a = to_app(n); SASSERT(a->get_num_args() == 2); mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0))); @@ -855,31 +1102,61 @@ public: if (negated) { if (x > y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= p; - double dbl = n.get_double(); - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + double dbl = 1.0 - n.get_double(); + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } else { if (x <= y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); + SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); @@ -1149,12 +1426,58 @@ public: return go_deeper(q); } + void go_deeper_only(expr * e) { + //if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q); + } + go_deeper(args[pos]); + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + go_deeper(q); + } + } + //} + else + { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + } + + ptr_vector & get_unsat_constants_only(expr * e) { + if (e && !m_temp_constants.size()) + go_deeper_only(e); + + return m_temp_constants; + } + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + { + m_temp_constants.reset(); return m_temp_constants; + } else return get_constants(); } @@ -1303,12 +1626,15 @@ public: } } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); - if (sz == 1) - return g->form(0); + if (sz == 1) { + if (m_mpz_manager.eq(get_value(g->form(0)), m_zero)) + return g->form(0); + else + return 0; + } m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1357,7 +1683,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #elif _UCT_ == 3 @@ -1440,6 +1766,23 @@ public: return get_unsat_constants_crsat(g, sz, pos); #endif } + + expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { + unsigned sz = g->size(); + + if (sz == 1) + return 0; + + m_temp_constants.reset(); + + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + + if (pos == static_cast(-1)) + return 0; + return g->form(pos); + } }; #endif \ No newline at end of file diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index ac53ca0c8..a7870176d 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -28,6 +28,8 @@ Notes: #include"bv_size_reduction_tactic.h" #include"aig_tactic.h" #include"sat_tactic.h" +//#include"nnf_tactic.h" +//#include"sls_tactic.h" #define MEMLIMIT 300 @@ -93,6 +95,32 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { mk_sat_tactic(m)); #endif + /* use full sls + tactic * st = using_params(and_then(preamble_st, + cond(mk_is_qfbv_probe(), + cond(mk_is_qfbv_eq_probe(), + and_then(mk_bv1_blaster_tactic(m), + using_params(mk_smt_tactic(), solver_p)), + and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))), + mk_smt_tactic())), + main_p);*/ + + /* use pure dpll + tactic * st = using_params(and_then(mk_simplify_tactic(m), + cond(mk_is_qfbv_probe(), + and_then(mk_bit_blaster_tactic(m), + when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), + and_then(using_params(and_then(mk_simplify_tactic(m), + mk_solve_eqs_tactic(m)), + local_ctx_p), + if_no_proofs(cond(mk_produce_unsat_cores_probe(), + mk_aig_tactic(), + using_params(mk_aig_tactic(), + big_aig_p))))), + new_sat), + mk_smt_tactic())), + main_p);*/ + tactic * st = using_params(and_then(preamble_st, // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function // symbols. In this case, we should not use From c1741d794155eea8041ef78075aff29b6bbce900 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 00:32:45 +0100 Subject: [PATCH 031/646] Almost cleaned up version. --- src/tactic/sls/sls_compilation_settings.h | 72 +------ src/tactic/sls/sls_engine.cpp | 231 +++++++--------------- src/tactic/sls/sls_engine.h | 13 +- src/tactic/sls/sls_evaluator.h | 175 ++-------------- src/tactic/sls/sls_tactic.cpp | 6 +- src/tactic/sls/sls_tracker.h | 170 ++++++++-------- 6 files changed, 177 insertions(+), 490 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 73ba1ffab..9add78daa 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,83 +22,13 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT) -#define _FOCUS_ 1 - -// shall we use additive weighting scheme? -#define _PAWS_ 5 -#define _PAWS_INIT_ 40 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 1 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 100 -//// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 2.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// shall we check 2-bit flips in plateaus using Monte Carlo? -#define _VNS_MC_ 0 - -// how many 2-bit flips shall we try per bit? -#define _VNS_MC_TRIES_ 1 - -// shall we check another assertion if no improving step was found in the first one? -#define _VNS_REPICK_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no, 1 = yes, by multiplying it with some factor -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.5 - -// shall we repick assertion when randomizing in a plateau or use the current one? -// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 20.0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 0 - -// do we gradually reduce the touched values of _UCT_? -#define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.9 - // shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 +#define _USE_ADDSUB_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - // shall we use early pruning for incremental update? #define _EARLY_PRUNE_ 1 -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - -#if ((_UCT_ > 0) + _REAL_RS_ > 1) -InvalidConfiguration; -#endif - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 938b6e0df..c240a0c51 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) : m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) { updt_params(p); + m_tracker.updt_params(p); } sls_engine::~sls_engine() { @@ -52,19 +53,21 @@ sls_engine::~sls_engine() { m_mpz_manager.del(m_two); } -double sls_engine::get_restart_armin(unsigned cnt_restarts) -{ - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); -} - void sls_engine::updt_params(params_ref const & _p) { sls_params p(_p); m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); + m_max_restarts = p.max_restarts(); m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); + m_walksat = p.walksat(); + m_walksat_repick = p.walksat_repick(); + m_paws_sp = p.paws_sp(); + m_wp = p.wp(); + m_vns_mc = p.vns_mc(); + m_vns_repick = p.vns_repick(); + + m_restart_base = p.restart_base(); + m_restart_next = m_restart_base; + m_restart_init = p.restart_init(); } void sls_engine::checkpoint() { @@ -105,9 +108,7 @@ double sls_engine::top_score() { tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); -#if _CACHE_TOP_SCORE_ m_tracker.set_top_sum(top_sum); -#endif return top_sum / (double)sz; } @@ -121,37 +122,21 @@ double sls_engine::rescore() { double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ return (m_tracker.get_top_sum() / m_assertions.size()); -#else - return top_score(); -#endif } double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ return (m_tracker.get_top_sum() / m_assertions.size()); -#else - return top_score(); -#endif } double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { -#if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ return (m_tracker.get_top_sum() / m_assertions.size()); -#else - return top_score(); -#endif else return 0.0; -#else - NOT_IMPLEMENTED_YET(); -#endif } // checks whether the score outcome of a given move is better than the previous score @@ -261,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + move_type mt = MV_FLIP; #endif unsigned bit = 0; @@ -300,7 +285,7 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); } - m_evaluator.update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_mpz_manager.del(new_value); } @@ -385,7 +370,7 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { for (unsigned j = 0; j < bv_sz; j++) { mk_flip(srt, old_value, j, temp); - for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++) { unsigned k = m_tracker.get_random_uint(16) % bv_sz; while (k == j) @@ -411,144 +396,85 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; + unsigned new_const = (unsigned)-1, new_bit; mpz new_value; move_type move; - unsigned plateau_cnt = 0; score = rescore(); unsigned sz = m_assertions.size(); -#if _RESTARTS_ - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - + while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; - -#if _UCT_FORGET_ - if (m_stats.m_moves % _UCT_FORGET_ == 0) - m_tracker.uct_forget(g); -#endif + if (m_stats.m_moves % m_restart_base == 0) + m_tracker.ucb_forget(m_assertions); #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - -#if _FOCUS_ - expr * e = m_tracker.get_unsat_assertion(m_assertions); - - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(m_assertions, sz); + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { res = l_true; goto bailout; } -#endif - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); -#if _CACHE_TOP_SCORE_ score = m_tracker.get_top_sum() / sz; -#else - score = top_score(g); -#endif continue; } old_score = score; new_const = (unsigned)-1; - move = MV_FLIP; - new_bit = 0; score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); -#if _VNS_MC_ > _VNS_REPICK_ -#if _VNS_MC_ - if (new_const == static_cast(-1)) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) + if (m_vns_mc && (new_const == static_cast(-1))) + score = find_best_move_mc(to_evaluate, score, new_const, new_value); + + /*if (m_vns_repick && (new_const == static_cast(-1))) { - expr * q = m_tracker.get_new_unsat_assertion(g, e); + expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); if (q) { ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); } - } -#endif -#endif - -#if _VNS_MC_ < _VNS_REPICK_ -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) - { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } - } -#endif -#if _VNS_MC_ - if (new_const == static_cast(-1)) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#endif + }*/ if (new_const == static_cast(-1)) { score = old_score; - plateau_cnt++; -#if _REPICK_ + if (m_walksat && m_walksat_repick) m_evaluator.randomize_local(m_assertions); -#else + else m_evaluator.randomize_local(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ score = m_tracker.get_top_sum() / m_assertions.size(); -#else - score = top_score(g); -#endif -#if _PAWS_ - for (unsigned i = 0; i < sz; i++) + if (m_paws_sp < 1024) { - expr * q = m_assertions[i]; - if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + for (unsigned i = 0; i < sz; i++) { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) - m_tracker.decrease_weight(q); - } - else - { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) - m_tracker.increase_weight(q); + expr * q = m_assertions[i]; + if (m_tracker.get_random_uint(10) < m_paws_sp) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } } } -#endif - } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _PAWS_ score = serious_score(fd, new_value); -#else - score = incremental_score(fd, new_value); -#endif } } @@ -569,30 +495,9 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; - verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; - verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; - verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; - verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; - verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; lbool res = operator()(); @@ -620,8 +525,6 @@ lbool sls_engine::operator()() { m_tracker.initialize(m_assertions); lbool res = l_undef; - m_restart_limit = _RESTART_LIMIT_; - do { checkpoint(); @@ -630,39 +533,53 @@ lbool sls_engine::operator()() { if (res == l_undef) { -#if _RESTART_INIT_ - m_tracker.randomize(); -#else - m_tracker.reset(m_assertions); -#endif + if (m_restart_init) + m_tracker.randomize(m_assertions); + else + m_tracker.reset(m_assertions); } - } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; return res; } -unsigned sls_engine::check_restart(unsigned curr_value) +/* Andreas: Needed for Armin's restart scheme if we don't want to use loops. +inline double sls_engine::get_restart_armin(unsigned cnt_restarts) { - if (curr_value > m_restart_limit) + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} +*/ + +inline unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_next) { + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 - m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); + m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); #elif _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); + m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; + m_restart_next += m_restart_base; else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; #else - m_restart_limit += _RESTART_LIMIT_; -#endif + m_restart_limit += m_restart_base; +#endif */ + if (m_stats.m_restarts & 1) + m_restart_next += m_restart_base; + else + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; return 0; } return 1; diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 4e5af8c93..ff0e55f24 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -70,9 +70,16 @@ protected: sls_evaluator m_evaluator; ptr_vector m_assertions; - unsigned m_restart_limit; unsigned m_max_restarts; - unsigned m_plateau_limit; + unsigned m_walksat; + unsigned m_walksat_repick; + unsigned m_wp; + unsigned m_vns_mc; + unsigned m_vns_repick; + unsigned m_paws_sp; + unsigned m_restart_base; + unsigned m_restart_next; + unsigned m_restart_init; ptr_vector m_old_values; @@ -110,7 +117,6 @@ public: protected: void checkpoint(); - double get_restart_armin(unsigned cnt_restarts); bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); @@ -129,6 +135,7 @@ protected: void mk_random_move(ptr_vector & unsat_constants); + //inline double get_restart_armin(unsigned cnt_restarts); inline unsigned check_restart(unsigned curr_value); }; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index da2a4b29f..37bfa5a2d 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -81,11 +81,7 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_zero); break; } @@ -93,11 +89,7 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_one); break; } @@ -105,16 +97,9 @@ public: } case OP_NOT: { SASSERT(n_args == 1); -#if _DIRTY_UP_ - if (m_tracker.is_top_expr(args[0])) - m_mpz_manager.set(result, m_zero); - else - m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); -#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); -#endif break; } case OP_EQ: { @@ -545,9 +530,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -569,23 +552,12 @@ public: } #endif + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { @@ -614,9 +586,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -627,23 +597,12 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -679,11 +638,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _PAWS_ run_serious_update(max_depth); -#else - run_update(max_depth); -#endif } void update(func_decl * fd, const mpz & new_value) { @@ -708,7 +663,6 @@ public: run_serious_update(cur_depth); } -#if _EARLY_PRUNE_ unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; @@ -722,10 +676,9 @@ public: expr * cur = cur_depth_exprs[i]; new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); @@ -746,9 +699,6 @@ public: } } } - else - { - } } cur_depth_exprs.reset(); @@ -762,14 +712,11 @@ public: for (unsigned i = 0; i < cur_size; i++) { expr * cur = cur_depth_exprs[i]; -#if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -850,103 +797,6 @@ public: } return run_update_bool_prune(cur_depth); } -#endif - - unsigned run_update_bool_prune_new(unsigned cur_depth) { - expr_fast_mark1 visited; - - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); - - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - prune_score = m_tracker.get_score_prune(cur); - m_tracker.set_score(cur, new_score); - - if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - else - { - } - } - - cur_depth_exprs.reset(); - cur_depth--; - - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } - - return pot_benefits; - } - - unsigned update_prune_new(func_decl * fd, const mpz & new_value) { - m_tracker.set_value(fd, new_value); - expr * ep = m_tracker.get_entry_point(fd); - unsigned cur_depth = m_tracker.get_distance(ep); - - if (m_traversal_stack_bool.size() <= cur_depth) - m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); - - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune_new(cur_depth); - } void randomize_local(ptr_vector & unsat_constants) { // Randomize _one_ candidate: @@ -954,11 +804,8 @@ public: func_decl * fd = unsat_constants[r]; mpz temp = m_tracker.get_random(fd->get_range()); -#if _REAL_RS_ || _PAWS_ serious_update(fd, temp); -#else - update(fd, temp); -#endif + m_mpz_manager.del(temp); TRACE("sls", tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 7a9252fe2..2a40e908d 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -159,16 +159,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? - //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! - //mk_simplify_tactic(m), mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); -// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); + //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 235ab9471..65011dc8d 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -39,11 +39,7 @@ class sls_tracker { mpz m_zero, m_one, m_two; struct value_score { -#if _EARLY_PRUNE_ value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; -#else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; -#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; @@ -80,20 +76,22 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; -#if _UCT_ + + unsigned m_walksat; + unsigned m_ucb; + double m_ucb_constant; + unsigned m_ucb_init; + double m_ucb_forget; unsigned m_touched; -#endif + double m_scale_unsat; + unsigned m_paws_init; #if _REAL_RS_ ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; #endif -#if _PAWS_ obj_map m_weights; -#endif -#if _CACHE_TOP_SCORE_ double m_top_sum; -#endif unsigned m_equal_scores; public: @@ -114,6 +112,17 @@ public: m_mpz_manager.del(m_two); } + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_walksat = p.walksat(); + m_ucb = p.walksat_ucb(); + m_ucb_constant = p.walksat_ucb_constant(); + m_ucb_init = p.walksat_ucb_init(); + m_ucb_forget = p.walksat_ucb_forget(); + m_scale_unsat = p.scale_unsat(); + m_paws_init = p.paws_init(); + } + unsigned get_formula_size() { return m_scores.size(); } @@ -147,13 +156,8 @@ public: return ++m_equal_scores; } -#if _CACHE_TOP_SCORE_ inline void adapt_top_sum(expr * e, double add, double sub) { -#if _PAWS_ m_top_sum += m_weights.find(e) * (add - sub); -#else - m_top_sum += add - sub; -#endif } inline void set_top_sum(double new_score) { @@ -163,7 +167,6 @@ public: inline double get_top_sum() { return m_top_sum; } -#endif inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); @@ -209,7 +212,6 @@ public: return get_score(ep); } -#if _EARLY_PRUNE_ inline void set_score_prune(expr * n, double score) { SASSERT(m_scores.contains(n)); m_scores.find(n).score_prune = score; @@ -229,7 +231,6 @@ public: SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; } -#endif inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); @@ -310,17 +311,20 @@ public: } #endif - void uct_forget(ptr_vector & as) { - expr * e; - unsigned touched_old, touched_new; - - for (unsigned i = 0; i < as.size(); i++) + inline void ucb_forget(ptr_vector & as) { + if (m_ucb_forget < 1.0) { - e = as[i]; - touched_old = m_scores.find(e).touched; - touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); - m_scores.find(e).touched = touched_new; - m_touched += touched_new - touched_old; + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < as.size(); i++) + { + e = as[i]; + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } } } @@ -490,26 +494,21 @@ public: //} #endif -#if _PAWS_ for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; if (!m_weights.contains(e)) - m_weights.insert(e, _PAWS_INIT_); + m_weights.insert(e, m_paws_init); } -#endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) setup_occs(as[i]); #endif -#if _UCT_ - m_touched = _UCT_INIT_ ? as.size() : 1; -#endif + m_touched = m_ucb_init ? as.size() : 1; } -#if _PAWS_ void increase_weight(expr * e) { m_weights.find(e)++; @@ -518,14 +517,13 @@ public: void decrease_weight(expr * e) { unsigned old_weight = m_weights.find(e); - m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; + m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init; } unsigned get_weight(expr * e) { return m_weights.find(e); } -#endif #if _REAL_RS_ void make_assertion(expr * e) @@ -684,7 +682,6 @@ public: } } -#if _EARLY_PRUNE_ void setup_occs(expr * n, bool negated = false) { if (m_manager.is_bool(n)) { @@ -717,7 +714,6 @@ public: else NOT_IMPLEMENTED_YET(); } -#endif double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -735,20 +731,17 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. -#if _SCORE_AND_AVG_ + /* Andreas: Seems to have no effect. But maybe you want to try it again at some point. double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) sum += get_score(args[i]); - res = sum / (double) a->get_num_args(); -#else + res = sum / (double) a->get_num_args(); */ double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; } res = min; -#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); @@ -927,13 +920,11 @@ public: SASSERT(res >= 0.0 && res <= 1.0); -#if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); if (afid == m_bv_util.get_family_id()) - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; -#endif + if (res < 1.0) res *= m_scale_unsat; TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; @@ -995,8 +986,8 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { - + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as) { + unsigned sz = as.size(); if (sz == 1) { if (m_mpz_manager.neq(get_value(as[0]), m_one)) return get_constants(); @@ -1033,89 +1024,88 @@ public: } ptr_vector & get_unsat_constants(ptr_vector const & as) { -#if _FOCUS_ - expr * e = get_unsat_assertion(as); - - if (!e) + if (m_walksat) { - m_temp_constants.reset(); - return m_temp_constants; - } + expr * e = get_unsat_assertion(as); - return get_unsat_constants_walksat(e); -#else - return m_tracker.get_unsat_constants_gsat(as, sz); -#endif + if (!e) + { + m_temp_constants.reset(); + return m_temp_constants; + } + + return get_unsat_constants_walksat(e); + } + else + return get_unsat_constants_gsat(as); } expr * get_unsat_assertion(ptr_vector const & as) { unsigned sz = as.size(); - if (sz == 1) { if (m_mpz_manager.neq(get_value(as[0]), m_one)) return as[0]; else return 0; } - m_temp_constants.reset(); -#if _UCT_ + unsigned pos = -1; - value_score vscore; - double max = -1.0; + if (m_ucb) + { + value_score vscore; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); -#elif _UCT_ == 3 + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); +#if _UCT_ == 3 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return 0; + if (pos == static_cast(-1)) + return 0; -#if _UCT_ - m_scores.find(as[pos]).touched++; - m_touched++; -#endif + m_scores.find(as[pos]).touched++; + m_touched++; // return m_list_false[pos]; + } + else + { + unsigned cnt_unsat = 0; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + } + return as[pos]; -#elif _REAL_RS_ +#if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; sz = m_where_false.size(); if (sz == 0) return 0; return m_list_false[get_random_uint(16) % sz]; -#else - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return 0; #endif - return as[pos]; } - expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { - unsigned sz = g->size(); - + expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + unsigned sz = as.size(); if (sz == 1) return 0; - m_temp_constants.reset(); - + unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; if (pos == static_cast(-1)) return 0; - return g->form(pos); + return as[pos]; } }; From 8346aed39c927923365efa3c2dbabc5bace18cb7 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 01:07:30 +0100 Subject: [PATCH 032/646] Fixed bug with VNS repick. --- src/tactic/sls/sls_compilation_settings.h | 2 +- src/tactic/sls/sls_engine.cpp | 22 +++++++++++++++++----- src/tactic/sls/sls_tracker.h | 7 ++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 9add78daa..a649bc9ed 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -23,7 +23,7 @@ Notes: #define _SLS_COMPILATION_SETTINGS_H_ // shall we use addition/subtraction? -#define _USE_ADDSUB_ 0 +#define _USE_ADDSUB_ 1 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index c240a0c51..af8ae1df2 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_base = p.restart_base(); m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. + if (m_walksat_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); + if (m_vns_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); } void sls_engine::checkpoint() { @@ -435,19 +441,25 @@ lbool sls_engine::search() { if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); - /*if (m_vns_repick && (new_const == static_cast(-1))) + if (m_vns_repick && (new_const == static_cast(-1))) { - expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); + expr * q = m_tracker.get_new_unsat_assertion(m_assertions); if (q) { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); + + if (new_const != static_cast(-1)) { + func_decl * fd = to_evaluate2[new_const]; + score = serious_score(fd, new_value); + continue; + } } - }*/ + } if (new_const == static_cast(-1)) { score = old_score; - if (m_walksat && m_walksat_repick) + if (m_walksat_repick) m_evaluator.randomize_local(m_assertions); else m_evaluator.randomize_local(to_evaluate); diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 65011dc8d..7b48057d4 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -76,7 +76,7 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; - + unsigned m_last_pos; unsigned m_walksat; unsigned m_ucb; double m_ucb_constant; @@ -1082,6 +1082,7 @@ public: return 0; } + m_last_pos = pos; return as[pos]; #if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; @@ -1093,7 +1094,7 @@ public: #endif } - expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + expr * get_new_unsat_assertion(ptr_vector const & as) { unsigned sz = as.size(); if (sz == 1) return 0; @@ -1101,7 +1102,7 @@ public: unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; + if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; if (pos == static_cast(-1)) return 0; From c441bb4388e6cd007c68e0974f4acf2c3a4e7d33 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 16:10:44 +0100 Subject: [PATCH 033/646] Backup before I touch early pruning ... --- src/tactic/sls/sls_compilation_settings.h | 3 --- src/tactic/sls/sls_engine.cpp | 30 +++++++++++++---------- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_evaluator.h | 4 +-- src/tactic/sls/sls_tracker.h | 9 ------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index a649bc9ed..5c837b4b2 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,9 +22,6 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index af8ae1df2..5d4df237e 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) { m_walksat = p.walksat(); m_walksat_repick = p.walksat_repick(); m_paws_sp = p.paws_sp(); + m_paws = m_paws_sp < 1024; m_wp = p.wp(); m_vns_mc = p.vns_mc(); m_vns_repick = p.vns_repick(); @@ -173,7 +174,6 @@ bool sls_engine::what_if( // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { - m_tracker.reset_equal_scores(); best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); else { -#if _USE_ADDSUB_ if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; move_type mt = (move_type)rnd_mv; // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; -#else - move_type mt = MV_FLIP; -#endif unsigned bit = 0; switch (mt) @@ -308,8 +304,9 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - m_tracker.reset_equal_scores(); - + //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); + //for (unsigned j = 0; j < to_evaluate.size(); j++) { + //unsigned i = (j + offset) % to_evaluate.size(); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -328,7 +325,6 @@ double sls_engine::find_best_move( } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); @@ -341,7 +337,6 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } -#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(fd, i, temp, new_score, best_const, best_value)) @@ -418,7 +413,7 @@ lbool sls_engine::search() { #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - + // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { @@ -426,6 +421,7 @@ lbool sls_engine::search() { goto bailout; } + // random walk with probability wp / 1024 if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); @@ -436,14 +432,18 @@ lbool sls_engine::search() { old_score = score; new_const = (unsigned)-1; + // find best increasing move score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); + // repick assertion if no increasing move was found previously if (m_vns_repick && (new_const == static_cast(-1))) { expr * q = m_tracker.get_new_unsat_assertion(m_assertions); + // only apply if another unsatisfied assertion actually exists if (q) { ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); @@ -457,6 +457,7 @@ lbool sls_engine::search() { } } + // randomize if no increasing move was found if (new_const == static_cast(-1)) { score = old_score; if (m_walksat_repick) @@ -466,16 +467,19 @@ lbool sls_engine::search() { score = m_tracker.get_top_sum() / m_assertions.size(); - if (m_paws_sp < 1024) + // update assertion weights if a weigthing is enabled (sp < 1024) + if (m_paws) { for (unsigned i = 0; i < sz; i++) { expr * q = m_assertions[i]; + // smooth weights with probability sp / 1024 if (m_tracker.get_random_uint(10) < m_paws_sp) { if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) m_tracker.decrease_weight(q); } + // increase weights otherwise else { if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) @@ -484,6 +488,7 @@ lbool sls_engine::search() { } } } + // otherwise, apply most increasing move else { func_decl * fd = to_evaluate[new_const]; score = serious_score(fd, new_value); @@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; @@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { - /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter. I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ff0e55f24..94f3fa626 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -76,6 +76,7 @@ protected: unsigned m_wp; unsigned m_vns_mc; unsigned m_vns_repick; + unsigned m_paws; unsigned m_paws_sp; unsigned m_restart_base; unsigned m_restart_next; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 37bfa5a2d..200a0e380 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -37,9 +37,7 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; -#if _EARLY_PRUNE_ vector > m_traversal_stack_bool; -#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -753,7 +751,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // Andreas: Should actually always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7b48057d4..a815c9ad3 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -92,7 +92,6 @@ private: #endif obj_map m_weights; double m_top_sum; - unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -148,14 +147,6 @@ public: return sum / count; } - void reset_equal_scores() { - m_equal_scores = 1; - } - - unsigned inc_equal_scores() { - return ++m_equal_scores; - } - inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); } From 9ebfb119dbd87babb52bed8eb55eee5c061cbcba Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 23 Apr 2014 14:52:18 +0100 Subject: [PATCH 034/646] Moved parameters to the right file. Almost clean. --- src/tactic/sls/sls_compilation_settings.h | 5 +-- src/tactic/sls/sls_engine.cpp | 38 +++++++++++------------ src/tactic/sls/sls_engine.h | 3 +- src/tactic/sls/sls_evaluator.h | 5 --- src/tactic/sls/sls_params.pyg | 20 ++++++++++-- src/tactic/sls/sls_tracker.h | 33 +++++++++----------- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 5c837b4b2..707802cf4 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,10 +22,7 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +// should we use unsat-structures as done in SLS 4 SAT? #define _REAL_RS_ 0 -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5d4df237e..a1c72609c 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + m_early_prune = p.early_prune(); + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) NOT_IMPLEMENTED_YET(); @@ -117,7 +119,7 @@ double sls_engine::top_score() { m_tracker.set_top_sum(top_sum); - return top_sum / (double)sz; + return top_sum; } double sls_engine::rescore() { @@ -129,21 +131,21 @@ double sls_engine::rescore() { double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); else - return 0.0; + return -DBL_MAX; } // checks whether the score outcome of a given move is better than the previous score @@ -160,11 +162,11 @@ bool sls_engine::what_if( m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif -#if _EARLY_PRUNE_ - double r = incremental_score_prune(fd, temp); -#else - double r = incremental_score(fd, temp); -#endif + double r; + if (m_early_prune) + r = incremental_score_prune(fd, temp); + else + r = incremental_score(fd, temp); #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl;); @@ -342,11 +344,8 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; } - // reset to what it was before - double check = incremental_score(fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double } } } - // reset to what it was before - double check = incremental_score(fd, old_value); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -408,7 +406,10 @@ lbool sls_engine::search() { checkpoint(); m_stats.m_moves++; if (m_stats.m_moves % m_restart_base == 0) + { m_tracker.ucb_forget(m_assertions); + //score = rescore(); + } #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); @@ -425,7 +426,7 @@ lbool sls_engine::search() { if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); - score = m_tracker.get_top_sum() / sz; + score = m_tracker.get_top_sum(); continue; } @@ -465,7 +466,7 @@ lbool sls_engine::search() { else m_evaluator.randomize_local(to_evaluate); - score = m_tracker.get_top_sum() / m_assertions.size(); + score = m_tracker.get_top_sum(); // update assertion weights if a weigthing is enabled (sp < 1024) if (m_paws) @@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { assert_expr(g->form(i)); verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; lbool res = operator()(); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 94f3fa626..ac8610871 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -81,8 +81,7 @@ protected: unsigned m_restart_base; unsigned m_restart_next; unsigned m_restart_init; - - ptr_vector m_old_values; + unsigned m_early_prune; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 200a0e380..e4cf3c466 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -554,9 +554,7 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -599,9 +597,6 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ - m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index cc3e05966..98875b20d 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -2,7 +2,21 @@ def_module_params('sls', export=True, description='Experimental Stochastic Local Search Solver (for QFBV only).', params=(max_memory_param(), - ('restarts', UINT, UINT_MAX, '(max) number of restarts'), - ('plateau_limit', UINT, 10, 'pleateau limit'), - ('random_seed', UINT, 0, 'random seed') + ('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'), + ('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'), + ('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'), + ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), + ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), + ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), + ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), + ('paws_init', UINT, 40, 'initial/minimum assertion weights'), + ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), + ('wp', UINT, 0, 'random walk with probability wp / 1024'), + ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), + ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), + ('restart_base', UINT, 100, 'base restart interval given by moves per run'), + ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), + ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index a815c9ad3..507596273 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -44,11 +44,9 @@ class sls_tracker { unsynch_mpz_manager * m; mpz value; double score; -#if _EARLY_PRUNE_ double score_prune; unsigned has_pos_occ; unsigned has_neg_occ; -#endif unsigned distance; // max distance from any root unsigned touched; value_score & operator=(const value_score & other) { @@ -122,6 +120,7 @@ public: m_paws_init = p.paws_init(); } + /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. unsigned get_formula_size() { return m_scores.size(); } @@ -145,7 +144,7 @@ public: } return sum / count; - } + }*/ inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); @@ -417,6 +416,8 @@ public: } } + /* Andreas: Used this at some point to have values for the non-top-level expressions. + However, it did not give better performance but even cause some additional m/o - is not used currently. void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { if (m_manager.is_and(e) || m_manager.is_or(e)) { app * a = to_app(e); @@ -445,7 +446,7 @@ public: find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + }*/ void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); @@ -455,8 +456,6 @@ public: expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); - else - printf("this is already in ...\n"); for_each_expr(proc, visited, e); } @@ -464,7 +463,6 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - // Andreas: Maybe not fully correct. ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -488,15 +486,16 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - if (!m_weights.contains(e)) + + // initialize weights + if (!m_weights.contains(e)) m_weights.insert(e, m_paws_init); + + // positive/negative occurences used for early pruning + setup_occs(as[i]); } -#if _EARLY_PRUNE_ - for (unsigned i = 0; i < sz; i++) - setup_occs(as[i]); -#endif - + // initialize ucb total touched value (individual ones are always initialized to 1) m_touched = m_ucb_init ? as.size() : 1; } @@ -738,7 +737,6 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); @@ -764,7 +762,6 @@ public: const mpz & v1 = get_value(arg1); if (negated) { - //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -1051,10 +1048,8 @@ public: // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); -#if _UCT_ == 3 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); -#endif + //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } if (pos == static_cast(-1)) From 0279a1042d6f7088e4628e592dc5ac9ef253bc92 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 18:39:36 +0100 Subject: [PATCH 035/646] FPA API documentation fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 7 +++---- src/api/dotnet/FPExpr.cs | 3 ++- src/api/dotnet/FPRMExpr.cs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 7ef91f7ac..b654feb7e 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3506,8 +3506,7 @@ namespace Microsoft.Z3 /// /// Create a floating point NaN numeral. - /// - /// A string representing the value in decimal notation. + /// /// floating point sort. public FPNum MkFPNaN(FPSort s) { @@ -3517,8 +3516,7 @@ namespace Microsoft.Z3 /// /// Create a floating point Inf numeral. - /// - /// A string representing the value in decimal notation. + /// /// floating point sort. /// indicates whether the result should be negative. public FPNum MkFPInf(FPSort s, bool negative) @@ -3625,6 +3623,7 @@ namespace Microsoft.Z3 /// /// Floating-point square root /// + /// rounding mode term /// floating point term public FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) { diff --git a/src/api/dotnet/FPExpr.cs b/src/api/dotnet/FPExpr.cs index 66b3fc10d..0bb1e4c09 100644 --- a/src/api/dotnet/FPExpr.cs +++ b/src/api/dotnet/FPExpr.cs @@ -30,7 +30,8 @@ namespace Microsoft.Z3 /// public class FPExpr : Expr { - #region Internal + #region Internal + /// Constructor for FPExpr internal protected FPExpr(Context ctx) : base(ctx) { diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs index fa43a346a..b95816023 100644 --- a/src/api/dotnet/FPRMExpr.cs +++ b/src/api/dotnet/FPRMExpr.cs @@ -31,6 +31,7 @@ namespace Microsoft.Z3 public class FPRMExpr : Expr { #region Internal + /// Constructor for FPRMExpr internal protected FPRMExpr(Context ctx) : base(ctx) { From a8b65ebb360168c9659e943e3f264690c5d8e3f8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 20:10:53 +0100 Subject: [PATCH 036/646] added stubs for theory_fpa Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 36 +++++++++++++++++++++++++++++++++++ src/ast/fpa/fpa2bv_rewriter.h | 6 ++---- src/smt/smt_setup.cpp | 15 +++++++++++++++ src/smt/smt_setup.h | 6 +++++- src/smt/theory_fpa.cpp | 19 ++++++++++++++++-- src/smt/theory_fpa.h | 8 +++++--- 6 files changed, 80 insertions(+), 10 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 27bf6de2c..4363ee382 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2595,6 +2595,42 @@ void substitute_vars_example() { Z3_del_context(ctx); } +void fpa_example() { + Z3_config cfg; + Z3_context ctx; + Z3_sort double_sort, rm_sort; + Z3_symbol symbol_rm, symbol_x, symbol_y; + Z3_ast rm, x, y, n, c; + + printf("\nFPA-example\n"); + LOG_MSG("FPA-example"); + + enable_trace("fpa"); + + cfg = Z3_mk_config(); + ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + + double_sort = Z3_mk_fpa_sort(ctx, 11, 53); + rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx); + + symbol_rm = Z3_mk_string_symbol(ctx, "rm"); + rm = Z3_mk_const(ctx, symbol_rm, rm_sort); + symbol_x = Z3_mk_string_symbol(ctx, "x"); + symbol_y = Z3_mk_string_symbol(ctx, "y"); + x = Z3_mk_const(ctx, symbol_x, double_sort); + y = Z3_mk_const(ctx, symbol_y, double_sort); + n = Z3_mk_double(ctx, 42.0, double_sort); + + c = Z3_mk_eq(ctx, Z3_mk_fpa_add(ctx, rm, x, y), n); + + Z3_assert_cnstr(ctx, c); + if (Z3_check(ctx) != Z3_L_TRUE) + printf("FPA-example not satisfied!\n"); + + Z3_del_context(ctx); +} + /*@}*/ /*@}*/ diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index b2e3da939..bdfa6ca3f 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -64,9 +64,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { } bool max_steps_exceeded(unsigned num_steps) const { - cooperate("fpa2bv"); - if (memory::get_allocation_size() > m_max_memory) - throw tactic_exception(TACTIC_MAX_MEMORY_MSG); + cooperate("fpa2bv"); return num_steps > m_max_steps; } @@ -147,7 +145,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); - throw tactic_exception("NYI"); + NOT_IMPLEMENTED_YET(); } } diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 51b83d61c..64477164a 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -30,6 +30,7 @@ Revision History: #include"theory_dummy.h" #include"theory_dl.h" #include"theory_seq_empty.h" +#include"theory_fpa.h" namespace smt { @@ -679,6 +680,15 @@ namespace smt { setup_mi_arith(); } + void setup::setup_QF_FPA() { + m_context.register_plugin(alloc(smt::theory_fpa, m_manager)); + } + + void setup::setup_QF_FPABV() { + setup_QF_BV(); + m_context.register_plugin(alloc(smt::theory_fpa, m_manager)); + } + bool is_arith(static_features const & st) { return st.m_num_arith_ineqs > 0 || st.m_num_arith_terms > 0 || st.m_num_arith_eqs > 0; } @@ -780,6 +790,10 @@ namespace smt { m_context.register_plugin(alloc(theory_seq_empty, m_manager)); } + void setup::setup_fpa() { + m_context.register_plugin(alloc(theory_fpa, m_manager)); + } + void setup::setup_unknown() { setup_arith(); setup_arrays(); @@ -787,6 +801,7 @@ namespace smt { setup_datatypes(); setup_dl(); setup_seq(); + setup_fpa(); } void setup::setup_unknown(static_features & st) { diff --git a/src/smt/smt_setup.h b/src/smt/smt_setup.h index e0188537e..299ce7834 100644 --- a/src/smt/smt_setup.h +++ b/src/smt/smt_setup.h @@ -75,6 +75,8 @@ namespace smt { void setup_QF_AX(static_features const & st); void setup_QF_AUFLIA(); void setup_QF_AUFLIA(static_features const & st); + void setup_QF_FPA(); + void setup_QF_FPABV(); void setup_LRA(); void setup_AUFLIA(bool simple_array = true); void setup_AUFLIA(static_features const & st); @@ -91,10 +93,12 @@ namespace smt { void setup_bv(); void setup_arith(); void setup_dl(); - void setup_seq(); + void setup_seq(); void setup_instgen(); void setup_i_arith(); void setup_mi_arith(); + void setup_fpa(); + public: setup(context & c, smt_params & params); void mark_already_configured() { m_already_configured = true; } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 147d87496..e235dbb06 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -17,14 +17,29 @@ Revision History: --*/ #include"ast_smt2_pp.h" +#include"smt_context.h" #include"theory_fpa.h" namespace smt { + theory_fpa::theory_fpa(ast_manager & m) : + theory(m.mk_family_id("float")), + m_converter(m), + m_rw(m, m_converter, params_ref()) + { + } + bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { - TRACE("bv", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); + TRACE("fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); - NOT_IMPLEMENTED_YET(); + + ast_manager & m = get_manager(); + context & ctx = get_context(); + + expr_ref res(m); + m_rw(atom, res); + SASSERT(res.get() != atom); + ctx.internalize(res, gate_ctx); return true; } diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 3716247d3..bb3a8b786 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -21,14 +21,16 @@ Revision History: #include"smt_theory.h" #include"fpa2bv_converter.h" +#include"fpa2bv_rewriter.h" namespace smt { class theory_fpa : public theory { fpa2bv_converter m_converter; + fpa2bv_rewriter m_rw; virtual final_check_status final_check_eh() { return FC_DONE; } - virtual bool internalize_atom(app*, bool); - virtual bool internalize_term(app*) { return internalize_atom(0, false); } + virtual bool internalize_atom(app * a, bool); + virtual bool internalize_term(app * a) { return internalize_atom(a, false); } virtual void new_eq_eh(theory_var, theory_var); virtual void new_diseq_eh(theory_var, theory_var); virtual void push_scope_eh(); @@ -36,7 +38,7 @@ namespace smt { virtual theory* mk_fresh(context*) { return alloc(theory_fpa, get_manager()); } virtual char const * get_name() const { return "fpa"; } public: - theory_fpa(ast_manager& m) : theory(m.mk_family_id("fpa")), m_converter(m) {} + theory_fpa(ast_manager& m); }; }; From 3df2967be92549427ad1410c41f37c80df8e3726 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Fri, 25 Apr 2014 13:56:15 +0100 Subject: [PATCH 037/646] Cleaned up final SLS version. Enjoy! --- src/tactic/sls/sls_compilation_settings.h | 28 ---- src/tactic/sls/sls_engine.cpp | 43 ++++-- src/tactic/sls/sls_engine.h | 2 + src/tactic/sls/sls_evaluator.h | 8 +- src/tactic/sls/sls_params.pyg | 6 +- src/tactic/sls/sls_tracker.h | 153 ++++++++-------------- 6 files changed, 94 insertions(+), 146 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 707802cf4..e69de29bb 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -1,28 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sls_compilation_constants.h - -Abstract: - - Stochastic Local Search (SLS) compilation constants - -Author: - - Christoph (cwinter) 2014-03-19 - -Notes: - - This file should go away completely once we have evaluated all options. - ---*/ - -#ifndef _SLS_COMPILATION_SETTINGS_H_ -#define _SLS_COMPILATION_SETTINGS_H_ - -// should we use unsat-structures as done in SLS 4 SAT? -#define _REAL_RS_ 0 - -#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index a1c72609c..269790902 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_init = p.restart_init(); m_early_prune = p.early_prune(); + m_random_offset = p.random_offset(); + m_rescore = p.rescore(); // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) @@ -174,6 +176,9 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif + // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection. + // r += 0.0001 * m_tracker.get_random_uint(8); + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { best_score = r; @@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) { if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + + // Andreas: The other option would be to scale the probability for flips according to the bit-width. + /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt); + rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3); + if (rnd_mv > 3) rnd_mv = 0; */ + move_type mt = (move_type)rnd_mv; - // inversion doesn't make sense, let's do a flip instead. + // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true? if (mt == MV_INV) mt = MV_FLIP; unsigned bit = 0; @@ -306,10 +317,13 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); - //for (unsigned j = 0; j < to_evaluate.size(); j++) { - //unsigned i = (j + offset) % to_evaluate.size(); - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double unsigned bv_sz; double new_score = score; - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -405,15 +425,16 @@ lbool sls_engine::search() { while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; + + // Andreas: Every base restart interval ... if (m_stats.m_moves % m_restart_base == 0) { + // ... potentially smooth the touched counters ... m_tracker.ucb_forget(m_assertions); - //score = rescore(); + // ... or normalize the top-level score. + if (m_rescore) score = rescore(); } -#if _REAL_RS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) @@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - lbool res = operator()(); if (res == l_true) { diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ac8610871..8158808fa 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -82,6 +82,8 @@ protected: unsigned m_restart_next; unsigned m_restart_init; unsigned m_early_prune; + unsigned m_random_offset; + unsigned m_rescore; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index e4cf3c466..61afb7457 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -22,7 +22,6 @@ Notes: #include"model_evaluator.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" @@ -540,19 +539,16 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); -#if _REAL_RS_ + new_score = m_tracker.score(cur); if (m_tracker.is_top_expr(cur)) { + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); if (m_mpz_manager.eq(new_value,m_one)) m_tracker.make_assertion(cur); else m_tracker.break_assertion(cur); } -#endif - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index 98875b20d..ad7a22675 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -8,15 +8,19 @@ def_module_params('sls', ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'), ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), ('paws_init', UINT, 40, 'initial/minimum assertion weights'), ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), - ('wp', UINT, 0, 'random walk with probability wp / 1024'), + ('wp', UINT, 100, 'random walk with probability wp / 1024'), ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), + ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 507596273..4356bcc9b 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -80,14 +80,13 @@ private: double m_ucb_constant; unsigned m_ucb_init; double m_ucb_forget; + double m_ucb_noise; unsigned m_touched; double m_scale_unsat; unsigned m_paws_init; -#if _REAL_RS_ - ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; -#endif + unsigned m_track_unsat; obj_map m_weights; double m_top_sum; @@ -116,8 +115,12 @@ public: m_ucb_constant = p.walksat_ucb_constant(); m_ucb_init = p.walksat_ucb_init(); m_ucb_forget = p.walksat_ucb_forget(); + m_ucb_noise = p.walksat_ucb_noise(); m_scale_unsat = p.scale_unsat(); m_paws_init = p.paws_init(); + // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy. + // If you want to use it, you will also need to change comments in the assertion selection. + m_track_unsat = 0;//p.track_unsat(); } /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. @@ -254,53 +257,6 @@ public: return m_uplinks.find(n); } -#if _REAL_RS_ - void debug_real(goal_ref const & g, unsigned flip) - { - unsigned count = 0; - for (unsigned i = 0; i < g->size(); i++) - { - expr * e = g->form(i); - if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is unsat but not in unsat list\n", i); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - expr * q = m_list_false[pos]; - if (q != e) - { - printf("iteration %d: ", flip); - printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); - exit(4); - } - } - - if (m_mpz_manager.eq(get_value(e),m_zero)) - count++; - } - - // should be true now that duplicate assertions are removed - if (count != m_where_false.size()) - { - printf("iteration %d: ", flip); - printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); - exit(4); - } - } -#endif - inline void ucb_forget(ptr_vector & as) { if (m_ucb_forget < 1.0) { @@ -474,14 +430,15 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); -#if _REAL_RS_ - m_list_false = new expr*[sz]; - //for (unsigned i = 0; i < sz; i++) - //{ - // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - // break_assertion(g->form(i)); - //} -#endif + if (m_track_unsat) + { + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + { + if (m_mpz_manager.eq(get_value(as[i]), m_zero)) + break_assertion(as[i]); + } + } for (unsigned i = 0; i < sz; i++) { @@ -515,44 +472,36 @@ public: return m_weights.find(e); } -#if _REAL_RS_ void make_assertion(expr * e) { - if (m_where_false.contains(e)) + if (m_track_unsat) { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) + if (m_where_false.contains(e)) { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } } - //else - //printf("Erasing %d from %d to %d\n", e, pos); -// m_list_false[m_where_false.size()] = 0; -// printf("Going in %d\n", m_where_false.size()); } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); } void break_assertion(expr * e) { - //printf("I'm broken... that's still fine.\n"); - if (!m_where_false.contains(e)) + if (m_track_unsat) { - //printf("This however is not so cool...\n"); - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + } } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); } -#endif void show_model(std::ostream & out) { unsigned sz = get_num_constants(); @@ -1043,24 +992,38 @@ public: { value_score vscore; double max = -1.0; + // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit. + /* for (unsigned i = 0; i < m_where_false.size(); i++) { + expr * e = m_list_false[i]; */ for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; -// for (unsigned i = 0; i < m_where_false.size(); i++) { -// expr * e = m_list_false[i]; - vscore = m_scores.find(e); - //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (m_mpz_manager.neq(get_value(e), m_one)) + { + vscore = m_scores.find(e); + // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise. + // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); + if (q > max) { max = q; pos = i; } + } } if (pos == static_cast(-1)) return 0; - m_scores.find(as[pos]).touched++; m_touched++; -// return m_list_false[pos]; + m_scores.find(as[pos]).touched++; + // Andreas: Also part of track_unsat data structures. Additionally disable the previous line! + /* m_last_pos = pos; + m_scores.find(m_list_false[pos]).touched++; + return m_list_false[pos]; */ } else { + // Andreas: The track_unsat data structures for random assertion selection. + /* sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; */ + unsigned cnt_unsat = 0; for (unsigned i = 0; i < sz; i++) if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; @@ -1070,14 +1033,6 @@ public: m_last_pos = pos; return as[pos]; -#if _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return 0; - return m_list_false[get_random_uint(16) % sz]; -#endif } expr * get_new_unsat_assertion(ptr_vector const & as) { From a3f20774a8538eeec48191ae474ae2416750527c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 17:17:47 +0100 Subject: [PATCH 038/646] BVSLS comments Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_params.pyg | 2 +- src/tactic/sls/sls_tracker.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index ad7a22675..bf5bd181a 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -19,7 +19,7 @@ def_module_params('sls', ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), - ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('random_offset', BOOL, 1, 'use random offset for candidate evaluation'), ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 4356bcc9b..d58f94af2 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -831,7 +831,9 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. + // Precondition: Assertion set is in NNF. + // Also: careful about the unsat assertion scaling further down. + if (m_manager.is_and(child) || m_manager.is_or(child)) NOT_IMPLEMENTED_YET(); res = score_bool(child, true); } From bfdea4242c9a26b43432040126a98fcf85a46075 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:03:35 +0100 Subject: [PATCH 039/646] removed unused file Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 0 src/tactic/sls/sls_engine.cpp | 1 - src/tactic/sls/sls_engine.h | 1 - src/tactic/sls/sls_tracker.h | 1 - 4 files changed, 3 deletions(-) delete mode 100644 src/tactic/sls/sls_compilation_settings.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 269790902..67dba0237 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -27,7 +27,6 @@ Notes: #include"cooperate.h" #include"luby.h" -#include"sls_compilation_settings.h" #include"sls_params.hpp" #include"sls_engine.h" diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8158808fa..8a8a57e0e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -24,7 +24,6 @@ Notes: #include"model_converter.h" #include"goal.h" -#include"sls_compilation_settings.h" #include"sls_tracker.h" #include"sls_evaluator.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index d58f94af2..186fae250 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,7 +25,6 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" class sls_tracker { From 4ff6a7c38dd86497eee7543a3fea54b75e03bcf2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:11:30 +0100 Subject: [PATCH 040/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 186fae250..73355197a 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,6 +25,7 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" +#include"sls_params.hpp" #include"sls_powers.h" class sls_tracker { @@ -1052,4 +1053,4 @@ public: } }; -#endif \ No newline at end of file +#endif From c9c40877a70f08cef1d48af3ecd805ff173be931 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:49:35 +0100 Subject: [PATCH 041/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8a8a57e0e..b056c438e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -136,8 +136,8 @@ protected: void mk_random_move(ptr_vector & unsat_constants); - //inline double get_restart_armin(unsigned cnt_restarts); - inline unsigned check_restart(unsigned curr_value); + //double get_restart_armin(unsigned cnt_restarts); + unsigned check_restart(unsigned curr_value); }; #endif From 23dccdc7d519a86d779ae8b582663885e4548520 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:54:08 +0100 Subject: [PATCH 042/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 67dba0237..5b32e5790 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,6 +16,7 @@ Author: Notes: --*/ +#include #include #include"map.h" From 39b562da44d4cc63374c1904d378b9b41a406ee7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 22:03:26 +0100 Subject: [PATCH 043/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5b32e5790..c0c319ab4 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -581,7 +581,7 @@ lbool sls_engine::operator()() { } /* Andreas: Needed for Armin's restart scheme if we don't want to use loops. -inline double sls_engine::get_restart_armin(unsigned cnt_restarts) +double sls_engine::get_restart_armin(unsigned cnt_restarts) { unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; @@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts) } */ -inline unsigned sls_engine::check_restart(unsigned curr_value) +unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { From baee61a2e48e7c601aad89797e15133f8768af0e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 2 Jun 2014 17:57:59 +0100 Subject: [PATCH 044/646] More experimental FPA theory code Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 254 +++++++++++++++++++++++++++++++++++++++-- src/smt/theory_fpa.h | 23 +++- 2 files changed, 263 insertions(+), 14 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index e235dbb06..bd95d78f1 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -19,43 +19,275 @@ Revision History: #include"ast_smt2_pp.h" #include"smt_context.h" #include"theory_fpa.h" +#include"smt_model_generator.h" namespace smt { theory_fpa::theory_fpa(ast_manager & m) : theory(m.mk_family_id("float")), m_converter(m), - m_rw(m, m_converter, params_ref()) + m_rw(m, m_converter, params_ref()), + m_trans_map(m), + m_trail_stack(*this) { } bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { TRACE("fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); + NOT_IMPLEMENTED_YET(); + } + + bool theory_fpa::internalize_term(app * term) { + TRACE("fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); + SASSERT(term->get_family_id() == get_family_id()); + SASSERT(!get_context().e_internalized(term)); ast_manager & m = get_manager(); context & ctx = get_context(); + simplifier & simp = ctx.get_simplifier(); + unsigned num_args = term->get_num_args(); + for (unsigned i = 0; i < num_args; i++) + ctx.internalize(term->get_arg(i), false); + expr_ref res(m); - m_rw(atom, res); - SASSERT(res.get() != atom); - ctx.internalize(res, gate_ctx); - return true; + m_rw(term, res); + SASSERT(is_app(res) && to_app(res)->get_num_args() == 3); + app * a = to_app(res); + TRACE("fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); + + expr_ref sgn(m), sig(m), exp(m); + proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); + simp(a->get_arg(0), sgn, pr_sgn); + simp(a->get_arg(1), sig, pr_sig); + simp(a->get_arg(2), exp, pr_exp); + + ctx.internalize(sgn, false); + ctx.internalize(sig, false); + ctx.internalize(exp, false); + + expr_ref s_term(m); + m_converter.mk_triple(sgn, sig, exp, s_term); + + SASSERT(!m_trans_map.contains(term)); + m_trans_map.insert(term, s_term, 0); + + enode * e = ctx.mk_enode(term, false, false, true); + theory_var v = mk_var(e); + ctx.attach_th_var(e, this, v); + TRACE("fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); + SASSERT(e->get_th_var(get_id()) != null_theory_var); + + return v != null_theory_var; } - void theory_fpa::new_eq_eh(theory_var, theory_var) { - NOT_IMPLEMENTED_YET(); + void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { + if (!is_attached_to_var(n)) { + context & ctx = get_context(); + ast_manager & m = get_manager(); + simplifier & simp = ctx.get_simplifier(); + app * owner = n->get_owner(); + expr_ref converted(m); + + theory_var v = mk_var(n); + ctx.attach_th_var(n, this, v); + m_rw(owner, converted); + m_trans_map.insert(owner, converted, 0); + + if (m_converter.is_rm_sort(m.get_sort(owner))) { + ctx.internalize(converted, false); + } + else { + app * a = to_app(converted); + expr_ref sgn(m), sig(m), exp(m); + proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); + simp(a->get_arg(0), sgn, pr_sgn); + simp(a->get_arg(1), sig, pr_sig); + simp(a->get_arg(2), exp, pr_exp); + + ctx.internalize(sgn, false); + ctx.internalize(sig, false); + ctx.internalize(exp, false); + } + + TRACE("fpa", tout << "new const: " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); + } } - void theory_fpa::new_diseq_eh(theory_var, theory_var) { - NOT_IMPLEMENTED_YET(); + void theory_fpa::new_eq_eh(theory_var x, theory_var y) { + TRACE("fpa", tout << "new eq: " << x << " = " << y << "\n";); + ast_manager & m = get_manager(); + context & ctx = get_context(); + app * ax = get_enode(x)->get_owner(); + app * ay = get_enode(y)->get_owner(); + + expr * ex, * ey; + proof * px, * py; + m_trans_map.get(ax, ex, px); + m_trans_map.get(ay, ey, py); + + expr * sgn_x, * sig_x, * exp_x; + expr * sgn_y, * sig_y, * exp_y; + split_triple(ex, sgn_x, sig_x, exp_x); + split_triple(ey, sgn_y, sig_y, exp_y); + + literal_vector lits; + lits.push_back(mk_eq(ax, ay, true)); + + expr_ref e1(m), e2(m), e3(m); + e1 = m.mk_eq(sgn_x, sgn_y); + e2 = m.mk_eq(sig_x, sig_y); + e3 = m.mk_eq(exp_x, exp_y); + ctx.internalize(e1, true); + ctx.internalize(e2, true); + ctx.internalize(e3, true); + lits.push_back(ctx.get_literal(e1)); + lits.push_back(ctx.get_literal(e2)); + lits.push_back(ctx.get_literal(e3)); + + ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); + } + + void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { + TRACE("fpa", tout << "new eq: " << x << " = " << y << "\n";); + ast_manager & m = get_manager(); + context & ctx = get_context(); + app * ax = get_enode(x)->get_owner(); + app * ay = get_enode(y)->get_owner(); + + expr * ex, *ey; + proof * px, *py; + m_trans_map.get(ax, ex, px); + m_trans_map.get(ay, ey, py); + + expr * sgn_x, *sig_x, *exp_x; + expr * sgn_y, *sig_y, *exp_y; + split_triple(ex, sgn_x, sig_x, exp_x); + split_triple(ex, sgn_y, sig_y, exp_y); + + ctx.internalize(m.mk_not(m.mk_eq(sgn_x, sgn_y)), true); + ctx.internalize(m.mk_not(m.mk_eq(sig_x, sig_y)), true); + ctx.internalize(m.mk_not(m.mk_eq(exp_x, exp_y)), true); } void theory_fpa::push_scope_eh() { - NOT_IMPLEMENTED_YET(); + theory::push_scope_eh(); + m_trail_stack.push_scope(); } void theory_fpa::pop_scope_eh(unsigned num_scopes) { - NOT_IMPLEMENTED_YET(); + m_trail_stack.pop_scope(num_scopes); + theory::pop_scope_eh(num_scopes); + } + + model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { + ast_manager & m = get_manager(); + context & ctx = get_context(); + bv_util & bu = m_converter.bu(); + float_util & fu = m_converter.fu(); + unsynch_mpz_manager & mpzm = fu.fm().mpz_manager(); + unsynch_mpq_manager & mpqm = fu.fm().mpq_manager(); + + theory_var v = n->get_th_var(get_id()); + SASSERT(v != null_theory_var); + expr * fpa_e = get_enode(v)->get_owner(); + TRACE("fpa", tout << "mk_value for: " << mk_ismt2_pp(fpa_e, m) << "\n";); + + expr * bv_e; + proof * bv_pr; + m_trans_map.get(fpa_e, bv_e, bv_pr); + + expr_wrapper_proc * res = 0; + + if (fu.is_rm(m.get_sort(fpa_e))) { + SASSERT(ctx.e_internalized(bv_e)); + sort * s = m.get_sort(bv_e); + family_id fid = s->get_family_id(); + theory * bv_th = ctx.get_theory(fid); + + enode * ev = ctx.get_enode(bv_e); + ptr_vector pve; + app_ref mv(m); + mv = ((expr_wrapper_proc*)bv_th->mk_value(ev, mg))->mk_value(mg, pve); + + rational val(0); + unsigned sz = 0; + if (bu.is_numeral(mv, val, sz)) { + app_ref fp_val_e(m); + SASSERT(val.is_uint64()); + switch (val.get_uint64()) + { + case BV_RM_TIES_TO_AWAY: fp_val_e = fu.mk_round_nearest_ties_to_away(); break; + case BV_RM_TIES_TO_EVEN: fp_val_e = fu.mk_round_nearest_ties_to_even(); break; + case BV_RM_TO_NEGATIVE: fp_val_e = fu.mk_round_toward_negative(); break; + case BV_RM_TO_POSITIVE: fp_val_e = fu.mk_round_toward_positive(); break; + case BV_RM_TO_ZERO: + default: fp_val_e = fu.mk_round_toward_zero(); + } + + TRACE("fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); + res = alloc(expr_wrapper_proc, fp_val_e); + m.inc_ref(fp_val_e); + } + } + else { + expr * bv_sgn, *bv_sig, *bv_exp; + split_triple(bv_e, bv_sgn, bv_sig, bv_exp); + + SASSERT(ctx.e_internalized(bv_sgn)); + SASSERT(ctx.e_internalized(bv_sig)); + SASSERT(ctx.e_internalized(bv_exp)); + + enode * e_sgn = ctx.get_enode(bv_sgn); + enode * e_sig = ctx.get_enode(bv_sig); + enode * e_exp = ctx.get_enode(bv_exp); + + sort * s = m.get_sort(e_sgn->get_owner()); + family_id fid = s->get_family_id(); + theory * bv_th = ctx.get_theory(fid); + + expr_wrapper_proc * mv_sgn = (expr_wrapper_proc*)bv_th->mk_value(e_sgn, mg); + expr_wrapper_proc * mv_sig = (expr_wrapper_proc*)bv_th->mk_value(e_sig, mg); + expr_wrapper_proc * mv_exp = (expr_wrapper_proc*)bv_th->mk_value(e_exp, mg); + + ptr_vector pve; + app_ref bvm_sgn(m), bvm_sig(m), bvm_exp(m); + bvm_sgn = mv_sgn->mk_value(mg, pve); + bvm_sig = mv_sig->mk_value(mg, pve); + bvm_exp = mv_exp->mk_value(mg, pve); + + TRACE("fpa", tout << "bv model: [" << mk_ismt2_pp(bvm_sgn, get_manager()) << " " + << mk_ismt2_pp(bvm_sig, get_manager()) << " " + << mk_ismt2_pp(bvm_exp, get_manager()) << "]\n";); + + unsigned sgn_sz, sig_sz, exp_sz; + rational sgn_q(0), sig_q(0), exp_q(0); + if (bvm_sgn) bu.is_numeral(bvm_sgn, sgn_q, sgn_sz); + if (bvm_sig) bu.is_numeral(bvm_sig, sig_q, sig_sz); + if (bvm_exp) bu.is_numeral(bvm_exp, exp_q, exp_sz); + + // un-bias exponent + rational exp_unbiased_q; + exp_unbiased_q = exp_q - fu.fm().m_powers2.m1(exp_sz - 1); + + mpz sig_z; mpf_exp_t exp_z; + mpzm.set(sig_z, sig_q.to_mpq().numerator()); + exp_z = mpzm.get_int64(exp_unbiased_q.to_mpq().numerator()); + + mpf fp_val; + fu.fm().set(fp_val, exp_sz, sig_sz+1, !mpqm.is_zero(sgn_q.to_mpq()), sig_z, exp_z); + + app_ref fp_val_e(m); + fp_val_e = fu.mk_value(fp_val); + mpzm.del(sig_z); + + TRACE("fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); + + res = alloc(expr_wrapper_proc, fp_val_e); + m.inc_ref(fp_val_e); + } + + return res; } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index bb3a8b786..51e0ff0d5 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -25,20 +25,37 @@ Revision History: namespace smt { class theory_fpa : public theory { + typedef trail_stack th_trail_stack; + fpa2bv_converter m_converter; fpa2bv_rewriter m_rw; + expr_map m_trans_map; + th_trail_stack m_trail_stack; virtual final_check_status final_check_eh() { return FC_DONE; } - virtual bool internalize_atom(app * a, bool); - virtual bool internalize_term(app * a) { return internalize_atom(a, false); } + virtual bool internalize_atom(app * atom, bool gate_ctx); + virtual bool internalize_term(app * term); + virtual void apply_sort_cnstr(enode * n, sort * s); virtual void new_eq_eh(theory_var, theory_var); virtual void new_diseq_eh(theory_var, theory_var); virtual void push_scope_eh(); virtual void pop_scope_eh(unsigned num_scopes); virtual theory* mk_fresh(context*) { return alloc(theory_fpa, get_manager()); } - virtual char const * get_name() const { return "fpa"; } + virtual char const * get_name() const { return "fpa"; } + + virtual model_value_proc * mk_value(enode * n, model_generator & mg); + public: theory_fpa(ast_manager& m); + + protected: + void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { + SASSERT(is_app_of(e, get_family_id(), OP_TO_FLOAT)); + SASSERT(to_app(e)->get_num_args() == 3); + sgn = to_app(e)->get_arg(0); + sig = to_app(e)->get_arg(1); + exp = to_app(e)->get_arg(2); + } }; }; From c2a2d2d0dfdccccc9e611d8556014fdff774be3f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 11 Jun 2014 13:27:21 +0100 Subject: [PATCH 045/646] Renamed Z3_mk_double to Z3_mk_fpa_double for consistency Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 4 ++-- src/api/z3_fpa.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 278a0556a..374e3d344 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -121,9 +121,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_double(Z3_context c, double v, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_double(Z3_context c, double v, Z3_sort ty) { Z3_TRY; - LOG_Z3_mk_double(c, v, ty); + LOG_Z3_mk_fpa_double(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->float_util().fm()); diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 93268b821..81cfff591 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -131,7 +131,7 @@ extern "C" { def_API('Z3_mk_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_double(__in Z3_context c, __in double v, __in Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); /** \brief Floating-point absolute value From ca89b120d3b2c1ebb83eb996f022425c701768db Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 11 Jun 2014 16:44:12 +0100 Subject: [PATCH 046/646] improve FPA theory implementation Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 239 ++++++++++++++++++++++++++++------------- src/smt/theory_fpa.h | 7 +- 2 files changed, 170 insertions(+), 76 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index bd95d78f1..e606857e5 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -19,27 +19,32 @@ Revision History: #include"ast_smt2_pp.h" #include"smt_context.h" #include"theory_fpa.h" +#include"theory_bv.h" #include"smt_model_generator.h" namespace smt { - theory_fpa::theory_fpa(ast_manager & m) : - theory(m.mk_family_id("float")), - m_converter(m), + theory_fpa::theory_fpa(ast_manager & m) : + theory(m.mk_family_id("float")), + m_converter(m), m_rw(m, m_converter, params_ref()), m_trans_map(m), m_trail_stack(*this) { } + theory_fpa::~theory_fpa() + { + } + bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { - TRACE("fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); + TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); NOT_IMPLEMENTED_YET(); } bool theory_fpa::internalize_term(app * term) { - TRACE("fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); + TRACE("t_fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); SASSERT(term->get_family_id() == get_family_id()); SASSERT(!get_context().e_internalized(term)); @@ -55,7 +60,7 @@ namespace smt { m_rw(term, res); SASSERT(is_app(res) && to_app(res)->get_num_args() == 3); app * a = to_app(res); - TRACE("fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); + TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); expr_ref sgn(m), sig(m), exp(m); proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); @@ -63,20 +68,34 @@ namespace smt { simp(a->get_arg(1), sig, pr_sig); simp(a->get_arg(2), exp, pr_exp); - ctx.internalize(sgn, false); - ctx.internalize(sig, false); - ctx.internalize(exp, false); + expr_ref bv_v_sgn(m), bv_v_sig(m), bv_v_exp(m); + bv_v_sgn = m.mk_fresh_const("fpa2bv", m.get_sort(sgn)); + bv_v_sig = m.mk_fresh_const("fpa2bv", m.get_sort(sig)); + bv_v_exp = m.mk_fresh_const("fpa2bv", m.get_sort(exp)); + expr_ref e1(m), e2(m), e3(m); + e1 = m.mk_eq(bv_v_sgn, sgn); + e2 = m.mk_eq(bv_v_sig, sig); + e3 = m.mk_eq(bv_v_exp, exp); + ctx.internalize(e1, false); + ctx.internalize(e2, false); + ctx.internalize(e3, false); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); + ctx.mark_as_relevant(e1); + ctx.mark_as_relevant(e2); + ctx.mark_as_relevant(e3); expr_ref s_term(m); - m_converter.mk_triple(sgn, sig, exp, s_term); + m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, s_term); SASSERT(!m_trans_map.contains(term)); m_trans_map.insert(term, s_term, 0); enode * e = ctx.mk_enode(term, false, false, true); - theory_var v = mk_var(e); + theory_var v = mk_var(e); ctx.attach_th_var(e, this, v); - TRACE("fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); + TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); SASSERT(e->get_th_var(get_id()) != null_theory_var); return v != null_theory_var; @@ -84,6 +103,7 @@ namespace smt { void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { if (!is_attached_to_var(n)) { + TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); context & ctx = get_context(); ast_manager & m = get_manager(); simplifier & simp = ctx.get_simplifier(); @@ -96,7 +116,12 @@ namespace smt { m_trans_map.insert(owner, converted, 0); if (m_converter.is_rm_sort(m.get_sort(owner))) { - ctx.internalize(converted, false); + expr_ref bv_v(m), eq(m); + bv_v = m.mk_fresh_const("fpa2bv", m.get_sort(converted)); + eq = m.mk_eq(bv_v, converted); + ctx.internalize(eq, false); + literal l = ctx.get_literal(eq); + ctx.mk_th_axiom(get_id(), 1, &l); } else { app * a = to_app(converted); @@ -109,14 +134,32 @@ namespace smt { ctx.internalize(sgn, false); ctx.internalize(sig, false); ctx.internalize(exp, false); + + expr_ref bv_v_sgn(m), bv_v_sig(m), bv_v_exp(m); + bv_v_sgn = m.mk_fresh_const("fpa2bv", m.get_sort(sgn)); + bv_v_sig = m.mk_fresh_const("fpa2bv", m.get_sort(sig)); + bv_v_exp = m.mk_fresh_const("fpa2bv", m.get_sort(exp)); + expr_ref e1(m), e2(m), e3(m); + e1 = m.mk_eq(bv_v_sgn, sgn); + e2 = m.mk_eq(bv_v_sig, sig); + e3 = m.mk_eq(bv_v_exp, exp); + ctx.internalize(e1, true); + ctx.internalize(e2, true); + ctx.internalize(e3, true); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); + ctx.mark_as_relevant(e1); + ctx.mark_as_relevant(e2); + ctx.mark_as_relevant(e3); } - TRACE("fpa", tout << "new const: " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); + TRACE("t_fpa", tout << "new theory var (const): " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); } } void theory_fpa::new_eq_eh(theory_var x, theory_var y) { - TRACE("fpa", tout << "new eq: " << x << " = " << y << "\n";); + TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); app * ax = get_enode(x)->get_owner(); @@ -132,9 +175,6 @@ namespace smt { split_triple(ex, sgn_x, sig_x, exp_x); split_triple(ey, sgn_y, sig_y, exp_y); - literal_vector lits; - lits.push_back(mk_eq(ax, ay, true)); - expr_ref e1(m), e2(m), e3(m); e1 = m.mk_eq(sgn_x, sgn_y); e2 = m.mk_eq(sig_x, sig_y); @@ -142,15 +182,16 @@ namespace smt { ctx.internalize(e1, true); ctx.internalize(e2, true); ctx.internalize(e3, true); - lits.push_back(ctx.get_literal(e1)); - lits.push_back(ctx.get_literal(e2)); - lits.push_back(ctx.get_literal(e3)); - - ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr()); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); + ctx.mark_as_relevant(e1); + ctx.mark_as_relevant(e2); + ctx.mark_as_relevant(e3); } void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { - TRACE("fpa", tout << "new eq: " << x << " = " << y << "\n";); + TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); app * ax = get_enode(x)->get_owner(); @@ -166,9 +207,13 @@ namespace smt { split_triple(ex, sgn_x, sig_x, exp_x); split_triple(ex, sgn_y, sig_y, exp_y); - ctx.internalize(m.mk_not(m.mk_eq(sgn_x, sgn_y)), true); - ctx.internalize(m.mk_not(m.mk_eq(sig_x, sig_y)), true); - ctx.internalize(m.mk_not(m.mk_eq(exp_x, exp_y)), true); + expr_ref e1(m), e2(m), e3(m); + e1 = m.mk_not(m.mk_eq(sgn_x, sgn_y)); + e2 = m.mk_or(e1, m.mk_not(m.mk_eq(sig_x, sig_y))); + e3 = m.mk_or(e2, m.mk_not(m.mk_eq(exp_x, exp_y))); + ctx.internalize(e3, true); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); + ctx.mark_as_relevant(e3); } void theory_fpa::push_scope_eh() { @@ -186,13 +231,14 @@ namespace smt { context & ctx = get_context(); bv_util & bu = m_converter.bu(); float_util & fu = m_converter.fu(); - unsynch_mpz_manager & mpzm = fu.fm().mpz_manager(); - unsynch_mpq_manager & mpqm = fu.fm().mpq_manager(); + mpf_manager & mpfm = fu.fm(); + unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); theory_var v = n->get_th_var(get_id()); SASSERT(v != null_theory_var); expr * fpa_e = get_enode(v)->get_owner(); - TRACE("fpa", tout << "mk_value for: " << mk_ismt2_pp(fpa_e, m) << "\n";); + TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(fpa_e, m) << "\n";); expr * bv_e; proof * bv_pr; @@ -204,17 +250,14 @@ namespace smt { SASSERT(ctx.e_internalized(bv_e)); sort * s = m.get_sort(bv_e); family_id fid = s->get_family_id(); - theory * bv_th = ctx.get_theory(fid); - - enode * ev = ctx.get_enode(bv_e); - ptr_vector pve; - app_ref mv(m); - mv = ((expr_wrapper_proc*)bv_th->mk_value(ev, mg))->mk_value(mg, pve); - - rational val(0); - unsigned sz = 0; - if (bu.is_numeral(mv, val, sz)) { - app_ref fp_val_e(m); + theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); + rational val; + if (!bv_th->get_fixed_value(ctx.get_enode(bv_e)->get_owner(), val)) { + NOT_IMPLEMENTED_YET(); + } + else + { + app * fp_val_e; SASSERT(val.is_uint64()); switch (val.get_uint64()) { @@ -226,9 +269,8 @@ namespace smt { default: fp_val_e = fu.mk_round_toward_zero(); } - TRACE("fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); + TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); res = alloc(expr_wrapper_proc, fp_val_e); - m.inc_ref(fp_val_e); } } else { @@ -241,53 +283,100 @@ namespace smt { enode * e_sgn = ctx.get_enode(bv_sgn); enode * e_sig = ctx.get_enode(bv_sig); - enode * e_exp = ctx.get_enode(bv_exp); + enode * e_exp = ctx.get_enode(bv_exp); + + TRACE("t_fpa", tout << "bv rep: [" << mk_ismt2_pp(e_sgn->get_owner(), m) << " " + << mk_ismt2_pp(e_sig->get_owner(), m) << " " + << mk_ismt2_pp(e_exp->get_owner(), m) << "]\n";); sort * s = m.get_sort(e_sgn->get_owner()); family_id fid = s->get_family_id(); - theory * bv_th = ctx.get_theory(fid); + theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); - expr_wrapper_proc * mv_sgn = (expr_wrapper_proc*)bv_th->mk_value(e_sgn, mg); - expr_wrapper_proc * mv_sig = (expr_wrapper_proc*)bv_th->mk_value(e_sig, mg); - expr_wrapper_proc * mv_exp = (expr_wrapper_proc*)bv_th->mk_value(e_exp, mg); + SASSERT(bv_th->is_attached_to_var(e_sgn)); + SASSERT(bv_th->is_attached_to_var(e_sig)); + SASSERT(bv_th->is_attached_to_var(e_exp)); - ptr_vector pve; - app_ref bvm_sgn(m), bvm_sig(m), bvm_exp(m); - bvm_sgn = mv_sgn->mk_value(mg, pve); - bvm_sig = mv_sig->mk_value(mg, pve); - bvm_exp = mv_exp->mk_value(mg, pve); + unsigned sig_sz, exp_sz; + sig_sz = bu.get_bv_size(e_sig->get_owner()); + exp_sz = bu.get_bv_size(e_exp->get_owner()); - TRACE("fpa", tout << "bv model: [" << mk_ismt2_pp(bvm_sgn, get_manager()) << " " - << mk_ismt2_pp(bvm_sig, get_manager()) << " " - << mk_ismt2_pp(bvm_exp, get_manager()) << "]\n";); + rational sgn_r(0), sig_r(0), exp_r(0); + + if (!bv_th->get_fixed_value(e_sgn->get_owner(), sgn_r) || + !bv_th->get_fixed_value(e_sig->get_owner(), sig_r) || + !bv_th->get_fixed_value(e_exp->get_owner(), exp_r)) { + NOT_IMPLEMENTED_YET(); + } + else { + TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " + << sig_r.to_string() << " " + << exp_r.to_string() << "]\n";); - unsigned sgn_sz, sig_sz, exp_sz; - rational sgn_q(0), sig_q(0), exp_q(0); - if (bvm_sgn) bu.is_numeral(bvm_sgn, sgn_q, sgn_sz); - if (bvm_sig) bu.is_numeral(bvm_sig, sig_q, sig_sz); - if (bvm_exp) bu.is_numeral(bvm_exp, exp_q, exp_sz); + // un-bias exponent + rational exp_unbiased_r; + exp_unbiased_r = exp_r - mpfm.m_powers2.m1(exp_sz - 1); - // un-bias exponent - rational exp_unbiased_q; - exp_unbiased_q = exp_q - fu.fm().m_powers2.m1(exp_sz - 1); + mpz sig_z; mpf_exp_t exp_z; + mpq sig_q, exp_q; + mpz sig_num, exp_num; + mpqm.set(sig_q, sig_r.to_mpq()); + mpzm.set(sig_num, sig_q.numerator()); + mpqm.set(exp_q, exp_unbiased_r.to_mpq()); + mpzm.set(exp_num, exp_q.numerator()); + mpzm.set(sig_z, sig_num); + exp_z = mpzm.get_int64(exp_num); - mpz sig_z; mpf_exp_t exp_z; - mpzm.set(sig_z, sig_q.to_mpq().numerator()); - exp_z = mpzm.get_int64(exp_unbiased_q.to_mpq().numerator()); + mpf fp_val; + mpfm.set(fp_val, exp_sz, sig_sz + 1, !sgn_r.is_zero(), sig_z, exp_z); - mpf fp_val; - fu.fm().set(fp_val, exp_sz, sig_sz+1, !mpqm.is_zero(sgn_q.to_mpq()), sig_z, exp_z); + app * fp_val_e; + fp_val_e = fu.mk_value(fp_val); - app_ref fp_val_e(m); - fp_val_e = fu.mk_value(fp_val); - mpzm.del(sig_z); + TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); - TRACE("fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); + mpfm.del(fp_val); + mpzm.del(sig_num); + mpzm.del(exp_num); + mpqm.del(sig_q); + mpqm.del(exp_q); + mpzm.del(sig_z); - res = alloc(expr_wrapper_proc, fp_val_e); - m.inc_ref(fp_val_e); + res = alloc(expr_wrapper_proc, fp_val_e); + } } return res; } + + void theory_fpa::assign_eh(bool_var v, bool is_true) { + TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << ")\n";); + UNREACHABLE(); + } + + void theory_fpa::relevant_eh(app * n) { + ast_manager & m = get_manager(); + context & ctx = get_context(); + float_util & fu = m_converter.fu(); + if (ctx.e_internalized(n)) { + SASSERT(m_trans_map.contains(n)); + expr * ex; + proof * px; + m_trans_map.get(n, ex, px); + + if (fu.is_rm(m.get_sort(n))) { + ctx.mark_as_relevant(ex); + } + else { + expr * bv_sgn, *bv_sig, *bv_exp; + split_triple(ex, bv_sgn, bv_sig, bv_exp); + + ctx.mark_as_relevant(bv_sgn); + ctx.mark_as_relevant(bv_sig); + ctx.mark_as_relevant(bv_exp); + } + } + else + NOT_IMPLEMENTED_YET(); + } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 51e0ff0d5..4a465ada2 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -44,9 +44,12 @@ namespace smt { virtual char const * get_name() const { return "fpa"; } virtual model_value_proc * mk_value(enode * n, model_generator & mg); - + + void assign_eh(bool_var v, bool is_true); + virtual void relevant_eh(app * n); public: theory_fpa(ast_manager& m); + virtual ~theory_fpa(); protected: void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { @@ -56,6 +59,8 @@ namespace smt { sig = to_app(e)->get_arg(1); exp = to_app(e)->get_arg(2); } + + void ensure_bv_var(expr_ref const & n); }; }; From 129e2f5e238daf2bb37d2e1e9dcc425a741fbf75 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 11 Jun 2014 17:55:31 +0100 Subject: [PATCH 047/646] FPA API fixes and examples Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 55 +++++++++++++++++++++++++++------------ src/api/dotnet/Context.cs | 2 +- src/api/z3_fpa.h | 2 +- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 4363ee382..578c563b7 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2604,29 +2604,49 @@ void fpa_example() { printf("\nFPA-example\n"); LOG_MSG("FPA-example"); - - enable_trace("fpa"); - cfg = Z3_mk_config(); - ctx = Z3_mk_context(cfg); + cfg = Z3_mk_config(); + ctx = Z3_mk_context(cfg); Z3_del_config(cfg); - double_sort = Z3_mk_fpa_sort(ctx, 11, 53); - rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx); + double_sort = Z3_mk_fpa_sort(ctx, 11, 53); + rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx); - symbol_rm = Z3_mk_string_symbol(ctx, "rm"); - rm = Z3_mk_const(ctx, symbol_rm, rm_sort); - symbol_x = Z3_mk_string_symbol(ctx, "x"); - symbol_y = Z3_mk_string_symbol(ctx, "y"); - x = Z3_mk_const(ctx, symbol_x, double_sort); - y = Z3_mk_const(ctx, symbol_y, double_sort); - n = Z3_mk_double(ctx, 42.0, double_sort); + symbol_rm = Z3_mk_string_symbol(ctx, "rm"); + rm = Z3_mk_const(ctx, symbol_rm, rm_sort); + symbol_x = Z3_mk_string_symbol(ctx, "x"); + symbol_y = Z3_mk_string_symbol(ctx, "y"); + x = Z3_mk_const(ctx, symbol_x, double_sort); + y = Z3_mk_const(ctx, symbol_y, double_sort); + n = Z3_mk_fpa_double(ctx, 42.0, double_sort); + + Z3_symbol q_s = Z3_mk_string_symbol(ctx, "q"); + Z3_ast q = Z3_mk_const(ctx, q_s, double_sort); + c = Z3_mk_eq(ctx, q, Z3_mk_fpa_add(ctx, rm, x, y)); + + Z3_ast args[2] = { c, Z3_mk_eq(ctx, q, n) }; + c = Z3_mk_and(ctx, 2, (Z3_ast*)&args); + + printf("c = %s\n", Z3_ast_to_string(ctx, c)); - c = Z3_mk_eq(ctx, Z3_mk_fpa_add(ctx, rm, x, y), n); - Z3_assert_cnstr(ctx, c); - if (Z3_check(ctx) != Z3_L_TRUE) - printf("FPA-example not satisfied!\n"); + + Z3_model m = 0; + Z3_lbool result = Z3_check_and_get_model(ctx, &m); + switch (result) { + case Z3_L_FALSE: + printf("unsat\n"); + break; + case Z3_L_UNDEF: + printf("unknown\n"); + break; + case Z3_L_TRUE: + printf("sat\n%s\n", Z3_model_to_string(ctx, m)); + break; + } + + if (m) + Z3_del_model(ctx, m); Z3_del_context(ctx); } @@ -2676,5 +2696,6 @@ int main() { smt2parser_example(); substitute_example(); substitute_vars_example(); + fpa_example(); return 0; } diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index b654feb7e..e60c93fba 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3533,7 +3533,7 @@ namespace Microsoft.Z3 public FPNum MkFP(double v, FPSort s) { Contract.Ensures(Contract.Result() != null); - return new FPNum(this, Native.Z3_mk_double(this.nCtx, v, s.NativeObject)); + return new FPNum(this, Native.Z3_mk_fpa_double(this.nCtx, v, s.NativeObject)); } /// diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 81cfff591..93cfb8dd5 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -129,7 +129,7 @@ extern "C" { \sa Z3_mk_numeral - def_API('Z3_mk_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) + def_API('Z3_mk_fpa_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) */ Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); From 8b8cee7f6484ff0dfaa466c29c5f7f318b780101 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 12 Jun 2014 15:14:06 +0100 Subject: [PATCH 048/646] FPA theory improvements Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 221 +++++++++++++++++++++-------------------- src/smt/theory_fpa.h | 5 +- 2 files changed, 119 insertions(+), 107 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index e606857e5..3a52b2590 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -37,6 +37,25 @@ namespace smt { { } + void theory_fpa::mk_bv_eq(expr * x, expr * y) { + ast_manager & m = get_manager(); + context & ctx = get_context(); + expr_ref eq(m); + eq = m.mk_eq(x, y); + ctx.internalize(eq, false); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(eq)); + ctx.mark_as_relevant(eq); + } + + expr_ref theory_fpa::mk_eq_bv_const(expr_ref const & e) { + ast_manager & m = get_manager(); + context & ctx = get_context(); + expr_ref bv_const(m); + bv_const = m.mk_fresh_const(0, m.get_sort(e)); + mk_bv_eq(bv_const, e); + return bv_const; + } + bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); @@ -51,53 +70,60 @@ namespace smt { ast_manager & m = get_manager(); context & ctx = get_context(); simplifier & simp = ctx.get_simplifier(); - + unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); + + if (m_converter.is_float(m.get_sort(term))) { + expr_ref res(m); + m_rw(term, res); + SASSERT(is_app(res) && to_app(res)->get_num_args() == 3); + TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); + + app * a = to_app(res); + expr_ref sgn(m), sig(m), exp(m); + proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); + simp(a->get_arg(0), sgn, pr_sgn); + simp(a->get_arg(1), sig, pr_sig); + simp(a->get_arg(2), exp, pr_exp); - expr_ref res(m); - m_rw(term, res); - SASSERT(is_app(res) && to_app(res)->get_num_args() == 3); - app * a = to_app(res); - TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); + expr_ref bv_v_sgn = mk_eq_bv_const(sgn); + expr_ref bv_v_sig = mk_eq_bv_const(sig); + expr_ref bv_v_exp = mk_eq_bv_const(exp); - expr_ref sgn(m), sig(m), exp(m); - proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); - simp(a->get_arg(0), sgn, pr_sgn); - simp(a->get_arg(1), sig, pr_sig); - simp(a->get_arg(2), exp, pr_exp); + expr_ref s_term(m); + m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, s_term); - expr_ref bv_v_sgn(m), bv_v_sig(m), bv_v_exp(m); - bv_v_sgn = m.mk_fresh_const("fpa2bv", m.get_sort(sgn)); - bv_v_sig = m.mk_fresh_const("fpa2bv", m.get_sort(sig)); - bv_v_exp = m.mk_fresh_const("fpa2bv", m.get_sort(exp)); - expr_ref e1(m), e2(m), e3(m); - e1 = m.mk_eq(bv_v_sgn, sgn); - e2 = m.mk_eq(bv_v_sig, sig); - e3 = m.mk_eq(bv_v_exp, exp); - ctx.internalize(e1, false); - ctx.internalize(e2, false); - ctx.internalize(e3, false); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); - ctx.mark_as_relevant(e1); - ctx.mark_as_relevant(e2); - ctx.mark_as_relevant(e3); + SASSERT(!m_trans_map.contains(term)); + m_trans_map.insert(term, s_term, 0); + } + else if (m_converter.is_rm_sort(m.get_sort(term))) { + expr_ref res(m); + m_rw(term, res); + SASSERT(is_app(res)); + TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); + + app * a = to_app(res); + expr_ref bv_rm(m); + proof_ref bv_pr(m); + simp(res, bv_rm, bv_pr); - expr_ref s_term(m); - m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, s_term); + expr_ref bv_v = mk_eq_bv_const(bv_rm); - SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, s_term, 0); + SASSERT(!m_trans_map.contains(term)); + m_trans_map.insert(term, bv_v, 0); + + + } + else + UNREACHABLE(); enode * e = ctx.mk_enode(term, false, false, true); - theory_var v = mk_var(e); + theory_var v = mk_var(e); ctx.attach_th_var(e, this, v); TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); SASSERT(e->get_th_var(get_id()) != null_theory_var); - return v != null_theory_var; } @@ -116,12 +142,7 @@ namespace smt { m_trans_map.insert(owner, converted, 0); if (m_converter.is_rm_sort(m.get_sort(owner))) { - expr_ref bv_v(m), eq(m); - bv_v = m.mk_fresh_const("fpa2bv", m.get_sort(converted)); - eq = m.mk_eq(bv_v, converted); - ctx.internalize(eq, false); - literal l = ctx.get_literal(eq); - ctx.mk_th_axiom(get_id(), 1, &l); + mk_eq_bv_const(converted); } else { app * a = to_app(converted); @@ -131,89 +152,77 @@ namespace smt { simp(a->get_arg(1), sig, pr_sig); simp(a->get_arg(2), exp, pr_exp); - ctx.internalize(sgn, false); - ctx.internalize(sig, false); - ctx.internalize(exp, false); - - expr_ref bv_v_sgn(m), bv_v_sig(m), bv_v_exp(m); - bv_v_sgn = m.mk_fresh_const("fpa2bv", m.get_sort(sgn)); - bv_v_sig = m.mk_fresh_const("fpa2bv", m.get_sort(sig)); - bv_v_exp = m.mk_fresh_const("fpa2bv", m.get_sort(exp)); - expr_ref e1(m), e2(m), e3(m); - e1 = m.mk_eq(bv_v_sgn, sgn); - e2 = m.mk_eq(bv_v_sig, sig); - e3 = m.mk_eq(bv_v_exp, exp); - ctx.internalize(e1, true); - ctx.internalize(e2, true); - ctx.internalize(e3, true); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); - ctx.mark_as_relevant(e1); - ctx.mark_as_relevant(e2); - ctx.mark_as_relevant(e3); + mk_eq_bv_const(sgn); + mk_eq_bv_const(sig); + mk_eq_bv_const(exp); } TRACE("t_fpa", tout << "new theory var (const): " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); } } - void theory_fpa::new_eq_eh(theory_var x, theory_var y) { + void theory_fpa::new_eq_eh(theory_var x, theory_var y) { TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); + app * ax = get_enode(x)->get_owner(); app * ay = get_enode(y)->get_owner(); - - expr * ex, * ey; - proof * px, * py; + expr * ex, *ey; + proof * px, *py; m_trans_map.get(ax, ex, px); m_trans_map.get(ay, ey, py); - expr * sgn_x, * sig_x, * exp_x; - expr * sgn_y, * sig_y, * exp_y; - split_triple(ex, sgn_x, sig_x, exp_x); - split_triple(ey, sgn_y, sig_y, exp_y); - - expr_ref e1(m), e2(m), e3(m); - e1 = m.mk_eq(sgn_x, sgn_y); - e2 = m.mk_eq(sig_x, sig_y); - e3 = m.mk_eq(exp_x, exp_y); - ctx.internalize(e1, true); - ctx.internalize(e2, true); - ctx.internalize(e3, true); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e1)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e2)); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); - ctx.mark_as_relevant(e1); - ctx.mark_as_relevant(e2); - ctx.mark_as_relevant(e3); + if (m_converter.fu().is_float(m.get_sort(get_enode(x)->get_owner()))) { + expr * sgn_x, *sig_x, *exp_x; + expr * sgn_y, *sig_y, *exp_y; + split_triple(ex, sgn_x, sig_x, exp_x); + split_triple(ey, sgn_y, sig_y, exp_y); + + mk_bv_eq(sgn_x, sgn_y); + mk_bv_eq(sig_x, sig_y); + mk_bv_eq(exp_x, exp_y); + } + else if (m_converter.fu().is_rm(m.get_sort(get_enode(x)->get_owner()))) { + mk_bv_eq(ex, ey); + } + else + UNREACHABLE(); } void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); + app * ax = get_enode(x)->get_owner(); app * ay = get_enode(y)->get_owner(); - expr * ex, *ey; proof * px, *py; m_trans_map.get(ax, ex, px); m_trans_map.get(ay, ey, py); - expr * sgn_x, *sig_x, *exp_x; - expr * sgn_y, *sig_y, *exp_y; - split_triple(ex, sgn_x, sig_x, exp_x); - split_triple(ex, sgn_y, sig_y, exp_y); + expr_ref deq(m); - expr_ref e1(m), e2(m), e3(m); - e1 = m.mk_not(m.mk_eq(sgn_x, sgn_y)); - e2 = m.mk_or(e1, m.mk_not(m.mk_eq(sig_x, sig_y))); - e3 = m.mk_or(e2, m.mk_not(m.mk_eq(exp_x, exp_y))); - ctx.internalize(e3, true); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(e3)); - ctx.mark_as_relevant(e3); + if (m_converter.fu().is_float(m.get_sort(get_enode(x)->get_owner()))) { + expr * sgn_x, *sig_x, *exp_x; + expr * sgn_y, *sig_y, *exp_y; + split_triple(ex, sgn_x, sig_x, exp_x); + split_triple(ex, sgn_y, sig_y, exp_y); + + deq = m.mk_or(m.mk_not(m.mk_eq(sgn_x, sgn_y)), + m.mk_not(m.mk_eq(sig_x, sig_y)), + m.mk_not(m.mk_eq(exp_x, exp_y))); + } + else if (m_converter.fu().is_rm(m.get_sort(get_enode(x)->get_owner()))) { + deq = m.mk_not(m.mk_eq(ex, ey)); + } + else + UNREACHABLE(); + + ctx.internalize(deq, true); + ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(deq)); + ctx.mark_as_relevant(deq); } void theory_fpa::push_scope_eh() { @@ -273,7 +282,7 @@ namespace smt { res = alloc(expr_wrapper_proc, fp_val_e); } } - else { + else if (fu.is_float(m.get_sort(fpa_e))) { expr * bv_sgn, *bv_sig, *bv_exp; split_triple(bv_e, bv_sgn, bv_sig, bv_exp); @@ -283,15 +292,15 @@ namespace smt { enode * e_sgn = ctx.get_enode(bv_sgn); enode * e_sig = ctx.get_enode(bv_sig); - enode * e_exp = ctx.get_enode(bv_exp); + enode * e_exp = ctx.get_enode(bv_exp); TRACE("t_fpa", tout << "bv rep: [" << mk_ismt2_pp(e_sgn->get_owner(), m) << " " - << mk_ismt2_pp(e_sig->get_owner(), m) << " " - << mk_ismt2_pp(e_exp->get_owner(), m) << "]\n";); + << mk_ismt2_pp(e_sig->get_owner(), m) << " " + << mk_ismt2_pp(e_exp->get_owner(), m) << "]\n";); sort * s = m.get_sort(e_sgn->get_owner()); family_id fid = s->get_family_id(); - theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); + theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); SASSERT(bv_th->is_attached_to_var(e_sgn)); SASSERT(bv_th->is_attached_to_var(e_sig)); @@ -301,8 +310,8 @@ namespace smt { sig_sz = bu.get_bv_size(e_sig->get_owner()); exp_sz = bu.get_bv_size(e_exp->get_owner()); - rational sgn_r(0), sig_r(0), exp_r(0); - + rational sgn_r(0), sig_r(0), exp_r(0); + if (!bv_th->get_fixed_value(e_sgn->get_owner(), sgn_r) || !bv_th->get_fixed_value(e_sig->get_owner(), sig_r) || !bv_th->get_fixed_value(e_exp->get_owner(), exp_r)) { @@ -310,8 +319,8 @@ namespace smt { } else { TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " - << sig_r.to_string() << " " - << exp_r.to_string() << "]\n";); + << sig_r.to_string() << " " + << exp_r.to_string() << "]\n";); // un-bias exponent rational exp_unbiased_r; @@ -345,6 +354,8 @@ namespace smt { res = alloc(expr_wrapper_proc, fp_val_e); } } + else + UNREACHABLE(); return res; } @@ -377,6 +388,6 @@ namespace smt { } } else - NOT_IMPLEMENTED_YET(); + UNREACHABLE(); } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 4a465ada2..ea09df27b 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -59,8 +59,9 @@ namespace smt { sig = to_app(e)->get_arg(1); exp = to_app(e)->get_arg(2); } - - void ensure_bv_var(expr_ref const & n); + + void mk_bv_eq(expr * x, expr * y); + expr_ref mk_eq_bv_const(expr_ref const & e); }; }; From 4a915f6528f33802f9b271be53a8fcf158384231 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 12 Jun 2014 21:16:11 +0100 Subject: [PATCH 049/646] FPA theory additions Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 163 ++++++++++++++++++++++++++++------------- src/smt/theory_fpa.h | 28 ++++++- 2 files changed, 139 insertions(+), 52 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 3a52b2590..7082a9582 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -24,6 +24,18 @@ Revision History: namespace smt { + class mk_atom_trail : public trail { + bool_var m_var; + public: + mk_atom_trail(bool_var v) : m_var(v) {} + virtual ~mk_atom_trail() {} + virtual void undo(theory_fpa & th) { + theory_fpa::atom * a = th.get_bv2a(m_var); + a->~atom(); + th.erase_bv2a(m_var); + } + }; + theory_fpa::theory_fpa(ast_manager & m) : theory(m.mk_family_id("float")), m_converter(m), @@ -38,13 +50,13 @@ namespace smt { } void theory_fpa::mk_bv_eq(expr * x, expr * y) { + SASSERT(get_sort(x)->get_family_id() == m_converter.bu().get_family_id()); ast_manager & m = get_manager(); - context & ctx = get_context(); - expr_ref eq(m); - eq = m.mk_eq(x, y); - ctx.internalize(eq, false); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(eq)); - ctx.mark_as_relevant(eq); + context & ctx = get_context(); + theory_id bv_tid = ctx.get_theory(m.get_sort(x)->get_family_id())->get_id(); + literal l = mk_eq(x, y, false); + ctx.mk_th_axiom(get_id(), 1, &l); + ctx.mark_as_relevant(l); } expr_ref theory_fpa::mk_eq_bv_const(expr_ref const & e) { @@ -59,7 +71,33 @@ namespace smt { bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); - NOT_IMPLEMENTED_YET(); + + ast_manager & m = get_manager(); + context & ctx = get_context(); + simplifier & simp = ctx.get_simplifier(); + bv_util & bu = m_converter.bu(); + expr_ref bv_atom(m); + + unsigned num_args = atom->get_num_args(); + for (unsigned i = 0; i < num_args; i++) + ctx.internalize(atom->get_arg(i), false); + + m_rw(atom, bv_atom); + + ctx.internalize(bv_atom, gate_ctx); + literal def = ctx.get_literal(bv_atom); + literal l(ctx.mk_bool_var(atom)); + ctx.set_var_theory(l.var(), get_id()); + pred_atom * a = new (get_region()) pred_atom(l, def); + insert_bv2a(l.var(), a); + m_trail_stack.push(mk_atom_trail(l.var())); + + if (!ctx.relevancy()) { + ctx.mk_th_axiom(get_id(), l, ~def); + ctx.mk_th_axiom(get_id(), ~l, def); + } + + return true; } bool theory_fpa::internalize_term(app * term) { @@ -69,19 +107,28 @@ namespace smt { ast_manager & m = get_manager(); context & ctx = get_context(); - simplifier & simp = ctx.get_simplifier(); + simplifier & simp = ctx.get_simplifier(); + bv_util & bu = m_converter.bu(); + sort * term_sort = m.get_sort(term); + expr_ref t(m), bv_term(m); unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); - - if (m_converter.is_float(m.get_sort(term))) { - expr_ref res(m); - m_rw(term, res); - SASSERT(is_app(res) && to_app(res)->get_num_args() == 3); - TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); - - app * a = to_app(res); + + m_rw(term, t); + + if (m_converter.is_rm_sort(term_sort)) { + SASSERT(is_app(t)); + expr_ref bv_rm(m); + proof_ref bv_pr(m); + simp(t, bv_rm, bv_pr); + + bv_term = mk_eq_bv_const(bv_rm); + } + else if (m_converter.is_float(term_sort)) { + SASSERT(is_app(t) && to_app(t)->get_num_args() == 3); + app * a = to_app(t); expr_ref sgn(m), sig(m), exp(m); proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); simp(a->get_arg(0), sgn, pr_sgn); @@ -92,34 +139,25 @@ namespace smt { expr_ref bv_v_sig = mk_eq_bv_const(sig); expr_ref bv_v_exp = mk_eq_bv_const(exp); - expr_ref s_term(m); - m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, s_term); - - SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, s_term, 0); + m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, bv_term); } - else if (m_converter.is_rm_sort(m.get_sort(term))) { - expr_ref res(m); - m_rw(term, res); - SASSERT(is_app(res)); - TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(res, get_manager()) << "\n";); - - app * a = to_app(res); - expr_ref bv_rm(m); + else if (term->get_decl_kind() == OP_TO_IEEE_BV) { + SASSERT(is_app(t)); + expr_ref bv_e(m); proof_ref bv_pr(m); - simp(res, bv_rm, bv_pr); + simp(t, bv_e, bv_pr); - expr_ref bv_v = mk_eq_bv_const(bv_rm); - - SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, bv_v, 0); - - + bv_term = mk_eq_bv_const(bv_e); } else - UNREACHABLE(); + NOT_IMPLEMENTED_YET(); - enode * e = ctx.mk_enode(term, false, false, true); + TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(bv_term, get_manager()) << "\n";); + + SASSERT(!m_trans_map.contains(term)); + m_trans_map.insert(term, bv_term, 0); + + enode * e = ctx.mk_enode(term, false, false, true); theory_var v = mk_var(e); ctx.attach_th_var(e, this, v); TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); @@ -191,7 +229,7 @@ namespace smt { } void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { - TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); + TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); @@ -219,7 +257,7 @@ namespace smt { } else UNREACHABLE(); - + ctx.internalize(deq, true); ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(deq)); ctx.mark_as_relevant(deq); @@ -252,17 +290,17 @@ namespace smt { expr * bv_e; proof * bv_pr; m_trans_map.get(fpa_e, bv_e, bv_pr); - + sort * fpa_e_srt = m.get_sort(fpa_e); expr_wrapper_proc * res = 0; - if (fu.is_rm(m.get_sort(fpa_e))) { + if (fu.is_rm(fpa_e_srt)) { SASSERT(ctx.e_internalized(bv_e)); sort * s = m.get_sort(bv_e); family_id fid = s->get_family_id(); theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); rational val; if (!bv_th->get_fixed_value(ctx.get_enode(bv_e)->get_owner(), val)) { - NOT_IMPLEMENTED_YET(); + UNREACHABLE(); } else { @@ -282,7 +320,7 @@ namespace smt { res = alloc(expr_wrapper_proc, fp_val_e); } } - else if (fu.is_float(m.get_sort(fpa_e))) { + else if (fu.is_float(fpa_e_srt)) { expr * bv_sgn, *bv_sig, *bv_exp; split_triple(bv_e, bv_sgn, bv_sig, bv_exp); @@ -315,7 +353,7 @@ namespace smt { if (!bv_th->get_fixed_value(e_sgn->get_owner(), sgn_r) || !bv_th->get_fixed_value(e_sig->get_owner(), sig_r) || !bv_th->get_fixed_value(e_exp->get_owner(), exp_r)) { - NOT_IMPLEMENTED_YET(); + UNREACHABLE(); } else { TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " @@ -362,23 +400,35 @@ namespace smt { void theory_fpa::assign_eh(bool_var v, bool is_true) { TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << ")\n";); - UNREACHABLE(); + /* CMW: okay to ignore? */ } void theory_fpa::relevant_eh(app * n) { + TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, get_manager()) << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); float_util & fu = m_converter.fu(); - if (ctx.e_internalized(n)) { + bv_util & bu = m_converter.bu(); + + if (m.is_bool(n)) { + bool_var v = ctx.get_bool_var(n); + atom * a = get_bv2a(v); + pred_atom * pa = static_cast(a); + ctx.mark_as_relevant(pa->m_def); + ctx.mk_th_axiom(get_id(), pa->m_var, ~pa->m_def); + ctx.mk_th_axiom(get_id(), ~pa->m_var, pa->m_def); + } + else if (ctx.e_internalized(n)) { SASSERT(m_trans_map.contains(n)); expr * ex; proof * px; m_trans_map.get(n, ex, px); + sort * n_srt = m.get_sort(n); - if (fu.is_rm(m.get_sort(n))) { - ctx.mark_as_relevant(ex); + if (fu.is_rm(n_srt)) { + ctx.mark_as_relevant(ex); } - else { + else if (fu.is_float(n_srt)) { expr * bv_sgn, *bv_sig, *bv_exp; split_triple(ex, bv_sgn, bv_sig, bv_exp); @@ -386,8 +436,21 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } + else if (n->get_decl()->get_decl_kind() == OP_TO_IEEE_BV) { + literal l = mk_eq(n, ex, false); + ctx.mark_as_relevant(l); + ctx.mk_th_axiom(get_id(), 1, &l); + } + else + NOT_IMPLEMENTED_YET(); } else UNREACHABLE(); } + + void theory_fpa::reset_eh() { + pop_scope_eh(m_trail_stack.get_num_scopes()); + m_bool_var2atom.reset(); + theory::reset_eh(); + } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index ea09df27b..2039e34df 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -20,17 +20,40 @@ Revision History: #define _THEORY_FPA_H_ #include"smt_theory.h" +#include"trail.h" #include"fpa2bv_converter.h" #include"fpa2bv_rewriter.h" namespace smt { + class theory_fpa : public theory { typedef trail_stack th_trail_stack; - + + public: + class atom { + public: + virtual ~atom() {} + }; + + struct pred_atom : public atom { + literal m_var; + literal m_def; + pred_atom(literal v, literal d) : m_var(v), m_def(d) {} + virtual ~pred_atom() {} + }; + + typedef ptr_vector bool_var2atom; + void insert_bv2a(bool_var bv, pred_atom * a) { m_bool_var2atom.setx(bv, a, 0); } + void erase_bv2a(bool_var bv) { m_bool_var2atom[bv] = 0; } + pred_atom * get_bv2a(bool_var bv) const { return m_bool_var2atom.get(bv, 0); } + region & get_region() { return m_trail_stack.get_region(); } + + protected: fpa2bv_converter m_converter; fpa2bv_rewriter m_rw; expr_map m_trans_map; th_trail_stack m_trail_stack; + bool_var2atom m_bool_var2atom; virtual final_check_status final_check_eh() { return FC_DONE; } virtual bool internalize_atom(app * atom, bool gate_ctx); @@ -40,6 +63,7 @@ namespace smt { virtual void new_diseq_eh(theory_var, theory_var); virtual void push_scope_eh(); virtual void pop_scope_eh(unsigned num_scopes); + virtual void reset_eh(); virtual theory* mk_fresh(context*) { return alloc(theory_fpa, get_manager()); } virtual char const * get_name() const { return "fpa"; } @@ -47,6 +71,7 @@ namespace smt { void assign_eh(bool_var v, bool is_true); virtual void relevant_eh(app * n); + public: theory_fpa(ast_manager& m); virtual ~theory_fpa(); @@ -67,4 +92,3 @@ namespace smt { }; #endif /* _THEORY_FPA_H_ */ - From 2cd4edf1a23a3978851c83338f01d0ea775dabb6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 31 Jul 2014 17:56:18 +0100 Subject: [PATCH 050/646] FPA API bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.h | 2 +- src/smt/theory_fpa.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 4dedbc2e2..2b6b7fd64 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -221,7 +221,7 @@ public: app * mk_value(mpf const & v) { return m_plugin->mk_value(v); } bool is_value(expr * n) { return m_plugin->is_value(n); } - bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); } + bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); } bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); } app * mk_pzero(unsigned ebits, unsigned sbits); diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index f44447b8f..9c03cb76c 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -122,7 +122,7 @@ namespace smt { m_rw(term, t); - if (m_converter.is_rm_sort(term_sort)) { + if (m_converter.is_rm(term_sort)) { SASSERT(is_app(t)); expr_ref bv_rm(m); proof_ref bv_pr(m); @@ -183,7 +183,7 @@ namespace smt { m_rw(owner, converted); m_trans_map.insert(owner, converted, 0); - if (m_converter.is_rm_sort(m.get_sort(owner))) { + if (m_converter.is_rm(m.get_sort(owner))) { mk_eq_bv_const(converted); } else { From 8b40d4a7357cbe13a3aaefb1b848a7b710cdd30d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Aug 2014 17:00:04 +0100 Subject: [PATCH 051/646] FPA theory bug fixes. Also removed unnecessary intermediate variables. Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 73 ++++++++++++++++++++++++++++++++--------- src/api/api_numeral.cpp | 2 +- src/smt/theory_fpa.cpp | 68 +++++++++++++++----------------------- src/smt/theory_fpa.h | 2 +- 4 files changed, 85 insertions(+), 60 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 578c563b7..6eb7a2e11 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2599,11 +2599,11 @@ void fpa_example() { Z3_config cfg; Z3_context ctx; Z3_sort double_sort, rm_sort; - Z3_symbol symbol_rm, symbol_x, symbol_y; - Z3_ast rm, x, y, n, c; - - printf("\nFPA-example\n"); - LOG_MSG("FPA-example"); + Z3_symbol symbol_rm, symbol_x, symbol_y, symbol_q; + Z3_ast rm, x, y, n, q, c1, c2, c3, c4, c5, c6; + + printf("\nfpa_example\n"); + LOG_MSG("fpa_example"); cfg = Z3_mk_config(); ctx = Z3_mk_context(cfg); @@ -2620,16 +2620,32 @@ void fpa_example() { y = Z3_mk_const(ctx, symbol_y, double_sort); n = Z3_mk_fpa_double(ctx, 42.0, double_sort); - Z3_symbol q_s = Z3_mk_string_symbol(ctx, "q"); - Z3_ast q = Z3_mk_const(ctx, q_s, double_sort); - c = Z3_mk_eq(ctx, q, Z3_mk_fpa_add(ctx, rm, x, y)); + symbol_q = Z3_mk_string_symbol(ctx, "q"); + q = Z3_mk_const(ctx, symbol_q, double_sort); + c1 = Z3_mk_eq(ctx, q, Z3_mk_fpa_add(ctx, rm, x, y)); - Z3_ast args[2] = { c, Z3_mk_eq(ctx, q, n) }; - c = Z3_mk_and(ctx, 2, (Z3_ast*)&args); + Z3_ast args[2] = { c1, Z3_mk_eq(ctx, q, n) }; + c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args); - printf("c = %s\n", Z3_ast_to_string(ctx, c)); + Z3_ast args2[2] = { c2, Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_round_nearest_ties_to_away(ctx))) }; + c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2); - Z3_assert_cnstr(ctx, c); + Z3_ast and_args[3] = { + Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)), + Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)), + Z3_mk_not(ctx, Z3_mk_fpa_is_inf(ctx, y)) }; + Z3_ast args3[2] = { c3, Z3_mk_and(ctx, 3, and_args) }; + c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3); + + + Z3_assert_cnstr(ctx, c4); + Z3_push(ctx); + + // c5 := (IEEEBV(x) == 7.0). + c5 = Z3_mk_eq(ctx, Z3_mk_fpa_to_ieee_bv(ctx, x), + Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64))); + + Z3_assert_cnstr(ctx, c5); Z3_model m = 0; Z3_lbool result = Z3_check_and_get_model(ctx, &m); @@ -2639,19 +2655,44 @@ void fpa_example() { break; case Z3_L_UNDEF: printf("unknown\n"); + printf("potential model:\n%s\n", Z3_model_to_string(ctx, m)); + break; + case Z3_L_TRUE: + printf("sat\n%s\n", Z3_model_to_string(ctx, m)); + Z3_del_model(ctx, m); + break; + } + + Z3_pop(ctx, 1); + + // c6 := (IEEEBV(x) == 28.0). + c6 = Z3_mk_eq(ctx, Z3_mk_fpa_to_ieee_bv(ctx, x), + Z3_mk_numeral(ctx, "4628574517030027264", Z3_mk_bv_sort(ctx, 64))); + + Z3_assert_cnstr(ctx, c6); + Z3_push(ctx); + + m = 0; + result = Z3_check_and_get_model(ctx, &m); + switch (result) { + case Z3_L_FALSE: + printf("unsat\n"); + break; + case Z3_L_UNDEF: + printf("unknown\n"); + printf("potential model:\n%s\n", Z3_model_to_string(ctx, m)); break; case Z3_L_TRUE: - printf("sat\n%s\n", Z3_model_to_string(ctx, m)); + printf("sat\n%s\n", Z3_model_to_string(ctx, m)); + Z3_del_model(ctx, m); break; } - if (m) - Z3_del_model(ctx, m); + Z3_pop(ctx, 1); Z3_del_context(ctx); } - /*@}*/ /*@}*/ diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 740fef2ac..d2829e990 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -193,7 +193,7 @@ extern "C" { // floats are separated from all others to avoid huge rationals. float_util & fu = mk_c(c)->float_util(); scoped_mpf tmp(fu.fm()); - if (mk_c(c)->float_util().is_numeral(to_expr(a), tmp)) { + if (mk_c(c)->float_util().is_value(to_expr(a), tmp)) { return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); } else { diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 9c03cb76c..a228ec4a5 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -60,15 +60,6 @@ namespace smt { ctx.mark_as_relevant(l); } - app_ref theory_fpa::mk_eq_bv_const(expr_ref const & e) { - ast_manager & m = get_manager(); - context & ctx = get_context(); - app_ref bv_const(m); - bv_const = m.mk_fresh_const(0, m.get_sort(e)); - mk_bv_eq(bv_const, e); - return bv_const; - } - bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); @@ -128,7 +119,7 @@ namespace smt { proof_ref bv_pr(m); simp(t, bv_rm, bv_pr); - bv_term = mk_eq_bv_const(bv_rm); + bv_term = bv_rm; } else if (m_converter.is_float(term_sort)) { SASSERT(is_app(t) && to_app(t)->get_num_args() == 3); @@ -139,19 +130,13 @@ namespace smt { simp(a->get_arg(1), sig, pr_sig); simp(a->get_arg(2), exp, pr_exp); - app_ref bv_v_sgn = mk_eq_bv_const(sgn); - app_ref bv_v_sig = mk_eq_bv_const(sig); - app_ref bv_v_exp = mk_eq_bv_const(exp); - - m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, bv_term); + m_converter.mk_triple(sgn, sig, exp, bv_term); } else if (term->get_decl_kind() == OP_TO_IEEE_BV) { SASSERT(is_app(t)); expr_ref bv_e(m); proof_ref bv_pr(m); - simp(t, bv_e, bv_pr); - - bv_term = mk_eq_bv_const(bv_e); + simp(t, bv_term, bv_pr); } else NOT_IMPLEMENTED_YET(); @@ -159,11 +144,12 @@ namespace smt { TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(bv_term, get_manager()) << "\n";); SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, bv_term, 0); + m_trans_map.insert(term, bv_term, 0); enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true); theory_var v = mk_var(e); ctx.attach_th_var(e, this, v); + m_tvars.push_back(v); TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); SASSERT(e->get_th_var(get_id()) != null_theory_var); return v != null_theory_var; @@ -180,23 +166,14 @@ namespace smt { theory_var v = mk_var(n); ctx.attach_th_var(n, this, v); + m_tvars.push_back(v); m_rw(owner, converted); m_trans_map.insert(owner, converted, 0); - if (m_converter.is_rm(m.get_sort(owner))) { - mk_eq_bv_const(converted); - } - else { - app * a = to_app(converted); - expr_ref sgn(m), sig(m), exp(m); - proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); - simp(a->get_arg(0), sgn, pr_sgn); - simp(a->get_arg(1), sig, pr_sig); - simp(a->get_arg(2), exp, pr_exp); - - mk_eq_bv_const(sgn); - mk_eq_bv_const(sig); - mk_eq_bv_const(exp); + sort * owner_sort = m.get_sort(owner); + if (m_converter.is_rm(owner_sort)) { + bv_util & bu = m_converter.bu(); + bu.mk_ule(converted, bu.mk_numeral(4, bu.get_bv_size(converted))); } TRACE("t_fpa", tout << "new theory var (const): " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); @@ -215,7 +192,7 @@ namespace smt { m_trans_map.get(ax, ex, px); m_trans_map.get(ay, ey, py); - if (m_converter.fu().is_float(m.get_sort(get_enode(x)->get_owner()))) { + if (m_converter.fu().is_float(get_enode(x)->get_owner())) { expr * sgn_x, *sig_x, *exp_x; expr * sgn_y, *sig_y, *exp_y; split_triple(ex, sgn_x, sig_x, exp_x); @@ -225,7 +202,7 @@ namespace smt { mk_bv_eq(sig_x, sig_y); mk_bv_eq(exp_x, exp_y); } - else if (m_converter.fu().is_rm(m.get_sort(get_enode(x)->get_owner()))) { + else if (m_converter.fu().is_rm(get_enode(x)->get_owner())) { mk_bv_eq(ex, ey); } else @@ -273,7 +250,13 @@ namespace smt { } void theory_fpa::pop_scope_eh(unsigned num_scopes) { + TRACE("bv", tout << num_scopes << "\n";); m_trail_stack.pop_scope(num_scopes); + unsigned num_old_vars = get_old_num_vars(num_scopes); + for (unsigned i = num_old_vars; i < get_num_vars(); i++) { + m_trans_map.erase(get_enode(m_tvars[i])->get_owner()); + } + m_tvars.shrink(num_old_vars); theory::pop_scope_eh(num_scopes); } @@ -405,6 +388,7 @@ namespace smt { void theory_fpa::assign_eh(bool_var v, bool is_true) { TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << ")\n";); /* CMW: okay to ignore? */ + theory::assign_eh(v, is_true); } void theory_fpa::relevant_eh(app * n) { @@ -441,14 +425,10 @@ namespace smt { ctx.mark_as_relevant(bv_exp); } else if (n->get_decl()->get_decl_kind() == OP_TO_IEEE_BV) { - //literal l = mk_eq(n, ex, false); - //ctx.mark_as_relevant(l); - //ctx.mk_th_axiom(get_id(), 1, &l); - + expr_ref eq(m); app * ex_a = to_app(ex); if (n->get_id() > ex_a->get_id()) - std::swap(n, ex_a); - expr_ref eq(m); + std::swap(n, ex_a); eq = m.mk_eq(n, ex_a); ctx.internalize(eq, false); literal l = ctx.get_literal(eq); @@ -464,7 +444,11 @@ namespace smt { void theory_fpa::reset_eh() { pop_scope_eh(m_trail_stack.get_num_scopes()); - m_bool_var2atom.reset(); + m_rw.reset(); + m_trans_map.reset(); + m_bool_var2atom.reset(); + m_temporaries.reset(); + m_tvars.reset(); theory::reset_eh(); } diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 998cc17e8..5c0d2acca 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -55,6 +55,7 @@ namespace smt { th_trail_stack m_trail_stack; bool_var2atom m_bool_var2atom; enode_vector m_temporaries; + int_vector m_tvars; virtual final_check_status final_check_eh() { return FC_DONE; } virtual bool internalize_atom(app * atom, bool gate_ctx); @@ -88,7 +89,6 @@ namespace smt { } void mk_bv_eq(expr * x, expr * y); - app_ref mk_eq_bv_const(expr_ref const & e); }; }; From 4610acca0f4e7761be73f7a6851f3169c9a49ff2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Aug 2014 17:10:56 +0100 Subject: [PATCH 052/646] FPA: reduced number of temporary variables. Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index d6f362902..07f0cdc8a 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -136,12 +136,13 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { unsigned sbits = m_util.get_sbits(srt); expr_ref sgn(m), s(m), e(m); - sort_ref s_sgn(m), s_sig(m), s_exp(m); - s_sgn = m_bv_util.mk_sort(1); - s_sig = m_bv_util.mk_sort(sbits-1); - s_exp = m_bv_util.mk_sort(ebits); #ifdef Z3DEBUG + sort_ref s_sgn(m), s_sig(m), s_exp(m); + s_sgn = m_bv_util.mk_sort(1); + s_sig = m_bv_util.mk_sort(sbits - 1); + s_exp = m_bv_util.mk_sort(ebits); + std::string p("fpa2bv"); std::string name = f->get_name().str(); @@ -149,9 +150,17 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { s = m.mk_fresh_const((p + "_sig_" + name).c_str(), s_sig); e = m.mk_fresh_const((p + "_exp_" + name).c_str(), s_exp); #else - sgn = m.mk_fresh_const(0, s_sgn); - s = m.mk_fresh_const(0, s_sig); - e = m.mk_fresh_const(0, s_exp); + expr_ref bv(m); + unsigned bv_sz = 1 + ebits + (sbits - 1); + bv = m.mk_fresh_const(0, m_bv_util.mk_sort(bv_sz)); + + sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv); + e = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv); + s = m_bv_util.mk_extract(sbits - 2, 0, bv); + + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(s) == sbits-1); + SASSERT(m_bv_util.get_bv_size(e) == ebits); #endif mk_triple(sgn, s, e, result); From 606eeb658e0ed20a97dfe29408c854867f09ba0f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 13 Aug 2014 23:05:45 +0100 Subject: [PATCH 053/646] bugfix for solver parameters that did not get passed on (codeplex discussion 560796). Thanks to user xor88 for reporting this issue. Signed-off-by: Christoph M. Wintersteiger --- src/api/api_solver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index ac30a0c21..c8b1723f1 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -40,6 +40,7 @@ extern "C" { params_ref p = s->m_params; mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled); s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic); + s->m_solver->updt_params(p); } static void init_solver(Z3_context c, Z3_solver s) { From 6b37b847a0e3717fe718e97e0b2f9d49320edc91 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 11 Sep 2014 00:27:37 +0100 Subject: [PATCH 054/646] merge fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tactic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 7ddf1a53d..9bbed20bb 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -79,10 +79,10 @@ public: } virtual void cleanup() { - imp * d = alloc(imp, m, m_params, m_stats); + sls_engine * d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - std::swap(d, m_imp); + std::swap(d, m_engine); } dealloc(d); } From 7af410e6d668674fab67019941995dad603fa736 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 18 Oct 2014 13:42:28 +0100 Subject: [PATCH 055/646] FPA updates and bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 12 +- src/api/z3_fpa.h | 33 ++- src/ast/float_decl_plugin.cpp | 326 ++++++++++++++++------------ src/ast/float_decl_plugin.h | 42 ++-- src/ast/fpa/fpa2bv_converter.cpp | 14 +- src/ast/fpa/fpa2bv_converter.h | 3 +- src/ast/fpa/fpa2bv_rewriter.h | 14 +- src/ast/rewriter/float_rewriter.cpp | 37 ++-- src/ast/rewriter/float_rewriter.h | 11 +- src/smt/theory_fpa.cpp | 4 +- 10 files changed, 308 insertions(+), 188 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 374e3d344..8bcc4c1af 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -121,6 +121,16 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_zero(Z3_context c, Z3_sort s, Z3_bool negative) { + Z3_TRY; + LOG_Z3_mk_fpa_inf(c, s, negative); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_nzero(to_sort(s)) : ctx->float_util().mk_pzero(to_sort(s))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_double(Z3_context c, double v, Z3_sort ty) { Z3_TRY; LOG_Z3_mk_fpa_double(c, v, ty); @@ -361,7 +371,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ieee_bv(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_to_ieee_bv(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_float_to_ieee_bv(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 93cfb8dd5..265657bf4 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -109,12 +109,25 @@ extern "C" { \param s target sort \param negative indicates whether the result should be negative - When \c negative is true, -Inf will be generated instead of +Inf. + When \c negative is true, -oo will be generated instead of +oo. def_API('Z3_mk_fpa_inf', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) */ Z3_ast Z3_API Z3_mk_fpa_inf(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); + /** + \brief Create a floating point zero of sort s. + + \param c logical context. + \param s target sort + \param negative indicates whether the result should be negative + + When \c negative is true, -zero will be generated instead of +zero. + + def_API('Z3_mk_fpa_zero', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) + */ + Z3_ast Z3_API Z3_mk_fpa_zero(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); + /** \brief Create a numeral of floating point sort. @@ -133,6 +146,24 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); + /** + \brief Create a numeral of floating point sort. + + This function can be use to create numerals that fit in a double value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. + + \params c logical context. + \params v value. + \params ty sort. + + ty must be a floating point sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_fpa_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); + /** \brief Floating-point absolute value diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index df26422c8..c31c0b89b 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -40,11 +40,10 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) { SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_int_sort); - if (m_manager->has_plugin(symbol("bv"))) { - // bv plugin is optional, so m_bv_plugin may be 0 - m_bv_fid = m_manager->mk_family_id("bv"); - m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); - } + // BV is not optional anymore. + SASSERT(m_manager->has_plugin(symbol("bv"))); + m_bv_fid = m_manager->mk_family_id("bv"); + m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); } float_decl_plugin::~float_decl_plugin() { @@ -103,6 +102,18 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) { m_fm.mk_nan(ebits, sbits, val); return true; } + else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_ZERO)) { + unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); + unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); + m_fm.mk_pzero(ebits, sbits, val); + return true; + } + else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_ZERO)) { + unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); + unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); + m_fm.mk_nzero(ebits, sbits, val); + return true; + } return false; } @@ -156,7 +167,7 @@ sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { p1, p2 }; sort_size sz; sz = sort_size::mk_very_big(); // TODO: refine - return m_manager->mk_sort(symbol("FP"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps)); + return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps)); } sort * float_decl_plugin::mk_rm_sort() { @@ -176,6 +187,14 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete return mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); case ROUNDING_MODE_SORT: return mk_rm_sort(); + case FLOAT16_SORT: + return mk_float_sort(5, 11); + case FLOAT32_SORT: + return mk_float_sort(8, 24); + case FLOAT64_SORT: + return mk_float_sort(11, 53); + case FLOAT128_SORT: + return mk_float_sort(15, 133); default: m_manager->raise_exception("unknown floating point theory sort"); return 0; @@ -229,17 +248,18 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par unsigned ebits = s->get_parameter(0).get_int(); unsigned sbits = s->get_parameter(1).get_int(); scoped_mpf val(m_fm); - if (k == OP_FLOAT_NAN) { - m_fm.mk_nan(ebits, sbits, val); + + switch (k) + { + case OP_FLOAT_NAN: m_fm.mk_nan(ebits, sbits, val); SASSERT(m_fm.is_nan(val)); + break; + case OP_FLOAT_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break; + case OP_FLOAT_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break; + case OP_FLOAT_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break; + case OP_FLOAT_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break; } - else if (k == OP_FLOAT_MINUS_INF) { - m_fm.mk_ninf(ebits, sbits, val); - } - else { - SASSERT(k == OP_FLOAT_PLUS_INF); - m_fm.mk_pinf(ebits, sbits, val); - } + return mk_value_decl(val); } @@ -251,11 +271,11 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_EQ: name = "=="; break; - case OP_FLOAT_LT: name = "<"; break; - case OP_FLOAT_GT: name = ">"; break; - case OP_FLOAT_LE: name = "<="; break; - case OP_FLOAT_GE: name = ">="; break; + case OP_FLOAT_EQ: name = "fp.eq"; break; + case OP_FLOAT_LT: name = "fp.lt"; break; + case OP_FLOAT_GT: name = "fp.gt"; break; + case OP_FLOAT_LE: name = "fp.lte"; break; + case OP_FLOAT_GE: name = "fp.gte"; break; default: UNREACHABLE(); break; @@ -273,14 +293,15 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_IS_ZERO: name = "isZero"; break; - case OP_FLOAT_IS_NZERO: name = "isNZero"; break; - case OP_FLOAT_IS_PZERO: name = "isPZero"; break; - case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break; - case OP_FLOAT_IS_NAN: name = "isNaN"; break; - case OP_FLOAT_IS_INF: name = "isInfinite"; break; - case OP_FLOAT_IS_NORMAL: name = "isNormal"; break; - case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal"; break; + case OP_FLOAT_IS_ZERO: name = "fp.isZero"; break; + case OP_FLOAT_IS_NZERO: name = "fp.isNZero"; break; + case OP_FLOAT_IS_PZERO: name = "fp.isPZero"; break; + case OP_FLOAT_IS_NEGATIVE: name = "fp.isNegative"; break; + case OP_FLOAT_IS_POSITIVE: name = "fp.isPositive"; break; + case OP_FLOAT_IS_NAN: name = "fp.isNaN"; break; + case OP_FLOAT_IS_INF: name = "fp.isInfinite"; break; + case OP_FLOAT_IS_NORMAL: name = "fp.isNormal"; break; + case OP_FLOAT_IS_SUBNORMAL: name = "fp.isSubnormal"; break; default: UNREACHABLE(); break; @@ -296,8 +317,8 @@ func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameter m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_ABS: name = "abs"; break; - case OP_FLOAT_UMINUS: name = "-"; break; + case OP_FLOAT_ABS: name = "fp.abs"; break; + case OP_FLOAT_NEG: name = "fp.neg"; break; default: UNREACHABLE(); break; @@ -313,9 +334,9 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_REM: name = "remainder"; break; - case OP_FLOAT_MIN: name = "min"; break; - case OP_FLOAT_MAX: name = "max"; break; + case OP_FLOAT_REM: name = "fp.rem"; break; + case OP_FLOAT_MIN: name = "fp.min"; break; + case OP_FLOAT_MAX: name = "fp.max"; break; default: UNREACHABLE(); break; @@ -331,10 +352,10 @@ func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_param m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_ADD: name = "+"; break; - case OP_FLOAT_SUB: name = "-"; break; - case OP_FLOAT_MUL: name = "*"; break; - case OP_FLOAT_DIV: name = "/"; break; + case OP_FLOAT_ADD: name = "fp.add"; break; + case OP_FLOAT_SUB: name = "fp.sub"; break; + case OP_FLOAT_MUL: name = "fp.mul"; break; + case OP_FLOAT_DIV: name = "fp.div"; break; default: UNREACHABLE(); break; @@ -350,8 +371,8 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame m_manager->raise_exception("sort mismatch"); symbol name; switch (k) { - case OP_FLOAT_SQRT: name = "squareRoot"; break; - case OP_FLOAT_ROUND_TO_INTEGRAL: name = "roundToIntegral"; break; + case OP_FLOAT_SQRT: name = "fp.sqrt"; break; + case OP_FLOAT_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break; default: UNREACHABLE(); break; @@ -359,13 +380,13 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 4) m_manager->raise_exception("invalid number of arguments to fused_ma operator"); if (!is_rm_sort(domain[0]) || domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1])) m_manager->raise_exception("sort mismatch"); - symbol name("fusedMA"); + symbol name("fp.fma"); return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } @@ -375,12 +396,13 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, is_sort_of(domain[0], m_bv_fid, BV_SORT) && is_sort_of(domain[1], m_bv_fid, BV_SORT) && is_sort_of(domain[2], m_bv_fid, BV_SORT)) { - // When the bv_decl_plugin is installed, then we know how to convert 3 bit-vectors into a float! + // 3 BVs -> 1 FP sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1); - symbol name("asFloat"); + symbol name("fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) { + // 1 BV -> 1 FP if (num_parameters != 2) m_manager->raise_exception("invalid number of parameters to to_fp"); if (!parameters[0].is_int() || !parameters[1].is_int()) @@ -389,28 +411,56 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, int sbits = parameters[1].get_int(); sort * fp = mk_float_sort(ebits, sbits); - symbol name("asFloat"); + symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } - else { - // .. Otherwise we only know how to convert rationals/reals. - if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) - m_manager->raise_exception("expecting two integer parameters to asFloat"); - if (arity != 2 && arity != 3) - m_manager->raise_exception("invalid number of arguments to asFloat operator"); - if (arity == 3 && domain[2] != m_int_sort) - m_manager->raise_exception("sort mismatch"); + else if (m_bv_plugin && arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_bv_fid, BV_SORT)) { + // Rounding + 1 BV -> 1 FP + if (num_parameters != 2) + m_manager->raise_exception("invalid number of parameters to to_fp"); + if (!parameters[0].is_int() || !parameters[1].is_int()) + m_manager->raise_exception("invalid parameter type to to_fp"); + int ebits = parameters[0].get_int(); + int sbits = parameters[1].get_int(); + + sort * fp = mk_float_sort(ebits, sbits); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else if (arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_family_id, FLOAT_SORT)) { + // Rounding + 1 FP -> 1 FP + if (num_parameters != 2) + m_manager->raise_exception("invalid number of parameters to to_fp"); + if (!parameters[0].is_int() || !parameters[1].is_int()) + m_manager->raise_exception("invalid parameter type to to_fp"); + int ebits = parameters[0].get_int(); + int sbits = parameters[1].get_int(); if (!is_rm_sort(domain[0]) || - !(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT))) + !is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + m_manager->raise_exception("sort mismatch"); + } + else { + // 1 Real -> 1 FP + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to to_fp"); + if (arity != 2 && arity != 3) + m_manager->raise_exception("invalid number of arguments to to_fp operator"); + if (arity == 3 && domain[2] != m_int_sort) + m_manager->raise_exception("sort mismatch"); + if (domain[1] != m_real_sort) m_manager->raise_exception("sort mismatch"); sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); - symbol name("asFloat"); + symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } } -func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (!m_bv_plugin) m_manager->raise_exception("asIEEEBV unsupported; use a logic with BV support"); @@ -443,7 +493,7 @@ func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (!m_bv_plugin) m_manager->raise_exception("to_fp_unsigned unsupported; use a logic with BV support"); @@ -455,15 +505,10 @@ func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_param m_manager->raise_exception("sort mismtach"); sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); - symbol name("to_fp_unsigned"); + symbol name("fp.t_ubv"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - NOT_IMPLEMENTED_YET(); -} - func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { NOT_IMPLEMENTED_YET(); @@ -498,14 +543,15 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_FLOAT_IS_ZERO: case OP_FLOAT_IS_NZERO: case OP_FLOAT_IS_PZERO: - case OP_FLOAT_IS_SIGN_MINUS: + case OP_FLOAT_IS_NEGATIVE: + case OP_FLOAT_IS_POSITIVE: case OP_FLOAT_IS_NAN: case OP_FLOAT_IS_INF: case OP_FLOAT_IS_NORMAL: case OP_FLOAT_IS_SUBNORMAL: return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_ABS: - case OP_FLOAT_UMINUS: + case OP_FLOAT_NEG: return mk_unary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_REM: case OP_FLOAT_MIN: @@ -517,20 +563,18 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_SUB: if (arity == 1) - return mk_unary_decl(OP_FLOAT_UMINUS, num_parameters, parameters, arity, domain, range); + return mk_unary_decl(OP_FLOAT_NEG, num_parameters, parameters, arity, domain, range); else return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_SQRT: case OP_FLOAT_ROUND_TO_INTEGRAL: return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_FUSED_MA: - return mk_fused_ma(k, num_parameters, parameters, arity, domain, range); - case OP_TO_IEEE_BV: - return mk_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_FMA: + return mk_fma(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_IEEE_BV: + return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_FP: return mk_from3bv(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_FP_UNSIGNED: - return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_UBV: return mk_to_ubv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_SBV: @@ -544,8 +588,11 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters } void float_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { - op_names.push_back(builtin_name("plusInfinity", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("minusInfinity", OP_FLOAT_MINUS_INF)); + // These are the operators from the final draft of the SMT FloatingPoint standard + op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF)); + op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF)); + op_names.push_back(builtin_name("+zero", OP_FLOAT_PLUS_ZERO)); + op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO)); op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN)); op_names.push_back(builtin_name("roundNearestTiesToEven", OP_RM_NEAREST_TIES_TO_EVEN)); @@ -553,22 +600,66 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("roundTowardPositive", OP_RM_TOWARD_POSITIVE)); op_names.push_back(builtin_name("roundTowardNegative", OP_RM_TOWARD_NEGATIVE)); op_names.push_back(builtin_name("roundTowardZero", OP_RM_TOWARD_ZERO)); - - op_names.push_back(builtin_name("+", OP_FLOAT_ADD)); - op_names.push_back(builtin_name("-", OP_FLOAT_SUB)); - op_names.push_back(builtin_name("/", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("*", OP_FLOAT_MUL)); - op_names.push_back(builtin_name("abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("remainder", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fusedMA", OP_FLOAT_FUSED_MA)); - op_names.push_back(builtin_name("squareRoot", OP_FLOAT_SQRT)); - op_names.push_back(builtin_name("roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); + op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN)); + op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY)); + op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE)); + op_names.push_back(builtin_name("RTN", OP_RM_TOWARD_NEGATIVE)); + op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO)); + + op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS)); + op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG)); + op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD)); + op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB)); + op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL)); + op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV)); + op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FMA)); + op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT)); + op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM)); + op_names.push_back(builtin_name("fp.roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); + op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN)); + op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX)); + op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE)); + op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT)); + op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE)); + op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT)); + op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ)); + + op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL)); + op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL)); + op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO)); + op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF)); + op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN)); + op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE)); + op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE)); + op_names.push_back(builtin_name("to_fp", OP_FLOAT_FP)); + + if (m_bv_plugin) { + op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); + op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); + op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); + } + + // We also support the names of operators in older drafts. + op_names.push_back(builtin_name("plusInfinity", OP_FLOAT_PLUS_INF)); + op_names.push_back(builtin_name("minusInfinity", OP_FLOAT_MINUS_INF)); + + op_names.push_back(builtin_name("+", OP_FLOAT_ADD)); + op_names.push_back(builtin_name("-", OP_FLOAT_SUB)); + op_names.push_back(builtin_name("/", OP_FLOAT_DIV)); + op_names.push_back(builtin_name("*", OP_FLOAT_MUL)); + + op_names.push_back(builtin_name("abs", OP_FLOAT_ABS)); + op_names.push_back(builtin_name("remainder", OP_FLOAT_REM)); + op_names.push_back(builtin_name("fusedMA", OP_FLOAT_FMA)); + op_names.push_back(builtin_name("squareRoot", OP_FLOAT_SQRT)); + op_names.push_back(builtin_name("roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); + op_names.push_back(builtin_name("==", OP_FLOAT_EQ)); - - op_names.push_back(builtin_name("<", OP_FLOAT_LT)); - op_names.push_back(builtin_name(">", OP_FLOAT_GT)); + + op_names.push_back(builtin_name("<", OP_FLOAT_LT)); + op_names.push_back(builtin_name(">", OP_FLOAT_GT)); op_names.push_back(builtin_name("<=", OP_FLOAT_LE)); op_names.push_back(builtin_name(">=", OP_FLOAT_GE)); @@ -579,65 +670,30 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO)); op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL)); op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL)); - op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS)); + op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_NEGATIVE)); - op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); - op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); + // Disabled min/max, clashes with user-defined min/max functions + // op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); + // op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); - op_names.push_back(builtin_name("asFloat", OP_TO_FLOAT)); - - if (m_bv_plugin) - op_names.push_back(builtin_name("asIEEEBV", OP_TO_IEEE_BV)); - - // These are the operators from the final draft of the SMT FloatingPoints standard - op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF)); - - op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN)); - op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY)); - op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE)); - op_names.push_back(builtin_name("RTN", OP_RM_TOWARD_NEGATIVE)); - op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO)); - - op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("fp.neg", OP_FLOAT_UMINUS)); - op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD)); - op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB)); - op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL)); - op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FUSED_MA)); - op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT)); - op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ)); - op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE)); - op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT)); - op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE)); - op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT)); - op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL)); - op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL)); - op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO)); - op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF)); - op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN)); - op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN)); - op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX)); op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); - if (m_bv_plugin) { - op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); - op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); - op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); - op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - } - - // op_names.push_back(builtin_name("fp.toReal", ?)); + if (m_bv_plugin) + op_names.push_back(builtin_name("asIEEEBV", OP_FLOAT_TO_IEEE_BV)); } void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { + // Old draft sort names. sort_names.push_back(builtin_name("FP", FLOAT_SORT)); sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT)); - // In the SMT FPA final draft, FP is called FloatingPoint + // In the final draft, FP is called FloatingPoint ... sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); + // ... and it supports three common FloatingPoint sorts + sort_names.push_back(builtin_name("Float16", FLOAT16_SORT)); + sort_names.push_back(builtin_name("Float32", FLOAT32_SORT)); + sort_names.push_back(builtin_name("Float64", FLOAT64_SORT)); + sort_names.push_back(builtin_name("Float128", FLOAT128_SORT)); } expr * float_decl_plugin::get_some_value(sort * s) { @@ -661,6 +717,8 @@ bool float_decl_plugin::is_value(app * e) const { case OP_FLOAT_VALUE: case OP_FLOAT_PLUS_INF: case OP_FLOAT_MINUS_INF: + case OP_FLOAT_PLUS_ZERO: + case OP_FLOAT_MINUS_ZERO: case OP_FLOAT_NAN: return true; case OP_TO_FLOAT: diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 2b6b7fd64..8a77b63cc 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -27,7 +27,11 @@ Revision History: enum float_sort_kind { FLOAT_SORT, - ROUNDING_MODE_SORT + ROUNDING_MODE_SORT, + FLOAT16_SORT, + FLOAT32_SORT, + FLOAT64_SORT, + FLOAT128_SORT }; enum float_op_kind { @@ -37,22 +41,23 @@ enum float_op_kind { OP_RM_TOWARD_NEGATIVE, OP_RM_TOWARD_ZERO, - OP_FLOAT_VALUE, OP_FLOAT_PLUS_INF, OP_FLOAT_MINUS_INF, OP_FLOAT_NAN, + OP_FLOAT_PLUS_ZERO, + OP_FLOAT_MINUS_ZERO, OP_FLOAT_ADD, OP_FLOAT_SUB, - OP_FLOAT_UMINUS, + OP_FLOAT_NEG, OP_FLOAT_MUL, OP_FLOAT_DIV, OP_FLOAT_REM, OP_FLOAT_ABS, OP_FLOAT_MIN, OP_FLOAT_MAX, - OP_FLOAT_FUSED_MA, // x*y + z + OP_FLOAT_FMA, // x*y + z OP_FLOAT_SQRT, OP_FLOAT_ROUND_TO_INTEGRAL, @@ -68,13 +73,14 @@ enum float_op_kind { OP_FLOAT_IS_SUBNORMAL, OP_FLOAT_IS_PZERO, OP_FLOAT_IS_NZERO, - OP_FLOAT_IS_SIGN_MINUS, + OP_FLOAT_IS_NEGATIVE, + OP_FLOAT_IS_POSITIVE, OP_TO_FLOAT, - OP_TO_IEEE_BV, + OP_FLOAT_TO_IEEE_BV, OP_FLOAT_FP, - OP_FLOAT_TO_FP_UNSIGNED, + OP_FLOAT_TO_FP, OP_FLOAT_TO_UBV, OP_FLOAT_TO_SBV, OP_FLOAT_TO_REAL, @@ -125,16 +131,14 @@ class float_decl_plugin : public decl_plugin { unsigned arity, sort * const * domain, sort * range); func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -243,7 +247,7 @@ public: app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_DIV, arg1, arg2, arg3); } - app * mk_uminus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_UMINUS, arg1); } + app * mk_uminus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_NEG, arg1); } app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); } app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); } app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); } @@ -252,7 +256,7 @@ public: app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); } app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) { expr * args[4] = { arg1, arg2, arg3, arg4 }; - return m().mk_app(m_fid, OP_FLOAT_FUSED_MA, 4, args); + return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args); } app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_EQ, arg1, arg2); } @@ -268,11 +272,13 @@ public: app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); } app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); } app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); } - app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); } + app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } + app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_POSITIVE, arg1); } + app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } - bool is_uminus(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_UMINUS); } + bool is_uminus(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } - app * mk_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_TO_IEEE_BV, arg1); } + app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } }; #endif diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 07f0cdc8a..8564777f2 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1844,11 +1844,19 @@ void fpa2bv_converter::mk_is_subnormal(func_decl * f, unsigned num, expr * const mk_is_denormal(args[0], result); } -void fpa2bv_converter::mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); mk_is_neg(args[0], result); } +void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 1); + expr_ref t1(m), t2(m); + mk_is_nan(args[0], t1); + mk_is_pos(args[0], t2); + result = m.mk_and(m.mk_not(t1), t2); +} + void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_float", for (unsigned i=0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl; ); @@ -2141,10 +2149,6 @@ void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, e mk_triple(args[0], args[2], args[1], result); } -void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - NOT_IMPLEMENTED_YET(); -} - void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { NOT_IMPLEMENTED_YET(); } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index dcb508ffd..31ff0f7c9 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -114,7 +114,8 @@ public: void mk_is_zero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_nzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_pzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 9a0f2564f..bb2506be0 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -115,17 +115,19 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE; case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE; + case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; + case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE; case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE; case OP_FLOAT_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE; case OP_FLOAT_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE; - case OP_FLOAT_UMINUS: m_conv.mk_uminus(f, num, args, result); return BR_DONE; + case OP_FLOAT_NEG: m_conv.mk_uminus(f, num, args, result); return BR_DONE; case OP_FLOAT_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE; case OP_FLOAT_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE; case OP_FLOAT_REM: m_conv.mk_remainder(f, num, args, result); return BR_DONE; case OP_FLOAT_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE; case OP_FLOAT_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE; case OP_FLOAT_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE; - case OP_FLOAT_FUSED_MA: m_conv.mk_fusedma(f, num, args, result); return BR_DONE; + case OP_FLOAT_FMA: m_conv.mk_fusedma(f, num, args, result); return BR_DONE; case OP_FLOAT_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE; case OP_FLOAT_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE; case OP_FLOAT_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE; @@ -140,11 +142,11 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_SIGN_MINUS: m_conv.mk_is_sign_minus(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE; - case OP_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; - case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; + case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index a4212d579..e44540290 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -36,17 +36,17 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { - case OP_TO_FLOAT: st = mk_to_float(f, num_args, args, result); break; + case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break; case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; - case OP_FLOAT_UMINUS: SASSERT(num_args == 1); st = mk_uminus(args[0], result); break; + case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; - case OP_FLOAT_FUSED_MA: SASSERT(num_args == 4); st = mk_fused_ma(args[0], args[1], args[2], args[3], result); break; + case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break; @@ -62,10 +62,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; - case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break; - case OP_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; - case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; - case OP_FLOAT_TO_FP_UNSIGNED: SASSERT(num_args == 2); st = mk_to_fp_unsigned(args[0], args[1], result); break; + case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; + case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; + case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; @@ -73,7 +73,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c return st; } -br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); SASSERT(f->get_parameter(1).is_int()); @@ -188,7 +188,7 @@ br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_uminus(expr * arg1, expr_ref & result) { +br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) { if (m_util.is_nan(arg1)) { // -nan --> nan result = arg1; @@ -284,7 +284,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { return BR_REWRITE_FULL; } -br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { +br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm()); @@ -480,7 +480,7 @@ br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) { +br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false(); @@ -490,6 +490,17 @@ br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) { return BR_FAILED; } +br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { + scoped_mpf v(m_util.fm()); + if (m_util.is_value(arg1, v)) { + result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true(); + return BR_DONE; + } + + return BR_FAILED; +} + + // This the SMT = br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); @@ -532,10 +543,6 @@ br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result) { - return BR_FAILED; -} - br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } diff --git a/src/ast/rewriter/float_rewriter.h b/src/ast/rewriter/float_rewriter.h index 0f44d227c..16ac766a9 100644 --- a/src/ast/rewriter/float_rewriter.h +++ b/src/ast/rewriter/float_rewriter.h @@ -44,18 +44,17 @@ public: br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_eq_core(expr * arg1, expr * arg2, expr_ref & result); - - br_status mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); + br_status mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); - br_status mk_uminus(expr * arg1, expr_ref & result); + br_status mk_neg(expr * arg1, expr_ref & result); br_status mk_rem(expr * arg1, expr * arg2, expr_ref & result); br_status mk_abs(expr * arg1, expr_ref & result); br_status mk_min(expr * arg1, expr * arg2, expr_ref & result); br_status mk_max(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result); + br_status mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result); br_status mk_sqrt(expr * arg1, expr * arg2, expr_ref & result); br_status mk_round(expr * arg1, expr * arg2, expr_ref & result); br_status mk_float_eq(expr * arg1, expr * arg2, expr_ref & result); @@ -70,10 +69,12 @@ public: br_status mk_is_inf(expr * arg1, expr_ref & result); br_status mk_is_normal(expr * arg1, expr_ref & result); br_status mk_is_subnormal(expr * arg1, expr_ref & result); - br_status mk_is_sign_minus(expr * arg1, expr_ref & result); + br_status mk_is_negative(expr * arg1, expr_ref & result); + br_status mk_is_positive(expr * arg1, expr_ref & result); br_status mk_to_ieee_bv(expr * arg1, expr_ref & result); + br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result); br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result); diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index a228ec4a5..ad353c3d0 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -132,7 +132,7 @@ namespace smt { m_converter.mk_triple(sgn, sig, exp, bv_term); } - else if (term->get_decl_kind() == OP_TO_IEEE_BV) { + else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { SASSERT(is_app(t)); expr_ref bv_e(m); proof_ref bv_pr(m); @@ -424,7 +424,7 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } - else if (n->get_decl()->get_decl_kind() == OP_TO_IEEE_BV) { + else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { expr_ref eq(m); app * ex_a = to_app(ex); if (n->get_id() > ex_a->get_id()) From b3f569574c46837209f8b38b8234924307deed1b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 22 Oct 2014 19:28:54 +0100 Subject: [PATCH 056/646] FPA API consistency Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 57 +++++------------------------------ 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index c31c0b89b..eb53403f6 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -635,61 +635,18 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("to_fp", OP_FLOAT_FP)); - if (m_bv_plugin) { - op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); - op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); - op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - } - - // We also support the names of operators in older drafts. - op_names.push_back(builtin_name("plusInfinity", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("minusInfinity", OP_FLOAT_MINUS_INF)); + op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); + op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); + op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - op_names.push_back(builtin_name("+", OP_FLOAT_ADD)); - op_names.push_back(builtin_name("-", OP_FLOAT_SUB)); - op_names.push_back(builtin_name("/", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("*", OP_FLOAT_MUL)); - - op_names.push_back(builtin_name("abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("remainder", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fusedMA", OP_FLOAT_FMA)); - op_names.push_back(builtin_name("squareRoot", OP_FLOAT_SQRT)); - op_names.push_back(builtin_name("roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); - - op_names.push_back(builtin_name("==", OP_FLOAT_EQ)); - - op_names.push_back(builtin_name("<", OP_FLOAT_LT)); - op_names.push_back(builtin_name(">", OP_FLOAT_GT)); - op_names.push_back(builtin_name("<=", OP_FLOAT_LE)); - op_names.push_back(builtin_name(">=", OP_FLOAT_GE)); - - op_names.push_back(builtin_name("isNaN", OP_FLOAT_IS_NAN)); - op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF)); - op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO)); - op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO)); - op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO)); - op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL)); - op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL)); - op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_NEGATIVE)); - - // Disabled min/max, clashes with user-defined min/max functions - // op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); - // op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); - - op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); - - if (m_bv_plugin) - op_names.push_back(builtin_name("asIEEEBV", OP_FLOAT_TO_IEEE_BV)); + op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); } -void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { - // Old draft sort names. - sort_names.push_back(builtin_name("FP", FLOAT_SORT)); +void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { + sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT)); - // In the final draft, FP is called FloatingPoint ... - sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); - // ... and it supports three common FloatingPoint sorts + // The final theory supports three common FloatingPoint sorts sort_names.push_back(builtin_name("Float16", FLOAT16_SORT)); sort_names.push_back(builtin_name("Float32", FLOAT32_SORT)); sort_names.push_back(builtin_name("Float64", FLOAT64_SORT)); From 60478b7022b31ada3c5cbfb48c58bb37c3cca579 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 22 Oct 2014 19:29:03 +0100 Subject: [PATCH 057/646] FPA API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_rewriter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index bb2506be0..89aaf4e12 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -142,8 +142,8 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; From cb3e9c96441406a7dd64a7cd2eec45b676d98b9e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 16:58:16 +0100 Subject: [PATCH 058/646] Bugfix for FPA models --- src/tactic/fpa/fpa2bv_model_converter.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 9b4b5a70f..53fa2405b 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -111,14 +111,25 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { unsigned ebits = fu.get_ebits(var->get_range()); unsigned sbits = fu.get_sbits(var->get_range()); - expr_ref sgn(m), sig(m), exp(m); - sgn = bv_mdl->get_const_interp(to_app(a->get_arg(0))->get_decl()); - sig = bv_mdl->get_const_interp(to_app(a->get_arg(1))->get_decl()); - exp = bv_mdl->get_const_interp(to_app(a->get_arg(2))->get_decl()); + expr_ref sgn(m), sig(m), exp(m); + bv_mdl->eval(a->get_arg(0), sgn, true); + bv_mdl->eval(a->get_arg(1), sig, true); + bv_mdl->eval(a->get_arg(2), exp, true); + SASSERT(a->is_app_of(fu.get_family_id(), OP_TO_FLOAT)); + +#ifdef Z3DEBUG + SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); seen.insert(to_app(a->get_arg(0))->get_decl()); seen.insert(to_app(a->get_arg(1))->get_decl()); seen.insert(to_app(a->get_arg(2))->get_decl()); +#else + SASSERT(a->get_arg(0)->get_kind() == OP_EXTRACT); + SASSERT(to_app(a->get_arg(0))->get_arg(0)->get_kind() == OP_EXTRACT); + seen.insert(to_app(to_app(a->get_arg(0))->get_arg(0))->get_decl()); +#endif if (!sgn && !sig && !exp) continue; From 6b51f7a6104c23b855ccf1e89bb5d7f10991471e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 16:59:24 +0100 Subject: [PATCH 059/646] Added item to release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index fa4857e32..ad2dcaf00 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,10 @@ RELEASE NOTES +Version 4.3.3 +============= + +- Fixed bug in floating point models + Version 4.3.2 ============= From f50a8b0a59ff5c98f509dddb46da33033384bf5d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 17:05:02 +0100 Subject: [PATCH 060/646] Bumped version number. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 170124bd8..b30bba609 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -9,7 +9,7 @@ from mk_util import * # Z3 Project definition def init_project_def(): - set_version(4, 3, 2, 0) + set_version(4, 3, 3, 0) add_lib('util', []) add_lib('polynomial', ['util'], 'math/polynomial') add_lib('sat', ['util']) From a6f58bdd173f7d8b4ee55c710c4158f59a76b8cb Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Thu, 30 Oct 2014 17:22:34 -0700 Subject: [PATCH 061/646] fixes and performance improvements for interp and duality --- src/duality/duality.h | 4 ++ src/duality/duality_rpfp.cpp | 108 ++++++++++++++++++++------------- src/duality/duality_solver.cpp | 12 ++++ src/interp/iz3mgr.cpp | 6 +- src/interp/iz3mgr.h | 3 +- 5 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/duality/duality.h b/src/duality/duality.h index edd89d78f..04527450c 100755 --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -778,6 +778,10 @@ protected: struct Bad { }; + // thrown on more serious internal error + struct ReallyBad { + }; + /** Pop a scope (see Push). Note, you cannot pop axioms. */ void Pop(int num_scopes); diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index f2824c9b0..cdc8fb3b2 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -2643,6 +2643,10 @@ namespace Duality { GetGroundLitsUnderQuants(memo,f.body(),res,1); return; } + if(f.is_var()){ + // std::cout << "foo!\n"; + return; + } if(under && f.is_ground()) res.push_back(f); } @@ -3065,10 +3069,14 @@ namespace Duality { node->Annotation.SetEmpty(); hash_set *core = new hash_set; core->insert(node->Outgoing->dual); + expr prev_annot = ctx.bool_val(false); + expr prev_impl = ctx.bool_val(false); + int repeated_case_count = 0; while(1){ by_case_counter++; is.push(); expr annot = !GetAnnotation(node); + Transformer old_annot = node->Annotation; is.add(annot); if(is.check() == unsat){ is.pop(1); @@ -3076,56 +3084,70 @@ namespace Duality { } is.pop(1); Push(); - ConstrainEdgeLocalized(node->Outgoing,is.get_implicant()); + expr the_impl = is.get_implicant(); + if(eq(the_impl,prev_impl)){ + // std::cout << "got old implicant\n"; + repeated_case_count++; + } + prev_impl = the_impl; + ConstrainEdgeLocalized(node->Outgoing,the_impl); ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this? - check_result foo = Check(root); - if(foo != unsat){ - slvr().print("should_be_unsat.smt2"); - throw "should be unsat"; - } - std::vector assumps, axioms_to_add; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++){ - (*core).insert(assumps[i]); - if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ - axioms_to_add.push_back(assumps[i]); - axioms_needed.erase(assumps[i]); - } - } - // AddToProofCore(*core); - Transformer old_annot = node->Annotation; - SolveSingleNode(root,node); - - { - expr itp = GetAnnotation(node); - dualModel = is.get_model(); // TODO: what does this mean? - std::vector case_lits; - itp = StrengthenFormulaByCaseSplitting(itp, case_lits); - SetAnnotation(node,itp); - node->Annotation.Formula = node->Annotation.Formula.simplify(); - } - - for(unsigned i = 0; i < axioms_to_add.size(); i++) - is.add(axioms_to_add[i]); -#define TEST_BAD -#ifdef TEST_BAD { - static int bad_count = 0, num_bads = 1; - if(bad_count >= num_bads){ - bad_count = 0; - num_bads = num_bads * 2; + check_result foo = Check(root); + if(foo != unsat){ Pop(1); is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); + // slvr().print("should_be_unsat.smt2"); + // throw "should be unsat"; } - bad_count++; - } -#endif + std::vector assumps, axioms_to_add; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++){ + (*core).insert(assumps[i]); + if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ + axioms_to_add.push_back(assumps[i]); + axioms_needed.erase(assumps[i]); + } + } + // AddToProofCore(*core); + SolveSingleNode(root,node); - if(node->Annotation.IsEmpty()){ + { + expr itp = GetAnnotation(node); + dualModel = is.get_model(); // TODO: what does this mean? + std::vector case_lits; + itp = StrengthenFormulaByCaseSplitting(itp, case_lits); + SetAnnotation(node,itp); + node->Annotation.Formula = node->Annotation.Formula.simplify(); + } + + for(unsigned i = 0; i < axioms_to_add.size(); i++) + is.add(axioms_to_add[i]); + +#define TEST_BAD +#ifdef TEST_BAD + { + static int bad_count = 0, num_bads = 1; + if(bad_count >= num_bads){ + bad_count = 0; + num_bads = num_bads * 2; + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw Bad(); + } + bad_count++; + } +#endif + } + + if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ + looks_bad: if(!axioms_added){ // add the axioms in the off chance they are useful const std::vector &theory = ls->get_axioms(); @@ -3134,6 +3156,7 @@ namespace Duality { axioms_added = true; } else { + //#define KILL_ON_BAD_INTERPOLANT #ifdef KILL_ON_BAD_INTERPOLANT std::cout << "bad in InterpolateByCase -- core:\n"; #if 0 @@ -3175,10 +3198,11 @@ namespace Duality { is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); } } Pop(1); + prev_annot = node->Annotation.Formula; node->Annotation.UnionWith(old_annot); } if(proof_core) diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index 69759f9bb..b40ab9370 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -2279,6 +2279,18 @@ namespace Duality { // bad interpolants can get us here throw DoRestart(); } + catch(const RPFP::ReallyBad &){ + // this could be caused by incompleteness + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + std::vector &chs = node->map->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++) + chs[j]->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation and child annotations"); + } + throw DoRestart(); + } catch(char const *msg){ // bad interpolants can get us here reporter->Message(std::string("interpolation failure:") + msg); diff --git a/src/interp/iz3mgr.cpp b/src/interp/iz3mgr.cpp index a39065922..e3ac59dfd 100755 --- a/src/interp/iz3mgr.cpp +++ b/src/interp/iz3mgr.cpp @@ -778,6 +778,8 @@ int iz3mgr::occurs_in(ast var, ast e){ bool iz3mgr::solve_arith(const ast &v, const ast &x, const ast &y, ast &res){ + if(occurs_in(v,y)) + return false; if(op(x) == Plus){ int n = num_args(x); for(int i = 0; i < n; i++){ @@ -801,8 +803,8 @@ iz3mgr::ast iz3mgr::cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, as return ast(); cont_eq_memo.insert(e); if(!truth && op(e) == Equal){ - if(arg(e,0) == v) return(arg(e,1)); - if(arg(e,1) == v) return(arg(e,0)); + if(arg(e,0) == v && !occurs_in(v,arg(e,1))) return(arg(e,1)); + if(arg(e,1) == v && !occurs_in(v,arg(e,0))) return(arg(e,0)); ast res; if(solve_arith(v,arg(e,0),arg(e,1),res)) return res; if(solve_arith(v,arg(e,1),arg(e,0),res)) return res; diff --git a/src/interp/iz3mgr.h b/src/interp/iz3mgr.h index 3ec2c42d1..7f66bb2d8 100755 --- a/src/interp/iz3mgr.h +++ b/src/interp/iz3mgr.h @@ -278,7 +278,8 @@ class iz3mgr { } symb sym(ast t){ - return to_app(t.raw())->get_decl(); + raw_ast *_ast = t.raw(); + return is_app(_ast) ? to_app(_ast)->get_decl() : 0; } std::string string_of_symbol(symb s){ From b4600ffda00b0ba2ba874effb1cb6e3139e6a6cd Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 31 Oct 2014 14:24:21 +0100 Subject: [PATCH 062/646] add print to SMT-LIB format from solver Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 1 + src/api/c++/z3++.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index b348e7d36..0d8a3ceb3 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -21,6 +21,7 @@ void demorgan() { // adding the negation of the conjecture as a constraint. s.add(!conjecture); std::cout << s << "\n"; + std::cout << s.to_smt2() << "\n"; switch (s.check()) { case unsat: std::cout << "de-Morgan is valid\n"; break; case sat: std::cout << "de-Morgan is not valid\n"; break; diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index c35208d86..7380e52f1 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1314,6 +1314,26 @@ namespace z3 { expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); } expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); } friend std::ostream & operator<<(std::ostream & out, solver const & s) { out << Z3_solver_to_string(s.ctx(), s); return out; } + + std::string to_smt2(char const* status = "unknown") { + array es(assertions()); + Z3_ast const* fmls = es.ptr(); + Z3_ast fml = 0; + unsigned sz = es.size(); + if (sz > 0) { + --sz; + fml = fmls[sz]; + } + else { + fml = ctx().bool_val(true); + } + return std::string(Z3_benchmark_to_smtlib_string( + ctx(), + "", "", status, "", + sz, + fmls, + fml)); + } }; class goal : public object { From 591f6d096f437445c56b51292e75fe757cd48dd1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Nov 2014 14:26:57 +0000 Subject: [PATCH 063/646] .NET API project directories fixed. Thanks to Marc Brockschmidt for reporting this. --- src/api/dotnet/Microsoft.Z3.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/dotnet/Microsoft.Z3.csproj b/src/api/dotnet/Microsoft.Z3.csproj index cc7d3c0c5..36bd6ad02 100644 --- a/src/api/dotnet/Microsoft.Z3.csproj +++ b/src/api/dotnet/Microsoft.Z3.csproj @@ -19,12 +19,12 @@ true full false - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\Debug\ DEBUG;TRACE prompt 4 true - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\Debug\Microsoft.Z3.XML False False True @@ -254,7 +254,7 @@ true - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\x86\Debug\ DEBUG;TRACE true full @@ -266,7 +266,7 @@ MinimumRecommendedRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\x86\Debug\Microsoft.Z3.XML bin\x86\Release\ From adeae184718a40e008823a0405bc679a5842a91b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Nov 2014 13:09:25 +0100 Subject: [PATCH 064/646] delay initializing internal manager so that parser does not choke on proper SMT-LIB logics. Reported by Venkateshan Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 8 ++++++++ src/cmd_context/cmd_context.cpp | 33 ++++++++++++++++++++------------- src/cmd_context/cmd_context.h | 1 + 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 248d2161e..71a6dde2b 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -3988,6 +3988,12 @@ END_MLAPI_EXCLUDE /** \brief Return a unique identifier for \c t. + The identifier is unique up to structural equality. Thus, two ast nodes + created by the same context and having the same children and same function symbols + have the same identifiers. Ast nodes created in the same context, but having + different children or different functions have different identifiers. + Variables and quantifiers are also assigned different identifiers according to + their structure. \mlonly \remark Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_id', UINT, (_in(CONTEXT), _in(AST))) @@ -3996,6 +4002,8 @@ END_MLAPI_EXCLUDE /** \brief Return a hash code for the given AST. + The hash code is structural. You can use Z3_get_ast_id interchangably with + this function. \mlonly \remark Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 731608524..7fa2dc53f 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -314,8 +314,9 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): m_numeral_as_real(false), m_ignore_check(false), m_exit_on_error(false), - m_manager(m), + m_manager(m), m_own_manager(m == 0), + m_manager_initialized(false), m_pmanager(0), m_sexpr_manager(0), m_regular("stdout", std::cout), @@ -326,8 +327,6 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): install_core_tactic_cmds(*this); install_interpolant_cmds(*this); SASSERT(m != 0 || !has_manager()); - if (m) - init_external_manager(); if (m_main_ctx) { set_verbose_stream(diagnostic_stream()); } @@ -620,12 +619,22 @@ void cmd_context::init_manager_core(bool new_manager) { } void cmd_context::init_manager() { - SASSERT(m_manager == 0); - SASSERT(m_pmanager == 0); - m_check_sat_result = 0; - m_manager = m_params.mk_ast_manager(); - m_pmanager = alloc(pdecl_manager, *m_manager); - init_manager_core(true); + if (m_manager_initialized) { + // no-op + } + else if (m_manager) { + SASSERT(!m_own_manager); + init_external_manager(); + m_manager_initialized = true; + } + else { + SASSERT(m_pmanager == 0); + m_check_sat_result = 0; + m_manager = m_params.mk_ast_manager(); + m_pmanager = alloc(pdecl_manager, *m_manager); + init_manager_core(true); + m_manager_initialized = true; + } } void cmd_context::init_external_manager() { @@ -1211,8 +1220,7 @@ void cmd_context::assert_expr(symbol const & name, expr * t) { void cmd_context::push() { m_check_sat_result = 0; - if (!has_manager()) - init_manager(); + init_manager(); m_scopes.push_back(scope()); scope & s = m_scopes.back(); s.m_func_decls_stack_lim = m_func_decls_stack.size(); @@ -1332,8 +1340,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions return; IF_VERBOSE(100, verbose_stream() << "(started \"check-sat\")" << std::endl;); TRACE("before_check_sat", dump_assertions(tout);); - if (!has_manager()) - init_manager(); + init_manager(); if (m_solver) { m_check_sat_result = m_solver.get(); // solver itself stores the result. m_solver->set_progress_callback(this); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 8ad07e8cc..7c42f41cf 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -149,6 +149,7 @@ protected: ast_manager * m_manager; bool m_own_manager; + bool m_manager_initialized; pdecl_manager * m_pmanager; sexpr_manager * m_sexpr_manager; check_logic m_check_logic; From 23bc982ad24e27feb6ad0635f23fce0a6b8ad8be Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Nov 2014 16:53:51 +0100 Subject: [PATCH 065/646] move initialization to support more sort usage scenarios Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 4 ++-- src/cmd_context/cmd_context.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 7fa2dc53f..5d24977b5 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -623,17 +623,17 @@ void cmd_context::init_manager() { // no-op } else if (m_manager) { + m_manager_initialized = true; SASSERT(!m_own_manager); init_external_manager(); - m_manager_initialized = true; } else { + m_manager_initialized = true; SASSERT(m_pmanager == 0); m_check_sat_result = 0; m_manager = m_params.mk_ast_manager(); m_pmanager = alloc(pdecl_manager, *m_manager); init_manager_core(true); - m_manager_initialized = true; } } diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 7c42f41cf..c4aa34c61 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -294,7 +294,7 @@ public: std::string reason_unknown() const; bool has_manager() const { return m_manager != 0; } - ast_manager & m() const { if (!m_manager) const_cast(this)->init_manager(); return *m_manager; } + ast_manager & m() const { const_cast(this)->init_manager(); return *m_manager; } virtual ast_manager & get_ast_manager() { return m(); } pdecl_manager & pm() const { if (!m_pmanager) const_cast(this)->init_manager(); return *m_pmanager; } sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; } From ce7303b5e2713be2909a39d862c0fe2bba8659c5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Nov 2014 15:44:21 +0100 Subject: [PATCH 066/646] fix reset logic and load only logics admitted by context Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 30 ++++++++++++++++++++++++++---- src/cmd_context/cmd_context.h | 1 + 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 5d24977b5..ee5437bd6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -470,6 +470,16 @@ void cmd_context::register_plugin(symbol const & name, decl_plugin * p, bool ins } } +void cmd_context::load_plugin(symbol const & name, bool install, svector& fids) { + family_id id = m_manager->get_family_id(name); + decl_plugin* p = m_manager->get_plugin(id); + if (install && p && fids.contains(id)) { + register_builtin_sorts(p); + register_builtin_ops(p); + } + fids.erase(id); +} + bool cmd_context::logic_has_arith_core(symbol const & s) const { return s == "QF_LRA" || @@ -586,17 +596,26 @@ void cmd_context::init_manager_core(bool new_manager) { register_builtin_sorts(basic); register_builtin_ops(basic); // the manager was created by the command context. - register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); - register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); - register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); + register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); + register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); + register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype()); register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq()); register_plugin(symbol("float"), alloc(float_decl_plugin), logic_has_floats()); } else { - // the manager was created by an external module, we must register all plugins available in the manager. + // the manager was created by an external module + // we register all plugins available in the manager. + // unless the logic specifies otherwise. svector fids; m_manager->get_range(fids); + load_plugin(symbol("arith"), logic_has_arith(), fids); + load_plugin(symbol("bv"), logic_has_bv(), fids); + load_plugin(symbol("array"), logic_has_array(), fids); + load_plugin(symbol("datatype"), logic_has_datatype(), fids); + load_plugin(symbol("seq"), logic_has_seq(), fids); + load_plugin(symbol("float"), logic_has_floats(), fids); + svector::iterator it = fids.begin(); svector::iterator end = fids.end(); for (; it != end; ++it) { @@ -1174,12 +1193,15 @@ void cmd_context::reset(bool finalize) { if (m_own_manager) { dealloc(m_manager); m_manager = 0; + m_manager_initialized = false; } else { // doesn't own manager... so it cannot be deleted // reinit cmd_context if this is not a finalization step if (!finalize) init_external_manager(); + else + m_manager_initialized = false; } } if (m_sexpr_manager) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index c4aa34c61..1c8dba21a 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -214,6 +214,7 @@ protected: void register_builtin_sorts(decl_plugin * p); void register_builtin_ops(decl_plugin * p); void register_plugin(symbol const & name, decl_plugin * p, bool install_names); + void load_plugin(symbol const & name, bool install_names, svector& fids); void init_manager_core(bool new_manager); void init_manager(); void init_external_manager(); From cf8ad072d017aada57ed2d342fc6bec6ddd0929a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Nov 2014 16:03:27 +0100 Subject: [PATCH 067/646] remove unused variable Signed-off-by: Nikolaj Bjorner --- src/smt/theory_array_base.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index b2c17b4e0..b33e6b4e6 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -362,7 +362,6 @@ namespace smt { (store A i v) <--- v is used as an value */ bool theory_array_base::is_shared(theory_var v) const { - context & ctx = get_context(); enode * n = get_enode(v); enode * r = n->get_root(); bool is_array = false; From 005bb82a1751f3d70705bff9819acdec608d9f41 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 7 Nov 2014 16:04:02 +0000 Subject: [PATCH 068/646] eliminated unused variables --- src/ast/fpa/fpa2bv_converter.cpp | 42 ++++++++++++++++---------------- src/interp/iz3base.h | 2 +- src/interp/iz3proof_itp.cpp | 3 ++- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 5f92b4d94..c23de3bfa 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2155,15 +2155,15 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2173,15 +2173,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2189,15 +2189,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } diff --git a/src/interp/iz3base.h b/src/interp/iz3base.h index bca9b8518..956191290 100755 --- a/src/interp/iz3base.h +++ b/src/interp/iz3base.h @@ -161,7 +161,7 @@ class iz3base : public iz3mgr, public scopes { stl_ext::hash_map simplify_memo; stl_ext::hash_map frame_map; // map assertions to frames - int frames; // number of frames + // int frames; // number of frames protected: void add_frame_range(int frame, ast t); diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 52ddcd64f..b487b2892 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -2747,7 +2747,8 @@ class iz3proof_itp_impl : public iz3proof_itp { ast orig_e = e; pf = make_refl(e); // proof that e = e - prover::range erng = pv->ast_scope(e); + // prover::range erng = + pv->ast_scope(e); #if 0 if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ return e; // this term occurs in range, so it's O.K. From 261fe01ceadae0f5a387fdaf0f2af4f3147f0c6d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Nov 2014 12:38:59 +0000 Subject: [PATCH 069/646] FPA API bug and consistency fixes Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 2 +- src/api/api_fpa.cpp | 26 +++++++-- src/api/dotnet/Context.cs | 2 +- src/api/z3_fpa.h | 94 ++++++++++++++++++++++++-------- src/ast/fpa/fpa2bv_converter.cpp | 8 --- 5 files changed, 95 insertions(+), 37 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 6eb7a2e11..1aef9eb1b 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2618,7 +2618,7 @@ void fpa_example() { symbol_y = Z3_mk_string_symbol(ctx, "y"); x = Z3_mk_const(ctx, symbol_x, double_sort); y = Z3_mk_const(ctx, symbol_y, double_sort); - n = Z3_mk_fpa_double(ctx, 42.0, double_sort); + n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort); symbol_q = Z3_mk_string_symbol(ctx, "q"); q = Z3_mk_const(ctx, symbol_q, double_sort); diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 8bcc4c1af..df0dd232a 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -99,7 +99,23 @@ extern "C" { Z3_sort r = of_sort(ctx->float_util().mk_float_sort(ebits, sbits)); RETURN_Z3(r); Z3_CATCH_RETURN(0); - } + } + + Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 5, 11); + } + + Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 8, 24); + } + + Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 11, 53); + } + + Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 15, 113); + } Z3_ast Z3_API Z3_mk_fpa_nan(Z3_context c, Z3_sort s) { Z3_TRY; @@ -131,9 +147,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_double(Z3_context c, double v, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_numeral_double(Z3_context c, double v, Z3_sort ty) { Z3_TRY; - LOG_Z3_mk_fpa_double(c, v, ty); + LOG_Z3_mk_fpa_numeral_double(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->float_util().fm()); @@ -158,7 +174,7 @@ extern "C" { LOG_Z3_mk_fpa_neg(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_uminus(to_expr(t))); + Z3_ast r = of_ast(ctx->float_util().mk_neg(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -208,7 +224,7 @@ extern "C" { LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_fused_ma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); + Z3_ast r = of_ast(ctx->float_util().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index b1e60d34f..19f6d582c 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3533,7 +3533,7 @@ namespace Microsoft.Z3 public FPNum MkFP(double v, FPSort s) { Contract.Ensures(Contract.Result() != null); - return new FPNum(this, Native.Z3_mk_fpa_double(this.nCtx, v, s.NativeObject)); + return new FPNum(this, Native.Z3_mk_fpa_numeral_double(this.nCtx, v, s.NativeObject)); } /// diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 265657bf4..63b489c83 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -23,6 +23,18 @@ Notes: extern "C" { #endif // __cplusplus + /** + \defgroup capi C API + + */ + + /*@{*/ + + /** + @name Floating-Point API + */ + /*@{*/ + /** \brief Create a rounding mode sort. @@ -92,6 +104,59 @@ extern "C" { */ Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits); + /** + \brief Create the half-precision (16-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_half', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c); + + /** + \brief Create the single-precision (32-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_single', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c); + + /** + \brief Create the double-precision (64-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_double', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c); + + /** + \brief Create the quadruple-precision (128-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_quadruple', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c); + + /** \brief Create a NaN of sort s. @@ -129,7 +194,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_zero(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); /** - \brief Create a numeral of floating point sort. + \brief Create a numeral of floating point sort from a double. This function can be use to create numerals that fit in a double value. It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. @@ -142,27 +207,9 @@ extern "C" { \sa Z3_mk_numeral - def_API('Z3_mk_fpa_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) + def_API('Z3_mk_fpa_numeral_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); - - /** - \brief Create a numeral of floating point sort. - - This function can be use to create numerals that fit in a double value. - It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. - - \params c logical context. - \params v value. - \params ty sort. - - ty must be a floating point sort - - \sa Z3_mk_numeral - - def_API('Z3_mk_fpa_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) - */ - Z3_ast Z3_API Z3_mk_fpa_double(__in Z3_context c, __in double v, __in Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_numeral_double(__in Z3_context c, __in double v, __in Z3_sort ty); /** \brief Floating-point absolute value @@ -468,7 +515,10 @@ extern "C" { def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); - + + /*@}*/ + /*@}*/ + #ifdef __cplusplus }; #endif // __cplusplus diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 20d8a00e1..de4797f80 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1858,14 +1858,6 @@ void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const result = m.mk_and(m.mk_not(t1), t2); } -void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - SASSERT(num == 1); - expr_ref t1(m), t2(m); - mk_is_nan(args[0], t1); - mk_is_pos(args[0], t2); - result = m.mk_and(m.mk_not(t1), t2); -} - void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_float", for (unsigned i=0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl; ); From 62d4542f83c4f314e94c1deaf1d4007e6d73aa6d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Nov 2014 13:05:48 +0000 Subject: [PATCH 070/646] FPA API bug fix for RoundingMode values in models Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/fpa2bv_model_converter.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 53fa2405b..3de869e15 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -167,14 +167,15 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { it++) { func_decl * var = it->m_key; - app * a = to_app(it->m_value); + expr * v = it->m_value; + expr_ref eval_v(m); SASSERT(fu.is_rm(var->get_range())); - rational val(0); + rational bv_val(0); unsigned sz = 0; - if (a && bu.is_numeral(a, val, sz)) { - TRACE("fpa2bv_mc", tout << var->get_name() << " == " << val.to_string() << std::endl;); - SASSERT(val.is_uint64()); - switch (val.get_uint64()) + if (v && bv_mdl->eval(v, eval_v, true) && bu.is_numeral(eval_v, bv_val, sz)) { + TRACE("fpa2bv_mc", tout << var->get_name() << " == " << bv_val.to_string() << std::endl;); + SASSERT(bv_val.is_uint64()); + switch (bv_val.get_uint64()) { case BV_RM_TIES_TO_AWAY: float_mdl->register_decl(var, fu.mk_round_nearest_ties_to_away()); break; case BV_RM_TIES_TO_EVEN: float_mdl->register_decl(var, fu.mk_round_nearest_ties_to_even()); break; @@ -183,7 +184,8 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { case BV_RM_TO_ZERO: default: float_mdl->register_decl(var, fu.mk_round_toward_zero()); } - seen.insert(var); + SASSERT(v->get_kind() == AST_APP); + seen.insert(to_app(v)->get_decl()); } } From 9503d955f9d0b4597fc1623e70df942e03dcabe0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Nov 2014 13:16:28 +0000 Subject: [PATCH 071/646] FPA API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 9bf2d5c81..f11389024 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -194,7 +194,7 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete case FLOAT64_SORT: return mk_float_sort(11, 53); case FLOAT128_SORT: - return mk_float_sort(15, 133); + return mk_float_sort(15, 113); default: m_manager->raise_exception("unknown floating point theory sort"); return 0; From c9c11f3b3ae5299ec2975e4c96171d20c8a277b8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Nov 2014 16:20:19 +0000 Subject: [PATCH 072/646] FPA API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index f11389024..20078f73f 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -454,20 +454,6 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } - else if (arity == 2 && - is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && - is_sort_of(domain[1], m_family_id, FLOAT_SORT)) { - // Rounding + 1 FP -> 1 FP - if (num_parameters != 2) - m_manager->raise_exception("invalid number of parameters to to_fp"); - if (!parameters[0].is_int() || !parameters[1].is_int()) - m_manager->raise_exception("invalid parameter type to to_fp"); - int ebits = parameters[0].get_int(); - int sbits = parameters[1].get_int(); - if (!is_rm_sort(domain[0]) || - !is_sort_of(domain[1], m_family_id, FLOAT_SORT)) - m_manager->raise_exception("sort mismatch"); - } else { // 1 Real -> 1 FP if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) @@ -481,7 +467,7 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); symbol name("to_fp"); - return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } } From b7c5a295705f10114e84d0d457a06ef27bda87b8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Nov 2014 18:36:18 +0000 Subject: [PATCH 073/646] FPA theory bug fixes Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 128 ++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 66 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index ad353c3d0..a7e1c7bf1 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -53,7 +53,7 @@ namespace smt { SASSERT(get_sort(x)->get_family_id() == m_converter.bu().get_family_id()); SASSERT(get_sort(y)->get_family_id() == m_converter.bu().get_family_id()); ast_manager & m = get_manager(); - context & ctx = get_context(); + context & ctx = get_context(); theory_id bv_tid = ctx.get_theory(m.get_sort(x)->get_family_id())->get_id(); literal l = mk_eq(x, y, false); ctx.mk_th_axiom(bv_tid, 1, &l); @@ -69,6 +69,7 @@ namespace smt { simplifier & simp = ctx.get_simplifier(); bv_util & bu = m_converter.bu(); expr_ref bv_atom(m); + proof_ref pr(m); if (ctx.b_internalized(atom)) return true; @@ -78,6 +79,7 @@ namespace smt { ctx.internalize(atom->get_arg(i), false); m_rw(atom, bv_atom); + simp(bv_atom, bv_atom, pr); ctx.internalize(bv_atom, gate_ctx); literal def = ctx.get_literal(bv_atom); @@ -106,12 +108,14 @@ namespace smt { bv_util & bu = m_converter.bu(); sort * term_sort = m.get_sort(term); expr_ref t(m), bv_term(m); + proof_ref pr(m); unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); m_rw(term, t); + simp(t, t, pr); if (m_converter.is_rm(term_sort)) { SASSERT(is_app(t)); @@ -163,11 +167,13 @@ namespace smt { simplifier & simp = ctx.get_simplifier(); app * owner = n->get_owner(); expr_ref converted(m); + proof_ref pr(m); theory_var v = mk_var(n); ctx.attach_th_var(n, this, v); m_tvars.push_back(v); m_rw(owner, converted); + simp(converted, converted, pr); m_trans_map.insert(owner, converted, 0); sort * owner_sort = m.get_sort(owner); @@ -260,7 +266,7 @@ namespace smt { theory::pop_scope_eh(num_scopes); } - model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { + model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { ast_manager & m = get_manager(); context & ctx = get_context(); bv_util & bu = m_converter.bu(); @@ -268,12 +274,12 @@ namespace smt { mpf_manager & mpfm = fu.fm(); unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - + theory_var v = n->get_th_var(get_id()); SASSERT(v != null_theory_var); expr * fpa_e = get_enode(v)->get_owner(); TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(fpa_e, m) << "\n";); - + expr * bv_e; proof * bv_pr; m_trans_map.get(fpa_e, bv_e, bv_pr); @@ -281,16 +287,14 @@ namespace smt { expr_wrapper_proc * res = 0; if (fu.is_rm(fpa_e_srt)) { - SASSERT(ctx.e_internalized(bv_e)); - sort * s = m.get_sort(bv_e); - family_id fid = s->get_family_id(); - theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); - rational val; - if (!bv_th->get_fixed_value(ctx.get_enode(bv_e)->get_owner(), val)) { - UNREACHABLE(); - } + if (!ctx.e_internalized(bv_e)) + res = alloc(expr_wrapper_proc, fu.mk_round_nearest_ties_to_away()); else { + theory_bv * bv_th = (theory_bv*)ctx.get_theory(m.get_family_id("bv")); + rational val; + + bv_th->get_fixed_value(ctx.get_enode(bv_e)->get_owner(), val); // OK to fail app * fp_val_e; SASSERT(val.is_uint64()); switch (val.get_uint64()) @@ -301,8 +305,8 @@ namespace smt { case BV_RM_TO_POSITIVE: fp_val_e = fu.mk_round_toward_positive(); break; case BV_RM_TO_ZERO: default: fp_val_e = fu.mk_round_toward_zero(); - } - + } + TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); res = alloc(expr_wrapper_proc, fp_val_e); } @@ -311,73 +315,65 @@ namespace smt { expr * bv_sgn, *bv_sig, *bv_exp; split_triple(bv_e, bv_sgn, bv_sig, bv_exp); - SASSERT(ctx.e_internalized(bv_sgn)); - SASSERT(ctx.e_internalized(bv_sig)); - SASSERT(ctx.e_internalized(bv_exp)); - - enode * e_sgn = ctx.get_enode(bv_sgn); - enode * e_sig = ctx.get_enode(bv_sig); - enode * e_exp = ctx.get_enode(bv_exp); - - TRACE("t_fpa", tout << "bv rep: [" << mk_ismt2_pp(e_sgn->get_owner(), m) << " " - << mk_ismt2_pp(e_sig->get_owner(), m) << " " - << mk_ismt2_pp(e_exp->get_owner(), m) << "]\n";); - - sort * s = m.get_sort(e_sgn->get_owner()); - family_id fid = s->get_family_id(); + family_id fid = m.get_family_id("bv"); theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); - SASSERT(bv_th->is_attached_to_var(e_sgn)); - SASSERT(bv_th->is_attached_to_var(e_sig)); - SASSERT(bv_th->is_attached_to_var(e_exp)); + app * e_sgn, *e_sig, *e_exp; + unsigned exp_sz = fpa_e_srt->get_parameter(0).get_int(); + unsigned sig_sz = fpa_e_srt->get_parameter(1).get_int() - 1; - unsigned sig_sz, exp_sz; - sig_sz = bu.get_bv_size(e_sig->get_owner()); - exp_sz = bu.get_bv_size(e_exp->get_owner()); + e_sgn = (ctx.e_internalized(bv_sgn)) ? ctx.get_enode(bv_sgn)->get_owner() : + m_converter.bu().mk_numeral(0, 1); + e_sig = (ctx.e_internalized(bv_sig)) ? ctx.get_enode(bv_sig)->get_owner() : + m_converter.bu().mk_numeral(0, sig_sz); + e_exp = (ctx.e_internalized(bv_exp)) ? ctx.get_enode(bv_exp)->get_owner() : + m_converter.bu().mk_numeral(0, exp_sz); + + TRACE("t_fpa", tout << "bv rep: [" + << mk_ismt2_pp(e_sgn, m) << "\n" + << mk_ismt2_pp(e_sig, m) << "\n" + << mk_ismt2_pp(e_exp, m) << "]\n";); rational sgn_r(0), sig_r(0), exp_r(0); - if (!bv_th->get_fixed_value(e_sgn->get_owner(), sgn_r) || - !bv_th->get_fixed_value(e_sig->get_owner(), sig_r) || - !bv_th->get_fixed_value(e_exp->get_owner(), exp_r)) { - UNREACHABLE(); - } - else { - TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " + bv_th->get_fixed_value(e_sgn, sgn_r); // OK to fail + bv_th->get_fixed_value(e_sig, sig_r); // OK to fail + bv_th->get_fixed_value(e_exp, exp_r); // OK to fail + + TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " << sig_r.to_string() << " " << exp_r.to_string() << "]\n";); - // un-bias exponent - rational exp_unbiased_r; - exp_unbiased_r = exp_r - mpfm.m_powers2.m1(exp_sz - 1); + // un-bias exponent + rational exp_unbiased_r; + exp_unbiased_r = exp_r - mpfm.m_powers2.m1(exp_sz - 1); - mpz sig_z; mpf_exp_t exp_z; - mpq sig_q, exp_q; - mpz sig_num, exp_num; - mpqm.set(sig_q, sig_r.to_mpq()); - mpzm.set(sig_num, sig_q.numerator()); - mpqm.set(exp_q, exp_unbiased_r.to_mpq()); - mpzm.set(exp_num, exp_q.numerator()); - mpzm.set(sig_z, sig_num); - exp_z = mpzm.get_int64(exp_num); + mpz sig_z; mpf_exp_t exp_z; + mpq sig_q, exp_q; + mpz sig_num, exp_num; + mpqm.set(sig_q, sig_r.to_mpq()); + mpzm.set(sig_num, sig_q.numerator()); + mpqm.set(exp_q, exp_unbiased_r.to_mpq()); + mpzm.set(exp_num, exp_q.numerator()); + mpzm.set(sig_z, sig_num); + exp_z = mpzm.get_int64(exp_num); - mpf fp_val; - mpfm.set(fp_val, exp_sz, sig_sz + 1, !sgn_r.is_zero(), sig_z, exp_z); + mpf fp_val; + mpfm.set(fp_val, exp_sz, sig_sz + 1, !sgn_r.is_zero(), sig_z, exp_z); - app * fp_val_e; - fp_val_e = fu.mk_value(fp_val); + app * fp_val_e; + fp_val_e = fu.mk_value(fp_val); - TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); + TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); - mpfm.del(fp_val); - mpzm.del(sig_num); - mpzm.del(exp_num); - mpqm.del(sig_q); - mpqm.del(exp_q); - mpzm.del(sig_z); + mpfm.del(fp_val); + mpzm.del(sig_num); + mpzm.del(exp_num); + mpqm.del(sig_q); + mpqm.del(exp_q); + mpzm.del(sig_z); - res = alloc(expr_wrapper_proc, fp_val_e); - } + res = alloc(expr_wrapper_proc, fp_val_e); } else UNREACHABLE(); From a309dbfdc2b3ebca65946b6afe443e815a1f1cee Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 12 Nov 2014 20:28:11 -0800 Subject: [PATCH 074/646] coerce equality and ite upward instead of downward for int2real coercions. Fixes bug reported by Enric Carbonell Signed-off-by: Nikolaj Bjorner --- src/ast/ast.cpp | 25 +++++++++++++++++++------ src/ast/ast.h | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 68f7596ee..09965be85 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1013,6 +1013,17 @@ func_decl * basic_decl_plugin::mk_ite_decl(sort * s) { return m_ite_decls[id]; } +sort* basic_decl_plugin::join(sort* s1, sort* s2) { + if (s1 == s2) return s1; + if (s1->get_family_id() == m_manager->m_arith_family_id && + s2->get_family_id() == m_manager->m_arith_family_id) { + if (s1->get_decl_kind() == REAL_SORT) { + return s1; + } + } + return s2; +} + func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (static_cast(k)) { @@ -1025,10 +1036,10 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return arity == 3 ? mk_ite_decl(domain[1]) : 0; + case OP_ITE: return arity == 3 ? mk_ite_decl(join(domain[1], domain[2])) : 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, domain[0], m_eq_decls) : 0; - case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, domain[0], m_oeq_decls) : 0; + case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, join(domain[0],domain[1]), m_eq_decls) : 0; + case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(domain[0],domain[1]), m_oeq_decls) : 0; case OP_DISTINCT: { func_decl_info info(m_family_id, OP_DISTINCT); info.set_pairwise(); @@ -1061,10 +1072,12 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return num_args == 3 ? mk_ite_decl(m_manager->get_sort(args[1])): 0; + case OP_ITE: return num_args == 3 ? mk_ite_decl(join(m_manager->get_sort(args[1]), m_manager->get_sort(args[2]))): 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, m_manager->get_sort(args[0]), m_eq_decls) : 0; - case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, m_manager->get_sort(args[0]), m_oeq_decls) : 0; + case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_eq_decls) : 0; + case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_oeq_decls) : 0; case OP_DISTINCT: return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); default: diff --git a/src/ast/ast.h b/src/ast/ast.h index 68f08e1ac..944c089f3 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1100,6 +1100,7 @@ protected: virtual void set_manager(ast_manager * m, family_id id); func_decl * mk_eq_decl_core(char const * name, decl_kind k, sort * s, ptr_vector & cache); func_decl * mk_ite_decl(sort * s); + sort* join(sort* s1, sort* s2); public: basic_decl_plugin(); @@ -1378,7 +1379,7 @@ enum proof_gen_mode { // ----------------------------------- class ast_manager { -protected: + friend basic_decl_plugin; protected: struct config { typedef ast_manager value_manager; From 4c5753f32144da6a4a8f244318a938e780d79dba Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 13 Nov 2014 18:08:24 -0800 Subject: [PATCH 075/646] be classy with your friends Signed-off-by: Nikolaj Bjorner --- src/ast/ast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/ast.h b/src/ast/ast.h index 944c089f3..93f456965 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1379,7 +1379,7 @@ enum proof_gen_mode { // ----------------------------------- class ast_manager { - friend basic_decl_plugin; + friend class basic_decl_plugin; protected: struct config { typedef ast_manager value_manager; From 213d816c0a418bafc8fe57acb4b10aeea5b1f5b2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Nov 2014 18:10:54 +0000 Subject: [PATCH 076/646] Bugfix for bv_size_reduction. Thanks to user rsas for reporting this isse! Signed-off-by: Christoph M. Wintersteiger --- src/tactic/bv/bv_size_reduction_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index e149afc75..14a2fb28d 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -229,7 +229,7 @@ struct bv_size_reduction_tactic::imp { else { // l < u if (l.is_neg()) { - unsigned i_nb = (u - l).get_num_bits(); + unsigned i_nb = (u - l).get_num_bits() + 1; unsigned v_nb = m_util.get_bv_size(v); if (i_nb < v_nb) { new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); From 53cfa472141fc9dd5c6f07e62a1786243636f846 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 25 Nov 2014 14:22:50 +0000 Subject: [PATCH 077/646] bugfix for bv_size_reduction Signed-off-by: Christoph M. Wintersteiger --- src/tactic/bv/bv_size_reduction_tactic.cpp | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index 14a2fb28d..5e32bf6c4 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -229,17 +229,35 @@ struct bv_size_reduction_tactic::imp { else { // l < u if (l.is_neg()) { - unsigned i_nb = (u - l).get_num_bits() + 1; + unsigned l_nb = (-l).get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); - if (i_nb < v_nb) { - new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); - new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + + if (u.is_neg()) + { + // l <= v <= u <= 0 + unsigned i_nb = l_nb; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= u <= 0 " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_concat(m_util.mk_numeral(numeral(-1), v_nb - i_nb), new_const); + } + } + else { + // l <= v <= 0 <= u + unsigned u_nb = u.get_num_bits(); + unsigned i_nb = ((l_nb > u_nb) ? l_nb : u_nb) + 1; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= 0 <= u " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + } } } else { // 0 <= l <= v <= u unsigned u_nb = u.get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); + TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << " --> " << u_nb << " bits\n";); if (u_nb < v_nb) { new_const = m.mk_fresh_const(0, m_util.mk_sort(u_nb)); new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), new_const); From 59dfd2abe451b9f0c5cb0218f53699f8bdf49a37 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 25 Nov 2014 14:54:47 +0000 Subject: [PATCH 078/646] fixed problem with Python 3.4.x complainging of inconsistent use of spaces/tabs. Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index e58e47640..851e8e243 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -298,8 +298,8 @@ class AstRef(Z3PPObject): return self.ast def get_id(self): - """Return unique identifier for object. It can be used for hash-tables and maps.""" - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + """Return unique identifier for object. It can be used for hash-tables and maps.""" + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def ctx_ref(self): @@ -453,7 +453,7 @@ class SortRef(AstRef): return Z3_sort_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def kind(self): @@ -595,7 +595,7 @@ class FuncDeclRef(AstRef): return Z3_func_decl_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def as_func_decl(self): return self.ast @@ -743,7 +743,7 @@ class ExprRef(AstRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the sort of expression `self`. @@ -1540,7 +1540,7 @@ class PatternRef(ExprRef): return Z3_pattern_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def is_pattern(a): """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation. @@ -1605,7 +1605,7 @@ class QuantifierRef(BoolRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the Boolean sort.""" @@ -6033,20 +6033,20 @@ class Solver(Z3PPObject): return Z3_solver_to_string(self.ctx.ref(), self.solver) def to_smt2(self): - """return SMTLIB2 formatted benchmark for solver's assertions""" - es = self.assertions() - sz = len(es) - sz1 = sz - if sz1 > 0: - sz1 -= 1 - v = (Ast * sz1)() - for i in range(sz1): - v[i] = es[i].as_ast() - if sz > 0: - e = es[sz1].as_ast() - else: - e = BoolVal(True, self.ctx).as_ast() - return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) + """return SMTLIB2 formatted benchmark for solver's assertions""" + es = self.assertions() + sz = len(es) + sz1 = sz + if sz1 > 0: + sz1 -= 1 + v = (Ast * sz1)() + for i in range(sz1): + v[i] = es[i].as_ast() + if sz > 0: + e = es[sz1].as_ast() + else: + e = BoolVal(True, self.ctx).as_ast() + return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) From 1a396b0bd2eebe4f3ad7826cfec1fd8cbb7574cf Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 25 Nov 2014 18:13:24 +0000 Subject: [PATCH 079/646] [BV size reduction] fix bug in detection of signed upperbound Signed-off-by: Nuno Lopes --- src/tactic/bv/bv_size_reduction_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index 5e32bf6c4..707a9284b 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -151,7 +151,7 @@ struct bv_size_reduction_tactic::imp { // bound is infeasible. } else { - update_signed_upper(to_app(lhs), val); + update_signed_upper(to_app(rhs), val); } } else update_signed_lower(to_app(rhs), val); From c88b2f6b5ebbaf34ab5a610008d054cee8da869a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 14:35:15 +0000 Subject: [PATCH 080/646] .NET API: Added build instructions for .NET 3.5 Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Readme.NET35 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/api/dotnet/Readme.NET35 diff --git a/src/api/dotnet/Readme.NET35 b/src/api/dotnet/Readme.NET35 new file mode 100644 index 000000000..73743fd15 --- /dev/null +++ b/src/api/dotnet/Readme.NET35 @@ -0,0 +1,9 @@ +The default Z3 bindings for .NET are built for the .NET framework version 4. +Should the need arise, it is also possible to build them for .NET 3.5; the +instructions are as follows: + +In the project properties of Microsoft.Z3.csproj: +- Under 'Application': Change Target framework to .NET Framework 3.5 +- Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols +- Remove the reference to System.Numerics +- Install the NuGet Package "Microsoft Code Contracts for Net3.5" From 45755bbd140231ad08fcbc487d60fc00a2eee78f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 3 Dec 2014 08:55:14 +0900 Subject: [PATCH 081/646] fix context sensitivity. Codeplex issue 148, thanks to clockish Signed-off-by: Nikolaj Bjorner --- src/api/python/z3.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 851e8e243..db629cd2d 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -6166,7 +6166,7 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) else: body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def rule(self, head, body = None, name = None): @@ -6194,7 +6194,7 @@ class Fixedpoint(Z3PPObject): if sz == 1: query = query[0] else: - query = And(query) + query = And(query, self.ctx) query = self.abstract(query, False) r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast()) return CheckSatResult(r) @@ -6213,7 +6213,7 @@ class Fixedpoint(Z3PPObject): name = "" name = to_symbol(name, self.ctx) body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def get_answer(self): From 8181b15a1bc86123a4f2c15de2f9cabe8bdbc481 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Mon, 8 Dec 2014 15:46:55 -0800 Subject: [PATCH 082/646] attempted interp fixes --- src/interp/iz3proof_itp.cpp | 2 +- src/interp/iz3translate.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 52ddcd64f..df436d206 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -1027,7 +1027,7 @@ class iz3proof_itp_impl : public iz3proof_itp { linear_comb(Aineqs,coeff,make(Leq,make_int(rational(0)),make(Sub,term2,term1))); } else { - ast pf = extract_rewrites(make(concat,mk_true(),rest),p1); + ast pf = extract_rewrites(make(concat,mk_true(),last),p1); ast new_normal = fix_normal(term1,term2,pf); normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); } diff --git a/src/interp/iz3translate.cpp b/src/interp/iz3translate.cpp index 26786d57a..f65ec72d4 100755 --- a/src/interp/iz3translate.cpp +++ b/src/interp/iz3translate.cpp @@ -1712,11 +1712,17 @@ public: std::cout << "foo!\n"; // no idea why this shows up - if(dk == PR_MODUS_PONENS_OEQ) + if(dk == PR_MODUS_PONENS_OEQ){ if(conc(prem(proof,0)) == con){ res = translate_main(prem(proof,0),expect_clause); return res; } + if(expect_clause && op(con) == Or){ // skolemization does this + Iproof::node clause = translate_main(prem(proof,0),true); + res = RewriteClause(clause,prem(proof,1)); + return res; + } + } #if 0 if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){ @@ -1800,7 +1806,9 @@ public: } break; } - case PR_MONOTONICITY: { + case PR_QUANT_INTRO: + case PR_MONOTONICITY: + { std::vector eqs; eqs.resize(args.size()); for(unsigned i = 0; i < args.size(); i++) eqs[i] = conc(prem(proof,i)); From 657595818ee97233bd47955630e63ef9a6d62d6e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 10 Dec 2014 18:45:44 +0000 Subject: [PATCH 083/646] FPA API: Renaming for consistency with final SMT standard. Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 31 +++++---- src/api/z3_fpa.h | 63 +++++++++++++---- src/ast/float_decl_plugin.cpp | 85 ++++++++++------------- src/ast/float_decl_plugin.h | 36 ++++------ src/ast/fpa/fpa2bv_converter.cpp | 26 +++---- src/ast/fpa/fpa2bv_converter.h | 2 +- src/ast/fpa/fpa2bv_rewriter.h | 13 ++-- src/ast/rewriter/float_rewriter.cpp | 5 +- src/smt/theory_fpa.cpp | 19 +---- src/smt/theory_fpa.h | 2 +- src/tactic/fpa/fpa2bv_model_converter.cpp | 2 +- 11 files changed, 146 insertions(+), 138 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index df0dd232a..12d32c04a 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -88,6 +88,7 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits) { Z3_TRY; LOG_Z3_mk_fpa_sort(c, ebits, sbits); @@ -105,18 +106,34 @@ extern "C" { return Z3_mk_fpa_sort(c, 5, 11); } + Z3_sort Z3_API Z3_mk_fpa_sort_16(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 5, 11); + } + Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c) { return Z3_mk_fpa_sort(c, 8, 24); } + Z3_sort Z3_API Z3_mk_fpa_sort_32(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 8, 24); + } + Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c) { return Z3_mk_fpa_sort(c, 11, 53); } + Z3_sort Z3_API Z3_mk_fpa_sort_64(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 11, 53); + } + Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c) { return Z3_mk_fpa_sort(c, 15, 113); } + Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c) { + return Z3_mk_fpa_sort(c, 15, 113); + } + Z3_ast Z3_API Z3_mk_fpa_nan(Z3_context c, Z3_sort s) { Z3_TRY; LOG_Z3_mk_fpa_nan(c, s); @@ -373,22 +390,12 @@ extern "C" { Z3_TRY; LOG_Z3_mk_fpa_convert(c, s, rm, t); RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); + api::context * ctx = mk_c(c); expr * args [2] = { to_expr(rm), to_expr(t) }; - Z3_ast r = of_ast(ctx->m().mk_app(ctx->float_util().get_family_id(), OP_TO_FLOAT, + Z3_ast r = of_ast(ctx->m().mk_app(ctx->float_util().get_family_id(), OP_FLOAT_TO_FP, to_sort(s)->get_num_parameters(), to_sort(s)->get_parameters(), 2, args)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) { - Z3_TRY; - LOG_Z3_mk_fpa_to_ieee_bv(c, t); - RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_float_to_ieee_bv(to_expr(t))); - RETURN_Z3(r); - Z3_CATCH_RETURN(0); - } }; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 63b489c83..f04b87ea3 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -117,6 +117,19 @@ extern "C" { */ Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c); + /** + \brief Create the half-precision (16-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_16', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_16(__in Z3_context c); + /** \brief Create the single-precision (32-bit) floating point sort. @@ -130,6 +143,19 @@ extern "C" { */ Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c); + /** + \brief Create the single-precision (32-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_32', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_32(__in Z3_context c); + /** \brief Create the double-precision (64-bit) floating point sort. @@ -143,6 +169,19 @@ extern "C" { */ Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c); + /** + \brief Create the double-precision (64-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort__64(__in Z3_context c); + /** \brief Create the quadruple-precision (128-bit) floating point sort. @@ -156,6 +195,18 @@ extern "C" { */ Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c); + /** + \brief Create the quadruple-precision (128-bit) floating point sort. + + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits + + \remark ebits must be larger than 1 and sbits must be larger than 2. + + def_API('Z3_mk_fpa_sort_128', SORT, (_in(CONTEXT),)) + */ + Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c); /** \brief Create a NaN of sort s. @@ -504,18 +555,6 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); - /** - \brief Conversion of a floating point term to a bit-vector term in IEEE754 format. - - \param c logical context. - \param t floating-point term. - - t must have floating point sort. The size of the resulting bit-vector is automatically determined. - - def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) - */ - Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); - /*@}*/ /*@}*/ diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 20078f73f..4f8650610 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -118,23 +118,23 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) { } bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) { - if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_AWAY)) { + if (is_app_of(n, m_family_id, OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)) { val = MPF_ROUND_NEAREST_TAWAY; return true; } - else if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_EVEN)) { + else if (is_app_of(n, m_family_id, OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)) { val = MPF_ROUND_NEAREST_TEVEN; return true; } - else if (is_app_of(n, m_family_id, OP_RM_TOWARD_NEGATIVE)) { + else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_NEGATIVE)) { val = MPF_ROUND_TOWARD_NEGATIVE; return true; } - else if (is_app_of(n, m_family_id, OP_RM_TOWARD_POSITIVE)) { + else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_POSITIVE)) { val = MPF_ROUND_TOWARD_POSITIVE; return true; } - else if (is_app_of(n, m_family_id, OP_RM_TOWARD_ZERO)) { + else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_ZERO)) { val = MPF_ROUND_TOWARD_ZERO; return true; } @@ -210,15 +210,15 @@ func_decl * float_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parame sort * s = mk_rm_sort(); func_decl_info finfo(m_family_id, k); switch (k) { - case OP_RM_NEAREST_TIES_TO_EVEN: + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: return m_manager->mk_const_decl(symbol("roundNearestTiesToEven"), s, finfo); - case OP_RM_NEAREST_TIES_TO_AWAY: + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: return m_manager->mk_const_decl(symbol("roundNearestTiesToAway"), s, finfo); - case OP_RM_TOWARD_POSITIVE: + case OP_FLOAT_RM_TOWARD_POSITIVE: return m_manager->mk_const_decl(symbol("roundTowardPositive"), s, finfo); - case OP_RM_TOWARD_NEGATIVE: + case OP_FLOAT_RM_TOWARD_NEGATIVE: return m_manager->mk_const_decl(symbol("roundTowardNegative"), s, finfo); - case OP_RM_TOWARD_ZERO: + case OP_FLOAT_RM_TOWARD_ZERO: return m_manager->mk_const_decl(symbol("roundTowardZero"), s, finfo); default: UNREACHABLE(); @@ -471,20 +471,6 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, } } -func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - if (arity != 1) - m_manager->raise_exception("invalid number of arguments to asIEEEBV"); - if (!is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); - - unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int(); - parameter ps[] = { parameter(float_sz) }; - sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); - symbol name("asIEEEBV"); - return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); -} - func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 3) @@ -528,17 +514,19 @@ func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (k) { - case OP_TO_FLOAT: + case OP_FLOAT_TO_FP: return mk_to_float(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_MINUS_INF: case OP_FLOAT_PLUS_INF: case OP_FLOAT_NAN: + case OP_FLOAT_MINUS_ZERO: + case OP_FLOAT_PLUS_ZERO: return mk_float_const_decl(k, num_parameters, parameters, arity, domain, range); - case OP_RM_NEAREST_TIES_TO_EVEN: - case OP_RM_NEAREST_TIES_TO_AWAY: - case OP_RM_TOWARD_POSITIVE: - case OP_RM_TOWARD_NEGATIVE: - case OP_RM_TOWARD_ZERO: + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: + case OP_FLOAT_RM_TOWARD_POSITIVE: + case OP_FLOAT_RM_TOWARD_NEGATIVE: + case OP_FLOAT_RM_TOWARD_ZERO: return mk_rm_const_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_EQ: case OP_FLOAT_LT: @@ -577,8 +565,6 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_FMA: return mk_fma(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_IEEE_BV: - return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_FP: return mk_from3bv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_UBV: @@ -601,17 +587,17 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO)); op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN)); - op_names.push_back(builtin_name("roundNearestTiesToEven", OP_RM_NEAREST_TIES_TO_EVEN)); - op_names.push_back(builtin_name("roundNearestTiesToAway", OP_RM_NEAREST_TIES_TO_AWAY)); - op_names.push_back(builtin_name("roundTowardPositive", OP_RM_TOWARD_POSITIVE)); - op_names.push_back(builtin_name("roundTowardNegative", OP_RM_TOWARD_NEGATIVE)); - op_names.push_back(builtin_name("roundTowardZero", OP_RM_TOWARD_ZERO)); + op_names.push_back(builtin_name("roundNearestTiesToEven", OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)); + op_names.push_back(builtin_name("roundNearestTiesToAway", OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)); + op_names.push_back(builtin_name("roundTowardPositive", OP_FLOAT_RM_TOWARD_POSITIVE)); + op_names.push_back(builtin_name("roundTowardNegative", OP_FLOAT_RM_TOWARD_NEGATIVE)); + op_names.push_back(builtin_name("roundTowardZero", OP_FLOAT_RM_TOWARD_ZERO)); - op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN)); - op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY)); - op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE)); - op_names.push_back(builtin_name("RTN", OP_RM_TOWARD_NEGATIVE)); - op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO)); + op_names.push_back(builtin_name("RNE", OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)); + op_names.push_back(builtin_name("RNA", OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)); + op_names.push_back(builtin_name("RTP", OP_FLOAT_RM_TOWARD_POSITIVE)); + op_names.push_back(builtin_name("RTN", OP_FLOAT_RM_TOWARD_NEGATIVE)); + op_names.push_back(builtin_name("RTZ", OP_FLOAT_RM_TOWARD_ZERO)); op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS)); op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG)); @@ -643,7 +629,8 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); + op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); + op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); } void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { @@ -670,11 +657,11 @@ bool float_decl_plugin::is_value(app * e) const { if (e->get_family_id() != m_family_id) return false; switch (e->get_decl_kind()) { - case OP_RM_NEAREST_TIES_TO_EVEN: - case OP_RM_NEAREST_TIES_TO_AWAY: - case OP_RM_TOWARD_POSITIVE: - case OP_RM_TOWARD_NEGATIVE: - case OP_RM_TOWARD_ZERO: + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: + case OP_FLOAT_RM_TOWARD_POSITIVE: + case OP_FLOAT_RM_TOWARD_NEGATIVE: + case OP_FLOAT_RM_TOWARD_ZERO: case OP_FLOAT_VALUE: case OP_FLOAT_PLUS_INF: case OP_FLOAT_MINUS_INF: @@ -682,7 +669,7 @@ bool float_decl_plugin::is_value(app * e) const { case OP_FLOAT_MINUS_ZERO: case OP_FLOAT_NAN: return true; - case OP_TO_FLOAT: + case OP_FLOAT_TO_FP: return m_manager->is_value(e->get_arg(0)); default: return false; diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 93ff2e664..98b87f6c9 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -35,11 +35,11 @@ enum float_sort_kind { }; enum float_op_kind { - OP_RM_NEAREST_TIES_TO_EVEN, - OP_RM_NEAREST_TIES_TO_AWAY, - OP_RM_TOWARD_POSITIVE, - OP_RM_TOWARD_NEGATIVE, - OP_RM_TOWARD_ZERO, + OP_FLOAT_RM_NEAREST_TIES_TO_EVEN, + OP_FLOAT_RM_NEAREST_TIES_TO_AWAY, + OP_FLOAT_RM_TOWARD_POSITIVE, + OP_FLOAT_RM_TOWARD_NEGATIVE, + OP_FLOAT_RM_TOWARD_ZERO, OP_FLOAT_VALUE, OP_FLOAT_PLUS_INF, @@ -76,11 +76,9 @@ enum float_op_kind { OP_FLOAT_IS_NEGATIVE, OP_FLOAT_IS_POSITIVE, - OP_TO_FLOAT, - OP_FLOAT_TO_IEEE_BV, - OP_FLOAT_FP, - OP_FLOAT_TO_FP, + OP_FLOAT_TO_FP, + OP_FLOAT_TO_FP_UNSIGNED, OP_FLOAT_TO_UBV, OP_FLOAT_TO_SBV, OP_FLOAT_TO_REAL, @@ -134,9 +132,7 @@ class float_decl_plugin : public decl_plugin { func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); - func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -210,11 +206,11 @@ public: unsigned get_ebits(sort * s); unsigned get_sbits(sort * s); - app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_RM_NEAREST_TIES_TO_EVEN); } - app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_RM_NEAREST_TIES_TO_AWAY); } - app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_RM_TOWARD_POSITIVE); } - app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_RM_TOWARD_NEGATIVE); } - app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_RM_TOWARD_ZERO); } + app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_FLOAT_RM_NEAREST_TIES_TO_EVEN); } + app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_FLOAT_RM_NEAREST_TIES_TO_AWAY); } + app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_POSITIVE); } + app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_NEGATIVE); } + app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_ZERO); } app * mk_nan(unsigned ebits, unsigned sbits); app * mk_plus_inf(unsigned ebits, unsigned sbits); @@ -240,9 +236,9 @@ public: bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } - bool is_to_float(expr * n) { return is_app_of(n, m_fid, OP_TO_FLOAT); } + bool is_to_float(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } - app * mk_to_float(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_TO_FLOAT, arg1, arg2); } + app * mk_to_float(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_TO_FP, arg1, arg2); } app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); } app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } @@ -277,8 +273,6 @@ public: app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } - - app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } }; #endif diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index de4797f80..3fbb7ccf8 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -53,8 +53,8 @@ fpa2bv_converter::~fpa2bv_converter() { } void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { - SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_TO_FLOAT)); - SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); expr_ref sgn(m), s(m), e(m); m_simp.mk_eq(to_app(a)->get_arg(0), to_app(b)->get_arg(0), sgn); @@ -73,8 +73,8 @@ void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { } void fpa2bv_converter::mk_ite(expr * c, expr * t, expr * f, expr_ref & result) { - SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_TO_FLOAT)); - SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); expr_ref sgn(m), s(m), e(m); m_simp.mk_ite(c, to_app(t)->get_arg(0), to_app(f)->get_arg(0), sgn); @@ -2203,7 +2203,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar } void fpa2bv_converter::split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sgn = to_app(e)->get_arg(0); @@ -2252,7 +2252,7 @@ void fpa2bv_converter::mk_is_ninf(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref zero(m); @@ -2261,7 +2261,7 @@ void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_neg(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref one(m); @@ -2424,7 +2424,7 @@ void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) { } void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sort * srt = to_app(e)->get_decl()->get_range(); @@ -2519,11 +2519,11 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) { switch(f->get_decl_kind()) { - case OP_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; - case OP_RM_NEAREST_TIES_TO_EVEN: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3); break; - case OP_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; - case OP_RM_TOWARD_POSITIVE: result = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); break; - case OP_RM_TOWARD_ZERO: result = m_bv_util.mk_numeral(BV_RM_TO_ZERO, 3); break; + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3); break; + case OP_FLOAT_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; + case OP_FLOAT_RM_TOWARD_POSITIVE: result = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); break; + case OP_FLOAT_RM_TOWARD_ZERO: result = m_bv_util.mk_numeral(BV_RM_TO_ZERO, 3); break; default: UNREACHABLE(); } } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index eb539d8ae..d033890be 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -73,7 +73,7 @@ public: SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); SASSERT(m_bv_util.is_bv(significand)); SASSERT(m_bv_util.is_bv(exponent)); - result = m.mk_app(m_util.get_family_id(), OP_TO_FLOAT, sign, significand, exponent); + result = m.mk_app(m_util.get_family_id(), OP_FLOAT_FP, sign, significand, exponent); } void mk_eq(expr * a, expr * b, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 7a245b71a..62554e06e 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -107,11 +107,11 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { if (m_conv.is_float_family(f)) { switch (f->get_decl_kind()) { - case OP_RM_NEAREST_TIES_TO_AWAY: - case OP_RM_NEAREST_TIES_TO_EVEN: - case OP_RM_TOWARD_NEGATIVE: - case OP_RM_TOWARD_POSITIVE: - case OP_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: + case OP_FLOAT_RM_TOWARD_NEGATIVE: + case OP_FLOAT_RM_TOWARD_POSITIVE: + case OP_FLOAT_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE; case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE; @@ -144,8 +144,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; - case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_FP: m_conv.mk_to_float(f, num, args, result); return BR_DONE; case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 04546bb4b..436194844 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -36,7 +36,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { - case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break; + case OP_FLOAT_TO_FP: st = mk_to_fp(f, num_args, args, result); break; case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; @@ -63,8 +63,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; - case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; - case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index a7e1c7bf1..b1947ceb5 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -135,13 +135,7 @@ namespace smt { simp(a->get_arg(2), exp, pr_exp); m_converter.mk_triple(sgn, sig, exp, bv_term); - } - else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { - SASSERT(is_app(t)); - expr_ref bv_e(m); - proof_ref bv_pr(m); - simp(t, bv_term, bv_pr); - } + } else NOT_IMPLEMENTED_YET(); @@ -420,17 +414,6 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } - else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { - expr_ref eq(m); - app * ex_a = to_app(ex); - if (n->get_id() > ex_a->get_id()) - std::swap(n, ex_a); - eq = m.mk_eq(n, ex_a); - ctx.internalize(eq, false); - literal l = ctx.get_literal(eq); - ctx.mk_th_axiom(get_id(), 1, &l); - ctx.mark_as_relevant(l); - } else NOT_IMPLEMENTED_YET(); } diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 5c0d2acca..c833f2be3 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -81,7 +81,7 @@ namespace smt { protected: void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { - SASSERT(is_app_of(e, get_family_id(), OP_TO_FLOAT)); + SASSERT(is_app_of(e, get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sgn = to_app(e)->get_arg(0); sig = to_app(e)->get_arg(1); diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 3de869e15..23809d265 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -116,7 +116,7 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { bv_mdl->eval(a->get_arg(1), sig, true); bv_mdl->eval(a->get_arg(2), exp, true); - SASSERT(a->is_app_of(fu.get_family_id(), OP_TO_FLOAT)); + SASSERT(a->is_app_of(fu.get_family_id(), OP_FLOAT_TO_FP)); #ifdef Z3DEBUG SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); From 7965d24df8a37f26b5f4d722d3c51ba7df4cc124 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 10 Dec 2014 19:36:58 +0000 Subject: [PATCH 084/646] FPA API: added conversion functions to float_decl_plugin Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 118 +++++++++++++++++++++++++--------- src/ast/float_decl_plugin.h | 13 ++-- 2 files changed, 95 insertions(+), 36 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 4f8650610..3941d3a97 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -31,12 +31,12 @@ float_decl_plugin::float_decl_plugin(): void float_decl_plugin::set_manager(ast_manager * m, family_id id) { decl_plugin::set_manager(m, id); - family_id aid = m_manager->mk_family_id("arith"); - m_real_sort = m_manager->mk_sort(aid, REAL_SORT); + m_arith_fid = m_manager->mk_family_id("arith"); + m_real_sort = m_manager->mk_sort(m_arith_fid, REAL_SORT); SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_real_sort); - m_int_sort = m_manager->mk_sort(aid, INT_SORT); + m_int_sort = m_manager->mk_sort(m_arith_fid, INT_SORT); SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_int_sort); @@ -396,8 +396,8 @@ func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, para return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { +func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { if (m_bv_plugin && arity == 3 && is_sort_of(domain[0], m_bv_fid, BV_SORT) && is_sort_of(domain[1], m_bv_fid, BV_SORT) && @@ -423,7 +423,7 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, else if (m_bv_plugin && arity == 2 && is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && is_sort_of(domain[1], m_bv_fid, BV_SORT)) { - // Rounding + 1 BV -> 1 FP + // RoundingMode + 1 BV -> 1 FP if (num_parameters != 2) m_manager->raise_exception("invalid number of parameters to to_fp"); if (!parameters[0].is_int() || !parameters[1].is_int()) @@ -471,51 +471,103 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, } } -func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { +func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + SASSERT(m_bv_plugin); + if (arity != 2) + m_manager->raise_exception("invalid number of arguments to to_fp_unsigned"); + if (!is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT)) + m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); + if (!is_sort_of(domain[1], m_bv_fid, BV_SORT)) + m_manager->raise_exception("sort mismatch, expected second argument of bit-vector sort"); + + // RoundingMode + 1 BV -> 1 FP + if (num_parameters != 2) + m_manager->raise_exception("invalid number of parameters to to_fp_unsigned"); + if (!parameters[0].is_int() || !parameters[1].is_int()) + m_manager->raise_exception("invalid parameter type to to_fp_unsigned"); + + int ebits = parameters[0].get_int(); + int sbits = parameters[1].get_int(); + + sort * fp = mk_float_sort(ebits, sbits); + symbol name("to_fp_unsigned"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + +func_decl * float_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { if (arity != 3) m_manager->raise_exception("invalid number of arguments to fp"); - if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) || + if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) || + (domain[0]->get_parameter(0).get_int() != 1) || !is_sort_of(domain[1], m_bv_fid, BV_SORT) || !is_sort_of(domain[2], m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismatch"); - - sort * fp = mk_float_sort(domain[1]->get_parameter(0).get_int(), domain[2]->get_parameter(0).get_int() + 1); - symbol name("fp"); + m_manager->raise_exception("sort mismatch, expected three bit-vectors, the first one of size 1."); + + int eb = (domain[1])->get_parameter(0).get_int(); + int sb = (domain[2])->get_parameter(0).get_int() + 1; + symbol name("fp"); + sort * fp = mk_float_sort(eb, sb); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - if (!m_bv_plugin) - m_manager->raise_exception("to_fp_unsigned unsupported; use a logic with BV support"); + unsigned arity, sort * const * domain, sort * range) { + SASSERT(m_bv_plugin); if (arity != 2) - m_manager->raise_exception("invalid number of arguments to to_fp_unsigned"); + m_manager->raise_exception("invalid number of arguments to fp.to_ubv"); + if (num_parameters != 1) + m_manager->raise_exception("invalid number of parameters to fp.to_ubv"); + if (parameters[0].is_int()) + m_manager->raise_exception("invalid parameter type; fp.to_ubv expects an int parameter"); if (is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); - if (!is_sort_of(domain[1], m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismatch, expected second argument of BV sort"); + if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); + if (parameters[0].get_int() <= 0) + m_manager->raise_exception("invalid parameter value; fp.to_ubv expects a parameter larger than 0"); - sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); - symbol name("fp.t_ubv"); - return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); + symbol name("fp.to_ubv"); + sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters); + return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k)); } func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - NOT_IMPLEMENTED_YET(); + unsigned arity, sort * const * domain, sort * range) { + SASSERT(m_bv_plugin); + if (arity != 2) + m_manager->raise_exception("invalid number of arguments to fp.to_sbv"); + if (parameters[0].is_int()) + m_manager->raise_exception("invalid parameter type; fp.to_sbv expects an int parameter"); + if (num_parameters != 1) + m_manager->raise_exception("invalid number of parameters to fp.to_sbv"); + if (is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); + if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); + if (parameters[0].get_int() <= 0) + m_manager->raise_exception("invalid parameter value; fp.to_ubv expects a parameter larger than 0"); + + symbol name("fp.to_sbv"); + sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters); + return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k)); } func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - NOT_IMPLEMENTED_YET(); + unsigned arity, sort * const * domain, sort * range) { + if (arity != 1) + m_manager->raise_exception("invalid number of arguments to fp.to_real"); + if (!is_float_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); + + symbol name("fp.to_real"); + return m_manager->mk_func_decl(name, 1, domain, m_real_sort, func_decl_info(m_family_id, k)); } func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { - switch (k) { - case OP_FLOAT_TO_FP: - return mk_to_float(k, num_parameters, parameters, arity, domain, range); + switch (k) { case OP_FLOAT_MINUS_INF: case OP_FLOAT_PLUS_INF: case OP_FLOAT_NAN: @@ -566,13 +618,17 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_FLOAT_FMA: return mk_fma(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_FP: - return mk_from3bv(k, num_parameters, parameters, arity, domain, range); + return mk_fp(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_UBV: return mk_to_ubv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_SBV: return mk_to_sbv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_REAL: return mk_to_real(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_FP: + return mk_to_fp(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_FP_UNSIGNED: + return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); return 0; @@ -628,7 +684,7 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - + op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); } diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 98b87f6c9..92610444a 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -108,6 +108,7 @@ class float_decl_plugin : public decl_plugin { value_table m_value_table; sort * m_real_sort; sort * m_int_sort; + family_id m_arith_fid; family_id m_bv_fid; bv_decl_plugin * m_bv_plugin; @@ -130,11 +131,13 @@ class float_decl_plugin : public decl_plugin { func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); - func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); - func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, From c2b5b6a36b1b20a8d729b8ca53678324dd2f59c6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 10 Dec 2014 19:45:18 +0000 Subject: [PATCH 085/646] typo Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_fpa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index f04b87ea3..6042fc044 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -180,7 +180,7 @@ extern "C" { def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),)) */ - Z3_sort Z3_API Z3_mk_fpa_sort__64(__in Z3_context c); + Z3_sort Z3_API Z3_mk_fpa_sort_64(__in Z3_context c); /** \brief Create the quadruple-precision (128-bit) floating point sort. From 72dbb2a51315e729cf6cadb515acad3b00359edc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 10 Dec 2014 20:04:24 +0000 Subject: [PATCH 086/646] FPA API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 13 ------------- src/ast/fpa/fpa2bv_converter.h | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 19f6d582c..87090dcc9 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3788,19 +3788,6 @@ namespace Microsoft.Z3 return new FPExpr(this, Native.Z3_mk_fpa_convert(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); } - /// - /// Conversion of a floating point term to a bit-vector term in IEEE754 format. - /// - /// - /// The size of the resulting bit-vector is automatically determined. - /// - /// floating point term - public FPExpr MkFPToIEEEBV(FPExpr t) - { - Contract.Ensures(Contract.Result() != null); - return new FPExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject)); - } - #endregion #region Miscellaneous diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index d033890be..08542cd40 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -73,7 +73,7 @@ public: SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); SASSERT(m_bv_util.is_bv(significand)); SASSERT(m_bv_util.is_bv(exponent)); - result = m.mk_app(m_util.get_family_id(), OP_FLOAT_FP, sign, significand, exponent); + result = m.mk_app(m_util.get_family_id(), OP_FLOAT_TO_FP, sign, significand, exponent); } void mk_eq(expr * a, expr * b, expr_ref & result); From d6ac98a494fc6b5e3d6fa9e82250b53ad1027051 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 11 Dec 2014 12:05:52 +0000 Subject: [PATCH 087/646] FPA API: reintroduced to_ieee_bv Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 11 +++++++++++ src/api/z3_fpa.h | 13 +++++++++++++ src/ast/float_decl_plugin.cpp | 20 ++++++++++++++++++++ src/ast/float_decl_plugin.h | 15 +++++++++++---- src/ast/rewriter/float_rewriter.cpp | 1 + src/smt/theory_fpa.cpp | 19 ++++++++++++++++++- 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 12d32c04a..876e3cff5 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -398,4 +398,15 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } + + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_to_ieee_bv(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_float_to_ieee_bv(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + }; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 6042fc044..50ad49590 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -555,6 +555,19 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); + /** + \brief Conversion of a floating point term to a bit-vector term in IEEE754 format. + + \param c logical context. + \param t floating-point term. + + t must have floating point sort. The size of the resulting bit-vector is automatically determined. + + def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); + + /*@}*/ /*@}*/ diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 3941d3a97..231d826b2 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -565,6 +565,21 @@ func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, return m_manager->mk_func_decl(name, 1, domain, m_real_sort, func_decl_info(m_family_id, k)); } +func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 1) + m_manager->raise_exception("invalid number of arguments to asIEEEBV"); + if (!is_float_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); + + unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int(); + parameter ps[] = { parameter(float_sz) }; + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); + symbol name("to_ieee_bv"); + return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + + func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (k) { @@ -629,6 +644,8 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_to_fp(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_FP_UNSIGNED: return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_IEEE_BV: + return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); return 0; @@ -687,6 +704,9 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); + + /* Extensions */ + op_names.push_back(builtin_name("to_ieee_bv", OP_FLOAT_TO_IEEE_BV)); } void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 92610444a..dbd3dda2e 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -82,6 +82,9 @@ enum float_op_kind { OP_FLOAT_TO_UBV, OP_FLOAT_TO_SBV, OP_FLOAT_TO_REAL, + + /* Extensions */ + OP_FLOAT_TO_IEEE_BV, LAST_FLOAT_OP }; @@ -139,12 +142,14 @@ class float_decl_plugin : public decl_plugin { func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); - + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + virtual void set_manager(ast_manager * m, family_id id); unsigned mk_id(mpf const & v); void recycled_id(unsigned id); @@ -276,6 +281,8 @@ public: app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } + + app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } }; #endif diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 436194844..d1e1ab00e 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -68,6 +68,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; + case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; } return st; } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index b1947ceb5..5efac6596 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -135,7 +135,13 @@ namespace smt { simp(a->get_arg(2), exp, pr_exp); m_converter.mk_triple(sgn, sig, exp, bv_term); - } + } + else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + SASSERT(is_app(t)); + expr_ref bv_e(m); + proof_ref bv_pr(m); + simp(t, bv_term, bv_pr); + } else NOT_IMPLEMENTED_YET(); @@ -414,6 +420,17 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } + else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + expr_ref eq(m); + app * ex_a = to_app(ex); + if (n->get_id() > ex_a->get_id()) + std::swap(n, ex_a); + eq = m.mk_eq(n, ex_a); + ctx.internalize(eq, false); + literal l = ctx.get_literal(eq); + ctx.mk_th_axiom(get_id(), 1, &l); + ctx.mark_as_relevant(l); + } else NOT_IMPLEMENTED_YET(); } From b30e61e528b819c18831b903a37ed98291b7db90 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 13 Dec 2014 19:34:55 +0000 Subject: [PATCH 088/646] FPA: bugfixes, leakfixes, added fp.to_real Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 7 +- src/ast/fpa/fpa2bv_converter.cpp | 136 ++++++++++++++++++++++------ src/ast/fpa/fpa2bv_converter.h | 2 +- src/ast/fpa/fpa2bv_rewriter.h | 3 +- src/ast/rewriter/float_rewriter.cpp | 9 ++ src/smt/theory_fpa.cpp | 6 +- src/util/mpf.cpp | 76 ++++++++++------ 7 files changed, 177 insertions(+), 62 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 231d826b2..9b6af92ff 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -413,9 +413,13 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa m_manager->raise_exception("invalid number of parameters to to_fp"); if (!parameters[0].is_int() || !parameters[1].is_int()) m_manager->raise_exception("invalid parameter type to to_fp"); + int ebits = parameters[0].get_int(); int sbits = parameters[1].get_int(); + if (domain[0]->get_parameter(0).get_int() != (ebits + sbits)) + m_manager->raise_exception("sort mismtach; invalid bit-vector size, expected bitvector of size (ebits+sbits)"); + sort * fp = mk_float_sort(ebits, sbits); symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); @@ -461,7 +465,7 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa if (arity != 2 && arity != 3) m_manager->raise_exception("invalid number of arguments to to_fp operator"); if (arity == 3 && domain[2] != m_int_sort) - m_manager->raise_exception("sort mismatch, expected second argument of Int sort"); + m_manager->raise_exception("sort mismatch, expected third argument of Int sort"); if (domain[1] != m_real_sort) m_manager->raise_exception("sort mismatch, expected second argument of Real sort"); @@ -701,6 +705,7 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); + op_names.push_back(builtin_name("fp.to_real", OP_FLOAT_TO_REAL)); op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 3fbb7ccf8..5fd96eace 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1858,9 +1858,9 @@ void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const result = m.mk_and(m.mk_not(t1), t2); } -void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - TRACE("fpa2bv_to_float", for (unsigned i=0; i < num; i++) - tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl; ); +void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_to_fp", for (unsigned i=0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl; ); if (num == 3 && m_bv_util.is_bv(args[0]) && @@ -1884,16 +1884,16 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a rational q; if (!m_arith_util.is_numeral(args[1], q)) - NOT_IMPLEMENTED_YET(); + UNREACHABLE(); rational e; if (!m_arith_util.is_numeral(args[2], e)) - NOT_IMPLEMENTED_YET(); + UNREACHABLE(); SASSERT(e.is_int64()); SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1)); - mpf nte, nta, tp, tn, tz; + scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager); m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator()); m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator()); m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator()); @@ -1914,21 +1914,26 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a mk_value(a_tn->get_decl(), 0, 0, bv_tn); mk_value(a_tz->get_decl(), 0, 0, bv_tz); - mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)), bv_tn, bv_tz, result); - mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)), bv_tp, result, result); - mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)), bv_nta, result, result); - mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)), bv_nte, result, result); + expr_ref c1(m), c2(m), c3(m), c4(m); + c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c2 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c3 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)); + c4 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)); + + mk_ite(c1, bv_tn, bv_tz, result); + mk_ite(c2, bv_tp, result, result); + mk_ite(c3, bv_nta, result, result); + mk_ite(c4, bv_nte, result, result); } else if (num == 1 && m_bv_util.is_bv(args[0])) { sort * s = f->get_range(); unsigned to_sbits = m_util.get_sbits(s); - unsigned to_ebits = m_util.get_ebits(s); + unsigned to_ebits = m_util.get_ebits(s); expr * bv = args[0]; int sz = m_bv_util.get_bv_size(bv); SASSERT((unsigned)sz == to_sbits + to_ebits); - - m_bv_util.mk_extract(sz - 1, sz - 1, bv); + mk_triple(m_bv_util.mk_extract(sz - 1, sz - 1, bv), m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), @@ -2093,8 +2098,8 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a else if (num == 2 && m_util.is_rm(args[0]), m_arith_util.is_real(args[1])) { - // .. other than that, we only support rationals for asFloat - SASSERT(m_util.is_float(f->get_range())); + // .. other than that, we only support rationals for to_fp + SASSERT(m_util.is_float(f->get_range())); unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); @@ -2121,16 +2126,16 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a rational q; m_util.au().is_numeral(args[1], q); - mpf v; + scoped_mpf v(m_mpf_manager); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); - expr * sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v)) ? 1 : 0, 1); - expr * s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits - 1); - expr * e = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits); + expr_ref sgn(m), s(m), e(m), unbiased_exp(m); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits); + mk_bias(unbiased_exp, e); mk_triple(sgn, s, e, result); - - m_util.fm().del(v); } else UNREACHABLE(); @@ -2187,19 +2192,92 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg } void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_to_real", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); SASSERT(num == 1); + SASSERT(f->get_num_parameters() == 0); + SASSERT(is_app_of(args[0], m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + + expr * x = args[0]; + sort * s = m.get_sort(x); + unsigned ebits = m_util.get_ebits(s); + unsigned sbits = m_util.get_sbits(s); - //unsigned ebits = m_util.get_ebits(f->get_range()); - //unsigned sbits = m_util.get_sbits(f->get_range()); - //int width = f->get_parameter(0).get_int(); + sort * rs = m_arith_util.mk_real(); + expr_ref x_is_nan(m), x_is_inf(m), x_is_zero(m); + mk_is_nan(x, x_is_nan); + mk_is_inf(x, x_is_inf); + mk_is_zero(x, x_is_zero); - //expr * rm = args[0]; - //expr * x = args[1]; + expr_ref sgn(m), sig(m), exp(m), lz(m); + unpack(x, sgn, sig, exp, lz, true); + // sig is of the form [1].[sigbits] - //expr * sgn, *s, *e; - //split(x, sgn, s, e); + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(sig) == sbits); + SASSERT(m_bv_util.get_bv_size(exp) == ebits); - NOT_IMPLEMENTED_YET(); + expr_ref rsig(m), bit(m), zero(m), one(m), two(m), bv0(m), bv1(m); + zero = m_arith_util.mk_numeral(rational(0), rs); + one = m_arith_util.mk_numeral(rational(1), rs); + two = m_arith_util.mk_numeral(rational(2), rs); + bv0 = m_bv_util.mk_numeral(0, 1); + bv1 = m_bv_util.mk_numeral(1, 1); + rsig = one; + for (unsigned i = sbits-2; i != (unsigned)-1; i--) + { + bit = m_bv_util.mk_extract(i, i, sig); + rsig = m_arith_util.mk_mul(rsig, two); + rsig = m_arith_util.mk_add(rsig, m.mk_ite(m.mk_eq(bit, bv1), one, zero)); + } + + const mpz & p2 = fu().fm().m_powers2(sbits-1); + expr_ref ep2(m); + ep2 = m_arith_util.mk_numeral(rational(p2), false); + rsig = m_arith_util.mk_div(rsig, ep2); + dbg_decouple("fpa2bv_to_real_ep2", ep2); + dbg_decouple("fpa2bv_to_real_rsig", rsig); + + expr_ref exp_n(m), exp_p(m), exp_is_neg(m), exp_abs(m); + exp_is_neg = m.mk_eq(m_bv_util.mk_extract(ebits - 1, ebits - 1, exp), bv1); + dbg_decouple("fpa2bv_to_real_exp_is_neg", exp_is_neg); + exp_p = m_bv_util.mk_sign_extend(1, exp); + exp_n = m_bv_util.mk_bv_not(m_bv_util.mk_sign_extend(1, exp)); + exp_abs = m.mk_ite(exp_is_neg, exp_n, exp_p); + dbg_decouple("fpa2bv_to_real_exp_abs", exp); + SASSERT(m_bv_util.get_bv_size(exp_abs) == ebits + 1); + + expr_ref exp2(m), prev_bit(m); + exp2 = zero; + prev_bit = bv0; + for (unsigned i = ebits; i != (unsigned)-1; i--) + { + bit = m_bv_util.mk_extract(i, i, exp_abs); + exp2 = m_arith_util.mk_mul(exp2, two); + exp2 = m_arith_util.mk_add(exp2, m.mk_ite(m.mk_eq(bit, prev_bit), zero, one)); + prev_bit = bit; + } + + exp2 = m.mk_ite(exp_is_neg, m_arith_util.mk_div(one, exp2), exp2); + dbg_decouple("fpa2bv_to_real_exp2", exp2); + + expr_ref res(m), two_exp2(m); + two_exp2 = m_arith_util.mk_power(two, exp2); + res = m_arith_util.mk_mul(rsig, two_exp2); + res = m.mk_ite(m.mk_eq(sgn, bv1), m_arith_util.mk_uminus(res), res); + dbg_decouple("fpa2bv_to_real_sig_times_exp2", res); + + TRACE("fpa2bv_to_real", tout << "rsig = " << mk_ismt2_pp(rsig, m) << std::endl; + tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;); + + expr_ref undef(m); + undef = m.mk_fresh_const(0, rs); + + result = m.mk_ite(x_is_zero, zero, res); + result = m.mk_ite(x_is_inf, undef, result); + result = m.mk_ite(x_is_nan, undef, result); + + SASSERT(is_well_sorted(m, result)); } void fpa2bv_converter::split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 08542cd40..caad0875c 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -121,7 +121,7 @@ public: void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 62554e06e..a5ff8f5ca 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -144,11 +144,12 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP: m_conv.mk_to_float(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE; case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index d1e1ab00e..42a4e5660 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -552,5 +552,14 @@ br_status float_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) } br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) { + scoped_mpf fv(m_util.fm()); + + if (m_util.is_value(arg1, fv)) { + scoped_mpq r(m_fm.mpq_manager()); + m_fm.to_rational(fv, r); + result = m_util.au().mk_numeral(r.get(), false); + return BR_DONE; + } + return BR_FAILED; } \ No newline at end of file diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 5efac6596..ba53dc20f 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -136,7 +136,8 @@ namespace smt { m_converter.mk_triple(sgn, sig, exp, bv_term); } - else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV || + term->get_decl_kind() == OP_FLOAT_TO_REAL) { SASSERT(is_app(t)); expr_ref bv_e(m); proof_ref bv_pr(m); @@ -420,7 +421,8 @@ namespace smt { ctx.mark_as_relevant(bv_sig); ctx.mark_as_relevant(bv_exp); } - else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV) { + else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV || + n->get_decl()->get_decl_kind() == OP_FLOAT_TO_REAL) { expr_ref eq(m); app * ex_a = to_app(ex); if (n->get_id() > ex_a->get_id()) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index f5785c072..c4fa17d9a 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -199,35 +199,59 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode o.sign = m_mpq_manager.is_neg(value); m_mpz_manager.set(o.significand, 0); - const mpz & p = m_powers2(sbits+2); - signed lz = 0; - - o.exponent = sbits+2; + const mpz & p = m_powers2(sbits+3); + + scoped_mpq v(m_mpq_manager); + m_mpq_manager.set(v, value); + o.exponent = 0; - // CMW: This could be optimized considerably. - scoped_mpz t(m_mpz_manager); - retry: - m_mpz_manager.mul2k(value.numerator(), lz, t); - m_mpz_manager.machine_div(t, value.denominator(), o.significand); - m_mpz_manager.abs(o.significand); - if (m_mpz_manager.lt(o.significand, p)) { - lz++; - goto retry; - } - o.exponent -= lz; - - bool sticky = false; - while (m_mpz_manager.ge(o.significand, m_powers2(sbits+3))) { - sticky = sticky || !m_mpz_manager.is_even(o.significand); - m_mpz_manager.machine_div2k(o.significand, 1); + // Normalize + while (m_mpq_manager.ge(v, mpq(2))) + { + m_mpq_manager.div(v, mpq(2), v); o.exponent++; } - if (sticky && m_mpz_manager.is_even(o.significand)) - m_mpz_manager.inc(o.significand); - TRACE("mpf_dbg", tout << "QUOTIENT = " << m_mpz_manager.to_string(o.significand) << " shift=" << lz << std::endl;); + while (m_mpq_manager.lt(v, mpq(1))) + { + m_mpq_manager.mul(v, mpq(2), v); + o.exponent--; + } - SASSERT(m_mpz_manager.ge(o.significand, m_powers2(sbits+2))); + m_mpz_manager.set(o.significand, 0); + // o.exponent += sbits ; + + SASSERT(m_mpq_manager.lt(v, mpq(2))); + SASSERT(m_mpq_manager.ge(v, mpq(1))); + + // 1.0 <= v < 2.0 (* 2^o.exponent) + // (and v != 0.0) + for (unsigned i = 0; i < sbits + 3 ; i++) + { + m_mpz_manager.mul(o.significand, mpz(2), o.significand); + if (m_mpq_manager.ge(v, mpq(1))) + m_mpz_manager.add(o.significand, mpz(1), o.significand); + m_mpq_manager.sub(v, mpq(1), v); // v := v - 1.0 + m_mpq_manager.mul(mpq(2), v, v); // v := 2.0 * v + } + + // Sticky + // m_mpz_manager.mul(o.significand, mpz(2), o.significand); + /*if (!m_mpq_manager.is_zero(v)) + m_mpz_manager.add(o.significand, mpz(1), o.significand);*/ + + // bias? + // o.exponent += m_mpz_manager.get_int64(m_powers2.m1(ebits - 1, false)); + + // mpq pow; + // m_mpq_manager.power(mpq(2), sbits + 3, pow); + // m_mpq_manager.div(o.significand, pow, o.significand); + // SASSERT(m_mpz_manager.ge(o.significand, mpq(1.0))); + // SASSERT(m_mpz_manager.lt(o.significand, mpq(2.0))); + + TRACE("mpf_dbg", tout << "sig=" << m_mpz_manager.to_string(o.significand) << " exp=" << o.exponent << + " sticky=" << (!m_mpq_manager.is_zero(v)) << std::endl;); + round(rm, o); } @@ -253,7 +277,6 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode TRACE("mpf_dbg", tout << " f = " << f << " e = " << e << std::endl;); - // [Leo]: potential memory leak. moving q and ex to scoped versions scoped_mpq q(m_mpq_manager); m_mpq_manager.set(q, f.c_str()); @@ -276,9 +299,6 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode if (m_mpq_manager.is_zero(significand)) mk_zero(ebits, sbits, o.sign, o); else { - // [Leo]: The following two lines may produce a memory leak. Moving to scoped version - // mpq sig; - // mpz exp; scoped_mpq sig(m_mpq_manager); scoped_mpz exp(m_mpq_manager); From 4e913bb18c561e47fef33a831cfcd568ad100e19 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 14 Dec 2014 17:34:18 +0000 Subject: [PATCH 089/646] FPA bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 6 ++++-- src/smt/theory_fpa.cpp | 10 +++++----- src/smt/theory_fpa.h | 6 +++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 9b6af92ff..1ae8a2a2c 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -750,8 +750,10 @@ bool float_decl_plugin::is_value(app * e) const { case OP_FLOAT_MINUS_ZERO: case OP_FLOAT_NAN: return true; - case OP_FLOAT_TO_FP: - return m_manager->is_value(e->get_arg(0)); + case OP_FLOAT_FP: + return m_manager->is_value(e->get_arg(0)) && + m_manager->is_value(e->get_arg(1)) && + m_manager->is_value(e->get_arg(2)); default: return false; } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index ba53dc20f..3c6b18349 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -24,11 +24,11 @@ Revision History: namespace smt { - class mk_atom_trail : public trail { + class fpa_atom_trail : public trail { bool_var m_var; public: - mk_atom_trail(bool_var v) : m_var(v) {} - virtual ~mk_atom_trail() {} + fpa_atom_trail(bool_var v) : m_var(v) {} + virtual ~fpa_atom_trail() {} virtual void undo(theory_fpa & th) { theory_fpa::atom * a = th.get_bv2a(m_var); a->~atom(); @@ -87,7 +87,7 @@ namespace smt { ctx.set_var_theory(l.var(), get_id()); pred_atom * a = new (get_region()) pred_atom(l, def); insert_bv2a(l.var(), a); - m_trail_stack.push(mk_atom_trail(l.var())); + m_trail_stack.push(fpa_atom_trail(l.var())); if (!ctx.relevancy()) { ctx.mk_th_axiom(get_id(), l, ~def); @@ -257,7 +257,7 @@ namespace smt { } void theory_fpa::pop_scope_eh(unsigned num_scopes) { - TRACE("bv", tout << num_scopes << "\n";); + TRACE("t_fpa", tout << num_scopes << "\n";); m_trail_stack.pop_scope(num_scopes); unsigned num_old_vars = get_old_num_vars(num_scopes); for (unsigned i = num_old_vars; i < get_num_vars(); i++) { diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index c833f2be3..41374fd8f 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -27,7 +27,11 @@ Revision History: namespace smt { class theory_fpa : public theory { - typedef trail_stack th_trail_stack; + class th_trail_stack : public trail_stack { + public: + th_trail_stack(theory_fpa & th) : trail_stack(th) {} + virtual ~th_trail_stack() {} + }; public: class atom { From f11ee40c38928d84e54ca5fcee404a8cc619f6aa Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 14 Dec 2014 19:09:17 +0000 Subject: [PATCH 090/646] FPA: bug and leak fixes Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 75 ++++++++++++++++++++++++----- src/ast/float_decl_plugin.h | 2 +- src/ast/fpa/fpa2bv_converter.cpp | 50 +++++++++++++++++++ src/ast/fpa/fpa2bv_converter.h | 8 +-- src/ast/rewriter/float_rewriter.cpp | 19 ++++++-- src/ast/rewriter/float_rewriter.h | 1 + src/smt/theory_fpa.cpp | 11 +++-- 7 files changed, 142 insertions(+), 24 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 1ae8a2a2c..625ed9ade 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -457,22 +457,47 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa sort * fp = mk_float_sort(ebits, sbits); symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); - } - else { - // 1 Real -> 1 FP - if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) - m_manager->raise_exception("expecting two integer parameters to to_fp"); - if (arity != 2 && arity != 3) - m_manager->raise_exception("invalid number of arguments to to_fp operator"); - if (arity == 3 && domain[2] != m_int_sort) - m_manager->raise_exception("sort mismatch, expected third argument of Int sort"); - if (domain[1] != m_real_sort) - m_manager->raise_exception("sort mismatch, expected second argument of Real sort"); - + } + else if (arity == 3 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_arith_fid, REAL_SORT) && + is_sort_of(domain[2], m_arith_fid, INT_SORT)) + { + // Rounding + 1 Real + 1 Int -> 1 FP + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to to_fp"); + sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } + else if (arity == 1 && + is_sort_of(domain[0], m_arith_fid, REAL_SORT)) + { + // 1 Real -> 1 FP + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to to_fp"); + if (domain[1] != m_real_sort) + m_manager->raise_exception("sort mismatch, expected one argument of Real sort"); + + sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else if (arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_arith_fid, REAL_SORT)) + { + // Rounding + 1 Real -> 1 FP + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to to_fp"); + + sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else + NOT_IMPLEMENTED_YET(); } func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -759,6 +784,32 @@ bool float_decl_plugin::is_value(app * e) const { } } +bool float_decl_plugin::is_unique_value(app* e) const { + if (e->get_family_id() != m_family_id) + return false; + switch (e->get_decl_kind()) { + case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: + case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: + case OP_FLOAT_RM_TOWARD_POSITIVE: + case OP_FLOAT_RM_TOWARD_NEGATIVE: + case OP_FLOAT_RM_TOWARD_ZERO: + return true; + case OP_FLOAT_PLUS_INF: /* No; +oo == fp(#b0 #b11 #b00) */ + case OP_FLOAT_MINUS_INF: /* Nol -oo == fp #b1 #b11 #b00) */ + case OP_FLOAT_PLUS_ZERO: /* No; +zero == fp #b0 #b00 #b000) */ + case OP_FLOAT_MINUS_ZERO: /* No; -zero == fp #b1 #b00 #b000) */ + case OP_FLOAT_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */ + case OP_FLOAT_VALUE: /* above */ + return false; + case OP_FLOAT_FP: + return m_manager->is_unique_value(e->get_arg(0)) && + m_manager->is_unique_value(e->get_arg(1)) && + m_manager->is_unique_value(e->get_arg(2)); + default: + return false; + } +} + float_util::float_util(ast_manager & m): m_manager(m), m_fid(m.mk_family_id("float")), diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index dbd3dda2e..bd180c45c 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -170,7 +170,7 @@ public: virtual void get_sort_names(svector & sort_names, symbol const & logic); virtual expr * get_some_value(sort * s); virtual bool is_value(app* e) const; - virtual bool is_unique_value(app* e) const { return is_value(e); } + virtual bool is_unique_value(app* e) const; mpf_manager & fm() { return m_fm; } func_decl * mk_value_decl(mpf const & v); diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 5fd96eace..afad59dff 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1870,6 +1870,12 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args // Just keep it here, as there will be something else that uses it. mk_triple(args[0], args[1], args[2], result); } + else if (num == 2 && + m_bv_util.is_bv(args[0]) && + m_bv_util.is_bv(args[1])) + { + mk_to_fp_signed(f, num, args, result); + } else if (num == 3 && m_bv_util.is_bv(args[0]) && m_arith_util.is_numeral(args[1]) && @@ -2143,6 +2149,50 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args SASSERT(is_well_sorted(m, result)); } +void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_to_fp_signed", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); + + // This is meant to be a conversion from signed bitvector to float: + // ; from signed machine integer, represented as a 2's complement bit vector + // ((_ to_fp eb sb) RoundingMode(_ BitVec m) (_ FloatingPoint eb sb)) + + + // Semantics: + //((_ to_fp eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb)): + // Let b in[[(_ BitVec m)]] and let n be the signed integer represented by b (in 2's complement format). + // [[(_ to_fp eb sb)]](r, b) = +/ -infinity if n is too large / too small to be represented as a finite + // number of [[(_ FloatingPoint eb sb)]]; [[(_ to_fp eb sb)]](r, x) = y otherwise, where y is the finite + // number such that [[fp.to_real]](y) is closest to n according to rounding mode r. + + NOT_IMPLEMENTED_YET(); + + SASSERT(m_util.is_float(f->get_range())); + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + unsigned sz = sbits + ebits; + SASSERT(m_bv_util.get_bv_size(args[0]) == 3); + SASSERT(m_bv_util.get_bv_size(args[1]) == sz); + + expr_ref rm(m), x(m); + rm = args[0]; + x = args[1]; + + expr_ref sgn(m), sig(m), exp(m); + sgn = m_bv_util.mk_extract(sz - 1, sz - 1, x); + sig = m_bv_util.mk_extract(sz - ebits - 2, 0, x); + exp = m_bv_util.mk_extract(sz - 2, sz - ebits - 1, x); + + round(f->get_range(), rm, sgn, sig, exp, result); +} + +void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_to_fp_unsigned", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); + + NOT_IMPLEMENTED_YET(); +} + void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index caad0875c..e83754e38 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -121,11 +121,13 @@ public: void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + + void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result); diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 42a4e5660..583268c34 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -37,6 +37,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { case OP_FLOAT_TO_FP: st = mk_to_fp(f, num_args, args, result); break; + case OP_FLOAT_TO_FP_UNSIGNED: st = mk_to_fp_unsigned(f, num_args, args, result); break; case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; @@ -86,10 +87,10 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons return BR_FAILED; rational q; - mpf q_mpf; + scoped_mpf q_mpf(m_util.fm()); if (m_util.au().is_numeral(args[1], q)) { TRACE("fp_rewriter", tout << "q: " << q << std::endl; ); - mpf v; + scoped_mpf v(m_util.fm()); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); result = m_util.mk_value(v); m_util.fm().del(v); @@ -98,7 +99,7 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons } else if (m_util.is_value(args[1], q_mpf)) { TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; ); - mpf v; + scoped_mpf v(m_util.fm()); m_util.fm().set(v, ebits, sbits, rm, q_mpf); result = m_util.mk_value(v); m_util.fm().del(v); @@ -126,7 +127,7 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons return BR_FAILED; TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";); - mpf v; + scoped_mpf v(m_util.fm()); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator()); result = m_util.mk_value(v); m_util.fm().del(v); @@ -137,6 +138,16 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons } } +br_status float_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { + SASSERT(f->get_num_parameters() == 2); + SASSERT(f->get_parameter(0).is_int()); + SASSERT(f->get_parameter(1).is_int()); + unsigned ebits = f->get_parameter(0).get_int(); + unsigned sbits = f->get_parameter(1).get_int(); + + return BR_FAILED; +} + br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { diff --git a/src/ast/rewriter/float_rewriter.h b/src/ast/rewriter/float_rewriter.h index 4d8cec856..31c571f32 100644 --- a/src/ast/rewriter/float_rewriter.h +++ b/src/ast/rewriter/float_rewriter.h @@ -75,6 +75,7 @@ public: br_status mk_to_ieee_bv(expr * arg1, expr_ref & result); br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); + br_status mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result); br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result); diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 3c6b18349..26ee88226 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -336,10 +336,13 @@ namespace smt { << mk_ismt2_pp(e_exp, m) << "]\n";); rational sgn_r(0), sig_r(0), exp_r(0); - - bv_th->get_fixed_value(e_sgn, sgn_r); // OK to fail - bv_th->get_fixed_value(e_sig, sig_r); // OK to fail - bv_th->get_fixed_value(e_exp, exp_r); // OK to fail + + if (ctx.e_internalized(bv_sgn) && ctx.get_enode(bv_sgn)->get_num_th_vars() > 0) + bv_th->get_fixed_value(e_sgn, sgn_r); // OK to fail + if (ctx.e_internalized(bv_sig) && ctx.get_enode(bv_sig)->get_num_th_vars() > 0) + bv_th->get_fixed_value(e_sig, sig_r); // OK to fail + if (ctx.e_internalized(bv_exp) && ctx.get_enode(bv_exp)->get_num_th_vars() > 0) + bv_th->get_fixed_value(e_exp, exp_r); // OK to fail TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " << sig_r.to_string() << " " From 1244d5a22ef196ce730ebf9fd94970419cbdcb8d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 16 Dec 2014 15:28:52 +0000 Subject: [PATCH 091/646] Python API: Added BVRedAnd, BVRedOr Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index db629cd2d..713226e23 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -3813,6 +3813,18 @@ def RepeatBitVec(n, a): _z3_assert(is_bv(a), "Second argument must be a Z3 Bitvector expression") return BitVecRef(Z3_mk_repeat(a.ctx_ref(), n, a.as_ast()), a.ctx) +def BVRedAnd(a): + """Return the reduction-and expression of `a`.""" + if __debug__: + _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") + return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx) + +def BVRedOr(a): + """Return the reduction-and expression of `a`.""" + if __debug__: + _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") + return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx) + ######################################### # # Arrays From d53fdb284858f331b3d577067926a626d23e8571 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 16 Dec 2014 15:36:31 +0000 Subject: [PATCH 092/646] typo Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 713226e23..720335d41 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -3820,7 +3820,7 @@ def BVRedAnd(a): return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx) def BVRedOr(a): - """Return the reduction-and expression of `a`.""" + """Return the reduction-or expression of `a`.""" if __debug__: _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx) From f4d256ef306dfb22aef306e73d1d7a90668aae5b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 16 Dec 2014 11:20:34 -0800 Subject: [PATCH 093/646] fix issue 153: assert rem/mod axiom no matter what is status of second argument Signed-off-by: Nikolaj Bjorner --- README | 2 ++ src/smt/smt_context.cpp | 7 +++---- src/smt/theory_arith_core.h | 33 ++++++++++++++++----------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README b/README index 1ca0cd577..074abd2a3 100644 --- a/README +++ b/README @@ -41,3 +41,5 @@ Remark: clang does not support OpenMP yet. cd build make + +To clean Z3 you can delete the build directory and run the mk_make.py script again. \ No newline at end of file diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index f3f2d4948..957d5ebe7 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -3321,13 +3321,13 @@ namespace smt { CASSERT("dyn_ack", check_clauses(m_lemmas) && check_clauses(m_aux_clauses)); } - if (resource_limits_exceeded()) { - SASSERT(!inconsistent()); + if (resource_limits_exceeded() && !inconsistent()) { return l_undef; } if (m_base_lvl == m_scope_lvl && m_fparams.m_simplify_clauses) simplify_clauses(); + if (!decide()) { final_check_status fcs = final_check(); @@ -3342,8 +3342,7 @@ namespace smt { } } - if (resource_limits_exceeded()) { - SASSERT(!inconsistent()); + if (resource_limits_exceeded() && !inconsistent()) { return l_undef; } } diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 66d232227..a7f442e1f 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -336,8 +336,9 @@ namespace smt { theory_var theory_arith::internalize_rem(app * n) { theory_var s = mk_binary_op(n); context & ctx = get_context(); - if (!ctx.relevancy()) + if (!ctx.relevancy()) { mk_rem_axiom(n->get_arg(0), n->get_arg(1)); + } return s; } @@ -456,22 +457,20 @@ namespace smt { template void theory_arith::mk_rem_axiom(expr * dividend, expr * divisor) { - if (!m_util.is_zero(divisor)) { - // if divisor is zero, then rem is an uninterpreted function. - ast_manager & m = get_manager(); - expr * zero = m_util.mk_numeral(rational(0), true); - expr * rem = m_util.mk_rem(dividend, divisor); - expr * mod = m_util.mk_mod(dividend, divisor); - expr_ref dltz(m), eq1(m), eq2(m); - dltz = m_util.mk_lt(divisor, zero); - eq1 = m.mk_eq(rem, mod); - eq2 = m.mk_eq(rem, m_util.mk_sub(zero, mod)); - // n < 0 || rem(a,n) = mod(a, n) - mk_axiom(dltz, eq1); - dltz = m.mk_not(dltz); - // !n < 0 || rem(a,n) = -mod(a, n) - mk_axiom(dltz, eq2); - } + // if divisor is zero, then rem is an uninterpreted function. + ast_manager & m = get_manager(); + expr * zero = m_util.mk_numeral(rational(0), true); + expr * rem = m_util.mk_rem(dividend, divisor); + expr * mod = m_util.mk_mod(dividend, divisor); + expr_ref dltz(m), eq1(m), eq2(m); + dltz = m_util.mk_lt(divisor, zero); + eq1 = m.mk_eq(rem, mod); + eq2 = m.mk_eq(rem, m_util.mk_sub(zero, mod)); + // n < 0 || rem(a,n) = mod(a, n) + mk_axiom(dltz, eq1); + dltz = m.mk_not(dltz); + // !n < 0 || rem(a,n) = -mod(a, n) + mk_axiom(dltz, eq2); } // From 47325c5fd3f8bee823a8a9a6a89930309cf2999f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 16 Dec 2014 23:59:27 +0000 Subject: [PATCH 094/646] FPA: bugfixes, naming convention, core theory additions Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 2 +- src/ast/float_decl_plugin.cpp | 9 +- src/ast/float_decl_plugin.h | 12 +- src/ast/fpa/fpa2bv_converter.cpp | 184 ++++++++++++++++++++++------ src/ast/fpa/fpa2bv_converter.h | 4 +- src/ast/fpa/fpa2bv_rewriter.h | 4 +- src/ast/rewriter/float_rewriter.cpp | 16 +-- src/qe/nlarith_util.cpp | 8 +- src/smt/theory_fpa.cpp | 128 +++++++++++-------- src/smt/theory_fpa.h | 34 ++++- 10 files changed, 287 insertions(+), 114 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 876e3cff5..bbf27d25d 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -149,7 +149,7 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_minus_inf(to_sort(s)) : ctx->float_util().mk_plus_inf(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_ninf(to_sort(s)) : ctx->float_util().mk_pinf(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 625ed9ade..816df906e 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -163,6 +163,11 @@ decl_plugin * float_decl_plugin::mk_fresh() { } sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { + if (ebits > sbits) + m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported"); + if (ebits <= 2) + m_manager->raise_exception("floating point sorts with ebits <= 2 are currently not supported"); + parameter p1(ebits), p2(sbits); parameter ps[2] = { p1, p2 }; sort_size sz; @@ -841,13 +846,13 @@ app * float_util::mk_nan(unsigned ebits, unsigned sbits) { return mk_value(v); } -app * float_util::mk_plus_inf(unsigned ebits, unsigned sbits) { +app * float_util::mk_pinf(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_pinf(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_minus_inf(unsigned ebits, unsigned sbits) { +app * float_util::mk_ninf(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_ninf(ebits, sbits, v); return mk_value(v); diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index bd180c45c..ebf424578 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -221,11 +221,11 @@ public: app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_ZERO); } app * mk_nan(unsigned ebits, unsigned sbits); - app * mk_plus_inf(unsigned ebits, unsigned sbits); - app * mk_minus_inf(unsigned ebits, unsigned sbits); + app * mk_pinf(unsigned ebits, unsigned sbits); + app * mk_ninf(unsigned ebits, unsigned sbits); app * mk_nan(sort * s) { return mk_nan(get_ebits(s), get_sbits(s)); } - app * mk_plus_inf(sort * s) { return mk_plus_inf(get_ebits(s), get_sbits(s)); } - app * mk_minus_inf(sort * s) { return mk_minus_inf(get_ebits(s), get_sbits(s)); } + app * mk_pinf(sort * s) { return mk_pinf(get_ebits(s), get_sbits(s)); } + app * mk_ninf(sort * s) { return mk_ninf(get_ebits(s), get_sbits(s)); } app * mk_value(mpf const & v) { return m_plugin->mk_value(v); } bool is_value(expr * n) { return m_plugin->is_value(n); } @@ -238,8 +238,8 @@ public: app * mk_nzero(sort * s) { return mk_nzero(get_ebits(s), get_sbits(s)); } bool is_nan(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nan(v); } - bool is_plus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pinf(v); } - bool is_minus_inf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); } + bool is_pinf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pinf(v); } + bool is_ninf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); } bool is_zero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_zero(v); } bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index afad59dff..be951098a 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -103,9 +103,9 @@ void fpa2bv_converter::mk_value(func_decl * f, unsigned num, expr * const * args mk_nan(f, result); else if (m_util.fm().is_inf(v)) { if (m_util.fm().sgn(v)) - mk_minus_inf(f, result); + mk_ninf(f, result); else - mk_plus_inf(f, result); + mk_pinf(f, result); } else { expr_ref bv_sgn(m), bv_sig(m), e(m), biased_exp(m); @@ -298,7 +298,7 @@ void fpa2bv_converter::mk_rm_const(func_decl * f, expr_ref & result) { } } -void fpa2bv_converter::mk_plus_inf(func_decl * f, expr_ref & result) { +void fpa2bv_converter::mk_pinf(func_decl * f, expr_ref & result) { sort * srt = f->get_range(); SASSERT(is_float(srt)); unsigned sbits = m_util.get_sbits(srt); @@ -311,7 +311,7 @@ void fpa2bv_converter::mk_plus_inf(func_decl * f, expr_ref & result) { result); } -void fpa2bv_converter::mk_minus_inf(func_decl * f, expr_ref & result) { +void fpa2bv_converter::mk_ninf(func_decl * f, expr_ref & result) { sort * srt = f->get_range(); SASSERT(is_float(srt)); unsigned sbits = m_util.get_sbits(srt); @@ -633,8 +633,8 @@ void fpa2bv_converter::mk_mul(func_decl * f, unsigned num, expr * const * args, mk_nan(f, nan); mk_nzero(f, nzero); mk_pzero(f, pzero); - mk_minus_inf(f, ninf); - mk_plus_inf(f, pinf); + mk_ninf(f, ninf); + mk_pinf(f, pinf); expr_ref x_is_nan(m), x_is_zero(m), x_is_pos(m), x_is_inf(m); expr_ref y_is_nan(m), y_is_zero(m), y_is_pos(m), y_is_inf(m); @@ -781,8 +781,8 @@ void fpa2bv_converter::mk_div(func_decl * f, unsigned num, expr * const * args, mk_nan(f, nan); mk_nzero(f, nzero); mk_pzero(f, pzero); - mk_minus_inf(f, ninf); - mk_plus_inf(f, pinf); + mk_ninf(f, ninf); + mk_pinf(f, pinf); expr_ref x_is_nan(m), x_is_zero(m), x_is_pos(m), x_is_inf(m); expr_ref y_is_nan(m), y_is_zero(m), y_is_pos(m), y_is_inf(m); @@ -927,8 +927,8 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args, mk_nan(f, nan); mk_nzero(f, nzero); mk_pzero(f, pzero); - mk_minus_inf(f, ninf); - mk_plus_inf(f, pinf); + mk_ninf(f, ninf); + mk_pinf(f, pinf); expr_ref x_is_nan(m), x_is_zero(m), x_is_pos(m), x_is_inf(m); expr_ref y_is_nan(m), y_is_zero(m), y_is_pos(m), y_is_inf(m); @@ -1137,8 +1137,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, mk_nan(f, nan); mk_nzero(f, nzero); mk_pzero(f, pzero); - mk_minus_inf(f, ninf); - mk_plus_inf(f, pinf); + mk_ninf(f, ninf); + mk_pinf(f, pinf); expr_ref x_is_nan(m), x_is_zero(m), x_is_pos(m), x_is_neg(m), x_is_inf(m); expr_ref y_is_nan(m), y_is_zero(m), y_is_pos(m), y_is_neg(m), y_is_inf(m); @@ -1447,8 +1447,8 @@ void fpa2bv_converter::mk_sqrt(func_decl * f, unsigned num, expr * const * args, mk_nan(f, nan); mk_nzero(f, nzero); mk_pzero(f, pzero); - mk_minus_inf(f, ninf); - mk_plus_inf(f, pinf); + mk_ninf(f, ninf); + mk_pinf(f, pinf); expr_ref x_is_nan(m), x_is_zero(m), x_is_pos(m), x_is_inf(m); mk_is_nan(x, x_is_nan); @@ -1871,9 +1871,11 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args mk_triple(args[0], args[1], args[2], result); } else if (num == 2 && - m_bv_util.is_bv(args[0]) && + m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && m_bv_util.is_bv(args[1])) { + mk_to_fp_signed(f, num, args, result); } else if (num == 3 && @@ -1968,8 +1970,8 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args one1 = m_bv_util.mk_numeral(1, 1); expr_ref ninf(m), pinf(m); - mk_plus_inf(f, pinf); - mk_minus_inf(f, ninf); + mk_pinf(f, pinf); + mk_ninf(f, ninf); // NaN -> NaN mk_is_nan(x, c1); @@ -2152,38 +2154,146 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_fp_signed", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); - - // This is meant to be a conversion from signed bitvector to float: + + // This is a conversion from signed bitvector to float: // ; from signed machine integer, represented as a 2's complement bit vector // ((_ to_fp eb sb) RoundingMode(_ BitVec m) (_ FloatingPoint eb sb)) - - - // Semantics: - //((_ to_fp eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb)): + // Semantics: // Let b in[[(_ BitVec m)]] and let n be the signed integer represented by b (in 2's complement format). // [[(_ to_fp eb sb)]](r, b) = +/ -infinity if n is too large / too small to be represented as a finite // number of [[(_ FloatingPoint eb sb)]]; [[(_ to_fp eb sb)]](r, x) = y otherwise, where y is the finite - // number such that [[fp.to_real]](y) is closest to n according to rounding mode r. - - NOT_IMPLEMENTED_YET(); + // number such that [[fp.to_real]](y) is closest to n according to rounding mode r. + SASSERT(num == 2); SASSERT(m_util.is_float(f->get_range())); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - unsigned sz = sbits + ebits; - SASSERT(m_bv_util.get_bv_size(args[0]) == 3); - SASSERT(m_bv_util.get_bv_size(args[1]) == sz); + SASSERT(m_bv_util.is_bv(args[0])); + SASSERT(m_bv_util.is_bv(args[1])); expr_ref rm(m), x(m); rm = args[0]; x = args[1]; - expr_ref sgn(m), sig(m), exp(m); - sgn = m_bv_util.mk_extract(sz - 1, sz - 1, x); - sig = m_bv_util.mk_extract(sz - ebits - 2, 0, x); - exp = m_bv_util.mk_extract(sz - 2, sz - ebits - 1, x); + dbg_decouple("fpa2bv_to_fp_signed_x", x); - round(f->get_range(), rm, sgn, sig, exp, result); + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + unsigned f_sz = sbits + ebits; + unsigned bv_sz = m_bv_util.get_bv_size(x); + SASSERT(m_bv_util.get_bv_size(rm) == 3); + + //if (bv_sz < f_sz) { + // x = m_bv_util.mk_zero_extend(f_sz - bv_sz, x); + // bv_sz = f_sz; + //} + + expr_ref bv0_1(m), bv1_1(m), bv0_sz(m), bv1_sz(m); + bv0_1 = m_bv_util.mk_numeral(0, 1); + bv1_1 = m_bv_util.mk_numeral(1, 1); + bv0_sz = m_bv_util.mk_numeral(0, bv_sz); + bv1_sz = m_bv_util.mk_numeral(1, bv_sz); + + expr_ref is_zero(m), nzero(m), pzero(m), ninf(m), pinf(m); + is_zero = m.mk_eq(x, bv0_sz); + mk_nzero(f, nzero); + mk_pzero(f, pzero); + mk_ninf(f, ninf); + mk_pinf(f, pinf); + + // Special case: x == 0 -> p/n zero + expr_ref c1(m), v1(m), rm_is_to_neg(m); + c1 = is_zero; + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); + mk_ite(rm_is_to_neg, nzero, pzero, v1); + + // Special case: x != 0 + expr_ref is_neg_bit(m), exp_too_large(m), sig_4(m), exp_2(m); + expr_ref is_neg(m), x_abs(m); + is_neg_bit = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, x); + is_neg = m.mk_eq(is_neg_bit, bv1_1); + x_abs = m.mk_ite(is_neg, m_bv_util.mk_bv_neg(x), x); + dbg_decouple("fpa2bv_to_fp_signed_is_neg", is_neg); + // x_abs has an extra bit in the front. + // x_abs is [bv_sz-1, bv_sz-2] . [bv_sz-3 ... 0] * 2^(bv_sz-2) + // bv_sz-2 is the "1.0" bit for the rounder. + + expr_ref lz(m), e_bv_sz(m), e_rest_sz(m); + mk_leading_zeros(x_abs, bv_sz, lz); + e_bv_sz = m_bv_util.mk_numeral(bv_sz, bv_sz); + e_rest_sz = m_bv_util.mk_bv_sub(e_bv_sz, lz); + SASSERT(m_bv_util.get_bv_size(lz) == m_bv_util.get_bv_size(e_bv_sz)); + dbg_decouple("fpa2bv_to_fp_signed_lz", lz); + expr_ref shifted_sig(m); + shifted_sig = m_bv_util.mk_bv_shl(x_abs, lz); + + expr_ref sticky(m); + // shifted_sig is [bv_sz-1, bv_sz-2] . [bv_sz-3 ... 0] * 2^(bv_sz-2) * 2^(-lz) + unsigned sig_sz = sbits + 4; // we want extra rounding bits. + if (sig_sz <= bv_sz) { + expr_ref sig_rest(m); + sig_4 = m_bv_util.mk_extract(bv_sz - 1, bv_sz - sig_sz + 1, shifted_sig); // one short + sig_rest = m_bv_util.mk_extract(bv_sz - sig_sz, 0, shifted_sig); + sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest); + sig_4 = m_bv_util.mk_concat(sig_4, sticky); + } + else { + unsigned extra_bits = sig_sz - bv_sz; + expr_ref extra_zeros(m); + extra_zeros = m_bv_util.mk_numeral(0, extra_bits); + sig_4 = m_bv_util.mk_concat(shifted_sig, extra_zeros); + lz = m_bv_util.mk_bv_add(m_bv_util.mk_concat(extra_zeros, lz), + m_bv_util.mk_numeral(extra_bits, sig_sz)); + bv_sz = bv_sz + extra_bits; + SASSERT(is_well_sorted(m, lz)); + } + SASSERT(m_bv_util.get_bv_size(sig_4) == sig_sz); + + expr_ref s_exp(m), exp_rest(m); + s_exp = m_bv_util.mk_bv_sub(m_bv_util.mk_numeral(bv_sz - 2, bv_sz), lz); + // s_exp = (bv_sz-2) + (-lz) signed + SASSERT(m_bv_util.get_bv_size(s_exp) == bv_sz); + + unsigned exp_sz = ebits + 2; // (+2 for rounder) + exp_2 = m_bv_util.mk_extract(exp_sz - 1, 0, s_exp); + // the remaining bits are 0 if ebits is large enough. + exp_too_large = m.mk_false(); // This is always in range. + + // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits. + // exp < bv_sz (+sign bit which is [0]) + unsigned exp_worst_case_sz = (unsigned)((log(bv_sz) / log(2)) + 1); + + if (exp_sz < exp_worst_case_sz) { + // exp_sz < exp_worst_case_sz and exp >= 0. + // Take the maximum legal exponent; this + // allows us to keep the most precision. + expr_ref max_exp(m), max_exp_bvsz(m); + mk_max_exp(exp_sz, max_exp); + max_exp_bvsz = m_bv_util.mk_zero_extend(bv_sz - exp_sz, max_exp); + + exp_too_large = m_bv_util.mk_ule(m_bv_util.mk_bv_add( + max_exp_bvsz, + m_bv_util.mk_numeral(1, bv_sz)), + s_exp); + sig_4 = m.mk_ite(exp_too_large, m_bv_util.mk_numeral(0, sig_sz), sig_4); + exp_2 = m.mk_ite(exp_too_large, max_exp, exp_2); + } + dbg_decouple("fpa2bv_to_fp_signed_exp_too_large", exp_too_large); + + expr_ref sgn(m), sig(m), exp(m); + sgn = is_neg_bit; + sig = sig_4; + exp = exp_2; + + dbg_decouple("fpa2bv_to_fp_signed_sgn", sgn); + dbg_decouple("fpa2bv_to_fp_signed_sig", sig); + dbg_decouple("fpa2bv_to_fp_signed_exp", exp); + + SASSERT(m_bv_util.get_bv_size(sig) == sbits + 4); + SASSERT(m_bv_util.get_bv_size(exp) == ebits + 2); + + expr_ref v2(m); + round(f->get_range(), rm, sgn, sig, exp, v2); + + mk_ite(c1, v1, v2, result); } void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -2538,7 +2648,7 @@ void fpa2bv_converter::mk_bias(expr * e, expr_ref & result) { void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) { unsigned ebits = m_bv_util.get_bv_size(e); - SASSERT(ebits >= 3); + SASSERT(ebits >= 2); expr_ref e_plus_one(m); e_plus_one = m_bv_util.mk_bv_add(e, m_bv_util.mk_numeral(1, ebits)); diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index e83754e38..eb4435132 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -86,8 +86,8 @@ public: void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_var(unsigned base_inx, sort * srt, expr_ref & result); - void mk_plus_inf(func_decl * f, expr_ref & result); - void mk_minus_inf(func_decl * f, expr_ref & result); + void mk_pinf(func_decl * f, expr_ref & result); + void mk_ninf(func_decl * f, expr_ref & result); void mk_nan(func_decl * f, expr_ref & result); void mk_nzero(func_decl *f, expr_ref & result); void mk_pzero(func_decl *f, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index a5ff8f5ca..bb42bdf5d 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -113,8 +113,8 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_RM_TOWARD_POSITIVE: case OP_FLOAT_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; - case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE; - case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE; + case OP_FLOAT_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE; + case OP_FLOAT_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE; case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE; case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE; diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 583268c34..3c1f51990 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -205,14 +205,14 @@ br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) { result = arg1; return BR_DONE; } - if (m_util.is_plus_inf(arg1)) { + if (m_util.is_pinf(arg1)) { // - +oo --> -oo - result = m_util.mk_minus_inf(m().get_sort(arg1)); + result = m_util.mk_ninf(m().get_sort(arg1)); return BR_DONE; } - if (m_util.is_minus_inf(arg1)) { + if (m_util.is_ninf(arg1)) { // - -oo -> +oo - result = m_util.mk_plus_inf(m().get_sort(arg1)); + result = m_util.mk_pinf(m().get_sort(arg1)); return BR_DONE; } if (m_util.is_neg(arg1)) { @@ -366,22 +366,22 @@ br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { result = m().mk_false(); return BR_DONE; } - if (m_util.is_minus_inf(arg1)) { + if (m_util.is_ninf(arg1)) { // -oo < arg2 --> not(arg2 = -oo) and not(arg2 = NaN) result = m().mk_and(m().mk_not(m().mk_eq(arg2, arg1)), mk_neq_nan(arg2)); return BR_REWRITE3; } - if (m_util.is_minus_inf(arg2)) { + if (m_util.is_ninf(arg2)) { // arg1 < -oo --> false result = m().mk_false(); return BR_DONE; } - if (m_util.is_plus_inf(arg1)) { + if (m_util.is_pinf(arg1)) { // +oo < arg2 --> false result = m().mk_false(); return BR_DONE; } - if (m_util.is_plus_inf(arg2)) { + if (m_util.is_pinf(arg2)) { // arg1 < +oo --> not(arg1 = +oo) and not(arg1 = NaN) result = m().mk_and(m().mk_not(m().mk_eq(arg1, arg2)), mk_neq_nan(arg1)); return BR_REWRITE3; diff --git a/src/qe/nlarith_util.cpp b/src/qe/nlarith_util.cpp index c555b71f1..fce54aaa4 100644 --- a/src/qe/nlarith_util.cpp +++ b/src/qe/nlarith_util.cpp @@ -1492,11 +1492,11 @@ namespace nlarith { } fml = mk_and(equivs.size(), equivs.c_ptr()); } - void mk_plus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { + void mk_pinf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { plus_inf_subst sub(*this); mk_inf_sign(sub, literals, fml, new_atoms); } - void mk_minus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { + void mk_ninf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { minus_inf_subst sub(*this); mk_inf_sign(sub, literals, fml, new_atoms); } @@ -1704,10 +1704,10 @@ namespace nlarith { app_ref fml(m()); app_ref_vector new_atoms(m()); if (is_pos) { - mk_plus_inf_sign(literals, fml, new_atoms); + mk_pinf_sign(literals, fml, new_atoms); } else { - mk_minus_inf_sign(literals, fml, new_atoms); + mk_ninf_sign(literals, fml, new_atoms); } simple_branch* br = alloc(simple_branch, m(), fml); swap_atoms(br, literals.lits(), new_atoms); diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 26ee88226..7552e276b 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -49,6 +49,24 @@ namespace smt { { } + void theory_fpa::add_extra_assertions() + { + ast_manager & m = get_manager(); + context & ctx = get_context(); + simplifier & simp = ctx.get_simplifier(); + + expr_ref_vector::iterator it = m_converter.extra_assertions.begin(); + expr_ref_vector::iterator end = m_converter.extra_assertions.end(); + for (; it != end; it++) { + expr_ref t(m); + proof_ref t_pr(m); + simp(*it, t, t_pr); + TRACE("t_fpa", tout << "extra: " << mk_ismt2_pp(t, m) << "\n";); + ctx.internalize_assertion(t, t_pr, 0); + } + m_converter.extra_assertions.reset(); + } + void theory_fpa::mk_bv_eq(expr * x, expr * y) { SASSERT(get_sort(x)->get_family_id() == m_converter.bu().get_family_id()); SASSERT(get_sort(y)->get_family_id() == m_converter.bu().get_family_id()); @@ -94,6 +112,8 @@ namespace smt { ctx.mk_th_axiom(get_id(), ~l, def); } + add_extra_assertions(); + return true; } @@ -134,7 +154,7 @@ namespace smt { simp(a->get_arg(1), sig, pr_sig); simp(a->get_arg(2), exp, pr_exp); - m_converter.mk_triple(sgn, sig, exp, bv_term); + m_converter.mk_triple(sgn, sig, exp, bv_term); } else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV || term->get_decl_kind() == OP_FLOAT_TO_REAL) { @@ -149,7 +169,9 @@ namespace smt { TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(bv_term, get_manager()) << "\n";); SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, bv_term, 0); + m_trans_map.insert(term, bv_term, 0); + + add_extra_assertions(); enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true); theory_var v = mk_var(e); @@ -176,11 +198,15 @@ namespace smt { m_rw(owner, converted); simp(converted, converted, pr); m_trans_map.insert(owner, converted, 0); + + add_extra_assertions(); sort * owner_sort = m.get_sort(owner); if (m_converter.is_rm(owner_sort)) { bv_util & bu = m_converter.bu(); - bu.mk_ule(converted, bu.mk_numeral(4, bu.get_bv_size(converted))); + expr_ref t(m); + t = bu.mk_ule(converted, bu.mk_numeral(4, bu.get_bv_size(converted))); + ctx.internalize_assertion(t, proof_ref(m), 0); } TRACE("t_fpa", tout << "new theory var (const): " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); @@ -191,7 +217,8 @@ namespace smt { TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); - + float_util & fu = m_converter.fu(); + app * ax = get_enode(x)->get_owner(); app * ay = get_enode(y)->get_owner(); expr * ex, *ey; @@ -199,7 +226,7 @@ namespace smt { m_trans_map.get(ax, ex, px); m_trans_map.get(ay, ey, py); - if (m_converter.fu().is_float(get_enode(x)->get_owner())) { + if (fu.is_float(get_enode(x)->get_owner())) { expr * sgn_x, *sig_x, *exp_x; expr * sgn_y, *sig_y, *exp_y; split_triple(ex, sgn_x, sig_x, exp_x); @@ -209,7 +236,7 @@ namespace smt { mk_bv_eq(sig_x, sig_y); mk_bv_eq(exp_x, exp_y); } - else if (m_converter.fu().is_rm(get_enode(x)->get_owner())) { + else if (fu.is_rm(get_enode(x)->get_owner())) { mk_bv_eq(ex, ey); } else @@ -220,7 +247,8 @@ namespace smt { TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << "\n";); ast_manager & m = get_manager(); context & ctx = get_context(); - + float_util & fu = m_converter.fu(); + app * ax = get_enode(x)->get_owner(); app * ay = get_enode(y)->get_owner(); expr * ex, *ey; @@ -230,7 +258,7 @@ namespace smt { expr_ref deq(m); - if (m_converter.fu().is_float(m.get_sort(get_enode(x)->get_owner()))) { + if (fu.is_float(m.get_sort(get_enode(x)->get_owner()))) { expr * sgn_x, *sig_x, *exp_x; expr * sgn_y, *sig_y, *exp_y; split_triple(ex, sgn_x, sig_x, exp_x); @@ -240,7 +268,7 @@ namespace smt { m.mk_not(m.mk_eq(sig_x, sig_y)), m.mk_not(m.mk_eq(exp_x, exp_y))); } - else if (m_converter.fu().is_rm(m.get_sort(get_enode(x)->get_owner()))) { + else if (fu.is_rm(m.get_sort(get_enode(x)->get_owner()))) { deq = m.mk_not(m.mk_eq(ex, ey)); } else @@ -317,67 +345,65 @@ namespace smt { split_triple(bv_e, bv_sgn, bv_sig, bv_exp); family_id fid = m.get_family_id("bv"); - theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); + theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); app * e_sgn, *e_sig, *e_exp; - unsigned exp_sz = fpa_e_srt->get_parameter(0).get_int(); + unsigned ebits = fpa_e_srt->get_parameter(0).get_int(); + unsigned sbits = fpa_e_srt->get_parameter(1).get_int(); unsigned sig_sz = fpa_e_srt->get_parameter(1).get_int() - 1; + rational bias = mpfm.m_powers2.m1(ebits - 1); + rational sgn_r(0), sig_r(0), exp_r(bias); + e_sgn = (ctx.e_internalized(bv_sgn)) ? ctx.get_enode(bv_sgn)->get_owner() : - m_converter.bu().mk_numeral(0, 1); + bu.mk_numeral(0, 1); e_sig = (ctx.e_internalized(bv_sig)) ? ctx.get_enode(bv_sig)->get_owner() : - m_converter.bu().mk_numeral(0, sig_sz); + bu.mk_numeral(0, sig_sz); e_exp = (ctx.e_internalized(bv_exp)) ? ctx.get_enode(bv_exp)->get_owner() : - m_converter.bu().mk_numeral(0, exp_sz); + bu.mk_numeral(bias, ebits); TRACE("t_fpa", tout << "bv rep: [" << mk_ismt2_pp(e_sgn, m) << "\n" << mk_ismt2_pp(e_sig, m) << "\n" - << mk_ismt2_pp(e_exp, m) << "]\n";); - - rational sgn_r(0), sig_r(0), exp_r(0); + << mk_ismt2_pp(e_exp, m) << "]\n";); - if (ctx.e_internalized(bv_sgn) && ctx.get_enode(bv_sgn)->get_num_th_vars() > 0) - bv_th->get_fixed_value(e_sgn, sgn_r); // OK to fail - if (ctx.e_internalized(bv_sig) && ctx.get_enode(bv_sig)->get_num_th_vars() > 0) - bv_th->get_fixed_value(e_sig, sig_r); // OK to fail - if (ctx.e_internalized(bv_exp) && ctx.get_enode(bv_exp)->get_num_th_vars() > 0) - bv_th->get_fixed_value(e_exp, exp_r); // OK to fail - - TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " - << sig_r.to_string() << " " - << exp_r.to_string() << "]\n";); + if (!ctx.e_internalized(bv_sgn) || + ctx.get_enode(bv_sgn)->get_num_th_vars() == 0 || + !bv_th->get_fixed_value(e_sgn, sgn_r)) + sgn_r = rational(0); + if (!ctx.e_internalized(bv_sig) || + ctx.get_enode(bv_sig)->get_num_th_vars() == 0 || + !bv_th->get_fixed_value(e_sig, sig_r)) + sig_r = rational(0); + if (!ctx.e_internalized(bv_exp) || + ctx.get_enode(bv_exp)->get_num_th_vars() == 0 || + !bv_th->get_fixed_value(e_exp, exp_r)) + exp_r = bias; // un-bias exponent rational exp_unbiased_r; - exp_unbiased_r = exp_r - mpfm.m_powers2.m1(exp_sz - 1); + exp_unbiased_r = exp_r - bias; - mpz sig_z; mpf_exp_t exp_z; - mpq sig_q, exp_q; - mpz sig_num, exp_num; + TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " + << sig_r.to_string() << " " + << exp_unbiased_r.to_string() << "(" << exp_r.to_string() << ")]\n"; ); + + scoped_mpz sig_z(mpzm); + mpf_exp_t exp_z; + scoped_mpq sig_q(mpqm), exp_q(mpqm); + scoped_mpz sig_num(mpzm), exp_num(mpzm); mpqm.set(sig_q, sig_r.to_mpq()); - mpzm.set(sig_num, sig_q.numerator()); + mpzm.set(sig_num, sig_q.get().numerator()); mpqm.set(exp_q, exp_unbiased_r.to_mpq()); - mpzm.set(exp_num, exp_q.numerator()); + mpzm.set(exp_num, exp_q.get().numerator()); mpzm.set(sig_z, sig_num); exp_z = mpzm.get_int64(exp_num); - mpf fp_val; - mpfm.set(fp_val, exp_sz, sig_sz + 1, !sgn_r.is_zero(), sig_z, exp_z); + scoped_mpf fp_val(mpfm); + mpfm.set(fp_val, ebits, sbits, !sgn_r.is_zero(), sig_z, exp_z); - app * fp_val_e; - fp_val_e = fu.mk_value(fp_val); - - TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); - - mpfm.del(fp_val); - mpzm.del(sig_num); - mpzm.del(exp_num); - mpqm.del(sig_q); - mpqm.del(exp_q); - mpzm.del(sig_z); - - res = alloc(expr_wrapper_proc, fp_val_e); + TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mpfm.to_string(fp_val) << std::endl;); + res = alloc(expr_wrapper_proc, m_factory->mk_value(fp_val)); } else UNREACHABLE(); @@ -445,7 +471,7 @@ namespace smt { void theory_fpa::reset_eh() { pop_scope_eh(m_trail_stack.get_num_scopes()); - m_rw.reset(); + m_rw.reset(); m_trans_map.reset(); m_bool_var2atom.reset(); m_temporaries.reset(); @@ -453,6 +479,8 @@ namespace smt { theory::reset_eh(); } - void theory_fpa::init_model(model_generator & m) { + void theory_fpa::init_model(model_generator & m) { + m_factory = alloc(fpa_factory, get_manager(), get_family_id()); + m.register_factory(m_factory); } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 41374fd8f..7b29b82de 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -23,9 +23,38 @@ Revision History: #include"trail.h" #include"fpa2bv_converter.h" #include"fpa2bv_rewriter.h" +#include"value_factory.h" namespace smt { + class fpa_factory : public value_factory { + float_util m_util; + + virtual app * mk_value_core(mpf const & val, sort * s) { + SASSERT(m_util.get_ebits(s) == val.get_ebits()); + SASSERT(m_util.get_sbits(s) == val.get_sbits()); + return m_util.mk_value(val); + } + + public: + fpa_factory(ast_manager & m, family_id fid) : + value_factory(m, fid), + m_util(m) { + } + + virtual ~fpa_factory() {} + + virtual expr * get_some_value(sort * s) { NOT_IMPLEMENTED_YET(); } + virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { NOT_IMPLEMENTED_YET(); } + virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } + virtual void register_value(expr * n) { /* Ignore */ } + + app * mk_value(mpf const & x) { + return m_util.mk_value(x); + } + }; + + class theory_fpa : public theory { class th_trail_stack : public trail_stack { public: @@ -60,6 +89,7 @@ namespace smt { bool_var2atom m_bool_var2atom; enode_vector m_temporaries; int_vector m_tvars; + fpa_factory * m_factory; virtual final_check_status final_check_eh() { return FC_DONE; } virtual bool internalize_atom(app * atom, bool gate_ctx); @@ -78,7 +108,6 @@ namespace smt { void assign_eh(bool_var v, bool is_true); virtual void relevant_eh(app * n); virtual void init_model(model_generator & m); - public: theory_fpa(ast_manager& m); virtual ~theory_fpa(); @@ -91,7 +120,8 @@ namespace smt { sig = to_app(e)->get_arg(1); exp = to_app(e)->get_arg(2); } - + + void add_extra_assertions(); void mk_bv_eq(expr * x, expr * y); }; From 75bae1b00c507dc4a85d7e9046063611b611507a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 19 Dec 2014 12:32:57 +0000 Subject: [PATCH 095/646] BV-SLS optimization Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 73355197a..89ef57871 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -89,6 +89,7 @@ private: unsigned m_track_unsat; obj_map m_weights; double m_top_sum; + obj_hashtable m_temp_seen; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -440,6 +441,7 @@ public: } } + m_temp_seen.reset(); for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; @@ -630,7 +632,14 @@ public: app * a = to_app(n); expr * const * args = a->get_args(); for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); + { + expr * child = args[i]; + if (!m_temp_seen.contains(child)) + { + setup_occs(child, false); + m_temp_seen.insert(child); + } + } } else if (m_manager.is_not(n)) { @@ -638,8 +647,7 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); + SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child)); setup_occs(child, true); } else From d5fef38c00ca42dbe91818f16f85ba239e1afb5f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 21 Dec 2014 18:43:22 +0000 Subject: [PATCH 096/646] FPA: Switched default value representation to 3-bitvector Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast_smt2_pp.cpp | 51 +++++++++++++++++++++++++++++------------ src/ast/ast_smt2_pp.h | 2 +- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 77c8ac58f..00ce6aa8f 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -222,34 +222,55 @@ format * smt2_pp_environment::pp_bv_literal(app * t, bool use_bv_lits, bool bv_n return vf; } -format * smt2_pp_environment::pp_float_literal(app * t) { +format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits) { mpf_manager & fm = get_futil().fm(); scoped_mpf v(fm); + ast_manager & m = get_manager(); format * body = 0; + string_buffer<> buf; VERIFY(get_futil().is_value(t, v)); if (fm.is_nan(v)) { - body = mk_string(get_manager(), "NaN"); + buf << "(_ NaN " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; + return mk_string(get_manager(), buf.c_str()); } else if (fm.is_pinf(v)) { - body = mk_string(get_manager(), "plusInfinity"); + buf << "(_ +oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; + return mk_string(get_manager(), buf.c_str()); } else if (fm.is_ninf(v)) { - body = mk_string(get_manager(), "minusInfinity"); + buf << "(_ -oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; + return mk_string(get_manager(), buf.c_str()); } - else if (fm.is_pzero(v)) { - // TODO: make it SMT 2.0 compatible - body = mk_string(get_manager(), "+0.0"); + else if (fm.is_pzero(v)) { + buf << "(_ +zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; + return mk_string(get_manager(), buf.c_str()); } else if (fm.is_nzero(v)) { - // TODO: make it SMT 2.0 compatible - body = mk_string(get_manager(), "-0.0"); + buf << "(_ -zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; + return mk_string(get_manager(), buf.c_str()); } - else { - // TODO: make it SMT 2.0 compatible - std::string val = fm.to_string(v); - body = mk_string(get_manager(), val.c_str()); + else { + buf << "(fp #b" << (fm.sgn(v) ? 1 : 0); + body = mk_string(get_manager(), buf.c_str()); + body = mk_compose(m, body, mk_string(get_manager(), " ")); + + mpf_exp_t exp = fm.exp(v); + const mpz & bias = fm.m_powers2.m1(v.get().get_ebits() - 1); + mpf_exp_t biased_exp = exp + fm.mpz_manager().get_int64(bias); + app_ref e_biased_exp(m); + e_biased_exp = get_bvutil().mk_numeral(biased_exp, v.get().get_ebits()); + body = mk_compose(m, body, pp_bv_literal(e_biased_exp, use_bv_lits, false)); + body = mk_compose(m, body, mk_string(get_manager(), " ")); + + scoped_mpz sig(fm.mpz_manager()); + sig = fm.sig(v); + app_ref e_sig(m); + e_sig = get_bvutil().mk_numeral(rational(sig), v.get().get_sbits() - 1); + body = mk_compose(m, body, pp_bv_literal(e_sig, use_bv_lits, false)); + + body = mk_compose(m, body, mk_string(get_manager(), ")")); + return body; } - return pp_as(body, get_manager().get_sort(t)); } // generate (- f) @@ -544,7 +565,7 @@ class smt2_printer { f = m_env.pp_bv_literal(c, m_pp_bv_lits, m_pp_bv_neg); } else if (m_env.get_futil().is_value(c)) { - f = m_env.pp_float_literal(c); + f = m_env.pp_float_literal(c, m_pp_bv_lits); } else if (m_env.get_dlutil().is_numeral(c)) { f = m_env.pp_datalog_literal(c); diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index aa84d6e03..93feec8d5 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -52,7 +52,7 @@ public: virtual format_ns::format * pp_fdecl(func_decl * f, unsigned & len); virtual format_ns::format * pp_bv_literal(app * t, bool use_bv_lits, bool bv_neg); virtual format_ns::format * pp_arith_literal(app * t, bool decimal, unsigned prec); - virtual format_ns::format * pp_float_literal(app * t); + virtual format_ns::format * pp_float_literal(app * t, bool use_bv_lits); virtual format_ns::format * pp_datalog_literal(app * t); virtual format_ns::format * pp_sort(sort * s); virtual format_ns::format * pp_fdecl_ref(func_decl * f); From a1b4ef9e1b7dcdf85eea923aab907bec5debf560 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 21 Dec 2014 18:44:12 +0000 Subject: [PATCH 097/646] fpa2bv refactoring Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 69 ++++++++++---- src/ast/float_decl_plugin.h | 9 ++ src/ast/fpa/fpa2bv_converter.cpp | 152 +++++++++++++++++++------------ src/ast/fpa/fpa2bv_converter.h | 18 ++-- src/ast/fpa/fpa2bv_rewriter.h | 2 + 5 files changed, 169 insertions(+), 81 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 816df906e..d775523ec 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -163,10 +163,10 @@ decl_plugin * float_decl_plugin::mk_fresh() { } sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { - if (ebits > sbits) - m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported"); - if (ebits <= 2) - m_manager->raise_exception("floating point sorts with ebits <= 2 are currently not supported"); + if (sbits < 2) + m_manager->raise_exception("minimum number of significand bits is 1"); + if (ebits < 2) + m_manager->raise_exception("minimum number of exponent bits is 2"); parameter p1(ebits), p2(sbits); parameter ps[2] = { p1, p2 }; @@ -182,13 +182,8 @@ sort * float_decl_plugin::mk_rm_sort() { sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) { switch (k) { case FLOAT_SORT: - if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) { - m_manager->raise_exception("expecting two integer parameters to floating point sort"); - } - if (parameters[0].get_int() <= 1 || parameters[1].get_int() <= 1) - m_manager->raise_exception("floating point sorts need parameters > 1"); - if (parameters[0].get_int() > parameters[1].get_int()) - m_manager->raise_exception("floating point sorts with ebits > sbits are currently not supported"); + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to floating point sort (ebits, sbits)"); return mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); case ROUNDING_MODE_SORT: return mk_rm_sort(); @@ -279,8 +274,8 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet case OP_FLOAT_EQ: name = "fp.eq"; break; case OP_FLOAT_LT: name = "fp.lt"; break; case OP_FLOAT_GT: name = "fp.gt"; break; - case OP_FLOAT_LE: name = "fp.lte"; break; - case OP_FLOAT_GE: name = "fp.gte"; break; + case OP_FLOAT_LE: name = "fp.leq"; break; + case OP_FLOAT_GE: name = "fp.geq"; break; default: UNREACHABLE(); break; @@ -408,9 +403,12 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa is_sort_of(domain[1], m_bv_fid, BV_SORT) && is_sort_of(domain[2], m_bv_fid, BV_SORT)) { // 3 BVs -> 1 FP - sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1); - symbol name("fp"); - return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + unsigned ebits = domain[1]->get_parameter(0).get_int(); + unsigned sbits = domain[2]->get_parameter(0).get_int() + 1; + parameter ps[] = { parameter(ebits), parameter(sbits) }; + sort * fp = mk_float_sort(ebits, sbits); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, 2, ps)); } else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) { // 1 BV -> 1 FP @@ -423,7 +421,7 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa int sbits = parameters[1].get_int(); if (domain[0]->get_parameter(0).get_int() != (ebits + sbits)) - m_manager->raise_exception("sort mismtach; invalid bit-vector size, expected bitvector of size (ebits+sbits)"); + m_manager->raise_exception("sort mismatch; invalid bit-vector size, expected bitvector of size (ebits+sbits)"); sort * fp = mk_float_sort(ebits, sbits); symbol name("to_fp"); @@ -613,6 +611,39 @@ func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_par return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); } +func_decl * float_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 1) + m_manager->raise_exception("invalid number of arguments to internal_bv_wrap"); + if (!is_float_sort(domain[0]) && !is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint or RoundingMode sort"); + + if (is_float_sort(domain[0])) + { + unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int(); + parameter ps[] = { parameter(float_sz) }; + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); + return m_manager->mk_func_decl(symbol("bv_wrap"), 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else { + parameter ps[] = { parameter(3) }; + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); + return m_manager->mk_func_decl(symbol("bv_wrap"), 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); + } +} + +func_decl * float_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 1) + m_manager->raise_exception("invalid number of arguments to internal_bv_unwrap"); + if (!is_sort_of(domain[0], m_bv_fid, BV_SORT)) + m_manager->raise_exception("sort mismatch, expected argument of bitvector sort"); + if (!is_float_sort(range) && !is_rm_sort(range)) + m_manager->raise_exception("sort mismatch, expected range of FloatingPoint sort"); + + return m_manager->mk_func_decl(symbol("bv_unwrap"), 1, domain, range, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { @@ -680,6 +711,10 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_IEEE_BV: return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_INTERNAL_BVWRAP: + return mk_internal_bv_wrap(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_INTERNAL_BVUNWRAP: + return mk_internal_bv_unwrap(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); return 0; diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index ebf424578..e4bf633a5 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -86,6 +86,10 @@ enum float_op_kind { /* Extensions */ OP_FLOAT_TO_IEEE_BV, + /* Internal use only */ + OP_FLOAT_INTERNAL_BVWRAP, + OP_FLOAT_INTERNAL_BVUNWRAP, + LAST_FLOAT_OP }; @@ -150,6 +154,11 @@ class float_decl_plugin : public decl_plugin { func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); + func_decl * mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + virtual void set_manager(ast_manager * m, family_id id); unsigned mk_id(mpf const & v); void recycled_id(unsigned id); diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index be951098a..f4b4e7951 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -32,7 +32,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : m_arith_util(m), m_mpf_manager(m_util.fm()), m_mpz_manager(m_mpf_manager.mpz_manager()), - extra_assertions(m) { + m_extra_assertions(m) { m_plugin = static_cast(m.get_plugin(m.mk_family_id("float"))); } @@ -76,10 +76,15 @@ void fpa2bv_converter::mk_ite(expr * c, expr * t, expr * f, expr_ref & result) { SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + expr *t_sgn, *t_sig, *t_exp; + expr *f_sgn, *f_sig, *f_exp; + split_triple(t, t_sgn, t_sig, t_exp); + split_triple(f, f_sgn, f_sig, f_exp); + expr_ref sgn(m), s(m), e(m); - m_simp.mk_ite(c, to_app(t)->get_arg(0), to_app(f)->get_arg(0), sgn); - m_simp.mk_ite(c, to_app(t)->get_arg(1), to_app(f)->get_arg(1), s); - m_simp.mk_ite(c, to_app(t)->get_arg(2), to_app(f)->get_arg(2), e); + m_simp.mk_ite(c, t_sgn, f_sgn, sgn); + m_simp.mk_ite(c, t_sig, f_sig, s); + m_simp.mk_ite(c, t_exp, f_exp, e); mk_triple(sgn, s, e, result); } @@ -122,6 +127,10 @@ void fpa2bv_converter::mk_value(func_decl * f, unsigned num, expr * const * args } } +app * fpa2bv_converter::mk_fresh_const(char const * prefix, unsigned sz) { + return m.mk_fresh_const(prefix, m_bv_util.mk_sort(sz)); +} + void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { SASSERT(f->get_family_id() == null_family_id); SASSERT(f->get_arity() == 0); @@ -134,25 +143,21 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { SASSERT(is_float(srt)); unsigned ebits = m_util.get_ebits(srt); unsigned sbits = m_util.get_sbits(srt); - - expr_ref sgn(m), s(m), e(m); + + app_ref sgn(m), s(m), e(m); #ifdef Z3DEBUG - sort_ref s_sgn(m), s_sig(m), s_exp(m); - s_sgn = m_bv_util.mk_sort(1); - s_sig = m_bv_util.mk_sort(sbits - 1); - s_exp = m_bv_util.mk_sort(ebits); - std::string p("fpa2bv"); std::string name = f->get_name().str(); - - sgn = m.mk_fresh_const((p + "_sgn_" + name).c_str(), s_sgn); - s = m.mk_fresh_const((p + "_sig_" + name).c_str(), s_sig); - e = m.mk_fresh_const((p + "_exp_" + name).c_str(), s_exp); + + sgn = mk_fresh_const((p + "_sgn_" + name).c_str(), 1); + s = mk_fresh_const((p + "_sig_" + name).c_str(), sbits - 1); + e = mk_fresh_const((p + "_exp_" + name).c_str(), ebits); #else - expr_ref bv(m); + app_ref bv(m); unsigned bv_sz = 1 + ebits + (sbits - 1); - bv = m.mk_fresh_const(0, m_bv_util.mk_sort(bv_sz)); + bv = mk_fresh_const(0, bv_sz); + m_fresh_bv_variables.insert(bv); sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv); e = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv); @@ -196,7 +201,7 @@ void fpa2bv_converter::mk_uninterpreted_function(func_decl * f, unsigned num, ex if (is_float(args[i])) { expr * sgn, * sig, * exp; - split(args[i], sgn, sig, exp); + split_triple(args[i], sgn, sig, exp); new_args.push_back(sgn); new_args.push_back(sig); new_args.push_back(exp); @@ -294,7 +299,7 @@ void fpa2bv_converter::mk_rm_const(func_decl * f, expr_ref & result) { expr_ref rcc(m); rcc = bu().mk_ule(result, bu().mk_numeral(4, 3)); - extra_assertions.push_back(rcc); + m_extra_assertions.push_back(rcc); } } @@ -612,7 +617,7 @@ void fpa2bv_converter::mk_sub(func_decl * f, unsigned num, expr * const * args, void fpa2bv_converter::mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split(args[0], sgn, s, e); + split_triple(args[0], sgn, s, e); expr_ref c(m), nsgn(m); mk_is_nan(args[0], c); nsgn = m_bv_util.mk_bv_not(sgn); @@ -695,8 +700,7 @@ void fpa2bv_converter::mk_mul(func_decl * f, unsigned num, expr * const * args, // else comes the actual multiplication. unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - SASSERT(ebits <= sbits); + unsigned sbits = m_util.get_sbits(f->get_range()); expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m), b_sgn(m), b_sig(m), b_exp(m), b_lz(m); unpack(x, a_sgn, a_sig, a_exp, a_lz, true); @@ -1033,7 +1037,7 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args, void fpa2bv_converter::mk_abs(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split(args[0], sgn, s, e); + split_triple(args[0], sgn, s, e); mk_triple(m_bv_util.mk_numeral(0, 1), s, e, result); } @@ -1044,8 +1048,8 @@ void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split(x, x_sgn, x_sig, x_exp); - split(y, y_sgn, y_sig, y_exp); + split_triple(x, x_sgn, x_sig, x_exp); + split_triple(y, y_sgn, y_sig, y_exp); expr_ref c1(m), c2(m), x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), c1_and(m); mk_is_zero(x, x_is_zero); @@ -1087,8 +1091,8 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split(x, x_sgn, x_sig, x_exp); - split(y, y_sgn, y_sig, y_exp); + split_triple(x, x_sgn, x_sig, x_exp); + split_triple(y, y_sgn, y_sig, y_exp); expr_ref c1(m), c2(m), x_is_nan(m), y_is_nan(m), y_is_zero(m), x_is_zero(m), c1_and(m); mk_is_zero(y, y_is_zero); @@ -1225,11 +1229,9 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, m_simp.mk_and(z_is_zero, m.mk_not(rm_is_to_neg), ite_c); mk_ite(ite_c, pzero, z, v7); - // else comes the fused multiplication. unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); - SASSERT(ebits <= sbits); expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m); expr_ref b_sgn(m), b_sig(m), b_exp(m), b_lz(m); @@ -1482,7 +1484,6 @@ void fpa2bv_converter::mk_sqrt(func_decl * f, unsigned num, expr * const * args, // else comes the actual square root. unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); - SASSERT(ebits <= sbits); expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m); unpack(x, a_sgn, a_sig, a_exp, a_lz, true); @@ -1698,8 +1699,8 @@ void fpa2bv_converter::mk_float_eq(func_decl * f, unsigned num, expr * const * a expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split(x, x_sgn, x_sig, x_exp); - split(y, y_sgn, y_sig, y_exp); + split_triple(x, x_sgn, x_sig, x_exp); + split_triple(y, y_sgn, y_sig, y_exp); expr_ref x_eq_y_sgn(m), x_eq_y_exp(m), x_eq_y_sig(m); m_simp.mk_eq(x_sgn, y_sgn, x_eq_y_sgn); @@ -1734,8 +1735,8 @@ void fpa2bv_converter::mk_float_lt(func_decl * f, unsigned num, expr * const * a expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split(x, x_sgn, x_sig, x_exp); - split(y, y_sgn, y_sig, y_exp); + split_triple(x, x_sgn, x_sig, x_exp); + split_triple(y, y_sgn, y_sig, y_exp); expr_ref c3(m), t3(m), t4(m), one_1(m), nil_1(m); one_1 = m_bv_util.mk_numeral(1, 1); @@ -1865,10 +1866,11 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args if (num == 3 && m_bv_util.is_bv(args[0]) && m_bv_util.is_bv(args[1]) && - m_bv_util.is_bv(args[2])) { - // Theoretically, the user could have thrown in it's own triple of bit-vectors. - // Just keep it here, as there will be something else that uses it. - mk_triple(args[0], args[1], args[2], result); + m_bv_util.is_bv(args[2])) { + SASSERT(m_bv_util.get_bv_size(args[0]) == 1); + SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); + SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); + mk_triple(args[0], args[2], args[1], result); } else if (num == 2 && m_bv_util.is_bv(args[0]) && @@ -2148,7 +2150,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args else UNREACHABLE(); - SASSERT(is_well_sorted(m, result)); + SASSERT(is_well_sorted(m, result)); } void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -2306,13 +2308,40 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split(args[0], sgn, s, e); + split_triple(args[0], sgn, s, e); result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s); } +void fpa2bv_converter::mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_internal", tout << "wrap "; + for (unsigned i = 0; i < num; i++) + tout << " " << mk_ismt2_pp(args[i], m); + tout << std::endl;); + SASSERT(num == 1); + result = m.mk_app(f, num, args); +} + +void fpa2bv_converter::mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_internal", tout << "unwrap "; + for (unsigned i = 0; i < num; i++) + tout << " " << mk_ismt2_pp(args[i], m); + tout << std::endl;); + SASSERT(num == 1); + app * a0 = to_app(args[0]); + SASSERT(a0->get_kind() == AST_APP); + SASSERT(is_float_family(a0->get_decl())); + decl_kind k = a0->get_decl_kind(); + SASSERT(k == OP_FLOAT_INTERNAL_BVWRAP); + SASSERT(a0->get_num_args() == 1); + result = a0->get_arg(0); +} void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 3); + SASSERT(m_bv_util.get_bv_size(args[0]) == 1); + SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); + SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); mk_triple(args[0], args[2], args[1], result); + TRACE("fpa2bv_mk_fp", tout << "mk_fp result = " << mk_ismt2_pp(result, m) << std::endl;); } void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -2328,7 +2357,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg //expr * x = args[1]; //expr * sgn, *s, *e; - //split(x, sgn, s, e); + //split_triple(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2346,7 +2375,7 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg //expr * x = args[1]; //expr * sgn, *s, *e; - //split(x, sgn, s, e); + //split_triple(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2440,18 +2469,28 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar SASSERT(is_well_sorted(m, result)); } -void fpa2bv_converter::split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { +void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sgn = to_app(e)->get_arg(0); - sig = to_app(e)->get_arg(1); - exp = to_app(e)->get_arg(2); + sig = to_app(e)->get_arg(2); + exp = to_app(e)->get_arg(1); +} + +void fpa2bv_converter::split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const { + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(to_app(e)->get_num_args() == 3); + expr *e_sgn, *e_sig, *e_exp; + split_triple(e, e_sgn, e_sig, e_exp); + sgn = e_sgn; + sig = e_sig; + exp = e_exp; } void fpa2bv_converter::mk_is_nan(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); // exp == 1^n , sig != 0 expr_ref sig_is_zero(m), sig_is_not_zero(m), exp_is_top(m), top_exp(m), zero(m); @@ -2466,7 +2505,7 @@ void fpa2bv_converter::mk_is_nan(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_inf(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref eq1(m), eq2(m), top_exp(m), zero(m); mk_top_exp(m_bv_util.get_bv_size(exp), top_exp); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(sig)); @@ -2509,7 +2548,7 @@ void fpa2bv_converter::mk_is_neg(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_zero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref eq1(m), eq2(m), bot_exp(m), zero(m); mk_bot_exp(m_bv_util.get_bv_size(exp), bot_exp); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(sig)); @@ -2520,7 +2559,7 @@ void fpa2bv_converter::mk_is_zero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_nzero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref e_is_zero(m), eq(m), one_1(m); mk_is_zero(e, e_is_zero); one_1 = m_bv_util.mk_numeral(1, 1); @@ -2530,7 +2569,7 @@ void fpa2bv_converter::mk_is_nzero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_pzero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref e_is_zero(m), eq(m), nil_1(m); mk_is_zero(e, e_is_zero); nil_1 = m_bv_util.mk_numeral(0, 1); @@ -2540,7 +2579,7 @@ void fpa2bv_converter::mk_is_pzero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_denormal(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref zero(m); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(exp)); m_simp.mk_eq(exp, zero, result); @@ -2548,7 +2587,7 @@ void fpa2bv_converter::mk_is_denormal(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_normal(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split(e, sgn, sig, exp); + split_triple(e, sgn, sig, exp); expr_ref is_special(m), is_denormal(m), p(m); mk_is_denormal(e, is_denormal); @@ -2670,9 +2709,7 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref unsigned sbits = m_util.get_sbits(srt); unsigned ebits = m_util.get_ebits(srt); - sgn = to_app(e)->get_arg(0); - sig = to_app(e)->get_arg(1); - exp = to_app(e)->get_arg(2); + split_triple(e, sgn, sig, exp); expr_ref is_normal(m); mk_is_normal(e, is_normal); @@ -2684,7 +2721,7 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref expr_ref denormal_sig(m), denormal_exp(m); denormal_sig = m_bv_util.mk_zero_extend(1, sig); - SASSERT(ebits >= 3); // Note: when ebits=2 there is no 1-exponent, so mk_unbias will produce a 0. + // SASSERT(ebits >= 3); // Note: when ebits=2 there is no 1-exponent, so mk_unbias will produce a 0. denormal_exp = m_bv_util.mk_numeral(1, ebits); mk_unbias(denormal_exp, denormal_exp); dbg_decouple("fpa2bv_unpack_denormal_exp", denormal_exp); @@ -2772,7 +2809,7 @@ void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { // CMW: This works only for quantifier-free formulas. expr_ref new_e(m); new_e = m.mk_fresh_const(prefix, m.get_sort(e)); - extra_assertions.push_back(m.mk_eq(new_e, e)); + m_extra_assertions.push_back(m.mk_eq(new_e, e)); e = new_e; #endif } @@ -2802,7 +2839,6 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & // i.e., it has 2 + (sbits-1) + 3 = sbits + 4 bits, where the first one is in sgn. // Furthermore, note that sig is an unsigned bit-vector, while exp is signed. - SASSERT(ebits <= sbits); SASSERT(m_bv_util.is_bv(rm) && m_bv_util.get_bv_size(rm) == 3); SASSERT(m_bv_util.is_bv(sgn) && m_bv_util.get_bv_size(sgn) == 1); SASSERT(m_bv_util.is_bv(sig) && m_bv_util.get_bv_size(sig) >= 5); diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index eb4435132..5da0ca463 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -42,6 +42,7 @@ struct func_decl_triple { }; class fpa2bv_converter { +protected: ast_manager & m; basic_simplifier_plugin m_simp; float_util m_util; @@ -73,16 +74,19 @@ public: SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); SASSERT(m_bv_util.is_bv(significand)); SASSERT(m_bv_util.is_bv(exponent)); - result = m.mk_app(m_util.get_family_id(), OP_FLOAT_TO_FP, sign, significand, exponent); + result = m.mk_app(m_util.get_family_id(), OP_FLOAT_TO_FP, sign, exponent, significand); } + void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const; + void split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const; + void mk_eq(expr * a, expr * b, expr_ref & result); void mk_ite(expr * c, expr * t, expr * f, expr_ref & result); void mk_rounding_mode(func_decl * f, expr_ref & result); void mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_const(func_decl * f, expr_ref & result); - void mk_rm_const(func_decl * f, expr_ref & result); + virtual void mk_const(func_decl * f, expr_ref & result); + virtual void mk_rm_const(func_decl * f, expr_ref & result); void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_var(unsigned base_inx, sort * srt, expr_ref & result); @@ -138,11 +142,11 @@ public: obj_map const & uf23bvuf() const { return m_uf23bvuf; } void dbg_decouple(const char * prefix, expr_ref & e); - expr_ref_vector extra_assertions; + expr_ref_vector m_extra_assertions; + void mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); protected: - void split(expr * e, expr * & sgn, expr * & sig, expr * & exp) const; - void mk_is_nan(expr * e, expr_ref & result); void mk_is_inf(expr * e, expr_ref & result); void mk_is_pinf(expr * e, expr_ref & result); @@ -173,6 +177,8 @@ protected: void add_core(unsigned sbits, unsigned ebits, expr_ref & rm, expr_ref & c_sgn, expr_ref & c_sig, expr_ref & c_exp, expr_ref & d_sgn, expr_ref & d_sig, expr_ref & d_exp, expr_ref & res_sgn, expr_ref & res_sig, expr_ref & res_exp); + + app * mk_fresh_const(char const * prefix, unsigned sz); }; #endif diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index bb42bdf5d..17ee924ad 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -150,6 +150,8 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; + case OP_FLOAT_INTERNAL_BVWRAP: m_conv.mk_internal_bvwrap(f, num, args, result); return BR_DONE; + case OP_FLOAT_INTERNAL_BVUNWRAP: m_conv.mk_internal_bvunwrap(f, num, args, result); return BR_DONE; default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); From d394b9579fd658afa26968251123392d095d5d92 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 21 Dec 2014 18:45:05 +0000 Subject: [PATCH 098/646] FPA: new conversion Signed-off-by: Christoph M. Wintersteiger --- src/ast/rewriter/float_rewriter.cpp | 67 +++++++++++++++++++---------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 3c1f51990..522fad678 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -109,33 +109,54 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons else return BR_FAILED; } - else if (num_args == 3 && - m_util.is_rm(args[0]) && - m_util.au().is_real(args[1]) && - m_util.au().is_int(args[2])) { + else if (num_args == 3) { + bv_util bu(m()); + rational r1, r2, r3; + unsigned bvs1, bvs2, bvs3; - mpf_rounding_mode rm; - if (!m_util.is_rm_value(args[0], rm)) + if (m_util.is_rm(args[0]) && + m_util.au().is_real(args[1]) && + m_util.au().is_int(args[2])) { + mpf_rounding_mode rm; + if (!m_util.is_rm_value(args[0], rm)) + return BR_FAILED; + + rational q; + if (!m_util.au().is_numeral(args[1], q)) + return BR_FAILED; + + rational e; + if (!m_util.au().is_numeral(args[2], e)) + return BR_FAILED; + + TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";); + scoped_mpf v(m_util.fm()); + m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator()); + result = m_util.mk_value(v); + m_util.fm().del(v); + return BR_DONE; + } + else if (bu.is_numeral(args[0], r1, bvs1) && + bu.is_numeral(args[1], r2, bvs2) && + bu.is_numeral(args[2], r3, bvs3)) { + SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator())); + SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator())); + SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator())); + scoped_mpf v(m_util.fm()); + mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator()); + m_util.fm().set(v, bvs2, bvs3 + 1, + r1.is_one(), + r3.to_mpq().numerator(), + m_util.fm().unbias_exp(bvs2, biased_exp)); + TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;); + result = m_util.mk_value(v); + return BR_DONE; + } + else return BR_FAILED; - - rational q; - if (!m_util.au().is_numeral(args[1], q)) - return BR_FAILED; - - rational e; - if (!m_util.au().is_numeral(args[2], e)) - return BR_FAILED; - - TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";); - scoped_mpf v(m_util.fm()); - m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator()); - result = m_util.mk_value(v); - m_util.fm().del(v); - return BR_DONE; } - else { + else return BR_FAILED; - } } br_status float_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { From cf4b7219e10c4fdb1a6533eaab0fe6b7ec892afc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 21 Dec 2014 18:45:36 +0000 Subject: [PATCH 099/646] new theory_fpa. plenty of bugs remain. Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 824 +++++++++++++++++++++++++---------------- src/smt/theory_fpa.h | 86 ++++- 2 files changed, 563 insertions(+), 347 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 7552e276b..354dc7596 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -22,7 +22,7 @@ Revision History: #include"theory_bv.h" #include"smt_model_generator.h" -namespace smt { +namespace smt { class fpa_atom_trail : public trail { bool_var m_var; @@ -36,11 +36,60 @@ namespace smt { } }; + void theory_fpa::fpa2bv_converter_wrapped::mk_const(func_decl * f, expr_ref & result) { + SASSERT(f->get_family_id() == null_family_id); + SASSERT(f->get_arity() == 0); + expr * r; + if (m_const2bv.find(f, r)) { + result = r; + } + else { + sort * s = f->get_range(); + func_decl *w, *u; + m_th.get_wrap(s, w, u); + expr_ref bv(m); + bv = m.mk_app(w, m.mk_const(f)); + unsigned bv_sz = m_th.m_converter.bu().get_bv_size(bv); + unsigned ebits = m_th.m_converter.fu().get_ebits(f->get_range()); + unsigned sbits = m_th.m_converter.fu().get_sbits(f->get_range()); + SASSERT(bv_sz == ebits + sbits); + m_th.m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), + m_bv_util.mk_extract(sbits - 2, 0, bv), + m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), + result); + + m_const2bv.insert(f, result); + m.inc_ref(f); + m.inc_ref(result); + } + } + + void theory_fpa::fpa2bv_converter_wrapped::mk_rm_const(func_decl * f, expr_ref & result) { + SASSERT(f->get_family_id() == null_family_id); + SASSERT(f->get_arity() == 0); + expr * r; + if (m_rm_const2bv.find(f, r)) { + result = r; + } + else { + SASSERT(is_rm(f->get_range())); + + sort * s = f->get_range(); + func_decl *w, *u; + m_th.get_wrap(s, w, u); + result = m.mk_app(w, m.mk_const(f)); + + m_rm_const2bv.insert(f, result); + m.inc_ref(f); + m.inc_ref(result); + } + } + theory_fpa::theory_fpa(ast_manager & m) : theory(m.mk_family_id("float")), - m_converter(m), + m_converter(m, this), m_rw(m, m_converter, params_ref()), - m_trans_map(m), + m_th_rw(m), m_trail_stack(*this) { } @@ -49,45 +98,277 @@ namespace smt { { } - void theory_fpa::add_extra_assertions() + app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector & values) { + TRACE("t_fpa", tout << "fpa_value_proc::mk_value for: " << mk_ismt2_pp(m_a, m_th.get_manager()) << "\n";); + ast_manager & m = m_th.get_manager(); + context & ctx = m_th.get_context(); + theory_id bv_id = m.mk_family_id("bv"); + theory_bv * th_bv = dynamic_cast(ctx.get_theory(bv_id)); + SASSERT(th_bv != 0); + + float_util & fu = m_th.m_converter.fu(); + bv_util & bu = m_th.m_converter.bu(); + mpf_manager & mpfm = fu.fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); + + sort * s = m.get_sort(m_a); + unsigned ebits = fu.get_ebits(s); + unsigned sbits = fu.get_sbits(s); + + scoped_mpz bias(mpzm); + mpzm.power(mpz(2), ebits - 1, bias); + mpzm.dec(bias); + + app * result; + float_op_kind k = (float_op_kind) to_app(m_a)->get_decl_kind(); + switch (k) + { + case -1: { + func_decl *w, *u; + m_th.get_wrap(s, w, u); + rational bv_val(0); + scoped_mpz sgn(mpzm), sig(mpzm), exp(bias); + app_ref bv_w(m); + bv_w = m.mk_app(w, m_a); + + if (!th_bv->get_fixed_value(bv_w, bv_val)) + result = fu.mk_nan(ebits, sbits); + else { + scoped_mpz all_bits(mpzm); + all_bits = bv_val.to_mpq().numerator(); + SASSERT(mpzm.is_one(bv_val.to_mpq().denominator())); + + mpzm.machine_div2k(all_bits, ebits + sbits - 1, sgn); + + scoped_mpz tmp_p(mpzm); + mpzm.power(mpz(2), ebits + sbits - 1, tmp_p); + + if (mpzm.is_one(sgn)) mpzm.sub(all_bits, tmp_p, all_bits); + + mpzm.machine_div2k(all_bits, sbits - 1, exp); + scoped_mpz exp_u(mpzm); + mpzm.sub(exp, bias, exp_u); + SASSERT(mpzm.is_int64(exp_u)); + + mpzm.power(mpz(2), sbits - 1, tmp_p); + mpzm.mod(all_bits, tmp_p, sig); + + scoped_mpf f(mpfm); + mpfm.set(f, ebits, sbits, mpzm.is_one(sgn), sig, mpzm.get_int64(exp_u)); + result = fu.mk_value(f); + } + break; + } + case OP_FLOAT_FP: { + bool is_internalized = ctx.e_internalized(m_a); + if (is_internalized) { + SASSERT(m_a->get_num_args() == 3); + app_ref a_sgn(m), a_sig(m), a_exp(m); + a_sgn = to_app(m_a->get_arg(0)); + a_exp = to_app(m_a->get_arg(1)); + a_sig = to_app(m_a->get_arg(2)); + + scoped_mpz bias(mpzm); + mpzm.power(mpz(2), ebits - 1, bias); + mpzm.dec(bias); + + rational sgn(0), sig(0), exp(bias); + th_bv->get_fixed_value(a_sgn, sgn); + th_bv->get_fixed_value(a_sig, sig); + th_bv->get_fixed_value(a_exp, exp); + + TRACE("t_fpa", tout << "sgn=" << sgn.to_string() << " ; " << + "sig=" << sig.to_string() << " ; " << + "exp=" << exp.to_string() << std::endl;); + + rational exp_u = exp - rational(bias); + SASSERT(exp_u.is_int64()); + + scoped_mpf f(mpfm); + scoped_mpq sig_q(mpqm); + sig_q = sig.to_mpq(); + mpfm.set(f, ebits, sbits, sgn.is_one(), sig_q.get().numerator(), exp_u.get_int64()); + result = fu.mk_value(f); + } + else { + result = fu.mk_nan(ebits, sbits); + } + break; + } + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("t_fpa", tout << "fpa_value_proc::mk_value result: " << mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + return result; + } + + app * theory_fpa::fpa_rm_value_proc::mk_value(model_generator & mg, ptr_vector & values) { + TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value for: " << mk_ismt2_pp(m_a, m_th.get_manager()) << "\n";); + ast_manager & m = m_th.get_manager(); + context & ctx = m_th.get_context(); + theory_id bv_id = m.mk_family_id("bv"); + theory_bv * th_bv = dynamic_cast(ctx.get_theory(bv_id)); + + app * result = 0; + mpf_rounding_mode rm; + if (m_th.m_converter.fu().is_rm_value(m_a, rm)) { + result = m_a.get(); + } + else { + sort * s = m.get_sort(m_a); + func_decl *w, *u; + m_th.get_wrap(s, w, u); + + app_ref bv_w(m); + bv_w = m.mk_app(w, m_a); + + rational val(0); + if (ctx.e_internalized(bv_w)) + if (!th_bv->get_fixed_value(bv_w, val)) + val = rational(0); + + switch (val.get_uint64()) + { + case BV_RM_TIES_TO_AWAY: result = m_fu.mk_round_nearest_ties_to_away(); break; + case BV_RM_TIES_TO_EVEN: result = m_fu.mk_round_nearest_ties_to_even(); break; + case BV_RM_TO_NEGATIVE: result = m_fu.mk_round_toward_negative(); break; + case BV_RM_TO_POSITIVE: result = m_fu.mk_round_toward_positive(); break; + case BV_RM_TO_ZERO: + default: result = m_fu.mk_round_toward_zero(); + } + } + + TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value result: " << mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + return result; + } + + void theory_fpa::get_wrap(sort * s, func_decl *& wrap, func_decl *& unwrap) + { + if (!m_wraps.find(s, wrap) || !m_unwraps.find(s, unwrap)) { + SASSERT(!m_wraps.contains(s)); + ast_manager & m = get_manager(); + sort * bv_srt = 0; + + if (m_converter.is_rm(s)) + bv_srt = m_converter.bu().mk_sort(3); + else { + SASSERT(m_converter.is_float(s)); + unsigned ebits = m_converter.fu().get_ebits(s); + unsigned sbits = m_converter.fu().get_sbits(s); + bv_srt = m_converter.bu().mk_sort(ebits + sbits); + } + + wrap = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &s, bv_srt); + unwrap = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); + m_wraps.insert(s, wrap); + m_unwraps.insert(s, unwrap); + get_context().push_trail(insert_obj_map(m_wraps, s)); + get_context().push_trail(insert_obj_map(m_unwraps, s)); + } + } + + expr_ref theory_fpa::convert_atom(expr * e) { + ast_manager & m = get_manager(); + expr_ref res(m); + proof_ref pr(m); + m_rw(e, res); + + TRACE("t_fpa", tout << "converted atom:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + return res; + } + + expr_ref theory_fpa::convert_term(expr * e) { + ast_manager & m = get_manager(); + expr_ref res(m); + proof_ref pr(m); + m_rw(e, res); + + SASSERT(is_app(res)); + + if (m_converter.fu().is_rm(e)) { + SASSERT(is_sort_of(m.get_sort(res), m_converter.bu().get_family_id(), BV_SORT)); + SASSERT(m_converter.bu().get_bv_size(res) == 3); + } + else { + SASSERT(to_app(res)->get_family_id() == get_family_id()); + decl_kind k = to_app(res)->get_decl_kind(); + if (k == OP_FLOAT_TO_FP) { + SASSERT(to_app(res)->get_num_args() == 3); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(0)), m_converter.bu().get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(1)), m_converter.bu().get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(2)), m_converter.bu().get_family_id(), BV_SORT)); + + expr *sgn, *sig, *exp; + expr_ref s_sgn(m), s_sig(m), s_exp(m); + m_converter.split_triple(res, sgn, sig, exp); + m_th_rw(sgn, s_sgn); + m_th_rw(sig, s_sig); + m_th_rw(exp, s_exp); + + m_converter.mk_triple(s_sgn, s_sig, s_exp, res); + } + else { + SASSERT(is_sort_of(m.get_sort(e), get_family_id(), ROUNDING_MODE_SORT)); + SASSERT(is_sort_of(m.get_sort(res), m_converter.bu().get_family_id(), BV_SORT)); + } + } + + TRACE("t_fpa", tout << "converted term:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + return res; + } + + expr_ref theory_fpa::mk_side_conditions() { ast_manager & m = get_manager(); context & ctx = get_context(); simplifier & simp = ctx.get_simplifier(); + + expr_ref res(m), t(m); + proof_ref t_pr(m); + res = m.mk_true(); - expr_ref_vector::iterator it = m_converter.extra_assertions.begin(); - expr_ref_vector::iterator end = m_converter.extra_assertions.end(); + expr_ref_vector::iterator it = m_converter.m_extra_assertions.begin(); + expr_ref_vector::iterator end = m_converter.m_extra_assertions.end(); for (; it != end; it++) { - expr_ref t(m); - proof_ref t_pr(m); - simp(*it, t, t_pr); - TRACE("t_fpa", tout << "extra: " << mk_ismt2_pp(t, m) << "\n";); - ctx.internalize_assertion(t, t_pr, 0); + simp(*it, t, t_pr); + res = m.mk_and(res, t); } - m_converter.extra_assertions.reset(); + m_converter.m_extra_assertions.reset(); + + TRACE("t_fpa", if (!m.is_true(res)) tout << "side condition: " << mk_ismt2_pp(res, m) << "\n";); + return res; } - void theory_fpa::mk_bv_eq(expr * x, expr * y) { - SASSERT(get_sort(x)->get_family_id() == m_converter.bu().get_family_id()); - SASSERT(get_sort(y)->get_family_id() == m_converter.bu().get_family_id()); - ast_manager & m = get_manager(); + void theory_fpa::assert_cnstr(expr * e) { + if (get_manager().is_true(e)) return; + TRACE("t_fpa", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); + context& ctx = get_context(); + ctx.internalize(e, false); + literal lit(ctx.get_literal(e)); + ctx.mark_as_relevant(lit); + ctx.mk_th_axiom(get_id(), 1, &lit); + } + + void theory_fpa::attach_new_th_var(enode * n) { context & ctx = get_context(); - theory_id bv_tid = ctx.get_theory(m.get_sort(x)->get_family_id())->get_id(); - literal l = mk_eq(x, y, false); - ctx.mk_th_axiom(bv_tid, 1, &l); - ctx.mark_as_relevant(l); + theory_var v = mk_var(n); + ctx.attach_th_var(n, this, v); + m_tvars.push_back(v); + TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(n->get_owner(), get_manager()) << " := " << v << "\n";); } bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { - TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); - SASSERT(atom->get_family_id() == get_family_id()); + TRACE("t_fpa_detail", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); + SASSERT(atom->get_family_id() == get_family_id()); ast_manager & m = get_manager(); context & ctx = get_context(); - simplifier & simp = ctx.get_simplifier(); - bv_util & bu = m_converter.bu(); - expr_ref bv_atom(m); - proof_ref pr(m); if (ctx.b_internalized(atom)) return true; @@ -96,187 +377,157 @@ namespace smt { for (unsigned i = 0; i < num_args; i++) ctx.internalize(atom->get_arg(i), false); - m_rw(atom, bv_atom); - simp(bv_atom, bv_atom, pr); - - ctx.internalize(bv_atom, gate_ctx); - literal def = ctx.get_literal(bv_atom); literal l(ctx.mk_bool_var(atom)); ctx.set_var_theory(l.var(), get_id()); - pred_atom * a = new (get_region()) pred_atom(l, def); - insert_bv2a(l.var(), a); - m_trail_stack.push(fpa_atom_trail(l.var())); + + expr_ref bv_atom(m); + bv_atom = convert_atom(atom); + bv_atom = m.mk_and(bv_atom, mk_side_conditions()); - if (!ctx.relevancy()) { - ctx.mk_th_axiom(get_id(), l, ~def); - ctx.mk_th_axiom(get_id(), ~l, def); - } - - add_extra_assertions(); - + expr_ref atom_iff(m); + assert_cnstr(m.mk_iff(atom, bv_atom)); return true; } bool theory_fpa::internalize_term(app * term) { - TRACE("t_fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); + TRACE("t_fpa_detail", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); SASSERT(term->get_family_id() == get_family_id()); SASSERT(!get_context().e_internalized(term)); - + ast_manager & m = get_manager(); context & ctx = get_context(); - simplifier & simp = ctx.get_simplifier(); - bv_util & bu = m_converter.bu(); - sort * term_sort = m.get_sort(term); - expr_ref t(m), bv_term(m); - proof_ref pr(m); unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); + + enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : + ctx.mk_enode(term, false, false, true); - m_rw(term, t); - simp(t, t, pr); + if (is_attached_to_var(e)) + return false; - if (m_converter.is_rm(term_sort)) { - SASSERT(is_app(t)); - expr_ref bv_rm(m); - proof_ref bv_pr(m); - simp(t, bv_rm, bv_pr); + attach_new_th_var(e); + TRACE("t_fpa", tout << "internalized? " << (ctx.e_internalized(term)?"yes":"no") << std::endl;); + return true; + } - bv_term = bv_rm; - } - else if (m_converter.is_float(term_sort)) { - SASSERT(is_app(t) && to_app(t)->get_num_args() == 3); - app * a = to_app(t); - expr_ref sgn(m), sig(m), exp(m); - proof_ref pr_sgn(m), pr_sig(m), pr_exp(m); - simp(a->get_arg(0), sgn, pr_sgn); - simp(a->get_arg(1), sig, pr_sig); - simp(a->get_arg(2), exp, pr_exp); + void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { + TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); + SASSERT(n->get_owner()->get_family_id() == get_family_id() || + n->get_owner()->get_family_id() == null_theory_id); + SASSERT(s->get_family_id() == get_family_id()); + ast_manager & m = get_manager(); - m_converter.mk_triple(sgn, sig, exp, bv_term); - } - else if (term->get_decl_kind() == OP_FLOAT_TO_IEEE_BV || - term->get_decl_kind() == OP_FLOAT_TO_REAL) { - SASSERT(is_app(t)); - expr_ref bv_e(m); - proof_ref bv_pr(m); - simp(t, bv_term, bv_pr); - } - else - NOT_IMPLEMENTED_YET(); - - TRACE("t_fpa", tout << "converted: " << mk_ismt2_pp(bv_term, get_manager()) << "\n";); - - SASSERT(!m_trans_map.contains(term)); - m_trans_map.insert(term, bv_term, 0); - - add_extra_assertions(); - - enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true); - theory_var v = mk_var(e); - ctx.attach_th_var(e, this, v); - m_tvars.push_back(v); - TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";); - SASSERT(e->get_th_var(get_id()) != null_theory_var); - return v != null_theory_var; - } - - void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { - if (!is_attached_to_var(n)) { - TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); - context & ctx = get_context(); - ast_manager & m = get_manager(); - simplifier & simp = ctx.get_simplifier(); - app * owner = n->get_owner(); - expr_ref converted(m); - proof_ref pr(m); - - theory_var v = mk_var(n); - ctx.attach_th_var(n, this, v); - m_tvars.push_back(v); - m_rw(owner, converted); - simp(converted, converted, pr); - m_trans_map.insert(owner, converted, 0); - - add_extra_assertions(); + if (!is_attached_to_var(n)) + attach_new_th_var(n); - sort * owner_sort = m.get_sort(owner); - if (m_converter.is_rm(owner_sort)) { - bv_util & bu = m_converter.bu(); - expr_ref t(m); - t = bu.mk_ule(converted, bu.mk_numeral(4, bu.get_bv_size(converted))); - ctx.internalize_assertion(t, proof_ref(m), 0); + app * owner = n->get_owner(); + sort * owner_sort = m.get_sort(owner); + if (m_converter.is_rm(owner_sort)) { + bv_util & bu = m_converter.bu(); + func_decl *wrap, *unwrap; + get_wrap(owner_sort, wrap, unwrap); + if (owner->get_decl() != unwrap) + { + expr_ref converted(m), t(m); + m_rw(owner, converted); + t = bu.mk_ule(converted, bu.mk_numeral(4, 3)); + assert_cnstr(t); } - - TRACE("t_fpa", tout << "new theory var (const): " << mk_ismt2_pp(owner, get_manager()) << " := " << v << "\n";); } } void theory_fpa::new_eq_eh(theory_var x, theory_var y) { - TRACE("t_fpa", tout << "new eq: " << x << " = " << y << "\n";); ast_manager & m = get_manager(); + + TRACE("t_fpa", tout << "new eq: " << x << " = " << y << std::endl; + tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " = " << + mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl; ); + context & ctx = get_context(); float_util & fu = m_converter.fu(); + bv_util & bu = m_converter.bu(); + mpf_manager & mpfm = fu.fm(); - app * ax = get_enode(x)->get_owner(); - app * ay = get_enode(y)->get_owner(); - expr * ex, *ey; - proof * px, *py; - m_trans_map.get(ax, ex, px); - m_trans_map.get(ay, ey, py); + app * xe = get_enode(x)->get_owner(); + app * ye = get_enode(y)->get_owner(); - if (fu.is_float(get_enode(x)->get_owner())) { - expr * sgn_x, *sig_x, *exp_x; - expr * sgn_y, *sig_y, *exp_y; - split_triple(ex, sgn_x, sig_x, exp_x); - split_triple(ey, sgn_y, sig_y, exp_y); + if (fu.is_float(xe) && fu.is_float(ye)) + { + expr_ref xc(m), yc(m); + xc = convert_term(xe); + yc = convert_term(ye); - mk_bv_eq(sgn_x, sgn_y); - mk_bv_eq(sig_x, sig_y); - mk_bv_eq(exp_x, exp_y); + expr *x_sgn, *x_sig, *x_exp; + m_converter.split_triple(xc, x_sgn, x_sig, x_exp); + expr *y_sgn, *y_sig, *y_exp; + m_converter.split_triple(yc, y_sgn, y_sig, y_exp); + + expr_ref c(m); + c = m.mk_and(m.mk_eq(x_sgn, y_sgn), + m.mk_eq(x_sig, y_sig), + m.mk_eq(x_exp, y_exp)); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); } - else if (fu.is_rm(get_enode(x)->get_owner())) { - mk_bv_eq(ex, ey); + else if (fu.is_rm(xe) && fu.is_rm(ye)) { + expr_ref xc(m), yc(m); + xc = convert_term(xe); + yc = convert_term(ye); + expr_ref c(m); + c = m.mk_eq(xc, yc); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); } - else - UNREACHABLE(); + + return; } void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { - TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << "\n";); ast_manager & m = get_manager(); + + TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << std::endl; + tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " != " << + mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); + context & ctx = get_context(); float_util & fu = m_converter.fu(); + bv_util & bu = m_converter.bu(); + mpf_manager & mpfm = fu.fm(); - app * ax = get_enode(x)->get_owner(); - app * ay = get_enode(y)->get_owner(); - expr * ex, *ey; - proof * px, *py; - m_trans_map.get(ax, ex, px); - m_trans_map.get(ay, ey, py); + app * xe = get_enode(x)->get_owner(); + app * ye = get_enode(y)->get_owner(); - expr_ref deq(m); + if (fu.is_float(xe) && fu.is_float(ye)) + { + expr_ref xc(m), yc(m); + xc = convert_term(xe); + yc = convert_term(ye); - if (fu.is_float(m.get_sort(get_enode(x)->get_owner()))) { - expr * sgn_x, *sig_x, *exp_x; - expr * sgn_y, *sig_y, *exp_y; - split_triple(ex, sgn_x, sig_x, exp_x); - split_triple(ex, sgn_y, sig_y, exp_y); - - deq = m.mk_or(m.mk_not(m.mk_eq(sgn_x, sgn_y)), - m.mk_not(m.mk_eq(sig_x, sig_y)), - m.mk_not(m.mk_eq(exp_x, exp_y))); - } - else if (fu.is_rm(m.get_sort(get_enode(x)->get_owner()))) { - deq = m.mk_not(m.mk_eq(ex, ey)); + expr *x_sgn, *x_sig, *x_exp; + m_converter.split_triple(xc, x_sgn, x_sig, x_exp); + expr *y_sgn, *y_sig, *y_exp; + m_converter.split_triple(yc, y_sgn, y_sig, y_exp); + + expr_ref c(m); + c = m.mk_or(m.mk_not(m.mk_eq(x_sgn, y_sgn)), + m.mk_not(m.mk_eq(x_sig, y_sig)), + m.mk_not(m.mk_eq(x_exp, y_exp))); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); } - else - UNREACHABLE(); - - ctx.internalize(deq, true); - ctx.mk_th_axiom(get_id(), 1, &ctx.get_literal(deq)); - ctx.mark_as_relevant(deq); + else if (fu.is_rm(xe) && fu.is_rm(ye)) { + expr_ref xc(m), yc(m); + xc = convert_term(xe); + yc = convert_term(ye); + expr_ref c(m); + c = m.mk_not(m.mk_eq(xc, yc)); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); + } + + return; } void theory_fpa::push_scope_eh() { @@ -289,198 +540,117 @@ namespace smt { m_trail_stack.pop_scope(num_scopes); unsigned num_old_vars = get_old_num_vars(num_scopes); for (unsigned i = num_old_vars; i < get_num_vars(); i++) { - m_trans_map.erase(get_enode(m_tvars[i])->get_owner()); + // m_trans_map.erase(get_enode(m_tvars[i])->get_owner()); } m_tvars.shrink(num_old_vars); theory::pop_scope_eh(num_scopes); - } - - model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { - ast_manager & m = get_manager(); - context & ctx = get_context(); - bv_util & bu = m_converter.bu(); - float_util & fu = m_converter.fu(); - mpf_manager & mpfm = fu.fm(); - unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - - theory_var v = n->get_th_var(get_id()); - SASSERT(v != null_theory_var); - expr * fpa_e = get_enode(v)->get_owner(); - TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(fpa_e, m) << "\n";); - - expr * bv_e; - proof * bv_pr; - m_trans_map.get(fpa_e, bv_e, bv_pr); - sort * fpa_e_srt = m.get_sort(fpa_e); - expr_wrapper_proc * res = 0; - - if (fu.is_rm(fpa_e_srt)) { - if (!ctx.e_internalized(bv_e)) - res = alloc(expr_wrapper_proc, fu.mk_round_nearest_ties_to_away()); - else - { - theory_bv * bv_th = (theory_bv*)ctx.get_theory(m.get_family_id("bv")); - rational val; - - bv_th->get_fixed_value(ctx.get_enode(bv_e)->get_owner(), val); // OK to fail - app * fp_val_e; - SASSERT(val.is_uint64()); - switch (val.get_uint64()) - { - case BV_RM_TIES_TO_AWAY: fp_val_e = fu.mk_round_nearest_ties_to_away(); break; - case BV_RM_TIES_TO_EVEN: fp_val_e = fu.mk_round_nearest_ties_to_even(); break; - case BV_RM_TO_NEGATIVE: fp_val_e = fu.mk_round_toward_negative(); break; - case BV_RM_TO_POSITIVE: fp_val_e = fu.mk_round_toward_positive(); break; - case BV_RM_TO_ZERO: - default: fp_val_e = fu.mk_round_toward_zero(); - } - - TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mk_ismt2_pp(fp_val_e, m) << std::endl;); - res = alloc(expr_wrapper_proc, fp_val_e); - } - } - else if (fu.is_float(fpa_e_srt)) { - expr * bv_sgn, *bv_sig, *bv_exp; - split_triple(bv_e, bv_sgn, bv_sig, bv_exp); - - family_id fid = m.get_family_id("bv"); - theory_bv * bv_th = (theory_bv*)ctx.get_theory(fid); - - app * e_sgn, *e_sig, *e_exp; - unsigned ebits = fpa_e_srt->get_parameter(0).get_int(); - unsigned sbits = fpa_e_srt->get_parameter(1).get_int(); - unsigned sig_sz = fpa_e_srt->get_parameter(1).get_int() - 1; - - rational bias = mpfm.m_powers2.m1(ebits - 1); - rational sgn_r(0), sig_r(0), exp_r(bias); - - e_sgn = (ctx.e_internalized(bv_sgn)) ? ctx.get_enode(bv_sgn)->get_owner() : - bu.mk_numeral(0, 1); - e_sig = (ctx.e_internalized(bv_sig)) ? ctx.get_enode(bv_sig)->get_owner() : - bu.mk_numeral(0, sig_sz); - e_exp = (ctx.e_internalized(bv_exp)) ? ctx.get_enode(bv_exp)->get_owner() : - bu.mk_numeral(bias, ebits); - - TRACE("t_fpa", tout << "bv rep: [" - << mk_ismt2_pp(e_sgn, m) << "\n" - << mk_ismt2_pp(e_sig, m) << "\n" - << mk_ismt2_pp(e_exp, m) << "]\n";); - - if (!ctx.e_internalized(bv_sgn) || - ctx.get_enode(bv_sgn)->get_num_th_vars() == 0 || - !bv_th->get_fixed_value(e_sgn, sgn_r)) - sgn_r = rational(0); - if (!ctx.e_internalized(bv_sig) || - ctx.get_enode(bv_sig)->get_num_th_vars() == 0 || - !bv_th->get_fixed_value(e_sig, sig_r)) - sig_r = rational(0); - if (!ctx.e_internalized(bv_exp) || - ctx.get_enode(bv_exp)->get_num_th_vars() == 0 || - !bv_th->get_fixed_value(e_exp, exp_r)) - exp_r = bias; - - // un-bias exponent - rational exp_unbiased_r; - exp_unbiased_r = exp_r - bias; - - TRACE("t_fpa", tout << "bv model: [" << sgn_r.to_string() << " " - << sig_r.to_string() << " " - << exp_unbiased_r.to_string() << "(" << exp_r.to_string() << ")]\n"; ); - - scoped_mpz sig_z(mpzm); - mpf_exp_t exp_z; - scoped_mpq sig_q(mpqm), exp_q(mpqm); - scoped_mpz sig_num(mpzm), exp_num(mpzm); - mpqm.set(sig_q, sig_r.to_mpq()); - mpzm.set(sig_num, sig_q.get().numerator()); - mpqm.set(exp_q, exp_unbiased_r.to_mpq()); - mpzm.set(exp_num, exp_q.get().numerator()); - mpzm.set(sig_z, sig_num); - exp_z = mpzm.get_int64(exp_num); - - scoped_mpf fp_val(mpfm); - mpfm.set(fp_val, ebits, sbits, !sgn_r.is_zero(), sig_z, exp_z); - - TRACE("t_fpa", tout << mk_ismt2_pp(fpa_e, m) << " := " << mpfm.to_string(fp_val) << std::endl;); - res = alloc(expr_wrapper_proc, m_factory->mk_value(fp_val)); - } - else - UNREACHABLE(); - - return res; - } + } void theory_fpa::assign_eh(bool_var v, bool is_true) { - TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << ")\n";); - /* CMW: okay to ignore? */ - theory::assign_eh(v, is_true); + ast_manager & m = get_manager(); + context & ctx = get_context(); + expr * e = ctx.bool_var2expr(v); + + TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << "):\n" << mk_ismt2_pp(e, m) << "\n";); + + expr_ref converted(m); + m_rw(e, converted); + converted = m.mk_and(converted, mk_side_conditions()); + if (!is_true) converted = m.mk_not(converted); + assert_cnstr(converted); } void theory_fpa::relevant_eh(app * n) { TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, get_manager()) << "\n";); + + NOT_IMPLEMENTED_YET(); + ast_manager & m = get_manager(); - context & ctx = get_context(); + + if (m.is_bool(n)) + return; + float_util & fu = m_converter.fu(); bv_util & bu = m_converter.bu(); + mpf_manager & mpfm = fu.fm(); - if (m.is_bool(n)) { - bool_var v = ctx.get_bool_var(n); - atom * a = get_bv2a(v); - pred_atom * pa = static_cast(a); - ctx.mark_as_relevant(pa->m_def); - ctx.mk_th_axiom(get_id(), pa->m_var, ~pa->m_def); - ctx.mk_th_axiom(get_id(), ~pa->m_var, pa->m_def); - } - else if (ctx.e_internalized(n)) { - SASSERT(m_trans_map.contains(n)); - expr * ex; - proof * px; - m_trans_map.get(n, ex, px); - sort * n_srt = m.get_sort(n); + if (bu.is_bv(n)) + return; - if (fu.is_rm(n_srt)) { - ctx.mark_as_relevant(ex); - } - else if (fu.is_float(n_srt)) { - expr * bv_sgn, *bv_sig, *bv_exp; - split_triple(ex, bv_sgn, bv_sig, bv_exp); + sort * s = m.get_sort(n); + func_decl *wrap, *unwrap; + get_wrap(s, wrap, unwrap); - ctx.mark_as_relevant(bv_sgn); - ctx.mark_as_relevant(bv_sig); - ctx.mark_as_relevant(bv_exp); - } - else if (n->get_decl()->get_decl_kind() == OP_FLOAT_TO_IEEE_BV || - n->get_decl()->get_decl_kind() == OP_FLOAT_TO_REAL) { - expr_ref eq(m); - app * ex_a = to_app(ex); - if (n->get_id() > ex_a->get_id()) - std::swap(n, ex_a); - eq = m.mk_eq(n, ex_a); - ctx.internalize(eq, false); - literal l = ctx.get_literal(eq); - ctx.mk_th_axiom(get_id(), 1, &l); - ctx.mark_as_relevant(l); + if (n->get_decl() != unwrap) { + expr * wrapped = m.mk_app(wrap, n); + mpf_rounding_mode rm; + scoped_mpf val(mpfm); + if (fu.is_rm_value(n, rm)) + assert_cnstr(m.mk_eq(wrapped, bu.mk_numeral(rm, 3))); + else if (fu.is_value(n, val)) { + unsigned sz = val.get().get_ebits() + val.get().get_sbits(); + scoped_mpq q(fu.fm().mpq_manager()); + mpfm.to_rational(val, q); + assert_cnstr(m.mk_eq(wrapped, bu.mk_numeral(rational(q), sz))); } else - NOT_IMPLEMENTED_YET(); + assert_cnstr(m.mk_eq(m.mk_app(unwrap, wrapped), n)); } - else - UNREACHABLE(); } void theory_fpa::reset_eh() { + TRACE("t_fpa", tout << "reset_eh for: " << "\n";); pop_scope_eh(m_trail_stack.get_num_scopes()); m_rw.reset(); - m_trans_map.reset(); m_bool_var2atom.reset(); m_temporaries.reset(); m_tvars.reset(); theory::reset_eh(); } - void theory_fpa::init_model(model_generator & m) { + void theory_fpa::init_model(model_generator & mg) { + TRACE("t_fpa", tout << "initializing model" << std::endl;); m_factory = alloc(fpa_factory, get_manager(), get_family_id()); - m.register_factory(m_factory); + mg.register_factory(m_factory); + TRACE("t_fpa", display(tout);); + } + + model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { + TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); + + ast_manager & m = get_manager(); + float_util & fu = m_converter.fu(); + + expr * owner = n->get_owner(); + sort * o_srt = m.get_sort(owner); + + mpf_rounding_mode rm; + + if (fu.is_rm_value(n->get_owner(), rm)) + return alloc(expr_wrapper_proc, n->get_owner()); + else if (fu.is_value(n->get_owner())) + return alloc(expr_wrapper_proc, n->get_owner()); + else if (fu.is_rm(owner)) + return alloc(fpa_rm_value_proc, this, app_ref(to_app(owner), m)); + else if (fu.is_float(owner)) + return alloc(fpa_value_proc, this, app_ref(to_app(owner), m)); + + UNREACHABLE(); + return 0; + } + + void theory_fpa::finalize_model(model_generator & mg) {} + + void theory_fpa::display(std::ostream & out) const + { + ast_manager & m = get_manager(); + context & ctx = get_context(); + + out << "theory variables:" << std::endl; + ptr_vector::const_iterator it = ctx.begin_enodes(); + ptr_vector::const_iterator end = ctx.end_enodes(); + for (; it != end; it++) + out << (*it)->get_th_var(get_family_id()) << " -> " << + mk_ismt2_pp((*it)->get_owner(), m) << std::endl; } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 7b29b82de..0c472be33 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -23,7 +23,9 @@ Revision History: #include"trail.h" #include"fpa2bv_converter.h" #include"fpa2bv_rewriter.h" +#include"th_rewriter.h" #include"value_factory.h" +#include"smt_model_generator.h" namespace smt { @@ -52,8 +54,7 @@ namespace smt { app * mk_value(mpf const & x) { return m_util.mk_value(x); } - }; - + }; class theory_fpa : public theory { class th_trail_stack : public trail_stack { @@ -62,6 +63,45 @@ namespace smt { virtual ~th_trail_stack() {} }; + class fpa2bv_converter_wrapped : public fpa2bv_converter { + public: + theory_fpa & m_th; + fpa2bv_converter_wrapped(ast_manager & m, theory_fpa * th) : + fpa2bv_converter(m), + m_th(*th) {} + virtual ~fpa2bv_converter_wrapped() {} + virtual void mk_const(func_decl * f, expr_ref & result); + virtual void mk_rm_const(func_decl * f, expr_ref & result); + }; + + class fpa_value_proc : public model_value_proc { + protected: + theory_fpa & m_th; + app_ref m_a; + svector m_dependencies; + public: + fpa_value_proc(theory_fpa * th, app_ref & a) : m_th(*th), m_a(a) {} + void add_dependency(enode * n) { m_dependencies.push_back(model_value_dependency(n)); } + virtual ~fpa_value_proc() {} + virtual void get_dependencies(buffer & result) { + result.append(m_dependencies.size(), m_dependencies.c_ptr()); + } + virtual app * mk_value(model_generator & mg, ptr_vector & values); + }; + + class fpa_rm_value_proc : public fpa_value_proc { + float_util & m_fu; + bv_util & m_bu; + public: + fpa_rm_value_proc(theory_fpa * th, app_ref & a) : + fpa_value_proc(th, a), + m_fu(th->m_converter.fu()), + m_bu(th->m_converter.bu()) {} + void add_dependency(enode * n) { fpa_value_proc::add_dependency(n); } + virtual ~fpa_rm_value_proc() {} + virtual app * mk_value(model_generator & mg, ptr_vector & values); + }; + public: class atom { public: @@ -79,17 +119,20 @@ namespace smt { void insert_bv2a(bool_var bv, pred_atom * a) { m_bool_var2atom.setx(bv, a, 0); } void erase_bv2a(bool_var bv) { m_bool_var2atom[bv] = 0; } pred_atom * get_bv2a(bool_var bv) const { return m_bool_var2atom.get(bv, 0); } - region & get_region() { return m_trail_stack.get_region(); } + region & get_region() { return m_trail_stack.get_region(); } protected: - fpa2bv_converter m_converter; - fpa2bv_rewriter m_rw; - expr_map m_trans_map; - th_trail_stack m_trail_stack; - bool_var2atom m_bool_var2atom; - enode_vector m_temporaries; - int_vector m_tvars; - fpa_factory * m_factory; + fpa2bv_converter_wrapped m_converter; + fpa2bv_rewriter m_rw; + th_rewriter m_th_rw; + th_trail_stack m_trail_stack; + bool_var2atom m_bool_var2atom; + enode_vector m_temporaries; + vector m_tvars; + fpa_factory * m_factory; + obj_map m_wraps; + obj_map m_unwraps; + float_decl_plugin m_flt_plugin; virtual final_check_status final_check_eh() { return FC_DONE; } virtual bool internalize_atom(app * atom, bool gate_ctx); @@ -108,21 +151,24 @@ namespace smt { void assign_eh(bool_var v, bool is_true); virtual void relevant_eh(app * n); virtual void init_model(model_generator & m); + virtual void finalize_model(model_generator & mg); + public: theory_fpa(ast_manager& m); virtual ~theory_fpa(); - protected: - void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { - SASSERT(is_app_of(e, get_family_id(), OP_FLOAT_TO_FP)); - SASSERT(to_app(e)->get_num_args() == 3); - sgn = to_app(e)->get_arg(0); - sig = to_app(e)->get_arg(1); - exp = to_app(e)->get_arg(2); - } + virtual void display(std::ostream & out) const; + + protected: + expr_ref mk_side_conditions(); + expr_ref convert_atom(expr * e); + expr_ref convert_term(expr * e); + void get_wrap(sort * s, func_decl *& wrap, func_decl *& unwrap); + void add_trail(ast * a); - void add_extra_assertions(); void mk_bv_eq(expr * x, expr * y); + void attach_new_th_var(enode * n); + void assert_cnstr(expr * e); }; }; From 9dd4d7b011886d3948ac7548eba337a08d5c04a5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 21 Dec 2014 20:43:26 +0000 Subject: [PATCH 100/646] Python API bugfix. Thanks to Tom Ball for reporting this one. Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 720335d41..bb0212820 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -6058,7 +6058,7 @@ class Solver(Z3PPObject): e = es[sz1].as_ast() else: e = BoolVal(True, self.ctx).as_ast() - return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) + return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) From b8c373bbce423f861cb1583dbc73d53fa987e3d6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 22 Dec 2014 14:25:23 +0000 Subject: [PATCH 101/646] fpa2bv tactic bugfix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/fpa2bv_tactic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_tactic.cpp b/src/tactic/fpa/fpa2bv_tactic.cpp index 4a3a01b6f..5fb35d972 100644 --- a/src/tactic/fpa/fpa2bv_tactic.cpp +++ b/src/tactic/fpa/fpa2bv_tactic.cpp @@ -96,8 +96,8 @@ class fpa2bv_tactic : public tactic { g->inc_depth(); result.push_back(g.get()); - for (unsigned i = 0; i < m_conv.extra_assertions.size(); i++) - result.back()->assert_expr(m_conv.extra_assertions[i].get()); + for (unsigned i = 0; i < m_conv.m_extra_assertions.size(); i++) + result.back()->assert_expr(m_conv.m_extra_assertions[i].get()); SASSERT(g->is_well_sorted()); TRACE("fpa2bv", tout << "AFTER: " << std::endl; g->display(tout); From 7f8a34d2e11e99ff5272de113bfbe382b16bb0cd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:31:30 +0000 Subject: [PATCH 102/646] Adjusted default model display for float literals. Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast_smt2_pp.cpp | 38 +++++++++++++++++++++++++------------- src/ast/ast_smt2_pp.h | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 00ce6aa8f..a9e223c55 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -222,7 +222,7 @@ format * smt2_pp_environment::pp_bv_literal(app * t, bool use_bv_lits, bool bv_n return vf; } -format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits) { +format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool use_float_real_lits) { mpf_manager & fm = get_futil().fm(); scoped_mpf v(fm); ast_manager & m = get_manager(); @@ -231,28 +231,38 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits) { VERIFY(get_futil().is_value(t, v)); if (fm.is_nan(v)) { buf << "(_ NaN " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; - return mk_string(get_manager(), buf.c_str()); + return mk_string(m, buf.c_str()); } else if (fm.is_pinf(v)) { buf << "(_ +oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; - return mk_string(get_manager(), buf.c_str()); + return mk_string(m, buf.c_str()); } else if (fm.is_ninf(v)) { buf << "(_ -oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; - return mk_string(get_manager(), buf.c_str()); + return mk_string(m, buf.c_str()); } else if (fm.is_pzero(v)) { buf << "(_ +zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; - return mk_string(get_manager(), buf.c_str()); + return mk_string(m, buf.c_str()); } else if (fm.is_nzero(v)) { buf << "(_ -zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; - return mk_string(get_manager(), buf.c_str()); + return mk_string(m, buf.c_str()); } - else { - buf << "(fp #b" << (fm.sgn(v) ? 1 : 0); - body = mk_string(get_manager(), buf.c_str()); - body = mk_compose(m, body, mk_string(get_manager(), " ")); + else if (use_float_real_lits) + { + buf << "((_ to_fp " << v.get().get_ebits() << " " << + v.get().get_sbits() << ") RTZ " << + fm.to_string(v).c_str() << ")"; + return mk_string(m, buf.c_str()); + } + else { + if (use_bv_lits) + buf << "(fp #b" << (fm.sgn(v) ? 1 : 0); + else + buf << "(fp (_ bv" << (fm.sgn(v) ? 1 : 0) << " 1)"; + body = mk_string(m, buf.c_str()); + body = mk_compose(m, body, mk_string(m, " ")); mpf_exp_t exp = fm.exp(v); const mpz & bias = fm.m_powers2.m1(v.get().get_ebits() - 1); @@ -260,7 +270,7 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits) { app_ref e_biased_exp(m); e_biased_exp = get_bvutil().mk_numeral(biased_exp, v.get().get_ebits()); body = mk_compose(m, body, pp_bv_literal(e_biased_exp, use_bv_lits, false)); - body = mk_compose(m, body, mk_string(get_manager(), " ")); + body = mk_compose(m, body, mk_string(m, " ")); scoped_mpz sig(fm.mpz_manager()); sig = fm.sig(v); @@ -268,7 +278,7 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits) { e_sig = get_bvutil().mk_numeral(rational(sig), v.get().get_sbits() - 1); body = mk_compose(m, body, pp_bv_literal(e_sig, use_bv_lits, false)); - body = mk_compose(m, body, mk_string(get_manager(), ")")); + body = mk_compose(m, body, mk_string(m, ")")); return body; } } @@ -446,6 +456,7 @@ class smt2_printer { bool m_pp_decimal; unsigned m_pp_decimal_precision; bool m_pp_bv_lits; + bool m_pp_float_real_lits; bool m_pp_bv_neg; unsigned m_pp_max_depth; unsigned m_pp_min_alias_size; @@ -565,7 +576,7 @@ class smt2_printer { f = m_env.pp_bv_literal(c, m_pp_bv_lits, m_pp_bv_neg); } else if (m_env.get_futil().is_value(c)) { - f = m_env.pp_float_literal(c, m_pp_bv_lits); + f = m_env.pp_float_literal(c, m_pp_bv_lits, m_pp_float_real_lits); } else if (m_env.get_dlutil().is_numeral(c)) { f = m_env.pp_datalog_literal(c); @@ -1008,6 +1019,7 @@ public: m_pp_decimal = p.decimal(); m_pp_decimal_precision = p.decimal_precision(); m_pp_bv_lits = p.bv_literals(); + m_pp_float_real_lits = p.fp_real_literals(); m_pp_bv_neg = p.bv_neg(); m_pp_max_depth = p.max_depth(); m_pp_min_alias_size = p.min_alias_size(); diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index 93feec8d5..37d13e57a 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -52,7 +52,7 @@ public: virtual format_ns::format * pp_fdecl(func_decl * f, unsigned & len); virtual format_ns::format * pp_bv_literal(app * t, bool use_bv_lits, bool bv_neg); virtual format_ns::format * pp_arith_literal(app * t, bool decimal, unsigned prec); - virtual format_ns::format * pp_float_literal(app * t, bool use_bv_lits); + virtual format_ns::format * pp_float_literal(app * t, bool use_bv_lits, bool use_float_real_lits); virtual format_ns::format * pp_datalog_literal(app * t); virtual format_ns::format * pp_sort(sort * s); virtual format_ns::format * pp_fdecl_ref(func_decl * f); From 6ebeebde509d23b597889f3dc2078c79d964beb8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:32:34 +0000 Subject: [PATCH 103/646] Added parameter to display floating point numerals as reals Signed-off-by: Christoph M. Wintersteiger --- src/ast/pp_params.pyg | 1 + src/util/mpf.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ast/pp_params.pyg b/src/ast/pp_params.pyg index 75b2baddd..7424b516f 100644 --- a/src/ast/pp_params.pyg +++ b/src/ast/pp_params.pyg @@ -10,6 +10,7 @@ def_module_params('pp', ('decimal', BOOL, False, 'pretty print real numbers using decimal notation (the output may be truncated). Z3 adds a ? if the value is not precise'), ('decimal_precision', UINT, 10, 'maximum number of decimal places to be used when pp.decimal=true'), ('bv_literals', BOOL, True, 'use Bit-Vector literals (e.g, #x0F and #b0101) during pretty printing'), + ('fp_real_literals', BOOL, False, 'use real-numbered floating point literals (e.g, +1.0p-1) during pretty printing'), ('bv_neg', BOOL, False, 'use bvneg when displaying Bit-Vector literals where the most significant bit is 1'), ('flat_assoc', BOOL, True, 'flat associative operators (when pretty printing SMT2 terms/formulas)'), ('fixed_indent', BOOL, False, 'use a fixed indentation for applications'), diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index c4fa17d9a..ac2eb3096 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1223,7 +1223,9 @@ std::string mpf_manager::to_string(mpf const & x) { std::stringstream ss; m_mpq_manager.display_decimal(ss, r, x.sbits); - ss << "p" << exponent; // "p" means 2^exp + if (m_mpq_manager.is_int(r)) + ss << ".0"; + ss << " " << exponent; res += ss.str(); } } From 55662bcf6b62d835878ebd4404f428a2b6ab4dbc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:33:19 +0000 Subject: [PATCH 104/646] fpa2bv: added reset(), adjustments for consistency Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 43 +++++++++++++++++++------------- src/ast/fpa/fpa2bv_converter.h | 4 +++ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index f4b4e7951..0de267d2f 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -37,19 +37,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : } fpa2bv_converter::~fpa2bv_converter() { - dec_ref_map_key_values(m, m_const2bv); - dec_ref_map_key_values(m, m_rm_const2bv); - dec_ref_map_key_values(m, m_uf2bvuf); - - obj_map::iterator it = m_uf23bvuf.begin(); - obj_map::iterator end = m_uf23bvuf.end(); - for (; it != end; ++it) { - m.dec_ref(it->m_key); - m.dec_ref(it->m_value.f_sgn); - m.dec_ref(it->m_value.f_sig); - m.dec_ref(it->m_value.f_exp); - } - m_uf23bvuf.reset(); + reset(); } void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { @@ -58,8 +46,8 @@ void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { expr_ref sgn(m), s(m), e(m); m_simp.mk_eq(to_app(a)->get_arg(0), to_app(b)->get_arg(0), sgn); - m_simp.mk_eq(to_app(a)->get_arg(1), to_app(b)->get_arg(1), s); - m_simp.mk_eq(to_app(a)->get_arg(2), to_app(b)->get_arg(2), e); + m_simp.mk_eq(to_app(a)->get_arg(1), to_app(b)->get_arg(1), e); + m_simp.mk_eq(to_app(a)->get_arg(2), to_app(b)->get_arg(2), s); // The SMT FPA theory asks for _one_ NaN value, but the bit-blasting // has many, like IEEE754. This encoding of equality makes it look like @@ -2261,7 +2249,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits. // exp < bv_sz (+sign bit which is [0]) - unsigned exp_worst_case_sz = (unsigned)((log(bv_sz) / log(2)) + 1); + unsigned exp_worst_case_sz = (unsigned)((log((double)bv_sz) / log((double)2)) + 1.0); if (exp_sz < exp_worst_case_sz) { // exp_sz < exp_worst_case_sz and exp >= 0. @@ -2473,9 +2461,9 @@ void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); - sgn = to_app(e)->get_arg(0); - sig = to_app(e)->get_arg(2); + sgn = to_app(e)->get_arg(0); exp = to_app(e)->get_arg(1); + sig = to_app(e)->get_arg(2); } void fpa2bv_converter::split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const { @@ -3140,3 +3128,22 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & TRACE("fpa2bv_round", tout << "ROUND = " << mk_ismt2_pp(result, m) << std::endl; ); } + + +void fpa2bv_converter::reset(void) { + dec_ref_map_key_values(m, m_const2bv); + dec_ref_map_key_values(m, m_rm_const2bv); + dec_ref_map_key_values(m, m_uf2bvuf); + + obj_map::iterator it = m_uf23bvuf.begin(); + obj_map::iterator end = m_uf23bvuf.end(); + for (; it != end; ++it) { + m.dec_ref(it->m_key); + m.dec_ref(it->m_value.f_sgn); + m.dec_ref(it->m_value.f_sig); + m.dec_ref(it->m_value.f_exp); + } + m_uf23bvuf.reset(); + + m_extra_assertions.reset(); +} \ No newline at end of file diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 5da0ca463..cd92a6ab2 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -63,6 +63,7 @@ public: float_util & fu() { return m_util; } bv_util & bu() { return m_bv_util; } + arith_util & au() { return m_arith_util; } bool is_float(sort * s) { return m_util.is_float(s); } bool is_float(expr * e) { return is_app(e) && m_util.is_float(to_app(e)->get_decl()->get_range()); } @@ -141,11 +142,14 @@ public: obj_map const & uf2bvuf() const { return m_uf2bvuf; } obj_map const & uf23bvuf() const { return m_uf23bvuf; } + void reset(void); + void dbg_decouple(const char * prefix, expr_ref & e); expr_ref_vector m_extra_assertions; void mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + protected: void mk_is_nan(expr * e, expr_ref & result); void mk_is_inf(expr * e, expr_ref & result); From d1cb2566e4e45239000d82b703ea66585e317285 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:33:48 +0000 Subject: [PATCH 105/646] fpa2bv: adjustments for consistency Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/fpa2bv_model_converter.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 23809d265..989ad64ff 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -112,16 +112,16 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { unsigned sbits = fu.get_sbits(var->get_range()); expr_ref sgn(m), sig(m), exp(m); - bv_mdl->eval(a->get_arg(0), sgn, true); - bv_mdl->eval(a->get_arg(1), sig, true); - bv_mdl->eval(a->get_arg(2), exp, true); + bv_mdl->eval(a->get_arg(0), sgn, true); + bv_mdl->eval(a->get_arg(1), exp, true); + bv_mdl->eval(a->get_arg(2), sig, true); SASSERT(a->is_app_of(fu.get_family_id(), OP_FLOAT_TO_FP)); #ifdef Z3DEBUG SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); - SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(2))->get_decl()->get_arity() == 0); seen.insert(to_app(a->get_arg(0))->get_decl()); seen.insert(to_app(a->get_arg(1))->get_decl()); seen.insert(to_app(a->get_arg(2))->get_decl()); @@ -134,9 +134,9 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { if (!sgn && !sig && !exp) continue; - unsigned sgn_sz = bu.get_bv_size(m.get_sort(a->get_arg(0))); - unsigned sig_sz = bu.get_bv_size(m.get_sort(a->get_arg(1))) - 1; - unsigned exp_sz = bu.get_bv_size(m.get_sort(a->get_arg(2))); + unsigned sgn_sz = bu.get_bv_size(m.get_sort(a->get_arg(0))); + unsigned exp_sz = bu.get_bv_size(m.get_sort(a->get_arg(1))); + unsigned sig_sz = bu.get_bv_size(m.get_sort(a->get_arg(2))) - 1; rational sgn_q(0), sig_q(0), exp_q(0); From 7a15c41c473152ffd6d83e48133c3dd30b3e67be Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:40:36 +0000 Subject: [PATCH 106/646] FPA: improved error messages for to_fp Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 15 +++++++++++++-- src/ast/float_decl_plugin.h | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index d775523ec..846d6ddb7 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -499,8 +499,19 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } - else - NOT_IMPLEMENTED_YET(); + else { + m_manager->raise_exception("Unexpected argument combination for (_ to_fp eb sb). Supported argument combinations are: " + "((_ BitVec 1) (_ BitVec eb) (_ BitVec sb-1))," + "(_ BitVec (eb+sb))," + "(Real)," + "(RoundingMode (_ BitVec (eb+sb)))," + "(RoundingMode (_ FloatingPoint eb' sb'))," + "(RoundingMode Real Int), and" + "(RoundingMode Real)." + ); + } + + return 0; } func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index e4bf633a5..01daab8e3 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -239,6 +239,7 @@ public: app * mk_value(mpf const & v) { return m_plugin->mk_value(v); } bool is_value(expr * n) { return m_plugin->is_value(n); } bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); } + bool is_rm_value(expr * n) { return m_plugin->is_rm_value(n); } bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); } app * mk_pzero(unsigned ebits, unsigned sbits); @@ -254,8 +255,7 @@ public: bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } bool is_to_float(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } - - app * mk_to_float(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_TO_FP, arg1, arg2); } + app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); } app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } From 23aa614d55994518ac9079badd8027839edf0e99 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 13:44:29 +0000 Subject: [PATCH 107/646] FPA: New theory implementation with support for "hidden" variables, relevancy, and eq/diseq. Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 638 ++++++++++++++++++++++------------------- src/smt/theory_fpa.h | 82 ++---- 2 files changed, 366 insertions(+), 354 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 354dc7596..ec22e3ebb 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -22,17 +22,46 @@ Revision History: #include"theory_bv.h" #include"smt_model_generator.h" -namespace smt { +namespace smt { + + class fpa_factory : public value_factory { + float_util m_util; + + virtual app * mk_value_core(mpf const & val, sort * s) { + SASSERT(m_util.get_ebits(s) == val.get_ebits()); + SASSERT(m_util.get_sbits(s) == val.get_sbits()); + return m_util.mk_value(val); + } - class fpa_atom_trail : public trail { - bool_var m_var; public: - fpa_atom_trail(bool_var v) : m_var(v) {} - virtual ~fpa_atom_trail() {} + fpa_factory(ast_manager & m, family_id fid) : + value_factory(m, fid), + m_util(m) { + } + + virtual ~fpa_factory() {} + + virtual expr * get_some_value(sort * s) { NOT_IMPLEMENTED_YET(); } + virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { NOT_IMPLEMENTED_YET(); } + virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } + virtual void register_value(expr * n) { /* Ignore */ } + + app * mk_value(mpf const & x) { + return m_util.mk_value(x); + } + }; + + class fpa_conv_trail : public trail { + ast_manager & m; + obj_map & m_conversions; + expr * m_e; + public: + fpa_conv_trail(ast_manager & m, obj_map & c, expr * e) : m(m), m_conversions(c), m_e(e) {} + virtual ~fpa_conv_trail() {} virtual void undo(theory_fpa & th) { - theory_fpa::atom * a = th.get_bv2a(m_var); - a->~atom(); - th.erase_bv2a(m_var); + expr * v = m_conversions.find(m_e); + m_conversions.remove(m_e); + m.dec_ref(v); } }; @@ -43,15 +72,15 @@ namespace smt { if (m_const2bv.find(f, r)) { result = r; } - else { + else { sort * s = f->get_range(); - func_decl *w, *u; + func_decl_ref w(m), u(m); m_th.get_wrap(s, w, u); expr_ref bv(m); bv = m.mk_app(w, m.mk_const(f)); - unsigned bv_sz = m_th.m_converter.bu().get_bv_size(bv); - unsigned ebits = m_th.m_converter.fu().get_ebits(f->get_range()); - unsigned sbits = m_th.m_converter.fu().get_sbits(f->get_range()); + unsigned bv_sz = m_th.m_bv_util.get_bv_size(bv); + unsigned ebits = m_th.m_float_util.get_ebits(f->get_range()); + unsigned sbits = m_th.m_float_util.get_sbits(f->get_range()); SASSERT(bv_sz == ebits + sbits); m_th.m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), m_bv_util.mk_extract(sbits - 2, 0, bv), @@ -75,7 +104,7 @@ namespace smt { SASSERT(is_rm(f->get_range())); sort * s = f->get_range(); - func_decl *w, *u; + func_decl_ref w(m), u(m); m_th.get_wrap(s, w, u); result = m.mk_app(w, m.mk_const(f)); @@ -87,186 +116,134 @@ namespace smt { theory_fpa::theory_fpa(ast_manager & m) : theory(m.mk_family_id("float")), - m_converter(m, this), + m_converter(m, this), m_rw(m, m_converter, params_ref()), m_th_rw(m), - m_trail_stack(*this) + m_trail_stack(*this), + m_float_util(m_converter.fu()), + m_bv_util(m_converter.bu()), + m_arith_util(m_converter.au()) { } theory_fpa::~theory_fpa() - { + { + ast_manager & m = get_manager(); + dec_ref_map_values(m, m_conversions); + dec_ref_map_values(m, m_wraps); + dec_ref_map_values(m, m_unwraps); } app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector & values) { - TRACE("t_fpa", tout << "fpa_value_proc::mk_value for: " << mk_ismt2_pp(m_a, m_th.get_manager()) << "\n";); + SASSERT(values.size() == 3); ast_manager & m = m_th.get_manager(); - context & ctx = m_th.get_context(); - theory_id bv_id = m.mk_family_id("bv"); - theory_bv * th_bv = dynamic_cast(ctx.get_theory(bv_id)); - SASSERT(th_bv != 0); - - float_util & fu = m_th.m_converter.fu(); - bv_util & bu = m_th.m_converter.bu(); - mpf_manager & mpfm = fu.fm(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); - - sort * s = m.get_sort(m_a); - unsigned ebits = fu.get_ebits(s); - unsigned sbits = fu.get_sbits(s); + TRACE("t_fpa", tout << "fpa_value_proc::mk_value for: [" << + mk_ismt2_pp(values[0], m) << " " << + mk_ismt2_pp(values[1], m) << " " << + mk_ismt2_pp(values[2], m) << "]" << std::endl;); + + mpf_manager & mpfm = m_fu.fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); + + unsigned ebits = m_bu.get_bv_size(values[2]); + unsigned sbits = m_bu.get_bv_size(values[1]) + 1; + app * result; + + scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); scoped_mpz bias(mpzm); mpzm.power(mpz(2), ebits - 1, bias); mpzm.dec(bias); - app * result; - float_op_kind k = (float_op_kind) to_app(m_a)->get_decl_kind(); - switch (k) - { - case -1: { - func_decl *w, *u; - m_th.get_wrap(s, w, u); - rational bv_val(0); - scoped_mpz sgn(mpzm), sig(mpzm), exp(bias); - app_ref bv_w(m); - bv_w = m.mk_app(w, m_a); + rational sgn_q(0), sig_q(0), exp_q(bias); + unsigned bv_sz; - if (!th_bv->get_fixed_value(bv_w, bv_val)) - result = fu.mk_nan(ebits, sbits); - else { - scoped_mpz all_bits(mpzm); - all_bits = bv_val.to_mpq().numerator(); - SASSERT(mpzm.is_one(bv_val.to_mpq().denominator())); - - mpzm.machine_div2k(all_bits, ebits + sbits - 1, sgn); + bool r; + r = m_bu.is_numeral(values[0], sgn_q, bv_sz); SASSERT(r); SASSERT(bv_sz == 1); + r = m_bu.is_numeral(values[1], sig_q, bv_sz); SASSERT(r); SASSERT(bv_sz == sbits - 1); + r = m_bu.is_numeral(values[2], exp_q, bv_sz); SASSERT(r); SASSERT(bv_sz == ebits); - scoped_mpz tmp_p(mpzm); - mpzm.power(mpz(2), ebits + sbits - 1, tmp_p); + TRACE("t_fpa", tout << "sgn=" << sgn_q.to_string() << " ; " << + "sig=" << sig_q.to_string() << " ; " << + "exp=" << exp_q.to_string() << std::endl;); - if (mpzm.is_one(sgn)) mpzm.sub(all_bits, tmp_p, all_bits); + rational exp_u = exp_q - rational(bias); + SASSERT(exp_u.is_int64()); - mpzm.machine_div2k(all_bits, sbits - 1, exp); - scoped_mpz exp_u(mpzm); - mpzm.sub(exp, bias, exp_u); - SASSERT(mpzm.is_int64(exp_u)); - - mpzm.power(mpz(2), sbits - 1, tmp_p); - mpzm.mod(all_bits, tmp_p, sig); + scoped_mpf f(mpfm); + scoped_mpq sig_mpq(mpqm); + sig_mpq = sig_q.to_mpq(); + mpfm.set(f, ebits, sbits, sgn_q.is_one(), sig_mpq.get().numerator(), exp_u.get_int64()); + result = m_fu.mk_value(f); - scoped_mpf f(mpfm); - mpfm.set(f, ebits, sbits, mpzm.is_one(sgn), sig, mpzm.get_int64(exp_u)); - result = fu.mk_value(f); - } - break; - } - case OP_FLOAT_FP: { - bool is_internalized = ctx.e_internalized(m_a); - if (is_internalized) { - SASSERT(m_a->get_num_args() == 3); - app_ref a_sgn(m), a_sig(m), a_exp(m); - a_sgn = to_app(m_a->get_arg(0)); - a_exp = to_app(m_a->get_arg(1)); - a_sig = to_app(m_a->get_arg(2)); - - scoped_mpz bias(mpzm); - mpzm.power(mpz(2), ebits - 1, bias); - mpzm.dec(bias); - - rational sgn(0), sig(0), exp(bias); - th_bv->get_fixed_value(a_sgn, sgn); - th_bv->get_fixed_value(a_sig, sig); - th_bv->get_fixed_value(a_exp, exp); - - TRACE("t_fpa", tout << "sgn=" << sgn.to_string() << " ; " << - "sig=" << sig.to_string() << " ; " << - "exp=" << exp.to_string() << std::endl;); - - rational exp_u = exp - rational(bias); - SASSERT(exp_u.is_int64()); - - scoped_mpf f(mpfm); - scoped_mpq sig_q(mpqm); - sig_q = sig.to_mpq(); - mpfm.set(f, ebits, sbits, sgn.is_one(), sig_q.get().numerator(), exp_u.get_int64()); - result = fu.mk_value(f); - } - else { - result = fu.mk_nan(ebits, sbits); - } - break; - } - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("t_fpa", tout << "fpa_value_proc::mk_value result: " << mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + TRACE("t_fpa", tout << "fpa_value_proc::mk_value result: " << + mk_ismt2_pp(result, m_th.get_manager()) << "\n";); return result; } - app * theory_fpa::fpa_rm_value_proc::mk_value(model_generator & mg, ptr_vector & values) { - TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value for: " << mk_ismt2_pp(m_a, m_th.get_manager()) << "\n";); + app * theory_fpa::fpa_rm_value_proc::mk_value(model_generator & mg, ptr_vector & values) { + SASSERT(values.size() == 1); ast_manager & m = m_th.get_manager(); - context & ctx = m_th.get_context(); - theory_id bv_id = m.mk_family_id("bv"); - theory_bv * th_bv = dynamic_cast(ctx.get_theory(bv_id)); + + TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value for: [" << + mk_ismt2_pp(values[0], m) << "]" << std::endl;); app * result = 0; - mpf_rounding_mode rm; - if (m_th.m_converter.fu().is_rm_value(m_a, rm)) { - result = m_a.get(); - } - else { - sort * s = m.get_sort(m_a); - func_decl *w, *u; - m_th.get_wrap(s, w, u); + sort * s = m.get_sort(values[0]); + unsigned bv_sz; - app_ref bv_w(m); - bv_w = m.mk_app(w, m_a); - - rational val(0); - if (ctx.e_internalized(bv_w)) - if (!th_bv->get_fixed_value(bv_w, val)) - val = rational(0); + rational val(0); + bool r = m_bu.is_numeral(values[0], val, bv_sz); + SASSERT(r); + SASSERT(bv_sz == 3); - switch (val.get_uint64()) - { - case BV_RM_TIES_TO_AWAY: result = m_fu.mk_round_nearest_ties_to_away(); break; - case BV_RM_TIES_TO_EVEN: result = m_fu.mk_round_nearest_ties_to_even(); break; - case BV_RM_TO_NEGATIVE: result = m_fu.mk_round_toward_negative(); break; - case BV_RM_TO_POSITIVE: result = m_fu.mk_round_toward_positive(); break; - case BV_RM_TO_ZERO: - default: result = m_fu.mk_round_toward_zero(); - } + switch (val.get_uint64()) + { + case BV_RM_TIES_TO_AWAY: result = m_fu.mk_round_nearest_ties_to_away(); break; + case BV_RM_TIES_TO_EVEN: result = m_fu.mk_round_nearest_ties_to_even(); break; + case BV_RM_TO_NEGATIVE: result = m_fu.mk_round_toward_negative(); break; + case BV_RM_TO_POSITIVE: result = m_fu.mk_round_toward_positive(); break; + case BV_RM_TO_ZERO: + default: result = m_fu.mk_round_toward_zero(); } - TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value result: " << mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value result: " << + mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + return result; } - void theory_fpa::get_wrap(sort * s, func_decl *& wrap, func_decl *& unwrap) + void theory_fpa::get_wrap(sort * s, func_decl_ref & wrap, func_decl_ref & unwrap) { - if (!m_wraps.find(s, wrap) || !m_unwraps.find(s, unwrap)) { + func_decl *w, *u; + + if (!m_wraps.find(s, w) || !m_unwraps.find(s, u)) { SASSERT(!m_wraps.contains(s)); + SASSERT(!m_unwraps.contains(s)); ast_manager & m = get_manager(); + context & ctx = get_context(); sort * bv_srt = 0; if (m_converter.is_rm(s)) - bv_srt = m_converter.bu().mk_sort(3); + bv_srt = m_bv_util.mk_sort(3); else { - SASSERT(m_converter.is_float(s)); - unsigned ebits = m_converter.fu().get_ebits(s); - unsigned sbits = m_converter.fu().get_sbits(s); - bv_srt = m_converter.bu().mk_sort(ebits + sbits); + SASSERT(m_converter.is_float(s)); + unsigned ebits = m_float_util.get_ebits(s); + unsigned sbits = m_float_util.get_sbits(s); + bv_srt = m_bv_util.mk_sort(ebits + sbits); } - - wrap = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &s, bv_srt); - unwrap = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); - m_wraps.insert(s, wrap); - m_unwraps.insert(s, unwrap); - get_context().push_trail(insert_obj_map(m_wraps, s)); - get_context().push_trail(insert_obj_map(m_unwraps, s)); + + w = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &s, bv_srt); + u = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); + m_wraps.insert(s, w); + m_unwraps.insert(s, u); + m.inc_ref(w); + m.inc_ref(u); } + + wrap = w; + unwrap = u; } expr_ref theory_fpa::convert_atom(expr * e) { @@ -274,52 +251,91 @@ namespace smt { expr_ref res(m); proof_ref pr(m); m_rw(e, res); + m_th_rw(res, res); - TRACE("t_fpa", tout << "converted atom:" << std::endl; - tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); + TRACE("t_fpa_detail", tout << "converted atom:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + + SASSERT(is_app(res)); + SASSERT(m.is_bool(res)); return res; } expr_ref theory_fpa::convert_term(expr * e) { ast_manager & m = get_manager(); + context & ctx = get_context(); expr_ref res(m); proof_ref pr(m); m_rw(e, res); SASSERT(is_app(res)); - if (m_converter.fu().is_rm(e)) { - SASSERT(is_sort_of(m.get_sort(res), m_converter.bu().get_family_id(), BV_SORT)); - SASSERT(m_converter.bu().get_bv_size(res) == 3); + if (m_float_util.is_rm(e)) { + SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(m_bv_util.get_bv_size(res) == 3); + ctx.internalize(res, false); } else { SASSERT(to_app(res)->get_family_id() == get_family_id()); decl_kind k = to_app(res)->get_decl_kind(); if (k == OP_FLOAT_TO_FP) { SASSERT(to_app(res)->get_num_args() == 3); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(0)), m_converter.bu().get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(1)), m_converter.bu().get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(2)), m_converter.bu().get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(2)), m_bv_util.get_family_id(), BV_SORT)); expr *sgn, *sig, *exp; expr_ref s_sgn(m), s_sig(m), s_exp(m); m_converter.split_triple(res, sgn, sig, exp); m_th_rw(sgn, s_sgn); m_th_rw(sig, s_sig); - m_th_rw(exp, s_exp); - + m_th_rw(exp, s_exp); + m_converter.mk_triple(s_sgn, s_sig, s_exp, res); } else { SASSERT(is_sort_of(m.get_sort(e), get_family_id(), ROUNDING_MODE_SORT)); - SASSERT(is_sort_of(m.get_sort(res), m_converter.bu().get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); } } - TRACE("t_fpa", tout << "converted term:" << std::endl; - tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); + TRACE("t_fpa_detail", tout << "converted term:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + return res; + } + + expr_ref theory_fpa::convert(expr * e) + { + ast_manager & m = get_manager(); + context & ctx = get_context(); + expr_ref res(m); + + if (m_conversions.contains(e)) { + res = m_conversions.find(e); + TRACE("t_fpa_detail", tout << "cached:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + return res; + } + else { + if (m.is_bool(e)) + res = convert_atom(e); + else if (m_float_util.is_float(e) || m_float_util.is_rm(e)) + res = convert_term(e); + else + UNREACHABLE(); + + TRACE("t_fpa_detail", tout << "caching:" << std::endl; + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); + + m_conversions.insert(e, res); + m.inc_ref(res); + m_trail_stack.push(fpa_conv_trail(m, m_conversions, e)); + } + return res; } @@ -340,14 +356,14 @@ namespace smt { res = m.mk_and(res, t); } m_converter.m_extra_assertions.reset(); - - TRACE("t_fpa", if (!m.is_true(res)) tout << "side condition: " << mk_ismt2_pp(res, m) << "\n";); + + CTRACE("t_fpa", !m.is_true(res), tout << "side condition: " << mk_ismt2_pp(res, m) << "\n";); return res; } - void theory_fpa::assert_cnstr(expr * e) { + void theory_fpa::assert_cnstr(expr * e) { + TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); if (get_manager().is_true(e)) return; - TRACE("t_fpa", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); context& ctx = get_context(); ctx.internalize(e, false); literal lit(ctx.get_literal(e)); @@ -359,7 +375,6 @@ namespace smt { context & ctx = get_context(); theory_var v = mk_var(n); ctx.attach_th_var(n, this, v); - m_tvars.push_back(v); TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(n->get_owner(), get_manager()) << " := " << v << "\n";); } @@ -381,7 +396,9 @@ namespace smt { ctx.set_var_theory(l.var(), get_id()); expr_ref bv_atom(m); - bv_atom = convert_atom(atom); + bv_atom = convert(atom); + TRACE("t_fpa_detail", tout << "converted: " << mk_ismt2_pp(bv_atom, get_manager()) << "\n";); + SASSERT(bv_atom.get()->get_kind() == AST_APP); bv_atom = m.mk_and(bv_atom, mk_side_conditions()); expr_ref atom_iff(m); @@ -390,13 +407,13 @@ namespace smt { } bool theory_fpa::internalize_term(app * term) { - TRACE("t_fpa_detail", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); - SASSERT(term->get_family_id() == get_family_id()); - SASSERT(!get_context().e_internalized(term)); - ast_manager & m = get_manager(); context & ctx = get_context(); + TRACE("t_fpa_detail", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); + SASSERT(term->get_family_id() == get_family_id()); + SASSERT(!ctx.e_internalized(term)); + unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); @@ -407,8 +424,7 @@ namespace smt { if (is_attached_to_var(e)) return false; - attach_new_th_var(e); - TRACE("t_fpa", tout << "internalized? " << (ctx.e_internalized(term)?"yes":"no") << std::endl;); + attach_new_th_var(e); return true; } @@ -417,22 +433,25 @@ namespace smt { SASSERT(n->get_owner()->get_family_id() == get_family_id() || n->get_owner()->get_family_id() == null_theory_id); SASSERT(s->get_family_id() == get_family_id()); - ast_manager & m = get_manager(); + ast_manager & m = get_manager(); if (!is_attached_to_var(n)) attach_new_th_var(n); - app * owner = n->get_owner(); - sort * owner_sort = m.get_sort(owner); - if (m_converter.is_rm(owner_sort)) { - bv_util & bu = m_converter.bu(); - func_decl *wrap, *unwrap; + app_ref owner(m); + sort_ref owner_sort(m); + owner = n->get_owner(); + owner_sort = m.get_sort(owner); + + if (m_float_util.is_rm(owner_sort)) { + func_decl_ref wrap(m), unwrap(m); get_wrap(owner_sort, wrap, unwrap); if (owner->get_decl() != unwrap) - { - expr_ref converted(m), t(m); - m_rw(owner, converted); - t = bu.mk_ule(converted, bu.mk_numeral(4, 3)); + { + expr_ref converted(m), t(m), limit(m); + converted = convert(owner); + limit = m_bv_util.mk_numeral(4, 3); + t = m_bv_util.mk_ule(converted, limit); assert_cnstr(t); } } @@ -446,41 +465,45 @@ namespace smt { mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl; ); context & ctx = get_context(); - float_util & fu = m_converter.fu(); - bv_util & bu = m_converter.bu(); + float_util & fu = m_float_util; + bv_util & bu = m_bv_util; mpf_manager & mpfm = fu.fm(); app * xe = get_enode(x)->get_owner(); - app * ye = get_enode(y)->get_owner(); + app * ye = get_enode(y)->get_owner(); + + if (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye)) + { + SASSERT(xe->get_decl()->get_family_id() == get_family_id()); + return; + } + + expr_ref xc(m), yc(m); + xc = convert(xe); + yc = convert(ye); + + expr_ref c(m); if (fu.is_float(xe) && fu.is_float(ye)) { - expr_ref xc(m), yc(m); - xc = convert_term(xe); - yc = convert_term(ye); - expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); expr *y_sgn, *y_sig, *y_exp; m_converter.split_triple(yc, y_sgn, y_sig, y_exp); - expr_ref c(m); c = m.mk_and(m.mk_eq(x_sgn, y_sgn), m.mk_eq(x_sig, y_sig), - m.mk_eq(x_exp, y_exp)); - assert_cnstr(c); - assert_cnstr(mk_side_conditions()); + m.mk_eq(x_exp, y_exp)); } - else if (fu.is_rm(xe) && fu.is_rm(ye)) { - expr_ref xc(m), yc(m); - xc = convert_term(xe); - yc = convert_term(ye); - expr_ref c(m); + else if (fu.is_rm(xe) && fu.is_rm(ye)) c = m.mk_eq(xc, yc); - assert_cnstr(c); - assert_cnstr(mk_side_conditions()); - } - + else + UNREACHABLE(); + + // assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); + return; } @@ -492,57 +515,55 @@ namespace smt { mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); context & ctx = get_context(); - float_util & fu = m_converter.fu(); - bv_util & bu = m_converter.bu(); - mpf_manager & mpfm = fu.fm(); + mpf_manager & mpfm = m_float_util.fm(); app * xe = get_enode(x)->get_owner(); app * ye = get_enode(y)->get_owner(); - if (fu.is_float(xe) && fu.is_float(ye)) + if (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye)) { - expr_ref xc(m), yc(m); - xc = convert_term(xe); - yc = convert_term(ye); + SASSERT(xe->get_decl()->get_family_id() == get_family_id()); + return; + } + expr_ref xc(m), yc(m); + xc = convert(xe); + yc = convert(ye); + + expr_ref c(m); + + if (m_float_util.is_float(xe) && m_float_util.is_float(ye)) + { expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); expr *y_sgn, *y_sig, *y_exp; m_converter.split_triple(yc, y_sgn, y_sig, y_exp); - - expr_ref c(m); + c = m.mk_or(m.mk_not(m.mk_eq(x_sgn, y_sgn)), m.mk_not(m.mk_eq(x_sig, y_sig)), m.mk_not(m.mk_eq(x_exp, y_exp))); - assert_cnstr(c); - assert_cnstr(mk_side_conditions()); } - else if (fu.is_rm(xe) && fu.is_rm(ye)) { - expr_ref xc(m), yc(m); - xc = convert_term(xe); - yc = convert_term(ye); - expr_ref c(m); + else if (m_float_util.is_rm(xe) && m_float_util.is_rm(ye)) c = m.mk_not(m.mk_eq(xc, yc)); - assert_cnstr(c); - assert_cnstr(mk_side_conditions()); - } + else + UNREACHABLE(); + + // assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); + assert_cnstr(c); + assert_cnstr(mk_side_conditions()); return; } void theory_fpa::push_scope_eh() { theory::push_scope_eh(); - m_trail_stack.push_scope(); + m_trail_stack.push_scope(); } - void theory_fpa::pop_scope_eh(unsigned num_scopes) { - TRACE("t_fpa", tout << num_scopes << "\n";); + void theory_fpa::pop_scope_eh(unsigned num_scopes) { m_trail_stack.pop_scope(num_scopes); - unsigned num_old_vars = get_old_num_vars(num_scopes); - for (unsigned i = num_old_vars; i < get_num_vars(); i++) { - // m_trans_map.erase(get_enode(m_tvars[i])->get_owner()); - } - m_tvars.shrink(num_old_vars); + TRACE("t_fpa", tout << "pop " << num_scopes << "; now " << m_trail_stack.get_num_scopes() << "\n";); + // unsigned num_old_vars = get_old_num_vars(num_scopes); theory::pop_scope_eh(num_scopes); } @@ -554,57 +575,68 @@ namespace smt { TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << "):\n" << mk_ismt2_pp(e, m) << "\n";); expr_ref converted(m); - m_rw(e, converted); + converted = convert(e); converted = m.mk_and(converted, mk_side_conditions()); if (!is_true) converted = m.mk_not(converted); assert_cnstr(converted); } void theory_fpa::relevant_eh(app * n) { - TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, get_manager()) << "\n";); - - NOT_IMPLEMENTED_YET(); - ast_manager & m = get_manager(); + TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, m) << "\n";); - if (m.is_bool(n)) - return; + mpf_manager & mpfm = m_float_util.fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - float_util & fu = m_converter.fu(); - bv_util & bu = m_converter.bu(); - mpf_manager & mpfm = fu.fm(); + if (m_float_util.is_float(n) || m_float_util.is_rm(n)) { + sort * s = m.get_sort(n); + func_decl_ref wrap(m), unwrap(m); + get_wrap(s, wrap, unwrap); - if (bu.is_bv(n)) - return; - - sort * s = m.get_sort(n); - func_decl *wrap, *unwrap; - get_wrap(s, wrap, unwrap); - - if (n->get_decl() != unwrap) { - expr * wrapped = m.mk_app(wrap, n); - mpf_rounding_mode rm; - scoped_mpf val(mpfm); - if (fu.is_rm_value(n, rm)) - assert_cnstr(m.mk_eq(wrapped, bu.mk_numeral(rm, 3))); - else if (fu.is_value(n, val)) { - unsigned sz = val.get().get_ebits() + val.get().get_sbits(); - scoped_mpq q(fu.fm().mpq_manager()); - mpfm.to_rational(val, q); - assert_cnstr(m.mk_eq(wrapped, bu.mk_numeral(rational(q), sz))); + if (n->get_decl() != unwrap) { + expr_ref wrapped(m), c(m); + wrapped = m.mk_app(wrap, n); + mpf_rounding_mode rm; + scoped_mpf val(mpfm); + if (m_float_util.is_rm_value(n, rm)) { + c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3)); + c = m.mk_and(c, mk_side_conditions()); + assert_cnstr(c); + } + else if (m_float_util.is_value(n, val)) { + unsigned sz = val.get().get_ebits() + val.get().get_sbits(); + expr_ref bv_val_e(m); + bv_val_e = convert(n); + SASSERT(is_app(bv_val_e)); + SASSERT(to_app(bv_val_e)->get_num_args() == 3); + app_ref bv_val_a(to_app(bv_val_e.get()), m); + c = m.mk_eq(wrapped, m_bv_util.mk_concat( + m_bv_util.mk_concat(bv_val_a->get_arg(0), bv_val_a->get_arg(1)), + bv_val_a->get_arg(2))); + c = m.mk_and(c, mk_side_conditions()); + assert_cnstr(c); + } + else { + c = m.mk_eq(m.mk_app(unwrap, wrapped), n); + c = m.mk_and(c, mk_side_conditions()); + assert_cnstr(c); + } } - else - assert_cnstr(m.mk_eq(m.mk_app(unwrap, wrapped), n)); } } void theory_fpa::reset_eh() { - TRACE("t_fpa", tout << "reset_eh for: " << "\n";); + TRACE("t_fpa", tout << "reset_eh\n";); pop_scope_eh(m_trail_stack.get_num_scopes()); + m_converter.reset(); m_rw.reset(); - m_bool_var2atom.reset(); - m_temporaries.reset(); - m_tvars.reset(); + m_th_rw.reset(); + m_trail_stack.pop_scope(m_trail_stack.get_num_scopes()); + if (m_factory) dealloc(m_factory); m_factory = 0; + ast_manager & m = get_manager(); + dec_ref_map_values(m, m_conversions); + dec_ref_map_values(m, m_wraps); + dec_ref_map_values(m, m_unwraps); theory::reset_eh(); } @@ -615,28 +647,54 @@ namespace smt { TRACE("t_fpa", display(tout);); } + void theory_fpa::add_value_dep(fpa_value_proc * vp, expr * e) { + SASSERT(m_bv_util.is_bv(e)); + ast_manager & m = get_manager(); + context & ctx = get_context(); + if (ctx.e_internalized(e)) + vp->add_dependency(ctx.get_enode(e)); + else { + expr_ref n(m); + n = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(e)); + if (!ctx.e_internalized(n)) + ctx.internalize(n, false); + vp->add_dependency(ctx.get_enode(n)); + } + } + model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { - TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); + TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); ast_manager & m = get_manager(); - float_util & fu = m_converter.fu(); + context & ctx = get_context(); + app * owner = n->get_owner(); - expr * owner = n->get_owner(); - sort * o_srt = m.get_sort(owner); + app_ref c_a(m); + c_a = to_app(convert(owner)); + SASSERT(ctx.e_internalized(owner)); - mpf_rounding_mode rm; + TRACE("t_fpa", tout << "converted = " << mk_ismt2_pp(c_a, get_manager()) << "\n";); - if (fu.is_rm_value(n->get_owner(), rm)) - return alloc(expr_wrapper_proc, n->get_owner()); - else if (fu.is_value(n->get_owner())) - return alloc(expr_wrapper_proc, n->get_owner()); - else if (fu.is_rm(owner)) - return alloc(fpa_rm_value_proc, this, app_ref(to_app(owner), m)); - else if (fu.is_float(owner)) - return alloc(fpa_value_proc, this, app_ref(to_app(owner), m)); - - UNREACHABLE(); - return 0; + model_value_proc * res = 0; + + if (m_float_util.is_rm(owner)) { + fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); + add_value_dep(vp, c_a); + res = vp; + } + else if (m_float_util.is_float(owner)) { + fpa_value_proc * vp = alloc(fpa_value_proc, this); + expr_ref bv_sgn(m), bv_sig(m), bv_exp(m); + m_converter.split_triple(c_a, bv_sgn, bv_sig, bv_exp); + add_value_dep(vp, bv_sgn); + add_value_dep(vp, bv_sig); + add_value_dep(vp, bv_exp); + res = vp; + } + else + UNREACHABLE(); + + return res; } void theory_fpa::finalize_model(model_generator & mg) {} @@ -649,8 +707,10 @@ namespace smt { out << "theory variables:" << std::endl; ptr_vector::const_iterator it = ctx.begin_enodes(); ptr_vector::const_iterator end = ctx.end_enodes(); - for (; it != end; it++) - out << (*it)->get_th_var(get_family_id()) << " -> " << - mk_ismt2_pp((*it)->get_owner(), m) << std::endl; + for (; it != end; it++) { + theory_var v = (*it)->get_th_var(get_family_id()); + if (v != -1) out << v << " -> " << + mk_ismt2_pp((*it)->get_owner(), m) << std::endl; + } } }; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 0c472be33..bd2ea29f8 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -29,39 +29,10 @@ Revision History: namespace smt { - class fpa_factory : public value_factory { - float_util m_util; - - virtual app * mk_value_core(mpf const & val, sort * s) { - SASSERT(m_util.get_ebits(s) == val.get_ebits()); - SASSERT(m_util.get_sbits(s) == val.get_sbits()); - return m_util.mk_value(val); - } - - public: - fpa_factory(ast_manager & m, family_id fid) : - value_factory(m, fid), - m_util(m) { - } - - virtual ~fpa_factory() {} - - virtual expr * get_some_value(sort * s) { NOT_IMPLEMENTED_YET(); } - virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { NOT_IMPLEMENTED_YET(); } - virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } - virtual void register_value(expr * n) { /* Ignore */ } - - app * mk_value(mpf const & x) { - return m_util.mk_value(x); - } - }; + class fpa_factory; class theory_fpa : public theory { - class th_trail_stack : public trail_stack { - public: - th_trail_stack(theory_fpa & th) : trail_stack(th) {} - virtual ~th_trail_stack() {} - }; + typedef trail_stack th_trail_stack; class fpa2bv_converter_wrapped : public fpa2bv_converter { public: @@ -76,11 +47,13 @@ namespace smt { class fpa_value_proc : public model_value_proc { protected: - theory_fpa & m_th; - app_ref m_a; + theory_fpa & m_th; + float_util & m_fu; + bv_util & m_bu; svector m_dependencies; public: - fpa_value_proc(theory_fpa * th, app_ref & a) : m_th(*th), m_a(a) {} + fpa_value_proc(theory_fpa * th) : + m_th(*th),m_fu(th->m_float_util),m_bu(th->m_bv_util) {} void add_dependency(enode * n) { m_dependencies.push_back(model_value_dependency(n)); } virtual ~fpa_value_proc() {} virtual void get_dependencies(buffer & result) { @@ -89,50 +62,27 @@ namespace smt { virtual app * mk_value(model_generator & mg, ptr_vector & values); }; - class fpa_rm_value_proc : public fpa_value_proc { - float_util & m_fu; - bv_util & m_bu; + class fpa_rm_value_proc : public fpa_value_proc { public: - fpa_rm_value_proc(theory_fpa * th, app_ref & a) : - fpa_value_proc(th, a), - m_fu(th->m_converter.fu()), - m_bu(th->m_converter.bu()) {} + fpa_rm_value_proc(theory_fpa * th) : + fpa_value_proc(th) {} void add_dependency(enode * n) { fpa_value_proc::add_dependency(n); } virtual ~fpa_rm_value_proc() {} virtual app * mk_value(model_generator & mg, ptr_vector & values); }; - public: - class atom { - public: - virtual ~atom() {} - }; - - struct pred_atom : public atom { - literal m_var; - literal m_def; - pred_atom(literal v, literal d) : m_var(v), m_def(d) {} - virtual ~pred_atom() {} - }; - - typedef ptr_vector bool_var2atom; - void insert_bv2a(bool_var bv, pred_atom * a) { m_bool_var2atom.setx(bv, a, 0); } - void erase_bv2a(bool_var bv) { m_bool_var2atom[bv] = 0; } - pred_atom * get_bv2a(bool_var bv) const { return m_bool_var2atom.get(bv, 0); } - region & get_region() { return m_trail_stack.get_region(); } - protected: fpa2bv_converter_wrapped m_converter; fpa2bv_rewriter m_rw; th_rewriter m_th_rw; th_trail_stack m_trail_stack; - bool_var2atom m_bool_var2atom; - enode_vector m_temporaries; - vector m_tvars; fpa_factory * m_factory; + float_util & m_float_util; + bv_util & m_bv_util; + arith_util & m_arith_util; obj_map m_wraps; obj_map m_unwraps; - float_decl_plugin m_flt_plugin; + obj_map m_conversions; virtual final_check_status final_check_eh() { return FC_DONE; } virtual bool internalize_atom(app * atom, bool gate_ctx); @@ -161,14 +111,16 @@ namespace smt { protected: expr_ref mk_side_conditions(); + expr_ref convert(expr * e); expr_ref convert_atom(expr * e); expr_ref convert_term(expr * e); - void get_wrap(sort * s, func_decl *& wrap, func_decl *& unwrap); + void get_wrap(sort * s, func_decl_ref & wrap, func_decl_ref & unwrap); void add_trail(ast * a); void mk_bv_eq(expr * x, expr * y); void attach_new_th_var(enode * n); void assert_cnstr(expr * e); + void add_value_dep(fpa_value_proc * vp, expr * e); }; }; From 1aae53f48c9d82fa3173f9a33054e8d7b5896830 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 15:26:41 +0000 Subject: [PATCH 108/646] FPA: comment fixes Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 846d6ddb7..bfc038cf7 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -846,11 +846,11 @@ bool float_decl_plugin::is_unique_value(app* e) const { case OP_FLOAT_RM_TOWARD_ZERO: return true; case OP_FLOAT_PLUS_INF: /* No; +oo == fp(#b0 #b11 #b00) */ - case OP_FLOAT_MINUS_INF: /* Nol -oo == fp #b1 #b11 #b00) */ + case OP_FLOAT_MINUS_INF: /* No; -oo == fp #b1 #b11 #b00) */ case OP_FLOAT_PLUS_ZERO: /* No; +zero == fp #b0 #b00 #b000) */ case OP_FLOAT_MINUS_ZERO: /* No; -zero == fp #b1 #b00 #b000) */ case OP_FLOAT_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */ - case OP_FLOAT_VALUE: /* above */ + case OP_FLOAT_VALUE: /* see NaN */ return false; case OP_FLOAT_FP: return m_manager->is_unique_value(e->get_arg(0)) && From 4d1f71775d1144fb7a2af4f548a8e1c9bc74cd03 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 15:26:52 +0000 Subject: [PATCH 109/646] FPA: added to_fp_unsigned Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 140 +++++++++++++++++++++++++++++-- src/ast/fpa/fpa2bv_rewriter.h | 3 +- 2 files changed, 134 insertions(+), 9 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 0de267d2f..4d2826681 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2171,11 +2171,6 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const unsigned bv_sz = m_bv_util.get_bv_size(x); SASSERT(m_bv_util.get_bv_size(rm) == 3); - //if (bv_sz < f_sz) { - // x = m_bv_util.mk_zero_extend(f_sz - bv_sz, x); - // bv_sz = f_sz; - //} - expr_ref bv0_1(m), bv1_1(m), bv0_sz(m), bv1_sz(m); bv0_1 = m_bv_util.mk_numeral(0, 1); bv1_1 = m_bv_util.mk_numeral(1, 1); @@ -2245,12 +2240,14 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const unsigned exp_sz = ebits + 2; // (+2 for rounder) exp_2 = m_bv_util.mk_extract(exp_sz - 1, 0, s_exp); // the remaining bits are 0 if ebits is large enough. - exp_too_large = m.mk_false(); // This is always in range. + exp_too_large = m.mk_false(); // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits. // exp < bv_sz (+sign bit which is [0]) unsigned exp_worst_case_sz = (unsigned)((log((double)bv_sz) / log((double)2)) + 1.0); + TRACE("fpa2bv_to_fp_signed", tout << "exp worst case sz: " << exp_worst_case_sz << std::endl;); + if (exp_sz < exp_worst_case_sz) { // exp_sz < exp_worst_case_sz and exp >= 0. // Take the maximum legal exponent; this @@ -2266,7 +2263,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const sig_4 = m.mk_ite(exp_too_large, m_bv_util.mk_numeral(0, sig_sz), sig_4); exp_2 = m.mk_ite(exp_too_large, max_exp, exp_2); } - dbg_decouple("fpa2bv_to_fp_signed_exp_too_large", exp_too_large); + dbg_decouple("fpa2bv_to_fp_signed_exp_too_large", exp_too_large); expr_ref sgn(m), sig(m), exp(m); sgn = is_neg_bit; @@ -2290,7 +2287,134 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con TRACE("fpa2bv_to_fp_unsigned", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); - NOT_IMPLEMENTED_YET(); + // This is a conversion from unsigned bitvector to float: + // ((_ to_fp_unsigned eb sb) RoundingMode(_ BitVec m) (_ FloatingPoint eb sb)) + // Semantics: + // Let b in[[(_ BitVec m)]] and let n be the unsigned integer represented by b. + // [[(_ to_fp_unsigned eb sb)]](r, x) = +infinity if n is too large to be + // represented as a finite number of[[(_ FloatingPoint eb sb)]]; + // [[(_ to_fp_unsigned eb sb)]](r, x) = y otherwise, where y is the finite number + // such that[[fp.to_real]](y) is closest to n according to rounding mode r. + + SASSERT(num == 2); + SASSERT(m_util.is_float(f->get_range())); + SASSERT(m_bv_util.is_bv(args[0])); + SASSERT(m_bv_util.is_bv(args[1])); + + expr_ref rm(m), x(m); + rm = args[0]; + x = args[1]; + + dbg_decouple("fpa2bv_to_fp_unsigned_x", x); + + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + unsigned f_sz = sbits + ebits; + unsigned bv_sz = m_bv_util.get_bv_size(x); + SASSERT(m_bv_util.get_bv_size(rm) == 3); + + expr_ref bv0_1(m), bv1_1(m), bv0_sz(m), bv1_sz(m); + bv0_1 = m_bv_util.mk_numeral(0, 1); + bv1_1 = m_bv_util.mk_numeral(1, 1); + bv0_sz = m_bv_util.mk_numeral(0, bv_sz); + bv1_sz = m_bv_util.mk_numeral(1, bv_sz); + + expr_ref is_zero(m), nzero(m), pzero(m), ninf(m), pinf(m); + is_zero = m.mk_eq(x, bv0_sz); + mk_nzero(f, nzero); + mk_pzero(f, pzero); + mk_ninf(f, ninf); + mk_pinf(f, pinf); + + // Special case: x == 0 -> p/n zero + expr_ref c1(m), v1(m), rm_is_to_neg(m); + c1 = is_zero; + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); + mk_ite(rm_is_to_neg, nzero, pzero, v1); + + // Special case: x != 0 + expr_ref exp_too_large(m), sig_4(m), exp_2(m); + // x is [bv_sz-1] . [bv_sz-2 ... 0] * 2^(bv_sz-1) + // bv_sz-1 is the "1.0" bit for the rounder. + + expr_ref lz(m), e_bv_sz(m), e_rest_sz(m); + mk_leading_zeros(x, bv_sz, lz); + e_bv_sz = m_bv_util.mk_numeral(bv_sz, bv_sz); + e_rest_sz = m_bv_util.mk_bv_sub(e_bv_sz, lz); + SASSERT(m_bv_util.get_bv_size(lz) == m_bv_util.get_bv_size(e_bv_sz)); + dbg_decouple("fpa2bv_to_fp_unsigned_lz", lz); + expr_ref shifted_sig(m); + shifted_sig = m_bv_util.mk_bv_shl(x, lz); + + expr_ref sticky(m); + // shifted_sig is [bv_sz-1] . [bv_sz-2 ... 0] * 2^(bv_sz-1) * 2^(-lz) + unsigned sig_sz = sbits + 4; // we want extra rounding bits. + if (sig_sz <= bv_sz) { + expr_ref sig_rest(m); + sig_4 = m_bv_util.mk_extract(bv_sz - 1, bv_sz - sig_sz + 1, shifted_sig); // one short + sig_rest = m_bv_util.mk_extract(bv_sz - sig_sz, 0, shifted_sig); + sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest); + sig_4 = m_bv_util.mk_concat(sig_4, sticky); + } + else { + unsigned extra_bits = sig_sz - bv_sz; + expr_ref extra_zeros(m); + extra_zeros = m_bv_util.mk_numeral(0, extra_bits); + sig_4 = m_bv_util.mk_concat(shifted_sig, extra_zeros); + lz = m_bv_util.mk_bv_add(m_bv_util.mk_concat(extra_zeros, lz), + m_bv_util.mk_numeral(extra_bits, sig_sz)); + bv_sz = bv_sz + extra_bits; + SASSERT(is_well_sorted(m, lz)); + } + SASSERT(m_bv_util.get_bv_size(sig_4) == sig_sz); + + expr_ref s_exp(m), exp_rest(m); + s_exp = m_bv_util.mk_bv_sub(m_bv_util.mk_numeral(bv_sz - 2, bv_sz), lz); + // s_exp = (bv_sz-2) + (-lz) signed + SASSERT(m_bv_util.get_bv_size(s_exp) == bv_sz); + + unsigned exp_sz = ebits + 2; // (+2 for rounder) + exp_2 = m_bv_util.mk_extract(exp_sz - 1, 0, s_exp); + // the remaining bits are 0 if ebits is large enough. + exp_too_large = m.mk_false(); // This is always in range. + + // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits. + // exp < bv_sz (+sign bit which is [0]) + unsigned exp_worst_case_sz = (unsigned)((log((double)bv_sz) / log((double)2)) + 1.0); + + if (exp_sz < exp_worst_case_sz) { + // exp_sz < exp_worst_case_sz and exp >= 0. + // Take the maximum legal exponent; this + // allows us to keep the most precision. + expr_ref max_exp(m), max_exp_bvsz(m); + mk_max_exp(exp_sz, max_exp); + max_exp_bvsz = m_bv_util.mk_zero_extend(bv_sz - exp_sz, max_exp); + + exp_too_large = m_bv_util.mk_ule(m_bv_util.mk_bv_add( + max_exp_bvsz, + m_bv_util.mk_numeral(1, bv_sz)), + s_exp); + sig_4 = m.mk_ite(exp_too_large, m_bv_util.mk_numeral(0, sig_sz), sig_4); + exp_2 = m.mk_ite(exp_too_large, max_exp, exp_2); + } + dbg_decouple("fpa2bv_to_fp_unsigned_exp_too_large", exp_too_large); + + expr_ref sgn(m), sig(m), exp(m); + sgn = bv0_1; + sig = sig_4; + exp = exp_2; + + dbg_decouple("fpa2bv_to_fp_unsigned_sgn", sgn); + dbg_decouple("fpa2bv_to_fp_unsigned_sig", sig); + dbg_decouple("fpa2bv_to_fp_unsigned_exp", exp); + + SASSERT(m_bv_util.get_bv_size(sig) == sbits + 4); + SASSERT(m_bv_util.get_bv_size(exp) == ebits + 2); + + expr_ref v2(m); + round(f->get_range(), rm, sgn, sig, exp, v2); + + mk_ite(c1, v1, v2, result); } void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 17ee924ad..42fd7a7fe 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -144,7 +144,8 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; From 12aaa0610b5dc064e60f783a00a8af2525e91b1a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 15:27:40 +0000 Subject: [PATCH 110/646] FPA: added get_some_value/s for FP models Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index ec22e3ebb..f05bca4a1 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -41,8 +41,23 @@ namespace smt { virtual ~fpa_factory() {} - virtual expr * get_some_value(sort * s) { NOT_IMPLEMENTED_YET(); } - virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { NOT_IMPLEMENTED_YET(); } + virtual expr * get_some_value(sort * s) { + mpf_manager & mpfm = m_util.fm(); + scoped_mpf q(mpfm); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); + return m_util.mk_value(q); + } + + virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { + mpf_manager & mpfm = m_util.fm(); + scoped_mpf q(mpfm); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); + v1 = m_util.mk_value(q); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 1); + v2 = m_util.mk_value(q); + return true; + } + virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } virtual void register_value(expr * n) { /* Ignore */ } From 96c8bd7e91ac9952612e38e17b150f52ba174f76 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 17:57:21 +0000 Subject: [PATCH 111/646] MPF conversion bugfix Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index ac2eb3096..405f34c9d 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -218,39 +218,24 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode o.exponent--; } - m_mpz_manager.set(o.significand, 0); - // o.exponent += sbits ; - + m_mpz_manager.set(o.significand, 0); SASSERT(m_mpq_manager.lt(v, mpq(2))); SASSERT(m_mpq_manager.ge(v, mpq(1))); // 1.0 <= v < 2.0 (* 2^o.exponent) - // (and v != 0.0) + // (and v != 0.0) for (unsigned i = 0; i < sbits + 3 ; i++) { - m_mpz_manager.mul(o.significand, mpz(2), o.significand); - if (m_mpq_manager.ge(v, mpq(1))) - m_mpz_manager.add(o.significand, mpz(1), o.significand); - m_mpq_manager.sub(v, mpq(1), v); // v := v - 1.0 + m_mpz_manager.mul2k(o.significand, 1); + if (m_mpq_manager.ge(v, mpq(1))) { + m_mpz_manager.inc(o.significand); + m_mpq_manager.dec(v); // v := v - 1.0 + } m_mpq_manager.mul(mpq(2), v, v); // v := 2.0 * v - } - - // Sticky - // m_mpz_manager.mul(o.significand, mpz(2), o.significand); - /*if (!m_mpq_manager.is_zero(v)) - m_mpz_manager.add(o.significand, mpz(1), o.significand);*/ + } - // bias? - // o.exponent += m_mpz_manager.get_int64(m_powers2.m1(ebits - 1, false)); - - // mpq pow; - // m_mpq_manager.power(mpq(2), sbits + 3, pow); - // m_mpq_manager.div(o.significand, pow, o.significand); - // SASSERT(m_mpz_manager.ge(o.significand, mpq(1.0))); - // SASSERT(m_mpz_manager.lt(o.significand, mpq(2.0))); - - TRACE("mpf_dbg", tout << "sig=" << m_mpz_manager.to_string(o.significand) << " exp=" << o.exponent << - " sticky=" << (!m_mpq_manager.is_zero(v)) << std::endl;); + TRACE("mpf_dbg", tout << "rnd sig=" << m_mpz_manager.to_string(o.significand) << + " exp=" << o.exponent << std::endl;); round(rm, o); } From 621be0f47f37588c27d546916a9a3afb448171a4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 18:01:18 +0000 Subject: [PATCH 112/646] FPA: Added fp.to_ubv Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 8 +-- src/ast/fpa/fpa2bv_converter.cpp | 112 +++++++++++++++++++++++++++---- 2 files changed, 103 insertions(+), 17 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index bfc038cf7..a861865f5 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -562,9 +562,9 @@ func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, p m_manager->raise_exception("invalid number of arguments to fp.to_ubv"); if (num_parameters != 1) m_manager->raise_exception("invalid number of parameters to fp.to_ubv"); - if (parameters[0].is_int()) + if (!parameters[0].is_int()) m_manager->raise_exception("invalid parameter type; fp.to_ubv expects an int parameter"); - if (is_rm_sort(domain[0])) + if (!is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); @@ -573,7 +573,7 @@ func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, p symbol name("fp.to_ubv"); sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters); - return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k)); + return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters)); } func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -594,7 +594,7 @@ func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, p symbol name("fp.to_sbv"); sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters); - return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k)); + return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters)); } func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 4d2826681..88e738041 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1865,7 +1865,6 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args m_bv_util.get_bv_size(args[0]) == 3 && m_bv_util.is_bv(args[1])) { - mk_to_fp_signed(f, num, args, result); } else if (num == 3 && @@ -2457,27 +2456,114 @@ void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, e } void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - SASSERT(num == 2); + TRACE("fpa2bv_to_ubv", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); + SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - - //unsigned ebits = m_util.get_ebits(f->get_range()); - //unsigned sbits = m_util.get_sbits(f->get_range()); - //int width = f->get_parameter(0).get_int(); + SASSERT(num == 2); + SASSERT(m_bv_util.get_bv_size(args[0]) == 3); + SASSERT(m_util.is_float(args[1])); - //expr * rm = args[0]; - //expr * x = args[1]; - - //expr * sgn, *s, *e; - //split_triple(x, sgn, s, e); + expr * rm = args[0]; + expr * x = args[1]; + sort * xs = m.get_sort(x); + sort * bv_srt = f->get_range(); - NOT_IMPLEMENTED_YET(); + dbg_decouple("fpa2bv_to_ubv_x", expr_ref(x, m)); + + unsigned ebits = m_util.get_ebits(xs); + unsigned sbits = m_util.get_sbits(xs); + unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); + + expr_ref bv0(m), bv1(m); + bv0 = m_bv_util.mk_numeral(0, 1); + bv1 = m_bv_util.mk_numeral(1, 1); + + expr_ref x_is_nan(m), x_is_inf(m), x_is_zero(m), x_is_neg(m), x_is_nzero(m); + mk_is_nan(x, x_is_nan); + mk_is_inf(x, x_is_inf); + mk_is_zero(x, x_is_zero); + mk_is_neg(x, x_is_neg); + mk_is_nzero(x, x_is_nzero); + + // NaN, Inf, or negative (except -0) -> undefined + expr_ref c1(m), v1(m); + c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero))); + v1 = mk_fresh_const(0, bv_sz); + dbg_decouple("fpa2bv_to_ubv_c1", c1); + + // +-Zero -> 0 + expr_ref c2(m), v2(m); + c2 = x_is_zero; + v2 = m_bv_util.mk_numeral(rational(0), bv_srt); + dbg_decouple("fpa2bv_to_ubv_c2", c2); + + // Otherwise... + expr_ref sgn(m), sig(m), exp(m), lz(m); + unpack(x, sgn, sig, exp, lz, true); + + // sig is of the form +- [1].[sig] * 2^(exp-lz) + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(sig) == sbits); + SASSERT(m_bv_util.get_bv_size(exp) == ebits); + SASSERT(m_bv_util.get_bv_size(lz) == ebits); + dbg_decouple("fpa2bv_to_ubv_sig", sig); + + // last number that's representable + expr_ref last_valid_bv(m); + last_valid_bv = m_bv_util.mk_numeral(-1, bv_sz); // == 1.0 * 2^bv_sz - 1.0 + + // first invalid bv + mpz const & first_invalid_bv = m_util.fm().m_powers2(bv_sz); + + unsigned sig_sz = m_bv_util.get_bv_size(sig); + SASSERT(sig_sz == sbits); + + expr_ref shift(m); + if (sig_sz < bv_sz) { + sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz - sig_sz)); + shift = m_bv_util.mk_bv_sub(m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp), + m_bv_util.mk_zero_extend(2, lz)), + m_bv_util.mk_numeral(bv_sz-1, ebits + 2)); + } + SASSERT(m_bv_util.get_bv_size(shift) == ebits + 2); + SASSERT(m_bv_util.get_bv_size(sig) >= bv_sz); + dbg_decouple("fpa2bv_to_ubv_shift", shift); + + expr_ref c_in_limits(m); + c_in_limits = m_bv_util.mk_sle(shift, m_bv_util.mk_numeral(0, ebits + 2)); + dbg_decouple("fpa2bv_to_ubv_in_limits", c_in_limits); + + expr_ref shifted_sig(m), shift_abs(m); + shift_abs = m_bv_util.mk_bv_neg(shift); + SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits+2); + SASSERT(bv_sz > (ebits + 2)); + shift_abs = m_bv_util.mk_zero_extend(bv_sz - ebits - 2, shift_abs); + + shifted_sig = m_bv_util.mk_bv_lshr(sig, shift_abs); + dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); + dbg_decouple("fpa2bv_to_ubv_shifted_sig", shifted_sig); + + expr_ref rounded(m); + rounded = shifted_sig; // TODO. + + result = m.mk_ite(c_in_limits, rounded, mk_fresh_const(0, bv_sz)); + result = m.mk_ite(c2, v2, result); + result = m.mk_ite(c1, v1, result); + + SASSERT(is_well_sorted(m, result)); } void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - SASSERT(num == 2); + TRACE("fpa2bv_to_sbv", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); + SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); + SASSERT(num == 2); + SASSERT(m_bv_util.get_bv_size(args[0]) == 3); + SASSERT(m_util.is_float(args[1])); //unsigned ebits = m_util.get_ebits(f->get_range()); //unsigned sbits = m_util.get_sbits(f->get_range()); From 05121e25d45319c22d976bacdfb82502c9a89333 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 28 Dec 2014 19:28:48 +0000 Subject: [PATCH 113/646] FPA theory support for conversion functions Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 64 +++++++++++++++++++++++++++++++- src/ast/float_decl_plugin.h | 24 +++++++++--- src/ast/fpa/fpa2bv_converter.cpp | 12 ++++-- src/ast/fpa/fpa2bv_converter.h | 4 ++ src/smt/theory_fpa.cpp | 22 ++++++----- 5 files changed, 107 insertions(+), 19 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index a861865f5..b019c7359 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -655,6 +655,45 @@ func_decl * float_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_p return m_manager->mk_func_decl(symbol("bv_unwrap"), 1, domain, range, func_decl_info(m_family_id, k, num_parameters, parameters)); } +func_decl * float_decl_plugin::mk_internal_to_ubv_unspecified( + decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 0) + m_manager->raise_exception("invalid number of arguments to fp.to_ubv_unspecified"); + if (num_parameters != 1) + m_manager->raise_exception("invalid number of parameters to fp.to_ubv_unspecified; expecting 1"); + if (!parameters[0].is_int()) + m_manager->raise_exception("invalid parameters type provided to fp.to_ubv_unspecified; expecting an integer"); + + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, parameters); + return m_manager->mk_func_decl(symbol("fp.to_ubv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + +func_decl * float_decl_plugin::mk_internal_to_sbv_unspecified( + decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 0) + m_manager->raise_exception("invalid number of arguments to internal_to_sbv_unspecified"); + if (!is_sort_of(domain[0], m_bv_fid, BV_SORT)) + m_manager->raise_exception("sort mismatch, expected argument of bitvector sort"); + if (!is_sort_of(range, m_bv_fid, BV_SORT)) + m_manager->raise_exception("sort mismatch, expected range of FloatingPoint sort"); + + sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, parameters); + return m_manager->mk_func_decl(symbol("fp.to_sbv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + +func_decl * float_decl_plugin::mk_internal_to_real_unspecified( + decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range) { + if (arity != 0) + m_manager->raise_exception("invalid number of arguments to internal_to_real_unspecified"); + if (!is_sort_of(range, m_arith_fid, REAL_SORT)) + m_manager->raise_exception("sort mismatch, expected range of FloatingPoint sort"); + + return m_manager->mk_func_decl(symbol("fp.to_real_unspecified"), 0, domain, m_real_sort, func_decl_info(m_family_id, k, num_parameters, parameters)); +} + func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { @@ -726,6 +765,12 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_internal_bv_wrap(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_INTERNAL_BVUNWRAP: return mk_internal_bv_unwrap(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED: + return mk_internal_to_ubv_unspecified(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED: + return mk_internal_to_sbv_unspecified(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED: + return mk_internal_to_real_unspecified(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); return 0; @@ -864,7 +909,8 @@ bool float_decl_plugin::is_unique_value(app* e) const { float_util::float_util(ast_manager & m): m_manager(m), m_fid(m.mk_family_id("float")), - m_a_util(m) { + m_a_util(m), + m_bv_util(m) { m_plugin = static_cast(m.get_plugin(m_fid)); } @@ -916,3 +962,19 @@ app * float_util::mk_nzero(unsigned ebits, unsigned sbits) { return mk_value(v); } +app * float_util::mk_internal_to_ubv_unspecified(unsigned width) { + parameter ps[] = { parameter(width) }; + sort * range = m_bv_util.mk_sort(width); + return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED, 1, ps, 0, 0, range); +} + +app * float_util::mk_internal_to_sbv_unspecified(unsigned width) { + parameter ps[] = { parameter(width) }; + sort * range = m_bv_util.mk_sort(width); + return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range); +} + +app * float_util::mk_internal_to_real_unspecified() { + sort * range = m_a_util.mk_real(); + return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED, 0, 0, 0, 0, range); +} \ No newline at end of file diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 01daab8e3..3403665a9 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -47,7 +47,7 @@ enum float_op_kind { OP_FLOAT_NAN, OP_FLOAT_PLUS_ZERO, OP_FLOAT_MINUS_ZERO, - + OP_FLOAT_ADD, OP_FLOAT_SUB, OP_FLOAT_NEG, @@ -70,7 +70,7 @@ enum float_op_kind { OP_FLOAT_IS_INF, OP_FLOAT_IS_ZERO, OP_FLOAT_IS_NORMAL, - OP_FLOAT_IS_SUBNORMAL, + OP_FLOAT_IS_SUBNORMAL, OP_FLOAT_IS_PZERO, OP_FLOAT_IS_NZERO, OP_FLOAT_IS_NEGATIVE, @@ -85,10 +85,13 @@ enum float_op_kind { /* Extensions */ OP_FLOAT_TO_IEEE_BV, - + /* Internal use only */ OP_FLOAT_INTERNAL_BVWRAP, OP_FLOAT_INTERNAL_BVUNWRAP, + OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED, + OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED, + OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED, LAST_FLOAT_OP }; @@ -155,9 +158,15 @@ class float_decl_plugin : public decl_plugin { unsigned arity, sort * const * domain, sort * range); func_decl * mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); func_decl * mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_internal_to_ubv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_internal_to_sbv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); + func_decl * mk_internal_to_real_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); virtual void set_manager(ast_manager * m, family_id id); unsigned mk_id(mpf const & v); @@ -203,6 +212,7 @@ class float_util { float_decl_plugin * m_plugin; family_id m_fid; arith_util m_a_util; + bv_util m_bv_util; public: float_util(ast_manager & m); ~float_util(); @@ -292,6 +302,10 @@ public: bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } + + app * mk_internal_to_ubv_unspecified(unsigned width); + app * mk_internal_to_sbv_unspecified(unsigned width); + app * mk_internal_to_real_unspecified(); }; #endif diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 88e738041..bd8240b31 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2487,10 +2487,13 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg mk_is_neg(x, x_is_neg); mk_is_nzero(x, x_is_nzero); + expr_ref undef(m); + undef = m_util.mk_internal_to_ubv_unspecified(bv_sz); + // NaN, Inf, or negative (except -0) -> undefined expr_ref c1(m), v1(m); c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero))); - v1 = mk_fresh_const(0, bv_sz); + v1 = undef; dbg_decouple("fpa2bv_to_ubv_c1", c1); // +-Zero -> 0 @@ -2546,9 +2549,10 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg dbg_decouple("fpa2bv_to_ubv_shifted_sig", shifted_sig); expr_ref rounded(m); - rounded = shifted_sig; // TODO. + // TODO: Rounding. + rounded = shifted_sig; - result = m.mk_ite(c_in_limits, rounded, mk_fresh_const(0, bv_sz)); + result = m.mk_ite(c_in_limits, rounded, undef); result = m.mk_ite(c2, v2, result); result = m.mk_ite(c1, v1, result); @@ -2658,7 +2662,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;); expr_ref undef(m); - undef = m.mk_fresh_const(0, rs); + undef = m_util.mk_internal_to_real_unspecified(); result = m.mk_ite(x_is_zero, zero, res); result = m.mk_ite(x_is_inf, undef, result); diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index cd92a6ab2..ee7ffa192 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -149,6 +149,10 @@ public: void mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + + void mk_internal_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_internal_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_internal_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); protected: void mk_is_nan(expr * e, expr_ref & result); diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index f05bca4a1..b63073893 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -291,7 +291,7 @@ namespace smt { SASSERT(m_bv_util.get_bv_size(res) == 3); ctx.internalize(res, false); } - else { + else if (m_float_util.is_float(e)) { SASSERT(to_app(res)->get_family_id() == get_family_id()); decl_kind k = to_app(res)->get_decl_kind(); if (k == OP_FLOAT_TO_FP) { @@ -314,6 +314,9 @@ namespace smt { SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); } } + else { + /* ignore; these are the conversion functions fp.to_* */ + } TRACE("t_fpa_detail", tout << "converted term:" << std::endl; tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << @@ -339,6 +342,8 @@ namespace smt { res = convert_atom(e); else if (m_float_util.is_float(e) || m_float_util.is_rm(e)) res = convert_term(e); + else if (m_arith_util.is_real(e)) + res = convert_term(e); else UNREACHABLE(); @@ -508,12 +513,10 @@ namespace smt { c = m.mk_and(m.mk_eq(x_sgn, y_sgn), m.mk_eq(x_sig, y_sig), - m.mk_eq(x_exp, y_exp)); + m.mk_eq(x_exp, y_exp)); } - else if (fu.is_rm(xe) && fu.is_rm(ye)) - c = m.mk_eq(xc, yc); else - UNREACHABLE(); + c = m.mk_eq(xc, yc); // assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); assert_cnstr(c); @@ -556,12 +559,10 @@ namespace smt { c = m.mk_or(m.mk_not(m.mk_eq(x_sgn, y_sgn)), m.mk_not(m.mk_eq(x_sig, y_sig)), - m.mk_not(m.mk_eq(x_exp, y_exp))); + m.mk_not(m.mk_eq(x_exp, y_exp))); } - else if (m_float_util.is_rm(xe) && m_float_util.is_rm(ye)) - c = m.mk_not(m.mk_eq(xc, yc)); else - UNREACHABLE(); + c = m.mk_not(m.mk_eq(xc, yc)); // assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); assert_cnstr(c); @@ -638,6 +639,9 @@ namespace smt { } } } + else { + // These are the conversion functions fp.to_* */ + } } void theory_fpa::reset_eh() { From 0ab2782048b733f31ff0364069ac8bb2284ce191 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 29 Dec 2014 17:08:46 +0000 Subject: [PATCH 114/646] FPA: name consistency Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 3403665a9..1598db9c3 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -264,7 +264,7 @@ public: bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } - bool is_to_float(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } + bool is_to_fp(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); } app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } From 33af7e8468ba0621149f65cfd856df72444c181a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 29 Dec 2014 17:09:18 +0000 Subject: [PATCH 115/646] FPA: bugfixes for fp.to_ubv Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 163 +++++++++++++++++++------------ src/ast/fpa/fpa2bv_converter.h | 1 + 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index bd8240b31..7edc4a7a0 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2475,6 +2475,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg unsigned ebits = m_util.get_ebits(xs); unsigned sbits = m_util.get_sbits(xs); unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); + unsigned rounding_sz = bv_sz + 3; expr_ref bv0(m), bv1(m); bv0 = m_bv_util.mk_numeral(0, 1); @@ -2489,6 +2490,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg expr_ref undef(m); undef = m_util.mk_internal_to_ubv_unspecified(bv_sz); + dbg_decouple("fpa2bv_to_ubv_undef", undef); // NaN, Inf, or negative (except -0) -> undefined expr_ref c1(m), v1(m); @@ -2499,7 +2501,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg // +-Zero -> 0 expr_ref c2(m), v2(m); c2 = x_is_zero; - v2 = m_bv_util.mk_numeral(rational(0), bv_srt); + v2 = m_bv_util.mk_numeral(rational(0), bv_srt); dbg_decouple("fpa2bv_to_ubv_c2", c2); // Otherwise... @@ -2512,47 +2514,73 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg SASSERT(m_bv_util.get_bv_size(exp) == ebits); SASSERT(m_bv_util.get_bv_size(lz) == ebits); dbg_decouple("fpa2bv_to_ubv_sig", sig); - - // last number that's representable - expr_ref last_valid_bv(m); - last_valid_bv = m_bv_util.mk_numeral(-1, bv_sz); // == 1.0 * 2^bv_sz - 1.0 - - // first invalid bv - mpz const & first_invalid_bv = m_util.fm().m_powers2(bv_sz); - unsigned sig_sz = m_bv_util.get_bv_size(sig); SASSERT(sig_sz == sbits); - - expr_ref shift(m); - if (sig_sz < bv_sz) { - sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz - sig_sz)); - shift = m_bv_util.mk_bv_sub(m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp), - m_bv_util.mk_zero_extend(2, lz)), - m_bv_util.mk_numeral(bv_sz-1, ebits + 2)); - } + if (sig_sz < (bv_sz + 3)) + sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz - sig_sz + 3)); + sig_sz = m_bv_util.get_bv_size(sig); + SASSERT(sig_sz >= (bv_sz + 3)); + + expr_ref exp_m_lz(m), shift(m), shift_neg(m), bv0_e2(m), shift_abs(m); + exp_m_lz = m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp), + m_bv_util.mk_zero_extend(2, lz)); + shift = m_bv_util.mk_bv_sub(exp_m_lz, + m_bv_util.mk_numeral(bv_sz - 1, ebits + 2)); + shift_neg = m_bv_util.mk_bv_neg(shift); + bv0_e2 = m_bv_util.mk_numeral(0, ebits + 2); + shift_abs = m.mk_ite(m_bv_util.mk_sle(shift, bv0_e2), shift_neg, shift); SASSERT(m_bv_util.get_bv_size(shift) == ebits + 2); - SASSERT(m_bv_util.get_bv_size(sig) >= bv_sz); + SASSERT(m_bv_util.get_bv_size(shift_neg) == ebits + 2); + SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits + 2); dbg_decouple("fpa2bv_to_ubv_shift", shift); + dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); + + // sig is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long + // [1][ ... sig ... ][r][g][ ... s ...] + // [ ... ubv ... ][r][g][ ... s ... ] + expr_ref max_shift(m); + max_shift = m_bv_util.mk_numeral(sig_sz, sig_sz); + shift_abs = m_bv_util.mk_zero_extend(sig_sz - ebits - 2, shift_abs); + SASSERT(m_bv_util.get_bv_size(shift_abs) == sig_sz); expr_ref c_in_limits(m); c_in_limits = m_bv_util.mk_sle(shift, m_bv_util.mk_numeral(0, ebits + 2)); dbg_decouple("fpa2bv_to_ubv_in_limits", c_in_limits); - expr_ref shifted_sig(m), shift_abs(m); - shift_abs = m_bv_util.mk_bv_neg(shift); - SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits+2); - SASSERT(bv_sz > (ebits + 2)); - shift_abs = m_bv_util.mk_zero_extend(bv_sz - ebits - 2, shift_abs); - + expr_ref shifted_sig(m); shifted_sig = m_bv_util.mk_bv_lshr(sig, shift_abs); - dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); dbg_decouple("fpa2bv_to_ubv_shifted_sig", shifted_sig); - expr_ref rounded(m); - // TODO: Rounding. - rounded = shifted_sig; + expr_ref last(m), round(m), sticky(m); + last = m_bv_util.mk_extract(sig_sz - bv_sz - 0, sig_sz - bv_sz - 0, shifted_sig); + round = m_bv_util.mk_extract(sig_sz - bv_sz - 1, sig_sz - bv_sz - 1, shifted_sig); + sticky = m.mk_ite(m.mk_eq(m_bv_util.mk_extract(sig_sz - bv_sz - 2, 0, shifted_sig), + m_bv_util.mk_numeral(0, sig_sz - (bv_sz + 3) + 2)), + bv0, + bv1); + dbg_decouple("fpa2bv_to_ubv_last", last); + dbg_decouple("fpa2bv_to_ubv_round", round); + dbg_decouple("fpa2bv_to_ubv_sticky", sticky); + + expr_ref rounding_decision(m); + rounding_decision = mk_rounding_decision(rm, sgn, last, round, sticky); + SASSERT(m_bv_util.get_bv_size(rounding_decision) == 1); + dbg_decouple("fpa2bv_to_ubv_rounding_decision", rounding_decision); - result = m.mk_ite(c_in_limits, rounded, undef); + expr_ref unrounded_sig(m), pre_rounded(m), inc(m); + unrounded_sig = m_bv_util.mk_zero_extend(1, + m_bv_util.mk_extract(sig_sz - 1, sig_sz - bv_sz, shifted_sig)); + inc = m_bv_util.mk_zero_extend(1, + m_bv_util.mk_zero_extend(bv_sz - 1, rounding_decision)); + pre_rounded = m_bv_util.mk_bv_add(unrounded_sig, inc); + + expr_ref rnd_overflow(m), rounded(m), rnd_has_overflown(m); + rnd_overflow = m_bv_util.mk_extract(bv_sz, bv_sz, pre_rounded); + rounded = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded); + rnd_has_overflown = m.mk_eq(rnd_overflow, bv1); + + result = m.mk_ite(rnd_has_overflown, undef, rounded); + result = m.mk_ite(c_in_limits, result, undef); result = m.mk_ite(c2, v2, result); result = m.mk_ite(c1, v1, result); @@ -3016,6 +3044,41 @@ void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { #endif } +expr_ref fpa2bv_converter::mk_rounding_decision(expr * rm, expr * sgn, expr * last, expr * round, expr * sticky) { + expr_ref last_or_sticky(m), round_or_sticky(m), not_round(m), not_lors(m), not_rors(m), not_sgn(m); + expr * last_sticky[2] = { last, sticky }; + expr * round_sticky[2] = { round, sticky }; + last_or_sticky = m_bv_util.mk_bv_or(2, last_sticky); + round_or_sticky = m_bv_util.mk_bv_or(2, round_sticky); + not_round = m_bv_util.mk_bv_not(round); + not_lors = m_bv_util.mk_bv_not(last_or_sticky); + not_rors = m_bv_util.mk_bv_not(round_or_sticky); + not_sgn = m_bv_util.mk_bv_not(sgn); + expr * round_lors[2] = { not_round, not_lors }; + expr * pos_args[2] = { sgn, not_rors }; + expr * neg_args[2] = { not_sgn, not_rors }; + + expr_ref inc_teven(m), inc_taway(m), inc_pos(m), inc_neg(m); + inc_teven = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, round_lors)); + inc_taway = round; + inc_pos = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, pos_args)); + inc_neg = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, neg_args)); + + expr_ref res(m), inc_c2(m), inc_c3(m), inc_c4(m); + expr_ref rm_is_to_neg(m), rm_is_to_pos(m), rm_is_away(m), rm_is_even(m), nil_1(m); + nil_1 = m_bv_util.mk_numeral(0, 1); + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); + mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_is_to_pos); + mk_is_rm(rm, BV_RM_TIES_TO_AWAY, rm_is_away); + mk_is_rm(rm, BV_RM_TIES_TO_EVEN, rm_is_even); + m_simp.mk_ite(rm_is_to_neg, inc_neg, nil_1, inc_c4); + m_simp.mk_ite(rm_is_to_pos, inc_pos, inc_c4, inc_c3); + m_simp.mk_ite(rm_is_away, inc_taway, inc_c3, inc_c2); + m_simp.mk_ite(rm_is_even, inc_teven, inc_c2, res); + + return res; +} + void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & result) { unsigned ebits = m_util.get_ebits(s); unsigned sbits = m_util.get_sbits(s); @@ -3110,7 +3173,6 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & SASSERT(is_well_sorted(m, beta)); dbg_decouple("fpa2bv_rnd_beta", beta); - dbg_decouple("fpa2bv_rnd_e_min", e_min); dbg_decouple("fpa2bv_rnd_e_max", e_max); @@ -3191,36 +3253,8 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig = m_bv_util.mk_extract(sbits+1, 2, sig); - expr_ref last_or_sticky(m), round_or_sticky(m), not_round(m), not_lors(m), not_rors(m), not_sgn(m); - expr * last_sticky[2] = { last, sticky }; - expr * round_sticky[2] = { round, sticky }; - last_or_sticky = m_bv_util.mk_bv_or(2, last_sticky); - round_or_sticky = m_bv_util.mk_bv_or(2, round_sticky); - not_round = m_bv_util.mk_bv_not(round); - not_lors = m_bv_util.mk_bv_not(last_or_sticky); - not_rors = m_bv_util.mk_bv_not(round_or_sticky); - not_sgn = m_bv_util.mk_bv_not(sgn); - expr * round_lors[2] = { not_round, not_lors}; - expr * pos_args[2] = { sgn, not_rors }; - expr * neg_args[2] = { not_sgn, not_rors }; - - expr_ref inc_teven(m), inc_taway(m), inc_pos(m), inc_neg(m); - inc_teven = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, round_lors)); - inc_taway = round; - inc_pos = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, pos_args)); - inc_neg = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, neg_args)); - - expr_ref inc(m), inc_c2(m), inc_c3(m), inc_c4(m); - expr_ref rm_is_to_neg(m), rm_is_to_pos(m), rm_is_away(m), rm_is_even(m), nil_1(m); - nil_1 = m_bv_util.mk_numeral(0, 1); - mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); - mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_is_to_pos); - mk_is_rm(rm, BV_RM_TIES_TO_AWAY, rm_is_away); - mk_is_rm(rm, BV_RM_TIES_TO_EVEN, rm_is_even); - m_simp.mk_ite(rm_is_to_neg, inc_neg, nil_1, inc_c4); - m_simp.mk_ite(rm_is_to_pos, inc_pos, inc_c4, inc_c3); - m_simp.mk_ite(rm_is_away, inc_taway, inc_c3, inc_c2); - m_simp.mk_ite(rm_is_even, inc_teven, inc_c2, inc); + expr_ref inc(m); + inc = mk_rounding_decision(rm, sgn, last, round, sticky); SASSERT(m_bv_util.get_bv_size(inc) == 1 && is_well_sorted(m, inc)); dbg_decouple("fpa2bv_rnd_inc", inc); @@ -3289,8 +3323,13 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & mk_top_exp(ebits, top_exp); mk_bot_exp(ebits, bot_exp); - expr_ref rm_is_to_zero(m), rm_zero_or_neg(m), rm_zero_or_pos(m); + expr_ref nil_1(m); + nil_1 = m_bv_util.mk_numeral(0, 1); + + expr_ref rm_is_to_zero(m), rm_is_to_neg(m), rm_is_to_pos(m), rm_zero_or_neg(m), rm_zero_or_pos(m); mk_is_rm(rm, BV_RM_TO_ZERO, rm_is_to_zero); + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); + mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_is_to_pos); m_simp.mk_or(rm_is_to_zero, rm_is_to_neg, rm_zero_or_neg); m_simp.mk_or(rm_is_to_zero, rm_is_to_pos, rm_zero_or_pos); @@ -3306,7 +3345,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & dbg_decouple("fpa2bv_rnd_max_exp", max_exp); - expr_ref ovfl_exp(m), max_inf_exp_neg(m), max_inf_exp_pos(m), n_d_check(m), n_d_exp(m); + expr_ref ovfl_exp(m), max_inf_exp_neg(m), max_inf_exp_pos(m), n_d_check(m), n_d_exp(m); m_simp.mk_ite(rm_zero_or_neg, max_exp, inf_exp, max_inf_exp_neg); m_simp.mk_ite(rm_zero_or_pos, max_exp, inf_exp, max_inf_exp_pos); m_simp.mk_ite(sgn_is_zero, max_inf_exp_neg, max_inf_exp_pos, ovfl_exp); diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index ee7ffa192..6a854adb3 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -181,6 +181,7 @@ protected: void unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize); void round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & result); + expr_ref mk_rounding_decision(expr * rm, expr * sgn, expr * last, expr * round, expr * sticky); void add_core(unsigned sbits, unsigned ebits, expr_ref & rm, expr_ref & c_sgn, expr_ref & c_sig, expr_ref & c_exp, expr_ref & d_sgn, expr_ref & d_sig, expr_ref & d_exp, From defb6158fe61d0c93662b07bd547c6dcf2dd7beb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 29 Dec 2014 17:09:28 +0000 Subject: [PATCH 116/646] MPF: bugfix Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 405f34c9d..e3f35538e 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1174,7 +1174,7 @@ std::string mpf_manager::to_string(mpf const & x) { if (is_nan(x)) res = "NaN"; else { - res = sgn(x) ? "-" : "+"; + res = sgn(x) ? "-" : ""; if (is_inf(x)) res += "INF"; From 2258988b37e7d8869ab5c2cf003d7e12272f92b4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 14:48:06 +0000 Subject: [PATCH 117/646] MPF bugfix Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index e3f35538e..245120866 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -301,28 +301,36 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode m_mpq_manager.mul(sig, 2, sig); m_mpz_manager.dec(exp); } - + // 1.0 <= sig < 2.0 SASSERT((m_mpq_manager.le(1, sig) && m_mpq_manager.lt(sig, 2))); - TRACE("mpf_dbg", tout << "sig = " << m_mpq_manager.to_string(sig) << " exp = " << m_mpz_manager.to_string(exp) << std::endl;); - + TRACE("mpf_dbg", tout << "sig = " << m_mpq_manager.to_string(sig) << + " exp = " << m_mpz_manager.to_string(exp) << std::endl;); + m_mpz_manager.set(o.significand, 0); for (unsigned i = 0; i < (sbits+3); i++) { m_mpz_manager.mul2k(o.significand, 1); - if (!m_mpq_manager.lt(sig, 1)) { - m_mpz_manager.inc(o.significand); + if (m_mpq_manager.ge(sig, 1)) { + m_mpz_manager.inc(o.significand); m_mpq_manager.dec(sig); } - m_mpq_manager.mul(sig, 2, sig); + m_mpq_manager.mul(sig, mpq(2), sig); } + + // sticky + if (!m_mpq_manager.is_zero(sig) && m_mpz_manager.is_even(o.significand)) + m_mpz_manager.inc(o.significand); + + TRACE("mpf_dbg", tout << "sig = " << m_mpz_manager.to_string(o.significand) << + " exp = " << o.exponent << std::endl;); if (m_mpz_manager.is_small(exp)) { o.exponent = m_mpz_manager.get_int64(exp); round(rm, o); } else - mk_inf(ebits, sbits, o.sign, o); // CMW: output warning message? throw exception? + mk_inf(ebits, sbits, o.sign, o); } TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;); From 4d18e24fb4ee28431cdbe7461ae611473076895c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 14:48:45 +0000 Subject: [PATCH 118/646] FPA rewriter bugfix Signed-off-by: Christoph M. Wintersteiger --- src/ast/rewriter/float_rewriter.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 522fad678..96561395e 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -587,9 +587,14 @@ br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) { scoped_mpf fv(m_util.fm()); if (m_util.is_value(arg1, fv)) { - scoped_mpq r(m_fm.mpq_manager()); - m_fm.to_rational(fv, r); - result = m_util.au().mk_numeral(r.get(), false); + if (m_fm.is_nan(fv) || m_fm.is_inf(fv)) { + result = m_util.mk_internal_to_real_unspecified(); + } + else { + scoped_mpq r(m_fm.mpq_manager()); + m_fm.to_rational(fv, r); + result = m_util.au().mk_numeral(r.get(), false); + } return BR_DONE; } From 01d78b7274d578e174851263728341ccde58ee4c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 14:49:52 +0000 Subject: [PATCH 119/646] added internal functions to fpa2bv converter Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 36 ++++++-------------------------- src/ast/fpa/fpa2bv_converter.h | 7 ------- src/ast/fpa/fpa2bv_rewriter.h | 7 +++++-- 3 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 7edc4a7a0..e396bb6b5 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2422,29 +2422,6 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * split_triple(args[0], sgn, s, e); result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s); } -void fpa2bv_converter::mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - TRACE("fpa2bv_internal", tout << "wrap "; - for (unsigned i = 0; i < num; i++) - tout << " " << mk_ismt2_pp(args[i], m); - tout << std::endl;); - SASSERT(num == 1); - result = m.mk_app(f, num, args); -} - -void fpa2bv_converter::mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - TRACE("fpa2bv_internal", tout << "unwrap "; - for (unsigned i = 0; i < num; i++) - tout << " " << mk_ismt2_pp(args[i], m); - tout << std::endl;); - SASSERT(num == 1); - app * a0 = to_app(args[0]); - SASSERT(a0->get_kind() == AST_APP); - SASSERT(is_float_family(a0->get_decl())); - decl_kind k = a0->get_decl_kind(); - SASSERT(k == OP_FLOAT_INTERNAL_BVWRAP); - SASSERT(a0->get_num_args() == 1); - result = a0->get_arg(0); -} void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 3); @@ -2631,7 +2608,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar expr_ref sgn(m), sig(m), exp(m), lz(m); unpack(x, sgn, sig, exp, lz, true); // sig is of the form [1].[sigbits] - + SASSERT(m_bv_util.get_bv_size(sgn) == 1); SASSERT(m_bv_util.get_bv_size(sig) == sbits); SASSERT(m_bv_util.get_bv_size(exp) == ebits); @@ -2646,8 +2623,8 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar for (unsigned i = sbits-2; i != (unsigned)-1; i--) { bit = m_bv_util.mk_extract(i, i, sig); - rsig = m_arith_util.mk_mul(rsig, two); - rsig = m_arith_util.mk_add(rsig, m.mk_ite(m.mk_eq(bit, bv1), one, zero)); + rsig = m_arith_util.mk_add(m_arith_util.mk_mul(rsig, two), + m.mk_ite(m.mk_eq(bit, bv1), one, zero)); } const mpz & p2 = fu().fm().m_powers2(sbits-1); @@ -2661,19 +2638,18 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar exp_is_neg = m.mk_eq(m_bv_util.mk_extract(ebits - 1, ebits - 1, exp), bv1); dbg_decouple("fpa2bv_to_real_exp_is_neg", exp_is_neg); exp_p = m_bv_util.mk_sign_extend(1, exp); - exp_n = m_bv_util.mk_bv_not(m_bv_util.mk_sign_extend(1, exp)); + exp_n = m_bv_util.mk_bv_neg(exp_p); exp_abs = m.mk_ite(exp_is_neg, exp_n, exp_p); dbg_decouple("fpa2bv_to_real_exp_abs", exp); SASSERT(m_bv_util.get_bv_size(exp_abs) == ebits + 1); expr_ref exp2(m), prev_bit(m); exp2 = zero; - prev_bit = bv0; for (unsigned i = ebits; i != (unsigned)-1; i--) { bit = m_bv_util.mk_extract(i, i, exp_abs); - exp2 = m_arith_util.mk_mul(exp2, two); - exp2 = m_arith_util.mk_add(exp2, m.mk_ite(m.mk_eq(bit, prev_bit), zero, one)); + exp2 = m_arith_util.mk_add(m_arith_util.mk_mul(exp2, two), + m.mk_ite(m.mk_eq(bit, bv1), one, zero)); prev_bit = bit; } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 6a854adb3..440fc9d14 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -147,13 +147,6 @@ public: void dbg_decouple(const char * prefix, expr_ref & e); expr_ref_vector m_extra_assertions; - void mk_internal_bvwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_internal_bvunwrap(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - - void mk_internal_to_ubv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_internal_to_sbv_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_internal_to_real_unspecified(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - protected: void mk_is_nan(expr * e, expr_ref & result); void mk_is_inf(expr * e, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 42fd7a7fe..c9296dd5b 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -151,8 +151,11 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; - case OP_FLOAT_INTERNAL_BVWRAP: m_conv.mk_internal_bvwrap(f, num, args, result); return BR_DONE; - case OP_FLOAT_INTERNAL_BVUNWRAP: m_conv.mk_internal_bvunwrap(f, num, args, result); return BR_DONE; + case OP_FLOAT_INTERNAL_BVWRAP: + case OP_FLOAT_INTERNAL_BVUNWRAP: + case OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED: + case OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED: + case OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED; default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); From 208994e2dc63214ddcf3f4dd25e344a253db484c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 15:33:50 +0000 Subject: [PATCH 120/646] Renamed the default tactics form QF_FPA and QF_FPABV to QF_FP and QF_FPBV, in anticipation of the logic name QF_FPA to mean floats+arrays. Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/qffpa_tactic.cpp | 53 +++---------------- src/tactic/fpa/qffpa_tactic.h | 14 ++--- src/tactic/portfolio/default_tactic.cpp | 2 +- src/tactic/portfolio/smt_strategic_solver.cpp | 6 +-- 4 files changed, 18 insertions(+), 57 deletions(-) diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index f9b7f88a1..6f1517c98 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -24,7 +24,7 @@ Notes: #include"qffpa_tactic.h" -tactic * mk_qffpa_tactic(ast_manager & m, params_ref const & p) { +tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { params_ref sat_simp_p = p; sat_simp_p .set_bool("elim_and", true); @@ -37,40 +37,14 @@ tactic * mk_qffpa_tactic(ast_manager & m, params_ref const & p) { mk_fail_if_undecided_tactic()); } -struct is_non_qffpa_predicate { - struct found {}; - ast_manager & m; - float_util u; - - is_non_qffpa_predicate(ast_manager & _m) : m(_m), u(m) {} - - void operator()(var *) { throw found(); } - - void operator()(quantifier *) { throw found(); } - - void operator()(app * n) { - sort * s = get_sort(n); - if (!m.is_bool(s) && !u.is_float(s) && !u.is_rm(s)) - 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(); - } -}; - -struct is_non_qffpabv_predicate { +struct is_non_qffp_predicate { struct found {}; ast_manager & m; bv_util bu; float_util fu; + arith_util au; - is_non_qffpabv_predicate(ast_manager & _m) : m(_m), bu(m), fu(m) {} + is_non_qffp_predicate(ast_manager & _m) : m(_m), bu(m), fu(m), au(m) {} void operator()(var *) { throw found(); } @@ -78,7 +52,7 @@ struct is_non_qffpabv_predicate { void operator()(app * n) { sort * s = get_sort(n); - if (!m.is_bool(s) && !fu.is_float(s) && !fu.is_rm(s) && !bu.is_bv_sort(s)) + if (!m.is_bool(s) && !fu.is_float(s) && !fu.is_rm(s) && !bu.is_bv_sort(s) && !au.is_real(s)) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) @@ -92,25 +66,14 @@ struct is_non_qffpabv_predicate { } }; -class is_qffpa_probe : public probe { +class is_qffp_probe : public probe { public: virtual result operator()(goal const & g) { - return !test(g); - } -}; - -class is_qffpabv_probe : public probe { -public: - virtual result operator()(goal const & g) { - return !test(g); + return !test(g); } }; probe * mk_is_qffpa_probe() { - return alloc(is_qffpa_probe); -} - -probe * mk_is_qffpabv_probe() { - return alloc(is_qffpabv_probe); + return alloc(is_qffp_probe); } \ No newline at end of file diff --git a/src/tactic/fpa/qffpa_tactic.h b/src/tactic/fpa/qffpa_tactic.h index cd16c5817..923c19970 100644 --- a/src/tactic/fpa/qffpa_tactic.h +++ b/src/tactic/fpa/qffpa_tactic.h @@ -24,17 +24,17 @@ Notes: class ast_manager; class tactic; -tactic * mk_qffpa_tactic(ast_manager & m, params_ref const & p = params_ref()); +tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p = params_ref()); /* - ADD_TACTIC("qffpa", "(try to) solve goal using the tactic for QF_FPA.", "mk_qffpa_tactic(m, p)") - ADD_TACTIC("qffpabv", "(try to) solve goal using the tactic for QF_FPABV (floats+bit-vectors).", "mk_qffpa_tactic(m, p)") + ADD_TACTIC("qffp", "(try to) solve goal using the tactic for QF_FPA.", "mk_qffp_tactic(m, p)") + ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPABV (floats+bit-vectors).", "mk_qffp_tactic(m, p)") */ -probe * mk_is_qffpa_probe(); -probe * mk_is_qffpabv_probe(); +probe * mk_is_qffp_probe(); +probe * mk_is_qffpbv_probe(); /* - ADD_PROBE("is-qffpa", "true if the goal is in QF_FPA (FloatingPoints).", "mk_is_qffpa_probe()") - ADD_PROBE("is-qffpabv", "true if the goal is in QF_FPABV (FloatingPoints+Bitvectors).", "mk_is_qffpabv_probe()") + ADD_PROBE("is-qffp", "true if the goal is in QF_FPA (FloatingPoints).", "mk_is_qffp_probe()") + ADD_PROBE("is-qffpbv", "true if the goal is in QF_FPABV (FloatingPoints+Bitvectors).", "mk_is_qffp_probe()") */ #endif diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 9ecc16ecf..a01b547df 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -38,7 +38,7 @@ tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { cond(mk_is_qfnia_probe(), mk_qfnia_tactic(m), cond(mk_is_nra_probe(), mk_nra_tactic(m), cond(mk_is_lira_probe(), mk_lira_tactic(m, p), - cond(mk_is_qffpabv_probe(), mk_qffpa_tactic(m, p), + cond(mk_is_qffp_probe(), mk_qffp_tactic(m, p), mk_smt_tactic()))))))))), p); return st; diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index ae79446e3..9e0ce6e89 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -78,10 +78,8 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const return mk_ufbv_tactic(m, p); else if (logic=="BV") return mk_ufbv_tactic(m, p); - else if (logic=="QF_FPA") - return mk_qffpa_tactic(m, p); - else if (logic=="QF_FPABV") - return mk_qffpa_tactic(m, p); + else if (logic=="QF_FP" || logic=="QF_FPBV") + return mk_qffp_tactic(m, p); else if (logic=="HORN") return mk_horn_tactic(m, p); else From 21a847d299972b6498cdf335c7fa1d30f2748ac8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 15:36:11 +0000 Subject: [PATCH 121/646] More renamings for QF_FP/qffp/is-qffp Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/qffpa_tactic.cpp | 2 +- src/tactic/fpa/qffpa_tactic.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index 6f1517c98..fc292bca6 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -73,7 +73,7 @@ public: } }; -probe * mk_is_qffpa_probe() { +probe * mk_is_qffp_probe() { return alloc(is_qffp_probe); } \ No newline at end of file diff --git a/src/tactic/fpa/qffpa_tactic.h b/src/tactic/fpa/qffpa_tactic.h index 923c19970..660622fb8 100644 --- a/src/tactic/fpa/qffpa_tactic.h +++ b/src/tactic/fpa/qffpa_tactic.h @@ -26,15 +26,15 @@ class tactic; tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p = params_ref()); /* - ADD_TACTIC("qffp", "(try to) solve goal using the tactic for QF_FPA.", "mk_qffp_tactic(m, p)") - ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPABV (floats+bit-vectors).", "mk_qffp_tactic(m, p)") + ADD_TACTIC("qffp", "(try to) solve goal using the tactic for QF_FP.", "mk_qffp_tactic(m, p)") + ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPBV (floats+bit-vectors).", "mk_qffp_tactic(m, p)") */ probe * mk_is_qffp_probe(); probe * mk_is_qffpbv_probe(); /* - ADD_PROBE("is-qffp", "true if the goal is in QF_FPA (FloatingPoints).", "mk_is_qffp_probe()") - ADD_PROBE("is-qffpbv", "true if the goal is in QF_FPABV (FloatingPoints+Bitvectors).", "mk_is_qffp_probe()") + ADD_PROBE("is-qffp", "true if the goal is in QF_FP (floats).", "mk_is_qffp_probe()") + ADD_PROBE("is-qffpbv", "true if the goal is in QF_FPBV (floats+bit-vectors).", "mk_is_qffp_probe()") */ #endif From afae49b9edd13cc45e8c5ae6a484b4a26abe1489 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 16:15:40 +0000 Subject: [PATCH 122/646] More renaming QF_FPA -> QF_FP Signed-off-by: Christoph M. Wintersteiger --- src/cmd_context/cmd_context.cpp | 10 +++++----- src/smt/smt_setup.cpp | 4 ++-- src/smt/smt_setup.h | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index ee5437bd6..4dd0cc614 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -512,8 +512,8 @@ bool cmd_context::logic_has_arith_core(symbol const & s) const { s == "UFNIA" || s == "LIA" || s == "LRA" || - s == "QF_FPA" || - s == "QF_FPABV" || + s == "QF_FP" || + s == "QF_FPBV" || s == "HORN"; } @@ -532,7 +532,7 @@ bool cmd_context::logic_has_bv_core(symbol const & s) const { s == "QF_ABV" || s == "QF_AUFBV" || s == "QF_BVRE" || - s == "QF_FPABV" || + s == "QF_FPBV" || s == "HORN"; } @@ -557,7 +557,7 @@ bool cmd_context::logic_has_seq() const { } bool cmd_context::logic_has_floats() const { - return !has_logic() || m_logic == "QF_FPA" || m_logic == "QF_FPABV"; + return !has_logic() || m_logic == "QF_FP" || m_logic == "QF_FPBV"; } bool cmd_context::logic_has_array_core(symbol const & s) const { @@ -668,7 +668,7 @@ bool cmd_context::supported_logic(symbol const & s) const { logic_has_arith_core(s) || logic_has_bv_core(s) || logic_has_array_core(s) || logic_has_seq_core(s) || logic_has_horn(s) || - s == "QF_FPA" || s == "QF_FPABV"; + s == "QF_FP" || s == "QF_FPBV"; } bool cmd_context::set_logic(symbol const & s) { diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 64477164a..68e960fb8 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -680,11 +680,11 @@ namespace smt { setup_mi_arith(); } - void setup::setup_QF_FPA() { + void setup::setup_QF_FP() { m_context.register_plugin(alloc(smt::theory_fpa, m_manager)); } - void setup::setup_QF_FPABV() { + void setup::setup_QF_FPBV() { setup_QF_BV(); m_context.register_plugin(alloc(smt::theory_fpa, m_manager)); } diff --git a/src/smt/smt_setup.h b/src/smt/smt_setup.h index 299ce7834..6cbcb9602 100644 --- a/src/smt/smt_setup.h +++ b/src/smt/smt_setup.h @@ -75,8 +75,8 @@ namespace smt { void setup_QF_AX(static_features const & st); void setup_QF_AUFLIA(); void setup_QF_AUFLIA(static_features const & st); - void setup_QF_FPA(); - void setup_QF_FPABV(); + void setup_QF_FP(); + void setup_QF_FPBV(); void setup_LRA(); void setup_AUFLIA(bool simple_array = true); void setup_AUFLIA(static_features const & st); From 80c025b2893cc6adc9d8747f0eb9145bfa04d2ec Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 16:15:55 +0000 Subject: [PATCH 123/646] Improved default tactic for QF_FP Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/qffpa_tactic.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index fc292bca6..6cfc699c7 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -21,6 +21,7 @@ Notes: #include"bit_blaster_tactic.h" #include"sat_tactic.h" #include"fpa2bv_tactic.h" +#include"smt_tactic.h" #include"qffpa_tactic.h" @@ -28,13 +29,17 @@ tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { params_ref sat_simp_p = p; sat_simp_p .set_bool("elim_and", true); - return and_then(mk_simplify_tactic(m, p), + return cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), + and_then(mk_simplify_tactic(m), + mk_smt_tactic()), + and_then( + mk_simplify_tactic(m, p), mk_fpa2bv_tactic(m, p), using_params(mk_simplify_tactic(m, p), sat_simp_p), mk_bit_blaster_tactic(m, p), using_params(mk_simplify_tactic(m, p), sat_simp_p), mk_sat_tactic(m, p), - mk_fail_if_undecided_tactic()); + mk_fail_if_undecided_tactic())); } struct is_non_qffp_predicate { From 2b7f9b7e5c98f5433877a65605f4fed824904c6d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 16:40:54 +0000 Subject: [PATCH 124/646] build fix for floats Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 2bdf7c4f8..1298093cf 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -53,8 +53,8 @@ def init_project_def(): add_lib('user_plugin', ['smt'], 'smt/user_plugin') add_lib('bv_tactics', ['tactic', 'bit_blaster'], 'tactic/bv') add_lib('fuzzing', ['ast'], 'test/fuzzing') - add_lib('fpa_tactics', ['fpa', 'core_tactics', 'bv_tactics', 'sat_tactic'], 'tactic/fpa') add_lib('smt_tactic', ['smt'], 'smt/tactic') + add_lib('fpa_tactics', ['fpa', 'core_tactics', 'bv_tactics', 'sat_tactic', 'smt_tactic'], 'tactic/fpa') add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls') add_lib('qe', ['smt','sat'], 'qe') add_lib('duality', ['smt', 'interp', 'qe']) From 7a5239ef707251a409894eef7eed773a96ede48e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 17:30:45 +0000 Subject: [PATCH 125/646] QF_FP default tactic bugfix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/fpa/qffpa_tactic.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index 6cfc699c7..919cf0c1b 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -29,7 +29,8 @@ tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { params_ref sat_simp_p = p; sat_simp_p .set_bool("elim_and", true); - return cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), + tactic * st = + cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), and_then(mk_simplify_tactic(m), mk_smt_tactic()), and_then( @@ -40,6 +41,9 @@ tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m, p), sat_simp_p), mk_sat_tactic(m, p), mk_fail_if_undecided_tactic())); + + st->updt_params(p); + return st; } struct is_non_qffp_predicate { From 3fe11e4c38977e938c106166cc361a46469cebb1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 17:31:11 +0000 Subject: [PATCH 126/646] improved handling of unspecified values in FP Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 39 ++++++++++++++++++++++---------- src/ast/fpa/fpa2bv_converter.h | 6 +++++ src/ast/fpa/fpa2bv_rewriter.h | 14 +++++++++--- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index e396bb6b5..94538861d 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -32,6 +32,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : m_arith_util(m), m_mpf_manager(m_util.fm()), m_mpz_manager(m_mpf_manager.mpz_manager()), + m_hi_fp_unspecified(true), m_extra_assertions(m) { m_plugin = static_cast(m.get_plugin(m.mk_family_id("float"))); } @@ -2465,14 +2466,10 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg mk_is_neg(x, x_is_neg); mk_is_nzero(x, x_is_nzero); - expr_ref undef(m); - undef = m_util.mk_internal_to_ubv_unspecified(bv_sz); - dbg_decouple("fpa2bv_to_ubv_undef", undef); - // NaN, Inf, or negative (except -0) -> undefined expr_ref c1(m), v1(m); c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero))); - v1 = undef; + v1 = mk_to_ubv_unspecified(bv_sz); dbg_decouple("fpa2bv_to_ubv_c1", c1); // +-Zero -> 0 @@ -2556,8 +2553,8 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg rounded = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded); rnd_has_overflown = m.mk_eq(rnd_overflow, bv1); - result = m.mk_ite(rnd_has_overflown, undef, rounded); - result = m.mk_ite(c_in_limits, result, undef); + result = m.mk_ite(rnd_has_overflown, mk_to_ubv_unspecified(bv_sz), rounded); + result = m.mk_ite(c_in_limits, result, mk_to_ubv_unspecified(bv_sz)); result = m.mk_ite(c2, v2, result); result = m.mk_ite(c1, v1, result); @@ -2664,17 +2661,35 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar TRACE("fpa2bv_to_real", tout << "rsig = " << mk_ismt2_pp(rsig, m) << std::endl; tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;); - - expr_ref undef(m); - undef = m_util.mk_internal_to_real_unspecified(); result = m.mk_ite(x_is_zero, zero, res); - result = m.mk_ite(x_is_inf, undef, result); - result = m.mk_ite(x_is_nan, undef, result); + result = m.mk_ite(x_is_inf, mk_to_real_unspecified(), result); + result = m.mk_ite(x_is_nan, mk_to_real_unspecified(), result); SASSERT(is_well_sorted(m, result)); } +expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned width) { + if (m_hi_fp_unspecified) + return expr_ref(m_bv_util.mk_numeral(0, width), m); + else + return expr_ref(m_util.mk_internal_to_ubv_unspecified(width), m); +} + +expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned width) { + if (m_hi_fp_unspecified) + return expr_ref(m_bv_util.mk_numeral(0, width), m); + else + return expr_ref(m_util.mk_internal_to_sbv_unspecified(width), m); +} + +expr_ref fpa2bv_converter::mk_to_real_unspecified() { + if (m_hi_fp_unspecified) + return expr_ref(m_arith_util.mk_numeral(rational(0), false), m); + else + return expr_ref(m_util.mk_internal_to_real_unspecified(), m); +} + void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 440fc9d14..197c7ce9a 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -51,6 +51,7 @@ protected: mpf_manager & m_mpf_manager; unsynch_mpz_manager & m_mpz_manager; float_decl_plugin * m_plugin; + bool m_hi_fp_unspecified; obj_map m_const2bv; obj_map m_rm_const2bv; @@ -137,6 +138,11 @@ public: void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; } + expr_ref mk_to_ubv_unspecified(unsigned width); + expr_ref mk_to_sbv_unspecified(unsigned width); + expr_ref mk_to_real_unspecified(); + obj_map const & const2bv() const { return m_const2bv; } obj_map const & rm_const2bv() const { return m_rm_const2bv; } obj_map const & uf2bvuf() const { return m_uf2bvuf; } diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index c9296dd5b..797f681e7 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -24,6 +24,7 @@ Notes: #include"rewriter_def.h" #include"bv_decl_plugin.h" #include"fpa2bv_converter.h" +#include"fpa2bv_rewriter_params.hpp" struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { ast_manager & m_manager; @@ -36,7 +37,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { ast_manager & m() const { return m_manager; } - fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p): + fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c, params_ref const & p) : m_manager(m), m_out(m), m_conv(c), @@ -58,9 +59,16 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { void reset() { } + void updt_local_params(params_ref const & _p) { + fpa2bv_rewriter_params p(_p); + bool v = p.hi_fp_unspecified(); + m_conv.set_unspecified_fp_hi(v); + } + 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_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); + m_max_steps = p.get_uint("max_steps", UINT_MAX); + updt_local_params(p); } bool max_steps_exceeded(unsigned num_steps) const { From 7d61223a3a94b1ac1091ac0a4997cb009ac25b35 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 31 Dec 2014 18:34:42 +0000 Subject: [PATCH 127/646] Improved FP theory Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 360 +++++++++++++++++++++-------------------- src/smt/theory_fpa.h | 90 +++++++++-- 2 files changed, 260 insertions(+), 190 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index b63073893..f7fd1de30 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -24,55 +24,14 @@ Revision History: namespace smt { - class fpa_factory : public value_factory { - float_util m_util; - - virtual app * mk_value_core(mpf const & val, sort * s) { - SASSERT(m_util.get_ebits(s) == val.get_ebits()); - SASSERT(m_util.get_sbits(s) == val.get_sbits()); - return m_util.mk_value(val); - } - - public: - fpa_factory(ast_manager & m, family_id fid) : - value_factory(m, fid), - m_util(m) { - } - - virtual ~fpa_factory() {} - - virtual expr * get_some_value(sort * s) { - mpf_manager & mpfm = m_util.fm(); - scoped_mpf q(mpfm); - mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); - return m_util.mk_value(q); - } - - virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { - mpf_manager & mpfm = m_util.fm(); - scoped_mpf q(mpfm); - mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); - v1 = m_util.mk_value(q); - mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 1); - v2 = m_util.mk_value(q); - return true; - } - - virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } - virtual void register_value(expr * n) { /* Ignore */ } - - app * mk_value(mpf const & x) { - return m_util.mk_value(x); - } - }; - - class fpa_conv_trail : public trail { + class fpa2bv_conversion_trail_elem : public trail { ast_manager & m; obj_map & m_conversions; expr * m_e; public: - fpa_conv_trail(ast_manager & m, obj_map & c, expr * e) : m(m), m_conversions(c), m_e(e) {} - virtual ~fpa_conv_trail() {} + fpa2bv_conversion_trail_elem(ast_manager & m, obj_map & c, expr * e) : + m(m), m_conversions(c), m_e(e) {} + virtual ~fpa2bv_conversion_trail_elem() {} virtual void undo(theory_fpa & th) { expr * v = m_conversions.find(m_e); m_conversions.remove(m_e); @@ -150,50 +109,52 @@ namespace smt { } app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector & values) { - SASSERT(values.size() == 3); - ast_manager & m = m_th.get_manager(); - - TRACE("t_fpa", tout << "fpa_value_proc::mk_value for: [" << - mk_ismt2_pp(values[0], m) << " " << - mk_ismt2_pp(values[1], m) << " " << - mk_ismt2_pp(values[2], m) << "]" << std::endl;); + SASSERT(values.size() == 1); + ast_manager & m = m_th.get_manager(); mpf_manager & mpfm = m_fu.fm(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); - - unsigned ebits = m_bu.get_bv_size(values[2]); - unsigned sbits = m_bu.get_bv_size(values[1]) + 1; + + SASSERT(m_bu.get_bv_size(values[0]) == (m_ebits + m_sbits)); + app * result; - scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); scoped_mpz bias(mpzm); - mpzm.power(mpz(2), ebits - 1, bias); + mpzm.power(mpz(2), m_ebits - 1, bias); mpzm.dec(bias); - rational sgn_q(0), sig_q(0), exp_q(bias); + rational all_rat(0); + scoped_mpz all_bits(mpzm); unsigned bv_sz; - bool r; - r = m_bu.is_numeral(values[0], sgn_q, bv_sz); SASSERT(r); SASSERT(bv_sz == 1); - r = m_bu.is_numeral(values[1], sig_q, bv_sz); SASSERT(r); SASSERT(bv_sz == sbits - 1); - r = m_bu.is_numeral(values[2], exp_q, bv_sz); SASSERT(r); SASSERT(bv_sz == ebits); + bool r = m_bu.is_numeral(values[0], all_rat, bv_sz); + SASSERT(r); + SASSERT(bv_sz == (m_ebits+m_sbits)); + SASSERT(all_rat.is_int()); + mpzm.set(all_bits, all_rat.to_mpq().numerator()); - TRACE("t_fpa", tout << "sgn=" << sgn_q.to_string() << " ; " << - "sig=" << sig_q.to_string() << " ; " << - "exp=" << exp_q.to_string() << std::endl;); + scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); + mpzm.machine_div2k(all_bits, m_ebits + m_sbits - 1, sgn_z); + mpzm.mod(all_bits, mpfm.m_powers2(m_ebits + m_sbits - 1), all_bits); - rational exp_u = exp_q - rational(bias); - SASSERT(exp_u.is_int64()); + mpzm.machine_div2k(all_bits, m_sbits - 1, exp_z); + mpzm.mod(all_bits, mpfm.m_powers2(m_sbits - 1), all_bits); - scoped_mpf f(mpfm); - scoped_mpq sig_mpq(mpqm); - sig_mpq = sig_q.to_mpq(); - mpfm.set(f, ebits, sbits, sgn_q.is_one(), sig_mpq.get().numerator(), exp_u.get_int64()); + TRACE("t_fpa_detail", tout << "sgn=" << mpzm.to_string(sgn_z) << " ; " << + "sig=" << mpzm.to_string(sig_z) << " ; " << + "exp=" << mpzm.to_string(exp_z) << std::endl;); + + scoped_mpz exp_u = exp_z - bias; + SASSERT(mpzm.is_int64(exp_u)); + + scoped_mpf f(mpfm); + mpfm.set(f, m_ebits, m_sbits, mpzm.is_one(sgn_z), sig_z, mpzm.get_int64(exp_u)); result = m_fu.mk_value(f); - TRACE("t_fpa", tout << "fpa_value_proc::mk_value result: " << - mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + TRACE("t_fpa", tout << "fpa_value_proc::mk_value [" << + mk_ismt2_pp(values[0], m) << "] --> " << + mk_ismt2_pp(result, m_th.get_manager()) << "\n";); return result; } @@ -267,11 +228,6 @@ namespace smt { proof_ref pr(m); m_rw(e, res); m_th_rw(res, res); - - TRACE("t_fpa_detail", tout << "converted atom:" << std::endl; - tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); - SASSERT(is_app(res)); SASSERT(m.is_bool(res)); return res; @@ -290,11 +246,13 @@ namespace smt { SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); SASSERT(m_bv_util.get_bv_size(res) == 3); ctx.internalize(res, false); + m_th_rw(res, res); } else if (m_float_util.is_float(e)) { SASSERT(to_app(res)->get_family_id() == get_family_id()); - decl_kind k = to_app(res)->get_decl_kind(); - if (k == OP_FLOAT_TO_FP) { + float_op_kind k = (float_op_kind)(to_app(res)->get_decl_kind()); + switch (k) { + case OP_FLOAT_TO_FP: { SASSERT(to_app(res)->get_num_args() == 3); SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); @@ -305,22 +263,32 @@ namespace smt { m_converter.split_triple(res, sgn, sig, exp); m_th_rw(sgn, s_sgn); m_th_rw(sig, s_sig); - m_th_rw(exp, s_exp); - - m_converter.mk_triple(s_sgn, s_sig, s_exp, res); - } - else { - SASSERT(is_sort_of(m.get_sort(e), get_family_id(), ROUNDING_MODE_SORT)); - SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); - } - } - else { - /* ignore; these are the conversion functions fp.to_* */ - } + m_th_rw(exp, s_exp); - TRACE("t_fpa_detail", tout << "converted term:" << std::endl; - tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); + m_converter.mk_triple(s_sgn, s_sig, s_exp, res); + break; + } + default: + /* nothing */; + } + } + else + UNREACHABLE(); + + return res; + } + + expr_ref theory_fpa::convert_conversion_term(expr * e) { + /* This is for the conversion functions fp.to_* */ + ast_manager & m = get_manager(); + context & ctx = get_context(); + expr_ref res(m); + proof_ref pr(m); + + SASSERT(m_arith_util.is_real(e) || m_bv_util.is_bv(e)); + + m_rw(e, res); + m_th_rw(res, res); return res; } @@ -342,18 +310,18 @@ namespace smt { res = convert_atom(e); else if (m_float_util.is_float(e) || m_float_util.is_rm(e)) res = convert_term(e); - else if (m_arith_util.is_real(e)) - res = convert_term(e); + else if (m_arith_util.is_real(e) || m_bv_util.is_bv(e)) + res = convert_conversion_term(e); else UNREACHABLE(); - TRACE("t_fpa_detail", tout << "caching:" << std::endl; + TRACE("t_fpa_detail", tout << "converted; caching:" << std::endl; tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << mk_ismt2_pp(res, m) << std::endl;); m_conversions.insert(e, res); m.inc_ref(res); - m_trail_stack.push(fpa_conv_trail(m, m_conversions, e)); + m_trail_stack.push(fpa2bv_conversion_trail_elem(m, m_conversions, e)); } return res; @@ -381,9 +349,9 @@ namespace smt { return res; } - void theory_fpa::assert_cnstr(expr * e) { - TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); + void theory_fpa::assert_cnstr(expr * e) { if (get_manager().is_true(e)) return; + TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); context& ctx = get_context(); ctx.internalize(e, false); literal lit(ctx.get_literal(e)); @@ -395,11 +363,11 @@ namespace smt { context & ctx = get_context(); theory_var v = mk_var(n); ctx.attach_th_var(n, this, v); - TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(n->get_owner(), get_manager()) << " := " << v << "\n";); + TRACE("t_fpa_detail", tout << "new theory var: " << mk_ismt2_pp(n->get_owner(), get_manager()) << " := " << v << "\n";); } bool theory_fpa::internalize_atom(app * atom, bool gate_ctx) { - TRACE("t_fpa_detail", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); + TRACE("t_fpa", tout << "internalizing atom: " << mk_ismt2_pp(atom, get_manager()) << "\n";); SASSERT(atom->get_family_id() == get_family_id()); ast_manager & m = get_manager(); @@ -416,9 +384,8 @@ namespace smt { ctx.set_var_theory(l.var(), get_id()); expr_ref bv_atom(m); - bv_atom = convert(atom); - TRACE("t_fpa_detail", tout << "converted: " << mk_ismt2_pp(bv_atom, get_manager()) << "\n";); - SASSERT(bv_atom.get()->get_kind() == AST_APP); + bv_atom = convert(atom); + SASSERT(is_app(bv_atom) && m.is_bool(bv_atom)); bv_atom = m.mk_and(bv_atom, mk_side_conditions()); expr_ref atom_iff(m); @@ -429,8 +396,7 @@ namespace smt { bool theory_fpa::internalize_term(app * term) { ast_manager & m = get_manager(); context & ctx = get_context(); - - TRACE("t_fpa_detail", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); + TRACE("t_fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); SASSERT(term->get_family_id() == get_family_id()); SASSERT(!ctx.e_internalized(term)); @@ -438,51 +404,90 @@ namespace smt { for (unsigned i = 0; i < num_args; i++) ctx.internalize(term->get_arg(i), false); - enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : + enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true); if (is_attached_to_var(e)) return false; - attach_new_th_var(e); + attach_new_th_var(e); + + // The conversion operators fp.to_* appear in non-FP constraints. + // The corresponding constraints will not be translated and added + // via convert(...) and assert_cnstr(...) in initialize_atom(...). + // Therefore, we translate and assert them here. + float_op_kind k = (float_op_kind)term->get_decl_kind(); + switch (k) { + case OP_FLOAT_TO_UBV: + case OP_FLOAT_TO_SBV: + case OP_FLOAT_TO_REAL: { + expr_ref conv(m); + conv = convert(term); + assert_cnstr(m.mk_eq(term, conv)); + assert_cnstr(mk_side_conditions()); + break; + } + default: /* ignore */; + } + return true; } - void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { - TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); + void theory_fpa::apply_sort_cnstr(enode * n, sort * s) { + TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); SASSERT(n->get_owner()->get_family_id() == get_family_id() || n->get_owner()->get_family_id() == null_theory_id); - SASSERT(s->get_family_id() == get_family_id()); - ast_manager & m = get_manager(); + SASSERT(s->get_family_id() == get_family_id()); if (!is_attached_to_var(n)) attach_new_th_var(n); - + + ast_manager & m = get_manager(); + context & ctx = get_context(); + app_ref owner(m); sort_ref owner_sort(m); owner = n->get_owner(); owner_sort = m.get_sort(owner); if (m_float_util.is_rm(owner_sort)) { + // For every RM term, we need to make sure that it's + // associated bit-vector is within the valid range. + // This also ensures that wrap(owner) is internalized. func_decl_ref wrap(m), unwrap(m); get_wrap(owner_sort, wrap, unwrap); if (owner->get_decl() != unwrap) { - expr_ref converted(m), t(m), limit(m); - converted = convert(owner); + expr_ref wrapped(m), valid(m), limit(m); + wrapped = m.mk_app(wrap, owner.get()); limit = m_bv_util.mk_numeral(4, 3); - t = m_bv_util.mk_ule(converted, limit); - assert_cnstr(t); + valid = m_bv_util.mk_ule(wrapped, limit); + assert_cnstr(valid); } } + else if (m_float_util.is_float(owner_sort)) { + // For every FP term, we need to make sure that + // its wrapped version is also internalized so that + // we can build a model for it later. + func_decl_ref wrap(m), unwrap(m); + get_wrap(owner_sort, wrap, unwrap); + if (owner->get_decl() != unwrap) { + expr_ref wrapped(m); + wrapped = m.mk_app(wrap, owner.get()); + if (!ctx.e_internalized(wrapped)) + ctx.internalize(wrapped, false); + } + } + else + UNREACHABLE(); } void theory_fpa::new_eq_eh(theory_var x, theory_var y) { ast_manager & m = get_manager(); - TRACE("t_fpa", tout << "new eq: " << x << " = " << y << std::endl; - tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " = " << - mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl; ); + TRACE("t_fpa", tout << "new eq: " << x << " = " << y << std::endl;); + TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " = " << + mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); context & ctx = get_context(); float_util & fu = m_float_util; @@ -492,7 +497,8 @@ namespace smt { app * xe = get_enode(x)->get_owner(); app * ye = get_enode(y)->get_owner(); - if (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye)) + if ((m.is_bool(xe) && m.is_bool(ye)) || + (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) { SASSERT(xe->get_decl()->get_family_id() == get_family_id()); return; @@ -503,9 +509,14 @@ namespace smt { yc = convert(ye); expr_ref c(m); - + if (fu.is_float(xe) && fu.is_float(ye)) { + func_decl_ref wrap(m), unwrap(m); + get_wrap(m.get_sort(ye), wrap, unwrap); + if (ye->get_decl() == unwrap) + return; + expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); expr *y_sgn, *y_sig, *y_exp; @@ -518,8 +529,7 @@ namespace smt { else c = m.mk_eq(xc, yc); - // assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); - assert_cnstr(c); + assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); assert_cnstr(mk_side_conditions()); return; @@ -528,9 +538,9 @@ namespace smt { void theory_fpa::new_diseq_eh(theory_var x, theory_var y) { ast_manager & m = get_manager(); - TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << std::endl; - tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " != " << - mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); + TRACE("t_fpa", tout << "new diseq: " << x << " != " << y << std::endl;); + TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " != " << + mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); context & ctx = get_context(); mpf_manager & mpfm = m_float_util.fm(); @@ -538,8 +548,8 @@ namespace smt { app * xe = get_enode(x)->get_owner(); app * ye = get_enode(y)->get_owner(); - if (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye)) - { + if ((m.is_bool(xe) && m.is_bool(ye)) || + (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) { SASSERT(xe->get_decl()->get_family_id() == get_family_id()); return; } @@ -559,13 +569,12 @@ namespace smt { c = m.mk_or(m.mk_not(m.mk_eq(x_sgn, y_sgn)), m.mk_not(m.mk_eq(x_sig, y_sig)), - m.mk_not(m.mk_eq(x_exp, y_exp))); + m.mk_not(m.mk_eq(x_exp, y_exp))); } else c = m.mk_not(m.mk_eq(xc, yc)); - // assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); - assert_cnstr(c); + assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); assert_cnstr(mk_side_conditions()); return; @@ -591,8 +600,7 @@ namespace smt { TRACE("t_fpa", tout << "assign_eh for: " << v << " (" << is_true << "):\n" << mk_ismt2_pp(e, m) << "\n";); expr_ref converted(m); - converted = convert(e); - converted = m.mk_and(converted, mk_side_conditions()); + converted = m.mk_and(convert(e), mk_side_conditions()); if (!is_true) converted = m.mk_not(converted); assert_cnstr(converted); } @@ -615,8 +623,7 @@ namespace smt { mpf_rounding_mode rm; scoped_mpf val(mpfm); if (m_float_util.is_rm_value(n, rm)) { - c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3)); - c = m.mk_and(c, mk_side_conditions()); + c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3)); assert_cnstr(c); } else if (m_float_util.is_value(n, val)) { @@ -626,22 +633,26 @@ namespace smt { SASSERT(is_app(bv_val_e)); SASSERT(to_app(bv_val_e)->get_num_args() == 3); app_ref bv_val_a(to_app(bv_val_e.get()), m); - c = m.mk_eq(wrapped, m_bv_util.mk_concat( - m_bv_util.mk_concat(bv_val_a->get_arg(0), bv_val_a->get_arg(1)), - bv_val_a->get_arg(2))); + c = m.mk_eq(wrapped, m_bv_util.mk_concat( m_bv_util.mk_concat( + bv_val_a->get_arg(0), + bv_val_a->get_arg(1)), + bv_val_a->get_arg(2))); c = m.mk_and(c, mk_side_conditions()); assert_cnstr(c); } else { c = m.mk_eq(m.mk_app(unwrap, wrapped), n); - c = m.mk_and(c, mk_side_conditions()); assert_cnstr(c); } } } - else { + else if (n->get_family_id() == get_family_id()) { + SASSERT(!m_float_util.is_float(n) && !m_float_util.is_rm(n)); // These are the conversion functions fp.to_* */ } + else + UNREACHABLE(); + } void theory_fpa::reset_eh() { @@ -659,26 +670,15 @@ namespace smt { theory::reset_eh(); } - void theory_fpa::init_model(model_generator & mg) { - TRACE("t_fpa", tout << "initializing model" << std::endl;); - m_factory = alloc(fpa_factory, get_manager(), get_family_id()); - mg.register_factory(m_factory); - TRACE("t_fpa", display(tout);); + final_check_status theory_fpa::final_check_eh() { + TRACE("t_fpa", tout << "final_check_eh\n";); + return FC_DONE; } - void theory_fpa::add_value_dep(fpa_value_proc * vp, expr * e) { - SASSERT(m_bv_util.is_bv(e)); - ast_manager & m = get_manager(); - context & ctx = get_context(); - if (ctx.e_internalized(e)) - vp->add_dependency(ctx.get_enode(e)); - else { - expr_ref n(m); - n = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(e)); - if (!ctx.e_internalized(n)) - ctx.internalize(n, false); - vp->add_dependency(ctx.get_enode(n)); - } + void theory_fpa::init_model(model_generator & mg) { + TRACE("t_fpa", tout << "initializing model" << std::endl; display(tout);); + m_factory = alloc(fpa_factory, get_manager(), get_family_id()); + mg.register_factory(m_factory); } model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { @@ -688,26 +688,36 @@ namespace smt { context & ctx = get_context(); app * owner = n->get_owner(); - app_ref c_a(m); - c_a = to_app(convert(owner)); + // If the owner is not internalized, it doesn't have an enode associated. SASSERT(ctx.e_internalized(owner)); - - TRACE("t_fpa", tout << "converted = " << mk_ismt2_pp(c_a, get_manager()) << "\n";); - + + if (m_float_util.is_rm_value(owner) || + m_float_util.is_value(owner)) + return alloc(expr_wrapper_proc, owner); + model_value_proc * res = 0; + func_decl_ref wrap(m), unwrap(m); + get_wrap(m.get_sort(owner), wrap, unwrap); + app_ref wrapped(m); + wrapped = m.mk_app(wrap, owner); + + CTRACE("t_fpa", !ctx.e_internalized(wrapped), + tout << "Model dependency not internalized: " << + mk_ismt2_pp(wrapped, m) << + " (owner " << (!ctx.e_internalized(owner) ? "not" : "is") << + " internalized)" << std::endl;); + if (m_float_util.is_rm(owner)) { - fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); - add_value_dep(vp, c_a); - res = vp; + fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); + vp->add_dependency(ctx.get_enode(wrapped)); + res = vp; } else if (m_float_util.is_float(owner)) { - fpa_value_proc * vp = alloc(fpa_value_proc, this); - expr_ref bv_sgn(m), bv_sig(m), bv_exp(m); - m_converter.split_triple(c_a, bv_sgn, bv_sig, bv_exp); - add_value_dep(vp, bv_sgn); - add_value_dep(vp, bv_sig); - add_value_dep(vp, bv_exp); + unsigned ebits = m_float_util.get_ebits(m.get_sort(owner)); + unsigned sbits = m_float_util.get_sbits(m.get_sort(owner)); + fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits); + vp->add_dependency(ctx.get_enode(wrapped)); res = vp; } else diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index bd2ea29f8..c21096ec0 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -29,9 +29,49 @@ Revision History: namespace smt { - class fpa_factory; + class fpa_factory : public value_factory { + float_util m_util; + + virtual app * mk_value_core(mpf const & val, sort * s) { + SASSERT(m_util.get_ebits(s) == val.get_ebits()); + SASSERT(m_util.get_sbits(s) == val.get_sbits()); + return m_util.mk_value(val); + } + + public: + fpa_factory(ast_manager & m, family_id fid) : + value_factory(m, fid), + m_util(m) {} + + virtual ~fpa_factory() {} + + virtual expr * get_some_value(sort * s) { + mpf_manager & mpfm = m_util.fm(); + scoped_mpf q(mpfm); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); + return m_util.mk_value(q); + } + + virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2) { + mpf_manager & mpfm = m_util.fm(); + scoped_mpf q(mpfm); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 0); + v1 = m_util.mk_value(q); + mpfm.set(q, m_util.get_ebits(s), m_util.get_sbits(s), 1); + v2 = m_util.mk_value(q); + return true; + } + + virtual expr * get_fresh_value(sort * s) { NOT_IMPLEMENTED_YET(); } + virtual void register_value(expr * n) { /* Ignore */ } + + app * mk_value(mpf const & x) { + return m_util.mk_value(x); + } + }; class theory_fpa : public theory { + protected: typedef trail_stack th_trail_stack; class fpa2bv_converter_wrapped : public fpa2bv_converter { @@ -46,27 +86,48 @@ namespace smt { }; class fpa_value_proc : public model_value_proc { - protected: - theory_fpa & m_th; + protected: + theory_fpa & m_th; + ast_manager & m; float_util & m_fu; bv_util & m_bu; - svector m_dependencies; + buffer m_deps; + unsigned m_ebits; + unsigned m_sbits; + public: - fpa_value_proc(theory_fpa * th) : - m_th(*th),m_fu(th->m_float_util),m_bu(th->m_bv_util) {} - void add_dependency(enode * n) { m_dependencies.push_back(model_value_dependency(n)); } + fpa_value_proc(theory_fpa * th, unsigned ebits, unsigned sbits) : + m_th(*th), m_fu(th->m_float_util), m_bu(th->m_bv_util), m(th->get_manager()), + m_ebits(ebits), m_sbits(sbits) {} + virtual ~fpa_value_proc() {} + + void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); } + virtual void get_dependencies(buffer & result) { - result.append(m_dependencies.size(), m_dependencies.c_ptr()); + result.append(m_deps); } + virtual app * mk_value(model_generator & mg, ptr_vector & values); }; - class fpa_rm_value_proc : public fpa_value_proc { + class fpa_rm_value_proc : public model_value_proc { + theory_fpa & m_th; + ast_manager & m; + float_util & m_fu; + bv_util & m_bu; + buffer m_deps; + public: fpa_rm_value_proc(theory_fpa * th) : - fpa_value_proc(th) {} - void add_dependency(enode * n) { fpa_value_proc::add_dependency(n); } + m_th(*th), m_fu(th->m_float_util), m_bu(th->m_bv_util), m(th->get_manager()) {} + + void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); } + + virtual void get_dependencies(buffer & result) { + result.append(m_deps); + } + virtual ~fpa_rm_value_proc() {} virtual app * mk_value(model_generator & mg, ptr_vector & values); }; @@ -84,7 +145,7 @@ namespace smt { obj_map m_unwraps; obj_map m_conversions; - virtual final_check_status final_check_eh() { return FC_DONE; } + virtual final_check_status final_check_eh(); virtual bool internalize_atom(app * atom, bool gate_ctx); virtual bool internalize_term(app * term); virtual void apply_sort_cnstr(enode * n, sort * s); @@ -114,13 +175,12 @@ namespace smt { expr_ref convert(expr * e); expr_ref convert_atom(expr * e); expr_ref convert_term(expr * e); + expr_ref convert_conversion_term(expr * e); void get_wrap(sort * s, func_decl_ref & wrap, func_decl_ref & unwrap); void add_trail(ast * a); - void mk_bv_eq(expr * x, expr * y); void attach_new_th_var(enode * n); - void assert_cnstr(expr * e); - void add_value_dep(fpa_value_proc * vp, expr * e); + void assert_cnstr(expr * e); }; }; From 4f453703f7baf85a16a822a48edc7c6cb95d5a64 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 15:23:02 +0000 Subject: [PATCH 128/646] Added arguments of type float to the replayer. Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_replayer.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- src/api/z3_replayer.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/api/z3_replayer.cpp b/src/api/z3_replayer.cpp index acdb10bf6..676ba0c69 100644 --- a/src/api/z3_replayer.cpp +++ b/src/api/z3_replayer.cpp @@ -40,11 +40,12 @@ struct z3_replayer::imp { __int64 m_int64; __uint64 m_uint64; double m_double; + float m_float; size_t m_ptr; size_t_map m_heap; svector m_cmds; - enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY }; + enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY, FLOAT }; struct value { value_kind m_kind; @@ -54,6 +55,7 @@ struct z3_replayer::imp { double m_double; char const * m_str; void * m_obj; + float m_float; }; value():m_kind(OBJECT), m_int(0) {} value(void * obj):m_kind(OBJECT), m_obj(obj) {} @@ -61,6 +63,7 @@ struct z3_replayer::imp { value(value_kind k, __uint64 u):m_kind(k), m_uint(u) {} value(value_kind k, __int64 i):m_kind(k), m_int(i) {} value(value_kind k, double d):m_kind(k), m_double(d) {} + value(value_kind k, float f):m_kind(k), m_float(f) {} }; svector m_args; @@ -85,9 +88,12 @@ struct z3_replayer::imp { case UINT64: out << v.m_uint; break; + case FLOAT: + out << v.m_float; + break; case DOUBLE: out << v.m_double; - break; + break; case STRING: out << v.m_str; break; @@ -219,6 +225,19 @@ struct z3_replayer::imp { return curr() == '-' || curr() == '.' || ('0' <= curr() && curr() <= '9') || curr() == 'e' || curr() == 'E'; } + void read_float() { + m_string.reset(); + while (is_double_char()) { + m_string.push_back(curr()); + next(); + } + if (m_string.empty()) + throw z3_replayer_exception("invalid float"); + m_string.push_back(0); + char * ptr; + m_float = strtof(m_string.begin(), &ptr); + } + void read_double() { m_string.reset(); while (is_double_char()) { @@ -407,12 +426,18 @@ struct z3_replayer::imp { TRACE("z3_replayer", tout << "[" << m_line << "] " << "U " << m_uint64 << "\n";); m_args.push_back(value(UINT64, m_uint64)); break; + case 'F': + // push float + next(); skip_blank(); read_float(); + TRACE("z3_replayer", tout << "[" << m_line << "] " << "F " << m_float << "\n";); + m_args.push_back(value(FLOAT, m_float)); + break; case 'D': // push double next(); skip_blank(); read_double(); TRACE("z3_replayer", tout << "[" << m_line << "] " << "D " << m_double << "\n";); m_args.push_back(value(DOUBLE, m_double)); - break; + break; case 'p': case 's': case 'u': @@ -516,6 +541,12 @@ struct z3_replayer::imp { return m_args[pos].m_uint; } + float get_float(unsigned pos) const { + if (pos >= m_args.size() || m_args[pos].m_kind != FLOAT) + throw_invalid_reference(); + return m_args[pos].m_float; + } + double get_double(unsigned pos) const { if (pos >= m_args.size() || m_args[pos].m_kind != DOUBLE) throw_invalid_reference(); @@ -653,6 +684,10 @@ __uint64 z3_replayer::get_uint64(unsigned pos) const { return m_imp->get_uint64(pos); } +float z3_replayer::get_float(unsigned pos) const { + return m_imp->get_float(pos); +} + double z3_replayer::get_double(unsigned pos) const { return m_imp->get_double(pos); } diff --git a/src/api/z3_replayer.h b/src/api/z3_replayer.h index 6de4bdb39..6320068ad 100644 --- a/src/api/z3_replayer.h +++ b/src/api/z3_replayer.h @@ -42,6 +42,7 @@ public: unsigned get_uint(unsigned pos) const; __int64 get_int64(unsigned pos) const; __uint64 get_uint64(unsigned pos) const; + float get_float(unsigned pos) const; double get_double(unsigned pos) const; bool get_bool(unsigned pos) const; Z3_string get_str(unsigned pos) const; From 97df505dbaed0e9c51cd756b5d84620e91ba2bb3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 15:23:27 +0000 Subject: [PATCH 129/646] MPF consistency fix Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 245120866..cc4b3a35a 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -336,7 +336,7 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;); } -void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, int exponent) { +void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent) { // Assumption: this represents (sign * -1) * (significand/2^sbits) * 2^exponent. o.ebits = ebits; o.sbits = sbits; From a28454d95e314d17beb4ca21c2eb51b3ed726ecb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 15:24:36 +0000 Subject: [PATCH 130/646] FPA: sort names consistency fix Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast_smt2_pp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index a9e223c55..982b80d37 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -396,7 +396,7 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) { unsigned ebits = get_futil().get_ebits(s); unsigned sbits = get_futil().get_sbits(s); ptr_buffer fs; - fs.push_back(mk_string(m, "FP")); + fs.push_back(mk_string(m, "FloatingPoint")); fs.push_back(mk_unsigned(m, ebits)); fs.push_back(mk_unsigned(m, sbits)); return mk_seq1(m, fs.begin(), fs.end(), f2f(), "_"); From 09247d2e29563d2f2a5926c85816ac1c2fb69187 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 18:44:41 +0000 Subject: [PATCH 131/646] FPA theory and API overhaul Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 14 +- src/api/api_fpa.cpp | 354 +++++++++++++++++--- src/api/dotnet/Context.cs | 14 +- src/api/z3_api.h | 3 +- src/api/z3_fpa.h | 641 ++++++++++++++++++++++++++---------- src/ast/float_decl_plugin.h | 39 ++- src/smt/theory_fpa.cpp | 200 ++++++----- src/smt/theory_fpa.h | 8 +- src/util/mpf.h | 2 +- 9 files changed, 944 insertions(+), 331 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 2fbf42cca..a47835904 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -124,6 +124,7 @@ SYMBOL = 9 PRINT_MODE = 10 ERROR_CODE = 11 DOUBLE = 12 +FLOAT = 13 FIRST_OBJ_ID = 100 @@ -131,28 +132,28 @@ def is_obj(ty): return ty >= FIRST_OBJ_ID Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double', - STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol', + FLOAT : 'float', STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol', PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code' } Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong', - UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double', + UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double', FLOAT : 'ctypes.c_float', STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol', PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint' } # Mapping to .NET types Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', INT64 : 'Int64', UINT64 : 'UInt64', DOUBLE : 'double', - STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr', + FLOAT : 'float', STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr', PRINT_MODE : 'uint', ERROR_CODE : 'uint' } # Mapping to Java types Type2Java = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', - STRING : 'String', STRING_PTR : 'StringPtr', + FLOAT : 'float', STRING : 'String', STRING_PTR : 'StringPtr', BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int'} Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', INT64 : 'jlong', UINT64 : 'jlong', DOUBLE : 'jdouble', - STRING : 'jstring', STRING_PTR : 'jobject', + FLOAT : 'jfloat', STRING : 'jstring', STRING_PTR : 'jobject', BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} @@ -927,6 +928,9 @@ def def_API(name, result, params): elif ty == DOUBLE: log_c.write(" D(a%s);\n" % i) exe_c.write("in.get_double(%s)" % i) + elif ty == FLOAT: + log_c.write(" D(a%s);\n" % i) + exe_c.write("in.get_float(%s)" % i) elif ty == BOOL: log_c.write(" I(a%s);\n" % i) exe_c.write("in.get_bool(%s)" % i) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index bbf27d25d..89b278c91 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -7,6 +7,7 @@ Module Name: Abstract: + Additional APIs for floating-point arithmetic (FP). Author: @@ -31,7 +32,7 @@ extern "C" { Z3_sort r = of_sort(ctx->float_util().mk_rm_sort()); RETURN_Z3(r); Z3_CATCH_RETURN(0); - } + } Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c) { @@ -44,10 +45,20 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_rne(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rne(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_even()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c) { Z3_TRY; - LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + LOG_Z3_mk_fpa_round_nearest_ties_to_away(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_away()); @@ -55,10 +66,20 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_rna(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rna(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_away()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c) { Z3_TRY; - LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + LOG_Z3_mk_fpa_round_toward_positive(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive()); @@ -66,10 +87,20 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_rtp(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rtp(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c) { Z3_TRY; - LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + LOG_Z3_mk_fpa_round_toward_negative(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative()); @@ -77,10 +108,20 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_rtn(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rtn(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c) { Z3_TRY; - LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); + LOG_Z3_mk_fpa_round_toward_zero(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero()); @@ -88,6 +129,16 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_rtz(Z3_context c) { + Z3_TRY; + LOG_Z3_mk_fpa_rtz(c); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero()); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits) { Z3_TRY; @@ -102,35 +153,35 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_half(Z3_context c) { return Z3_mk_fpa_sort(c, 5, 11); } - Z3_sort Z3_API Z3_mk_fpa_sort_16(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_16(Z3_context c) { return Z3_mk_fpa_sort(c, 5, 11); } - Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_single(Z3_context c) { return Z3_mk_fpa_sort(c, 8, 24); } - Z3_sort Z3_API Z3_mk_fpa_sort_32(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_32(Z3_context c) { return Z3_mk_fpa_sort(c, 8, 24); } - Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_double(Z3_context c) { return Z3_mk_fpa_sort(c, 11, 53); } - Z3_sort Z3_API Z3_mk_fpa_sort_64(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_64(Z3_context c) { return Z3_mk_fpa_sort(c, 11, 53); } - Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(Z3_context c) { return Z3_mk_fpa_sort(c, 15, 113); } - Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c) { + Z3_sort Z3_API Z3_mk_fpa_sort_128(Z3_context c) { return Z3_mk_fpa_sort(c, 15, 113); } @@ -164,6 +215,28 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast sig, Z3_ast exp) { + Z3_TRY; + LOG_Z3_mk_fpa_fp(c, sgn, sig, exp); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_numeral_float(Z3_context c, float v, Z3_sort ty) { + Z3_TRY; + LOG_Z3_mk_fpa_numeral_float(c, v, ty); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + scoped_mpf tmp(ctx->float_util().fm()); + ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_numeral_double(Z3_context c, double v, Z3_sort ty) { Z3_TRY; LOG_Z3_mk_fpa_numeral_double(c, v, ty); @@ -175,6 +248,51 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } + + Z3_ast Z3_API Z3_mk_fpa_numeral_int(Z3_context c, signed v, Z3_sort ty) { + Z3_TRY; + LOG_Z3_mk_fpa_numeral_int(c, v, ty); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + scoped_mpf tmp(ctx->float_util().fm()); + ctx->float_util().fm().set(tmp, + ctx->float_util().get_ebits(to_sort(ty)), + ctx->float_util().get_sbits(to_sort(ty)), + v); + Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, bool sgn, unsigned sig, signed exp, Z3_sort ty) { + Z3_TRY; + LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + scoped_mpf tmp(ctx->float_util().fm()); + ctx->float_util().fm().set(tmp, + ctx->float_util().get_ebits(to_sort(ty)), + ctx->float_util().get_sbits(to_sort(ty)), + sgn, sig, exp); + Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, bool sgn, __uint64 sig, __int64 exp, Z3_sort ty) { + Z3_TRY; + LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + scoped_mpf tmp(ctx->float_util().fm()); + ctx->float_util().fm().set(tmp, + ctx->float_util().get_ebits(to_sort(ty)), + ctx->float_util().get_sbits(to_sort(ty)), + sgn, sig, exp); + Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t) { Z3_TRY; @@ -265,20 +383,40 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_mk_fpa_eq(Z3_context c, Z3_ast t1, Z3_ast t2) { + + Z3_ast Z3_API Z3_mk_fpa_round_to_integral(Z3_context c, Z3_ast rm, Z3_ast t) { Z3_TRY; - LOG_Z3_mk_fpa_eq(c, t1, t2); + LOG_Z3_mk_fpa_round_to_integral(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_float_eq(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_round_to_integral(to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_min(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_min(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_max(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_max(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_max(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_le(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; - LOG_Z3_mk_fpa_le(c, t1, t2); + LOG_Z3_mk_fpa_leq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_le(to_expr(t1), to_expr(t2))); @@ -296,9 +434,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_ge(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; - LOG_Z3_mk_fpa_ge(c, t1, t2); + LOG_Z3_mk_fpa_geq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_ge(to_expr(t1), to_expr(t2))); @@ -315,6 +453,16 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } + + Z3_ast Z3_API Z3_mk_fpa_eq(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_TRY; + LOG_Z3_mk_fpa_eq(c, t1, t2); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_float_eq(to_expr(t1), to_expr(t2))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } Z3_ast Z3_API Z3_mk_fpa_is_normal(Z3_context c, Z3_ast t) { Z3_TRY; @@ -346,9 +494,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_is_inf(Z3_context c, Z3_ast t) { + Z3_ast Z3_API Z3_mk_fpa_is_infinite(Z3_context c, Z3_ast t) { Z3_TRY; - LOG_Z3_mk_fpa_is_inf(c, t); + LOG_Z3_mk_fpa_is_infinite(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); Z3_ast r = of_ast(ctx->float_util().mk_is_inf(to_expr(t))); @@ -366,40 +514,142 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2) { + Z3_ast Z3_API Z3_mk_fpa_is_negative(Z3_context c, Z3_ast t) { Z3_TRY; - LOG_Z3_mk_fpa_min(c, t1, t2); + LOG_Z3_mk_fpa_is_negative(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_min(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); - Z3_CATCH_RETURN(0); - } - - Z3_ast Z3_API Z3_mk_fpa_max(Z3_context c, Z3_ast t1, Z3_ast t2) { - Z3_TRY; - LOG_Z3_mk_fpa_max(c, t1, t2); - RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_max(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->float_util().mk_is_negative(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_convert(Z3_context c, Z3_sort s, Z3_ast rm, Z3_ast t) { + Z3_ast Z3_API Z3_mk_fpa_is_positive(Z3_context c, Z3_ast t) { Z3_TRY; - LOG_Z3_mk_fpa_convert(c, s, rm, t); + LOG_Z3_mk_fpa_is_positive(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - expr * args [2] = { to_expr(rm), to_expr(t) }; - Z3_ast r = of_ast(ctx->m().mk_app(ctx->float_util().get_family_id(), OP_FLOAT_TO_FP, - to_sort(s)->get_num_parameters(), to_sort(s)->get_parameters(), - 2, args)); + Z3_ast r = of_ast(ctx->float_util().mk_is_positive(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t) { + + Z3_ast Z3_API Z3_mk_fpa_to_fp_bv(Z3_context c, Z3_ast bv, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_bv(c, bv, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!ctx->bvutil().is_bv(to_expr(bv)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(bv))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_fp_float(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_float(c, rm, t, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!fu.is_rm(to_expr(rm)) || + !fu.is_float(to_expr(t)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_fp_real(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_real(c, rm, t, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!fu.is_rm(to_expr(rm)) || + !ctx->autil().is_real(to_expr(t)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_fp_signed(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_signed(c, rm, t, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!fu.is_rm(to_expr(rm)) || + !ctx->bvutil().is_bv(to_expr(t)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_fp_unsigned(Z3_context c, Z3_ast rm, Z3_ast t, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_unsigned(c, rm, t, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!fu.is_rm(to_expr(rm)) || + !ctx->bvutil().is_bv(to_expr(t)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp_unsigned(to_sort(s), to_expr(rm), to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_ubv(Z3_context c, Z3_ast rm, Z3_ast t, unsigned sz) { + Z3_TRY; + LOG_Z3_mk_fpa_to_ubv(c, rm, t, sz); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_to_ubv(to_expr(rm), to_expr(t), sz)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_sbv(Z3_context c, Z3_ast rm, Z3_ast t, unsigned sz) { + Z3_TRY; + LOG_Z3_mk_fpa_to_sbv(c, rm, t, sz); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_to_sbv(to_expr(rm), to_expr(t), sz)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_real(Z3_context c, Z3_ast t) { + Z3_TRY; + LOG_Z3_mk_fpa_to_real(c, t); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + Z3_ast r = of_ast(ctx->float_util().mk_to_real(to_expr(t))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_to_ieee_bv(c, t); RESET_ERROR_CODE(); @@ -409,4 +659,22 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(Z3_context c, Z3_ast rm, Z3_ast sig, Z3_ast exp, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_to_fp_real_int(c, rm, sig, exp, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + float_util & fu = ctx->float_util(); + if (!fu.is_rm(to_expr(rm)) || + !ctx->autil().is_real(to_expr(sig)) || + !ctx->autil().is_int(to_expr(exp)) || + !fu.is_float(to_sort(s))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(sig), to_expr(exp))); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + }; diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 87090dcc9..69855fc4f 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3661,10 +3661,10 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - public BoolExpr MkFPLe(FPExpr t1, FPExpr t2) + public BoolExpr MkFPLEq(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); - return new BoolExpr(this, Native.Z3_mk_fpa_le(this.nCtx, t1.NativeObject, t2.NativeObject)); + return new BoolExpr(this, Native.Z3_mk_fpa_leq(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// @@ -3683,10 +3683,10 @@ namespace Microsoft.Z3 /// /// floating point term /// floating point term - public BoolExpr MkFPGe(FPExpr t1, FPExpr t2) + public BoolExpr MkFPGEq(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); - return new BoolExpr(this, Native.Z3_mk_fpa_ge(this.nCtx, t1.NativeObject, t2.NativeObject)); + return new BoolExpr(this, Native.Z3_mk_fpa_geq(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// @@ -3737,7 +3737,7 @@ namespace Microsoft.Z3 public BoolExpr MkFPIsInf(FPExpr t) { Contract.Ensures(Contract.Result() != null); - return new BoolExpr(this, Native.Z3_mk_fpa_is_inf(this.nCtx, t.NativeObject)); + return new BoolExpr(this, Native.Z3_mk_fpa_is_infinite(this.nCtx, t.NativeObject)); } /// @@ -3782,10 +3782,10 @@ namespace Microsoft.Z3 /// floating point sort /// floating point rounding mode term /// floating point term - public FPExpr MkFPConvert(FPSort s, FPRMExpr rm, FPExpr t) + public FPExpr MkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) { Contract.Ensures(Contract.Result() != null); - return new FPExpr(this, Native.Z3_mk_fpa_convert(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); } #endregion diff --git a/src/api/z3_api.h b/src/api/z3_api.h index e4bb4bd1d..776e4e9fe 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1700,8 +1700,7 @@ extern "C" { /** \brief Create the real type. - This type is not a floating point number. - Z3 does not have support for floating point numbers yet. + Note that this type is not a floating point number. def_API('Z3_mk_real_sort', SORT, (_in(CONTEXT), )) */ diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 50ad49590..48d3e790d 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -7,7 +7,7 @@ Module Name: Abstract: - Additional APIs for floating-point arithmetic (FPA). + Additional APIs for floating-point arithmetic (FP). Author: @@ -36,7 +36,7 @@ extern "C" { /*@{*/ /** - \brief Create a rounding mode sort. + \brief Create the RoundingMode sort. \param c logical context. @@ -45,7 +45,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(__in Z3_context c); /** - \brief Create a numeral of rounding mode sort which represents the NearestTiesToEven rounding mode. + \brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. \param c logical context. @@ -54,7 +54,16 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(__in Z3_context c); /** - \brief Create a numeral of rounding mode sort which represents the NearestTiesToAway rounding mode. + \brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. + + \param c logical context. + + def_API('Z3_mk_fpa_rne', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_rne(__in Z3_context c); + + /** + \brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. \param c logical context. @@ -63,25 +72,52 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(__in Z3_context c); /** - \brief Create a numeral of rounding mode sort which represents the TowardPositive rounding mode. + \brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + + \param c logical context. + + def_API('Z3_mk_fpa_rna', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_rna(__in Z3_context c); + + /** + \brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. \param c logical context. def_API('Z3_mk_fpa_round_toward_positive', AST, (_in(CONTEXT),)) */ - Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c); + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(__in Z3_context c); /** - \brief Create a numeral of rounding mode sort which represents the TowardNegative rounding mode. + \brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. + + \param c logical context. + + def_API('Z3_mk_fpa_rtp', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_rtp(__in Z3_context c); + + /** + \brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. \param c logical context. def_API('Z3_mk_fpa_round_toward_negative', AST, (_in(CONTEXT),)) */ - Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c); + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(__in Z3_context c); /** - \brief Create a numeral of rounding mode sort which represents the TowardZero rounding mode. + \brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. + + \param c logical context. + + def_API('Z3_mk_fpa_rtn', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_rtn(__in Z3_context c); + + /** + \brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. \param c logical context. @@ -89,14 +125,21 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(__in Z3_context c); - - /** - \brief Create a floating point sort. + \brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits + + def_API('Z3_mk_fpa_rtz', AST, (_in(CONTEXT),)) + */ + Z3_ast Z3_API Z3_mk_fpa_rtz(__in Z3_context c); + + /** + \brief Create a FloatingPoint sort. + + \param c logical context. + \param ebits number of exponent bits. + \param sbits number of significand bits. \remark ebits must be larger than 1 and sbits must be larger than 2. @@ -105,85 +148,61 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_sort(__in Z3_context c, __in unsigned ebits, __in unsigned sbits); /** - \brief Create the half-precision (16-bit) floating point sort. + \brief Create the half-precision (16-bit) FloatingPoint sort. \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits - - \remark ebits must be larger than 1 and sbits must be larger than 2. def_API('Z3_mk_fpa_sort_half', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_half(__in Z3_context c); /** - \brief Create the half-precision (16-bit) floating point sort. + \brief Create the half-precision (16-bit) FloatingPoint sort. - \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits + \param c logical context. - \remark ebits must be larger than 1 and sbits must be larger than 2. - - def_API('Z3_mk_fpa_sort_16', SORT, (_in(CONTEXT),)) + def_API('Z3_mk_fpa_sort_16', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_16(__in Z3_context c); /** - \brief Create the single-precision (32-bit) floating point sort. + \brief Create the single-precision (32-bit) FloatingPoint sort. - \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits - - \remark ebits must be larger than 1 and sbits must be larger than 2. + \param c logical context. def_API('Z3_mk_fpa_sort_single', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_single(__in Z3_context c); /** - \brief Create the single-precision (32-bit) floating point sort. + \brief Create the single-precision (32-bit) FloatingPoint sort. - \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits + \param c logical context. - \remark ebits must be larger than 1 and sbits must be larger than 2. - - def_API('Z3_mk_fpa_sort_32', SORT, (_in(CONTEXT),)) + def_API('Z3_mk_fpa_sort_32', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_32(__in Z3_context c); /** - \brief Create the double-precision (64-bit) floating point sort. + \brief Create the double-precision (64-bit) FloatingPoint sort. \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits - - \remark ebits must be larger than 1 and sbits must be larger than 2. def_API('Z3_mk_fpa_sort_double', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_double(__in Z3_context c); /** - \brief Create the double-precision (64-bit) floating point sort. + \brief Create the double-precision (64-bit) FloatingPoint sort. - \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits + \param c logical context. - \remark ebits must be larger than 1 and sbits must be larger than 2. - - def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),)) + def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_64(__in Z3_context c); /** - \brief Create the quadruple-precision (128-bit) floating point sort. + \brief Create the quadruple-precision (128-bit) FloatingPoint sort. \param c logical context. \param ebits number of exponent bits @@ -196,15 +215,15 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(__in Z3_context c); /** - \brief Create the quadruple-precision (128-bit) floating point sort. + \brief Create the quadruple-precision (128-bit) FloatingPoint sort. - \param c logical context. - \param ebits number of exponent bits - \param sbits number of significand bits + \param c logical context. + \param ebits number of exponent bits + \param sbits number of significand bits - \remark ebits must be larger than 1 and sbits must be larger than 2. + \remark ebits must be larger than 1 and sbits must be larger than 2. - def_API('Z3_mk_fpa_sort_128', SORT, (_in(CONTEXT),)) + def_API('Z3_mk_fpa_sort_128', SORT, (_in(CONTEXT),)) */ Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c); @@ -219,7 +238,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_nan(__in Z3_context c, __in Z3_sort s); /** - \brief Create a floating point infinity of sort s. + \brief Create a floating-point infinity of sort s. \param c logical context. \param s target sort @@ -232,29 +251,64 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_inf(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); /** - \brief Create a floating point zero of sort s. + \brief Create a floating-point zero of sort s. - \param c logical context. - \param s target sort - \param negative indicates whether the result should be negative + \param c logical context. + \param s target sort + \param negative indicates whether the result should be negative - When \c negative is true, -zero will be generated instead of +zero. + When \c negative is true, -zero will be generated instead of +zero. - def_API('Z3_mk_fpa_zero', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) + def_API('Z3_mk_fpa_zero', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) */ Z3_ast Z3_API Z3_mk_fpa_zero(__in Z3_context c, __in Z3_sort s, __in Z3_bool negative); /** - \brief Create a numeral of floating point sort from a double. + \brief Create an expression of FloatingPoint sort from three bit-vector expressions. + + Note that \c sign is required to be a bit-vector of size 1. Significand and exponent + are required to be greater than 1 and 2 respectively. The FloatingPoint sort + of the resulting expression is automatically determined from the bit-vector sizes + of the arguments. + + \params c logical context. + \params sgn sign + \params sig significand + \params exp exponent + + def_API('Z3_mk_fpa_fp', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_fp(__in Z3_context c, __in Z3_ast sgn, __in Z3_ast sig, __in Z3_ast exp); + + /** + \brief Create a numeral of FloatingPoint sort from a float. + + This function is used to create numerals that fit in a float value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. + + \params c logical context. + \params v value. + \params ty sort. + + ty must be a FloatingPoint sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_fpa_numeral_float', AST, (_in(CONTEXT), _in(FLOAT), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_numeral_float(__in Z3_context c, __in float v, __in Z3_sort ty); + + /** + \brief Create a numeral of FloatingPoint sort from a double. - This function can be use to create numerals that fit in a double value. + This function is used to create numerals that fit in a double value. It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. \params c logical context. \params v value. \params ty sort. - ty must be a floating point sort + ty must be a FloatingPoint sort \sa Z3_mk_numeral @@ -262,13 +316,57 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_numeral_double(__in Z3_context c, __in double v, __in Z3_sort ty); + /** + \brief Create a numeral of FloatingPoint sort from a signed integer. + + \params c logical context. + \params v value. + + ty must be a FloatingPoint sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_fpa_numeral_int', AST, (_in(CONTEXT), _in(INT), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_numeral_int(__in Z3_context c, __in signed v, Z3_sort ty); + + /** + \brief Create a numeral of FloatingPoint sort from a sign bit and two integers. + + \params c logical context. + \params sgn sign bit (true == negative). + \params sig significand. + \params exp exponent. + + ty must be a FloatingPoint sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_fpa_numeral_uint_int', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(INT), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(__in Z3_context c, __in bool sgn, __in unsigned sig, __in signed exp, Z3_sort ty); + + /** + \brief Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + + \params c logical context. + \params sgn sign bit (true == negative). + \params sig significand. + \params exp exponent. + + ty must be a FloatingPoint sort + + \sa Z3_mk_numeral + + def_API('Z3_mk_fpa_numeral_uint64_int64', AST, (_in(CONTEXT), _in(BOOL), _in(UINT64), _in(INT64), _in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(__in Z3_context c, __in bool sgn, __in __uint64 sig, __in __int64 exp, Z3_sort ty); + /** \brief Floating-point absolute value \param c logical context. - \param t floating-point term. - - t must have floating point sort. + \param t term of FloatingPoint sort. def_API('Z3_mk_fpa_abs', AST, (_in(CONTEXT),_in(AST))) */ @@ -278,9 +376,7 @@ extern "C" { \brief Floating-point negation \param c logical context. - \param t floating-point term. - - t must have floating point sort. + \param t term of FloatingPoint sort. def_API('Z3_mk_fpa_neg', AST, (_in(CONTEXT),_in(AST))) */ @@ -290,11 +386,11 @@ extern "C" { \brief Floating-point addition \param c logical context. - \param rm rounding mode - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. + rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_add', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -304,11 +400,11 @@ extern "C" { \brief Floating-point subtraction \param c logical context. - \param rm rounding mode - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. + rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_sub', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -318,11 +414,11 @@ extern "C" { \brief Floating-point multiplication \param c logical context. - \param rm rounding mode - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - rm must be of FPA rounding mode sort, t1 and t2 must have the same floating point sort. + rm must be of RoundingMode sort, t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_mul', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -332,11 +428,11 @@ extern "C" { \brief Floating-point division \param c logical context. - \param rm rounding mode - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - The nodes rm must be of FPA rounding mode sort t1 and t2 must have the same floating point sort. + The nodes rm must be of RoundingMode sort t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_div', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST))) */ @@ -346,13 +442,13 @@ extern "C" { \brief Floating-point fused multiply-add. \param c logical context. - \param rm rounding mode - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. The result is round((t1 * t2) + t3) - rm must be of FPA rounding mode sort, t1, t2, and t3 must have the same floating point sort. + rm must be of RoundingMode sort, t1, t2, and t3 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_fma', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(AST))) */ @@ -362,10 +458,10 @@ extern "C" { \brief Floating-point square root \param c logical context. - \param rm rounding mode - \param t floating-point term. + \param rm term of RoundingMode sort. + \param t term of FloatingPoint sort. - rm must be of FPA rounding mode sort, t must have floating point sort. + rm must be of RoundingMode sort, t must have FloatingPoint sort. def_API('Z3_mk_fpa_sqrt', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ @@ -375,198 +471,387 @@ extern "C" { \brief Floating-point remainder \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t1 and t2 must have the same floating point sort. + t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_rem', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_rem(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); - + Z3_ast Z3_API Z3_mk_fpa_rem(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + /** - \brief Floating-point equality + \brief Floating-point roundToIntegral. Rounds a floating-point number to + the closest integer, again represented as a floating-point number. \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param rm term of RoundingMode sort. + \param t term of FloatingPoint sort. - Note that this is IEEE 754 equality (as opposed to SMT-LIB =). + t must be of FloatingPoint sort. - t1 and t2 must have the same floating point sort. - - def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST))) - */ - Z3_ast Z3_API Z3_mk_fpa_eq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + def_API('Z3_mk_fpa_round_to_integral', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_round_to_integral(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t); + + /** + \brief Minimum of floating-point numbers + + \param c logical context. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. + + t1, t2 must have the same FloatingPoint sort. + + def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Maximum of floating-point numbers + + \param c logical context. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. + + t1, t2 must have the same FloatingPoint sort. + + def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** \brief Floating-point less than or equal \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t1 and t2 must have the same floating point sort. + t1 and t2 must have the same FloatingPoint sort. - def_API('Z3_mk_fpa_le', AST, (_in(CONTEXT),_in(AST),_in(AST))) + def_API('Z3_mk_fpa_leq', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_le(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + Z3_ast Z3_API Z3_mk_fpa_leq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** \brief Floating-point less-than \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t1 and t2 must have the same floating point sort. + t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_lt', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_lt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); - - + /** \brief Floating-point greater than or equal \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t1 and t2 must have the same floating point sort. + t1 and t2 must have the same FloatingPoint sort. - def_API('Z3_mk_fpa_ge', AST, (_in(CONTEXT),_in(AST),_in(AST))) + def_API('Z3_mk_fpa_geq', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_ge(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + Z3_ast Z3_API Z3_mk_fpa_geq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** \brief Floating-point greater-than \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t1 and t2 must have the same floating point sort. + t1 and t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_gt', AST, (_in(CONTEXT),_in(AST),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_gt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); - + /** - \brief Predicate indicating whether t is a normal floating point number + \brief Floating-point equality \param c logical context. - \param t floating-point term. + \param t1 term of FloatingPoint sort. + \param t2 term of FloatingPoint sort. - t must have floating point sort. + Note that this is IEEE 754 equality (as opposed to SMT-LIB =). + + t1 and t2 must have the same FloatingPoint sort. + + def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_eq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + + /** + \brief Predicate indicating whether t is a normal floating-point number. + + \param c logical context. + \param t term of FloatingPoint sort. + + t must have FloatingPoint sort. def_API('Z3_mk_fpa_is_normal', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_is_normal(__in Z3_context c, __in Z3_ast t); /** - \brief Predicate indicating whether t is a subnormal floating point number + \brief Predicate indicating whether t is a subnormal floating-point number. \param c logical context. - \param t floating-point term. + \param t term of FloatingPoint sort. - t must have floating point sort. + t must have FloatingPoint sort. def_API('Z3_mk_fpa_is_subnormal', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_is_subnormal(__in Z3_context c, __in Z3_ast t); /** - \brief Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. + \brief Predicate indicating whether t is a floating-point number with zero value, i.e., +zero or -zero. \param c logical context. - \param t floating-point term. + \param t term of FloatingPoint sort. - t must have floating point sort. + t must have FloatingPoint sort. def_API('Z3_mk_fpa_is_zero', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_is_zero(__in Z3_context c, __in Z3_ast t); /** - \brief Predicate indicating whether t is a floating point number representing +Inf or -Inf + \brief Predicate indicating whether t is a floating-point number representing +oo or -oo. \param c logical context. - \param t floating-point term. + \param t term of FloatingPoint sort. - t must have floating point sort. + t must have FloatingPoint sort. - def_API('Z3_mk_fpa_is_inf', AST, (_in(CONTEXT),_in(AST))) + def_API('Z3_mk_fpa_is_infinite', AST, (_in(CONTEXT),_in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_is_inf(__in Z3_context c, __in Z3_ast t); + Z3_ast Z3_API Z3_mk_fpa_is_infinite(__in Z3_context c, __in Z3_ast t); /** \brief Predicate indicating whether t is a NaN \param c logical context. - \param t floating-point term. + \param t term of FloatingPoint sort. - t must have floating point sort. + t must have FloatingPoint sort. def_API('Z3_mk_fpa_is_nan', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_is_nan(__in Z3_context c, __in Z3_ast t); /** - \brief Minimum of floating point numbers + \brief Predicate indicating whether t is a negative floating-point number. \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. + \param t term of FloatingPoint sort. - t1, t2 must have the same floating point sort. - - def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) - */ - Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); - - /** - \brief Maximum of floating point numbers + t must have FloatingPoint sort. - \param c logical context. - \param t1 floating-point term. - \param t2 floating-point term. - - t1, t2 must have the same floating point sort. - - def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST))) - */ - Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + def_API('Z3_mk_fpa_is_negative', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_negative(__in Z3_context c, __in Z3_ast t); /** - \brief Conversion of a floating point number to another floating-point sort s. - - Produces a term that represents the conversion of a floating-point term t to a different - floating point sort s. If necessary, rounding according to rm is applied. + \brief Predicate indicating whether t is a positive floating-point number. \param c logical context. + \param t term of FloatingPoint sort. + + t must have FloatingPoint sort. + + def_API('Z3_mk_fpa_is_positive', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_is_positive(__in Z3_context c, __in Z3_ast t); + + /** + \brief Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. + + Produces a term that represents the conversion of a bit-vector term bv to a + floating-point term of sort s. + + \param c logical context. + \param bv a bit-vector term. \param s floating-point sort. - \param rm rounding mode. - \param t floating-point term. - s must be a floating point sort, rm must have rounding mode sort, and t must have floating point sort. + s must be a FloatingPoint sort, t must be of bit-vector sort, and the bit-vector + size of bv, m, must be equal to ebits+sbits of s. The format of the bit-vector is + as defined by the IEEE 754-2008 interchange format and the resulting floating-point + sort (ebits, sbits) is automatically determined. - def_API('Z3_mk_fpa_convert', AST, (_in(CONTEXT),_in(SORT),_in(AST),_in(AST))) + def_API('Z3_mk_fpa_to_fp_bv', AST, (_in(CONTEXT),_in(AST),_in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_convert(__in Z3_context c, __in Z3_sort s, __in Z3_ast rm, __in Z3_ast t); + Z3_ast Z3_API Z3_mk_fpa_to_fp_bv(__in Z3_context c, __in Z3_ast bv, __in Z3_sort s); /** - \brief Conversion of a floating point term to a bit-vector term in IEEE754 format. + \brief Conversion of a floating-point term into another floating-point term of different floating-point sort. + + Produces a term that represents the conversion of a floating-point term t to a + floating-point term of sort s. If necessary, the result will be rounded according + to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param t term of FloatingPoint sort. + \param s floating-point sort. + + s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of floating-point sort. + + def_API('Z3_mk_fpa_to_fp_float', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_fp_float(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s); + + /** + \brief Conversion of a term of real sort into a term of FloatingPoint sort. + + Produces a term that represents the conversion of term t of real sort into a + floating-point term of sort s. If necessary, the result will be rounded according + to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param t term of Real sort. + \param s floating-point sort. + + s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort. + + def_API('Z3_mk_fpa_to_fp_real', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_fp_real(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s); + + /** + \brief Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. + + Produces a term that represents the conversion of the bit-vector term t into a + floating-point term of sort s. The bit-vector t is taken to be in signed + 2's complement format. If necessary, the result will be rounded according + to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param t term of bit-vector sort. + \param s floating-point sort. + + s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of bit-vector sort. + + def_API('Z3_mk_fpa_to_fp_signed', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_fp_signed(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s); + + /** + \brief Conversion of a 2's complement unsigned bit-vector term into a term of FloatingPoint sort. + + Produces a term that represents the conversion of the bit-vector term t into a + floating-point term of sort s. The bit-vector t is taken to be in unsigned + 2's complement format. If necessary, the result will be rounded according + to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param t term of bit-vector sort. + \param s floating-point sort. + + s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of bit-vector sort. + + def_API('Z3_mk_fpa_to_fp_unsigned', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_fp_unsigned(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in Z3_sort s); + + /** + \brief Conversion of a floating-point term into an unsigned bit-vector. + + Produces a term that represents the conversion of the floating-poiunt term t into a + bit-vector term in unsigned 2's complement format. If necessary, the result will be + rounded according to rounding mode rm. \param c logical context. - \param t floating-point term. + \param rm term of RoundingMode sort. + \param t term of FloatingPoint sort. + \param sz size of the resulting bit-vector. - t must have floating point sort. The size of the resulting bit-vector is automatically determined. + def_API('Z3_mk_fpa_to_ubv', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(UINT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_ubv(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in unsigned sz); + + /** + \brief Conversion of a floating-point term into a signed bit-vector. + + Produces a term that represents the conversion of the floating-poiunt term t into a + bit-vector term in signed 2's complement format. If necessary, the result will be + rounded according to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param t term of FloatingPoint sort. + \param sz size of the resulting bit-vector. + + def_API('Z3_mk_fpa_to_sbv', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(UINT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_sbv(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in unsigned sz); + + /** + \brief Conversion of a floating-point term into a real number. + + Produces a term that represents the conversion of the floating-poiunt term t into a + real number. Note that this type of conversion will often result in non-linear + constraints over real terms. + + \param c logical context. + \param t term of FloatingPoint sort. + + def_API('Z3_mk_fpa_to_real', AST, (_in(CONTEXT),_in(AST))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_real(__in Z3_context c, __in Z3_ast t); + + /** + @name Z3-specific extensions + */ + /*@{*/ + + /** + \brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. + + \param c logical context. + \param t term of FloatingPoint sort. + + t must have FloatingPoint sort. The size of the resulting bit-vector is automatically + determined. + + Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion + knows only one NaN and it will always produce the same bit-vector represenatation of + that NaN. def_API('Z3_mk_fpa_to_ieee_bv', AST, (_in(CONTEXT),_in(AST))) */ Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(__in Z3_context c, __in Z3_ast t); + /** + \brief Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. + + Produces a term that represents the conversion of sig * 2^exp into a + floating-point term of sort s. If necessary, the result will be rounded + according to rounding mode rm. + + \param c logical context. + \param rm term of RoundingMode sort. + \param sig significand term of Real sort. + \param exp exponent term of Real sort. + \param s floating-point sort. + + s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort. + + def_API('Z3_mk_fpa_to_fp_real_int', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(SORT))) + */ + Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(__in Z3_context c, __in Z3_ast rm, __in Z3_ast sig, __in Z3_ast exp, __in Z3_sort s); + + /*@}*/ /*@}*/ /*@}*/ diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 1598db9c3..cbcd706cd 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -263,9 +263,41 @@ public: bool is_zero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_zero(v); } bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } + + app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_FP, arg1, arg2, arg3); } + app * mk_to_fp(sort * s, expr * bv_t) { + SASSERT(is_float(s) && s->get_num_parameters() == 2); + return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 1, &bv_t); + } + app * mk_to_fp(sort * s, expr * rm, expr * t) { + SASSERT(is_float(s) && s->get_num_parameters() == 2); + expr * args[] = { rm, t }; + return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 2, args); + } + app * mk_to_fp(sort * s, expr * rm, expr * sig, expr * exp) { + SASSERT(is_float(s) && s->get_num_parameters() == 2); + expr * args[] = { rm, sig, exp }; + return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 3, args); + } + app * mk_to_fp_unsigned(sort * s, expr * rm, expr * t) { + SASSERT(is_float(s) && s->get_num_parameters() == 2); + expr * args[] = { rm, t }; + return m().mk_app(m_fid, OP_FLOAT_TO_FP_UNSIGNED, 2, s->get_parameters(), 2, args); + } bool is_to_fp(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } - + + app * mk_to_ubv(expr * rm, expr * t, unsigned sz) { + parameter ps[] = { parameter(sz) }; + expr * args[] = { rm, t }; + return m().mk_app(m_fid, OP_FLOAT_TO_UBV, 1, ps, 2, args); } + app * mk_to_sbv(expr * rm, expr * t, unsigned sz) { + parameter ps[] = { parameter(sz) }; + expr * args[] = { rm, t }; + return m().mk_app(m_fid, OP_FLOAT_TO_SBV, 1, ps, 2, args); + } + app * mk_to_real(expr * t) { return m().mk_app(m_fid, OP_FLOAT_TO_REAL, t); } + app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); } app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } @@ -276,7 +308,7 @@ public: app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); } app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); } app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); } - app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); } + app * mk_round_to_integral(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); } app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) { expr * args[4] = { arg1, arg2, arg3, arg4 }; return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args); @@ -306,6 +338,9 @@ public: app * mk_internal_to_ubv_unspecified(unsigned width); app * mk_internal_to_sbv_unspecified(unsigned width); app * mk_internal_to_real_unspecified(); + + bool is_wrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FLOAT_INTERNAL_BVWRAP); } + bool is_unwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP); } }; #endif diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index f7fd1de30..03a2e73bf 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -48,13 +48,11 @@ namespace smt { } else { sort * s = f->get_range(); - func_decl_ref w(m), u(m); - m_th.get_wrap(s, w, u); expr_ref bv(m); - bv = m.mk_app(w, m.mk_const(f)); + bv = m_th.wrap(m.mk_const(f)); unsigned bv_sz = m_th.m_bv_util.get_bv_size(bv); - unsigned ebits = m_th.m_float_util.get_ebits(f->get_range()); - unsigned sbits = m_th.m_float_util.get_sbits(f->get_range()); + unsigned ebits = m_th.m_float_util.get_ebits(s); + unsigned sbits = m_th.m_float_util.get_sbits(s); SASSERT(bv_sz == ebits + sbits); m_th.m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), m_bv_util.mk_extract(sbits - 2, 0, bv), @@ -76,12 +74,7 @@ namespace smt { } else { SASSERT(is_rm(f->get_range())); - - sort * s = f->get_range(); - func_decl_ref w(m), u(m); - m_th.get_wrap(s, w, u); - result = m.mk_app(w, m.mk_const(f)); - + result = m_th.wrap(m.mk_const(f)); m_rm_const2bv.insert(f, result); m.inc_ref(f); m.inc_ref(result); @@ -133,13 +126,15 @@ namespace smt { SASSERT(bv_sz == (m_ebits+m_sbits)); SASSERT(all_rat.is_int()); mpzm.set(all_bits, all_rat.to_mpq().numerator()); - + scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); mpzm.machine_div2k(all_bits, m_ebits + m_sbits - 1, sgn_z); mpzm.mod(all_bits, mpfm.m_powers2(m_ebits + m_sbits - 1), all_bits); mpzm.machine_div2k(all_bits, m_sbits - 1, exp_z); mpzm.mod(all_bits, mpfm.m_powers2(m_sbits - 1), all_bits); + + mpzm.set(sig_z, all_bits); TRACE("t_fpa_detail", tout << "sgn=" << mpzm.to_string(sgn_z) << " ; " << "sig=" << mpzm.to_string(sig_z) << " ; " << @@ -190,36 +185,53 @@ namespace smt { return result; } - void theory_fpa::get_wrap(sort * s, func_decl_ref & wrap, func_decl_ref & unwrap) - { - func_decl *w, *u; + app_ref theory_fpa::wrap(expr * e) { + SASSERT(!m_float_util.is_wrap(e)); + ast_manager & m = get_manager(); + context & ctx = get_context(); + sort * e_srt = m.get_sort(e); - if (!m_wraps.find(s, w) || !m_unwraps.find(s, u)) { - SASSERT(!m_wraps.contains(s)); - SASSERT(!m_unwraps.contains(s)); - ast_manager & m = get_manager(); - context & ctx = get_context(); + func_decl *w; + + if (!m_wraps.find(e_srt, w)) { + SASSERT(!m_wraps.contains(e_srt)); + sort * bv_srt = 0; - if (m_converter.is_rm(s)) + if (m_converter.is_rm(e_srt)) bv_srt = m_bv_util.mk_sort(3); else { - SASSERT(m_converter.is_float(s)); - unsigned ebits = m_float_util.get_ebits(s); - unsigned sbits = m_float_util.get_sbits(s); + SASSERT(m_converter.is_float(e_srt)); + unsigned ebits = m_float_util.get_ebits(e_srt); + unsigned sbits = m_float_util.get_sbits(e_srt); bv_srt = m_bv_util.mk_sort(ebits + sbits); } - w = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &s, bv_srt); + w = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt); + m_wraps.insert(e_srt, w); + m.inc_ref(w); + } + + return app_ref(m.mk_app(w, e), m); + } + + app_ref theory_fpa::unwrap(expr * e, sort * s) { + SASSERT(!m_float_util.is_unwrap(e)); + ast_manager & m = get_manager(); + context & ctx = get_context(); + sort * e_srt = m.get_sort(e); + + func_decl *u; + + if (!m_unwraps.find(e_srt, u)) { + SASSERT(!m_unwraps.contains(e_srt)); + sort * bv_srt = m.get_sort(e); u = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); - m_wraps.insert(s, w); m_unwraps.insert(s, u); - m.inc_ref(w); m.inc_ref(u); } - wrap = w; - unwrap = u; + return app_ref(m.mk_app(u, e), m); } expr_ref theory_fpa::convert_atom(expr * e) { @@ -235,32 +247,39 @@ namespace smt { expr_ref theory_fpa::convert_term(expr * e) { ast_manager & m = get_manager(); + TRACE("t_fpa_detail", tout << "converting: " << mk_ismt2_pp(e, m) << " sort is: " << mk_ismt2_pp(m.get_sort(e), m) << std::endl;); + context & ctx = get_context(); - expr_ref res(m); + expr_ref ec(m), res(m); proof_ref pr(m); - m_rw(e, res); - - SASSERT(is_app(res)); - - if (m_float_util.is_rm(e)) { - SASSERT(is_sort_of(m.get_sort(res), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(m_bv_util.get_bv_size(res) == 3); - ctx.internalize(res, false); - m_th_rw(res, res); + m_rw(e, ec); + + SASSERT(is_app(ec)); + app_ref eca(to_app(ec), m); + TRACE("t_fpa_detail", tout << "eca = " << mk_ismt2_pp(eca, m) << " sort is: " << mk_ismt2_pp(m.get_sort(eca), m) << std::endl;); + + if (m_float_util.is_rm(e)) { + expr_ref bv_rm(m); + bv_rm = eca; + TRACE("t_fpa_detail", tout << "bvrm = " << mk_ismt2_pp(bv_rm, m) << " sort is: " << mk_ismt2_pp(m.get_sort(bv_rm), m) << std::endl;); + SASSERT(is_sort_of(m.get_sort(bv_rm), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(m_bv_util.get_bv_size(bv_rm) == 3); + m_th_rw(bv_rm, res); } else if (m_float_util.is_float(e)) { - SASSERT(to_app(res)->get_family_id() == get_family_id()); - float_op_kind k = (float_op_kind)(to_app(res)->get_decl_kind()); + SASSERT(eca->get_family_id() == get_family_id()); + float_op_kind k = (float_op_kind)(eca->get_decl_kind()); + SASSERT(k == OP_FLOAT_TO_FP || k == OP_FLOAT_INTERNAL_BVUNWRAP); switch (k) { case OP_FLOAT_TO_FP: { - SASSERT(to_app(res)->get_num_args() == 3); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(to_app(res)->get_arg(2)), m_bv_util.get_family_id(), BV_SORT)); - + SASSERT(eca->get_num_args() == 3); + SASSERT(is_sort_of(m.get_sort(eca->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(eca->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(is_sort_of(m.get_sort(eca->get_arg(2)), m_bv_util.get_family_id(), BV_SORT)); + expr *sgn, *sig, *exp; expr_ref s_sgn(m), s_sig(m), s_exp(m); - m_converter.split_triple(res, sgn, sig, exp); + m_converter.split_triple(eca, sgn, sig, exp); m_th_rw(sgn, s_sgn); m_th_rw(sig, s_sig); m_th_rw(exp, s_exp); @@ -269,12 +288,13 @@ namespace smt { break; } default: - /* nothing */; + res = eca; } } else UNREACHABLE(); + SASSERT(res.get() != 0); return res; } @@ -292,6 +312,28 @@ namespace smt { return res; } + expr_ref theory_fpa::convert_unwrap(expr * e) { + SASSERT(m_float_util.is_unwrap(e)); + ast_manager & m = get_manager(); + sort * srt = m.get_sort(e); + expr_ref res(m); + if (m_float_util.is_rm(srt)) { + res = to_app(e)->get_arg(0); + } + else { + SASSERT(m_float_util.is_float(srt)); + unsigned ebits = m_float_util.get_ebits(srt); + unsigned sbits = m_float_util.get_sbits(srt); + expr * bv = to_app(e)->get_arg(0); + unsigned bv_sz = m_bv_util.get_bv_size(bv); + m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), + m_bv_util.mk_extract(sbits - 2, 0, bv), + m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), + res); + } + return res; + } + expr_ref theory_fpa::convert(expr * e) { ast_manager & m = get_manager(); @@ -306,7 +348,9 @@ namespace smt { return res; } else { - if (m.is_bool(e)) + if (m_float_util.is_unwrap(e)) + res = convert_unwrap(e); + else if (m.is_bool(e)) res = convert_atom(e); else if (m_float_util.is_float(e) || m_float_util.is_rm(e)) res = convert_term(e); @@ -452,34 +496,18 @@ namespace smt { if (m_float_util.is_rm(owner_sort)) { // For every RM term, we need to make sure that it's - // associated bit-vector is within the valid range. - // This also ensures that wrap(owner) is internalized. - func_decl_ref wrap(m), unwrap(m); - get_wrap(owner_sort, wrap, unwrap); - if (owner->get_decl() != unwrap) + // associated bit-vector is within the valid range. + if (!m_float_util.is_unwrap(owner)) { - expr_ref wrapped(m), valid(m), limit(m); - wrapped = m.mk_app(wrap, owner.get()); + expr_ref valid(m), limit(m); limit = m_bv_util.mk_numeral(4, 3); - valid = m_bv_util.mk_ule(wrapped, limit); + valid = m_bv_util.mk_ule(wrap(owner), limit); assert_cnstr(valid); } } - else if (m_float_util.is_float(owner_sort)) { - // For every FP term, we need to make sure that - // its wrapped version is also internalized so that - // we can build a model for it later. - func_decl_ref wrap(m), unwrap(m); - get_wrap(owner_sort, wrap, unwrap); - if (owner->get_decl() != unwrap) { - expr_ref wrapped(m); - wrapped = m.mk_app(wrap, owner.get()); - if (!ctx.e_internalized(wrapped)) - ctx.internalize(wrapped, false); - } - } - else - UNREACHABLE(); + + if (!ctx.relevancy() && !m_float_util.is_unwrap(owner)) + assert_cnstr(m.mk_eq(unwrap(wrap(owner), owner_sort), owner)); } void theory_fpa::new_eq_eh(theory_var x, theory_var y) { @@ -498,8 +526,7 @@ namespace smt { app * ye = get_enode(y)->get_owner(); if ((m.is_bool(xe) && m.is_bool(ye)) || - (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) - { + (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) { SASSERT(xe->get_decl()->get_family_id() == get_family_id()); return; } @@ -509,16 +536,13 @@ namespace smt { yc = convert(ye); expr_ref c(m); - + if (fu.is_float(xe) && fu.is_float(ye)) { - func_decl_ref wrap(m), unwrap(m); - get_wrap(m.get_sort(ye), wrap, unwrap); - if (ye->get_decl() == unwrap) - return; expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); + expr *y_sgn, *y_sig, *y_exp; m_converter.split_triple(yc, y_sgn, y_sig, y_exp); @@ -614,12 +638,10 @@ namespace smt { if (m_float_util.is_float(n) || m_float_util.is_rm(n)) { sort * s = m.get_sort(n); - func_decl_ref wrap(m), unwrap(m); - get_wrap(s, wrap, unwrap); - if (n->get_decl() != unwrap) { + if (!m_float_util.is_unwrap(n)) { expr_ref wrapped(m), c(m); - wrapped = m.mk_app(wrap, n); + wrapped = wrap(n); mpf_rounding_mode rm; scoped_mpf val(mpfm); if (m_float_util.is_rm_value(n, rm)) { @@ -633,15 +655,13 @@ namespace smt { SASSERT(is_app(bv_val_e)); SASSERT(to_app(bv_val_e)->get_num_args() == 3); app_ref bv_val_a(to_app(bv_val_e.get()), m); - c = m.mk_eq(wrapped, m_bv_util.mk_concat( m_bv_util.mk_concat( - bv_val_a->get_arg(0), - bv_val_a->get_arg(1)), - bv_val_a->get_arg(2))); + expr * args[] = { bv_val_a->get_arg(0), bv_val_a->get_arg(1), bv_val_a->get_arg(2) }; + c = m.mk_eq(wrapped, m_bv_util.mk_concat(3, args)); c = m.mk_and(c, mk_side_conditions()); assert_cnstr(c); } else { - c = m.mk_eq(m.mk_app(unwrap, wrapped), n); + c = m.mk_eq(unwrap(wrapped, m.get_sort(n)), n); assert_cnstr(c); } } @@ -696,11 +716,9 @@ namespace smt { return alloc(expr_wrapper_proc, owner); model_value_proc * res = 0; - func_decl_ref wrap(m), unwrap(m); - get_wrap(m.get_sort(owner), wrap, unwrap); app_ref wrapped(m); - wrapped = m.mk_app(wrap, owner); + wrapped = wrap(owner); CTRACE("t_fpa", !ctx.e_internalized(wrapped), tout << "Model dependency not internalized: " << diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index c21096ec0..c51b02c28 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -176,11 +176,15 @@ namespace smt { expr_ref convert_atom(expr * e); expr_ref convert_term(expr * e); expr_ref convert_conversion_term(expr * e); - void get_wrap(sort * s, func_decl_ref & wrap, func_decl_ref & unwrap); + expr_ref convert_unwrap(expr * e); + void add_trail(ast * a); void attach_new_th_var(enode * n); - void assert_cnstr(expr * e); + void assert_cnstr(expr * e); + + app_ref wrap(expr * e); + app_ref unwrap(expr * e, sort * s); }; }; diff --git a/src/util/mpf.h b/src/util/mpf.h index 83646f9f3..b919e0371 100644 --- a/src/util/mpf.h +++ b/src/util/mpf.h @@ -75,7 +75,7 @@ public: void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value); void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, char const * value); void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & significand, mpz const & exponent); - void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, int exponent); + void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, uint64 significand, mpf_exp_t exponent); void set(mpf & o, unsigned ebits, unsigned sbits, bool sign, mpz const & significand, mpf_exp_t exponent); void set(mpf & o, mpf const & x); void set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpf const & x); From 076c709453146ca526fa454340370bbf2ad2376b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 19:00:06 +0000 Subject: [PATCH 132/646] cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 03a2e73bf..bec9cf235 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -344,7 +344,7 @@ namespace smt { res = m_conversions.find(e); TRACE("t_fpa_detail", tout << "cached:" << std::endl; tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); + mk_ismt2_pp(res, m) << std::endl;); return res; } else { @@ -360,8 +360,8 @@ namespace smt { UNREACHABLE(); TRACE("t_fpa_detail", tout << "converted; caching:" << std::endl; - tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << - mk_ismt2_pp(res, m) << std::endl;); + tout << mk_ismt2_pp(e, m) << std::endl << " -> " << std::endl << + mk_ismt2_pp(res, m) << std::endl;); m_conversions.insert(e, res); m.inc_ref(res); @@ -539,10 +539,8 @@ namespace smt { if (fu.is_float(xe) && fu.is_float(ye)) { - expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); - expr *y_sgn, *y_sig, *y_exp; m_converter.split_triple(yc, y_sgn, y_sig, y_exp); From 6e849d7f73905d415a9fd4e07970a52baa1972bf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 19:16:02 +0000 Subject: [PATCH 133/646] FPA API cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 8 ++++---- src/api/z3_fpa.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 89b278c91..97225f0f3 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -264,7 +264,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, bool sgn, unsigned sig, signed exp, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, Z3_bool sgn, unsigned sig, signed exp, Z3_sort ty) { Z3_TRY; LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); @@ -273,13 +273,13 @@ extern "C" { ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), - sgn, sig, exp); + sgn != 0, sig, exp); Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, bool sgn, __uint64 sig, __int64 exp, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, Z3_bool sgn, __uint64 sig, __int64 exp, Z3_sort ty) { Z3_TRY; LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); @@ -288,7 +288,7 @@ extern "C" { ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), - sgn, sig, exp); + sgn != 0, sig, exp); Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 48d3e790d..61ee0bd7f 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -344,7 +344,7 @@ extern "C" { def_API('Z3_mk_fpa_numeral_uint_int', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(INT), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(__in Z3_context c, __in bool sgn, __in unsigned sig, __in signed exp, Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(__in Z3_context c, __in Z3_bool sgn, __in unsigned sig, __in signed exp, Z3_sort ty); /** \brief Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. @@ -360,7 +360,7 @@ extern "C" { def_API('Z3_mk_fpa_numeral_uint64_int64', AST, (_in(CONTEXT), _in(BOOL), _in(UINT64), _in(INT64), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(__in Z3_context c, __in bool sgn, __in __uint64 sig, __in __int64 exp, Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(__in Z3_context c, __in Z3_bool sgn, __in __uint64 sig, __in __int64 exp, Z3_sort ty); /** \brief Floating-point absolute value From b46d76cddbc889822ff5a1bdab7ab104113c9628 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 1 Jan 2015 19:16:44 +0000 Subject: [PATCH 134/646] New FPA C-API example Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 149 ++++++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 76 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 1aef9eb1b..920fdeb8c 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2595,16 +2595,20 @@ void substitute_vars_example() { Z3_del_context(ctx); } +/** + \brief Demonstrates some basic features of the FloatingPoint theory. +*/ + void fpa_example() { Z3_config cfg; Z3_context ctx; Z3_sort double_sort, rm_sort; - Z3_symbol symbol_rm, symbol_x, symbol_y, symbol_q; - Z3_ast rm, x, y, n, q, c1, c2, c3, c4, c5, c6; + Z3_symbol s_rm, s_x, s_y, s_x_plus_y; + Z3_ast rm, x, y, n, x_plus_y, c1, c2, c3, c4, c5, c6; + + printf("\nFPA-example\n"); + LOG_MSG("FPA-example"); - printf("\nfpa_example\n"); - LOG_MSG("fpa_example"); - cfg = Z3_mk_config(); ctx = Z3_mk_context(cfg); Z3_del_config(cfg); @@ -2612,83 +2616,76 @@ void fpa_example() { double_sort = Z3_mk_fpa_sort(ctx, 11, 53); rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx); - symbol_rm = Z3_mk_string_symbol(ctx, "rm"); - rm = Z3_mk_const(ctx, symbol_rm, rm_sort); - symbol_x = Z3_mk_string_symbol(ctx, "x"); - symbol_y = Z3_mk_string_symbol(ctx, "y"); - x = Z3_mk_const(ctx, symbol_x, double_sort); - y = Z3_mk_const(ctx, symbol_y, double_sort); - n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort); + { + // Show that there are x, y s.t. (x + y) = 42.0 (with rounding mode). + s_rm = Z3_mk_string_symbol(ctx, "rm"); + rm = Z3_mk_const(ctx, s_rm, rm_sort); + s_x = Z3_mk_string_symbol(ctx, "x"); + s_y = Z3_mk_string_symbol(ctx, "y"); + x = Z3_mk_const(ctx, s_x, double_sort); + y = Z3_mk_const(ctx, s_y, double_sort); + n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort); - symbol_q = Z3_mk_string_symbol(ctx, "q"); - q = Z3_mk_const(ctx, symbol_q, double_sort); - c1 = Z3_mk_eq(ctx, q, Z3_mk_fpa_add(ctx, rm, x, y)); + s_x_plus_y = Z3_mk_string_symbol(ctx, "x_plus_y"); + x_plus_y = Z3_mk_const(ctx, s_x_plus_y, double_sort); + c1 = Z3_mk_eq(ctx, x_plus_y, Z3_mk_fpa_add(ctx, rm, x, y)); - Z3_ast args[2] = { c1, Z3_mk_eq(ctx, q, n) }; - c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args); + Z3_ast args[2] = { c1, Z3_mk_eq(ctx, x_plus_y, n) }; + c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args); - Z3_ast args2[2] = { c2, Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_round_nearest_ties_to_away(ctx))) }; - c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2); + Z3_ast args2[2] = { c2, Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_rtz(ctx))) }; + c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2); - Z3_ast and_args[3] = { - Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)), - Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)), - Z3_mk_not(ctx, Z3_mk_fpa_is_inf(ctx, y)) }; - Z3_ast args3[2] = { c3, Z3_mk_and(ctx, 3, and_args) }; - c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3); - - - Z3_assert_cnstr(ctx, c4); - Z3_push(ctx); - - // c5 := (IEEEBV(x) == 7.0). - c5 = Z3_mk_eq(ctx, Z3_mk_fpa_to_ieee_bv(ctx, x), - Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64))); - - Z3_assert_cnstr(ctx, c5); - - Z3_model m = 0; - Z3_lbool result = Z3_check_and_get_model(ctx, &m); - switch (result) { - case Z3_L_FALSE: - printf("unsat\n"); - break; - case Z3_L_UNDEF: - printf("unknown\n"); - printf("potential model:\n%s\n", Z3_model_to_string(ctx, m)); - break; - case Z3_L_TRUE: - printf("sat\n%s\n", Z3_model_to_string(ctx, m)); - Z3_del_model(ctx, m); - break; - } - - Z3_pop(ctx, 1); - - // c6 := (IEEEBV(x) == 28.0). - c6 = Z3_mk_eq(ctx, Z3_mk_fpa_to_ieee_bv(ctx, x), - Z3_mk_numeral(ctx, "4628574517030027264", Z3_mk_bv_sort(ctx, 64))); - - Z3_assert_cnstr(ctx, c6); - Z3_push(ctx); - - m = 0; - result = Z3_check_and_get_model(ctx, &m); - switch (result) { - case Z3_L_FALSE: - printf("unsat\n"); - break; - case Z3_L_UNDEF: - printf("unknown\n"); - printf("potential model:\n%s\n", Z3_model_to_string(ctx, m)); - break; - case Z3_L_TRUE: - printf("sat\n%s\n", Z3_model_to_string(ctx, m)); - Z3_del_model(ctx, m); - break; + Z3_ast and_args[3] = { + Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)), + Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)), + Z3_mk_not(ctx, Z3_mk_fpa_is_infinite(ctx, y)) }; + Z3_ast args3[2] = { c3, Z3_mk_and(ctx, 3, and_args) }; + c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3); + + printf("c4: %s\n", Z3_ast_to_string(ctx, c4)); + Z3_push(ctx); + Z3_assert_cnstr(ctx, c4); + check(ctx, Z3_L_TRUE); + Z3_pop(ctx, 1); } - Z3_pop(ctx, 1); + + { + // Show that the following are equal: + // (fp #b0 #b10000000001 #xc000000000000) + // ((_ to_fp 11 53) #x401c000000000000)) + // ((_ to_fp 11 53) RTZ 1.75 2))) + // ((_ to_fp 11 53) RTZ 7.0))) + Z3_ast args3[3]; + + Z3_push(ctx); + c1 = Z3_mk_fpa_fp(ctx, + Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)), + Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11)), + Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52))); + c2 = Z3_mk_fpa_to_fp_bv(ctx, + Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), + Z3_mk_fpa_sort(ctx, 11, 53)); + c3 = Z3_mk_fpa_to_fp_real_int(ctx, + Z3_mk_fpa_rtz(ctx), + Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), + Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), + Z3_mk_fpa_sort(ctx, 11, 53)); + c4 = Z3_mk_fpa_to_fp_real(ctx, + Z3_mk_fpa_rtz(ctx), + Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)), + Z3_mk_fpa_sort(ctx, 11, 53)); + args3[0] = Z3_mk_eq(ctx, c1, c2); + args3[1] = Z3_mk_eq(ctx, c1, c3); + args3[2] = Z3_mk_eq(ctx, c1, c4); + c5 = Z3_mk_and(ctx, 3, args3); + + printf("c5: %s\n", Z3_ast_to_string(ctx, c5)); + Z3_assert_cnstr(ctx, c5); + check(ctx, Z3_L_TRUE); + Z3_pop(ctx, 1); + } Z3_del_context(ctx); } From 8e7278f02c15cc6f2cef6f3585c5fd206b62f62f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 18:10:47 +0000 Subject: [PATCH 135/646] Java API: Removed unnecessary imports Signed-off-by: Christoph M. Wintersteiger --- src/api/java/InterpolationContext.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 3e9996b3e..05d99b305 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -20,8 +20,6 @@ package com.microsoft.z3; import java.util.Map; import java.lang.String; -import com.microsoft.z3.Native.IntPtr; -import com.microsoft.z3.Native.UIntArrayPtr; import com.microsoft.z3.enumerations.Z3_lbool; /** From 09814128a62446d40f9aad264bce092321188c59 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 18:57:38 +0000 Subject: [PATCH 136/646] Update MPF toString Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index cc4b3a35a..f5dcfc612 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1181,14 +1181,13 @@ std::string mpf_manager::to_string(mpf const & x) { if (is_nan(x)) res = "NaN"; - else { - res = sgn(x) ? "-" : ""; - + else { if (is_inf(x)) - res += "INF"; + res = sgn(x) ? "-oo" : "+oo"; else if (is_zero(x)) - res += "0"; + res = sgn(x) ? "-zero" : "+zero"; else { + res = sgn(x) ? "-" : ""; scoped_mpz num(m_mpq_manager), denom(m_mpq_manager); num = 0; denom = 1; @@ -1218,7 +1217,7 @@ std::string mpf_manager::to_string(mpf const & x) { m_mpq_manager.display_decimal(ss, r, x.sbits); if (m_mpq_manager.is_int(r)) ss << ".0"; - ss << " " << exponent; + ss << "p" << exponent; res += ss.str(); } } From f684675a6e7bf18722ccb9d21b15768853a14cb9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 18:58:43 +0000 Subject: [PATCH 137/646] FPA API: Added get_ebits/get_sbits + doc fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 20 +++++++++++++++ src/api/z3_fpa.h | 59 ++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 97225f0f3..d2d4e7155 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -649,6 +649,26 @@ extern "C" { Z3_CATCH_RETURN(0); } + unsigned int Z3_API Z3_mk_fpa_get_ebits(Z3_context c, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_get_ebits(c, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + unsigned r = ctx->float_util().get_ebits(to_sort(s)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + + unsigned Z3_API Z3_mk_fpa_get_sbits(Z3_context c, Z3_sort s) { + Z3_TRY; + LOG_Z3_mk_fpa_get_sbits(c, s); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + unsigned r = ctx->float_util().get_sbits(to_sort(s)); + RETURN_Z3(r); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_to_ieee_bv(c, t); diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 61ee0bd7f..8208fbb2c 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -228,7 +228,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_sort_128(__in Z3_context c); /** - \brief Create a NaN of sort s. + \brief Create a floating-point NaN of sort s. \param c logical context. \param s target sort @@ -266,6 +266,7 @@ extern "C" { /** \brief Create an expression of FloatingPoint sort from three bit-vector expressions. + This is the operator named `fp' in the SMT FP theory definition. Note that \c sign is required to be a bit-vector of size 1. Significand and exponent are required to be greater than 1 and 2 respectively. The FloatingPoint sort of the resulting expression is automatically determined from the bit-vector sizes @@ -495,7 +496,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_round_to_integral(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t); /** - \brief Minimum of floating-point numbers + \brief Minimum of floating-point numbers. \param c logical context. \param t1 term of FloatingPoint sort. @@ -508,7 +509,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Maximum of floating-point numbers + \brief Maximum of floating-point numbers. \param c logical context. \param t1 term of FloatingPoint sort. @@ -521,7 +522,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_max(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point less than or equal + \brief Floating-point less than or equal. \param c logical context. \param t1 term of FloatingPoint sort. @@ -534,7 +535,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_leq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point less-than + \brief Floating-point less than. \param c logical context. \param t1 term of FloatingPoint sort. @@ -547,7 +548,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_lt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point greater than or equal + \brief Floating-point greater than or equal. \param c logical context. \param t1 term of FloatingPoint sort. @@ -560,7 +561,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_geq(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point greater-than + \brief Floating-point greater than. \param c logical context. \param t1 term of FloatingPoint sort. @@ -573,7 +574,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_gt(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); /** - \brief Floating-point equality + \brief Floating-point equality. \param c logical context. \param t1 term of FloatingPoint sort. @@ -636,7 +637,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_is_infinite(__in Z3_context c, __in Z3_ast t); /** - \brief Predicate indicating whether t is a NaN + \brief Predicate indicating whether t is a NaN. \param c logical context. \param t term of FloatingPoint sort. @@ -682,16 +683,15 @@ extern "C" { \param s floating-point sort. s must be a FloatingPoint sort, t must be of bit-vector sort, and the bit-vector - size of bv, m, must be equal to ebits+sbits of s. The format of the bit-vector is - as defined by the IEEE 754-2008 interchange format and the resulting floating-point - sort (ebits, sbits) is automatically determined. + size of bv must be equal to ebits+sbits of s. The format of the bit-vector is + as defined by the IEEE 754-2008 interchange format. def_API('Z3_mk_fpa_to_fp_bv', AST, (_in(CONTEXT),_in(AST),_in(SORT))) */ Z3_ast Z3_API Z3_mk_fpa_to_fp_bv(__in Z3_context c, __in Z3_ast bv, __in Z3_sort s); /** - \brief Conversion of a floating-point term into another floating-point term of different floating-point sort. + \brief Conversion of a FloatingPoint term into another term of different FloatingPoint sort. Produces a term that represents the conversion of a floating-point term t to a floating-point term of sort s. If necessary, the result will be rounded according @@ -768,8 +768,8 @@ extern "C" { \brief Conversion of a floating-point term into an unsigned bit-vector. Produces a term that represents the conversion of the floating-poiunt term t into a - bit-vector term in unsigned 2's complement format. If necessary, the result will be - rounded according to rounding mode rm. + bit-vector term of size sz in unsigned 2's complement format. If necessary, the result + will be rounded according to rounding mode rm. \param c logical context. \param rm term of RoundingMode sort. @@ -784,8 +784,8 @@ extern "C" { \brief Conversion of a floating-point term into a signed bit-vector. Produces a term that represents the conversion of the floating-poiunt term t into a - bit-vector term in signed 2's complement format. If necessary, the result will be - rounded according to rounding mode rm. + bit-vector term of size sz in signed 2's complement format. If necessary, the result + will be rounded according to rounding mode rm. \param c logical context. \param rm term of RoundingMode sort. @@ -797,7 +797,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_to_sbv(__in Z3_context c, __in Z3_ast rm, __in Z3_ast t, __in unsigned sz); /** - \brief Conversion of a floating-point term into a real number. + \brief Conversion of a floating-point term into a real-numbered term. Produces a term that represents the conversion of the floating-poiunt term t into a real number. Note that this type of conversion will often result in non-linear @@ -810,11 +810,30 @@ extern "C" { */ Z3_ast Z3_API Z3_mk_fpa_to_real(__in Z3_context c, __in Z3_ast t); + /** @name Z3-specific extensions */ /*@{*/ + /** + \brief Retrieves the number of bits reserved for the exponent in a FloatingPoint sort. + + \param s FloatingPoint sort. + + def_API('Z3_mk_fpa_get_ebits', UINT, (_in(CONTEXT),_in(SORT))) + */ + unsigned Z3_API Z3_mk_fpa_get_ebits(__in Z3_context c, __in Z3_sort s); + + /** + \brief Retrieves the number of bits reserved for the significand in a FloatingPoint sort. + + \param s FloatingPoint sort. + + def_API('Z3_mk_fpa_get_sbits', UINT, (_in(CONTEXT),_in(SORT))) + */ + unsigned Z3_API Z3_mk_fpa_get_sbits(__in Z3_context c, __in Z3_sort s); + /** \brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. @@ -842,8 +861,8 @@ extern "C" { \param c logical context. \param rm term of RoundingMode sort. \param sig significand term of Real sort. - \param exp exponent term of Real sort. - \param s floating-point sort. + \param exp exponent term of Int sort. + \param s FloatingPoint sort. s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort. From 3266e96e8008e1544e0ecb86717ab7314ac5c125 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 18:59:27 +0000 Subject: [PATCH 138/646] fpa2bv slight refactoring Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 349 ++++++++++++++++--------------- src/ast/fpa/fpa2bv_converter.h | 6 +- 2 files changed, 181 insertions(+), 174 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 94538861d..d51e34058 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1873,7 +1873,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args m_arith_util.is_numeral(args[1]) && m_arith_util.is_numeral(args[2])) { - // Three arguments, some of them are not numerals. + // rm + real + int -> float SASSERT(m_util.is_float(f->get_range())); unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); @@ -1926,191 +1926,197 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args else if (num == 1 && m_bv_util.is_bv(args[0])) { sort * s = f->get_range(); unsigned to_sbits = m_util.get_sbits(s); - unsigned to_ebits = m_util.get_ebits(s); + unsigned to_ebits = m_util.get_ebits(s); expr * bv = args[0]; int sz = m_bv_util.get_bv_size(bv); SASSERT((unsigned)sz == to_sbits + to_ebits); - + mk_triple(m_bv_util.mk_extract(sz - 1, sz - 1, bv), m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), result); } - else if (num == 2 && + else if (num == 2 && + m_util.is_rm(args[0]) && is_app(args[1]) && - m_util.is_float(m.get_sort(args[1]))) { - // We also support float to float conversion - sort * s = f->get_range(); - expr_ref rm(m), x(m); - rm = args[0]; - x = args[1]; - - unsigned from_sbits = m_util.get_sbits(m.get_sort(x)); - unsigned from_ebits = m_util.get_ebits(m.get_sort(x)); - unsigned to_sbits = m_util.get_sbits(s); - unsigned to_ebits = m_util.get_ebits(s); - - if (from_sbits == to_sbits && from_ebits == to_ebits) - result = x; - else { - expr_ref c1(m), c2(m), c3(m), c4(m), c5(m); - expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m); - expr_ref one1(m); - - one1 = m_bv_util.mk_numeral(1, 1); - expr_ref ninf(m), pinf(m); - mk_pinf(f, pinf); - mk_ninf(f, ninf); - - // NaN -> NaN - mk_is_nan(x, c1); - mk_nan(f, v1); - - // +0 -> +0 - mk_is_pzero(x, c2); - mk_pzero(f, v2); - - // -0 -> -0 - mk_is_nzero(x, c3); - mk_nzero(f, v3); - - // +oo -> +oo - mk_is_pinf(x, c4); - v4 = pinf; - - // -oo -> -oo - mk_is_ninf(x, c5); - v5 = ninf; - - // otherwise: the actual conversion with rounding. - expr_ref sgn(m), sig(m), exp(m), lz(m); - unpack(x, sgn, sig, exp, lz, true); - - dbg_decouple("fpa2bv_to_float_x_sig", sig); - dbg_decouple("fpa2bv_to_float_x_exp", exp); - dbg_decouple("fpa2bv_to_float_lz", lz); - - expr_ref res_sgn(m), res_sig(m), res_exp(m); - - res_sgn = sgn; - - SASSERT(m_bv_util.get_bv_size(sgn) == 1); - SASSERT(m_bv_util.get_bv_size(sig) == from_sbits); - SASSERT(m_bv_util.get_bv_size(exp) == from_ebits); - SASSERT(m_bv_util.get_bv_size(lz) == from_ebits); - - if (from_sbits < (to_sbits + 3)) - { - // make sure that sig has at least to_sbits + 3 - res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits+3-from_sbits)); - } - else if (from_sbits > (to_sbits + 3)) - { - // collapse the extra bits into a sticky bit. - expr_ref sticky(m), low(m), high(m); - low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig); - high = m_bv_util.mk_extract(from_sbits - 1, from_sbits - to_sbits - 2, sig); - sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, low.get()); - res_sig = m_bv_util.mk_concat(high, sticky); - } - else - res_sig = sig; - - res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder. - unsigned sig_sz = m_bv_util.get_bv_size(res_sig); - SASSERT(sig_sz == to_sbits+4); - - expr_ref exponent_overflow(m); - exponent_overflow = m.mk_false(); - - if (from_ebits < (to_ebits + 2)) - { - res_exp = m_bv_util.mk_sign_extend(to_ebits-from_ebits+2, exp); - - // subtract lz for subnormal numbers. - expr_ref lz_ext(m); - lz_ext = m_bv_util.mk_zero_extend(to_ebits-from_ebits+2, lz); - res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext); - } - else if (from_ebits > (to_ebits + 2)) - { - expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m); - expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m); - high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp); - low = m_bv_util.mk_extract(to_ebits+1, 0, exp); - lows = m_bv_util.mk_extract(to_ebits+1, to_ebits+1, low); - - high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get()); - high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get()); - - zero1 = m_bv_util.mk_numeral(0, 1); - m_simp.mk_eq(high_red_and, one1, h_and_eq); - m_simp.mk_eq(high_red_or, zero1, h_or_eq); - m_simp.mk_eq(lows, zero1, s_is_zero); - m_simp.mk_eq(lows, one1, s_is_one); - - expr_ref c2(m); - m_simp.mk_ite(h_or_eq, s_is_one, m.mk_false(), c2); - m_simp.mk_ite(h_and_eq, s_is_zero, c2, exponent_overflow); - - // Note: Upon overflow, we _could_ try to shift the significand around... - - // subtract lz for subnormal numbers. - expr_ref lz_ext(m), lz_rest(m), lz_redor(m), lz_redor_bool(m); - lz_ext = m_bv_util.mk_extract(to_ebits+1, 0, lz); - lz_rest = m_bv_util.mk_extract(from_ebits-1, to_ebits+2, lz); - lz_redor = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, lz_rest.get()); - m_simp.mk_eq(lz_redor, one1, lz_redor_bool); - m_simp.mk_or(exponent_overflow, lz_redor_bool, exponent_overflow); - - res_exp = m_bv_util.mk_bv_sub(low, lz_ext); - } - else // from_ebits == (to_ebits + 2) - res_exp = m_bv_util.mk_bv_sub(exp, lz); - - SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits+2); - SASSERT(is_well_sorted(m, res_exp)); - - dbg_decouple("fpa2bv_to_float_res_sig", res_sig); - dbg_decouple("fpa2bv_to_float_res_exp", res_exp); - - expr_ref rounded(m); - round(s, rm, res_sgn, res_sig, res_exp, rounded); - - expr_ref is_neg(m), sig_inf(m); - m_simp.mk_eq(sgn, one1, is_neg); - mk_ite(is_neg, ninf, pinf, sig_inf); - - dbg_decouple("fpa2bv_to_float_exp_ovf", exponent_overflow); - mk_ite(exponent_overflow, sig_inf, rounded, v6); - - // And finally, we tie them together. - mk_ite(c5, v5, v6, result); - mk_ite(c4, v4, result, result); - mk_ite(c3, v3, result, result); - mk_ite(c2, v2, result, result); - mk_ite(c1, v1, result, result); - } + m_util.is_float(m.get_sort(args[1]))) { + // float -> float conversion + mk_to_fp_float(f, f->get_range(), args[0], args[1], result); } - else if (num == 2 && + else if (num == 2 && m_util.is_rm(args[0]), m_arith_util.is_real(args[1])) { - // .. other than that, we only support rationals for to_fp - SASSERT(m_util.is_float(f->get_range())); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); + // rm + real -> float + mk_to_fp_real(f, f->get_range(), args[0], args[1], result); + } + else + UNREACHABLE(); - SASSERT(m_bv_util.is_numeral(args[0])); + SASSERT(is_well_sorted(m, result)); +} + +void fpa2bv_converter::mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) { + unsigned from_sbits = m_util.get_sbits(m.get_sort(x)); + unsigned from_ebits = m_util.get_ebits(m.get_sort(x)); + unsigned to_sbits = m_util.get_sbits(s); + unsigned to_ebits = m_util.get_ebits(s); + + if (from_sbits == to_sbits && from_ebits == to_ebits) + result = x; + else { + expr_ref c1(m), c2(m), c3(m), c4(m), c5(m); + expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m); + expr_ref one1(m); + + one1 = m_bv_util.mk_numeral(1, 1); + expr_ref ninf(m), pinf(m); + mk_pinf(f, pinf); + mk_ninf(f, ninf); + + // NaN -> NaN + mk_is_nan(x, c1); + mk_nan(f, v1); + + // +0 -> +0 + mk_is_pzero(x, c2); + mk_pzero(f, v2); + + // -0 -> -0 + mk_is_nzero(x, c3); + mk_nzero(f, v3); + + // +oo -> +oo + mk_is_pinf(x, c4); + v4 = pinf; + + // -oo -> -oo + mk_is_ninf(x, c5); + v5 = ninf; + + // otherwise: the actual conversion with rounding. + expr_ref sgn(m), sig(m), exp(m), lz(m); + unpack(x, sgn, sig, exp, lz, true); + + dbg_decouple("fpa2bv_to_float_x_sig", sig); + dbg_decouple("fpa2bv_to_float_x_exp", exp); + dbg_decouple("fpa2bv_to_float_lz", lz); + + expr_ref res_sgn(m), res_sig(m), res_exp(m); + + res_sgn = sgn; + + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(sig) == from_sbits); + SASSERT(m_bv_util.get_bv_size(exp) == from_ebits); + SASSERT(m_bv_util.get_bv_size(lz) == from_ebits); + + if (from_sbits < (to_sbits + 3)) { + // make sure that sig has at least to_sbits + 3 + res_sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, to_sbits + 3 - from_sbits)); + } + else if (from_sbits >(to_sbits + 3)) { + // collapse the extra bits into a sticky bit. + expr_ref sticky(m), low(m), high(m); + low = m_bv_util.mk_extract(from_sbits - to_sbits - 3, 0, sig); + high = m_bv_util.mk_extract(from_sbits - 1, from_sbits - to_sbits - 2, sig); + sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, low.get()); + res_sig = m_bv_util.mk_concat(high, sticky); + } + else + res_sig = sig; + + res_sig = m_bv_util.mk_zero_extend(1, res_sig); // extra zero in the front for the rounder. + unsigned sig_sz = m_bv_util.get_bv_size(res_sig); + SASSERT(sig_sz == to_sbits + 4); + + expr_ref exponent_overflow(m); + exponent_overflow = m.mk_false(); + + if (from_ebits < (to_ebits + 2)) { + res_exp = m_bv_util.mk_sign_extend(to_ebits - from_ebits + 2, exp); + + // subtract lz for subnormal numbers. + expr_ref lz_ext(m); + lz_ext = m_bv_util.mk_zero_extend(to_ebits - from_ebits + 2, lz); + res_exp = m_bv_util.mk_bv_sub(res_exp, lz_ext); + } + else if (from_ebits >(to_ebits + 2)) { + expr_ref high(m), low(m), lows(m), high_red_or(m), high_red_and(m), h_or_eq(m), h_and_eq(m); + expr_ref no_ovf(m), zero1(m), s_is_one(m), s_is_zero(m); + high = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, exp); + low = m_bv_util.mk_extract(to_ebits + 1, 0, exp); + lows = m_bv_util.mk_extract(to_ebits + 1, to_ebits + 1, low); + + high_red_or = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, high.get()); + high_red_and = m.mk_app(m_bv_util.get_fid(), OP_BREDAND, high.get()); + + zero1 = m_bv_util.mk_numeral(0, 1); + m_simp.mk_eq(high_red_and, one1, h_and_eq); + m_simp.mk_eq(high_red_or, zero1, h_or_eq); + m_simp.mk_eq(lows, zero1, s_is_zero); + m_simp.mk_eq(lows, one1, s_is_one); + + expr_ref c2(m); + m_simp.mk_ite(h_or_eq, s_is_one, m.mk_false(), c2); + m_simp.mk_ite(h_and_eq, s_is_zero, c2, exponent_overflow); + + // Note: Upon overflow, we _could_ try to shift the significand around... + + // subtract lz for subnormal numbers. + expr_ref lz_ext(m), lz_rest(m), lz_redor(m), lz_redor_bool(m); + lz_ext = m_bv_util.mk_extract(to_ebits + 1, 0, lz); + lz_rest = m_bv_util.mk_extract(from_ebits - 1, to_ebits + 2, lz); + lz_redor = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, lz_rest.get()); + m_simp.mk_eq(lz_redor, one1, lz_redor_bool); + m_simp.mk_or(exponent_overflow, lz_redor_bool, exponent_overflow); + + res_exp = m_bv_util.mk_bv_sub(low, lz_ext); + } + else // from_ebits == (to_ebits + 2) + res_exp = m_bv_util.mk_bv_sub(exp, lz); + + SASSERT(m_bv_util.get_bv_size(res_exp) == to_ebits + 2); + SASSERT(is_well_sorted(m, res_exp)); + + dbg_decouple("fpa2bv_to_float_res_sig", res_sig); + dbg_decouple("fpa2bv_to_float_res_exp", res_exp); + + expr_ref rounded(m); + round(s, expr_ref (rm, m), res_sgn, res_sig, res_exp, rounded); + + expr_ref is_neg(m), sig_inf(m); + m_simp.mk_eq(sgn, one1, is_neg); + mk_ite(is_neg, ninf, pinf, sig_inf); + + dbg_decouple("fpa2bv_to_float_exp_ovf", exponent_overflow); + mk_ite(exponent_overflow, sig_inf, rounded, v6); + + // And finally, we tie them together. + mk_ite(c5, v5, v6, result); + mk_ite(c4, v4, result, result); + mk_ite(c3, v3, result, result); + mk_ite(c2, v2, result, result); + mk_ite(c1, v1, result, result); + } + + SASSERT(is_well_sorted(m, result)); +} + +void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) { + SASSERT(m_util.is_float(s)); + unsigned ebits = m_util.get_ebits(s); + unsigned sbits = m_util.get_sbits(s); + + if (m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) { rational tmp_rat; unsigned sz; - m_bv_util.is_numeral(to_expr(args[0]), tmp_rat, sz); + m_bv_util.is_numeral(to_expr(rm), tmp_rat, sz); SASSERT(tmp_rat.is_int32()); SASSERT(sz == 3); BV_RM_VAL bv_rm = (BV_RM_VAL)tmp_rat.get_unsigned(); mpf_rounding_mode rm; - switch (bv_rm) - { + switch (bv_rm) { case BV_RM_TIES_TO_AWAY: rm = MPF_ROUND_NEAREST_TAWAY; break; case BV_RM_TIES_TO_EVEN: rm = MPF_ROUND_NEAREST_TEVEN; break; case BV_RM_TO_NEGATIVE: rm = MPF_ROUND_TOWARD_NEGATIVE; break; @@ -2119,10 +2125,8 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args default: UNREACHABLE(); } - SASSERT(m_util.au().is_numeral(args[1])); - rational q; - m_util.au().is_numeral(args[1], q); + m_util.au().is_numeral(x, q); scoped_mpf v(m_mpf_manager); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); @@ -2135,10 +2139,11 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args mk_triple(sgn, s, e, result); } - else - UNREACHABLE(); + else { + NOT_IMPLEMENTED_YET(); + } - SASSERT(is_well_sorted(m, result)); + SASSERT(is_well_sorted(m, result)); } void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 197c7ce9a..6a7b6e92f 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -129,7 +129,9 @@ public: void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); + void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); @@ -186,7 +188,7 @@ protected: expr_ref & c_sgn, expr_ref & c_sig, expr_ref & c_exp, expr_ref & d_sgn, expr_ref & d_sig, expr_ref & d_exp, expr_ref & res_sgn, expr_ref & res_sig, expr_ref & res_exp); - app * mk_fresh_const(char const * prefix, unsigned sz); + app * mk_fresh_const(char const * prefix, unsigned sz); }; #endif From 3c75b700e88d04cac373e05ecef1cbd9270e4090 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 19:03:20 +0000 Subject: [PATCH 139/646] Updates to the .NET API for FP Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 665 +++++++++++++++++++++++++++++++------ src/api/dotnet/FPExpr.cs | 2 +- src/api/dotnet/FPNum.cs | 2 +- src/api/dotnet/FPRMExpr.cs | 2 +- src/api/dotnet/FPRMNum.cs | 2 +- src/api/dotnet/FPRMSort.cs | 4 +- src/api/dotnet/FPSort.cs | 15 +- 7 files changed, 575 insertions(+), 117 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 69855fc4f..986efc94d 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3439,65 +3439,118 @@ namespace Microsoft.Z3 #endregion #region Floating-Point Arithmetic + + #region Rounding Modes + #region RoundingMode Sort /// - /// Create a floating point rounding mode sort. + /// Create the floating-point RoundingMode sort. /// - public FPRMSort MkFPRMSort() + public FPRMSort MkFPRoundingModeSort() { Contract.Ensures(Contract.Result() != null); return new FPRMSort(this); } - + #endregion + + #region Numerals /// - /// Create a NearestTiesToEven rounding mode numeral. + /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// - public FPRMNum MkFPRMNearestTiesToEven() + public FPRMNum MkFPRoundNearestTiesToEven() { Contract.Ensures(Contract.Result() != null); return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx)); } /// - /// Create a NearestTiesToAway rounding mode numeral. + /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// - public FPRMNum MkFPRMNearestTiesToAway() + public FPRMNum MkFPRNE() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_rne(nCtx)); + } + + /// + /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + /// + public FPRMNum MkFPRoundNearestTiesToAway() { Contract.Ensures(Contract.Result() != null); return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); } /// - /// Create a TowardPositive rounding mode numeral. + /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// - public FPRMNum MkFPRMTowardPositive() + public FPRMNum MkFPRNA() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_rna(nCtx)); + } + + /// + /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. + /// + public FPRMNum MkFPRoundTowardPositive() { Contract.Ensures(Contract.Result() != null); return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); } /// - /// Create a TowardNegative rounding mode numeral. + /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// - public FPRMNum MkFPRMTowardNegative() + public FPRMNum MkFPRTP() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_rtp(nCtx)); + } + + /// + /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. + /// + public FPRMNum MkFPRoundTowardNegative() { Contract.Ensures(Contract.Result() != null); return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); } /// - /// Create a TowardZero rounding mode numeral. + /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// - public FPRMNum MkFPRMTowardZero() + public FPRMNum MkFPRTN() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_rtn(nCtx)); + } + + /// + /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. + /// + public FPRMNum MkFPRoundTowardZero() { Contract.Ensures(Contract.Result() != null); return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); } /// - /// Create a floating point sort. + /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// - /// exponent bits in the floating point sort. - /// significand bits in the floating point sort. + public FPRMNum MkFPRTZ() + { + Contract.Ensures(Contract.Result() != null); + return new FPRMNum(this, Native.Z3_mk_fpa_rtz(nCtx)); + } + #endregion + #endregion + + #region FloatingPoint Sorts + /// + /// Create a FloatingPoint sort. + /// + /// exponent bits in the FloatingPoint sort. + /// significand bits in the FloatingPoint sort. public FPSort MkFPSort(uint ebits, uint sbits) { Contract.Ensures(Contract.Result() != null); @@ -3505,9 +3558,83 @@ namespace Microsoft.Z3 } /// - /// Create a floating point NaN numeral. + /// Create the half-precision (16-bit) FloatingPoint sort. + /// + public FPSort MkFPSortHalf() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_half(nCtx)); + } + + /// + /// Create the half-precision (16-bit) FloatingPoint sort. + /// + public FPSort MkFPSort16() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_16(nCtx)); + } + + /// + /// Create the single-precision (32-bit) FloatingPoint sort. + /// + public FPSort MkFPSortSingle() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_single(nCtx)); + } + + /// + /// Create the single-precision (32-bit) FloatingPoint sort. + /// + public FPSort MkFPSort32() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_16(nCtx)); + } + + /// + /// Create the double-precision (64-bit) FloatingPoint sort. + /// + public FPSort MkFPSortDouble() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_double(nCtx)); + } + + /// + /// Create the double-precision (64-bit) FloatingPoint sort. + /// + public FPSort MkFPSort64() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_64(nCtx)); + } + + /// + /// Create the quadruple-precision (128-bit) FloatingPoint sort. + /// + public FPSort MkFPSortQuadruple() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_double(nCtx)); + } + + /// + /// Create the quadruple-precision (128-bit) FloatingPoint sort. + /// + public FPSort MkFPSort128() + { + Contract.Ensures(Contract.Result() != null); + return new FPSort(this, Native.Z3_mk_fpa_sort_128(nCtx)); + } + #endregion + + #region Numerals + /// + /// Create a NaN of sort s. /// - /// floating point sort. + /// FloatingPoint sort. public FPNum MkFPNaN(FPSort s) { Contract.Ensures(Contract.Result() != null); @@ -3515,9 +3642,9 @@ namespace Microsoft.Z3 } /// - /// Create a floating point Inf numeral. + /// Create a floating-point infinity of sort s. /// - /// floating point sort. + /// FloatingPoint sort. /// indicates whether the result should be negative. public FPNum MkFPInf(FPSort s, bool negative) { @@ -3526,20 +3653,141 @@ namespace Microsoft.Z3 } /// - /// Create a floating point numeral. - /// - /// A string representing the value in decimal notation. - /// floating point sort + /// Create a floating-point zero of sort s. + /// + /// FloatingPoint sort. + /// indicates whether the result should be negative. + public FPNum MkFPZero(FPSort s, bool negative) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, negative ? 1 : 0)); + } + + /// + /// Create a numeral of FloatingPoint sort from a float. + /// + /// numeral value. + /// FloatingPoint sort. + public FPNum MkFPNumeral(float v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_numeral_float(nCtx, v, s.NativeObject)); + } + + /// + /// Create a numeral of FloatingPoint sort from a float. + /// + /// numeral value. + /// FloatingPoint sort. + public FPNum MkFPNumeral(double v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_numeral_double(nCtx, v, s.NativeObject)); + } + + /// + /// Create a numeral of FloatingPoint sort from an int. + /// + /// numeral value. + /// FloatingPoint sort. + public FPNum MkFPNumeral(int v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_numeral_int(nCtx, v, s.NativeObject)); + } + + /// + /// Create a numeral of FloatingPoint sort from a sign bit and two integers. + /// + /// the sign. + /// the significand. + /// the exponent. + /// FloatingPoint sort. + public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_numeral_uint_int(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); + } + + /// + /// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + /// + /// the sign. + /// the significand. + /// the exponent. + /// FloatingPoint sort. + public FPNum MkFPNumeral(bool sgn, UInt64 sig, Int64 exp, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPNum(this, Native.Z3_mk_fpa_numeral_uint64_int64(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); + } + + /// + /// Create a numeral of FloatingPoint sort from a float. + /// + /// numeral value. + /// FloatingPoint sort. + public FPNum MkFP(float v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return MkFPNumeral(v, s); + } + + /// + /// Create a numeral of FloatingPoint sort from a float. + /// + /// numeral value. + /// FloatingPoint sort. public FPNum MkFP(double v, FPSort s) { - Contract.Ensures(Contract.Result() != null); - return new FPNum(this, Native.Z3_mk_fpa_numeral_double(this.nCtx, v, s.NativeObject)); - } + Contract.Ensures(Contract.Result() != null); + return MkFPNumeral(v, s); + } + /// + /// Create a numeral of FloatingPoint sort from an int. + /// + /// numeral value. + /// FloatingPoint sort. + public FPNum MkFP(int v, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return MkFPNumeral(v, s); + } + + /// + /// Create a numeral of FloatingPoint sort from a sign bit and two integers. + /// + /// the sign. + /// the significand. + /// the exponent. + /// FloatingPoint sort. + public FPNum MkFP(bool sgn, uint sig, int exp, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return MkFPNumeral(sgn, sig, exp, s); + } + + /// + /// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + /// + /// the sign. + /// the significand. + /// the exponent. + /// FloatingPoint sort. + public FPNum MkFP(bool sgn, UInt64 sig, Int64 exp, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return MkFPNumeral(sgn, sig, exp, s); + } + + #endregion + + #region Operators /// /// Floating-point absolute value /// - /// floating point term + /// floating-point term public FPExpr MkFPAbs(FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3549,7 +3797,7 @@ namespace Microsoft.Z3 /// /// Floating-point negation /// - /// floating point term + /// floating-point term public FPExpr MkFPNeg(FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3560,8 +3808,8 @@ namespace Microsoft.Z3 /// Floating-point addition /// /// rounding mode term - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3572,8 +3820,8 @@ namespace Microsoft.Z3 /// Floating-point subtraction /// /// rounding mode term - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3584,8 +3832,8 @@ namespace Microsoft.Z3 /// Floating-point multiplication /// /// rounding mode term - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3596,8 +3844,8 @@ namespace Microsoft.Z3 /// Floating-point division /// /// rounding mode term - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3611,9 +3859,9 @@ namespace Microsoft.Z3 /// The result is round((t1 * t2) + t3) /// /// rounding mode term - /// floating point term - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term + /// floating-point term public FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) { Contract.Ensures(Contract.Result() != null); @@ -3624,7 +3872,7 @@ namespace Microsoft.Z3 /// Floating-point square root /// /// rounding mode term - /// floating point term + /// floating-point term public FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3634,33 +3882,53 @@ namespace Microsoft.Z3 /// /// Floating-point remainder /// - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public FPExpr MkFPRem(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_rem(this.nCtx, t1.NativeObject, t2.NativeObject)); } - + /// - /// Floating-point equality - /// - /// - /// Note that this is IEEE 754 equality (as opposed to standard =). - /// - /// floating point term - /// floating point term - public BoolExpr MkFPEq(FPExpr t1, FPExpr t2) - { - Contract.Ensures(Contract.Result() != null); - return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject)); - } - - /// - /// Floating-point less than or equal + /// Floating-point roundToIntegral. Rounds a floating-point number to + /// the closest integer, again represented as a floating-point number. /// - /// floating point term - /// floating point term + /// term of RoundingMode sort + /// floating-point term + public FPExpr MkFPRoundToIntegral(FPRMExpr rm, FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_round_to_integral(this.nCtx, rm.NativeObject, t.NativeObject)); + } + + /// + /// Minimum of floating-point numbers. + /// + /// floating-point term + /// floating-point term + public FPExpr MkFPMin(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Maximum of floating-point numbers. + /// + /// floating-point term + /// floating-point term + public FPExpr MkFPMax(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Floating-point less than or equal. + /// + /// floating-point term + /// floating-point term public BoolExpr MkFPLEq(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3668,10 +3936,10 @@ namespace Microsoft.Z3 } /// - /// Floating-point less than + /// Floating-point less than. /// - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public BoolExpr MkFPLt(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3679,10 +3947,10 @@ namespace Microsoft.Z3 } /// - /// Floating-point greater than or equal + /// Floating-point greater than or equal. /// - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public BoolExpr MkFPGEq(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3690,10 +3958,10 @@ namespace Microsoft.Z3 } /// - /// Floating-point greater than + /// Floating-point greater than. /// - /// floating point term - /// floating point term + /// floating-point term + /// floating-point term public BoolExpr MkFPGt(FPExpr t1, FPExpr t2) { Contract.Ensures(Contract.Result() != null); @@ -3701,9 +3969,23 @@ namespace Microsoft.Z3 } /// - /// Predicate indicating whether t is a normal floating point number + /// Floating-point equality. + /// + /// + /// Note that this is IEEE 754 equality (as opposed to standard =). + /// + /// floating-point term + /// floating-point term + public BoolExpr MkFPEq(FPExpr t1, FPExpr t2) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject)); + } + + /// + /// Predicate indicating whether t is a normal floating-point number. /// - /// floating point term + /// floating-point term public BoolExpr MkFPIsNormal(FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3711,9 +3993,9 @@ namespace Microsoft.Z3 } /// - /// Predicate indicating whether t is a subnormal floating point number + /// Predicate indicating whether t is a subnormal floating-point number. /// - /// floating point term + /// floating-point term public BoolExpr MkFPIsSubnormal(FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3721,29 +4003,29 @@ namespace Microsoft.Z3 } /// - /// Predicate indicating whether t is a floating point number with zero value, i.e., +0 or -0. + /// Predicate indicating whether t is a floating-point number with zero value, i.e., +0 or -0. /// - /// floating point term - public BoolExpr MkFPIsZero(FPExpr t) - { + /// floating-point term + public BoolExpr MkFPIsZero(FPExpr t) + { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_zero(this.nCtx, t.NativeObject)); } /// - /// Predicate indicating whether t is a floating point number representing +Inf or -Inf + /// Predicate indicating whether t is a floating-point number representing +oo or -oo. /// - /// floating point term - public BoolExpr MkFPIsInf(FPExpr t) - { + /// floating-point term + public BoolExpr MkFPIsInfinite(FPExpr t) + { Contract.Ensures(Contract.Result() != null); return new BoolExpr(this, Native.Z3_mk_fpa_is_infinite(this.nCtx, t.NativeObject)); } /// - /// Predicate indicating whether t is a NaN + /// Predicate indicating whether t is a NaN. /// - /// floating point term + /// floating-point term public BoolExpr MkFPIsNaN(FPExpr t) { Contract.Ensures(Contract.Result() != null); @@ -3751,45 +4033,212 @@ namespace Microsoft.Z3 } /// - /// Floating-point minimum + /// Predicate indicating whether t is a negative floating-point number. /// - /// floating point term - /// floating point term - public FPExpr MkFPMin(FPExpr t1, FPExpr t2) + /// floating-point term + public BoolExpr MkFPIsNegative(FPExpr t) { - Contract.Ensures(Contract.Result() != null); - return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject)); + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_negative(this.nCtx, t.NativeObject)); } - - /// - /// Floating-point maximium - /// - /// floating point term - /// floating point term - public FPExpr MkFPMax(FPExpr t1, FPExpr t2) - { - Contract.Ensures(Contract.Result() != null); - return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject)); - } /// - /// Conversion of a floating point number to another floating-point sort s. + /// Predicate indicating whether t is a positive floating-point number. + /// + /// floating-point term + public BoolExpr MkFPIsPositive(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BoolExpr(this, Native.Z3_mk_fpa_is_positive(this.nCtx, t.NativeObject)); + } + #endregion + + #region Conversions to FloatingPoint terms + /// + /// Create an expression of FloatingPoint sort from three bit-vector expressions. + /// + /// + /// This is the operator named `fp' in the SMT FP theory definition. + /// Note that sgn is required to be a bit-vector of size 1. Significand and exponent + /// are required to be greater than 1 and 2 respectively. The FloatingPoint sort + /// of the resulting expression is automatically determined from the bit-vector sizes + /// of the arguments. + /// + /// bit-vector term (of size 1) representing the sign. + /// bit-vector term representing the significand. + /// bit-vector term representing the exponent. + public FPExpr MkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_fp(this.nCtx, sgn.NativeObject, sig.NativeObject, exp.NativeObject)); + } + + /// + /// Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. + /// + /// + /// Produces a term that represents the conversion of a bit-vector term bv to a + /// floating-point term of sort s. The bit-vector size of bv (m) must be equal + /// to ebits+sbits of s. The format of the bit-vector is as defined by the + /// IEEE 754-2008 interchange format. + /// + /// bit-vector value (of size m). + /// FloatingPoint sort (ebits+sbits == m) + public FPExpr MkFPToFP(BitVecExpr bv, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_bv(this.nCtx, bv.NativeObject, s.NativeObject)); + } + + /// + /// Conversion of a FloatingPoint term into another term of different FloatingPoint sort. + /// + /// + /// Produces a term that represents the conversion of a floating-point term t to a + /// floating-point term of sort s. If necessary, the result will be rounded according + /// to rounding mode rm. + /// + /// RoundingMode term. + /// FloatingPoint term. + /// FloatingPoint sort. + public FPExpr MkFPToFP(FPRMExpr rm, FPExpr t, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); + } + + /// + /// Conversion of a term of real sort into a term of FloatingPoint sort. + /// + /// + /// Produces a term that represents the conversion of term t of real sort into a + /// floating-point term of sort s. If necessary, the result will be rounded according + /// to rounding mode rm. + /// + /// RoundingMode term. + /// term of Real sort. + /// FloatingPoint sort. + public FPExpr MkFPToFP(FPRMExpr rm, RealExpr t, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_real(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); + } + + /// + /// Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. + /// + /// + /// Produces a term that represents the conversion of the bit-vector term t into a + /// floating-point term of sort s. The bit-vector t is taken to be in signed + /// 2's complement format (when signed==true, otherwise unsigned). If necessary, the + /// result will be rounded according to rounding mode rm. + /// + /// RoundingMode term. + /// term of bit-vector sort. + /// FloatingPoint sort. + /// flag indicating whether t is interpreted as signed or unsigned bit-vector. + public FPExpr MkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, bool signed) + { + Contract.Ensures(Contract.Result() != null); + if (signed) + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_signed(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); + else + return new FPExpr(this, Native.Z3_mk_fpa_to_fp_unsigned(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); + } + + /// + /// Conversion of a floating-point number to another FloatingPoint sort s. /// /// /// Produces a term that represents the conversion of a floating-point term t to a different - /// floating point sort s. If necessary, rounding according to rm is applied. + /// FloatingPoint sort s. If necessary, rounding according to rm is applied. /// - /// floating point sort - /// floating point rounding mode term - /// floating point term - public FPExpr MkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) + /// FloatingPoint sort + /// floating-point rounding mode term + /// floating-point term + public FPExpr MkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); } #endregion + #region Conversions from FloatingPoint terms + /// + /// Conversion of a floating-point term into a bit-vector. + /// + /// + /// Produces a term that represents the conversion of the floating-poiunt term t into a + /// bit-vector term of size sz in 2's complement format (signed when signed==true). If necessary, + /// the result will be rounded according to rounding mode rm. + /// + /// RoundingMode term. + /// FloatingPoint term + /// Size of the resulting bit-vector. + /// Indicates whether the result is a signed or unsigned bit-vector. + public BitVecExpr MkFPToBV(FPRMExpr rm, FPExpr t, uint sz, bool signed) + { + Contract.Ensures(Contract.Result() != null); + if (signed) + return new BitVecExpr(this, Native.Z3_mk_fpa_to_sbv(this.nCtx, rm.NativeObject, t.NativeObject, sz)); + else + return new BitVecExpr(this, Native.Z3_mk_fpa_to_ubv(this.nCtx, rm.NativeObject, t.NativeObject, sz)); + } + + /// + /// Conversion of a floating-point term into a real-numbered term. + /// + /// + /// Produces a term that represents the conversion of the floating-poiunt term t into a + /// real number. Note that this type of conversion will often result in non-linear + /// constraints over real terms. + /// + /// FloatingPoint term + public RealExpr MkFPToReal(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new RealExpr(this, Native.Z3_mk_fpa_to_real(this.nCtx, t.NativeObject)); + } + #endregion + + #region Z3-specific extensions + /// + /// Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. + /// + /// + /// The size of the resulting bit-vector is automatically determined. Note that + /// IEEE 754-2008 allows multiple different representations of NaN. This conversion + /// knows only one NaN and it will always produce the same bit-vector represenatation of + /// that NaN. + /// + /// FloatingPoint term. + public BitVecExpr MkFPToIEEEBV(FPExpr t) + { + Contract.Ensures(Contract.Result() != null); + return new BitVecExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject)); + } + + /// + /// Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. + /// + /// + /// Produces a term that represents the conversion of sig * 2^exp into a + /// floating-point term of sort s. If necessary, the result will be rounded + /// according to rounding mode rm. + /// + /// RoundingMode term. + /// Significand term of Real sort. + /// Exponent term of Int sort. + /// FloatingPoint sort. + public BitVecExpr MkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s) + { + Contract.Ensures(Contract.Result() != null); + return new BitVecExpr(this, Native.Z3_mk_fpa_to_fp_real_int(this.nCtx, rm.NativeObject, sig.NativeObject, exp.NativeObject, s.NativeObject)); + } + #endregion + #endregion // Floating-point Arithmetic + #region Miscellaneous /// /// Wraps an AST. diff --git a/src/api/dotnet/FPExpr.cs b/src/api/dotnet/FPExpr.cs index 0bb1e4c09..cbba272d1 100644 --- a/src/api/dotnet/FPExpr.cs +++ b/src/api/dotnet/FPExpr.cs @@ -26,7 +26,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Floating Point Expressions + /// FloatingPoint Expressions /// public class FPExpr : Expr { diff --git a/src/api/dotnet/FPNum.cs b/src/api/dotnet/FPNum.cs index 044598e58..ab57d57c3 100644 --- a/src/api/dotnet/FPNum.cs +++ b/src/api/dotnet/FPNum.cs @@ -22,7 +22,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Floatiung Point Numerals + /// FloatiungPoint Numerals /// [ContractVerification(true)] public class FPNum : FPExpr diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs index b95816023..92fea1ad4 100644 --- a/src/api/dotnet/FPRMExpr.cs +++ b/src/api/dotnet/FPRMExpr.cs @@ -26,7 +26,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Floating Point Expressions + /// FloatingPoint RoundingMode Expressions /// public class FPRMExpr : Expr { diff --git a/src/api/dotnet/FPRMNum.cs b/src/api/dotnet/FPRMNum.cs index eaf105718..7caa56f9f 100644 --- a/src/api/dotnet/FPRMNum.cs +++ b/src/api/dotnet/FPRMNum.cs @@ -22,7 +22,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// Floatiung Point Rounding Mode Numerals + /// FloatingPoint RoundingMode Numerals /// [ContractVerification(true)] public class FPRMNum : FPRMExpr diff --git a/src/api/dotnet/FPRMSort.cs b/src/api/dotnet/FPRMSort.cs index 23d454a65..1d8334eb5 100644 --- a/src/api/dotnet/FPRMSort.cs +++ b/src/api/dotnet/FPRMSort.cs @@ -7,7 +7,7 @@ Module Name: Abstract: - Z3 Managed API: Floating Point Rounding Mode Sorts + Z3 Managed API: Rounding Mode Sort Author: @@ -23,7 +23,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// A floating point rounding mode sort + /// The FloatingPoint RoundingMode sort /// public class FPRMSort : Sort { diff --git a/src/api/dotnet/FPSort.cs b/src/api/dotnet/FPSort.cs index a79557ae6..8d8560e53 100644 --- a/src/api/dotnet/FPSort.cs +++ b/src/api/dotnet/FPSort.cs @@ -16,17 +16,26 @@ Author: Notes: --*/ - using System; using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// A floating point sort + /// FloatingPoint sort /// public class FPSort : Sort { + /// + /// The number of exponent bits. + /// + public uint EBits { get { return Native.Z3_mk_fpa_get_ebits(Context.nCtx, NativeObject); } } + + /// + /// The number of significand bits. + /// + public uint SBits { get { return Native.Z3_mk_fpa_get_ebits(Context.nCtx, NativeObject); } } + #region Internal internal FPSort(Context ctx, IntPtr obj) : base(ctx, obj) @@ -39,5 +48,5 @@ namespace Microsoft.Z3 Contract.Requires(ctx != null); } #endregion - } + } } From 263456116dde88c961900c88dc4da96b72deeb06 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 2 Jan 2015 19:05:40 +0000 Subject: [PATCH 140/646] Added fpa2bv_rewriter_params Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_rewriter_params.pyg | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/ast/fpa/fpa2bv_rewriter_params.pyg diff --git a/src/ast/fpa/fpa2bv_rewriter_params.pyg b/src/ast/fpa/fpa2bv_rewriter_params.pyg new file mode 100644 index 000000000..42df0fa0e --- /dev/null +++ b/src/ast/fpa/fpa2bv_rewriter_params.pyg @@ -0,0 +1,5 @@ +def_module_params(module_name='rewriter', + class_name='fpa2bv_rewriter_params', + export=True, + params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real)"), + )) From 376614a7822d8de38b764c5f6ba392930d8ea7d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 15:09:52 +0000 Subject: [PATCH 141/646] Java API: slight overhaul in preparation for the FP additions Signed-off-by: Christoph M. Wintersteiger --- src/api/java/AST.java | 30 +- src/api/java/ASTMap.java | 23 +- src/api/java/ASTVector.java | 20 +- src/api/java/AlgebraicNum.java | 22 +- src/api/java/ApplyResult.java | 6 +- src/api/java/ArithExpr.java | 2 +- src/api/java/ArrayExpr.java | 2 +- src/api/java/ArraySort.java | 4 + src/api/java/BitVecExpr.java | 4 +- src/api/java/BitVecSort.java | 2 + src/api/java/BoolExpr.java | 5 +- src/api/java/Constructor.java | 6 + src/api/java/ConstructorList.java | 1 + src/api/java/Context.java | 1009 +++++++++++------------- src/api/java/DatatypeExpr.java | 2 +- src/api/java/DatatypeSort.java | 5 + src/api/java/EnumSort.java | 4 + src/api/java/Expr.java | 692 ++++++++++++---- src/api/java/FiniteDomainSort.java | 1 + src/api/java/Fixedpoint.java | 11 +- src/api/java/FuncDecl.java | 26 +- src/api/java/FuncInterp.java | 16 +- src/api/java/Global.java | 20 +- src/api/java/Goal.java | 25 +- src/api/java/IntExpr.java | 3 +- src/api/java/IntSymbol.java | 5 +- src/api/java/InterpolationContext.java | 54 +- src/api/java/Log.java | 11 +- src/api/java/Model.java | 46 +- src/api/java/Probe.java | 4 +- src/api/java/RatNum.java | 5 +- src/api/java/RealExpr.java | 2 +- src/api/java/Solver.java | 83 +- src/api/java/Sort.java | 4 +- src/api/java/Statistics.java | 7 +- src/api/java/StringSymbol.java | 5 +- src/api/java/Tactic.java | 8 +- src/api/java/Version.java | 3 +- 38 files changed, 1289 insertions(+), 889 deletions(-) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index a201d5697..30d303d6c 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -28,7 +28,8 @@ public class AST extends Z3Object /** * Object comparison. - * another AST + * + * @param o another AST **/ public boolean equals(Object o) { @@ -46,10 +47,12 @@ public class AST extends Z3Object } /** - * Object Comparison. Another AST + * Object Comparison. + * @param other Another AST * - * @return Negative if the object should be sorted before , positive if after else zero. + * @return Negative if the object should be sorted before {@code other}, + * positive if after else zero. + * @throws Z3Exception on error **/ public int compareTo(Object other) throws Z3Exception { @@ -90,6 +93,7 @@ public class AST extends Z3Object /** * A unique identifier for the AST (unique among all ASTs). + * @throws Z3Exception on error **/ public int getId() throws Z3Exception { @@ -97,10 +101,11 @@ public class AST extends Z3Object } /** - * Translates (copies) the AST to the Context . A context + * Translates (copies) the AST to the Context {@code ctx}. + * @param ctx A context * - * @return A copy of the AST which is associated with + * @return A copy of the AST which is associated with {@code ctx} + * @throws Z3Exception on error **/ public AST translate(Context ctx) throws Z3Exception { @@ -114,6 +119,7 @@ public class AST extends Z3Object /** * The kind of the AST. + * @throws Z3Exception on error **/ public Z3_ast_kind getASTKind() throws Z3Exception { @@ -123,6 +129,8 @@ public class AST extends Z3Object /** * Indicates whether the AST is an Expr + * @throws Z3Exception on error + * @throws Z3Exception on error **/ public boolean isExpr() throws Z3Exception { @@ -140,6 +148,8 @@ public class AST extends Z3Object /** * Indicates whether the AST is an application + * @return a boolean + * @throws Z3Exception on error **/ public boolean isApp() throws Z3Exception { @@ -147,7 +157,9 @@ public class AST extends Z3Object } /** - * Indicates whether the AST is a BoundVariable + * Indicates whether the AST is a BoundVariable. + * @return a boolean + * @throws Z3Exception on error **/ public boolean isVar() throws Z3Exception { @@ -156,6 +168,8 @@ public class AST extends Z3Object /** * Indicates whether the AST is a Quantifier + * @return a boolean + * @throws Z3Exception on error **/ public boolean isQuantifier() throws Z3Exception { diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index 6a4e6d56f..3d63939ca 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -23,10 +23,10 @@ package com.microsoft.z3; class ASTMap extends Z3Object { /** - * Checks whether the map contains the key . An AST + * Checks whether the map contains the key {@code k}. + * @param k An AST * - * @return True if is a key in the map, false + * @return True if {@code k} is a key in the map, false * otherwise. **/ public boolean contains(AST k) throws Z3Exception @@ -37,9 +37,10 @@ class ASTMap extends Z3Object } /** - * Finds the value associated with the key . - * This function signs an error when is not a key in - * the map. An AST + * Finds the value associated with the key {@code k}. + * Remarks: This function signs an error when {@code k} is not a key in + * the map. + * @param k An AST * * @throws Z3Exception **/ @@ -50,8 +51,9 @@ class ASTMap extends Z3Object } /** - * Stores or replaces a new key/value pair in the map. The - * key AST The value AST + * Stores or replaces a new key/value pair in the map. + * @param k The key AST + * @param v The value AST **/ public void insert(AST k, AST v) throws Z3Exception { @@ -61,12 +63,11 @@ class ASTMap extends Z3Object } /** - * Erases the key from the map. An - * AST + * Erases the key {@code k} from the map. + * @param k An AST **/ public void erase(AST k) throws Z3Exception { - Native.astMapErase(getContext().nCtx(), getNativeObject(), k.getNativeObject()); } diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 07b7dbf56..d4df02244 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -31,9 +31,10 @@ class ASTVector extends Z3Object } /** - * Retrieves the i-th object in the vector. May throw an - * IndexOutOfBoundsException when is out of - * range. Index + * Retrieves the i-th object in the vector. + * Remarks: May throw an {@code IndexOutOfBoundsException} when + * {@code i} is out of range. + * @param i Index * * @return An AST * @throws Z3Exception @@ -52,8 +53,8 @@ class ASTVector extends Z3Object } /** - * Resize the vector to . The new size of the vector. + * Resize the vector to {@code newSize}. + * @param newSize The new size of the vector. **/ public void resize(int newSize) throws Z3Exception { @@ -61,8 +62,9 @@ class ASTVector extends Z3Object } /** - * Add the AST to the back of the vector. The size is - * increased by 1. An AST + * Add the AST {@code a} to the back of the vector. The size is + * increased by 1. + * @param a An AST **/ public void push(AST a) throws Z3Exception { @@ -70,8 +72,8 @@ class ASTVector extends Z3Object } /** - * Translates all ASTs in the vector to . A context + * Translates all ASTs in the vector to {@code ctx}. + * @param ctx A context * * @return A new ASTVector * @throws Z3Exception diff --git a/src/api/java/AlgebraicNum.java b/src/api/java/AlgebraicNum.java index 340f37f80..322b24d39 100644 --- a/src/api/java/AlgebraicNum.java +++ b/src/api/java/AlgebraicNum.java @@ -24,11 +24,13 @@ public class AlgebraicNum extends ArithExpr { /** * Return a upper bound for a given real algebraic number. The interval - * isolating the number is smaller than 1/10^. - * the - * precision of the result + * isolating the number is smaller than 1/10^{@code precision}. + * + * @see Expr#isAlgebraicNumber + * @param precision the precision of the result * * @return A numeral Expr of sort Real + * @throws Z3Exception on error **/ public RatNum toUpper(int precision) throws Z3Exception { @@ -39,10 +41,13 @@ public class AlgebraicNum extends ArithExpr /** * Return a lower bound for the given real algebraic number. The interval - * isolating the number is smaller than 1/10^. - * + * isolating the number is smaller than 1/10^{@code precision}. + * + * @see Expr#isAlgebraicNumber + * @param precision precision * * @return A numeral Expr of sort Real + * @throws Z3Exception on error **/ public RatNum toLower(int precision) throws Z3Exception { @@ -52,8 +57,11 @@ public class AlgebraicNum extends ArithExpr } /** - * Returns a string representation in decimal notation. The result - * has at most decimal places. + * Returns a string representation in decimal notation. + * Remarks: The result has at most {@code precision} decimal places. + * @param precision precision + * @return String + * @throws Z3Exception on error **/ public String toDecimal(int precision) throws Z3Exception { diff --git a/src/api/java/ApplyResult.java b/src/api/java/ApplyResult.java index c550c05ae..d21a78a9c 100644 --- a/src/api/java/ApplyResult.java +++ b/src/api/java/ApplyResult.java @@ -48,10 +48,10 @@ public class ApplyResult extends Z3Object } /** - * Convert a model for the subgoal into a model for the - * original goal g, that the ApplyResult was obtained from. + * Convert a model for the subgoal {@code i} into a model for the + * original goal {@code g}, that the ApplyResult was obtained from. * - * @return A model for g + * @return A model for {@code g} * @throws Z3Exception **/ public Model convertModel(int i, Model m) throws Z3Exception diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index 83ec35d01..a788fda35 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -23,7 +23,7 @@ package com.microsoft.z3; public class ArithExpr extends Expr { /** - * Constructor for ArithExpr + * Constructor for ArithExpr **/ protected ArithExpr(Context ctx) { diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index 2d5a5a273..34d04693f 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -24,7 +24,7 @@ package com.microsoft.z3; public class ArrayExpr extends Expr { /** - * Constructor for ArrayExpr + * Constructor for ArrayExpr **/ protected ArrayExpr(Context ctx) { diff --git a/src/api/java/ArraySort.java b/src/api/java/ArraySort.java index a371fa3cb..ab545b7c1 100644 --- a/src/api/java/ArraySort.java +++ b/src/api/java/ArraySort.java @@ -25,6 +25,8 @@ public class ArraySort extends Sort /** * The domain of the array sort. * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort **/ public Sort getDomain() throws Z3Exception { @@ -35,6 +37,8 @@ public class ArraySort extends Sort /** * The range of the array sort. * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort **/ public Sort getRange() throws Z3Exception { diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 24b1cfdf3..c410e33a6 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -26,6 +26,8 @@ public class BitVecExpr extends Expr /** * The size of the sort of a bit-vector term. * @throws Z3Exception + * @throws Z3Exception on error + * @return an int **/ public int getSortSize() throws Z3Exception { @@ -33,7 +35,7 @@ public class BitVecExpr extends Expr } /** - * Constructor for BitVecExpr + * Constructor for BitVecExpr **/ BitVecExpr(Context ctx) { diff --git a/src/api/java/BitVecSort.java b/src/api/java/BitVecSort.java index be406c806..69d74151c 100644 --- a/src/api/java/BitVecSort.java +++ b/src/api/java/BitVecSort.java @@ -24,6 +24,8 @@ public class BitVecSort extends Sort { /** * The size of the bit-vector sort. + * @throws Z3Exception on error + * @return an int **/ public int getSize() throws Z3Exception { diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index 99453496a..ea3cdbfb4 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -23,7 +23,7 @@ package com.microsoft.z3; public class BoolExpr extends Expr { /** - * Constructor for BoolExpr + * Constructor for BoolExpr **/ protected BoolExpr(Context ctx) { @@ -31,8 +31,9 @@ public class BoolExpr extends Expr } /** - * Constructor for BoolExpr + * Constructor for BoolExpr * @throws Z3Exception + * @throws Z3Exception on error **/ BoolExpr(Context ctx, long obj) throws Z3Exception { diff --git a/src/api/java/Constructor.java b/src/api/java/Constructor.java index 4813c2b0a..a5440092c 100644 --- a/src/api/java/Constructor.java +++ b/src/api/java/Constructor.java @@ -25,6 +25,8 @@ public class Constructor extends Z3Object /** * The number of fields of the constructor. * @throws Z3Exception + * @throws Z3Exception on error + * @return an int **/ public int getNumFields() throws Z3Exception { @@ -34,6 +36,7 @@ public class Constructor extends Z3Object /** * The function declaration of the constructor. * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl ConstructorDecl() throws Z3Exception { @@ -47,6 +50,7 @@ public class Constructor extends Z3Object /** * The function declaration of the tester. * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl getTesterDecl() throws Z3Exception { @@ -60,6 +64,7 @@ public class Constructor extends Z3Object /** * The function declarations of the accessors * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl[] getAccessorDecls() throws Z3Exception { @@ -75,6 +80,7 @@ public class Constructor extends Z3Object /** * Destructor. + * @throws Z3Exception on error **/ protected void finalize() throws Z3Exception { diff --git a/src/api/java/ConstructorList.java b/src/api/java/ConstructorList.java index 315a2e535..b38678b8a 100644 --- a/src/api/java/ConstructorList.java +++ b/src/api/java/ConstructorList.java @@ -24,6 +24,7 @@ public class ConstructorList extends Z3Object { /** * Destructor. + * @throws Z3Exception on error **/ protected void finalize() throws Z3Exception { diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 4fbd79be2..f7fa471fb 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -38,7 +38,7 @@ public class Context extends IDisposable /** * Constructor. - * + * Remarks: * The following parameters can be set: * - proof (Boolean) Enable proof generation * - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting @@ -51,8 +51,7 @@ public class Context extends IDisposable * - model_validate validate models produced by solvers * - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver * Note that in previous versions of Z3, this constructor was also used to set global and - * module parameters. For this purpose we should now use - * + * module parameters. For this purpose we should now use {@code Global.setParameter} **/ public Context(Map settings) throws Z3Exception { @@ -66,9 +65,9 @@ public class Context extends IDisposable } /** - * Creates a new symbol using an integer. Not all integers can be - * passed to this function. The legal range of unsigned integers is 0 to - * 2^30-1. + * Creates a new symbol using an integer. + * Remarks: Not all integers can be passed to this function. + * The legal range of unsigned integers is 0 to 2^30-1. **/ public IntSymbol mkSymbol(int i) throws Z3Exception { @@ -135,7 +134,6 @@ public class Context extends IDisposable **/ public BoolSort mkBoolSort() throws Z3Exception { - return new BoolSort(this); } @@ -144,7 +142,6 @@ public class Context extends IDisposable **/ public UninterpretedSort mkUninterpretedSort(Symbol s) throws Z3Exception { - checkContextMatch(s); return new UninterpretedSort(this, s); } @@ -154,7 +151,6 @@ public class Context extends IDisposable **/ public UninterpretedSort mkUninterpretedSort(String str) throws Z3Exception { - return mkUninterpretedSort(mkSymbol(str)); } @@ -163,7 +159,6 @@ public class Context extends IDisposable **/ public IntSort mkIntSort() throws Z3Exception { - return new IntSort(this); } @@ -172,7 +167,6 @@ public class Context extends IDisposable **/ public RealSort mkRealSort() throws Z3Exception { - return new RealSort(this); } @@ -181,7 +175,6 @@ public class Context extends IDisposable **/ public BitVecSort mkBitVecSort(int size) throws Z3Exception { - return new BitVecSort(this, Native.mkBvSort(nCtx(), size)); } @@ -190,7 +183,6 @@ public class Context extends IDisposable **/ public ArraySort mkArraySort(Sort domain, Sort range) throws Z3Exception { - checkContextMatch(domain); checkContextMatch(range); return new ArraySort(this, domain, range); @@ -202,7 +194,6 @@ public class Context extends IDisposable public TupleSort mkTupleSort(Symbol name, Symbol[] fieldNames, Sort[] fieldSorts) throws Z3Exception { - checkContextMatch(name); checkContextMatch(fieldNames); checkContextMatch(fieldSorts); @@ -216,7 +207,6 @@ public class Context extends IDisposable public EnumSort mkEnumSort(Symbol name, Symbol... enumNames) throws Z3Exception { - checkContextMatch(name); checkContextMatch(enumNames); return new EnumSort(this, name, enumNames); @@ -236,7 +226,6 @@ public class Context extends IDisposable **/ public ListSort mkListSort(Symbol name, Sort elemSort) throws Z3Exception { - checkContextMatch(name); checkContextMatch(elemSort); return new ListSort(this, name, elemSort); @@ -247,7 +236,6 @@ public class Context extends IDisposable **/ public ListSort mkListSort(String name, Sort elemSort) throws Z3Exception { - checkContextMatch(elemSort); return new ListSort(this, mkSymbol(name), elemSort); } @@ -258,7 +246,6 @@ public class Context extends IDisposable public FiniteDomainSort mkFiniteDomainSort(Symbol name, long size) throws Z3Exception { - checkContextMatch(name); return new FiniteDomainSort(this, name, size); } @@ -269,20 +256,19 @@ public class Context extends IDisposable public FiniteDomainSort mkFiniteDomainSort(String name, long size) throws Z3Exception { - return new FiniteDomainSort(this, mkSymbol(name), size); } /** - * Create a datatype constructor. constructor - * name name of recognizer - * function. names of the constructor - * fields. field sorts, 0 if the field sort - * refers to a recursive sort. reference to - * datatype sort that is an argument to the constructor; if the - * corresponding sort reference is 0, then the value in sort_refs should be + * Create a datatype constructor. + * @param name constructor name + * @param recognizer name of recognizer function. + * @param fieldNames names of the constructor fields. + * @param sorts field sorts, 0 if the field sort refers to a recursive sort. + * @param sortRefs reference to datatype sort that is an argument to the + * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be * an index referring to one of the recursive datatypes that is - * declared. + * declared. **/ public Constructor mkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) @@ -294,9 +280,12 @@ public class Context extends IDisposable } /** - * Create a datatype constructor. + * Create a datatype constructor. + * @param name + * @param recognizer + * @param fieldNames + * @param sorts + * @param sortRefs * * @return **/ @@ -315,7 +304,6 @@ public class Context extends IDisposable public DatatypeSort mkDatatypeSort(Symbol name, Constructor[] constructors) throws Z3Exception { - checkContextMatch(name); checkContextMatch(constructors); return new DatatypeSort(this, name, constructors); @@ -327,20 +315,18 @@ public class Context extends IDisposable public DatatypeSort mkDatatypeSort(String name, Constructor[] constructors) throws Z3Exception { - checkContextMatch(constructors); return new DatatypeSort(this, mkSymbol(name), constructors); } /** - * Create mutually recursive datatypes. names of - * datatype sorts list of constructors, one list per - * sort. + * Create mutually recursive datatypes. + * @param names names of datatype sorts + * @param c list of constructors, one list per sort. **/ public DatatypeSort[] mkDatatypeSorts(Symbol[] names, Constructor[][] c) throws Z3Exception { - checkContextMatch(names); int n = (int) names.length; ConstructorList[] cla = new ConstructorList[n]; @@ -363,15 +349,15 @@ public class Context extends IDisposable } /** - * Create mutually recursive data-types. + * Create mutually recursive data-types. + * @param names + * @param c * * @return **/ public DatatypeSort[] mkDatatypeSorts(String[] names, Constructor[][] c) throws Z3Exception { - return mkDatatypeSorts(MkSymbols(names), c); } @@ -381,7 +367,6 @@ public class Context extends IDisposable public FuncDecl mkFuncDecl(Symbol name, Sort[] domain, Sort range) throws Z3Exception { - checkContextMatch(name); checkContextMatch(domain); checkContextMatch(range); @@ -394,7 +379,6 @@ public class Context extends IDisposable public FuncDecl mkFuncDecl(Symbol name, Sort domain, Sort range) throws Z3Exception { - checkContextMatch(name); checkContextMatch(domain); checkContextMatch(range); @@ -408,7 +392,6 @@ public class Context extends IDisposable public FuncDecl mkFuncDecl(String name, Sort[] domain, Sort range) throws Z3Exception { - checkContextMatch(domain); checkContextMatch(range); return new FuncDecl(this, mkSymbol(name), domain, range); @@ -420,7 +403,6 @@ public class Context extends IDisposable public FuncDecl mkFuncDecl(String name, Sort domain, Sort range) throws Z3Exception { - checkContextMatch(domain); checkContextMatch(range); Sort[] q = new Sort[] { domain }; @@ -428,14 +410,14 @@ public class Context extends IDisposable } /** - * Creates a fresh function declaration with a name prefixed with . + * Creates a fresh function declaration with a name prefixed with + * {@code prefix}. + * @see mkFuncDecl(String,Sort,Sort) + * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) throws Z3Exception { - checkContextMatch(domain); checkContextMatch(range); return new FuncDecl(this, prefix, domain, range); @@ -446,7 +428,6 @@ public class Context extends IDisposable **/ public FuncDecl mkConstDecl(Symbol name, Sort range) throws Z3Exception { - checkContextMatch(name); checkContextMatch(range); return new FuncDecl(this, name, null, range); @@ -457,27 +438,27 @@ public class Context extends IDisposable **/ public FuncDecl mkConstDecl(String name, Sort range) throws Z3Exception { - checkContextMatch(range); return new FuncDecl(this, mkSymbol(name), null, range); } /** * Creates a fresh constant function declaration with a name prefixed with - * . - * + * {@code prefix"}. + * @see mkFuncDecl(String,Sort,Sort) + * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshConstDecl(String prefix, Sort range) throws Z3Exception { - checkContextMatch(range); return new FuncDecl(this, prefix, null, range); } /** - * Creates a new bound variable. The de-Bruijn index of - * the variable The sort of the variable + * Creates a new bound variable. + * @param index The de-Bruijn index of the variable + * @param ty The sort of the variable **/ public Expr mkBound(int index, Sort ty) throws Z3Exception { @@ -499,12 +480,11 @@ public class Context extends IDisposable } /** - * Creates a new Constant of sort and named - * . + * Creates a new Constant of sort {@code range} and named + * {@code name}. **/ public Expr mkConst(Symbol name, Sort range) throws Z3Exception { - checkContextMatch(name); checkContextMatch(range); @@ -515,34 +495,31 @@ public class Context extends IDisposable } /** - * Creates a new Constant of sort and named - * . + * Creates a new Constant of sort {@code range} and named + * {@code name}. **/ public Expr mkConst(String name, Sort range) throws Z3Exception { - return mkConst(mkSymbol(name), range); } /** - * Creates a fresh Constant of sort and a name - * prefixed with . + * Creates a fresh Constant of sort {@code range} and a name + * prefixed with {@code prefix}. **/ public Expr mkFreshConst(String prefix, Sort range) throws Z3Exception { - checkContextMatch(range); return Expr.create(this, Native.mkFreshConst(nCtx(), prefix, range.getNativeObject())); } /** - * Creates a fresh constant from the FuncDecl . A decl of a 0-arity function + * Creates a fresh constant from the FuncDecl {@code f}. + * @param f A decl of a 0-arity function **/ public Expr mkConst(FuncDecl f) throws Z3Exception { - return mkApp(f, (Expr[]) null); } @@ -551,7 +528,6 @@ public class Context extends IDisposable **/ public BoolExpr mkBoolConst(Symbol name) throws Z3Exception { - return (BoolExpr) mkConst(name, getBoolSort()); } @@ -560,7 +536,6 @@ public class Context extends IDisposable **/ public BoolExpr mkBoolConst(String name) throws Z3Exception { - return (BoolExpr) mkConst(mkSymbol(name), getBoolSort()); } @@ -569,7 +544,6 @@ public class Context extends IDisposable **/ public IntExpr mkIntConst(Symbol name) throws Z3Exception { - return (IntExpr) mkConst(name, getIntSort()); } @@ -578,7 +552,6 @@ public class Context extends IDisposable **/ public IntExpr mkIntConst(String name) throws Z3Exception { - return (IntExpr) mkConst(name, getIntSort()); } @@ -587,7 +560,6 @@ public class Context extends IDisposable **/ public RealExpr mkRealConst(Symbol name) throws Z3Exception { - return (RealExpr) mkConst(name, getRealSort()); } @@ -596,7 +568,6 @@ public class Context extends IDisposable **/ public RealExpr mkRealConst(String name) throws Z3Exception { - return (RealExpr) mkConst(name, getRealSort()); } @@ -605,7 +576,6 @@ public class Context extends IDisposable **/ public BitVecExpr mkBVConst(Symbol name, int size) throws Z3Exception { - return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } @@ -614,7 +584,6 @@ public class Context extends IDisposable **/ public BitVecExpr mkBVConst(String name, int size) throws Z3Exception { - return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } @@ -653,7 +622,7 @@ public class Context extends IDisposable } /** - * Creates the equality = . + * Creates the equality {@code x"/> = An expression with Boolean - * sort An expression An - * expression with the same sort as + * {@code ite(t1, t2, t3)}. + * @param t1 An expression with Boolean sort + * @param t2 An expression + * @param t3 An expression with the same sort as {@code t2} **/ public Expr mkITE(BoolExpr t1, Expr t2, Expr t3) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); checkContextMatch(t3); @@ -700,11 +668,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 iff t2. + * Create an expression representing {@code t1 iff t2}. **/ public BoolExpr mkIff(BoolExpr t1, BoolExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkIff(nCtx(), t1.getNativeObject(), @@ -712,11 +679,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 -> t2. + * Create an expression representing {@code t1 -> t2}. **/ public BoolExpr mkImplies(BoolExpr t1, BoolExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkImplies(nCtx(), @@ -724,11 +690,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 xor t2. + * Create an expression representing {@code t1 xor t2}. **/ public BoolExpr mkXor(BoolExpr t1, BoolExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkXor(nCtx(), t1.getNativeObject(), @@ -736,77 +701,70 @@ public class Context extends IDisposable } /** - * Create an expression representing t[0] and t[1] and .... + * Create an expression representing {@code t[0] and t[1] and ...}. **/ public BoolExpr mkAnd(BoolExpr... t) throws Z3Exception { - checkContextMatch(t); return new BoolExpr(this, Native.mkAnd(nCtx(), (int) t.length, AST.arrayToNative(t))); } /** - * Create an expression representing t[0] or t[1] or .... + * Create an expression representing {@code t[0] or t[1] or ...}. **/ public BoolExpr mkOr(BoolExpr... t) throws Z3Exception { - checkContextMatch(t); return new BoolExpr(this, Native.mkOr(nCtx(), (int) t.length, AST.arrayToNative(t))); } /** - * Create an expression representing t[0] + t[1] + .... + * Create an expression representing {@code t[0] + t[1] + ...}. **/ public ArithExpr mkAdd(ArithExpr... t) throws Z3Exception { - checkContextMatch(t); return (ArithExpr) Expr.create(this, Native.mkAdd(nCtx(), (int) t.length, AST.arrayToNative(t))); } /** - * Create an expression representing t[0] * t[1] * .... + * Create an expression representing {@code t[0] * t[1] * ...}. **/ public ArithExpr mkMul(ArithExpr... t) throws Z3Exception { - checkContextMatch(t); return (ArithExpr) Expr.create(this, Native.mkMul(nCtx(), (int) t.length, AST.arrayToNative(t))); } /** - * Create an expression representing t[0] - t[1] - .... + * Create an expression representing {@code t[0] - t[1] - ...}. **/ public ArithExpr mkSub(ArithExpr... t) throws Z3Exception { - checkContextMatch(t); return (ArithExpr) Expr.create(this, Native.mkSub(nCtx(), (int) t.length, AST.arrayToNative(t))); } /** - * Create an expression representing -t. + * Create an expression representing {@code -t}. **/ public ArithExpr mkUnaryMinus(ArithExpr t) throws Z3Exception { - checkContextMatch(t); return (ArithExpr) Expr.create(this, Native.mkUnaryMinus(nCtx(), t.getNativeObject())); } /** - * Create an expression representing t1 / t2. + * Create an expression representing {@code t1 / t2}. **/ public ArithExpr mkDiv(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return (ArithExpr) Expr.create(this, Native.mkDiv(nCtx(), @@ -814,12 +772,12 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 mod t2. The - * arguments must have int type. + * Create an expression representing {@code t1 mod t2}. + * Remarks: The + * arguments must have int type. **/ public IntExpr mkMod(IntExpr t1, IntExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new IntExpr(this, Native.mkMod(nCtx(), t1.getNativeObject(), @@ -827,12 +785,12 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 rem t2. The - * arguments must have int type. + * Create an expression representing {@code t1 rem t2}. + * Remarks: The + * arguments must have int type. **/ public IntExpr mkRem(IntExpr t1, IntExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new IntExpr(this, Native.mkRem(nCtx(), t1.getNativeObject(), @@ -840,11 +798,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 ^ t2. + * Create an expression representing {@code t1 ^ t2}. **/ public ArithExpr mkPower(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return (ArithExpr) Expr.create( @@ -854,11 +811,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 < t2 + * Create an expression representing {@code t1 < t2} **/ public BoolExpr mkLt(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkLt(nCtx(), t1.getNativeObject(), @@ -866,11 +822,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 <= t2 + * Create an expression representing {@code t1 <= t2} **/ public BoolExpr mkLe(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkLe(nCtx(), t1.getNativeObject(), @@ -878,11 +833,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 > t2 + * Create an expression representing {@code t1 > t2} **/ public BoolExpr mkGt(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkGt(nCtx(), t1.getNativeObject(), @@ -890,11 +844,10 @@ public class Context extends IDisposable } /** - * Create an expression representing t1 >= t2 + * Create an expression representing {@code t1 >= t2} **/ public BoolExpr mkGe(ArithExpr t1, ArithExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkGe(nCtx(), t1.getNativeObject(), @@ -902,30 +855,30 @@ public class Context extends IDisposable } /** - * Coerce an integer to a real. There is also a converse operation + * Coerce an integer to a real. + * Remarks: There is also a converse operation * exposed. It follows the semantics prescribed by the SMT-LIB standard. * * You can take the floor of a real by creating an auxiliary integer Term - * k and and asserting - * MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. The argument - * must be of integer sort. + * {@code k} and and asserting + * {@code MakeInt2Real(k) <= t1 < MkInt2Real(k)+1}. The argument + * must be of integer sort. **/ public RealExpr mkInt2Real(IntExpr t) throws Z3Exception { - checkContextMatch(t); return new RealExpr(this, Native.mkInt2real(nCtx(), t.getNativeObject())); } /** - * Coerce a real to an integer. The semantics of this function + * Coerce a real to an integer. + * Remarks: The semantics of this function * follows the SMT-LIB standard for the function to_int. The argument must - * be of real sort. + * be of real sort. **/ public IntExpr mkReal2Int(RealExpr t) throws Z3Exception { - checkContextMatch(t); return new IntExpr(this, Native.mkReal2int(nCtx(), t.getNativeObject())); } @@ -935,29 +888,28 @@ public class Context extends IDisposable **/ public BoolExpr mkIsInteger(RealExpr t) throws Z3Exception { - checkContextMatch(t); return new BoolExpr(this, Native.mkIsInt(nCtx(), t.getNativeObject())); } /** - * Bitwise negation. The argument must have a bit-vector - * sort. + * Bitwise negation. + * Remarks: The argument must have a bit-vector + * sort. **/ public BitVecExpr mkBVNot(BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkBvnot(nCtx(), t.getNativeObject())); } /** * Take conjunction of bits in a vector, return vector of length 1. - * The argument must have a bit-vector sort. + * + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedAND(BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkBvredand(nCtx(), t.getNativeObject())); @@ -965,23 +917,23 @@ public class Context extends IDisposable /** * Take disjunction of bits in a vector, return vector of length 1. - * The argument must have a bit-vector sort. + * + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedOR(BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkBvredor(nCtx(), t.getNativeObject())); } /** - * Bitwise conjunction. The arguments must have a bit-vector - * sort. + * Bitwise conjunction. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvand(nCtx(), @@ -989,12 +941,12 @@ public class Context extends IDisposable } /** - * Bitwise disjunction. The arguments must have a bit-vector - * sort. + * Bitwise disjunction. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvor(nCtx(), t1.getNativeObject(), @@ -1002,12 +954,12 @@ public class Context extends IDisposable } /** - * Bitwise XOR. The arguments must have a bit-vector - * sort. + * Bitwise XOR. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVXOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvxor(nCtx(), @@ -1015,12 +967,12 @@ public class Context extends IDisposable } /** - * Bitwise NAND. The arguments must have a bit-vector - * sort. + * Bitwise NAND. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVNAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvnand(nCtx(), @@ -1028,12 +980,12 @@ public class Context extends IDisposable } /** - * Bitwise NOR. The arguments must have a bit-vector - * sort. + * Bitwise NOR. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvnor(nCtx(), @@ -1041,12 +993,12 @@ public class Context extends IDisposable } /** - * Bitwise XNOR. The arguments must have a bit-vector - * sort. + * Bitwise XNOR. + * Remarks: The arguments must have a bit-vector + * sort. **/ public BitVecExpr mkBVXNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvxnor(nCtx(), @@ -1054,23 +1006,23 @@ public class Context extends IDisposable } /** - * Standard two's complement unary minus. The arguments must have a - * bit-vector sort. + * Standard two's complement unary minus. + * Remarks: The arguments must have a + * bit-vector sort. **/ public BitVecExpr mkBVNeg(BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkBvneg(nCtx(), t.getNativeObject())); } /** - * Two's complement addition. The arguments must have the same - * bit-vector sort. + * Two's complement addition. + * Remarks: The arguments must have the same + * bit-vector sort. **/ public BitVecExpr mkBVAdd(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvadd(nCtx(), @@ -1078,12 +1030,12 @@ public class Context extends IDisposable } /** - * Two's complement subtraction. The arguments must have the same - * bit-vector sort. + * Two's complement subtraction. + * Remarks: The arguments must have the same + * bit-vector sort. **/ public BitVecExpr mkBVSub(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvsub(nCtx(), @@ -1091,12 +1043,12 @@ public class Context extends IDisposable } /** - * Two's complement multiplication. The arguments must have the - * same bit-vector sort. + * Two's complement multiplication. + * Remarks: The arguments must have the + * same bit-vector sort. **/ public BitVecExpr mkBVMul(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvmul(nCtx(), @@ -1104,14 +1056,14 @@ public class Context extends IDisposable } /** - * Unsigned division. It is defined as the floor of - * t1/t2 if \c t2 is different from zero. If t2 is + * Unsigned division. + * Remarks: It is defined as the floor of + * {@code t1/t2} if \c t2 is different from zero. If {@code t2} is * zero, then the result is undefined. The arguments must have the same - * bit-vector sort. + * bit-vector sort. **/ public BitVecExpr mkBVUDiv(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvudiv(nCtx(), @@ -1119,20 +1071,20 @@ public class Context extends IDisposable } /** - * Signed division. It is defined in the following way: + * Signed division. + * Remarks: It is defined in the following way: * - * - The \c floor of t1/t2 if \c t2 is different from zero, and - * t1*t2 >= 0. + * - The \c floor of {@code t1/t2} if \c t2 is different from zero, and + * {@code t1*t2 >= 0}. * - * - The \c ceiling of t1/t2 if \c t2 is different from zero, - * and t1*t2 < 0. + * - The \c ceiling of {@code t1/t2} if \c t2 is different from zero, + * and {@code t1*t2 < 0}. * - * If t2 is zero, then the result is undefined. The arguments - * must have the same bit-vector sort. + * If {@code t2} is zero, then the result is undefined. The arguments + * must have the same bit-vector sort. **/ public BitVecExpr mkBVSDiv(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvsdiv(nCtx(), @@ -1140,14 +1092,14 @@ public class Context extends IDisposable } /** - * Unsigned remainder. It is defined as - * t1 - (t1 /u t2) * t2, where /u represents - * unsigned division. If t2 is zero, then the result is - * undefined. The arguments must have the same bit-vector sort. + * Unsigned remainder. + * Remarks: It is defined as + * {@code t1 - (t1 /u t2) * t2}, where {@code /u} represents + * unsigned division. If {@code t2} is zero, then the result is + * undefined. The arguments must have the same bit-vector sort. **/ public BitVecExpr mkBVURem(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvurem(nCtx(), @@ -1155,17 +1107,17 @@ public class Context extends IDisposable } /** - * Signed remainder. It is defined as - * t1 - (t1 /s t2) * t2, where /s represents + * Signed remainder. + * Remarks: It is defined as + * {@code t1 - (t1 /s t2) * t2}, where {@code /s} represents * signed division. The most significant bit (sign) of the result is equal * to the most significant bit of \c t1. * - * If t2 is zero, then the result is undefined. The arguments - * must have the same bit-vector sort. + * If {@code t2} is zero, then the result is undefined. The arguments + * must have the same bit-vector sort. **/ public BitVecExpr mkBVSRem(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvsrem(nCtx(), @@ -1173,13 +1125,13 @@ public class Context extends IDisposable } /** - * Two's complement signed remainder (sign follows divisor). If - * t2 is zero, then the result is undefined. The arguments must - * have the same bit-vector sort. + * Two's complement signed remainder (sign follows divisor). + * Remarks: If + * {@code t2} is zero, then the result is undefined. The arguments must + * have the same bit-vector sort. **/ public BitVecExpr mkBVSMod(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvsmod(nCtx(), @@ -1187,12 +1139,12 @@ public class Context extends IDisposable } /** - * Unsigned less-than The arguments must have the same bit-vector - * sort. + * Unsigned less-than + * Remarks: The arguments must have the same bit-vector + * sort. **/ public BoolExpr mkBVULT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvult(nCtx(), t1.getNativeObject(), @@ -1200,12 +1152,12 @@ public class Context extends IDisposable } /** - * Two's complement signed less-than The arguments must have the - * same bit-vector sort. + * Two's complement signed less-than + * Remarks: The arguments must have the + * same bit-vector sort. **/ public BoolExpr mkBVSLT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvslt(nCtx(), t1.getNativeObject(), @@ -1213,12 +1165,12 @@ public class Context extends IDisposable } /** - * Unsigned less-than or equal to. The arguments must have the - * same bit-vector sort. + * Unsigned less-than or equal to. + * Remarks: The arguments must have the + * same bit-vector sort. **/ public BoolExpr mkBVULE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvule(nCtx(), t1.getNativeObject(), @@ -1226,12 +1178,12 @@ public class Context extends IDisposable } /** - * Two's complement signed less-than or equal to. The arguments - * must have the same bit-vector sort. + * Two's complement signed less-than or equal to. + * Remarks: The arguments + * must have the same bit-vector sort. **/ public BoolExpr mkBVSLE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsle(nCtx(), t1.getNativeObject(), @@ -1239,12 +1191,12 @@ public class Context extends IDisposable } /** - * Unsigned greater than or equal to. The arguments must have the - * same bit-vector sort. + * Unsigned greater than or equal to. + * Remarks: The arguments must have the + * same bit-vector sort. **/ public BoolExpr mkBVUGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvuge(nCtx(), t1.getNativeObject(), @@ -1252,12 +1204,12 @@ public class Context extends IDisposable } /** - * Two's complement signed greater than or equal to. The arguments - * must have the same bit-vector sort. + * Two's complement signed greater than or equal to. + * Remarks: The arguments + * must have the same bit-vector sort. **/ public BoolExpr mkBVSGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsge(nCtx(), t1.getNativeObject(), @@ -1265,12 +1217,12 @@ public class Context extends IDisposable } /** - * Unsigned greater-than. The arguments must have the same - * bit-vector sort. + * Unsigned greater-than. + * Remarks: The arguments must have the same + * bit-vector sort. **/ public BoolExpr mkBVUGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvugt(nCtx(), t1.getNativeObject(), @@ -1278,12 +1230,12 @@ public class Context extends IDisposable } /** - * Two's complement signed greater-than. The arguments must have - * the same bit-vector sort. + * Two's complement signed greater-than. + * Remarks: The arguments must have + * the same bit-vector sort. **/ public BoolExpr mkBVSGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsgt(nCtx(), t1.getNativeObject(), @@ -1291,17 +1243,17 @@ public class Context extends IDisposable } /** - * Bit-vector concatenation. The arguments must have a bit-vector - * sort. + * Bit-vector concatenation. + * Remarks: The arguments must have a bit-vector + * sort. * - * @return The result is a bit-vector of size n1+n2, where - * n1 (n2) is the size of t1 - * (t2). + * @return The result is a bit-vector of size {@code n1+n2}, where + * {@code n1} ({@code n2}) is the size of {@code t1} + * ({@code t2}). * **/ public BitVecExpr mkConcat(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkConcat(nCtx(), @@ -1309,74 +1261,74 @@ public class Context extends IDisposable } /** - * Bit-vector extraction. Extract the bits - * down to from a bitvector of size m to - * yield a new bitvector of size n, where - * n = high - low + 1. The argument must - * have a bit-vector sort. + * Bit-vector extraction. + * Remarks: Extract the bits {@code high} + * down to {@code low} from a bitvector of size {@code m} to + * yield a new bitvector of size {@code n}, where + * {@code n = high - low + 1}. The argument {@code t} must + * have a bit-vector sort. **/ public BitVecExpr mkExtract(int high, int low, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkExtract(nCtx(), high, low, t.getNativeObject())); } /** - * Bit-vector sign extension. Sign-extends the given bit-vector to - * the (signed) equivalent bitvector of size m+i, where \c m is - * the size of the given bit-vector. The argument must - * have a bit-vector sort. + * Bit-vector sign extension. + * Remarks: Sign-extends the given bit-vector to + * the (signed) equivalent bitvector of size {@code m+i}, where \c m is + * the size of the given bit-vector. The argument {@code t} must + * have a bit-vector sort. **/ public BitVecExpr mkSignExt(int i, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkSignExt(nCtx(), i, t.getNativeObject())); } /** - * Bit-vector zero extension. Extend the given bit-vector with - * zeros to the (unsigned) equivalent bitvector of size m+i, - * where \c m is the size of the given bit-vector. The argument must have a bit-vector sort. + * Bit-vector zero extension. + * Remarks: Extend the given bit-vector with + * zeros to the (unsigned) equivalent bitvector of size {@code m+i}, + * where \c m is the size of the given bit-vector. The argument {@code t} + * must have a bit-vector sort. **/ public BitVecExpr mkZeroExt(int i, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkZeroExt(nCtx(), i, t.getNativeObject())); } /** - * Bit-vector repetition. The argument must - * have a bit-vector sort. + * Bit-vector repetition. + * Remarks: The argument {@code t} must + * have a bit-vector sort. **/ public BitVecExpr mkRepeat(int i, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkRepeat(nCtx(), i, t.getNativeObject())); } /** - * Shift left. It is equivalent to multiplication by - * 2^x where \c x is the value of . + * Shift left. + * Remarks: It is equivalent to multiplication by + * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This * definition does not necessarily capture directly the semantics of the * programming language or assembly architecture you are modeling. * - * The arguments must have a bit-vector sort. + * The arguments must have a bit-vector sort. **/ public BitVecExpr mkBVSHL(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvshl(nCtx(), @@ -1384,18 +1336,18 @@ public class Context extends IDisposable } /** - * Logical shift right It is equivalent to unsigned division by - * 2^x where \c x is the value of . + * Logical shift right + * Remarks: It is equivalent to unsigned division by + * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This * definition does not necessarily capture directly the semantics of the * programming language or assembly architecture you are modeling. * - * The arguments must have a bit-vector sort. + * The arguments must have a bit-vector sort. **/ public BitVecExpr mkBVLSHR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvlshr(nCtx(), @@ -1403,7 +1355,8 @@ public class Context extends IDisposable } /** - * Arithmetic shift right It is like logical shift right except + * Arithmetic shift right + * Remarks: It is like logical shift right except * that the most significant bits of the result always copy the most * significant bit of the second argument. * @@ -1411,11 +1364,10 @@ public class Context extends IDisposable * definition does not necessarily capture directly the semantics of the * programming language or assembly architecture you are modeling. * - * The arguments must have a bit-vector sort. + * The arguments must have a bit-vector sort. **/ public BitVecExpr mkBVASHR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkBvashr(nCtx(), @@ -1423,38 +1375,38 @@ public class Context extends IDisposable } /** - * Rotate Left. Rotate bits of \c t to the left \c i times. The - * argument must have a bit-vector sort. + * Rotate Left. + * Remarks: Rotate bits of \c t to the left \c i times. The + * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateLeft(int i, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkRotateLeft(nCtx(), i, t.getNativeObject())); } /** - * Rotate Right. Rotate bits of \c t to the right \c i times. The - * argument must have a bit-vector sort. + * Rotate Right. + * Remarks: Rotate bits of \c t to the right \c i times. The + * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateRight(int i, BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkRotateRight(nCtx(), i, t.getNativeObject())); } /** - * Rotate Left. Rotate bits of to the left - * times. The arguments must have the same bit-vector - * sort. + * Rotate Left. + * Remarks: Rotate bits of {@code t1} to the left + * {@code t2} times. The arguments must have the same bit-vector + * sort. **/ public BitVecExpr mkBVRotateLeft(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkExtRotateLeft(nCtx(), @@ -1462,14 +1414,14 @@ public class Context extends IDisposable } /** - * Rotate Right. Rotate bits of to the - * right times. The arguments must have the same - * bit-vector sort. + * Rotate Right. + * Remarks: Rotate bits of {@code t1} to the + * right{@code t2} times. The arguments must have the same + * bit-vector sort. **/ public BitVecExpr mkBVRotateRight(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BitVecExpr(this, Native.mkExtRotateRight(nCtx(), @@ -1477,38 +1429,37 @@ public class Context extends IDisposable } /** - * Create an bit bit-vector from the integer argument - * . NB. This function is essentially treated + * Create an {@code n} bit bit-vector from the integer argument + * {@code t}. + * Remarks: NB. This function is essentially treated * as uninterpreted. So you cannot expect Z3 to precisely reflect the * semantics of this function when solving constraints with this function. * - * The argument must be of integer sort. + * The argument must be of integer sort. **/ public BitVecExpr mkInt2BV(int n, IntExpr t) throws Z3Exception { - checkContextMatch(t); return new BitVecExpr(this, Native.mkInt2bv(nCtx(), n, t.getNativeObject())); } /** - * Create an integer from the bit-vector argument . - * If \c is_signed is false, then the bit-vector \c t1 is treated + * Create an integer from the bit-vector argument {@code t}. + * Remarks: If \c is_signed is false, then the bit-vector \c t1 is treated * as unsigned. So the result is non-negative and in the range - * [0..2^N-1], where N are the number of bits in . If \c is_signed is true, \c t1 is treated as a signed + * {@code [0..2^N-1]}, where N are the number of bits in {@code t}. + * If \c is_signed is true, \c t1 is treated as a signed * bit-vector. * * NB. This function is essentially treated as uninterpreted. So you cannot * expect Z3 to precisely reflect the semantics of this function when * solving constraints with this function. * - * The argument must be of bit-vector sort. + * The argument must be of bit-vector sort. **/ public IntExpr mkBV2Int(BitVecExpr t, boolean signed) throws Z3Exception { - checkContextMatch(t); return new IntExpr(this, Native.mkBv2int(nCtx(), t.getNativeObject(), (signed) ? true : false)); @@ -1516,12 +1467,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not - * overflow. The arguments must be of bit-vector sort. + * overflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvaddNoOverflow(nCtx(), t1 @@ -1531,12 +1482,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not - * underflow. The arguments must be of bit-vector sort. + * underflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvaddNoUnderflow(nCtx(), @@ -1545,12 +1496,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not - * overflow. The arguments must be of bit-vector sort. + * overflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsubNoOverflow(nCtx(), @@ -1559,12 +1510,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not - * underflow. The arguments must be of bit-vector sort. + * underflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsubNoUnderflow(nCtx(), t1 @@ -1574,12 +1525,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise signed division does not - * overflow. The arguments must be of bit-vector sort. + * overflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvsdivNoOverflow(nCtx(), @@ -1588,11 +1539,11 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise negation does not - * overflow. The arguments must be of bit-vector sort. + * overflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVNegNoOverflow(BitVecExpr t) throws Z3Exception { - checkContextMatch(t); return new BoolExpr(this, Native.mkBvnegNoOverflow(nCtx(), t.getNativeObject())); @@ -1600,12 +1551,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not - * overflow. The arguments must be of bit-vector sort. + * overflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvmulNoOverflow(nCtx(), t1 @@ -1615,12 +1566,12 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not - * underflow. The arguments must be of bit-vector sort. + * underflow. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new BoolExpr(this, Native.mkBvmulNoUnderflow(nCtx(), @@ -1633,7 +1584,6 @@ public class Context extends IDisposable public ArrayExpr mkArrayConst(Symbol name, Sort domain, Sort range) throws Z3Exception { - return (ArrayExpr) mkConst(name, mkArraySort(domain, range)); } @@ -1643,22 +1593,24 @@ public class Context extends IDisposable public ArrayExpr mkArrayConst(String name, Sort domain, Sort range) throws Z3Exception { - return (ArrayExpr) mkConst(mkSymbol(name), mkArraySort(domain, range)); } /** - * Array read. The argument a is the array and - * i is the index of the array that gets read. + * Array read. + * Remarks: The argument {@code a} is the array and + * {@code i} is the index of the array that gets read. * - * The node a must have an array sort - * [domain -> range], and i must have the sort - * domain. The sort of the result is range. - * + * The node {@code a} must have an array sort + * {@code [domain -> range]}, and {@code i} must have the sort + * {@code domain}. The sort of the result is {@code range}. + * + * @see mkArraySort + * @see mkStore + **/ public Expr mkSelect(ArrayExpr a, Expr i) throws Z3Exception { - checkContextMatch(a); checkContextMatch(i); return Expr.create( @@ -1668,21 +1620,23 @@ public class Context extends IDisposable } /** - * Array update. The node a must have an array sort - * [domain -> range], i must have sort - * domain, v must have sort range. The sort of the - * result is [domain -> range]. The semantics of this function + * Array update. + * Remarks: The node {@code a} must have an array sort + * {@code [domain -> range]}, {@code i} must have sort + * {@code domain}, {@code v} must have sort range. The sort of the + * result is {@code [domain -> range]}. The semantics of this function * is given by the theory of arrays described in the SMT-LIB standard. See * http://smtlib.org for more details. The result of this function is an - * array that is equal to a (with respect to - * select) on all indices except for i, where it - * maps to v (and the select of a - * with respect to i may be a different value). + * array that is equal to {@code a} (with respect to + * {@code select}) on all indices except for {@code i}, where it + * maps to {@code v} (and the {@code select} of {@code a} + * with respect to {@code i} may be a different value). + * @see mkArraySort + * @see mkSelect + **/ public ArrayExpr mkStore(ArrayExpr a, Expr i, Expr v) throws Z3Exception { - checkContextMatch(a); checkContextMatch(i); checkContextMatch(v); @@ -1691,14 +1645,16 @@ public class Context extends IDisposable } /** - * Create a constant array. The resulting term is an array, such - * that a selecton an arbitrary index produces the value - * v. - * + * Create a constant array. + * Remarks: The resulting term is an array, such + * that a {@code select} on an arbitrary index produces the value + * {@code v}. + * @see mkArraySort + * @see mkSelect + * **/ public ArrayExpr mkConstArray(Sort domain, Expr v) throws Z3Exception { - checkContextMatch(domain); checkContextMatch(v); return new ArrayExpr(this, Native.mkConstArray(nCtx(), @@ -1706,17 +1662,20 @@ public class Context extends IDisposable } /** - * Maps f on the argument arrays. Eeach element of - * args must be of an array sort - * [domain_i -> range_i]. The function declaration - * f must have type range_1 .. range_n -> range. - * v must have sort range. The sort of the result is - * [domain_i -> range]. + * Maps f on the argument arrays. + * Remarks: Eeach element of + * {@code args} must be of an array sort + * {@code [domain_i -> range_i]}. The function declaration + * {@code f} must have type {@code range_1 .. range_n -> range}. + * {@code v} must have sort range. The sort of the result is + * {@code [domain_i -> range]}. + * @see mkArraySort + * @see mkSelect + * @see mkStore + **/ public ArrayExpr mkMap(FuncDecl f, ArrayExpr... args) throws Z3Exception { - checkContextMatch(f); checkContextMatch(args); return (ArrayExpr) Expr.create(this, Native.mkMap(nCtx(), @@ -1725,13 +1684,13 @@ public class Context extends IDisposable } /** - * Access the array default value. Produces the default range + * Access the array default value. + * Remarks: Produces the default range * value, for arrays that can be represented as finite maps with a default - * range value. + * range value. **/ public Expr mkTermArray(ArrayExpr array) throws Z3Exception { - checkContextMatch(array); return Expr.create(this, Native.mkArrayDefault(nCtx(), array.getNativeObject())); @@ -1742,7 +1701,6 @@ public class Context extends IDisposable **/ public SetSort mkSetSort(Sort ty) throws Z3Exception { - checkContextMatch(ty); return new SetSort(this, ty); } @@ -1752,7 +1710,6 @@ public class Context extends IDisposable **/ public Expr mkEmptySet(Sort domain) throws Z3Exception { - checkContextMatch(domain); return Expr.create(this, Native.mkEmptySet(nCtx(), domain.getNativeObject())); @@ -1763,7 +1720,6 @@ public class Context extends IDisposable **/ public Expr mkFullSet(Sort domain) throws Z3Exception { - checkContextMatch(domain); return Expr.create(this, Native.mkFullSet(nCtx(), domain.getNativeObject())); @@ -1774,7 +1730,6 @@ public class Context extends IDisposable **/ public Expr mkSetAdd(Expr set, Expr element) throws Z3Exception { - checkContextMatch(set); checkContextMatch(element); return Expr.create( @@ -1788,7 +1743,6 @@ public class Context extends IDisposable **/ public Expr mkSetDel(Expr set, Expr element) throws Z3Exception { - checkContextMatch(set); checkContextMatch(element); return Expr.create( @@ -1802,7 +1756,6 @@ public class Context extends IDisposable **/ public Expr mkSetUnion(Expr... args) throws Z3Exception { - checkContextMatch(args); return Expr.create( this, @@ -1815,7 +1768,6 @@ public class Context extends IDisposable **/ public Expr mkSetIntersection(Expr... args) throws Z3Exception { - checkContextMatch(args); return Expr.create( this, @@ -1828,7 +1780,6 @@ public class Context extends IDisposable **/ public Expr mkSetDifference(Expr arg1, Expr arg2) throws Z3Exception { - checkContextMatch(arg1); checkContextMatch(arg2); return Expr.create( @@ -1842,7 +1793,6 @@ public class Context extends IDisposable **/ public Expr mkSetComplement(Expr arg) throws Z3Exception { - checkContextMatch(arg); return Expr.create(this, Native.mkSetComplement(nCtx(), arg.getNativeObject())); @@ -1853,7 +1803,6 @@ public class Context extends IDisposable **/ public Expr mkSetMembership(Expr elem, Expr set) throws Z3Exception { - checkContextMatch(elem); checkContextMatch(set); return Expr.create( @@ -1867,7 +1816,6 @@ public class Context extends IDisposable **/ public Expr mkSetSubset(Expr arg1, Expr arg2) throws Z3Exception { - checkContextMatch(arg1); checkContextMatch(arg2); return Expr.create( @@ -1877,19 +1825,18 @@ public class Context extends IDisposable } /** - * Create a Term of a given sort. A string representing the - * Term value in decimal notation. If the given sort is a real, then the + * Create a Term of a given sort. + * @param v A string representing the term value in decimal notation. If the given sort is a real, then the * Term can be a rational, that is, a string of the form - * [num]* / [num]*. The sort of the + * {@code [num]* / [num]*}. + * @param ty The sort of the * numeral. In the current implementation, the given sort can be an int, - * real, or bit-vectors of arbitrary size. + * real, or bit-vectors of arbitrary size. * - * @return A Term with value and sort + * @return A Term with value {@code v} and sort {@code ty} **/ public Expr mkNumeral(String v, Sort ty) throws Z3Exception { - checkContextMatch(ty); return Expr.create(this, Native.mkNumeral(nCtx(), v, ty.getNativeObject())); @@ -1898,16 +1845,15 @@ public class Context extends IDisposable /** * Create a Term of a given sort. This function can be use to create * numerals that fit in a machine integer. It is slightly faster than - * MakeNumeral since it is not necessary to parse a string. - * Value of the numeral Sort of the - * numeral + * {@code MakeNumeral} since it is not necessary to parse a string. * - * @return A Term with value and type + * @param v Value of the numeral + * @param ty Sort of the numeral + * + * @return A Term with value {@code v} and type {@code ty} **/ public Expr mkNumeral(int v, Sort ty) throws Z3Exception { - checkContextMatch(ty); return Expr.create(this, Native.mkInt(nCtx(), v, ty.getNativeObject())); } @@ -1915,27 +1861,28 @@ public class Context extends IDisposable /** * Create a Term of a given sort. This function can be use to create * numerals that fit in a machine integer. It is slightly faster than - * MakeNumeral since it is not necessary to parse a string. - * Value of the numeral Sort of the - * numeral + * {@code MakeNumeral} since it is not necessary to parse a string. * - * @return A Term with value and type + * @param v Value of the numeral + * @param ty Sort of the numeral + * + * @return A Term with value {@code v} and type {@code ty} **/ public Expr mkNumeral(long v, Sort ty) throws Z3Exception { - checkContextMatch(ty); return Expr.create(this, Native.mkInt64(nCtx(), v, ty.getNativeObject())); } /** - * Create a real from a fraction. numerator of - * rational. denominator of rational. + * Create a real from a fraction. + * @param num numerator of rational. + * @param den denominator of rational. * - * @return A Term with value / - * and sort Real + * @return A Term with value {@code num}/{@code den} + * and sort Real + * @see mkNumeral(String,Sort) **/ public RatNum mkReal(int num, int den) throws Z3Exception { @@ -1946,10 +1893,10 @@ public class Context extends IDisposable } /** - * Create a real numeral. A string representing the Term - * value in decimal notation. + * Create a real numeral. + * @param v A string representing the Term value in decimal notation. * - * @return A Term with value and sort Real + * @return A Term with value {@code v} and sort Real **/ public RatNum mkReal(String v) throws Z3Exception { @@ -1959,9 +1906,10 @@ public class Context extends IDisposable } /** - * Create a real numeral. value of the numeral. + * Create a real numeral. + * @param v value of the numeral. * - * @return A Term with value and sort Real + * @return A Term with value {@code v} and sort Real **/ public RatNum mkReal(int v) throws Z3Exception { @@ -1971,9 +1919,10 @@ public class Context extends IDisposable } /** - * Create a real numeral. value of the numeral. + * Create a real numeral. + * @param v value of the numeral. * - * @return A Term with value and sort Real + * @return A Term with value {@code v} and sort Real **/ public RatNum mkReal(long v) throws Z3Exception { @@ -1983,8 +1932,8 @@ public class Context extends IDisposable } /** - * Create an integer numeral. A string representing the Term - * value in decimal notation. + * Create an integer numeral. + * @param v A string representing the Term value in decimal notation. **/ public IntNum mkInt(String v) throws Z3Exception { @@ -1994,9 +1943,10 @@ public class Context extends IDisposable } /** - * Create an integer numeral. value of the numeral. + * Create an integer numeral. + * @param v value of the numeral. * - * @return A Term with value and sort Integer + * @return A Term with value {@code v} and sort Integer **/ public IntNum mkInt(int v) throws Z3Exception { @@ -2006,9 +1956,10 @@ public class Context extends IDisposable } /** - * Create an integer numeral. value of the numeral. + * Create an integer numeral. + * @param v value of the numeral. * - * @return A Term with value and sort Integer + * @return A Term with value {@code v} and sort Integer **/ public IntNum mkInt(long v) throws Z3Exception { @@ -2018,54 +1969,56 @@ public class Context extends IDisposable } /** - * Create a bit-vector numeral. A string representing the - * value in decimal notation. the size of the - * bit-vector + * Create a bit-vector numeral. + * @param v A string representing the value in decimal notation. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(String v, int size) throws Z3Exception { - return (BitVecNum) mkNumeral(v, mkBitVecSort(size)); } /** - * Create a bit-vector numeral. value of the - * numeral. the size of the bit-vector + * Create a bit-vector numeral. + * @param v value of the numeral. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(int v, int size) throws Z3Exception { - return (BitVecNum) mkNumeral(v, mkBitVecSort(size)); } /** - * Create a bit-vector numeral. value of the - * numeral. * the size of the bit-vector + * Create a bit-vector numeral. + * @param v value of the numeral. * + * @param size the size of the bit-vector **/ public BitVecNum mkBV(long v, int size) throws Z3Exception { - return (BitVecNum) mkNumeral(v, mkBitVecSort(size)); } /** - * Create a universal Quantifier. Creates a forall formula, where - * is the weight, is - * an array of patterns, is an array with the sorts - * of the bound variables, is an array with the - * 'names' of the bound variables, and is the body + * Create a universal Quantifier. + * Remarks: Creates a forall formula, where + * {@code weight"/> is the weight, the sorts of the bound variables. names of the bound variables the - * body of the quantifier. quantifiers are + * importance of using the quantifier during instantiation. + * + * @param sorts the sorts of the bound variables. + * @param names names of the bound variables + * @param body the body of the quantifier. + * @param weight quantifiers are * associated with weights indicating the importance of using the quantifier - * during instantiation. By default, pass the weight 0. array containing the patterns created using - * MkPattern. array containing - * the anti-patterns created using MkPattern. optional symbol to track quantifier. optional symbol to track skolem constants. + * during instantiation. By default, pass the weight 0. + * @param patterns array containing the patterns created using + * {@code MkPattern}. + * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. + * @param quantifierID optional symbol to track quantifier. + * @param skolemID optional symbol to track skolem constants. **/ public Quantifier mkForall(Sort[] sorts, Symbol[] names, Expr body, int weight, Pattern[] patterns, Expr[] noPatterns, @@ -2089,8 +2042,8 @@ public class Context extends IDisposable } /** - * Create an existential Quantifier. + * Create an existential Quantifier. + * @see mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol) **/ public Quantifier mkExists(Sort[] sorts, Symbol[] names, Expr body, int weight, Pattern[] patterns, Expr[] noPatterns, @@ -2147,15 +2100,18 @@ public class Context extends IDisposable } /** - * Selects the format used for pretty-printing expressions. The + * Selects the format used for pretty-printing expressions. + * Remarks: The * default mode for pretty printing expressions is to produce SMT-LIB style * output where common subexpressions are printed at each occurrence. The * mode is called Z3_PRINT_SMTLIB_FULL. To print shared common * subexpressions only once, use the Z3_PRINT_LOW_LEVEL mode. To print in * way that conforms to SMT-LIB standards and uses let expressions to share - * common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + * common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + * @see AST#toString + * @see Pattern#toString + * @see FuncDecl#toString + * @see Sort#toString **/ public void setPrintMode(Z3_ast_print_mode value) throws Z3Exception { @@ -2163,14 +2119,15 @@ public class Context extends IDisposable } /** - * Convert a benchmark into an SMT-LIB formatted string. Name of the benchmark. The argument is optional. - * The benchmark logic. The status string (sat, unsat, or unknown) Other attributes, such as source, difficulty or - * category. Auxiliary - * assumptions. Formula to be checked for - * consistency in conjunction with assumptions. + * Convert a benchmark into an SMT-LIB formatted string. + * @param name Name of the benchmark. The argument is optional. + * + * @param logic The benchmark logic. + * @param status The status string (sat, unsat, or unknown) + * @param attributes Other attributes, such as source, difficulty or + * category. + * @param assumptions Auxiliary assumptions. + * @param formula Formula to be checked for consistency in conjunction with assumptions. * * @return A string representation of the benchmark. **/ @@ -2185,13 +2142,13 @@ public class Context extends IDisposable } /** - * Parse the given string using the SMT-LIB parser. The symbol + * Parse the given string using the SMT-LIB parser. + * Remarks: The symbol * table of the parser can be initialized using the given sorts and - * declarations. The symbols in the arrays and - * don't need to match the names of the sorts - * and declarations in the arrays and . This is a useful feature since we can use arbitrary names - * to reference sorts and declarations. + * declarations. The symbols in the arrays {@code sortNames} and + * {@code declNames} don't need to match the names of the sorts + * and declarations in the arrays {@code sorts} and {@code decls}. This is a useful feature since we can use arbitrary names + * to reference sorts and declarations. **/ public void parseSMTLIBString(String str, Symbol[] sortNames, Sort[] sorts, Symbol[] declNames, FuncDecl[] decls) throws Z3Exception @@ -2209,8 +2166,8 @@ public class Context extends IDisposable } /** - * Parse the given file using the SMT-LIB parser. + * Parse the given file using the SMT-LIB parser. + * @see parseSMTLIBString **/ public void parseSMTLIBFile(String fileName, Symbol[] sortNames, Sort[] sorts, Symbol[] declNames, FuncDecl[] decls) @@ -2230,7 +2187,7 @@ public class Context extends IDisposable /** * The number of SMTLIB formulas parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public int getNumSMTLIBFormulas() throws Z3Exception { @@ -2238,8 +2195,8 @@ public class Context extends IDisposable } /** - * The formulas parsed by the last call to ParseSMTLIBString or - * ParseSMTLIBFile. + * The formulas parsed by the last call to {@code ParseSMTLIBString} or + * {@code ParseSMTLIBFile}. **/ public BoolExpr[] getSMTLIBFormulas() throws Z3Exception { @@ -2254,7 +2211,7 @@ public class Context extends IDisposable /** * The number of SMTLIB assumptions parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public int getNumSMTLIBAssumptions() throws Z3Exception { @@ -2262,8 +2219,8 @@ public class Context extends IDisposable } /** - * The assumptions parsed by the last call to ParseSMTLIBString - * or ParseSMTLIBFile. + * The assumptions parsed by the last call to {@code ParseSMTLIBString} + * or {@code ParseSMTLIBFile}. **/ public BoolExpr[] getSMTLIBAssumptions() throws Z3Exception { @@ -2278,7 +2235,7 @@ public class Context extends IDisposable /** * The number of SMTLIB declarations parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public int getNumSMTLIBDecls() throws Z3Exception { @@ -2287,7 +2244,7 @@ public class Context extends IDisposable /** * The declarations parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public FuncDecl[] getSMTLIBDecls() throws Z3Exception { @@ -2301,7 +2258,7 @@ public class Context extends IDisposable /** * The number of SMTLIB sorts parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public int getNumSMTLIBSorts() throws Z3Exception { @@ -2310,7 +2267,7 @@ public class Context extends IDisposable /** * The declarations parsed by the last call to - * ParseSMTLIBString or ParseSMTLIBFile. + * {@code ParseSMTLIBString} or {@code ParseSMTLIBFile}. **/ public Sort[] getSMTLIBSorts() throws Z3Exception { @@ -2323,8 +2280,8 @@ public class Context extends IDisposable } /** - * Parse the given string using the SMT-LIB2 parser. + * Parse the given string using the SMT-LIB2 parser. + * @see parseSMTLIBString * * @return A conjunction of assertions in the scope (up to push/pop) at the * end of the string. @@ -2347,8 +2304,8 @@ public class Context extends IDisposable } /** - * Parse the given file using the SMT-LIB2 parser. + * Parse the given file using the SMT-LIB2 parser. + * @see parseSMTLIB2String **/ public BoolExpr parseSMTLIB2File(String fileName, Symbol[] sortNames, Sort[] sorts, Symbol[] declNames, FuncDecl[] decls) @@ -2369,18 +2326,18 @@ public class Context extends IDisposable } /** - * Creates a new Goal. Note that the Context must have been - * created with proof generation support if is set - * to true here. Indicates whether model - * generation should be enabled. Indicates - * whether unsat core generation should be enabled. Indicates whether proof generation should be - * enabled. + * Creates a new Goal. + * Remarks: Note that the Context must have been + * created with proof generation support if {@code proofs} is set + * to true here. + * @param models Indicates whether model generation should be enabled. + * @param unsatCores Indicates whether unsat core generation should be enabled. + * @param proofs Indicates whether proof generation should be + * enabled. **/ public Goal mkGoal(boolean models, boolean unsatCores, boolean proofs) throws Z3Exception { - return new Goal(this, models, unsatCores, proofs); } @@ -2389,7 +2346,6 @@ public class Context extends IDisposable **/ public Params mkParams() throws Z3Exception { - return new Params(this); } @@ -2420,7 +2376,6 @@ public class Context extends IDisposable **/ public String getTacticDescription(String name) throws Z3Exception { - return Native.tacticGetDescr(nCtx(), name); } @@ -2429,13 +2384,12 @@ public class Context extends IDisposable **/ public Tactic mkTactic(String name) throws Z3Exception { - return new Tactic(this, name); } /** - * Create a tactic that applies to a Goal and then - * to every subgoal produced by . + * Create a tactic that applies {@code t1} to a Goal and then + * {@code t2"/> to every subgoal produced by to a Goal and then - * to every subgoal produced by . - * Shorthand for AndThen. + * Create a tactic that applies {@code t1} to a Goal and then + * {@code t2"/> to every subgoal produced by to a Goal and if - * it fails then returns the result of applied to the + * Create a tactic that first applies {@code t1} to a Goal and if + * it fails then returns the result of {@code t2} applied to the * Goal. **/ public Tactic orElse(Tactic t1, Tactic t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new Tactic(this, Native.tacticOrElse(nCtx(), @@ -2487,28 +2441,26 @@ public class Context extends IDisposable } /** - * Create a tactic that applies to a goal for milliseconds. If does not - * terminate within milliseconds, then it fails. - * + * Create a tactic that applies {@code t} to a goal for {@code ms} milliseconds. + * Remarks: If {@code t} does not + * terminate within {@code ms} milliseconds, then it fails. + * **/ public Tactic tryFor(Tactic t, int ms) throws Z3Exception { - checkContextMatch(t); return new Tactic(this, Native.tacticTryFor(nCtx(), t.getNativeObject(), ms)); } /** - * Create a tactic that applies to a given goal if the - * probe evaluates to true. If evaluates to false, then the new tactic behaves like the - * skip tactic. + * Create a tactic that applies {@code t} to a given goal if the + * probe {@code p} evaluates to true. + * Remarks: If {@code p} evaluates to false, then the new tactic behaves like the + * {@code skip} tactic. **/ public Tactic when(Probe p, Tactic t) throws Z3Exception { - checkContextMatch(t); checkContextMatch(p); return new Tactic(this, Native.tacticWhen(nCtx(), p.getNativeObject(), @@ -2516,13 +2468,12 @@ public class Context extends IDisposable } /** - * Create a tactic that applies to a given goal if the - * probe evaluates to true and + * Create a tactic that applies {@code t1} to a given goal if the + * probe {@code p"/> evaluates to true and until the goal - * is not modified anymore or the maximum number of iterations is reached. + * Create a tactic that keeps applying {@code t} until the goal + * is not modified anymore or the maximum number of iterations {@code max} is reached. **/ public Tactic repeat(Tactic t, int max) throws Z3Exception { - checkContextMatch(t); return new Tactic(this, Native.tacticRepeat(nCtx(), t.getNativeObject(), max)); @@ -2548,7 +2497,6 @@ public class Context extends IDisposable **/ public Tactic skip() throws Z3Exception { - return new Tactic(this, Native.tacticSkip(nCtx())); } @@ -2557,17 +2505,15 @@ public class Context extends IDisposable **/ public Tactic fail() throws Z3Exception { - return new Tactic(this, Native.tacticFail(nCtx())); } /** - * Create a tactic that fails if the probe evaluates to + * Create a tactic that fails if the probe {@code p} evaluates to * false. **/ public Tactic failIf(Probe p) throws Z3Exception { - checkContextMatch(p); return new Tactic(this, Native.tacticFailIf(nCtx(), p.getNativeObject())); @@ -2583,8 +2529,8 @@ public class Context extends IDisposable } /** - * Create a tactic that applies using the given set of - * parameters . + * Create a tactic that applies {@code t} using the given set of + * parameters {@code p}. **/ public Tactic usingParams(Tactic t, Params p) throws Z3Exception { @@ -2595,9 +2541,10 @@ public class Context extends IDisposable } /** - * Create a tactic that applies using the given set of - * parameters . Alias for - * UsingParams + * Create a tactic that applies {@code t} using the given set of + * parameters {@code p}. + * Remarks: Alias for + * {@code UsingParams} **/ public Tactic with(Tactic t, Params p) throws Z3Exception { @@ -2615,13 +2562,11 @@ public class Context extends IDisposable } /** - * Create a tactic that applies to a given goal and - * then to every subgoal produced by . The subgoals are processed in parallel. + * Create a tactic that applies {@code t1} to a given goal and + * then {@code t2} to every subgoal produced by {@code t1}. The subgoals are processed in parallel. **/ public Tactic parAndThen(Tactic t1, Tactic t2) throws Z3Exception { - checkContextMatch(t1); checkContextMatch(t2); return new Tactic(this, Native.tacticParAndThen(nCtx(), @@ -2629,8 +2574,9 @@ public class Context extends IDisposable } /** - * Interrupt the execution of a Z3 procedure. This procedure can be - * used to interrupt: solvers, simplifiers and tactics. + * Interrupt the execution of a Z3 procedure. + * Remarks: This procedure can be + * used to interrupt: solvers, simplifiers and tactics. **/ public void interrupt() throws Z3Exception { @@ -2676,7 +2622,7 @@ public class Context extends IDisposable } /** - * Create a probe that always evaluates to . + * Create a probe that always evaluates to {@code val}. **/ public Probe constProbe(double val) throws Z3Exception { @@ -2685,12 +2631,10 @@ public class Context extends IDisposable /** * Create a probe that evaluates to "true" when the value returned by - * is less than the value returned by + * {@code p1} is less than the value returned by {@code p2} **/ public Probe lt(Probe p1, Probe p2) throws Z3Exception { - checkContextMatch(p1); checkContextMatch(p2); return new Probe(this, Native.probeLt(nCtx(), p1.getNativeObject(), @@ -2699,12 +2643,10 @@ public class Context extends IDisposable /** * Create a probe that evaluates to "true" when the value returned by - * is greater than the value returned by + * {@code p1} is greater than the value returned by {@code p2} **/ public Probe gt(Probe p1, Probe p2) throws Z3Exception { - checkContextMatch(p1); checkContextMatch(p2); return new Probe(this, Native.probeGt(nCtx(), p1.getNativeObject(), @@ -2713,12 +2655,11 @@ public class Context extends IDisposable /** * Create a probe that evaluates to "true" when the value returned by - * is less than or equal the value returned by - * + * {@code p1} is less than or equal the value returned by + * {@code p2} **/ public Probe le(Probe p1, Probe p2) throws Z3Exception { - checkContextMatch(p1); checkContextMatch(p2); return new Probe(this, Native.probeLe(nCtx(), p1.getNativeObject(), @@ -2727,8 +2668,8 @@ public class Context extends IDisposable /** * Create a probe that evaluates to "true" when the value returned by - * is greater than or equal the value returned by - * + * {@code p1} is greater than or equal the value returned by + * {@code p2} **/ public Probe ge(Probe p1, Probe p2) throws Z3Exception { @@ -2740,8 +2681,7 @@ public class Context extends IDisposable /** * Create a probe that evaluates to "true" when the value returned by - * is equal to the value returned by + * {@code p1} is equal to the value returned by {@code p2} **/ public Probe eq(Probe p1, Probe p2) throws Z3Exception { @@ -2752,8 +2692,7 @@ public class Context extends IDisposable } /** - * Create a probe that evaluates to "true" when the value and evaluate to "true". + * Create a probe that evaluates to "true" when the value {@code p1} and {@code p2} evaluate to "true". **/ public Probe and(Probe p1, Probe p2) throws Z3Exception { @@ -2764,8 +2703,7 @@ public class Context extends IDisposable } /** - * Create a probe that evaluates to "true" when the value or evaluate to "true". + * Create a probe that evaluates to "true" when the value {@code p1} or {@code p2} evaluate to "true". **/ public Probe or(Probe p1, Probe p2) throws Z3Exception { @@ -2776,21 +2714,20 @@ public class Context extends IDisposable } /** - * Create a probe that evaluates to "true" when the value does not evaluate to "true". + * Create a probe that evaluates to "true" when the value {@code p} does not evaluate to "true". **/ public Probe not(Probe p) throws Z3Exception { - checkContextMatch(p); return new Probe(this, Native.probeNot(nCtx(), p.getNativeObject())); } /** - * Creates a new (incremental) solver. This solver also uses a set + * Creates a new (incremental) solver. + * Remarks: This solver also uses a set * of builtin tactics for handling the first check-sat command, and * check-sat commands that take more than a given number of milliseconds to - * be solved. + * be solved. **/ public Solver mkSolver() throws Z3Exception { @@ -2798,10 +2735,11 @@ public class Context extends IDisposable } /** - * Creates a new (incremental) solver. This solver also uses a set + * Creates a new (incremental) solver. + * Remarks: This solver also uses a set * of builtin tactics for handling the first check-sat command, and * check-sat commands that take more than a given number of milliseconds to - * be solved. + * be solved. **/ public Solver mkSolver(Symbol logic) throws Z3Exception { @@ -2814,11 +2752,11 @@ public class Context extends IDisposable } /** - * Creates a new (incremental) solver. + * Creates a new (incremental) solver. + * @see mkSolver(Symbol) **/ public Solver mkSolver(String logic) throws Z3Exception { - return mkSolver(mkSymbol(logic)); } @@ -2827,14 +2765,14 @@ public class Context extends IDisposable **/ public Solver mkSimpleSolver() throws Z3Exception { - return new Solver(this, Native.mkSimpleSolver(nCtx())); } /** - * Creates a solver that is implemented using the given tactic. - * The solver supports the commands Push and Pop, - * but it will always solve each check from scratch. + * Creates a solver that is implemented using the given tactic. + * Remarks: + * The solver supports the commands {@code Push} and {@code Pop}, + * but it will always solve each check from scratch. **/ public Solver mkSolver(Tactic t) throws Z3Exception { @@ -2848,33 +2786,35 @@ public class Context extends IDisposable **/ public Fixedpoint mkFixedpoint() throws Z3Exception { - return new Fixedpoint(this); } /** - * Wraps an AST. This function is used for transitions between - * native and managed objects. Note that - * must be a native object obtained from Z3 (e.g., through ) and that it must have a correct reference count (see - * e.g., . The native pointer to - * wrap. + * Wraps an AST. + * Remarks: This function is used for transitions between + * native and managed objects. Note that {@code nativeObject} + * must be a native object obtained from Z3 (e.g., through + * {@code UnwrapAST}) and that it must have a correct reference count. + * @see Native#incRef + * @see unwrapAST + * @param nativeObject The native pointer to wrap. **/ public AST wrapAST(long nativeObject) throws Z3Exception { - return AST.create(this, nativeObject); } /** - * Unwraps an AST. This function is used for transitions between + * Unwraps an AST. + * Remarks: This function is used for transitions between * native and managed objects. It returns the native pointer to the AST. * Note that AST objects are reference counted and unwrapping an AST * disables automatic reference counting, i.e., all references to the IntPtr * that is returned must be handled externally and through native calls (see - * e.g., ). The AST to unwrap. + * e.g., + * @see Native#incRef + * @see wrapAST + * @param a The AST to unwrap. **/ public long unwrapAST(AST a) { @@ -2883,11 +2823,10 @@ public class Context extends IDisposable /** * Return a string describing all available parameters to - * Expr.Simplify. + * {@code Expr.Simplify}. **/ public String SimplifyHelp() throws Z3Exception { - return Native.simplifyGetHelp(nCtx()); } @@ -2900,9 +2839,10 @@ public class Context extends IDisposable } /** - * Enable/disable printing of warning messages to the console. Note + * Enable/disable printing of warning messages to the console. + * Remarks: Note * that this function is static and effects the behaviour of all contexts - * globally. + * globally. **/ public static void ToggleWarningMessages(boolean enabled) throws Z3Exception @@ -2911,11 +2851,12 @@ public class Context extends IDisposable } /** - * Update a mutable configuration parameter. The list of all + * Update a mutable configuration parameter. + * Remarks: The list of all * configuration parameters can be obtained using the Z3 executable: - * z3.exe -ini? Only a few configuration parameters are mutable + * {@code z3.exe -ini?} Only a few configuration parameters are mutable * once the context is created. An exception is thrown when trying to modify - * an immutable parameter. + * an immutable parameter. **/ public void updateParamValue(String id, String value) throws Z3Exception { diff --git a/src/api/java/DatatypeExpr.java b/src/api/java/DatatypeExpr.java index 806ceacab..805784642 100644 --- a/src/api/java/DatatypeExpr.java +++ b/src/api/java/DatatypeExpr.java @@ -23,7 +23,7 @@ package com.microsoft.z3; public class DatatypeExpr extends Expr { /** - * Constructor for DatatypeExpr + * Constructor for DatatypeExpr **/ protected DatatypeExpr(Context ctx) { diff --git a/src/api/java/DatatypeSort.java b/src/api/java/DatatypeSort.java index 9c339d932..4a31b6c38 100644 --- a/src/api/java/DatatypeSort.java +++ b/src/api/java/DatatypeSort.java @@ -24,6 +24,8 @@ public class DatatypeSort extends Sort { /** * The number of constructors of the datatype sort. + * @throws Z3Exception on error + * @return an int **/ public int getNumConstructors() throws Z3Exception { @@ -35,6 +37,7 @@ public class DatatypeSort extends Sort * The constructors. * * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl[] getConstructors() throws Z3Exception { @@ -50,6 +53,7 @@ public class DatatypeSort extends Sort * The recognizers. * * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl[] getRecognizers() throws Z3Exception { @@ -65,6 +69,7 @@ public class DatatypeSort extends Sort * The constructor accessors. * * @throws Z3Exception + * @throws Z3Exception on error **/ public FuncDecl[][] getAccessors() throws Z3Exception { diff --git a/src/api/java/EnumSort.java b/src/api/java/EnumSort.java index 9715b9a97..6176f020a 100644 --- a/src/api/java/EnumSort.java +++ b/src/api/java/EnumSort.java @@ -24,6 +24,7 @@ public class EnumSort extends Sort { /** * The function declarations of the constants in the enumeration. + * @throws Z3Exception on error **/ public FuncDecl[] getConstDecls() throws Z3Exception { @@ -36,6 +37,8 @@ public class EnumSort extends Sort /** * The constants in the enumeration. + * @throws Z3Exception on error + * @return an Expr **/ public Expr[] getConsts() throws Z3Exception { @@ -48,6 +51,7 @@ public class EnumSort extends Sort /** * The test predicates for the constants in the enumeration. + * @throws Z3Exception on error **/ public FuncDecl[] getTesterDecls() throws Z3Exception { diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index a4c669dad..f94eb12cb 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -31,6 +31,9 @@ public class Expr extends AST { /** * Returns a simplified version of the expression + * @return Expr + * @throws Z3Exception on error + * @return an Expr **/ public Expr simplify() throws Z3Exception { @@ -40,8 +43,12 @@ public class Expr extends AST /** * Returns a simplified version of the expression * A set of - * parameters a Params object to configure the simplifier - * + * parameters + * @param p a Params object to configure the simplifier + * @see Context#SimplifyHelp + * @return an Expr + * @throws Z3Exception on error + * @return an Expr **/ public Expr simplify(Params p) throws Z3Exception { @@ -59,6 +66,8 @@ public class Expr extends AST /** * The function declaration of the function that is applied in this * expression. + * @return a FuncDecl + * @throws Z3Exception on error **/ public FuncDecl getFuncDecl() throws Z3Exception { @@ -69,6 +78,8 @@ public class Expr extends AST /** * Indicates whether the expression is the true or false expression or * something else (Z3_L_UNDEF). + * @throws Z3Exception on error + * @return a Z3_lbool **/ public Z3_lbool getBoolValue() throws Z3Exception { @@ -78,6 +89,8 @@ public class Expr extends AST /** * The number of arguments of the expression. + * @throws Z3Exception on error + * @return an int **/ public int getNumArgs() throws Z3Exception { @@ -86,6 +99,8 @@ public class Expr extends AST /** * The arguments of the expression. + * @throws Z3Exception on error + * @return an Expr[] **/ public Expr[] getArgs() throws Z3Exception { @@ -98,9 +113,11 @@ public class Expr extends AST } /** - * Update the arguments of the expression using the arguments The number of new arguments should coincide with the + * Update the arguments of the expression using the arguments {@code args} + * The number of new arguments should coincide with the * current number of arguments. + * @param args arguments + * @throws Z3Exception on error **/ public void update(Expr[] args) throws Z3Exception { @@ -112,13 +129,16 @@ public class Expr extends AST } /** - * Substitute every occurrence of from[i] in the expression - * with to[i], for i smaller than - * num_exprs. The result is the new expression. The - * arrays from and to must have size - * num_exprs. For every i smaller than - * num_exprs, we must have that sort of from[i] - * must be equal to sort of to[i]. + * Substitute every occurrence of {@code from[i]} in the expression + * with {@code to[i]}, for {@code i} smaller than + * {@code num_exprs}. + * Remarks: The result is the new expression. The + * arrays {@code from} and {@code to} must have size + * {@code num_exprs}. For every {@code i} smaller than + * {@code num_exprs}, we must have that sort of {@code from[i]} + * must be equal to sort of {@code to[i]}. + * @throws Z3Exception on error + * @return an Expr **/ public Expr substitute(Expr[] from, Expr[] to) throws Z3Exception { @@ -132,8 +152,11 @@ public class Expr extends AST } /** - * Substitute every occurrence of from in the expression with - * to. + * Substitute every occurrence of {@code from} in the expression with + * {@code to}. + * @see Expr#substitute(Expr[],Expr[]) + * @throws Z3Exception on error + * @return an Expr **/ public Expr substitute(Expr from, Expr to) throws Z3Exception { @@ -143,9 +166,13 @@ public class Expr extends AST /** * Substitute the free variables in the expression with the expressions in - * For every i smaller than - * num_exprs, the variable with de-Bruijn index i - * is replaced with term to[i]. + * {@code to} + * Remarks: For every {@code i} smaller than * {@code num_exprs}, the + * variable with de-Bruijn index {@code i} * is replaced with term + * {@code to[i]}. + * @throws Z3Exception on error + * @throws Z3Exception on error + * @return an Expr **/ public Expr substituteVars(Expr[] to) throws Z3Exception { @@ -156,11 +183,13 @@ public class Expr extends AST } /** - * Translates (copies) the term to the Context . - * A context + * Translates (copies) the term to the Context {@code ctx}. * - * @return A copy of the term which is associated with + * @param ctx A context + * + * @return A copy of the term which is associated with {@code ctx} + * @throws Z3Exception on error + * @return an Expr **/ public Expr translate(Context ctx) throws Z3Exception { @@ -184,6 +213,8 @@ public class Expr extends AST /** * Indicates whether the term is a numeral + * @throws Z3Exception on error + * @return a boolean **/ public boolean isNumeral() throws Z3Exception { @@ -194,6 +225,8 @@ public class Expr extends AST * Indicates whether the term is well-sorted. * * @return True if the term is well-sorted, false otherwise. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isWellSorted() throws Z3Exception { @@ -202,6 +235,8 @@ public class Expr extends AST /** * The Sort of the term. + * @throws Z3Exception on error + * @return a sort **/ public Sort getSort() throws Z3Exception { @@ -211,6 +246,8 @@ public class Expr extends AST /** * Indicates whether the term represents a constant. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isConst() throws Z3Exception { @@ -219,6 +256,8 @@ public class Expr extends AST /** * Indicates whether the term is an integer numeral. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIntNum() throws Z3Exception { @@ -227,6 +266,8 @@ public class Expr extends AST /** * Indicates whether the term is a real numeral. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRatNum() throws Z3Exception { @@ -235,6 +276,8 @@ public class Expr extends AST /** * Indicates whether the term is an algebraic number + * @throws Z3Exception on error + * @return a boolean **/ public boolean isAlgebraicNumber() throws Z3Exception { @@ -243,6 +286,8 @@ public class Expr extends AST /** * Indicates whether the term has Boolean sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBool() throws Z3Exception { @@ -253,6 +298,8 @@ public class Expr extends AST /** * Indicates whether the term is the constant true. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isTrue() throws Z3Exception { @@ -261,6 +308,8 @@ public class Expr extends AST /** * Indicates whether the term is the constant false. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isFalse() throws Z3Exception { @@ -269,6 +318,8 @@ public class Expr extends AST /** * Indicates whether the term is an equality predicate. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isEq() throws Z3Exception { @@ -278,6 +329,8 @@ public class Expr extends AST /** * Indicates whether the term is an n-ary distinct predicate (every argument * is mutually distinct). + * @throws Z3Exception on error + * @return a boolean **/ public boolean isDistinct() throws Z3Exception { @@ -286,6 +339,8 @@ public class Expr extends AST /** * Indicates whether the term is a ternary if-then-else term + * @throws Z3Exception on error + * @return a boolean **/ public boolean isITE() throws Z3Exception { @@ -294,6 +349,8 @@ public class Expr extends AST /** * Indicates whether the term is an n-ary conjunction + * @throws Z3Exception on error + * @return a boolean **/ public boolean isAnd() throws Z3Exception { @@ -302,6 +359,8 @@ public class Expr extends AST /** * Indicates whether the term is an n-ary disjunction + * @throws Z3Exception on error + * @return a boolean **/ public boolean isOr() throws Z3Exception { @@ -311,6 +370,8 @@ public class Expr extends AST /** * Indicates whether the term is an if-and-only-if (Boolean equivalence, * binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIff() throws Z3Exception { @@ -319,6 +380,8 @@ public class Expr extends AST /** * Indicates whether the term is an exclusive or + * @throws Z3Exception on error + * @return a boolean **/ public boolean isXor() throws Z3Exception { @@ -327,6 +390,8 @@ public class Expr extends AST /** * Indicates whether the term is a negation + * @throws Z3Exception on error + * @return a boolean **/ public boolean isNot() throws Z3Exception { @@ -335,6 +400,8 @@ public class Expr extends AST /** * Indicates whether the term is an implication + * @throws Z3Exception on error + * @return a boolean **/ public boolean isImplies() throws Z3Exception { @@ -343,6 +410,8 @@ public class Expr extends AST /** * Indicates whether the term is of integer sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isInt() throws Z3Exception { @@ -354,6 +423,8 @@ public class Expr extends AST /** * Indicates whether the term is of sort real. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isReal() throws Z3Exception { @@ -364,6 +435,8 @@ public class Expr extends AST /** * Indicates whether the term is an arithmetic numeral. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isArithmeticNumeral() throws Z3Exception { @@ -372,6 +445,8 @@ public class Expr extends AST /** * Indicates whether the term is a less-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isLE() throws Z3Exception { @@ -380,6 +455,8 @@ public class Expr extends AST /** * Indicates whether the term is a greater-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isGE() throws Z3Exception { @@ -388,6 +465,8 @@ public class Expr extends AST /** * Indicates whether the term is a less-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isLT() throws Z3Exception { @@ -396,6 +475,8 @@ public class Expr extends AST /** * Indicates whether the term is a greater-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isGT() throws Z3Exception { @@ -404,6 +485,8 @@ public class Expr extends AST /** * Indicates whether the term is addition (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isAdd() throws Z3Exception { @@ -412,6 +495,8 @@ public class Expr extends AST /** * Indicates whether the term is subtraction (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSub() throws Z3Exception { @@ -420,6 +505,8 @@ public class Expr extends AST /** * Indicates whether the term is a unary minus + * @throws Z3Exception on error + * @return a boolean **/ public boolean isUMinus() throws Z3Exception { @@ -428,6 +515,8 @@ public class Expr extends AST /** * Indicates whether the term is multiplication (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isMul() throws Z3Exception { @@ -436,6 +525,8 @@ public class Expr extends AST /** * Indicates whether the term is division (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isDiv() throws Z3Exception { @@ -444,6 +535,8 @@ public class Expr extends AST /** * Indicates whether the term is integer division (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIDiv() throws Z3Exception { @@ -452,6 +545,8 @@ public class Expr extends AST /** * Indicates whether the term is remainder (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRemainder() throws Z3Exception { @@ -460,6 +555,8 @@ public class Expr extends AST /** * Indicates whether the term is modulus (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isModulus() throws Z3Exception { @@ -468,6 +565,8 @@ public class Expr extends AST /** * Indicates whether the term is a coercion of integer to real (unary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIntToReal() throws Z3Exception { @@ -476,6 +575,8 @@ public class Expr extends AST /** * Indicates whether the term is a coercion of real to integer (unary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRealToInt() throws Z3Exception { @@ -485,6 +586,8 @@ public class Expr extends AST /** * Indicates whether the term is a check that tests whether a real is * integral (unary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRealIsInt() throws Z3Exception { @@ -493,6 +596,8 @@ public class Expr extends AST /** * Indicates whether the term is of an array sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isArray() throws Z3Exception { @@ -502,9 +607,10 @@ public class Expr extends AST } /** - * Indicates whether the term is an array store. It satisfies - * select(store(a,i,v),j) = if i = j then v else select(a,j). Array store - * takes at least 3 arguments. + * Indicates whether the term is an array store. + * Remarks: It satisfies * select(store(a,i,v),j) = if i = j then v else select(a,j). Array store * takes at least 3 arguments. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isStore() throws Z3Exception { @@ -513,6 +619,8 @@ public class Expr extends AST /** * Indicates whether the term is an array select. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSelect() throws Z3Exception { @@ -520,9 +628,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a constant array. For example, - * select(const(v),i) = v holds for every v and i. The function is - * unary. + * Indicates whether the term is a constant array. + * Remarks: For example, * select(const(v),i) = v holds for every v and i. The function is * unary. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isConstantArray() throws Z3Exception { @@ -530,8 +639,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a default array. For example - * default(const(v)) = v. The function is unary. + * Indicates whether the term is a default array. + * Remarks: For example default(const(v)) = v. The function is unary. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isDefaultArray() throws Z3Exception { @@ -539,8 +650,11 @@ public class Expr extends AST } /** - * Indicates whether the term is an array map. It satisfies - * map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + * Indicates whether the term is an array map. + * Remarks: It satisfies + * map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isArrayMap() throws Z3Exception { @@ -548,9 +662,10 @@ public class Expr extends AST } /** - * Indicates whether the term is an as-array term. An as-array term - * is n array value that behaves as the function graph of the function - * passed as parameter. + * Indicates whether the term is an as-array term. + * Remarks: An as-array term * is n array value that behaves as the function graph of the function * passed as parameter. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isAsArray() throws Z3Exception { @@ -559,6 +674,8 @@ public class Expr extends AST /** * Indicates whether the term is set union + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSetUnion() throws Z3Exception { @@ -567,6 +684,8 @@ public class Expr extends AST /** * Indicates whether the term is set intersection + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSetIntersect() throws Z3Exception { @@ -575,6 +694,8 @@ public class Expr extends AST /** * Indicates whether the term is set difference + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSetDifference() throws Z3Exception { @@ -583,6 +704,8 @@ public class Expr extends AST /** * Indicates whether the term is set complement + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSetComplement() throws Z3Exception { @@ -591,6 +714,8 @@ public class Expr extends AST /** * Indicates whether the term is set subset + * @throws Z3Exception on error + * @return a boolean **/ public boolean isSetSubset() throws Z3Exception { @@ -599,6 +724,8 @@ public class Expr extends AST /** * Indicates whether the terms is of bit-vector sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBV() throws Z3Exception { @@ -609,6 +736,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector numeral + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVNumeral() throws Z3Exception { @@ -617,6 +746,8 @@ public class Expr extends AST /** * Indicates whether the term is a one-bit bit-vector with value one + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVBitOne() throws Z3Exception { @@ -625,6 +756,8 @@ public class Expr extends AST /** * Indicates whether the term is a one-bit bit-vector with value zero + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVBitZero() throws Z3Exception { @@ -633,6 +766,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector unary minus + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVUMinus() throws Z3Exception { @@ -641,6 +776,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector addition (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVAdd() throws Z3Exception { @@ -649,6 +786,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector subtraction (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSub() throws Z3Exception { @@ -657,6 +796,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector multiplication (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVMul() throws Z3Exception { @@ -665,6 +806,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector signed division (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSDiv() throws Z3Exception { @@ -673,6 +816,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector unsigned division (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVUDiv() throws Z3Exception { @@ -681,6 +826,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector signed remainder (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSRem() throws Z3Exception { @@ -689,6 +836,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector unsigned remainder (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVURem() throws Z3Exception { @@ -697,6 +846,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector signed modulus + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSMod() throws Z3Exception { @@ -705,46 +856,58 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector signed division by zero + * @return a boolean + * @throws Z3Exception on error **/ - boolean IsBVSDiv0() throws Z3Exception + boolean isBVSDiv0() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_BSDIV0; } /** * Indicates whether the term is a bit-vector unsigned division by zero + * @return a boolean + * @throws Z3Exception on error **/ - boolean IsBVUDiv0() throws Z3Exception + boolean isBVUDiv0() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_BUDIV0; } /** * Indicates whether the term is a bit-vector signed remainder by zero + * @return a boolean + * @throws Z3Exception on error **/ - boolean IsBVSRem0() throws Z3Exception + boolean isBVSRem0() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_BSREM0; } /** * Indicates whether the term is a bit-vector unsigned remainder by zero + * @return a boolean + * @throws Z3Exception on error **/ - boolean IsBVURem0() throws Z3Exception + boolean isBVURem0() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_BUREM0; } /** * Indicates whether the term is a bit-vector signed modulus by zero + * @return a boolean + * @throws Z3Exception on error **/ - boolean IsBVSMod0() throws Z3Exception + boolean isBVSMod0() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_BSMOD0; } /** * Indicates whether the term is an unsigned bit-vector less-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVULE() throws Z3Exception { @@ -753,6 +916,8 @@ public class Expr extends AST /** * Indicates whether the term is a signed bit-vector less-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSLE() throws Z3Exception { @@ -762,6 +927,8 @@ public class Expr extends AST /** * Indicates whether the term is an unsigned bit-vector * greater-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVUGE() throws Z3Exception { @@ -770,6 +937,8 @@ public class Expr extends AST /** * Indicates whether the term is a signed bit-vector greater-than-or-equal + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSGE() throws Z3Exception { @@ -778,6 +947,8 @@ public class Expr extends AST /** * Indicates whether the term is an unsigned bit-vector less-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVULT() throws Z3Exception { @@ -786,6 +957,8 @@ public class Expr extends AST /** * Indicates whether the term is a signed bit-vector less-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSLT() throws Z3Exception { @@ -794,6 +967,8 @@ public class Expr extends AST /** * Indicates whether the term is an unsigned bit-vector greater-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVUGT() throws Z3Exception { @@ -802,6 +977,8 @@ public class Expr extends AST /** * Indicates whether the term is a signed bit-vector greater-than + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSGT() throws Z3Exception { @@ -810,6 +987,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise AND + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVAND() throws Z3Exception { @@ -818,6 +997,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise OR + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVOR() throws Z3Exception { @@ -826,6 +1007,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise NOT + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVNOT() throws Z3Exception { @@ -834,6 +1017,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise XOR + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVXOR() throws Z3Exception { @@ -842,6 +1027,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise NAND + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVNAND() throws Z3Exception { @@ -850,6 +1037,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise NOR + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVNOR() throws Z3Exception { @@ -858,6 +1047,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-wise XNOR + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVXNOR() throws Z3Exception { @@ -866,6 +1057,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector concatenation (binary) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVConcat() throws Z3Exception { @@ -874,6 +1067,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector sign extension + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVSignExtension() throws Z3Exception { @@ -882,6 +1077,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector zero extension + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVZeroExtension() throws Z3Exception { @@ -890,6 +1087,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector extraction + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVExtract() throws Z3Exception { @@ -898,6 +1097,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector repetition + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVRepeat() throws Z3Exception { @@ -906,6 +1107,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector reduce OR + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVReduceOR() throws Z3Exception { @@ -914,6 +1117,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector reduce AND + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVReduceAND() throws Z3Exception { @@ -922,6 +1127,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector comparison + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVComp() throws Z3Exception { @@ -930,6 +1137,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector shift left + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVShiftLeft() throws Z3Exception { @@ -938,6 +1147,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector logical shift right + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVShiftRightLogical() throws Z3Exception { @@ -946,6 +1157,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector arithmetic shift left + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVShiftRightArithmetic() throws Z3Exception { @@ -954,6 +1167,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector rotate left + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVRotateLeft() throws Z3Exception { @@ -962,6 +1177,8 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector rotate right + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVRotateRight() throws Z3Exception { @@ -970,8 +1187,10 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector rotate left (extended) - * Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator - * instead of a parametric one. + * Remarks: Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator + * instead of a parametric one. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVRotateLeftExtended() throws Z3Exception { @@ -980,8 +1199,10 @@ public class Expr extends AST /** * Indicates whether the term is a bit-vector rotate right (extended) - * Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator - * instead of a parametric one. + * Remarks: Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator + * instead of a parametric one. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVRotateRightExtended() throws Z3Exception { @@ -990,9 +1211,10 @@ public class Expr extends AST /** * Indicates whether the term is a coercion from integer to bit-vector - * This function is not supported by the decision procedures. Only - * the most rudimentary simplification rules are applied to this - * function. + * + * Remarks: This function is not supported by the decision procedures. Only * the most rudimentary simplification rules are applied to this * function. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIntToBV() throws Z3Exception { @@ -1001,9 +1223,10 @@ public class Expr extends AST /** * Indicates whether the term is a coercion from bit-vector to integer - * This function is not supported by the decision procedures. Only - * the most rudimentary simplification rules are applied to this - * function. + * + * Remarks: This function is not supported by the decision procedures. Only * the most rudimentary simplification rules are applied to this * function. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVToInt() throws Z3Exception { @@ -1011,9 +1234,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a bit-vector carry Compute the - * carry bit in a full-adder. The meaning is given by the equivalence (carry - * l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + * Indicates whether the term is a bit-vector carry + * Remarks: Compute the * carry bit in a full-adder. The meaning is given by the equivalence (carry * l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVCarry() throws Z3Exception { @@ -1021,9 +1245,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a bit-vector ternary XOR The - * meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor - * l1 l2) l3) + * Indicates whether the term is a bit-vector ternary XOR + * Remarks: The * meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor * l1 l2) l3) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isBVXOR3() throws Z3Exception { @@ -1032,8 +1257,11 @@ public class Expr extends AST /** * Indicates whether the term is a label (used by the Boogie Verification - * condition generator). The label has two parameters, a string and - * a Boolean polarity. It takes one argument, a formula. + * condition generator). + * Remarks: The label has two parameters, a string and + * a Boolean polarity. It takes one argument, a formula. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isLabel() throws Z3Exception { @@ -1042,8 +1270,11 @@ public class Expr extends AST /** * Indicates whether the term is a label literal (used by the Boogie - * Verification condition generator). A label literal has a set of - * string parameters. It takes no arguments. + * Verification condition generator). + * Remarks: A label literal has a set of + * string parameters. It takes no arguments. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isLabelLit() throws Z3Exception { @@ -1052,8 +1283,10 @@ public class Expr extends AST /** * Indicates whether the term is a binary equivalence modulo namings. - * This binary predicate is used in proof terms. It captures - * equisatisfiability and equivalence modulo renamings. + * Remarks: This binary predicate is used in proof terms. It captures + * equisatisfiability and equivalence modulo renamings. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isOEQ() throws Z3Exception { @@ -1062,6 +1295,8 @@ public class Expr extends AST /** * Indicates whether the term is a Proof for the expression 'true'. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofTrue() throws Z3Exception { @@ -1070,6 +1305,8 @@ public class Expr extends AST /** * Indicates whether the term is a proof for a fact asserted by the user. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofAsserted() throws Z3Exception { @@ -1079,6 +1316,8 @@ public class Expr extends AST /** * Indicates whether the term is a proof for a fact (tagged as goal) * asserted by the user. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofGoal() throws Z3Exception { @@ -1086,10 +1325,13 @@ public class Expr extends AST } /** - * Indicates whether the term is proof via modus ponens Given a + * Indicates whether the term is proof via modus ponens + * Remarks: Given a * proof for p and a proof for (implies p q), produces a proof for q. T1: p * T2: (implies p q) [mp T1 T2]: q The second antecedents may also be a - * proof for (iff p q). + * proof for (iff p q). + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofModusPonens() throws Z3Exception { @@ -1098,10 +1340,13 @@ public class Expr extends AST /** * Indicates whether the term is a proof for (R t t), where R is a reflexive - * relation. This proof object has no antecedents. The only + * relation. + * Remarks: This proof object has no antecedents. The only * reflexive relations that are used are equivalence modulo namings, * equality and equivalence. That is, R is either '~', '=' or - * 'iff'. + * 'iff'. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofReflexivity() throws Z3Exception { @@ -1110,9 +1355,10 @@ public class Expr extends AST /** * Indicates whether the term is proof by symmetricity of a relation - * Given an symmetric relation R and a proof for (R t s), produces - * a proof for (R s t). T1: (R t s) [symmetry T1]: (R s t) T1 is the - * antecedent of this proof object. + * + * Remarks: Given an symmetric relation R and a proof for (R t s), produces * a proof for (R s t). T1: (R t s) [symmetry T1]: (R s t) T1 is the * antecedent of this proof object. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofSymmetry() throws Z3Exception { @@ -1121,9 +1367,10 @@ public class Expr extends AST /** * Indicates whether the term is a proof by transitivity of a relation - * Given a transitive relation R, and proofs for (R t s) and (R s - * u), produces a proof for (R t u). T1: (R t s) T2: (R s u) [trans T1 T2]: - * (R t u) + * + * Remarks: Given a transitive relation R, and proofs for (R t s) and (R s * u), produces a proof for (R t u). T1: (R t s) T2: (R s u) [trans T1 T2]: * (R t u) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofTransitivity() throws Z3Exception { @@ -1132,7 +1379,8 @@ public class Expr extends AST /** * Indicates whether the term is a proof by condensed transitivity of a - * relation Condensed transitivity proof. This proof object is + * relation + * Remarks: Condensed transitivity proof. This proof object is * only used if the parameter PROOF_MODE is 1. It combines several symmetry * and transitivity proofs. Example: T1: (R a b) T2: (R c b) T3: (R c d) * [trans* T1 T2 T3]: (R a d) R must be a symmetric and transitive relation. @@ -1141,7 +1389,9 @@ public class Expr extends AST * checker must check if it is possible to prove (R s t) using the * antecedents, symmetry and transitivity. That is, if there is a path from * s to t, if we view every antecedent (R a b) as an edge between a and b. - * + * + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofTransitivityStar() throws Z3Exception { @@ -1149,11 +1399,14 @@ public class Expr extends AST } /** - * Indicates whether the term is a monotonicity proof object. T1: + * Indicates whether the term is a monotonicity proof object. + * Remarks: T1: * (R t_1 s_1) ... Tn: (R t_n s_n) [monotonicity T1 ... Tn]: (R (f t_1 ... * t_n) (f s_1 ... s_n)) Remark: if t_i == s_i, then the antecedent Ti is * suppressed. That is, reflexivity proofs are supressed to save space. - * + * + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofMonotonicity() throws Z3Exception { @@ -1161,9 +1414,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a quant-intro proof Given a proof - * for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). T1: - * (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) + * Indicates whether the term is a quant-intro proof + * Remarks: Given a proof * for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). T1: * (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofQuantIntro() throws Z3Exception { @@ -1171,7 +1425,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a distributivity proof object. + * Indicates whether the term is a distributivity proof object. + * Remarks: * Given that f (= or) distributes over g (= and), produces a proof for (= * (f a (g c d)) (g (f a c) (f a d))) If f and g are associative, this proof * also justifies the following equality: (= (f (g a b) (g c d)) (g (f a c) @@ -1179,7 +1434,9 @@ public class Expr extends AST * arguments. * * This proof object has no antecedents. Remark. This rule is used by the - * CNF conversion pass and instantiated by f = or, and g = and. + * CNF conversion pass and instantiated by f = or, and g = and. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofDistributivity() throws Z3Exception { @@ -1187,9 +1444,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by elimination of AND - * Given a proof for (and l_1 ... l_n), produces a proof for l_i T1: (and - * l_1 ... l_n) [and-elim T1]: l_i + * Indicates whether the term is a proof by elimination of AND + * Remarks: * Given a proof for (and l_1 ... l_n), produces a proof for l_i T1: (and * l_1 ... l_n) [and-elim T1]: l_i + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofAndElimination() throws Z3Exception { @@ -1197,9 +1455,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by eliminiation of not-or - * Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - * T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) + * Indicates whether the term is a proof by eliminiation of not-or + * Remarks: * Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). * T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofOrElimination() throws Z3Exception { @@ -1207,7 +1466,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by rewriting A proof for + * Indicates whether the term is a proof by rewriting + * Remarks: A proof for * a local rewriting step (= t s). The head function symbol of t is * interpreted. * @@ -1216,7 +1476,9 @@ public class Expr extends AST * equi-satisfiability (~ t s). Remark: if f is bool, then = is iff. * * Examples: (= (+ x 0) x) (= (+ x 1 2) (+ 3 x)) (iff (or x false) x) - * + * + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofRewrite() throws Z3Exception { @@ -1224,7 +1486,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by rewriting A proof for + * Indicates whether the term is a proof by rewriting + * Remarks: A proof for * rewriting an expression t into an expression s. This proof object is used * if the parameter PROOF_MODE is 1. This proof object can have n * antecedents. The antecedents are proofs for equalities used as @@ -1232,7 +1495,9 @@ public class Expr extends AST * parameter PROOF_MODE is 2. The cases are: - When applying contextual * simplification (CONTEXT_SIMPLIFIER=true) - When converting bit-vectors to * Booleans (BIT2BOOL=true) - When pulling ite expression up - * (PULL_CHEAP_ITE_TREES=true) + * (PULL_CHEAP_ITE_TREES=true) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofRewriteStar() throws Z3Exception { @@ -1241,8 +1506,10 @@ public class Expr extends AST /** * Indicates whether the term is a proof for pulling quantifiers out. - * A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) - * r))). This proof object has no antecedents. + * Remarks: A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) + * r))). This proof object has no antecedents. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofPullQuant() throws Z3Exception { @@ -1251,9 +1518,10 @@ public class Expr extends AST /** * Indicates whether the term is a proof for pulling quantifiers out. - * A proof for (iff P Q) where Q is in prenex normal form. This - * proof object is only used if the parameter PROOF_MODE is 1. This proof - * object has no antecedents + * + * Remarks: A proof for (iff P Q) where Q is in prenex normal form. This * proof object is only used if the parameter PROOF_MODE is 1. This proof * object has no antecedents + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofPullQuantStar() throws Z3Exception { @@ -1262,10 +1530,12 @@ public class Expr extends AST /** * Indicates whether the term is a proof for pushing quantifiers in. - * A proof for: (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] + * Remarks: A proof for: (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] * ... p_n[x_1 ... x_m])) (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) ... * (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) This proof object has no - * antecedents + * antecedents + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofPushQuant() throws Z3Exception { @@ -1274,11 +1544,14 @@ public class Expr extends AST /** * Indicates whether the term is a proof for elimination of unused - * variables. A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) + * variables. + * Remarks: A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) * p[x_1 ... x_n]) (forall (x_1 ... x_n) p[x_1 ... x_n])) * * It is used to justify the elimination of unused variables. This proof - * object has no antecedents. + * object has no antecedents. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofElimUnusedVars() throws Z3Exception { @@ -1287,12 +1560,14 @@ public class Expr extends AST /** * Indicates whether the term is a proof for destructive equality resolution - * A proof for destructive equality resolution: (iff (forall (x) + * Remarks: A proof for destructive equality resolution: (iff (forall (x) * (or (not (= x t)) P[x])) P[t]) if x does not occur in t. * * This proof object has no antecedents. * - * Several variables can be eliminated simultaneously. + * Several variables can be eliminated simultaneously. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofDER() throws Z3Exception { @@ -1301,7 +1576,10 @@ public class Expr extends AST /** * Indicates whether the term is a proof for quantifier instantiation - * A proof of (or (not (forall (x) (P x))) (P a)) + * + * Remarks: A proof of (or (not (forall (x) (P x))) (P a)) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofQuantInst() throws Z3Exception { @@ -1309,8 +1587,11 @@ public class Expr extends AST } /** - * Indicates whether the term is a hypthesis marker. Mark a - * hypothesis in a natural deduction style proof. + * Indicates whether the term is a hypthesis marker. + * Remarks: Mark a + * hypothesis in a natural deduction style proof. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofHypothesis() throws Z3Exception { @@ -1318,12 +1599,15 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by lemma T1: false [lemma + * Indicates whether the term is a proof by lemma + * Remarks: T1: false [lemma * T1]: (or (not l_1) ... (not l_n)) * * This proof object has one antecedent: a hypothetical proof for false. It * converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 - * contains the hypotheses: l_1, ..., l_n. + * contains the hypotheses: l_1, ..., l_n. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofLemma() throws Z3Exception { @@ -1331,9 +1615,10 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by unit resolution T1: - * (or l_1 ... l_n l_1' ... l_m') T2: (not l_1) ... T(n+1): (not l_n) - * [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') + * Indicates whether the term is a proof by unit resolution + * Remarks: T1: * (or l_1 ... l_n l_1' ... l_m') T2: (not l_1) ... T(n+1): (not l_n) * [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofUnitResolution() throws Z3Exception { @@ -1341,8 +1626,11 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by iff-true T1: p - * [iff-true T1]: (iff p true) + * Indicates whether the term is a proof by iff-true + * Remarks: T1: p + * [iff-true T1]: (iff p true) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofIFFTrue() throws Z3Exception { @@ -1350,8 +1638,11 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by iff-false T1: (not p) - * [iff-false T1]: (iff p false) + * Indicates whether the term is a proof by iff-false + * Remarks: T1: (not p) + * [iff-false T1]: (iff p false) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofIFFFalse() throws Z3Exception { @@ -1359,13 +1650,16 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof by commutativity [comm]: + * Indicates whether the term is a proof by commutativity + * Remarks: [comm]: * (= (f a b) (f b a)) * * f is a commutative operator. * * This proof object has no antecedents. Remark: if f is bool, then = is - * iff. + * iff. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofCommutativity() throws Z3Exception { @@ -1373,7 +1667,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof for Tseitin-like axioms + * Indicates whether the term is a proof for Tseitin-like axioms + * Remarks: * Proof object used to justify Tseitin's like axioms: * * (or (not (and p q)) p) (or (not (and p q)) q) (or (not (and p q r)) p) @@ -1388,7 +1683,9 @@ public class Expr extends AST * tautologies. Note also that 'and' and 'or' can take multiple arguments. * You can recover the propositional tautologies by unfolding the Boolean * connectives in the axioms a small bounded number of steps (=3). - * + * + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofDefAxiom() throws Z3Exception { @@ -1397,7 +1694,7 @@ public class Expr extends AST /** * Indicates whether the term is a proof for introduction of a name - * Introduces a name for a formula/term. Suppose e is an + * Remarks: Introduces a name for a formula/term. Suppose e is an * expression with free variables x, and def-intro introduces the name n(x). * The possible cases are: * @@ -1409,7 +1706,9 @@ public class Expr extends AST * When e is of the form (ite cond th el): [def-intro]: (and (or (not cond) * (= n th)) (or cond (= n el))) * - * Otherwise: [def-intro]: (= n e) + * Otherwise: [def-intro]: (= n e) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofDefIntro() throws Z3Exception { @@ -1418,8 +1717,10 @@ public class Expr extends AST /** * Indicates whether the term is a proof for application of a definition - * [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is - * a proof that n is a name for F. + * Remarks: [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is + * a proof that n is a name for F. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofApplyDef() throws Z3Exception { @@ -1427,8 +1728,11 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof iff-oeq T1: (iff p q) - * [iff~ T1]: (~ p q) + * Indicates whether the term is a proof iff-oeq + * Remarks: T1: (iff p q) + * [iff~ T1]: (~ p q) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofIFFOEQ() throws Z3Exception { @@ -1436,7 +1740,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof for a positive NNF step + * Indicates whether the term is a proof for a positive NNF step + * Remarks: * Proof for a (positive) NNF step. Example: * * T1: (not s_1) ~ r_1 T2: (not s_2) ~ r_2 T3: s_1 ~ r_1' T4: s_2 ~ r_2' @@ -1453,7 +1758,9 @@ public class Expr extends AST * top-level connective is changed during NNF conversion. The relevant * Boolean connectives for NNF_POS are 'implies', 'iff', 'xor', 'ite'. * NNF_NEG furthermore handles the case where negation is pushed over - * Boolean connectives 'and' and 'or'. + * Boolean connectives 'and' and 'or'. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofNNFPos() throws Z3Exception { @@ -1461,7 +1768,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof for a negative NNF step + * Indicates whether the term is a proof for a negative NNF step + * Remarks: * Proof for a (negative) NNF step. Examples: * * T1: (not s_1) ~ r_1 ... Tn: (not s_n) ~ r_n [nnf-neg T1 ... Tn]: (not @@ -1469,7 +1777,9 @@ public class Expr extends AST * (not s_n) ~ r_n [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 * ... r_n) and T1: (not s_1) ~ r_1 T2: (not s_2) ~ r_2 T3: s_1 ~ r_1' T4: * s_2 ~ r_2' [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 - * r_2) (or r_1' r_2'))) + * r_2) (or r_1' r_2'))) + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofNNFNeg() throws Z3Exception { @@ -1478,13 +1788,16 @@ public class Expr extends AST /** * Indicates whether the term is a proof for (~ P Q) here Q is in negation - * normal form. A proof for (~ P Q) where Q is in negation normal + * normal form. + * Remarks: A proof for (~ P Q) where Q is in negation normal * form. * * This proof object is only used if the parameter PROOF_MODE is 1. * * This proof object may have n antecedents. Each antecedent is a - * PR_DEF_INTRO. + * PR_DEF_INTRO. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofNNFStar() throws Z3Exception { @@ -1493,10 +1806,13 @@ public class Expr extends AST /** * Indicates whether the term is a proof for (~ P Q) where Q is in - * conjunctive normal form. A proof for (~ P Q) where Q is in + * conjunctive normal form. + * Remarks: A proof for (~ P Q) where Q is in * conjunctive normal form. This proof object is only used if the parameter * PROOF_MODE is 1. This proof object may have n antecedents. Each - * antecedent is a PR_DEF_INTRO. + * antecedent is a PR_DEF_INTRO. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofCNFStar() throws Z3Exception { @@ -1504,13 +1820,16 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof for a Skolemization step + * Indicates whether the term is a proof for a Skolemization step + * Remarks: * Proof for: * * [sk]: (~ (not (forall x (p x y))) (not (p (sk y) y))) [sk]: (~ (exists x * (p x y)) (p (sk y) y)) * - * This proof object has no antecedents. + * This proof object has no antecedents. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofSkolemize() throws Z3Exception { @@ -1519,8 +1838,11 @@ public class Expr extends AST /** * Indicates whether the term is a proof by modus ponens for - * equi-satisfiability. Modus ponens style rule for - * equi-satisfiability. T1: p T2: (~ p q) [mp~ T1 T2]: q + * equi-satisfiability. + * Remarks: Modus ponens style rule for + * equi-satisfiability. T1: p T2: (~ p q) [mp~ T1 T2]: q + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofModusPonensOEQ() throws Z3Exception { @@ -1528,7 +1850,8 @@ public class Expr extends AST } /** - * Indicates whether the term is a proof for theory lemma Generic + * Indicates whether the term is a proof for theory lemma + * Remarks: Generic * proof for theory lemmas. * * The theory lemma function comes with one or more parameters. The first @@ -1539,7 +1862,9 @@ public class Expr extends AST * (negated) inequalities and obtain a contradiction. - triangle-eq - * Indicates a lemma related to the equivalence: (iff (= t1 t2) (and (<= * t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear - * arithmetic lemma that uses a gcd test. + * arithmetic lemma that uses a gcd test. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isProofTheoryLemma() throws Z3Exception { @@ -1548,6 +1873,8 @@ public class Expr extends AST /** * Indicates whether the term is of an array sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelation() throws Z3Exception { @@ -1558,10 +1885,13 @@ public class Expr extends AST } /** - * Indicates whether the term is an relation store Insert a record - * into a relation. The function takes n+1 arguments, where the - * first argument is the relation and the remaining n elements - * correspond to the n columns of the relation. + * Indicates whether the term is an relation store + * Remarks: Insert a record + * into a relation. The function takes {@code n+1} arguments, where the + * first argument is the relation and the remaining {@code n} elements + * correspond to the {@code n} columns of the relation. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationStore() throws Z3Exception { @@ -1570,6 +1900,8 @@ public class Expr extends AST /** * Indicates whether the term is an empty relation + * @throws Z3Exception on error + * @return a boolean **/ public boolean isEmptyRelation() throws Z3Exception { @@ -1578,6 +1910,8 @@ public class Expr extends AST /** * Indicates whether the term is a test for the emptiness of a relation + * @throws Z3Exception on error + * @return a boolean **/ public boolean isIsEmptyRelation() throws Z3Exception { @@ -1586,6 +1920,8 @@ public class Expr extends AST /** * Indicates whether the term is a relational join + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationalJoin() throws Z3Exception { @@ -1594,7 +1930,10 @@ public class Expr extends AST /** * Indicates whether the term is the union or convex hull of two relations. - * The function takes two arguments. + * + * Remarks: The function takes two arguments. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationUnion() throws Z3Exception { @@ -1602,8 +1941,11 @@ public class Expr extends AST } /** - * Indicates whether the term is the widening of two relations The - * function takes two arguments. + * Indicates whether the term is the widening of two relations + * Remarks: The + * function takes two arguments. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationWiden() throws Z3Exception { @@ -1612,8 +1954,11 @@ public class Expr extends AST /** * Indicates whether the term is a projection of columns (provided as - * numbers in the parameters). The function takes one - * argument. + * numbers in the parameters). + * Remarks: The function takes one + * argument. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationProject() throws Z3Exception { @@ -1621,11 +1966,14 @@ public class Expr extends AST } /** - * Indicates whether the term is a relation filter Filter + * Indicates whether the term is a relation filter + * Remarks: Filter * (restrict) a relation with respect to a predicate. The first argument is * a relation. The second argument is a predicate with free de-Brujin * indices corresponding to the columns of the relation. So the first column - * in the relation has index 0. + * in the relation has index 0. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationFilter() throws Z3Exception { @@ -1634,7 +1982,8 @@ public class Expr extends AST /** * Indicates whether the term is an intersection of a relation with the - * negation of another. Intersect the first relation with respect + * negation of another. + * Remarks: Intersect the first relation with respect * to negation of the second relation (the function takes two arguments). * Logically, the specification can be described by a function * @@ -1642,7 +1991,9 @@ public class Expr extends AST * * where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, * such that target are elements in x in pos, such that there is no y in neg - * that agrees with x on the columns c1, d1, .., cN, dN. + * that agrees with x on the columns c1, d1, .., cN, dN. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationNegationFilter() throws Z3Exception { @@ -1651,8 +2002,10 @@ public class Expr extends AST /** * Indicates whether the term is the renaming of a column in a relation - * The function takes one argument. The parameters contain the - * renaming as a cycle. + * Remarks: The function takes one argument. The parameters contain the + * renaming as a cycle. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationRename() throws Z3Exception { @@ -1661,6 +2014,8 @@ public class Expr extends AST /** * Indicates whether the term is the complement of a relation + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationComplement() throws Z3Exception { @@ -1668,10 +2023,13 @@ public class Expr extends AST } /** - * Indicates whether the term is a relational select Check if a - * record is an element of the relation. The function takes n+1 + * Indicates whether the term is a relational select + * Remarks: Check if a + * record is an element of the relation. The function takes {@code n+1} * arguments, where the first argument is a relation, and the remaining - * n arguments correspond to a record. + * {@code n} arguments correspond to a record. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationSelect() throws Z3Exception { @@ -1679,11 +2037,15 @@ public class Expr extends AST } /** - * Indicates whether the term is a relational clone (copy) Create + * Indicates whether the term is a relational clone (copy) + * Remarks: Create * a fresh copy (clone) of a relation. The function is logically the * identity, but in the context of a register machine allows for terms of - * kind to perform destructive updates to - * the first argument. + * kind {@code isRelationUnion} to perform destructive updates to + * the first argument. + * @see isRelationUnion + * @throws Z3Exception on error + * @return a boolean **/ public boolean isRelationClone() throws Z3Exception { @@ -1692,6 +2054,8 @@ public class Expr extends AST /** * Indicates whether the term is of an array sort. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isFiniteDomain() throws Z3Exception { @@ -1703,6 +2067,8 @@ public class Expr extends AST /** * Indicates whether the term is a less than predicate over a finite domain. + * @throws Z3Exception on error + * @return a boolean **/ public boolean isFiniteDomainLT() throws Z3Exception { @@ -1710,19 +2076,22 @@ public class Expr extends AST } /** - * The de-Burijn index of a bound variable. Bound variables are + * The de-Burijn index of a bound variable. + * Remarks: Bound variables are * indexed by de-Bruijn indices. It is perhaps easiest to explain the * meaning of de-Bruijn indices by indicating the compilation process from - * non-de-Bruijn formulas to de-Bruijn format. + * non-de-Bruijn formulas to de-Bruijn format. {@code * abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) * abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) * abs1(x, x, n) = b_n * abs1(y, x, n) = y * abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) * abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - * The last line is significant: the index of a bound variable is + * } The last line is significant: the index of a bound variable is * different depending on the scope in which it appears. The deeper x - * appears, the higher is its index. + * appears, the higher is its index. + * @throws Z3Exception on error + * @return an int **/ public int getIndex() throws Z3Exception { @@ -1744,6 +2113,7 @@ public class Expr extends AST /** * Constructor for Expr + * @throws Z3Exception on error **/ protected Expr(Context ctx, long obj) throws Z3Exception { diff --git a/src/api/java/FiniteDomainSort.java b/src/api/java/FiniteDomainSort.java index 4cb2ab917..cece06f1a 100644 --- a/src/api/java/FiniteDomainSort.java +++ b/src/api/java/FiniteDomainSort.java @@ -24,6 +24,7 @@ public class FiniteDomainSort extends Sort { /** * The size of the finite domain sort. + * @throws Z3Exception on error **/ public long getSize() throws Z3Exception { diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index 57e1e105a..587f47cbb 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -163,7 +163,8 @@ public class Fixedpoint extends Z3Object } /** - * Creates a backtracking point. + * Creates a backtracking point. + * @see pop **/ public void push() throws Z3Exception { @@ -171,9 +172,11 @@ public class Fixedpoint extends Z3Object } /** - * Backtrack one backtracking point. Note that an exception is - * thrown if Pop is called without a corresponding Push - * + * Backtrack one backtracking point. + * Remarks: Note that an exception is thrown if {#code pop} + * is called without a corresponding {@code push} + * + * @see push **/ public void pop() throws Z3Exception { diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index 573ebd102..5307951e5 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -29,7 +29,7 @@ public class FuncDecl extends AST /** * Comparison operator. * - * @return True if and share the + * @return True if {@code a"/> and and do not + * @return True if {@code a"/> and + * The size of the domain of the function declaration + * @see getArity **/ public int getDomainSize() throws Z3Exception { @@ -221,7 +221,7 @@ public class FuncDecl extends AST private String r; /** - * The int value of the parameter. + * The int value of the parameter. **/ public int getInt() throws Z3Exception { @@ -231,7 +231,7 @@ public class FuncDecl extends AST } /** - * The double value of the parameter. + * The double value of the parameter. **/ public double getDouble() throws Z3Exception { @@ -241,7 +241,7 @@ public class FuncDecl extends AST } /** - * The Symbol value of the parameter. + * The Symbol value of the parameter. **/ public Symbol getSymbol() throws Z3Exception { @@ -251,7 +251,7 @@ public class FuncDecl extends AST } /** - * The Sort value of the parameter. + * The Sort value of the parameter. **/ public Sort getSort() throws Z3Exception { @@ -261,7 +261,7 @@ public class FuncDecl extends AST } /** - * The AST value of the parameter. + * The AST value of the parameter. **/ public AST getAST() throws Z3Exception { @@ -271,7 +271,7 @@ public class FuncDecl extends AST } /** - * The FunctionDeclaration value of the parameter. + * The FunctionDeclaration value of the parameter. **/ public FuncDecl getFuncDecl() throws Z3Exception { @@ -281,7 +281,7 @@ public class FuncDecl extends AST } /** - * The rational string value of the parameter. + * The rational string value of the parameter. **/ public String getRational() throws Z3Exception { @@ -375,8 +375,8 @@ public class FuncDecl extends AST } /** - * Create expression that applies function to arguments. + * Create expression that applies function to arguments. + * @param args * * @return **/ diff --git a/src/api/java/FuncInterp.java b/src/api/java/FuncInterp.java index 243ade71f..fd0c10d2e 100644 --- a/src/api/java/FuncInterp.java +++ b/src/api/java/FuncInterp.java @@ -34,7 +34,8 @@ public class FuncInterp extends Z3Object * Return the (symbolic) value of this entry. * * @throws Z3Exception - **/ + * @throws Z3Exception on error + **/ public Expr getValue() throws Z3Exception { return Expr.create(getContext(), @@ -43,7 +44,8 @@ public class FuncInterp extends Z3Object /** * The number of arguments of the entry. - **/ + * @throws Z3Exception on error + **/ public int getNumArgs() throws Z3Exception { return Native.funcEntryGetNumArgs(getContext().nCtx(), getNativeObject()); @@ -53,7 +55,8 @@ public class FuncInterp extends Z3Object * The arguments of the function entry. * * @throws Z3Exception - **/ + * @throws Z3Exception on error + **/ public Expr[] getArgs() throws Z3Exception { int n = getNumArgs(); @@ -103,6 +106,8 @@ public class FuncInterp extends Z3Object /** * The number of entries in the function interpretation. + * @throws Z3Exception on error + * @return an int **/ public int getNumEntries() throws Z3Exception { @@ -113,6 +118,7 @@ public class FuncInterp extends Z3Object * The entries in the function interpretation * * @throws Z3Exception + * @throws Z3Exception on error **/ public Entry[] getEntries() throws Z3Exception { @@ -128,6 +134,8 @@ public class FuncInterp extends Z3Object * The (symbolic) `else' value of the function interpretation. * * @throws Z3Exception + * @throws Z3Exception on error + * @return an Expr **/ public Expr getElse() throws Z3Exception { @@ -137,6 +145,8 @@ public class FuncInterp extends Z3Object /** * The arity of the function interpretation + * @throws Z3Exception on error + * @return an int **/ public int getArity() throws Z3Exception { diff --git a/src/api/java/Global.java b/src/api/java/Global.java index c93f46c88..b31c4a7ae 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -19,16 +19,16 @@ package com.microsoft.z3; /** * Global functions for Z3. - * + * Remarks: * This (static) class contains functions that effect the behaviour of Z3 * globally across contexts, etc. - * + * **/ public final class Global { /** * Set a global (or module) parameter, which is shared by all Z3 contexts. - * + * Remarks: * When a Z3 module is initialized it will use the value of these parameters * when Z3_params objects are not provided. * The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. @@ -36,11 +36,11 @@ public final class Global * The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. * Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". * This function can be used to set parameters for a specific Z3 module. - * This can be done by using .. + * This can be done by using <module-name>.<parameter-name>. * For example: * Z3_global_param_set('pp.decimal', 'true') * will set the parameter "decimal" in the module "pp" to true. - * + * **/ public static void setParameter(String id, String value) { @@ -49,11 +49,10 @@ public final class Global /** * Get a global (or module) parameter. - * - * Returns null if the parameter parameter id does not exist. + * Remarks: * This function cannot be invoked simultaneously from different threads without synchronization. * The result string stored in param_value is stored in a shared location. - * + * @return null if the parameter {@code id} does not exist. **/ public static String getParameter(String id) { @@ -66,10 +65,9 @@ public final class Global /** * Restore the value of all global (and module) parameters. - * + * Remarks: * This command will not affect already created objects (such as tactics and solvers) - * - * + * @see setParameter **/ public static void resetParameters() { diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index aba8b0149..5a9221b63 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -26,11 +26,12 @@ import com.microsoft.z3.enumerations.Z3_goal_prec; public class Goal extends Z3Object { /** - * The precision of the goal. Goals can be transformed using over + * The precision of the goal. + * Remarks: Goals can be transformed using over * and under approximations. An under approximation is applied when the * objective is to find a model for a given goal. An over approximation is * applied when the objective is to find a proof for a given goal. - * + * **/ public Z3_goal_prec getPrecision() throws Z3Exception { @@ -72,7 +73,7 @@ public class Goal extends Z3Object } /** - * Adds the to the given goal. + * Adds the {@code constraints} to the given goal. * * @throws Z3Exception **/ @@ -95,8 +96,9 @@ public class Goal extends Z3Object } /** - * The depth of the goal. This tracks how many transformations - * were applied to it. + * The depth of the goal. + * Remarks: This tracks how many transformations + * were applied to it. **/ public int getDepth() throws Z3Exception { @@ -162,8 +164,7 @@ public class Goal extends Z3Object } /** - * Translates (copies) the Goal to the target Context . + * Translates (copies) the Goal to the target Context {@code ctx}. * * @throws Z3Exception **/ @@ -174,8 +175,9 @@ public class Goal extends Z3Object } /** - * Simplifies the goal. Essentially invokes the `simplify' tactic - * on the goal. + * Simplifies the goal. + * Remarks: Essentially invokes the `simplify' tactic + * on the goal. **/ public Goal simplify() throws Z3Exception { @@ -189,8 +191,9 @@ public class Goal extends Z3Object } /** - * Simplifies the goal. Essentially invokes the `simplify' tactic - * on the goal. + * Simplifies the goal. + * Remarks: Essentially invokes the `simplify' tactic + * on the goal. **/ public Goal simplify(Params p) throws Z3Exception { diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index 2e90c3cbf..712b950aa 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -23,7 +23,8 @@ package com.microsoft.z3; public class IntExpr extends ArithExpr { /** - * Constructor for IntExpr + * Constructor for IntExpr + * @throws Z3Exception on error **/ protected IntExpr(Context ctx) throws Z3Exception { diff --git a/src/api/java/IntSymbol.java b/src/api/java/IntSymbol.java index b0f1af685..a677c9102 100644 --- a/src/api/java/IntSymbol.java +++ b/src/api/java/IntSymbol.java @@ -25,8 +25,9 @@ import com.microsoft.z3.enumerations.Z3_symbol_kind; public class IntSymbol extends Symbol { /** - * The int value of the symbol. Throws an exception if the symbol - * is not of int kind. + * The int value of the symbol. + * Remarks: Throws an exception if the symbol + * is not of int kind. **/ public int getInt() throws Z3Exception { diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 05d99b305..c1590e07f 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -22,11 +22,11 @@ import java.lang.String; import com.microsoft.z3.enumerations.Z3_lbool; -/** +/** * The InterpolationContext is suitable for generation of interpolants. - * - * For more information on interpolation please refer - * too the C/C++ API, which is well documented. + * + * Remarks: For more information on interpolation please refer + * too the C/C++ API, which is well documented. **/ public class InterpolationContext extends Context { @@ -42,7 +42,9 @@ public class InterpolationContext extends Context /** * Constructor. * - * + * + * Remarks: + * @see Context#Context **/ public InterpolationContext(Map settings) throws Z3Exception { @@ -56,7 +58,7 @@ public class InterpolationContext extends Context /** * Create an expression that marks a formula position for interpolation. - * @throws Z3Exception + * @throws Z3Exception **/ public BoolExpr MkInterpolant(BoolExpr a) throws Z3Exception { @@ -66,9 +68,9 @@ public class InterpolationContext extends Context /** * Computes an interpolant. - * For more information on interpolation please refer + * Remarks: For more information on interpolation please refer * too the function Z3_get_interpolant in the C/C++ API, which is - * well documented. + * well documented. * @throws Z3Exception **/ Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception @@ -87,9 +89,9 @@ public class InterpolationContext extends Context /** * Computes an interpolant. - * For more information on interpolation please refer + * Remarks: For more information on interpolation please refer * too the function Z3_compute_interpolant in the C/C++ API, which is - * well documented. + * well documented. * @throws Z3Exception **/ Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception @@ -105,23 +107,23 @@ public class InterpolationContext extends Context return Z3_lbool.fromInt(r); } - /// + /// /// Return a string summarizing cumulative time used for interpolation. - /// - /// For more information on interpolation please refer + /// + /// Remarks: For more information on interpolation please refer /// too the function Z3_interpolation_profile in the C/C++ API, which is - /// well documented. + /// well documented. public String InterpolationProfile() throws Z3Exception { return Native.interpolationProfile(nCtx()); } - /// + /// /// Checks the correctness of an interpolant. - /// - /// For more information on interpolation please refer + /// + /// Remarks: For more information on interpolation please refer /// too the function Z3_check_interpolant in the C/C++ API, which is - /// well documented. + /// well documented. public int CheckInterpolant(Expr[] cnsts, int[] parents, Expr[] interps, String error, Expr[] theory) throws Z3Exception { Native.StringPtr n_err_str = new Native.StringPtr(); @@ -137,12 +139,12 @@ public class InterpolationContext extends Context return r; } - /// + /// /// Reads an interpolation problem from a file. - /// - /// For more information on interpolation please refer + /// + /// Remarks: For more information on interpolation please refer /// too the function Z3_read_interpolation_problem in the C/C++ API, which is - /// well documented. + /// well documented. public int ReadInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception { Native.IntPtr n_num = new Native.IntPtr(); @@ -168,12 +170,12 @@ public class InterpolationContext extends Context return r; } - /// + /// /// Writes an interpolation problem to a file. - /// - /// For more information on interpolation please refer + /// + /// Remarks: For more information on interpolation please refer /// too the function Z3_write_interpolation_problem in the C/C++ API, which is - /// well documented. + /// well documented. public void WriteInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception { Native.writeInterpolationProblem(nCtx(), cnsts.length, Expr.arrayToNative(cnsts), parents, filename, theory.length, Expr.arrayToNative(theory)); diff --git a/src/api/java/Log.java b/src/api/java/Log.java index 254da1bc6..3e8f0050b 100644 --- a/src/api/java/Log.java +++ b/src/api/java/Log.java @@ -18,17 +18,18 @@ Notes: package com.microsoft.z3; /** - * Interaction logging for Z3. Note that this is a global, static log + * Interaction logging for Z3. + * Remarks: Note that this is a global, static log * and if multiple Context objects are created, it logs the interaction with all - * of them. + * of them. **/ public final class Log { private static boolean m_is_open = false; /** - * Open an interaction log file. the name of the file - * to open + * Open an interaction log file. + * @param filename the name of the file to open * * @return True if opening the log file succeeds, false otherwise. **/ @@ -48,7 +49,7 @@ public final class Log } /** - * Appends the user-provided string to the interaction + * Appends the user-provided string {@code s} to the interaction * log. * @throws Z3Exception **/ diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 11eed201e..70f0e91c5 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -25,8 +25,9 @@ import com.microsoft.z3.enumerations.Z3_sort_kind; public class Model extends Z3Object { /** - * Retrieves the interpretation (the assignment) of in - * the model. A Constant + * Retrieves the interpretation (the assignment) of {@code a} in + * the model. + * @param a A Constant * * @return An expression if the constant has an interpretation in the model, * null otherwise. @@ -39,8 +40,9 @@ public class Model extends Z3Object } /** - * Retrieves the interpretation (the assignment) of in - * the model. A function declaration of zero arity + * Retrieves the interpretation (the assignment) of {@code f} in + * the model. + * @param f A function declaration of zero arity * * @return An expression if the function has an interpretation in the model, * null otherwise. @@ -65,9 +67,8 @@ public class Model extends Z3Object } /** - * Retrieves the interpretation (the assignment) of a non-constant in the model. A function declaration of - * non-zero arity + * Retrieves the interpretation (the assignment) of a non-constant {@code f} in the model. + * @param f A function declaration of non-zero arity * * @return A FunctionInterpretation if the function has an interpretation in * the model, null otherwise. @@ -196,16 +197,15 @@ public class Model extends Z3Object } /** - * Evaluates the expression in the current model. - * This function may fail if contains - * quantifiers, is partial (MODEL_PARTIAL enabled), or if is not well-sorted. In this case a - * ModelEvaluationFailedException is thrown. An expression When this flag + * Evaluates the expression {@code t} in the current model. + * Remarks: This function may fail if {@code t} contains + * quantifiers, is partial (MODEL_PARTIAL enabled), or if {@code t} is not well-sorted. In this case a + * {@code ModelEvaluationFailedException} is thrown. + * @param t An expression {@code completion} When this flag * is enabled, a model value will be assigned to any constant or function - * that does not have an interpretation in the model. + * that does not have an interpretation in the model. * - * @return The evaluation of in the model. + * @return The evaluation of {@code t} in the model. * @throws Z3Exception **/ public Expr eval(Expr t, boolean completion) throws Z3Exception @@ -219,7 +219,7 @@ public class Model extends Z3Object } /** - * Alias for Eval. + * Alias for {@code Eval}. * * @throws Z3Exception **/ @@ -239,10 +239,12 @@ public class Model extends Z3Object /** * The uninterpreted sorts that the model has an interpretation for. - * Z3 also provides an intepretation for uninterpreted sorts used + * Remarks: Z3 also provides an intepretation for uninterpreted sorts used * in a formula. The interpretation for a sort is a finite set of distinct - * values. We say this finite set is the "universe" of the sort. - * + * values. We say this finite set is the "universe" of the sort. + * + * @see getNumSorts + * @see getSortUniverse * * @throws Z3Exception **/ @@ -259,11 +261,11 @@ public class Model extends Z3Object /** * The finite set of distinct values that represent the interpretation for - * sort . An - * uninterpreted sort + * sort {@code s}. + * @param s An uninterpreted sort * * @return An array of expressions, where each is an element of the universe - * of + * of {@code s} * @throws Z3Exception **/ public Expr[] getSortUniverse(Sort s) throws Z3Exception diff --git a/src/api/java/Probe.java b/src/api/java/Probe.java index 17ad81b5c..335bd038c 100644 --- a/src/api/java/Probe.java +++ b/src/api/java/Probe.java @@ -21,8 +21,8 @@ package com.microsoft.z3; * Probes are used to inspect a goal (aka problem) and collect information that * may be used to decide which solver and/or preprocessing step will be used. * The complete list of probes may be obtained using the procedures - * Context.NumProbes and Context.ProbeNames. It may - * also be obtained using the command (help-tactics) in the SMT 2.0 + * {@code Context.NumProbes} and {@code Context.ProbeNames}. It may + * also be obtained using the command {@code (help-tactics)} in the SMT 2.0 * front-end. **/ public class Probe extends Z3Object diff --git a/src/api/java/RatNum.java b/src/api/java/RatNum.java index f937ea593..2e92a9429 100644 --- a/src/api/java/RatNum.java +++ b/src/api/java/RatNum.java @@ -61,8 +61,9 @@ public class RatNum extends RealExpr } /** - * Returns a string representation in decimal notation. The result - * has at most decimal places. + * Returns a string representation in decimal notation. + * Remarks: The result + * has at most {@code precision} decimal places. **/ public String toDecimalString(int precision) throws Z3Exception { diff --git a/src/api/java/RealExpr.java b/src/api/java/RealExpr.java index 6188e2999..3352639bf 100644 --- a/src/api/java/RealExpr.java +++ b/src/api/java/RealExpr.java @@ -23,7 +23,7 @@ package com.microsoft.z3; public class RealExpr extends ArithExpr { /** - * Constructor for RealExpr + * Constructor for RealExpr **/ protected RealExpr(Context ctx) { diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index e129189f9..b9c9ebca6 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -56,8 +56,9 @@ public class Solver extends Z3Object } /** - * The current number of backtracking points (scopes). - * + * The current number of backtracking points (scopes). + * @see pop + * @see push **/ public int getNumScopes() throws Z3Exception { @@ -66,7 +67,8 @@ public class Solver extends Z3Object } /** - * Creates a backtracking point. + * Creates a backtracking point. + * @see pop **/ public void push() throws Z3Exception { @@ -74,7 +76,8 @@ public class Solver extends Z3Object } /** - * Backtracks one backtracking point. . + * Backtracks one backtracking point. + * Remarks: . **/ public void pop() throws Z3Exception { @@ -82,9 +85,11 @@ public class Solver extends Z3Object } /** - * Backtracks backtracking points. Note that - * an exception is thrown if is not smaller than - * NumScopes + * Backtracks {@code n} backtracking points. + * Remarks: Note that + * an exception is thrown if {@code n} is not smaller than + * {@code NumScopes} + * @see push **/ public void pop(int n) throws Z3Exception { @@ -92,8 +97,9 @@ public class Solver extends Z3Object } /** - * Resets the Solver. This removes all assertions from the - * solver. + * Resets the Solver. + * Remarks: This removes all assertions from the + * solver. **/ public void reset() throws Z3Exception { @@ -115,12 +121,12 @@ public class Solver extends Z3Object } } - // / + // / // / Assert multiple constraints into the solver, and track them (in the // unsat) core // / using the Boolean constants in ps. - // / - // / + // / + // / Remarks: // / This API is an alternative to with assumptions for // extracting unsat cores. // / Both APIs can be used in the same solver. The unsat core will contain a @@ -128,7 +134,7 @@ public class Solver extends Z3Object // / of the Boolean variables provided using // and the Boolean literals // / provided using with assumptions. - // / + // / public void assertAndTrack(BoolExpr[] constraints, BoolExpr[] ps) throws Z3Exception { getContext().checkContextMatch(constraints); @@ -141,11 +147,11 @@ public class Solver extends Z3Object constraints[i].getNativeObject(), ps[i].getNativeObject()); } - // / + // / // / Assert a constraint into the solver, and track it (in the unsat) core // / using the Boolean constant p. - // / - // / + // / + // / Remarks: // / This API is an alternative to with assumptions for // extracting unsat cores. // / Both APIs can be used in the same solver. The unsat core will contain a @@ -153,7 +159,7 @@ public class Solver extends Z3Object // / of the Boolean variables provided using // and the Boolean literals // / provided using with assumptions. - // / + // / public void assertAndTrack(BoolExpr constraint, BoolExpr p) throws Z3Exception { getContext().checkContextMatch(constraint); @@ -193,8 +199,10 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. - * + * Remarks: + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check(Expr... assumptions) throws Z3Exception { @@ -219,8 +227,10 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. - * + * Remarks: + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check() throws Z3Exception { @@ -228,10 +238,11 @@ public class Solver extends Z3Object } /** - * The model of the last Check. The result is - * null if Check was not invoked before, if its - * results was not SATISFIABLE, or if model production is not - * enabled. + * The model of the last {@code Check}. + * Remarks: The result is + * {@code null} if {@code Check} was not invoked before, if its + * results was not {@code SATISFIABLE}, or if model production is not + * enabled. * * @throws Z3Exception **/ @@ -245,10 +256,11 @@ public class Solver extends Z3Object } /** - * The proof of the last Check. The result is - * null if Check was not invoked before, if its - * results was not UNSATISFIABLE, or if proof production is - * disabled. + * The proof of the last {@code Check}. + * Remarks: The result is + * {@code null} if {@code Check} was not invoked before, if its + * results was not {@code UNSATISFIABLE}, or if proof production is + * disabled. * * @throws Z3Exception **/ @@ -262,10 +274,11 @@ public class Solver extends Z3Object } /** - * The unsat core of the last Check. The unsat core - * is a subset of Assertions The result is empty if - * Check was not invoked before, if its results was not - * UNSATISFIABLE, or if core production is disabled. + * The unsat core of the last {@code Check}. + * Remarks: The unsat core + * is a subset of {@code Assertions} The result is empty if + * {@code Check} was not invoked before, if its results was not + * {@code UNSATISFIABLE}, or if core production is disabled. * * @throws Z3Exception **/ @@ -282,8 +295,8 @@ public class Solver extends Z3Object } /** - * A brief justification of why the last call to Check returned - * UNKNOWN. + * A brief justification of why the last call to {@code Check} returned + * {@code UNKNOWN}. **/ public String getReasonUnknown() throws Z3Exception { diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 7d89428c6..e8043b193 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -28,8 +28,8 @@ public class Sort extends AST /* Overloaded operators are not translated. */ /** - * Equality operator for objects of type Sort. - * + * Equality operator for objects of type Sort. + * @param o * @return **/ public boolean equals(Object o) diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index 315feeaa2..88a897d15 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -24,7 +24,7 @@ public class Statistics extends Z3Object { /** * Statistical data is organized into pairs of [Key, Entry], where every - * Entry is either a DoubleEntry or a UIntEntry + * Entry is either a {@code DoubleEntry} or a {@code UIntEntry} **/ public class Entry { @@ -176,8 +176,9 @@ public class Statistics extends Z3Object } /** - * The value of a particular statistical counter. Returns null if - * the key is unknown. + * The value of a particular statistical counter. + * Remarks: Returns null if + * the key is unknown. * * @throws Z3Exception **/ diff --git a/src/api/java/StringSymbol.java b/src/api/java/StringSymbol.java index 09273c946..4692b0fb9 100644 --- a/src/api/java/StringSymbol.java +++ b/src/api/java/StringSymbol.java @@ -25,8 +25,9 @@ import com.microsoft.z3.enumerations.Z3_symbol_kind; public class StringSymbol extends Symbol { /** - * The string value of the symbol. Throws an exception if the - * symbol is not of string kind. + * The string value of the symbol. + * Remarks: Throws an exception if the + * symbol is not of string kind. **/ public String getString() throws Z3Exception { diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index 6573a1407..0286e786d 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -20,8 +20,8 @@ package com.microsoft.z3; /** * Tactics are the basic building block for creating custom solvers for specific * problem domains. The complete list of tactics may be obtained using - * Context.NumTactics and Context.TacticNames. It may - * also be obtained using the command (help-tactics) in the SMT 2.0 + * {@code Context.NumTactics} and {@code Context.TacticNames}. It may + * also be obtained using the command {@code (help-tactics)} in the SMT 2.0 * front-end. **/ public class Tactic extends Z3Object @@ -73,8 +73,8 @@ public class Tactic extends Z3Object } /** - * Creates a solver that is implemented using the given tactic. + * Creates a solver that is implemented using the given tactic. + * @see Context#mkSolver(Tactic) * @throws Z3Exception **/ public Solver getSolver() throws Z3Exception diff --git a/src/api/java/Version.java b/src/api/java/Version.java index 3f019390b..6e2fe5084 100644 --- a/src/api/java/Version.java +++ b/src/api/java/Version.java @@ -18,7 +18,8 @@ Notes: package com.microsoft.z3; /** - * Version information. Note that this class is static. + * Version information. + * Remarks: Note that this class is static. **/ public class Version { From 6bfc9878fb90c73cb80b7b80f725f70c9db01238 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 15:13:57 +0000 Subject: [PATCH 142/646] FPA API cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_fpa.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 8208fbb2c..043d43e2f 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -821,18 +821,18 @@ extern "C" { \param s FloatingPoint sort. - def_API('Z3_mk_fpa_get_ebits', UINT, (_in(CONTEXT),_in(SORT))) + def_API('Z3_fpa_get_ebits', UINT, (_in(CONTEXT),_in(SORT))) */ - unsigned Z3_API Z3_mk_fpa_get_ebits(__in Z3_context c, __in Z3_sort s); + unsigned Z3_API Z3_fpa_get_ebits(__in Z3_context c, __in Z3_sort s); /** \brief Retrieves the number of bits reserved for the significand in a FloatingPoint sort. \param s FloatingPoint sort. - def_API('Z3_mk_fpa_get_sbits', UINT, (_in(CONTEXT),_in(SORT))) + def_API('Z3_fpa_get_sbits', UINT, (_in(CONTEXT),_in(SORT))) */ - unsigned Z3_API Z3_mk_fpa_get_sbits(__in Z3_context c, __in Z3_sort s); + unsigned Z3_API Z3_fpa_get_sbits(__in Z3_context c, __in Z3_sort s); /** \brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. From 3a2db1c793289014f2a8d487b9bbbbb23ea57e56 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 15:15:55 +0000 Subject: [PATCH 143/646] FPA API cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/FPSort.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/dotnet/FPSort.cs b/src/api/dotnet/FPSort.cs index 8d8560e53..e1ad62d49 100644 --- a/src/api/dotnet/FPSort.cs +++ b/src/api/dotnet/FPSort.cs @@ -29,12 +29,12 @@ namespace Microsoft.Z3 /// /// The number of exponent bits. /// - public uint EBits { get { return Native.Z3_mk_fpa_get_ebits(Context.nCtx, NativeObject); } } + public uint EBits { get { return Native.Z3_fpa_get_ebits(Context.nCtx, NativeObject); } } /// /// The number of significand bits. /// - public uint SBits { get { return Native.Z3_mk_fpa_get_ebits(Context.nCtx, NativeObject); } } + public uint SBits { get { return Native.Z3_fpa_get_sbits(Context.nCtx, NativeObject); } } #region Internal internal FPSort(Context ctx, IntPtr obj) From cf4dc527c420a1e5e221f47aec7757fd1b0773ff Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 16:49:42 +0000 Subject: [PATCH 144/646] .NET FPA API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 986efc94d..f3e6220cf 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3590,7 +3590,7 @@ namespace Microsoft.Z3 public FPSort MkFPSort32() { Contract.Ensures(Contract.Result() != null); - return new FPSort(this, Native.Z3_mk_fpa_sort_16(nCtx)); + return new FPSort(this, Native.Z3_mk_fpa_sort_32(nCtx)); } /// @@ -3617,7 +3617,7 @@ namespace Microsoft.Z3 public FPSort MkFPSortQuadruple() { Contract.Ensures(Contract.Result() != null); - return new FPSort(this, Native.Z3_mk_fpa_sort_double(nCtx)); + return new FPSort(this, Native.Z3_mk_fpa_sort_quadruple(nCtx)); } /// From fa26e2423ef6f6c674b06a4b465f54baef2d96bf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 16:50:31 +0000 Subject: [PATCH 145/646] Java API: Added FPA Signed-off-by: Christoph M. Wintersteiger --- src/api/java/AST.java | 4 +- src/api/java/ASTMap.java | 4 +- src/api/java/ASTVector.java | 4 +- src/api/java/AlgebraicNum.java | 11 +- src/api/java/Context.java | 878 +++++++++++++++++++++++-- src/api/java/Expr.java | 10 +- src/api/java/Fixedpoint.java | 4 +- src/api/java/Global.java | 4 +- src/api/java/InterpolationContext.java | 2 +- src/api/java/Model.java | 8 +- src/api/java/Solver.java | 12 +- 11 files changed, 868 insertions(+), 73 deletions(-) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index a201d5697..579d4b24d 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -28,7 +28,7 @@ public class AST extends Z3Object /** * Object comparison. - * another AST + * @param o another AST **/ public boolean equals(Object o) { @@ -46,7 +46,7 @@ public class AST extends Z3Object } /** - * Object Comparison. Another AST + * Object Comparison. @param other Another AST * * @return Negative if the object should be sorted before , positive if after else zero. diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index 6a4e6d56f..a26140a3d 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -39,7 +39,7 @@ class ASTMap extends Z3Object /** * Finds the value associated with the key . * This function signs an error when is not a key in - * the map. An AST + * the map. @param k An AST * * @throws Z3Exception **/ @@ -51,7 +51,7 @@ class ASTMap extends Z3Object /** * Stores or replaces a new key/value pair in the map. The - * key AST The value AST + * key AST @param v The value AST **/ public void insert(AST k, AST v) throws Z3Exception { diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 07b7dbf56..99879848f 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -33,7 +33,7 @@ class ASTVector extends Z3Object /** * Retrieves the i-th object in the vector. May throw an * IndexOutOfBoundsException when is out of - * range. Index + * range. @param i Index * * @return An AST * @throws Z3Exception @@ -62,7 +62,7 @@ class ASTVector extends Z3Object /** * Add the AST to the back of the vector. The size is - * increased by 1. An AST + * increased by 1. @param a An AST **/ public void push(AST a) throws Z3Exception { diff --git a/src/api/java/AlgebraicNum.java b/src/api/java/AlgebraicNum.java index 340f37f80..a45e5a58e 100644 --- a/src/api/java/AlgebraicNum.java +++ b/src/api/java/AlgebraicNum.java @@ -25,7 +25,7 @@ public class AlgebraicNum extends ArithExpr /** * Return a upper bound for a given real algebraic number. The interval * isolating the number is smaller than 1/10^. - * the + * @see Expr.IsAlgebraicNumber the * precision of the result * * @return A numeral Expr of sort Real @@ -33,14 +33,17 @@ public class AlgebraicNum extends ArithExpr public RatNum toUpper(int precision) throws Z3Exception { - return new RatNum(getContext(), Native.getAlgebraicNumberUpper(getContext() - .nCtx(), getNativeObject(), precision)); + return new RatNum(getContext(), + Native.getAlgebraicNumberUpper( + getContext().nCtx(), + getNativeObject(), + precision)); } /** * Return a lower bound for the given real algebraic number. The interval * isolating the number is smaller than 1/10^. - * + * @see Expr.IsAlgebraicNumber @param precision * * @return A numeral Expr of sort Real **/ diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 4fbd79be2..cd3b9bebd 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -294,9 +294,9 @@ public class Context extends IDisposable } /** - * Create a datatype constructor. + * Create a datatype constructor. @param name @param fieldNames @param sortRefs * * @return **/ @@ -363,7 +363,7 @@ public class Context extends IDisposable } /** - * Create mutually recursive data-types. * * @return @@ -429,7 +429,7 @@ public class Context extends IDisposable /** * Creates a fresh function declaration with a name prefixed with . . @see MkFuncDecl(string,Sort,Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) @@ -464,8 +464,8 @@ public class Context extends IDisposable /** * Creates a fresh constant function declaration with a name prefixed with - * . - * + * . @see MkFuncDecl(string,Sort,Sort) + * @see MkFuncDecl(string,Sort[],Sort) **/ public FuncDecl mkFreshConstDecl(String prefix, Sort range) throws Z3Exception @@ -477,7 +477,7 @@ public class Context extends IDisposable /** * Creates a new bound variable. The de-Bruijn index of - * the variable The sort of the variable + * the variable @param ty The sort of the variable **/ public Expr mkBound(int index, Sort ty) throws Z3Exception { @@ -686,7 +686,7 @@ public class Context extends IDisposable /** * Create an expression representing an if-then-else: * ite(t1, t2, t3). An expression with Boolean - * sort An expression An + * sort @param t2 An expression An * expression with the same sort as **/ public Expr mkITE(BoolExpr t1, Expr t2, Expr t3) throws Z3Exception @@ -1654,7 +1654,7 @@ public class Context extends IDisposable * The node a must have an array sort * [domain -> range], and i must have the sort * domain. The sort of the result is range. - * + * @see MkArraySort"/> + * cref="MkArraySort"/> @see MkSelect **/ public ArrayExpr mkStore(ArrayExpr a, Expr i, Expr v) throws Z3Exception { @@ -1693,7 +1693,7 @@ public class Context extends IDisposable /** * Create a constant array. The resulting term is an array, such * that a selecton an arbitrary index produces the value - * v. + * v. @see MkArraySort"/> + * [domain_i -> range]. @see MkArraySort @see MkStore **/ public ArrayExpr mkMap(FuncDecl f, ArrayExpr... args) throws Z3Exception { @@ -1899,7 +1899,7 @@ public class Context extends IDisposable * Create a Term of a given sort. This function can be use to create * numerals that fit in a machine integer. It is slightly faster than * MakeNumeral since it is not necessary to parse a string. - * Value of the numeral Sort of the + * @param v Value of the numeral Sort of the * numeral * * @return A Term with value and type MakeNumeral since it is not necessary to parse a string. - * Value of the numeral Sort of the + * @param v Value of the numeral Sort of the * numeral * * @return A Term with value and type numerator of - * rational. denominator of rational. + * rational. @param den denominator of rational. * * @return A Term with value / - * and sort Real + * and sort Real @see MkNumeral(string, Sort) **/ public RatNum mkReal(int num, int den) throws Z3Exception { @@ -1959,7 +1959,7 @@ public class Context extends IDisposable } /** - * Create a real numeral. value of the numeral. + * Create a real numeral. @param v value of the numeral. * * @return A Term with value and sort Real **/ @@ -1971,7 +1971,7 @@ public class Context extends IDisposable } /** - * Create a real numeral. value of the numeral. + * Create a real numeral. @param v value of the numeral. * * @return A Term with value and sort Real **/ @@ -1994,7 +1994,7 @@ public class Context extends IDisposable } /** - * Create an integer numeral. value of the numeral. + * Create an integer numeral. @param v value of the numeral. * * @return A Term with value and sort Integer **/ @@ -2006,7 +2006,7 @@ public class Context extends IDisposable } /** - * Create an integer numeral. value of the numeral. + * Create an integer numeral. @param v value of the numeral. * * @return A Term with value and sort Integer **/ @@ -2030,7 +2030,7 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. value of the - * numeral. the size of the bit-vector + * numeral. @param size the size of the bit-vector **/ public BitVecNum mkBV(int v, int size) throws Z3Exception { @@ -2040,7 +2040,7 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. value of the - * numeral. * the size of the bit-vector + * numeral. * @param size the size of the bit-vector **/ public BitVecNum mkBV(long v, int size) throws Z3Exception { @@ -2056,7 +2056,7 @@ public class Context extends IDisposable * 'names' of the bound variables, and is the body * of the quantifier. Quantifiers are associated with weights indicating the * importance of using the quantifier during instantiation. - * the sorts of the bound variables. names of the bound variables the * body of the quantifier. quantifiers are * associated with weights indicating the importance of using the quantifier @@ -2154,8 +2154,8 @@ public class Context extends IDisposable * subexpressions only once, use the Z3_PRINT_LOW_LEVEL mode. To print in * way that conforms to SMT-LIB standards and uses let expressions to share * common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + * cref="AST.ToString()"/> @see Pattern.ToString() @see Sort.ToString() **/ public void setPrintMode(Z3_ast_print_mode value) throws Z3Exception { @@ -2165,7 +2165,7 @@ public class Context extends IDisposable /** * Convert a benchmark into an SMT-LIB formatted string. Name of the benchmark. The argument is optional. - * The benchmark logic. The status string (sat, unsat, or unknown) Other attributes, such as source, difficulty or * category. Auxiliary @@ -2809,12 +2809,11 @@ public class Context extends IDisposable if (logic == null) return new Solver(this, Native.mkSolver(nCtx())); else - return new Solver(this, Native.mkSolverForLogic(nCtx(), - logic.getNativeObject())); + return new Solver(this, Native.mkSolverForLogic(nCtx(), logic.getNativeObject())); } /** - * Creates a new (incremental) solver. + * Creates a new (incremental) solver. @see MkSolver(Symbol) **/ public Solver mkSolver(String logic) throws Z3Exception { @@ -2839,8 +2838,7 @@ public class Context extends IDisposable public Solver mkSolver(Tactic t) throws Z3Exception { - return new Solver(this, Native.mkSolverFromTactic(nCtx(), - t.getNativeObject())); + return new Solver(this, Native.mkSolverFromTactic(nCtx(), t.getNativeObject())); } /** @@ -2851,15 +2849,807 @@ public class Context extends IDisposable return new Fixedpoint(this); } + + /** Begin Floating-Point Arithmetic **/ + + /** Rounding Modes: RoundingMode Sort **/ + + /** + * Create the floating-point RoundingMode sort. + * @throws Z3Exception on error + **/ + public FPRMSort mkFPRoundingModeSort() throws Z3Exception + { + return new FPRMSort(this); + } + + /** Rounding Modes: Numerals **/ + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. + * @throws Z3Exception on error + **/ + public FPRMNum mkFPRoundNearestTiesToEven() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRNE() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRne(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundNearestTiesToAway() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRNA() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRna(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardPositive() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardPositive(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTP() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtp(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardNegative() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardNegative(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTN() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtn(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardZero() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardZero(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTZ() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtz(nCtx())); + } + + /** FloatingPoint Sorts **/ + + /** + * Create a FloatingPoint sort. + * @param ebits exponent bits in the FloatingPoint sort. + * @param sbits significand bits in the FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort(int ebits, int sbits) throws Z3Exception + { + return new FPSort(this, ebits, sbits); + } + + /** + * Create the half-precision (16-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortHalf() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortHalf(nCtx())); + } + + /** + * Create the half-precision (16-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort16() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort16(nCtx())); + } + + /** + * Create the single-precision (32-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortSingle() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortSingle(nCtx())); + } + + /** + * Create the single-precision (32-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort32() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort16(nCtx())); + } + + /** + * Create the double-precision (64-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortDouble() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortDouble(nCtx())); + } + + /** + * Create the double-precision (64-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort64() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort64(nCtx())); + } + + /** + * Create the quadruple-precision (128-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortQuadruple() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortQuadruple(nCtx())); + } + + /** + * Create the quadruple-precision (128-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort128() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort128(nCtx())); + } + + /** FloatingPoint Numerals **/ + + /** + * Create a NaN of sort s. + * @throws Z3Exception + * @param s FloatingPoint sort. + **/ + public FPNum mkFPNaN(FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNan(nCtx(), s.getNativeObject())); + } + + /** + * Create a floating-point infinity of sort s. + * @throws Z3Exception + * @param s FloatingPoint sort. + * @param negative indicates whether the result should be negative. + **/ + public FPNum mkFPInf(FPSort s, boolean negative) throws Z3Exception + { + return new FPNum(this, Native.mkFpaInf(nCtx(), s.getNativeObject(), negative)); + } + + /** + * Create a floating-point zero of sort s. + * @throws Z3Exception + * @param s FloatingPoint sort. + * @param negative indicates whether the result should be negative. + **/ + public FPNum mkFPZero(FPSort s, boolean negative) throws Z3Exception + { + return new FPNum(this, Native.mkFpaZero(nCtx(), s.getNativeObject(), negative)); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @throws Z3Exception + * @param v numeral value. + * @param s FloatingPoint sort. + **/ + public FPNum mkFPNumeral(float v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralFloat(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @throws Z3Exception + * @param v numeral value. + * @param s FloatingPoint sort. + **/ + public FPNum mkFPNumeral(double v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralDouble(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from an int. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(int v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralInt(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(boolean sgn, int sig, int exp, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralUintInt(nCtx(), sgn, sig, exp, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two long integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(boolean sgn, long sig, long exp, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralUint64Int64(nCtx(), sgn, sig, exp, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(float v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(double v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from an int. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(int v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(boolean sgn, int sig, int exp, FPSort s) throws Z3Exception + { + return mkFPNumeral(sgn, sig, exp, s); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(boolean sgn, long sig, long exp, FPSort s) throws Z3Exception + { + return mkFPNumeral(sgn, sig, exp, s); + } + + /** FloatingPoint Operators **/ + + /** + * Floating-point absolute value + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPAbs(FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaAbs(nCtx(), t.getNativeObject())); + } + + /** + * Floating-point negation + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPNeg(FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaNeg(nCtx(), t.getNativeObject())); + } + + /** + * Floating-point addition + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaAdd(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point subtraction + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaSub(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point multiplication + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMul(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point division + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaDiv(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point fused multiply-add + * + * Remarks: The result is round((t1 * t2) + t3) + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @param t3 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaFma(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject(), t3.getNativeObject())); + } + + /** + * Floating-point square root + * @param rm rounding mode term + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPSqrt(FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaSqrt(nCtx(), rm.getNativeObject(), t.getNativeObject())); + } + + /** + * Floating-point remainder + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPRem(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaRem(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } /** - * Wraps an AST. This function is used for transitions between + * Floating-point roundToIntegral. Rounds a floating-point number to + * the closest integer, again represented as a floating-point number. + * @param rm term of RoundingMode sort + * @param t2 floating-point term + * @throws Z3Exception + */ + public FPExpr mkFPRoundToIntegral(FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaRoundToIntegral(nCtx(), rm.getNativeObject(), t.getNativeObject())); + } + + /** + * Minimum of floating-point numbers. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMin(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMin(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Maximum of floating-point numbers. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMax(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMax(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point less than or equal. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPLEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + + return new BoolExpr(this, Native.mkFpaLeq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point less than. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPLt(FPExpr t1, FPExpr t2) throws Z3Exception + { + + return new BoolExpr(this, Native.mkFpaLt(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point greater than or equal. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPGEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + + return new BoolExpr(this, Native.mkFpaGeq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point greater than. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPGt(FPExpr t1, FPExpr t2) throws Z3Exception + { + + return new BoolExpr(this, Native.mkFpaGt(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point equality. + * + * Remarks: Note that this is IEEE 754 equality (as opposed to standard =). + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaEq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Predicate indicating whether t is a normal floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNormal(FPExpr t) throws Z3Exception + { + + return new BoolExpr(this, Native.mkFpaIsNormal(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a subnormal floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsSubnormal(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsSubnormal(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a floating-point number with zero value, i.e., +0 or -0. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsZero(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsZero(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a floating-point number representing +oo or -oo. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsInfinite(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsInfinite(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a NaN. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNaN(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsNan(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a negative floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNegative(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsNegative(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a positive floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsPositive(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsPositive(nCtx(), t.getNativeObject())); + } + + /** Conversions to FloatingPoint terms **/ + + /** + * Create an expression of FloatingPoint sort from three bit-vector expressions. + * + * Remarks: This is the operator named `fp' in the SMT FP theory definition. + * Note that sgn is required to be a bit-vector of size 1. Significand and exponent + * are required to be greater than 1 and 2 respectively. The FloatingPoint sort + * of the resulting expression is automatically determined from the bit-vector sizes + * of the arguments. + * @param sgn bit-vector term (of size 1) representing the sign. + * @param sig bit-vector term representing the significand. + * @param exp bit-vector term representing the exponent. + * @throws Z3Exception + **/ + public FPExpr mkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaFp(nCtx(), sgn.getNativeObject(), sig.getNativeObject(), exp.getNativeObject())); + } + + /** + * Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. + * + * Remarks: Produces a term that represents the conversion of a bit-vector term bv to a + * floating-point term of sort s. The bit-vector size of bv (m) must be equal + * to ebits+sbits of s. The format of the bit-vector is as defined by the + * IEEE 754-2008 interchange format. + * @param bv bit-vector value (of size m). + * @param s FloatingPoint sort (ebits+sbits == m) + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(BitVecExpr bv, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpBv(nCtx(), bv.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a FloatingPoint term into another term of different FloatingPoint sort. + * + * Remarks: Produces a term that represents the conversion of a floating-point term t to a + * floating-point term of sort s. If necessary, the result will be rounded according + * to rounding mode rm. + * @param rm RoundingMode term. + * @param t FloatingPoint term. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, FPExpr t, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpFloat(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a term of real sort into a term of FloatingPoint sort. + * + * Remarks: Produces a term that represents the conversion of term t of real sort into a + * floating-point term of sort s. If necessary, the result will be rounded according + * to rounding mode rm. + * @param rm RoundingMode term. + * @param t term of Real sort. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, RealExpr t, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpReal(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. + * + * Remarks: Produces a term that represents the conversion of the bit-vector term t into a + * floating-point term of sort s. The bit-vector t is taken to be in signed + * 2's complement format (when signed==true, otherwise unsigned). If necessary, the + * result will be rounded according to rounding mode rm. + * @param rm RoundingMode term. + * @param t term of bit-vector sort. + * @param s FloatingPoint sort. + * @param signed flag indicating whether t is interpreted as signed or unsigned bit-vector. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, boolean signed) throws Z3Exception + { + if (signed) + return new FPExpr(this, Native.mkFpaToFpSigned(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + else + return new FPExpr(this, Native.mkFpaToFpUnsigned(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a floating-point number to another FloatingPoint sort s. + * + * Remarks: Produces a term that represents the conversion of a floating-point term t to a different + * FloatingPoint sort s. If necessary, rounding according to rm is applied. + * @param s FloatingPoint sort + * @param rm floating-point rounding mode term + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpFloat(nCtx(), s.getNativeObject(), rm.getNativeObject(), t.getNativeObject())); + } + + /** Conversions from FloatingPoint terms **/ + + /** + * Conversion of a floating-point term into a bit-vector. + * + * Remarks: Produces a term that represents the conversion of the floating-poiunt term t into a + * bit-vector term of size sz in 2's complement format (signed when signed==true). If necessary, + * the result will be rounded according to rounding mode rm. + * @param rm RoundingMode term. + * @param t FloatingPoint term + * @param sz Size of the resulting bit-vector. + * @param signed Indicates whether the result is a signed or unsigned bit-vector. + * @throws Z3Exception + **/ + public BitVecExpr mkFPToBV(FPRMExpr rm, FPExpr t, int sz, boolean signed) throws Z3Exception + { + if (signed) + return new BitVecExpr(this, Native.mkFpaToSbv(nCtx(), rm.getNativeObject(), t.getNativeObject(), sz)); + else + return new BitVecExpr(this, Native.mkFpaToUbv(nCtx(), rm.getNativeObject(), t.getNativeObject(), sz)); + } + + /** + * Conversion of a floating-point term into a real-numbered term. + * + * Remarks: Produces a term that represents the conversion of the floating-poiunt term t into a + * real number. Note that this type of conversion will often result in non-linear + * constraints over real terms. + * @param t FloatingPoint term + * @throws Z3Exception + **/ + public RealExpr mkFPToReal(FPExpr t) throws Z3Exception + { + return new RealExpr(this, Native.mkFpaToReal(nCtx(), t.getNativeObject())); + } + + /** Z3-specific extensions **/ + + /** + * Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. + * + * Remarks: The size of the resulting bit-vector is automatically determined. Note that + * IEEE 754-2008 allows multiple different representations of NaN. This conversion + * knows only one NaN and it will always produce the same bit-vector represenatation of + * that NaN. + * @param t FloatingPoint term. + * @throws Z3Exception + **/ + public BitVecExpr mkFPToIEEEBV(FPExpr t) throws Z3Exception + { + return new BitVecExpr(this, Native.mkFpaToIeeeBv(nCtx(), t.getNativeObject())); + } + + /** + * Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. + * + * Remarks: Produces a term that represents the conversion of sig * 2^exp into a + * floating-point term of sort s. If necessary, the result will be rounded + * according to rounding mode rm. + * @param rm RoundingMode term. + * @param sig Significand term of Real sort. + * @param exp Exponent term of Int sort. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public BitVecExpr mkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s) throws Z3Exception + { + return new BitVecExpr(this, Native.mkFpaToFpRealInt(nCtx(), rm.getNativeObject(), sig.getNativeObject(), exp.getNativeObject(), s.getNativeObject())); + } + + /** End Floating-Point Arithmetic **/ + + /** + * Wraps an AST. + * Remarks: This function is used for transitions between * native and managed objects. Note that - * must be a native object obtained from Z3 (e.g., through ) and that it must have a correct reference count (see - * e.g., . The native pointer to - * wrap. + * must be a native object obtained from Z3 (e.g., through {@code unwrapAST}) + * and that it must have a correct reference count. + * @see Native.incRef + * @see wnwrapAST + * The native pointer to wrap. **/ public AST wrapAST(long nativeObject) throws Z3Exception { @@ -2868,13 +3658,15 @@ public class Context extends IDisposable } /** - * Unwraps an AST. This function is used for transitions between + * Unwraps an AST. + * Remarks: This function is used for transitions between * native and managed objects. It returns the native pointer to the AST. * Note that AST objects are reference counted and unwrapping an AST * disables automatic reference counting, i.e., all references to the IntPtr - * that is returned must be handled externally and through native calls (see - * e.g., ). The AST to unwrap. + * that is returned must be handled externally and through native calls + * @see Native.incRef + * @see wrapAST + * @param a The AST to unwrap. **/ public long unwrapAST(AST a) { diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index a4c669dad..6a7241e98 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -40,8 +40,8 @@ public class Expr extends AST /** * Returns a simplified version of the expression * A set of - * parameters a Params object to configure the simplifier - * + * parameters @param p a Params object to configure the simplifier + * @see Context.SimplifyHelp **/ public Expr simplify(Params p) throws Z3Exception { @@ -133,7 +133,7 @@ public class Expr extends AST /** * Substitute every occurrence of from in the expression with - * to. + * to. @see Substitute(Expr[],Expr[]) **/ public Expr substitute(Expr from, Expr to) throws Z3Exception { @@ -157,7 +157,7 @@ public class Expr extends AST /** * Translates (copies) the term to the Context . - * A context + * @param ctx A context * * @return A copy of the term which is associated with @@ -1682,7 +1682,7 @@ public class Expr extends AST * Indicates whether the term is a relational clone (copy) Create * a fresh copy (clone) of a relation. The function is logically the * identity, but in the context of a register machine allows for terms of - * kind to perform destructive updates to + * kind @see IsRelationUnion to perform destructive updates to * the first argument. **/ public boolean isRelationClone() throws Z3Exception diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index 57e1e105a..37653bbd0 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -163,7 +163,7 @@ public class Fixedpoint extends Z3Object } /** - * Creates a backtracking point. + * Creates a backtracking point. @see Pop **/ public void push() throws Z3Exception { @@ -173,7 +173,7 @@ public class Fixedpoint extends Z3Object /** * Backtrack one backtracking point. Note that an exception is * thrown if Pop is called without a corresponding Push - * + * @see Push **/ public void pop() throws Z3Exception { diff --git a/src/api/java/Global.java b/src/api/java/Global.java index c93f46c88..2fa3abbbe 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -50,7 +50,7 @@ public final class Global /** * Get a global (or module) parameter. * - * Returns null if the parameter parameter id does not exist. + * Returns null if the parameter @param id parameter id does not exist. * This function cannot be invoked simultaneously from different threads without synchronization. * The result string stored in param_value is stored in a shared location. * @@ -69,7 +69,7 @@ public final class Global * * This command will not affect already created objects (such as tactics and solvers) * - * + * @see SetParameter **/ public static void resetParameters() { diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 05d99b305..43ae86162 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -42,7 +42,7 @@ public class InterpolationContext extends Context /** * Constructor. * - * + * @see Context.Context(Dictionary<string, string>) **/ public InterpolationContext(Map settings) throws Z3Exception { diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 11eed201e..1ebe7973b 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -26,7 +26,7 @@ public class Model extends Z3Object { /** * Retrieves the interpretation (the assignment) of in - * the model. A Constant + * the model. @param a A Constant * * @return An expression if the constant has an interpretation in the model, * null otherwise. @@ -40,7 +40,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of in - * the model. A function declaration of zero arity + * the model. @param f A function declaration of zero arity * * @return An expression if the function has an interpretation in the model, * null otherwise. @@ -242,7 +242,7 @@ public class Model extends Z3Object * Z3 also provides an intepretation for uninterpreted sorts used * in a formula. The interpretation for a sort is a finite set of distinct * values. We say this finite set is the "universe" of the sort. - * + * @see NumSorts"/> . An + * sort . @see Sorts An * uninterpreted sort * * @return An array of expressions, where each is an element of the universe diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index e129189f9..4a7c1ed09 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -56,8 +56,8 @@ public class Solver extends Z3Object } /** - * The current number of backtracking points (scopes). - * + * The current number of backtracking points (scopes). @see Pop + * @see Push **/ public int getNumScopes() throws Z3Exception { @@ -66,7 +66,7 @@ public class Solver extends Z3Object } /** - * Creates a backtracking point. + * Creates a backtracking point. @see Pop **/ public void push() throws Z3Exception { @@ -84,7 +84,7 @@ public class Solver extends Z3Object /** * Backtracks backtracking points. Note that * an exception is thrown if is not smaller than - * NumScopes + * NumScopes @see Push **/ public void pop(int n) throws Z3Exception { @@ -193,7 +193,7 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. - * @see Model"/> **/ public Status check(Expr... assumptions) throws Z3Exception @@ -219,7 +219,7 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. - * @see Model"/> **/ public Status check() throws Z3Exception From 0faf329054fc64410f5d832ca4473678bf946604 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 3 Jan 2015 17:26:58 +0000 Subject: [PATCH 146/646] FPA API: bugfixes and examples for .NET and Java Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 101 +++++++++++++++++++++------------ examples/java/JavaExample.java | 84 ++++++++++++++++++++++++++- src/api/api_fpa.cpp | 18 +++--- src/api/dotnet/Context.cs | 2 +- src/api/java/Expr.java | 8 +++ 5 files changed, 165 insertions(+), 48 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 3d2910c8f..b03cfd28c 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2028,53 +2028,81 @@ namespace test_mapi // Console.WriteLine("{0}", ctx.MkEq(s1, t1)); } - public static void FloatingPointExample(Context ctx) + public static void FloatingPointExample1(Context ctx) { - Console.WriteLine("FloatingPointExample"); + Console.WriteLine("FloatingPointExample1"); FPSort s = ctx.MkFPSort(11, 53); Console.WriteLine("Sort: {0}", s); - FPNum x = (FPNum)ctx.MkNumeral("-1e1", s); - Console.WriteLine("Numeral: {0}", x.ToString()); - - FPNum y = (FPNum)ctx.MkNumeral("-10", s); - Console.WriteLine("Numeral: {0}", y.ToString()); - - FPNum z = (FPNum)ctx.MkNumeral("-1.25p3", s); - Console.WriteLine("Numeral: {0}", z.ToString()); + FPNum x = (FPNum)ctx.MkNumeral("-1e1", s); /* -1 * 10^1 = -10 */ + FPNum y = (FPNum)ctx.MkNumeral("-10", s); /* -10 */ + FPNum z = (FPNum)ctx.MkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */ + Console.WriteLine("x={0}; y={1}; z={2}", x.ToString(), y.ToString(), z.ToString()); BoolExpr a = ctx.MkAnd(ctx.MkFPEq(x, y), ctx.MkFPEq(y, z)); - Check(ctx, ctx.MkNot(a), Status.UNSATISFIABLE); - x = ctx.MkFPNaN(s); - FPExpr c = (FPExpr)ctx.MkConst("y", s); + /* nothing is equal to NaN according to floating-point + * equality, so NaN == k should be unsatisfiable. */ + FPExpr k = (FPExpr)ctx.MkConst("x", s); + FPExpr nan = ctx.MkFPNaN(s); - // Note: We need to use a special solver for QF_FPA here; the - // general solver does not support FPA yet. - - Solver slvr = ctx.MkSolver("QF_FPA"); - slvr.Add(ctx.MkFPEq(x, c)); - if (slvr.Check() != Status.UNSATISFIABLE) // nothing is equal to NaN according to floating-point equality. - throw new TestFailedException(); - - slvr = ctx.MkSolver("QF_FPA"); - slvr.Add(ctx.MkEq(x, c)); // NaN is equal to NaN according to normal equality. - if (slvr.Check() != Status.SATISFIABLE) - throw new TestFailedException(); - - - x = (FPNum)ctx.MkNumeral("-1e1", s); - y = (FPNum)ctx.MkNumeral("-10", s); - FPExpr q = (FPExpr)ctx.MkConst("q", s); - FPNum mh = (FPNum)ctx.MkNumeral("100", s); - slvr = ctx.MkSolver("QF_FPA"); - // Let's prove -1e1 * -10 == +100 - slvr.Add(ctx.MkEq(ctx.MkFPMul(ctx.MkFPRMNearestTiesToAway(), x, y), q)); - slvr.Add(ctx.MkNot(ctx.MkFPEq(q, mh))); + /* solver that runs the default tactic for QF_FP. */ + Solver slvr = ctx.MkSolver("QF_FP"); + slvr.Add(ctx.MkFPEq(nan, k)); if (slvr.Check() != Status.UNSATISFIABLE) throw new TestFailedException(); + Console.WriteLine("OK, unsat:" + Environment.NewLine + slvr); + + /* NaN is equal to NaN according to normal equality. */ + slvr = ctx.MkSolver("QF_FP"); + slvr.Add(ctx.MkEq(nan, nan)); + if (slvr.Check() != Status.SATISFIABLE) + throw new TestFailedException(); + Console.WriteLine("OK, sat:" + Environment.NewLine + slvr); + + /* Let's prove -1e1 * -1.25e3 == +100 */ + x = (FPNum)ctx.MkNumeral("-1e1", s); + y = (FPNum)ctx.MkNumeral("-1.25p3", s); + FPExpr x_plus_y = (FPExpr)ctx.MkConst("x_plus_y", s); + FPNum r = (FPNum)ctx.MkNumeral("100", s); + slvr = ctx.MkSolver("QF_FP"); + + slvr.Add(ctx.MkEq(x_plus_y, ctx.MkFPMul(ctx.MkFPRoundNearestTiesToAway(), x, y))); + slvr.Add(ctx.MkNot(ctx.MkFPEq(x_plus_y, r))); + if (slvr.Check() != Status.UNSATISFIABLE) + throw new TestFailedException(); + Console.WriteLine("OK, unsat:" + Environment.NewLine + slvr); + } + + public static void FloatingPointExample2(Context ctx) + { + Console.WriteLine("FloatingPointExample2"); + FPSort double_sort = ctx.MkFPSort(11, 53); + FPRMSort rm_sort = ctx.MkFPRoundingModeSort(); + + FPRMExpr rm = (FPRMExpr)ctx.MkConst(ctx.MkSymbol("rm"), rm_sort); + BitVecExpr x = (BitVecExpr)ctx.MkConst(ctx.MkSymbol("x"), ctx.MkBitVecSort(64)); + FPExpr y = (FPExpr)ctx.MkConst(ctx.MkSymbol("y"), double_sort); + RealExpr real_val = ctx.MkReal(42); + BitVecExpr bv_val = ctx.MkBV(42, 64); + FPExpr fp_val = ctx.MkFP(42, double_sort); + + BoolExpr c1 = ctx.MkEq(x, ctx.MkFPToIEEEBV(fp_val)); + BoolExpr c2 = ctx.MkEq(x, ctx.MkBV(42, 64)); + BoolExpr c3 = ctx.MkEq(fp_val, ctx.MkFPToFP(rm, real_val, double_sort)); + BoolExpr c4 = ctx.MkAnd(c1, c2); + Console.WriteLine("c3 = " + c3); + + /* Generic solver */ + Solver s = ctx.MkSolver(); + s.Assert(c3); + + if (s.Check() != Status.SATISFIABLE) + throw new TestFailedException(); + + Console.WriteLine("OK, model: ", s.Model.ToString()); } static void Main(string[] args) @@ -2118,7 +2146,8 @@ namespace test_mapi FindSmallModelExample(ctx); SimplifierExample(ctx); FiniteDomainExample(ctx); - FloatingPointExample(ctx); + FloatingPointExample1(ctx); + FloatingPointExample2(ctx); } // These examples need proof generation turned on. diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 48395d8c2..878ec4693 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -1095,7 +1095,7 @@ class JavaExample // / Shows how to use Solver(logic) - // / + // / @param ctx void logicExample(Context ctx) throws Z3Exception, TestFailedException { System.out.println("LogicTest"); @@ -2157,6 +2157,86 @@ class JavaExample // System.out.println(ctx.mkEq(s1, t1)); } + public void floatingPointExample1(Context ctx) throws Z3Exception, TestFailedException + { + System.out.println("FloatingPointExample1"); + Log.append("FloatingPointExample1"); + + FPSort s = ctx.mkFPSort(11, 53); + System.out.println("Sort: " + s); + + FPNum x = (FPNum)ctx.mkNumeral("-1e1", s); /* -1 * 10^1 = -10 */ + FPNum y = (FPNum)ctx.mkNumeral("-10", s); /* -10 */ + FPNum z = (FPNum)ctx.mkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */ + System.out.println("x=" + x.toString() + + "; y=" + y.toString() + + "; z=" + z.toString()); + + BoolExpr a = ctx.mkAnd(ctx.mkFPEq(x, y), ctx.mkFPEq(y, z)); + check(ctx, ctx.mkNot(a), Status.UNSATISFIABLE); + + /* nothing is equal to NaN according to floating-point + * equality, so NaN == k should be unsatisfiable. */ + FPExpr k = (FPExpr)ctx.mkConst("x", s); + FPExpr nan = ctx.mkFPNaN(s); + + /* solver that runs the default tactic for QF_FP. */ + Solver slvr = ctx.mkSolver("QF_FP"); + slvr.add(ctx.mkFPEq(nan, k)); + if (slvr.check() != Status.UNSATISFIABLE) + throw new TestFailedException(); + System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); + + /* NaN is equal to NaN according to normal equality. */ + slvr = ctx.mkSolver("QF_FP"); + slvr.add(ctx.mkEq(nan, nan)); + if (slvr.check() != Status.SATISFIABLE) + throw new TestFailedException(); + System.out.println("OK, sat:" + System.getProperty("line.separator") + slvr); + + /* Let's prove -1e1 * -1.25e3 == +100 */ + x = (FPNum)ctx.mkNumeral("-1e1", s); + y = (FPNum)ctx.mkNumeral("-1.25p3", s); + FPExpr x_plus_y = (FPExpr)ctx.mkConst("x_plus_y", s); + FPNum r = (FPNum)ctx.mkNumeral("100", s); + slvr = ctx.mkSolver("QF_FP"); + + slvr.add(ctx.mkEq(x_plus_y, ctx.mkFPMul(ctx.mkFPRoundNearestTiesToAway(), x, y))); + slvr.add(ctx.mkNot(ctx.mkFPEq(x_plus_y, r))); + if (slvr.check() != Status.UNSATISFIABLE) + throw new TestFailedException(); + System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); + } + + public void floatingPointExample2(Context ctx) throws Z3Exception, TestFailedException + { + System.out.println("FloatingPointExample2"); + Log.append("FloatingPointExample2"); + + FPSort double_sort = ctx.mkFPSort(11, 53); + FPRMSort rm_sort = ctx.mkFPRoundingModeSort(); + + FPRMExpr rm = (FPRMExpr)ctx.mkConst(ctx.mkSymbol("rm"), rm_sort); + BitVecExpr x = (BitVecExpr)ctx.mkConst(ctx.mkSymbol("x"), ctx.mkBitVecSort(64)); + RealExpr real_val = ctx.mkReal(42); + FPExpr fp_val = ctx.mkFP(42, double_sort); + + BoolExpr c1 = ctx.mkEq(x, ctx.mkFPToIEEEBV(fp_val)); + BoolExpr c2 = ctx.mkEq(x, ctx.mkBV(42, 64)); + BoolExpr c3 = ctx.mkEq(fp_val, ctx.mkFPToFP(rm, real_val, double_sort)); + BoolExpr c4 = ctx.mkAnd(c1, c2); + System.out.println("c3 = " + c3); + + /* Generic solver */ + Solver s = ctx.mkSolver(); + s.add(c3); + + if (s.check() != Status.SATISFIABLE) + throw new TestFailedException(); + + System.out.println("OK, model: " + s.getModel().toString()); + } + public static void main(String[] args) { JavaExample p = new JavaExample(); @@ -2200,6 +2280,8 @@ class JavaExample p.findSmallModelExample(ctx); p.simplifierExample(ctx); p.finiteDomainExample(ctx); + p.floatingPointExample1(ctx); + p.floatingPointExample2(ctx); } { // These examples need proof generation turned on. diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index d2d4e7155..87568af09 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -649,23 +649,21 @@ extern "C" { Z3_CATCH_RETURN(0); } - unsigned int Z3_API Z3_mk_fpa_get_ebits(Z3_context c, Z3_sort s) { + unsigned Z3_API Z3_fpa_get_ebits(Z3_context c, Z3_sort s) { Z3_TRY; - LOG_Z3_mk_fpa_get_ebits(c, s); + LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - unsigned r = ctx->float_util().get_ebits(to_sort(s)); - RETURN_Z3(r); + CHECK_NON_NULL(s, 0); + return mk_c(c)->float_util().get_ebits(to_sort(s)); Z3_CATCH_RETURN(0); } - unsigned Z3_API Z3_mk_fpa_get_sbits(Z3_context c, Z3_sort s) { + unsigned Z3_API Z3_fpa_get_sbits(Z3_context c, Z3_sort s) { Z3_TRY; - LOG_Z3_mk_fpa_get_sbits(c, s); + LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - unsigned r = ctx->float_util().get_sbits(to_sort(s)); - RETURN_Z3(r); + CHECK_NON_NULL(s, 0); + return mk_c(c)->float_util().get_sbits(to_sort(s)); Z3_CATCH_RETURN(0); } diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index f3e6220cf..609db802d 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3895,7 +3895,7 @@ namespace Microsoft.Z3 /// the closest integer, again represented as a floating-point number. /// /// term of RoundingMode sort - /// floating-point term + /// floating-point term public FPExpr MkFPRoundToIntegral(FPRMExpr rm, FPExpr t) { Contract.Ensures(Contract.Result() != null); diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 6a7241e98..233076516 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -1791,6 +1791,10 @@ public class Expr extends AST return new RatNum(ctx, obj); case Z3_BV_SORT: return new BitVecNum(ctx, obj); + case Z3_FLOATING_POINT_SORT: + return new FPNum(ctx, obj); + case Z3_FLOATING_POINT_ROUNDING_MODE_SORT: + return new FPRMNum(ctx, obj); default: ; } } @@ -1809,6 +1813,10 @@ public class Expr extends AST return new ArrayExpr(ctx, obj); case Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj); + case Z3_FLOATING_POINT_SORT: + return new FPExpr(ctx, obj); + case Z3_FLOATING_POINT_ROUNDING_MODE_SORT: + return new FPRMExpr(ctx, obj); default: ; } From 007ecb4ab29aa02b15569299db924ee4d8dca5c1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 4 Jan 2015 14:37:33 +0000 Subject: [PATCH 147/646] MPF bugfix Signed-off-by: Christoph M. Wintersteiger --- src/util/mpf.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index f5dcfc612..511bdb03c 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -196,13 +196,17 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode else { o.ebits = ebits; o.sbits = sbits; - o.sign = m_mpq_manager.is_neg(value); - + o.sign = m_mpq_manager.is_neg(value); + + scoped_mpq x(m_mpq_manager); + m_mpq_manager.set(x, value); + m_mpq_manager.abs(x); + m_mpz_manager.set(o.significand, 0); const mpz & p = m_powers2(sbits+3); scoped_mpq v(m_mpq_manager); - m_mpq_manager.set(v, value); + m_mpq_manager.set(v, x); o.exponent = 0; // Normalize From cf81f86c6741e09ed93abdf14ee7fe63fcbe0827 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 4 Jan 2015 18:52:23 +0000 Subject: [PATCH 148/646] build fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_replayer.cpp | 7 +++++++ src/ast/fpa/fpa2bv_converter.cpp | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/z3_replayer.cpp b/src/api/z3_replayer.cpp index 676ba0c69..cfd022124 100644 --- a/src/api/z3_replayer.cpp +++ b/src/api/z3_replayer.cpp @@ -225,6 +225,13 @@ struct z3_replayer::imp { return curr() == '-' || curr() == '.' || ('0' <= curr() && curr() <= '9') || curr() == 'e' || curr() == 'E'; } +#if (!defined(strtof)) + float strtof(const char * str, char ** end_ptr) { + // Note: This may introduce a double-rounding problem. + return (float)strtod(str, end_ptr); + } +#endif + void read_float() { m_string.reset(); while (is_double_char()) { diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index d51e34058..d6d1420e3 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -146,7 +146,6 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { app_ref bv(m); unsigned bv_sz = 1 + ebits + (sbits - 1); bv = mk_fresh_const(0, bv_sz); - m_fresh_bv_variables.insert(bv); sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv); e = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv); From 6d8587dff9ab55d4190607c118b1242303e72ef0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 4 Jan 2015 18:53:21 +0000 Subject: [PATCH 149/646] FPA fixes for internal func_decls Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index b019c7359..bdc0c6fb1 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -581,20 +581,21 @@ func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, p SASSERT(m_bv_plugin); if (arity != 2) m_manager->raise_exception("invalid number of arguments to fp.to_sbv"); - if (parameters[0].is_int()) - m_manager->raise_exception("invalid parameter type; fp.to_sbv expects an int parameter"); if (num_parameters != 1) m_manager->raise_exception("invalid number of parameters to fp.to_sbv"); - if (is_rm_sort(domain[0])) + if (!parameters[0].is_int()) + m_manager->raise_exception("invalid parameter type; fp.to_sbv expects an int parameter"); + if (!is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); if (parameters[0].get_int() <= 0) - m_manager->raise_exception("invalid parameter value; fp.to_ubv expects a parameter larger than 0"); + m_manager->raise_exception("invalid parameter value; fp.to_sbv expects a parameter larger than 0"); symbol name("fp.to_sbv"); sort * bvs = m_bv_plugin->mk_sort(BV_SORT, 1, parameters); return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters)); + } func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -674,11 +675,10 @@ func_decl * float_decl_plugin::mk_internal_to_sbv_unspecified( unsigned arity, sort * const * domain, sort * range) { if (arity != 0) m_manager->raise_exception("invalid number of arguments to internal_to_sbv_unspecified"); - if (!is_sort_of(domain[0], m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismatch, expected argument of bitvector sort"); - if (!is_sort_of(range, m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismatch, expected range of FloatingPoint sort"); - + if (num_parameters != 1) + m_manager->raise_exception("invalid number of parameters to fp.to_sbv_unspecified; expecting 1"); + if (!parameters[0].is_int()) + m_manager->raise_exception("invalid parameters type provided to fp.to_sbv_unspecified; expecting an integer"); sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, parameters); return m_manager->mk_func_decl(symbol("fp.to_sbv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); } From 5ff923f5043a275d1ca36231f240fe3c17d11603 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 4 Jan 2015 19:01:02 +0000 Subject: [PATCH 150/646] Added fp.to_sbv Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 238 +++++++++++++++++++++++-------- 1 file changed, 178 insertions(+), 60 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index d6d1420e3..24e606cdc 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1851,7 +1851,42 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args TRACE("fpa2bv_to_fp", for (unsigned i=0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl; ); - if (num == 3 && + if (num == 1 && + m_bv_util.is_bv(args[0])) { + sort * s = f->get_range(); + unsigned to_sbits = m_util.get_sbits(s); + unsigned to_ebits = m_util.get_ebits(s); + + expr * bv = args[0]; + int sz = m_bv_util.get_bv_size(bv); + SASSERT((unsigned)sz == to_sbits + to_ebits); + + mk_triple(m_bv_util.mk_extract(sz - 1, sz - 1, bv), + m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), + m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), + result); + } + else if (num == 2 && + m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && + m_util.is_float(m.get_sort(args[1]))) { + // float -> float conversion + mk_to_fp_float(f, f->get_range(), args[0], args[1], result); + } + else if (num == 2 && + m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && + m_arith_util.is_real(args[1])) { + // rm + real -> float + mk_to_fp_real(f, f->get_range(), args[0], args[1], result); + } + else if (num == 2 && + m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && + m_bv_util.is_bv(args[1])) { + mk_to_fp_signed(f, num, args, result); + } + else if (num == 3 && m_bv_util.is_bv(args[0]) && m_bv_util.is_bv(args[1]) && m_bv_util.is_bv(args[2])) { @@ -1860,13 +1895,6 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); mk_triple(args[0], args[2], args[1], result); } - else if (num == 2 && - m_bv_util.is_bv(args[0]) && - m_bv_util.get_bv_size(args[0]) == 3 && - m_bv_util.is_bv(args[1])) - { - mk_to_fp_signed(f, num, args, result); - } else if (num == 3 && m_bv_util.is_bv(args[0]) && m_arith_util.is_numeral(args[1]) && @@ -1921,34 +1949,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args mk_ite(c2, bv_tp, result, result); mk_ite(c3, bv_nta, result, result); mk_ite(c4, bv_nte, result, result); - } - else if (num == 1 && m_bv_util.is_bv(args[0])) { - sort * s = f->get_range(); - unsigned to_sbits = m_util.get_sbits(s); - unsigned to_ebits = m_util.get_ebits(s); - - expr * bv = args[0]; - int sz = m_bv_util.get_bv_size(bv); - SASSERT((unsigned)sz == to_sbits + to_ebits); - - mk_triple(m_bv_util.mk_extract(sz - 1, sz - 1, bv), - m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), - m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), - result); - } - else if (num == 2 && - m_util.is_rm(args[0]) && - is_app(args[1]) && - m_util.is_float(m.get_sort(args[1]))) { - // float -> float conversion - mk_to_fp_float(f, f->get_range(), args[0], args[1], result); } - else if (num == 2 && - m_util.is_rm(args[0]), - m_arith_util.is_real(args[1])) { - // rm + real -> float - mk_to_fp_real(f, f->get_range(), args[0], args[1], result); - } else UNREACHABLE(); @@ -2452,8 +2453,6 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg sort * xs = m.get_sort(x); sort * bv_srt = f->get_range(); - dbg_decouple("fpa2bv_to_ubv_x", expr_ref(x, m)); - unsigned ebits = m_util.get_ebits(xs); unsigned sbits = m_util.get_sbits(xs); unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); @@ -2470,7 +2469,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg mk_is_neg(x, x_is_neg); mk_is_nzero(x, x_is_nzero); - // NaN, Inf, or negative (except -0) -> undefined + // NaN, Inf, or negative (except -0) -> unspecified expr_ref c1(m), v1(m); c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero))); v1 = mk_to_ubv_unspecified(bv_sz); @@ -2513,7 +2512,7 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg dbg_decouple("fpa2bv_to_ubv_shift", shift); dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); - // sig is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long + // x is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long // [1][ ... sig ... ][r][g][ ... s ...] // [ ... ubv ... ][r][g][ ... s ... ] expr_ref max_shift(m); @@ -2546,18 +2545,17 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg dbg_decouple("fpa2bv_to_ubv_rounding_decision", rounding_decision); expr_ref unrounded_sig(m), pre_rounded(m), inc(m); - unrounded_sig = m_bv_util.mk_zero_extend(1, - m_bv_util.mk_extract(sig_sz - 1, sig_sz - bv_sz, shifted_sig)); - inc = m_bv_util.mk_zero_extend(1, - m_bv_util.mk_zero_extend(bv_sz - 1, rounding_decision)); + unrounded_sig = m_bv_util.mk_zero_extend(1, m_bv_util.mk_extract(sig_sz - 1, sig_sz - bv_sz, shifted_sig)); + inc = m_bv_util.mk_zero_extend(1, m_bv_util.mk_zero_extend(bv_sz - 1, rounding_decision)); pre_rounded = m_bv_util.mk_bv_add(unrounded_sig, inc); - expr_ref rnd_overflow(m), rounded(m), rnd_has_overflown(m); + expr_ref rnd_overflow(m), rnd(m), rnd_has_overflown(m); rnd_overflow = m_bv_util.mk_extract(bv_sz, bv_sz, pre_rounded); - rounded = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded); + rnd = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded); rnd_has_overflown = m.mk_eq(rnd_overflow, bv1); + dbg_decouple("fpa2bv_to_ubv_rnd_has_overflown", rnd_has_overflown); - result = m.mk_ite(rnd_has_overflown, mk_to_ubv_unspecified(bv_sz), rounded); + result = m.mk_ite(rnd_has_overflown, mk_to_ubv_unspecified(bv_sz), rnd); result = m.mk_ite(c_in_limits, result, mk_to_ubv_unspecified(bv_sz)); result = m.mk_ite(c2, v2, result); result = m.mk_ite(c1, v1, result); @@ -2568,24 +2566,138 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_sbv", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); - + SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); SASSERT(num == 2); SASSERT(m_bv_util.get_bv_size(args[0]) == 3); SASSERT(m_util.is_float(args[1])); - //unsigned ebits = m_util.get_ebits(f->get_range()); - //unsigned sbits = m_util.get_sbits(f->get_range()); - //int width = f->get_parameter(0).get_int(); + expr * rm = args[0]; + expr * x = args[1]; + sort * xs = m.get_sort(x); + sort * bv_srt = f->get_range(); - //expr * rm = args[0]; - //expr * x = args[1]; + unsigned ebits = m_util.get_ebits(xs); + unsigned sbits = m_util.get_sbits(xs); + unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); + unsigned rounding_sz = bv_sz + 3; - //expr * sgn, *s, *e; - //split_triple(x, sgn, s, e); + expr_ref bv0(m), bv1(m), bv0_2(m), bv1_2(m), bv3_2(m); + bv0 = m_bv_util.mk_numeral(0, 1); + bv1 = m_bv_util.mk_numeral(1, 1); + bv0_2 = m_bv_util.mk_numeral(0, 2); + bv1_2 = m_bv_util.mk_numeral(1, 2); + bv3_2 = m_bv_util.mk_numeral(3, 2); - NOT_IMPLEMENTED_YET(); + expr_ref x_is_nan(m), x_is_inf(m), x_is_zero(m), x_is_neg(m), x_is_nzero(m); + mk_is_nan(x, x_is_nan); + mk_is_inf(x, x_is_inf); + mk_is_zero(x, x_is_zero); + mk_is_neg(x, x_is_neg); + mk_is_nzero(x, x_is_nzero); + + // NaN, Inf -> unspecified + expr_ref c1(m), v1(m); + c1 = m.mk_or(x_is_nan, x_is_inf); + v1 = mk_to_sbv_unspecified(bv_sz); + dbg_decouple("fpa2bv_to_sbv_c1", c1); + + // +-Zero -> 0 + expr_ref c2(m), v2(m); + c2 = x_is_zero; + v2 = m_bv_util.mk_numeral(rational(0), bv_srt); + dbg_decouple("fpa2bv_to_sbv_c2", c2); + + // Otherwise... + expr_ref sgn(m), sig(m), exp(m), lz(m); + unpack(x, sgn, sig, exp, lz, true); + + // x is of the form +- [1].[sig] * 2^(exp-lz) + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(sig) == sbits); + SASSERT(m_bv_util.get_bv_size(exp) == ebits); + SASSERT(m_bv_util.get_bv_size(lz) == ebits); + dbg_decouple("fpa2bv_to_sbv_sig", sig); + unsigned sig_sz = m_bv_util.get_bv_size(sig); + SASSERT(sig_sz == sbits); + if (sig_sz < (bv_sz + 3)) + sig = m_bv_util.mk_concat(sig, m_bv_util.mk_numeral(0, bv_sz - sig_sz + 3)); + sig_sz = m_bv_util.get_bv_size(sig); + SASSERT(sig_sz >= (bv_sz + 3)); + + expr_ref exp_m_lz(m), shift(m), shift_neg(m), bv0_e2(m), shift_abs(m); + exp_m_lz = m_bv_util.mk_bv_sub(m_bv_util.mk_sign_extend(2, exp), + m_bv_util.mk_zero_extend(2, lz)); + shift = m_bv_util.mk_bv_sub(exp_m_lz, + m_bv_util.mk_numeral(bv_sz - 1, ebits + 2)); + shift_neg = m_bv_util.mk_bv_neg(shift); + bv0_e2 = m_bv_util.mk_numeral(0, ebits + 2); + shift_abs = m.mk_ite(m_bv_util.mk_sle(shift, bv0_e2), shift_neg, shift); + SASSERT(m_bv_util.get_bv_size(shift) == ebits + 2); + SASSERT(m_bv_util.get_bv_size(shift_neg) == ebits + 2); + SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits + 2); + dbg_decouple("fpa2bv_to_ubv_shift", shift); + dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); + + // sig is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long + // [1][ ... sig ... ][r][g][ ... s ...] + // [ ... ubv ... ][r][g][ ... s ... ] + expr_ref max_shift(m); + max_shift = m_bv_util.mk_numeral(sig_sz, sig_sz); + shift_abs = m_bv_util.mk_zero_extend(sig_sz - ebits - 2, shift_abs); + SASSERT(m_bv_util.get_bv_size(shift_abs) == sig_sz); + + expr_ref c_in_limits(m); + c_in_limits = m_bv_util.mk_sle(shift, m_bv_util.mk_numeral(0, ebits + 2)); + dbg_decouple("fpa2bv_to_sbv_in_limits", c_in_limits); + + expr_ref shifted_sig(m); + shifted_sig = m_bv_util.mk_bv_lshr(sig, shift_abs); + dbg_decouple("fpa2bv_to_sbv_shifted_sig", shifted_sig); + + expr_ref last(m), round(m), sticky(m); + last = m_bv_util.mk_extract(sig_sz - bv_sz - 0, sig_sz - bv_sz - 0, shifted_sig); + round = m_bv_util.mk_extract(sig_sz - bv_sz - 1, sig_sz - bv_sz - 1, shifted_sig); + sticky = m.mk_ite(m.mk_eq(m_bv_util.mk_extract(sig_sz - bv_sz - 2, 0, shifted_sig), + m_bv_util.mk_numeral(0, sig_sz - (bv_sz + 3) + 2)), + bv0, + bv1); + dbg_decouple("fpa2bv_to_sbv_last", last); + dbg_decouple("fpa2bv_to_sbv_round", round); + dbg_decouple("fpa2bv_to_sbv_sticky", sticky); + + expr_ref rounding_decision(m); + rounding_decision = mk_rounding_decision(rm, sgn, last, round, sticky); + SASSERT(m_bv_util.get_bv_size(rounding_decision) == 1); + dbg_decouple("fpa2bv_to_sbv_rounding_decision", rounding_decision); + + expr_ref unrounded_sig(m), pre_rounded(m), inc(m); + unrounded_sig = m_bv_util.mk_zero_extend(1, m_bv_util.mk_extract(sig_sz - 1, sig_sz - bv_sz, shifted_sig)); + inc = m_bv_util.mk_zero_extend(1, m_bv_util.mk_zero_extend(bv_sz - 1, rounding_decision)); + pre_rounded = m_bv_util.mk_bv_add(unrounded_sig, inc); + dbg_decouple("fpa2bv_to_sbv_inc", inc); + dbg_decouple("fpa2bv_to_sbv_unrounded_sig", unrounded_sig); + dbg_decouple("fpa2bv_to_sbv_pre_rounded", pre_rounded); + + expr_ref rnd_overflow(m), rnd_abs(m), rnd_signed(m), rnd_has_overflown(m), extra_neg(m); + rnd_overflow = m_bv_util.mk_extract(bv_sz, bv_sz - 1, pre_rounded); + rnd_abs = m_bv_util.mk_extract(bv_sz - 1, 0, pre_rounded); + rnd_signed = m.mk_ite(m.mk_eq(sgn, bv1), m_bv_util.mk_bv_neg(rnd_abs), rnd_abs); + extra_neg = m_bv_util.mk_numeral(fu().fm().m_powers2(bv_sz-1), bv_sz+1); + rnd_has_overflown = m.mk_and(m.mk_not(m.mk_eq(rnd_overflow, bv0_2)), + m.mk_not(m.mk_and(m.mk_eq(sgn, bv1), m.mk_eq(pre_rounded, extra_neg)))); + dbg_decouple("fpa2bv_to_sbv_extra_neg", extra_neg); + dbg_decouple("fpa2bv_to_sbv_rnd_overflow", rnd_overflow); + dbg_decouple("fpa2bv_to_sbv_rnd_abs", rnd_abs); + dbg_decouple("fpa2bv_to_sbv_rnd_has_overflown", rnd_has_overflown); + + result = m.mk_ite(rnd_has_overflown, mk_to_sbv_unspecified(bv_sz), rnd_signed); + result = m.mk_ite(c_in_limits, result, mk_to_sbv_unspecified(bv_sz)); + result = m.mk_ite(c2, v2, result); + result = m.mk_ite(c1, v1, result); + + SASSERT(is_well_sorted(m, result)); } void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -3030,7 +3142,7 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { #ifdef Z3DEBUG - return; + // return; // CMW: This works only for quantifier-free formulas. expr_ref new_e(m); new_e = m.mk_fresh_const(prefix, m.get_sort(e)); @@ -3040,22 +3152,28 @@ void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { } expr_ref fpa2bv_converter::mk_rounding_decision(expr * rm, expr * sgn, expr * last, expr * round, expr * sticky) { - expr_ref last_or_sticky(m), round_or_sticky(m), not_round(m), not_lors(m), not_rors(m), not_sgn(m); + expr_ref last_or_sticky(m), round_or_sticky(m), not_last(m), not_round(m), not_sticky(m), not_lors(m), not_rors(m), not_sgn(m); expr * last_sticky[2] = { last, sticky }; expr * round_sticky[2] = { round, sticky }; last_or_sticky = m_bv_util.mk_bv_or(2, last_sticky); round_or_sticky = m_bv_util.mk_bv_or(2, round_sticky); + not_last= m_bv_util.mk_bv_not(last); not_round = m_bv_util.mk_bv_not(round); + not_sticky = m_bv_util.mk_bv_not(sticky); not_lors = m_bv_util.mk_bv_not(last_or_sticky); not_rors = m_bv_util.mk_bv_not(round_or_sticky); not_sgn = m_bv_util.mk_bv_not(sgn); - expr * round_lors[2] = { not_round, not_lors }; + expr * nround_lors[2] = { not_round, not_lors }; expr * pos_args[2] = { sgn, not_rors }; expr * neg_args[2] = { not_sgn, not_rors }; + expr * nl_r[2] = { last, not_round }; + expr * nl_nr_sn[3] = { not_last, not_round, not_sticky }; expr_ref inc_teven(m), inc_taway(m), inc_pos(m), inc_neg(m); - inc_teven = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, round_lors)); - inc_taway = round; + inc_teven = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, nround_lors)); + expr *taway_args[2] = { m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, nl_r)), + m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(3, nl_nr_sn)) }; + inc_taway = m_bv_util.mk_bv_or(2, taway_args); inc_pos = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, pos_args)); inc_neg = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, neg_args)); From dd17f3c7d6802e5649a22d2ae7f93f2cf368d416 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 13:18:56 +0000 Subject: [PATCH 151/646] Renaming floats, float, Floats, Float -> FPA, fpa Signed-off-by: Christoph M. Wintersteiger --- src/api/api_ast.cpp | 62 ++- src/api/api_context.cpp | 2 +- src/api/api_context.h | 2 +- src/api/api_fpa.cpp | 2 +- src/api/api_numeral.cpp | 2 +- src/api/dotnet/Expr.cs | 4 +- src/api/z3_api.h | 53 +- src/ast/ast_smt2_pp.h | 2 +- src/ast/fpa/fpa2bv_converter.cpp | 373 ++++++++------ src/ast/fpa/fpa2bv_converter.h | 15 +- src/ast/fpa/fpa2bv_rewriter.h | 98 ++-- ...at_decl_plugin.cpp => fpa_decl_plugin.cpp} | 460 +++++++++--------- ...{float_decl_plugin.h => fpa_decl_plugin.h} | 216 ++++---- src/ast/reg_decl_plugins.cpp | 6 +- .../{float_rewriter.cpp => fpa_rewriter.cpp} | 154 +++--- .../{float_rewriter.h => fpa_rewriter.h} | 8 +- src/ast/rewriter/mk_simplified_app.cpp | 4 +- src/ast/rewriter/th_rewriter.cpp | 4 +- src/cmd_context/cmd_context.cpp | 8 +- src/cmd_context/cmd_context.h | 2 +- src/model/model_evaluator.cpp | 4 +- src/smt/theory_fpa.cpp | 27 +- src/tactic/fpa/fpa2bv_model_converter.cpp | 2 +- src/tactic/fpa/qffpa_tactic.cpp | 32 +- src/tactic/fpa/qffpa_tactic.h | 4 +- 25 files changed, 859 insertions(+), 687 deletions(-) rename src/ast/{float_decl_plugin.cpp => fpa_decl_plugin.cpp} (71%) rename src/ast/{float_decl_plugin.h => fpa_decl_plugin.h} (77%) rename src/ast/rewriter/{float_rewriter.cpp => fpa_rewriter.cpp} (69%) rename src/ast/rewriter/{float_rewriter.h => fpa_rewriter.h} (95%) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 67358726c..c6b413dd4 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -648,11 +648,11 @@ extern "C" { else if (fid == mk_c(c)->get_datalog_fid() && k == datalog::DL_FINITE_SORT) { return Z3_FINITE_DOMAIN_SORT; } - else if (fid == mk_c(c)->get_fpa_fid() && k == FLOAT_SORT) { + else if (fid == mk_c(c)->get_fpa_fid() && k == FLOATING_POINT_SORT) { return Z3_FLOATING_POINT_SORT; } else if (fid == mk_c(c)->get_fpa_fid() && k == ROUNDING_MODE_SORT) { - return Z3_FLOATING_POINT_ROUNDING_MODE_SORT; + return Z3_ROUNDING_MODE_SORT; } else { return Z3_UNKNOWN_SORT; @@ -1119,6 +1119,64 @@ extern "C" { return Z3_OP_UNINTERPRETED; } } + + if (mk_c(c)->get_fpa_fid() == _d->get_family_id()) { + switch (_d->get_decl_kind()) { + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: return Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: return Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; + case OP_FPA_RM_TOWARD_POSITIVE: return Z3_OP_FPA_RM_TOWARD_POSITIVE; + case OP_FPA_RM_TOWARD_NEGATIVE: return Z3_OP_FPA_RM_TOWARD_NEGATIVE; + case OP_FPA_RM_TOWARD_ZERO: return Z3_OP_FPA_RM_TOWARD_ZERO; + case OP_FPA_VALUE: return Z3_OP_FPA_VALUE; + case OP_FPA_PLUS_INF: return Z3_OP_FPA_PLUS_INF; + case OP_FPA_MINUS_INF: return Z3_OP_FPA_MINUS_INF; + case OP_FPA_NAN: return Z3_OP_FPA_NAN; + case OP_FPA_MINUS_ZERO: return Z3_OP_FPA_MINUS_ZERO; + case OP_FPA_PLUS_ZERO: return Z3_OP_FPA_PLUS_ZERO; + case OP_FPA_ADD: return Z3_OP_FPA_ADD; + case OP_FPA_SUB: return Z3_OP_FPA_SUB; + case OP_FPA_NEG: return Z3_OP_FPA_NEG; + case OP_FPA_MUL: return Z3_OP_FPA_MUL; + case OP_FPA_DIV: return Z3_OP_FPA_DIV; + case OP_FPA_REM: return Z3_OP_FPA_REM; + case OP_FPA_ABS: return Z3_OP_FPA_ABS; + case OP_FPA_MIN: return Z3_OP_FPA_MIN; + case OP_FPA_MAX: return Z3_OP_FPA_MAX; + case OP_FPA_FMA: return Z3_OP_FPA_FMA; + case OP_FPA_SQRT: return Z3_OP_FPA_SQRT; + case OP_FPA_EQ: return Z3_OP_FPA_EQ; + case OP_FPA_ROUND_TO_INTEGRAL: return Z3_OP_FPA_ROUND_TO_INTEGRAL; + case OP_FPA_LT: return Z3_OP_FPA_LT; + case OP_FPA_GT: return Z3_OP_FPA_GT; + case OP_FPA_LE: return Z3_OP_FPA_LE; + case OP_FPA_GE: return Z3_OP_FPA_GE; + case OP_FPA_IS_NAN: return Z3_OP_FPA_IS_NAN; + case OP_FPA_IS_INF: return Z3_OP_FPA_IS_INF; + case OP_FPA_IS_ZERO: return Z3_OP_FPA_IS_ZERO; + case OP_FPA_IS_NORMAL: return Z3_OP_FPA_IS_NORMAL; + case OP_FPA_IS_SUBNORMAL: return Z3_OP_FPA_IS_SUBNORMAL; + case OP_FPA_IS_PZERO: return Z3_OP_FPA_IS_PZERO; + case OP_FPA_IS_NZERO: return Z3_OP_FPA_IS_NZERO; + case OP_FPA_IS_NEGATIVE: return Z3_OP_FPA_IS_NEGATIVE; + case OP_FPA_IS_POSITIVE: return Z3_OP_FPA_IS_POSITIVE; + case OP_FPA_FP: return Z3_OP_FPA_FP; + case OP_FPA_TO_FP: return Z3_OP_FPA_TO_FP; + case OP_FPA_TO_FP_UNSIGNED: return Z3_OP_FPA_TO_FP_UNSIGNED; + case OP_FPA_TO_UBV: return Z3_OP_FPA_TO_UBV; + case OP_FPA_TO_SBV: return Z3_OP_FPA_TO_SBV; + case OP_FPA_TO_REAL: return Z3_OP_FPA_TO_REAL; + case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV; + case OP_FPA_INTERNAL_BVWRAP: + case OP_FPA_INTERNAL_BVUNWRAP: + case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: + return Z3_OP_UNINTERPRETED; + default: + UNREACHABLE(); + return Z3_OP_UNINTERPRETED; + } + } if (mk_c(c)->m().get_label_family_id() == _d->get_family_id()) { switch(_d->get_decl_kind()) { diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 5d11e5bce..b83b72e35 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -113,7 +113,7 @@ namespace api { m_array_fid = m().mk_family_id("array"); m_dt_fid = m().mk_family_id("datatype"); m_datalog_fid = m().mk_family_id("datalog_relation"); - m_fpa_fid = m().mk_family_id("float"); + m_fpa_fid = m().mk_family_id("fpa"); m_dt_plugin = static_cast(m().get_plugin(m_dt_fid)); if (!m_user_ref_count) { diff --git a/src/api/api_context.h b/src/api/api_context.h index f409a4ece..c71b88b61 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -27,7 +27,7 @@ Revision History: #include"bv_decl_plugin.h" #include"datatype_decl_plugin.h" #include"dl_decl_plugin.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"smt_kernel.h" #include"smt_params.h" #include"event_handler.h" diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 87568af09..0f0f68ae1 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -20,7 +20,7 @@ Notes: #include"z3.h" #include"api_log_macros.h" #include"api_context.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" extern "C" { diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index d2829e990..17a743880 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -23,7 +23,7 @@ Revision History: #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" #include"algebraic_numbers.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" bool is_numeral_sort(Z3_context c, Z3_sort ty) { sort * _ty = to_sort(ty); diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index ec8beeac0..826860eec 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1543,7 +1543,7 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_REAL_SORT: return new RatNum(ctx, obj); case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj); case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); - case Z3_sort_kind.Z3_FLOATING_POINT_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj); + case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj); } } @@ -1556,7 +1556,7 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_ARRAY_SORT: return new ArrayExpr(ctx, obj); case Z3_sort_kind.Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj); case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPExpr(ctx, obj); - case Z3_sort_kind.Z3_FLOATING_POINT_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); + case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); } return new Expr(ctx, obj); diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 776e4e9fe..3c3a5d1c2 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -195,7 +195,7 @@ typedef enum Z3_RELATION_SORT, Z3_FINITE_DOMAIN_SORT, Z3_FLOATING_POINT_SORT, - Z3_FLOATING_POINT_ROUNDING_MODE_SORT, + Z3_ROUNDING_MODE_SORT, Z3_UNKNOWN_SORT = 1000 } Z3_sort_kind; @@ -1058,6 +1058,57 @@ typedef enum { Z3_OP_DT_RECOGNISER, Z3_OP_DT_ACCESSOR, + // Floating-Point Arithmetic + Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN, + Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY, + Z3_OP_FPA_RM_TOWARD_POSITIVE, + Z3_OP_FPA_RM_TOWARD_NEGATIVE, + Z3_OP_FPA_RM_TOWARD_ZERO, + + Z3_OP_FPA_VALUE, + Z3_OP_FPA_PLUS_INF, + Z3_OP_FPA_MINUS_INF, + Z3_OP_FPA_NAN, + Z3_OP_FPA_PLUS_ZERO, + Z3_OP_FPA_MINUS_ZERO, + + Z3_OP_FPA_ADD, + Z3_OP_FPA_SUB, + Z3_OP_FPA_NEG, + Z3_OP_FPA_MUL, + Z3_OP_FPA_DIV, + Z3_OP_FPA_REM, + Z3_OP_FPA_ABS, + Z3_OP_FPA_MIN, + Z3_OP_FPA_MAX, + Z3_OP_FPA_FMA, + Z3_OP_FPA_SQRT, + Z3_OP_FPA_ROUND_TO_INTEGRAL, + + Z3_OP_FPA_EQ, + Z3_OP_FPA_LT, + Z3_OP_FPA_GT, + Z3_OP_FPA_LE, + Z3_OP_FPA_GE, + Z3_OP_FPA_IS_NAN, + Z3_OP_FPA_IS_INF, + Z3_OP_FPA_IS_ZERO, + Z3_OP_FPA_IS_NORMAL, + Z3_OP_FPA_IS_SUBNORMAL, + Z3_OP_FPA_IS_PZERO, + Z3_OP_FPA_IS_NZERO, + Z3_OP_FPA_IS_NEGATIVE, + Z3_OP_FPA_IS_POSITIVE, + + Z3_OP_FPA_FP, + Z3_OP_FPA_TO_FP, + Z3_OP_FPA_TO_FP_UNSIGNED, + Z3_OP_FPA_TO_UBV, + Z3_OP_FPA_TO_SBV, + Z3_OP_FPA_TO_REAL, + + Z3_OP_FPA_TO_IEEE_BV, + Z3_OP_UNINTERPRETED } Z3_decl_kind; diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index 37d13e57a..bc62448c7 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -27,7 +27,7 @@ Revision History: #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" #include"array_decl_plugin.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"dl_decl_plugin.h" #include"smt2_util.h" diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 24e606cdc..dc1a255e8 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -16,8 +16,10 @@ Author: Notes: --*/ +#include #include"ast_smt2_pp.h" #include"well_sorted.h" +#include"th_rewriter.h" #include"fpa2bv_converter.h" @@ -34,7 +36,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : m_mpz_manager(m_mpf_manager.mpz_manager()), m_hi_fp_unspecified(true), m_extra_assertions(m) { - m_plugin = static_cast(m.get_plugin(m.mk_family_id("float"))); + m_plugin = static_cast(m.get_plugin(m.mk_family_id("fpa"))); } fpa2bv_converter::~fpa2bv_converter() { @@ -42,8 +44,8 @@ fpa2bv_converter::~fpa2bv_converter() { } void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { - SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); - SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_FPA_TO_FP)); expr_ref sgn(m), s(m), e(m); m_simp.mk_eq(to_app(a)->get_arg(0), to_app(b)->get_arg(0), sgn); @@ -62,8 +64,8 @@ void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { } void fpa2bv_converter::mk_ite(expr * c, expr * t, expr * f, expr_ref & result) { - SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); - SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FPA_TO_FP)); expr *t_sgn, *t_sig, *t_exp; expr *f_sgn, *f_sig, *f_exp; @@ -1881,15 +1883,15 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args mk_to_fp_real(f, f->get_range(), args[0], args[1], result); } else if (num == 2 && - m_bv_util.is_bv(args[0]) && - m_bv_util.get_bv_size(args[0]) == 3 && - m_bv_util.is_bv(args[1])) { - mk_to_fp_signed(f, num, args, result); + m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && + m_bv_util.is_bv(args[1])) { + mk_to_fp_signed(f, num, args, result); } else if (num == 3 && - m_bv_util.is_bv(args[0]) && - m_bv_util.is_bv(args[1]) && - m_bv_util.is_bv(args[2])) { + m_bv_util.is_bv(args[0]) && + m_bv_util.is_bv(args[1]) && + m_bv_util.is_bv(args[2])) { SASSERT(m_bv_util.get_bv_size(args[0]) == 1); SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); @@ -1900,55 +1902,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args m_arith_util.is_numeral(args[1]) && m_arith_util.is_numeral(args[2])) { - // rm + real + int -> float - SASSERT(m_util.is_float(f->get_range())); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - - expr * rm = args[0]; - - rational q; - if (!m_arith_util.is_numeral(args[1], q)) - UNREACHABLE(); - - rational e; - if (!m_arith_util.is_numeral(args[2], e)) - UNREACHABLE(); - - SASSERT(e.is_int64()); - SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1)); - - scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager); - m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator()); - - app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); - a_nte = m_plugin->mk_value(nte); - a_nta = m_plugin->mk_value(nta); - a_tp = m_plugin->mk_value(tp); - a_tn = m_plugin->mk_value(tn); - a_tz = m_plugin->mk_value(tz); - - expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); - mk_value(a_nte->get_decl(), 0, 0, bv_nte); - mk_value(a_nta->get_decl(), 0, 0, bv_nta); - mk_value(a_tp->get_decl(), 0, 0, bv_tp); - mk_value(a_tn->get_decl(), 0, 0, bv_tn); - mk_value(a_tz->get_decl(), 0, 0, bv_tz); - - expr_ref c1(m), c2(m), c3(m), c4(m); - c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); - c2 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); - c3 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)); - c4 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)); - - mk_ite(c1, bv_tn, bv_tz, result); - mk_ite(c2, bv_tp, result, result); - mk_ite(c3, bv_nta, result, result); - mk_ite(c4, bv_nte, result, result); + mk_to_fp_real_int(f, num, args, result); } else UNREACHABLE(); @@ -2104,11 +2058,13 @@ void fpa2bv_converter::mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * } void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) { + TRACE("fpa2bv_to_fp_real", tout << "rm: " << mk_ismt2_pp(rm, m) << std::endl << + "x: " << mk_ismt2_pp(x, m) << std::endl;); SASSERT(m_util.is_float(s)); unsigned ebits = m_util.get_ebits(s); unsigned sbits = m_util.get_sbits(s); - if (m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) { + if (false && m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) { rational tmp_rat; unsigned sz; m_bv_util.is_numeral(to_expr(rm), tmp_rat, sz); SASSERT(tmp_rat.is_int32()); @@ -2140,19 +2096,201 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * mk_triple(sgn, s, e, result); } else { - NOT_IMPLEMENTED_YET(); + mpf_manager & fm = fu().fm(); + bv_util & bu = m_bv_util; + arith_util & au = m_arith_util; + + expr_ref bv0(m), bv1(m), zero(m), two(m); + bv0 = bu.mk_numeral(0, 1); + bv1 = bu.mk_numeral(1, 1); + zero = au.mk_numeral(rational(0), false); + two = au.mk_numeral(rational(2), false); + + expr_ref sgn(m), sig(m), exp(m); + sgn = m.mk_ite(au.mk_lt(x, zero), bv1, bv0); + sig = bu.mk_numeral(0, sbits + 4); + mpz const & max_normal_exponent = fm.m_powers2.m1(ebits-1); + exp = bu.mk_numeral(max_normal_exponent, ebits); + + //expr_ref cur_s(m), cur_d(m), cur_r(m), cur_s2(m), bv1_s4(m); + //bv1_s4 = bu.mk_numeral(1, sbits + 4); + //cur_s = x; + //std::string trace_name; + //for (unsigned i = 0; i < sbits + 3; i++) { + // std::stringstream dbg_name; + // dbg_name << "fpa2bv_to_float_real_sig_" << i; + // dbg_decouple(dbg_name.str().c_str(), sig); + + // cur_s = au.mk_div(cur_s, two); + // // cur_r = au.mk_rem(cur_s, two); + // cur_r = au.mk_mod(cur_s, two); + // cur_s2 = bu.mk_bv_shl(sig, bv1_s4); + // sig = m.mk_ite(au.mk_eq(cur_r, zero), + // cur_s2, + // bu.mk_bv_add(cur_s2, bv1_s4)); + //} + //dbg_decouple("fpa2bv_to_float_real_last_cur_s", cur_s); + //expr_ref inc(m); + //inc = m.mk_not(m.mk_eq(cur_s, zero)); + //dbg_decouple("fpa2bv_to_float_real_inc", inc); + //sig = m.mk_ite(inc, bu.mk_bv_add(sig, bv1_s4), sig); + + SASSERT(bu.get_bv_size(sgn) == 1); + SASSERT(bu.get_bv_size(sig) == sbits + 4); + SASSERT(bu.get_bv_size(exp) == ebits + 2); + + dbg_decouple("fpa2bv_to_float_real_sgn", sgn); + dbg_decouple("fpa2bv_to_float_real_sig", sig); + dbg_decouple("fpa2bv_to_float_real_exp", exp); + + expr_ref rmr(rm, m); + round(s, rmr, sgn, sig, exp, result); } SASSERT(is_well_sorted(m, result)); } +void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + // rm + real + int -> float + SASSERT(m_util.is_float(f->get_range())); + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + + expr * rm = args[0]; + + rational q; + if (!m_arith_util.is_numeral(args[1], q)) + UNREACHABLE(); + + rational e; + if (!m_arith_util.is_numeral(args[2], e)) + UNREACHABLE(); + + SASSERT(e.is_int64()); + SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1)); + + scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager); + m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator()); + + app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); + a_nte = m_plugin->mk_value(nte); + a_nta = m_plugin->mk_value(nta); + a_tp = m_plugin->mk_value(tp); + a_tn = m_plugin->mk_value(tn); + a_tz = m_plugin->mk_value(tz); + + expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); + mk_value(a_nte->get_decl(), 0, 0, bv_nte); + mk_value(a_nta->get_decl(), 0, 0, bv_nta); + mk_value(a_tp->get_decl(), 0, 0, bv_tp); + mk_value(a_tn->get_decl(), 0, 0, bv_tn); + mk_value(a_tz->get_decl(), 0, 0, bv_tz); + + expr_ref c1(m), c2(m), c3(m), c4(m); + c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c2 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c3 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)); + c4 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)); + + mk_ite(c1, bv_tn, bv_tz, result); + mk_ite(c2, bv_tp, result, result); + mk_ite(c3, bv_nta, result, result); + mk_ite(c4, bv_nte, result, result); +} +void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + TRACE("fpa2bv_to_real", for (unsigned i = 0; i < num; i++) + tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); + SASSERT(num == 1); + SASSERT(f->get_num_parameters() == 0); + SASSERT(is_app_of(args[0], m_plugin->get_family_id(), OP_FPA_TO_FP)); + + expr * x = args[0]; + sort * s = m.get_sort(x); + unsigned ebits = m_util.get_ebits(s); + unsigned sbits = m_util.get_sbits(s); + + sort * rs = m_arith_util.mk_real(); + expr_ref x_is_nan(m), x_is_inf(m), x_is_zero(m); + mk_is_nan(x, x_is_nan); + mk_is_inf(x, x_is_inf); + mk_is_zero(x, x_is_zero); + + expr_ref sgn(m), sig(m), exp(m), lz(m); + unpack(x, sgn, sig, exp, lz, true); + // sig is of the form [1].[sigbits] + + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(sig) == sbits); + SASSERT(m_bv_util.get_bv_size(exp) == ebits); + + expr_ref rsig(m), bit(m), zero(m), one(m), two(m), bv0(m), bv1(m); + zero = m_arith_util.mk_numeral(rational(0), rs); + one = m_arith_util.mk_numeral(rational(1), rs); + two = m_arith_util.mk_numeral(rational(2), rs); + bv0 = m_bv_util.mk_numeral(0, 1); + bv1 = m_bv_util.mk_numeral(1, 1); + rsig = one; + for (unsigned i = sbits - 2; i != (unsigned)-1; i--) { + bit = m_bv_util.mk_extract(i, i, sig); + rsig = m_arith_util.mk_add(m_arith_util.mk_mul(rsig, two), + m.mk_ite(m.mk_eq(bit, bv1), one, zero)); + } + + const mpz & p2 = fu().fm().m_powers2(sbits - 1); + expr_ref ep2(m); + ep2 = m_arith_util.mk_numeral(rational(p2), false); + rsig = m_arith_util.mk_div(rsig, ep2); + dbg_decouple("fpa2bv_to_real_ep2", ep2); + dbg_decouple("fpa2bv_to_real_rsig", rsig); + + expr_ref exp_n(m), exp_p(m), exp_is_neg(m), exp_abs(m); + exp_is_neg = m.mk_eq(m_bv_util.mk_extract(ebits - 1, ebits - 1, exp), bv1); + dbg_decouple("fpa2bv_to_real_exp_is_neg", exp_is_neg); + exp_p = m_bv_util.mk_sign_extend(1, exp); + exp_n = m_bv_util.mk_bv_neg(exp_p); + exp_abs = m.mk_ite(exp_is_neg, exp_n, exp_p); + dbg_decouple("fpa2bv_to_real_exp_abs", exp); + SASSERT(m_bv_util.get_bv_size(exp_abs) == ebits + 1); + + expr_ref exp2(m), prev_bit(m); + exp2 = zero; + for (unsigned i = ebits; i != (unsigned)-1; i--) { + bit = m_bv_util.mk_extract(i, i, exp_abs); + exp2 = m_arith_util.mk_add(m_arith_util.mk_mul(exp2, two), + m.mk_ite(m.mk_eq(bit, bv1), one, zero)); + prev_bit = bit; + } + + exp2 = m.mk_ite(exp_is_neg, m_arith_util.mk_div(one, exp2), exp2); + dbg_decouple("fpa2bv_to_real_exp2", exp2); + + expr_ref res(m), two_exp2(m); + two_exp2 = m_arith_util.mk_power(two, exp2); + res = m_arith_util.mk_mul(rsig, two_exp2); + res = m.mk_ite(m.mk_eq(sgn, bv1), m_arith_util.mk_uminus(res), res); + dbg_decouple("fpa2bv_to_real_sig_times_exp2", res); + + TRACE("fpa2bv_to_real", tout << "rsig = " << mk_ismt2_pp(rsig, m) << std::endl; + tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;); + + result = m.mk_ite(x_is_zero, zero, res); + result = m.mk_ite(x_is_inf, mk_to_real_unspecified(), result); + result = m.mk_ite(x_is_nan, mk_to_real_unspecified(), result); + + SASSERT(is_well_sorted(m, result)); +} + void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_fp_signed", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); // This is a conversion from signed bitvector to float: // ; from signed machine integer, represented as a 2's complement bit vector - // ((_ to_fp eb sb) RoundingMode(_ BitVec m) (_ FloatingPoint eb sb)) + // ((_ to_fp eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb)) // Semantics: // Let b in[[(_ BitVec m)]] and let n be the signed integer represented by b (in 2's complement format). // [[(_ to_fp eb sb)]](r, b) = +/ -infinity if n is too large / too small to be represented as a finite @@ -2293,7 +2431,7 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); // This is a conversion from unsigned bitvector to float: - // ((_ to_fp_unsigned eb sb) RoundingMode(_ BitVec m) (_ FloatingPoint eb sb)) + // ((_ to_fp_unsigned eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb)) // Semantics: // Let b in[[(_ BitVec m)]] and let n be the unsigned integer represented by b. // [[(_ to_fp_unsigned eb sb)]](r, x) = +infinity if n is too large to be @@ -2700,91 +2838,6 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg SASSERT(is_well_sorted(m, result)); } -void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - TRACE("fpa2bv_to_real", for (unsigned i = 0; i < num; i++) - tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); - SASSERT(num == 1); - SASSERT(f->get_num_parameters() == 0); - SASSERT(is_app_of(args[0], m_plugin->get_family_id(), OP_FLOAT_TO_FP)); - - expr * x = args[0]; - sort * s = m.get_sort(x); - unsigned ebits = m_util.get_ebits(s); - unsigned sbits = m_util.get_sbits(s); - - sort * rs = m_arith_util.mk_real(); - expr_ref x_is_nan(m), x_is_inf(m), x_is_zero(m); - mk_is_nan(x, x_is_nan); - mk_is_inf(x, x_is_inf); - mk_is_zero(x, x_is_zero); - - expr_ref sgn(m), sig(m), exp(m), lz(m); - unpack(x, sgn, sig, exp, lz, true); - // sig is of the form [1].[sigbits] - - SASSERT(m_bv_util.get_bv_size(sgn) == 1); - SASSERT(m_bv_util.get_bv_size(sig) == sbits); - SASSERT(m_bv_util.get_bv_size(exp) == ebits); - - expr_ref rsig(m), bit(m), zero(m), one(m), two(m), bv0(m), bv1(m); - zero = m_arith_util.mk_numeral(rational(0), rs); - one = m_arith_util.mk_numeral(rational(1), rs); - two = m_arith_util.mk_numeral(rational(2), rs); - bv0 = m_bv_util.mk_numeral(0, 1); - bv1 = m_bv_util.mk_numeral(1, 1); - rsig = one; - for (unsigned i = sbits-2; i != (unsigned)-1; i--) - { - bit = m_bv_util.mk_extract(i, i, sig); - rsig = m_arith_util.mk_add(m_arith_util.mk_mul(rsig, two), - m.mk_ite(m.mk_eq(bit, bv1), one, zero)); - } - - const mpz & p2 = fu().fm().m_powers2(sbits-1); - expr_ref ep2(m); - ep2 = m_arith_util.mk_numeral(rational(p2), false); - rsig = m_arith_util.mk_div(rsig, ep2); - dbg_decouple("fpa2bv_to_real_ep2", ep2); - dbg_decouple("fpa2bv_to_real_rsig", rsig); - - expr_ref exp_n(m), exp_p(m), exp_is_neg(m), exp_abs(m); - exp_is_neg = m.mk_eq(m_bv_util.mk_extract(ebits - 1, ebits - 1, exp), bv1); - dbg_decouple("fpa2bv_to_real_exp_is_neg", exp_is_neg); - exp_p = m_bv_util.mk_sign_extend(1, exp); - exp_n = m_bv_util.mk_bv_neg(exp_p); - exp_abs = m.mk_ite(exp_is_neg, exp_n, exp_p); - dbg_decouple("fpa2bv_to_real_exp_abs", exp); - SASSERT(m_bv_util.get_bv_size(exp_abs) == ebits + 1); - - expr_ref exp2(m), prev_bit(m); - exp2 = zero; - for (unsigned i = ebits; i != (unsigned)-1; i--) - { - bit = m_bv_util.mk_extract(i, i, exp_abs); - exp2 = m_arith_util.mk_add(m_arith_util.mk_mul(exp2, two), - m.mk_ite(m.mk_eq(bit, bv1), one, zero)); - prev_bit = bit; - } - - exp2 = m.mk_ite(exp_is_neg, m_arith_util.mk_div(one, exp2), exp2); - dbg_decouple("fpa2bv_to_real_exp2", exp2); - - expr_ref res(m), two_exp2(m); - two_exp2 = m_arith_util.mk_power(two, exp2); - res = m_arith_util.mk_mul(rsig, two_exp2); - res = m.mk_ite(m.mk_eq(sgn, bv1), m_arith_util.mk_uminus(res), res); - dbg_decouple("fpa2bv_to_real_sig_times_exp2", res); - - TRACE("fpa2bv_to_real", tout << "rsig = " << mk_ismt2_pp(rsig, m) << std::endl; - tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;); - - result = m.mk_ite(x_is_zero, zero, res); - result = m.mk_ite(x_is_inf, mk_to_real_unspecified(), result); - result = m.mk_ite(x_is_nan, mk_to_real_unspecified(), result); - - SASSERT(is_well_sorted(m, result)); -} - expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned width) { if (m_hi_fp_unspecified) return expr_ref(m_bv_util.mk_numeral(0, width), m); @@ -2807,7 +2860,7 @@ expr_ref fpa2bv_converter::mk_to_real_unspecified() { } void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sgn = to_app(e)->get_arg(0); @@ -2816,7 +2869,7 @@ void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * } void fpa2bv_converter::split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr *e_sgn, *e_sig, *e_exp; split_triple(e, e_sgn, e_sig, e_exp); @@ -2866,7 +2919,7 @@ void fpa2bv_converter::mk_is_ninf(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref zero(m); @@ -2875,7 +2928,7 @@ void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_neg(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref one(m); @@ -3038,7 +3091,7 @@ void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) { } void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); SASSERT(to_app(e)->get_num_args() == 3); sort * srt = to_app(e)->get_decl()->get_range(); @@ -3131,11 +3184,11 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) { switch(f->get_decl_kind()) { - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3); break; - case OP_FLOAT_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; - case OP_FLOAT_RM_TOWARD_POSITIVE: result = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); break; - case OP_FLOAT_RM_TOWARD_ZERO: result = m_bv_util.mk_numeral(BV_RM_TO_ZERO, 3); break; + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3); break; + case OP_FPA_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; + case OP_FPA_RM_TOWARD_POSITIVE: result = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); break; + case OP_FPA_RM_TOWARD_ZERO: result = m_bv_util.mk_numeral(BV_RM_TO_ZERO, 3); break; default: UNREACHABLE(); } } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 6a7b6e92f..f81edb653 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -22,7 +22,7 @@ Notes: #include"ast.h" #include"obj_hashtable.h" #include"ref_util.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"bv_decl_plugin.h" #include"basic_simplifier_plugin.h" @@ -50,7 +50,7 @@ protected: arith_util m_arith_util; mpf_manager & m_mpf_manager; unsynch_mpz_manager & m_mpz_manager; - float_decl_plugin * m_plugin; + fpa_decl_plugin * m_plugin; bool m_hi_fp_unspecified; obj_map m_const2bv; @@ -76,7 +76,7 @@ public: SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); SASSERT(m_bv_util.is_bv(significand)); SASSERT(m_bv_util.is_bv(exponent)); - result = m.mk_app(m_util.get_family_id(), OP_FLOAT_TO_FP, sign, exponent, significand); + result = m.mk_app(m_util.get_family_id(), OP_FPA_TO_FP, sign, exponent, significand); } void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const; @@ -130,15 +130,16 @@ public: void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); - void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); + void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); void mk_to_fp_signed(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - + void mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); + void mk_to_fp_real_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; } expr_ref mk_to_ubv_unspecified(unsigned width); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 797f681e7..cbbd9e8a7 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -115,55 +115,55 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { if (m_conv.is_float_family(f)) { switch (f->get_decl_kind()) { - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: - case OP_FLOAT_RM_TOWARD_NEGATIVE: - case OP_FLOAT_RM_TOWARD_POSITIVE: - case OP_FLOAT_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; - case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; - case OP_FLOAT_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE; - case OP_FLOAT_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE; - case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; - case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE; - case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE; - case OP_FLOAT_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE; - case OP_FLOAT_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE; - case OP_FLOAT_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE; - case OP_FLOAT_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE; - case OP_FLOAT_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE; - case OP_FLOAT_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE; - case OP_FLOAT_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE; - case OP_FLOAT_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE; - case OP_FLOAT_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE; - case OP_FLOAT_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE; - case OP_FLOAT_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE; - case OP_FLOAT_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE; - case OP_FLOAT_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE; - case OP_FLOAT_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE; - case OP_FLOAT_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE; - case OP_FLOAT_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE; - case OP_FLOAT_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; - case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; - case OP_FLOAT_INTERNAL_BVWRAP: - case OP_FLOAT_INTERNAL_BVUNWRAP: - case OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED: - case OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED: - case OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED; + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; + case OP_FPA_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; + case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE; + case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE; + case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; + case OP_FPA_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE; + case OP_FPA_NAN: m_conv.mk_nan(f, result); return BR_DONE; + case OP_FPA_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE; + case OP_FPA_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE; + case OP_FPA_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE; + case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE; + case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE; + case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE; + case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE; + case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE; + case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE; + case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE; + case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE; + case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE; + case OP_FPA_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE; + case OP_FPA_LT: m_conv.mk_float_lt(f, num, args, result); return BR_DONE; + case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE; + case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE; + case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE; + case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE; + case OP_FPA_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE; + case OP_FPA_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE; + case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE; + case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; + case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; + case OP_FPA_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; + case OP_FPA_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; + case OP_FPA_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; + case OP_FPA_TO_FP: m_conv.mk_to_fp(f, num, args, result); return BR_DONE; + case OP_FPA_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; + case OP_FPA_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; + case OP_FPA_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; + case OP_FPA_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; + case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; + case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; + case OP_FPA_INTERNAL_BVWRAP: + case OP_FPA_INTERNAL_BVUNWRAP: + case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED; default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp similarity index 71% rename from src/ast/float_decl_plugin.cpp rename to src/ast/fpa_decl_plugin.cpp index bdc0c6fb1..be3e5f3ec 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - float_decl_plugin.cpp + fpa_decl_plugin.cpp Abstract: @@ -16,11 +16,11 @@ Author: Revision History: --*/ -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" -float_decl_plugin::float_decl_plugin(): +fpa_decl_plugin::fpa_decl_plugin(): m_values(m_fm), m_value_table(mpf_hash_proc(m_values), mpf_eq_proc(m_values)) { m_real_sort = 0; @@ -28,16 +28,16 @@ float_decl_plugin::float_decl_plugin(): m_bv_plugin = 0; } -void float_decl_plugin::set_manager(ast_manager * m, family_id id) { +void fpa_decl_plugin::set_manager(ast_manager * m, family_id id) { decl_plugin::set_manager(m, id); m_arith_fid = m_manager->mk_family_id("arith"); m_real_sort = m_manager->mk_sort(m_arith_fid, REAL_SORT); - SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. + SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before fpa_decl_plugin. m_manager->inc_ref(m_real_sort); m_int_sort = m_manager->mk_sort(m_arith_fid, INT_SORT); - SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. + SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before fpa_decl_plugin. m_manager->inc_ref(m_int_sort); // BV is not optional anymore. @@ -46,10 +46,10 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) { m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); } -float_decl_plugin::~float_decl_plugin() { +fpa_decl_plugin::~fpa_decl_plugin() { } -unsigned float_decl_plugin::mk_id(mpf const & v) { +unsigned fpa_decl_plugin::mk_id(mpf const & v) { unsigned new_id = m_id_gen.mk(); m_values.reserve(new_id+1); m_fm.set(m_values[new_id], v); @@ -61,54 +61,54 @@ unsigned float_decl_plugin::mk_id(mpf const & v) { return old_id; } -void float_decl_plugin::recycled_id(unsigned id) { +void fpa_decl_plugin::recycled_id(unsigned id) { SASSERT(m_value_table.contains(id)); m_value_table.erase(id); m_id_gen.recycle(id); m_fm.del(m_values[id]); } -func_decl * float_decl_plugin::mk_value_decl(mpf const & v) { +func_decl * fpa_decl_plugin::mk_value_decl(mpf const & v) { parameter p(mk_id(v), true); SASSERT(p.is_external()); sort * s = mk_float_sort(v.get_ebits(), v.get_sbits()); - return m_manager->mk_const_decl(symbol("float"), s, func_decl_info(m_family_id, OP_FLOAT_VALUE, 1, &p)); + return m_manager->mk_const_decl(symbol("fpa"), s, func_decl_info(m_family_id, OP_FPA_VALUE, 1, &p)); } -app * float_decl_plugin::mk_value(mpf const & v) { +app * fpa_decl_plugin::mk_value(mpf const & v) { return m_manager->mk_const(mk_value_decl(v)); } -bool float_decl_plugin::is_value(expr * n, mpf & val) { - if (is_app_of(n, m_family_id, OP_FLOAT_VALUE)) { +bool fpa_decl_plugin::is_value(expr * n, mpf & val) { + if (is_app_of(n, m_family_id, OP_FPA_VALUE)) { m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]); return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_INF)) { + else if (is_app_of(n, m_family_id, OP_FPA_MINUS_INF)) { unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); m_fm.mk_ninf(ebits, sbits, val); return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_INF)) { + else if (is_app_of(n, m_family_id, OP_FPA_PLUS_INF)) { unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); m_fm.mk_pinf(ebits, sbits, val); return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_NAN)) { + else if (is_app_of(n, m_family_id, OP_FPA_NAN)) { unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); m_fm.mk_nan(ebits, sbits, val); return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_ZERO)) { + else if (is_app_of(n, m_family_id, OP_FPA_PLUS_ZERO)) { unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); m_fm.mk_pzero(ebits, sbits, val); return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_ZERO)) { + else if (is_app_of(n, m_family_id, OP_FPA_MINUS_ZERO)) { unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); m_fm.mk_nzero(ebits, sbits, val); @@ -117,24 +117,24 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) { return false; } -bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) { - if (is_app_of(n, m_family_id, OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)) { +bool fpa_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) { + if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_AWAY)) { val = MPF_ROUND_NEAREST_TAWAY; return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)) { + else if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_EVEN)) { val = MPF_ROUND_NEAREST_TEVEN; return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_NEGATIVE)) { + else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_NEGATIVE)) { val = MPF_ROUND_TOWARD_NEGATIVE; return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_POSITIVE)) { + else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_POSITIVE)) { val = MPF_ROUND_TOWARD_POSITIVE; return true; } - else if (is_app_of(n, m_family_id, OP_FLOAT_RM_TOWARD_ZERO)) { + else if (is_app_of(n, m_family_id, OP_FPA_RM_TOWARD_ZERO)) { val = MPF_ROUND_TOWARD_ZERO; return true; } @@ -142,27 +142,27 @@ bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) { return 0; } -void float_decl_plugin::del(parameter const & p) { +void fpa_decl_plugin::del(parameter const & p) { SASSERT(p.is_external()); recycled_id(p.get_ext_id()); } -parameter float_decl_plugin::translate(parameter const & p, decl_plugin & target) { +parameter fpa_decl_plugin::translate(parameter const & p, decl_plugin & target) { SASSERT(p.is_external()); - float_decl_plugin & _target = static_cast(target); + fpa_decl_plugin & _target = static_cast(target); return parameter(_target.mk_id(m_values[p.get_ext_id()]), true); } -void float_decl_plugin::finalize() { +void fpa_decl_plugin::finalize() { if (m_real_sort) { m_manager->dec_ref(m_real_sort); } if (m_int_sort) { m_manager->dec_ref(m_int_sort); } } -decl_plugin * float_decl_plugin::mk_fresh() { - return alloc(float_decl_plugin); +decl_plugin * fpa_decl_plugin::mk_fresh() { + return alloc(fpa_decl_plugin); } -sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { +sort * fpa_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { if (sbits < 2) m_manager->raise_exception("minimum number of significand bits is 1"); if (ebits < 2) @@ -172,16 +172,16 @@ sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { p1, p2 }; sort_size sz; sz = sort_size::mk_very_big(); // TODO: refine - return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps)); + return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOATING_POINT_SORT, sz, 2, ps)); } -sort * float_decl_plugin::mk_rm_sort() { +sort * fpa_decl_plugin::mk_rm_sort() { return m_manager->mk_sort(symbol("RoundingMode"), sort_info(m_family_id, ROUNDING_MODE_SORT)); } -sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) { +sort * fpa_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) { switch (k) { - case FLOAT_SORT: + case FLOATING_POINT_SORT: if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) m_manager->raise_exception("expecting two integer parameters to floating point sort (ebits, sbits)"); return mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); @@ -201,7 +201,7 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete } } -func_decl * float_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (num_parameters != 0) m_manager->raise_exception("rounding mode constant does not have parameters"); @@ -210,15 +210,15 @@ func_decl * float_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parame sort * s = mk_rm_sort(); func_decl_info finfo(m_family_id, k); switch (k) { - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: return m_manager->mk_const_decl(symbol("roundNearestTiesToEven"), s, finfo); - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: return m_manager->mk_const_decl(symbol("roundNearestTiesToAway"), s, finfo); - case OP_FLOAT_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_POSITIVE: return m_manager->mk_const_decl(symbol("roundTowardPositive"), s, finfo); - case OP_FLOAT_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_NEGATIVE: return m_manager->mk_const_decl(symbol("roundTowardNegative"), s, finfo); - case OP_FLOAT_RM_TOWARD_ZERO: + case OP_FPA_RM_TOWARD_ZERO: return m_manager->mk_const_decl(symbol("roundTowardZero"), s, finfo); default: UNREACHABLE(); @@ -226,7 +226,7 @@ func_decl * float_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_parame } } -func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { sort * s; if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast()) && is_float_sort(to_sort(parameters[0].get_ast()))) { @@ -243,7 +243,7 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par UNREACHABLE(); } - SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT)); + SASSERT(is_sort_of(s, m_family_id, FLOATING_POINT_SORT)); unsigned ebits = s->get_parameter(0).get_int(); unsigned sbits = s->get_parameter(1).get_int(); @@ -251,19 +251,19 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par switch (k) { - case OP_FLOAT_NAN: m_fm.mk_nan(ebits, sbits, val); + case OP_FPA_NAN: m_fm.mk_nan(ebits, sbits, val); SASSERT(m_fm.is_nan(val)); break; - case OP_FLOAT_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break; - case OP_FLOAT_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break; - case OP_FLOAT_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break; - case OP_FLOAT_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break; + case OP_FPA_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break; + case OP_FPA_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break; + case OP_FPA_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break; + case OP_FPA_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break; } return mk_value_decl(val); } -func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point relation"); @@ -271,11 +271,11 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet m_manager->raise_exception("sort mismatch, expected equal FloatingPoint sorts as arguments"); symbol name; switch (k) { - case OP_FLOAT_EQ: name = "fp.eq"; break; - case OP_FLOAT_LT: name = "fp.lt"; break; - case OP_FLOAT_GT: name = "fp.gt"; break; - case OP_FLOAT_LE: name = "fp.leq"; break; - case OP_FLOAT_GE: name = "fp.geq"; break; + case OP_FPA_EQ: name = "fp.eq"; break; + case OP_FPA_LT: name = "fp.lt"; break; + case OP_FPA_GT: name = "fp.gt"; break; + case OP_FPA_LE: name = "fp.leq"; break; + case OP_FPA_GE: name = "fp.geq"; break; default: UNREACHABLE(); break; @@ -285,7 +285,7 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet return m_manager->mk_func_decl(name, arity, domain, m_manager->mk_bool_sort(), finfo); } -func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to floating point relation"); @@ -293,15 +293,15 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); symbol name; switch (k) { - case OP_FLOAT_IS_ZERO: name = "fp.isZero"; break; - case OP_FLOAT_IS_NZERO: name = "fp.isNZero"; break; - case OP_FLOAT_IS_PZERO: name = "fp.isPZero"; break; - case OP_FLOAT_IS_NEGATIVE: name = "fp.isNegative"; break; - case OP_FLOAT_IS_POSITIVE: name = "fp.isPositive"; break; - case OP_FLOAT_IS_NAN: name = "fp.isNaN"; break; - case OP_FLOAT_IS_INF: name = "fp.isInfinite"; break; - case OP_FLOAT_IS_NORMAL: name = "fp.isNormal"; break; - case OP_FLOAT_IS_SUBNORMAL: name = "fp.isSubnormal"; break; + case OP_FPA_IS_ZERO: name = "fp.isZero"; break; + case OP_FPA_IS_NZERO: name = "fp.isNZero"; break; + case OP_FPA_IS_PZERO: name = "fp.isPZero"; break; + case OP_FPA_IS_NEGATIVE: name = "fp.isNegative"; break; + case OP_FPA_IS_POSITIVE: name = "fp.isPositive"; break; + case OP_FPA_IS_NAN: name = "fp.isNaN"; break; + case OP_FPA_IS_INF: name = "fp.isInfinite"; break; + case OP_FPA_IS_NORMAL: name = "fp.isNormal"; break; + case OP_FPA_IS_SUBNORMAL: name = "fp.isSubnormal"; break; default: UNREACHABLE(); break; @@ -309,7 +309,7 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param return m_manager->mk_func_decl(name, arity, domain, m_manager->mk_bool_sort(), func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to floating point operator"); @@ -317,8 +317,8 @@ func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameter m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); symbol name; switch (k) { - case OP_FLOAT_ABS: name = "fp.abs"; break; - case OP_FLOAT_NEG: name = "fp.neg"; break; + case OP_FPA_ABS: name = "fp.abs"; break; + case OP_FPA_NEG: name = "fp.neg"; break; default: UNREACHABLE(); break; @@ -326,7 +326,7 @@ func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameter return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point operator"); @@ -334,9 +334,9 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete m_manager->raise_exception("sort mismatch, expected arguments of equal FloatingPoint sorts"); symbol name; switch (k) { - case OP_FLOAT_REM: name = "fp.rem"; break; - case OP_FLOAT_MIN: name = "fp.min"; break; - case OP_FLOAT_MAX: name = "fp.max"; break; + case OP_FPA_REM: name = "fp.rem"; break; + case OP_FPA_MIN: name = "fp.min"; break; + case OP_FPA_MAX: name = "fp.max"; break; default: UNREACHABLE(); break; @@ -344,7 +344,7 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete return m_manager->mk_func_decl(name, arity, domain, domain[0], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 3) m_manager->raise_exception("invalid number of arguments to floating point operator"); @@ -354,10 +354,10 @@ func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_param m_manager->raise_exception("sort mismatch, expected arguments 1 and 2 of equal FloatingPoint sorts"); symbol name; switch (k) { - case OP_FLOAT_ADD: name = "fp.add"; break; - case OP_FLOAT_SUB: name = "fp.sub"; break; - case OP_FLOAT_MUL: name = "fp.mul"; break; - case OP_FLOAT_DIV: name = "fp.div"; break; + case OP_FPA_ADD: name = "fp.add"; break; + case OP_FPA_SUB: name = "fp.sub"; break; + case OP_FPA_MUL: name = "fp.mul"; break; + case OP_FPA_DIV: name = "fp.div"; break; default: UNREACHABLE(); break; @@ -365,7 +365,7 @@ func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_param return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point operator"); @@ -375,8 +375,8 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame m_manager->raise_exception("sort mismatch, expected FloatingPoint as second argument"); symbol name; switch (k) { - case OP_FLOAT_SQRT: name = "fp.sqrt"; break; - case OP_FLOAT_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break; + case OP_FPA_SQRT: name = "fp.sqrt"; break; + case OP_FPA_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break; default: UNREACHABLE(); break; @@ -384,7 +384,7 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 4) m_manager->raise_exception("invalid number of arguments to fused_ma operator"); @@ -396,7 +396,7 @@ func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, para return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (m_bv_plugin && arity == 3 && is_sort_of(domain[0], m_bv_fid, BV_SORT) && @@ -444,7 +444,7 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa } else if (arity == 2 && is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && - is_sort_of(domain[1], m_family_id, FLOAT_SORT)) { + is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT)) { // Rounding + 1 FP -> 1 FP if (num_parameters != 2) m_manager->raise_exception("invalid number of parameters to to_fp"); @@ -454,7 +454,7 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa int sbits = parameters[1].get_int(); if (!is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); - if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT)) m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); sort * fp = mk_float_sort(ebits, sbits); @@ -514,7 +514,7 @@ func_decl * float_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, pa return 0; } -func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { SASSERT(m_bv_plugin); if (arity != 2) @@ -538,7 +538,7 @@ func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_param return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 3) m_manager->raise_exception("invalid number of arguments to fp"); @@ -555,7 +555,7 @@ func_decl * float_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, param return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { SASSERT(m_bv_plugin); if (arity != 2) @@ -566,7 +566,7 @@ func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, p m_manager->raise_exception("invalid parameter type; fp.to_ubv expects an int parameter"); if (!is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); - if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT)) m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); if (parameters[0].get_int() <= 0) m_manager->raise_exception("invalid parameter value; fp.to_ubv expects a parameter larger than 0"); @@ -576,7 +576,7 @@ func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, p return m_manager->mk_func_decl(name, arity, domain, bvs, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { SASSERT(m_bv_plugin); if (arity != 2) @@ -587,7 +587,7 @@ func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, p m_manager->raise_exception("invalid parameter type; fp.to_sbv expects an int parameter"); if (!is_rm_sort(domain[0])) m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); - if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + if (!is_sort_of(domain[1], m_family_id, FLOATING_POINT_SORT)) m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); if (parameters[0].get_int() <= 0) m_manager->raise_exception("invalid parameter value; fp.to_sbv expects a parameter larger than 0"); @@ -598,7 +598,7 @@ func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, p } -func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to fp.to_real"); @@ -609,7 +609,7 @@ func_decl * float_decl_plugin::mk_to_real(decl_kind k, unsigned num_parameters, return m_manager->mk_func_decl(name, 1, domain, m_real_sort, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to asIEEEBV"); @@ -623,7 +623,7 @@ func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_par return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to internal_bv_wrap"); @@ -644,7 +644,7 @@ func_decl * float_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_par } } -func_decl * float_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 1) m_manager->raise_exception("invalid number of arguments to internal_bv_unwrap"); @@ -656,7 +656,7 @@ func_decl * float_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_p return m_manager->mk_func_decl(symbol("bv_unwrap"), 1, domain, range, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_internal_to_ubv_unspecified( +func_decl * fpa_decl_plugin::mk_internal_to_ubv_unspecified( decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 0) @@ -670,7 +670,7 @@ func_decl * float_decl_plugin::mk_internal_to_ubv_unspecified( return m_manager->mk_func_decl(symbol("fp.to_ubv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_internal_to_sbv_unspecified( +func_decl * fpa_decl_plugin::mk_internal_to_sbv_unspecified( decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 0) @@ -683,7 +683,7 @@ func_decl * float_decl_plugin::mk_internal_to_sbv_unspecified( return m_manager->mk_func_decl(symbol("fp.to_sbv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters)); } -func_decl * float_decl_plugin::mk_internal_to_real_unspecified( +func_decl * fpa_decl_plugin::mk_internal_to_real_unspecified( decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 0) @@ -695,81 +695,81 @@ func_decl * float_decl_plugin::mk_internal_to_real_unspecified( } -func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (k) { - case OP_FLOAT_MINUS_INF: - case OP_FLOAT_PLUS_INF: - case OP_FLOAT_NAN: - case OP_FLOAT_MINUS_ZERO: - case OP_FLOAT_PLUS_ZERO: + case OP_FPA_MINUS_INF: + case OP_FPA_PLUS_INF: + case OP_FPA_NAN: + case OP_FPA_MINUS_ZERO: + case OP_FPA_PLUS_ZERO: return mk_float_const_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: - case OP_FLOAT_RM_TOWARD_POSITIVE: - case OP_FLOAT_RM_TOWARD_NEGATIVE: - case OP_FLOAT_RM_TOWARD_ZERO: + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_ZERO: return mk_rm_const_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_EQ: - case OP_FLOAT_LT: - case OP_FLOAT_GT: - case OP_FLOAT_LE: - case OP_FLOAT_GE: + case OP_FPA_EQ: + case OP_FPA_LT: + case OP_FPA_GT: + case OP_FPA_LE: + case OP_FPA_GE: return mk_bin_rel_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_IS_ZERO: - case OP_FLOAT_IS_NZERO: - case OP_FLOAT_IS_PZERO: - case OP_FLOAT_IS_NEGATIVE: - case OP_FLOAT_IS_POSITIVE: - case OP_FLOAT_IS_NAN: - case OP_FLOAT_IS_INF: - case OP_FLOAT_IS_NORMAL: - case OP_FLOAT_IS_SUBNORMAL: + case OP_FPA_IS_ZERO: + case OP_FPA_IS_NZERO: + case OP_FPA_IS_PZERO: + case OP_FPA_IS_NEGATIVE: + case OP_FPA_IS_POSITIVE: + case OP_FPA_IS_NAN: + case OP_FPA_IS_INF: + case OP_FPA_IS_NORMAL: + case OP_FPA_IS_SUBNORMAL: return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_ABS: - case OP_FLOAT_NEG: + case OP_FPA_ABS: + case OP_FPA_NEG: return mk_unary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_REM: - case OP_FLOAT_MIN: - case OP_FLOAT_MAX: + case OP_FPA_REM: + case OP_FPA_MIN: + case OP_FPA_MAX: return mk_binary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_ADD: - case OP_FLOAT_MUL: - case OP_FLOAT_DIV: + case OP_FPA_ADD: + case OP_FPA_MUL: + case OP_FPA_DIV: return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_SUB: + case OP_FPA_SUB: if (arity == 1) - return mk_unary_decl(OP_FLOAT_NEG, num_parameters, parameters, arity, domain, range); + return mk_unary_decl(OP_FPA_NEG, num_parameters, parameters, arity, domain, range); else return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_SQRT: - case OP_FLOAT_ROUND_TO_INTEGRAL: + case OP_FPA_SQRT: + case OP_FPA_ROUND_TO_INTEGRAL: return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_FMA: + case OP_FPA_FMA: return mk_fma(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_FP: + case OP_FPA_FP: return mk_fp(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_UBV: + case OP_FPA_TO_UBV: return mk_to_ubv(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_SBV: + case OP_FPA_TO_SBV: return mk_to_sbv(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_REAL: + case OP_FPA_TO_REAL: return mk_to_real(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_FP: + case OP_FPA_TO_FP: return mk_to_fp(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_FP_UNSIGNED: + case OP_FPA_TO_FP_UNSIGNED: return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_IEEE_BV: + case OP_FPA_TO_IEEE_BV: return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_INTERNAL_BVWRAP: + case OP_FPA_INTERNAL_BVWRAP: return mk_internal_bv_wrap(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_INTERNAL_BVUNWRAP: + case OP_FPA_INTERNAL_BVUNWRAP: return mk_internal_bv_unwrap(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: return mk_internal_to_ubv_unspecified(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return mk_internal_to_sbv_unspecified(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED: + case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: return mk_internal_to_real_unspecified(k, num_parameters, parameters, arity, domain, range); default: m_manager->raise_exception("unsupported floating point operator"); @@ -777,66 +777,66 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters } } -void float_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { +void fpa_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { // These are the operators from the final draft of the SMT FloatingPoint standard - op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF)); - op_names.push_back(builtin_name("+zero", OP_FLOAT_PLUS_ZERO)); - op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO)); - op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN)); + op_names.push_back(builtin_name("+oo", OP_FPA_PLUS_INF)); + op_names.push_back(builtin_name("-oo", OP_FPA_MINUS_INF)); + op_names.push_back(builtin_name("+zero", OP_FPA_PLUS_ZERO)); + op_names.push_back(builtin_name("-zero", OP_FPA_MINUS_ZERO)); + op_names.push_back(builtin_name("NaN", OP_FPA_NAN)); - op_names.push_back(builtin_name("roundNearestTiesToEven", OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)); - op_names.push_back(builtin_name("roundNearestTiesToAway", OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)); - op_names.push_back(builtin_name("roundTowardPositive", OP_FLOAT_RM_TOWARD_POSITIVE)); - op_names.push_back(builtin_name("roundTowardNegative", OP_FLOAT_RM_TOWARD_NEGATIVE)); - op_names.push_back(builtin_name("roundTowardZero", OP_FLOAT_RM_TOWARD_ZERO)); + op_names.push_back(builtin_name("roundNearestTiesToEven", OP_FPA_RM_NEAREST_TIES_TO_EVEN)); + op_names.push_back(builtin_name("roundNearestTiesToAway", OP_FPA_RM_NEAREST_TIES_TO_AWAY)); + op_names.push_back(builtin_name("roundTowardPositive", OP_FPA_RM_TOWARD_POSITIVE)); + op_names.push_back(builtin_name("roundTowardNegative", OP_FPA_RM_TOWARD_NEGATIVE)); + op_names.push_back(builtin_name("roundTowardZero", OP_FPA_RM_TOWARD_ZERO)); - op_names.push_back(builtin_name("RNE", OP_FLOAT_RM_NEAREST_TIES_TO_EVEN)); - op_names.push_back(builtin_name("RNA", OP_FLOAT_RM_NEAREST_TIES_TO_AWAY)); - op_names.push_back(builtin_name("RTP", OP_FLOAT_RM_TOWARD_POSITIVE)); - op_names.push_back(builtin_name("RTN", OP_FLOAT_RM_TOWARD_NEGATIVE)); - op_names.push_back(builtin_name("RTZ", OP_FLOAT_RM_TOWARD_ZERO)); + op_names.push_back(builtin_name("RNE", OP_FPA_RM_NEAREST_TIES_TO_EVEN)); + op_names.push_back(builtin_name("RNA", OP_FPA_RM_NEAREST_TIES_TO_AWAY)); + op_names.push_back(builtin_name("RTP", OP_FPA_RM_TOWARD_POSITIVE)); + op_names.push_back(builtin_name("RTN", OP_FPA_RM_TOWARD_NEGATIVE)); + op_names.push_back(builtin_name("RTZ", OP_FPA_RM_TOWARD_ZERO)); - op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG)); - op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD)); - op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB)); - op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL)); - op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FMA)); - op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT)); - op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fp.roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); - op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN)); - op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX)); - op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE)); - op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT)); - op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE)); - op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT)); - op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ)); + op_names.push_back(builtin_name("fp.abs", OP_FPA_ABS)); + op_names.push_back(builtin_name("fp.neg", OP_FPA_NEG)); + op_names.push_back(builtin_name("fp.add", OP_FPA_ADD)); + op_names.push_back(builtin_name("fp.sub", OP_FPA_SUB)); + op_names.push_back(builtin_name("fp.mul", OP_FPA_MUL)); + op_names.push_back(builtin_name("fp.div", OP_FPA_DIV)); + op_names.push_back(builtin_name("fp.fma", OP_FPA_FMA)); + op_names.push_back(builtin_name("fp.sqrt", OP_FPA_SQRT)); + op_names.push_back(builtin_name("fp.rem", OP_FPA_REM)); + op_names.push_back(builtin_name("fp.roundToIntegral", OP_FPA_ROUND_TO_INTEGRAL)); + op_names.push_back(builtin_name("fp.min", OP_FPA_MIN)); + op_names.push_back(builtin_name("fp.max", OP_FPA_MAX)); + op_names.push_back(builtin_name("fp.leq", OP_FPA_LE)); + op_names.push_back(builtin_name("fp.lt", OP_FPA_LT)); + op_names.push_back(builtin_name("fp.geq", OP_FPA_GE)); + op_names.push_back(builtin_name("fp.gt", OP_FPA_GT)); + op_names.push_back(builtin_name("fp.eq", OP_FPA_EQ)); - op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL)); - op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL)); - op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO)); - op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF)); - op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN)); - op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE)); - op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE)); + op_names.push_back(builtin_name("fp.isNormal", OP_FPA_IS_NORMAL)); + op_names.push_back(builtin_name("fp.isSubnormal", OP_FPA_IS_SUBNORMAL)); + op_names.push_back(builtin_name("fp.isZero", OP_FPA_IS_ZERO)); + op_names.push_back(builtin_name("fp.isInfinite", OP_FPA_IS_INF)); + op_names.push_back(builtin_name("fp.isNaN", OP_FPA_IS_NAN)); + op_names.push_back(builtin_name("fp.isNegative", OP_FPA_IS_NEGATIVE)); + op_names.push_back(builtin_name("fp.isPositive", OP_FPA_IS_POSITIVE)); - op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); - op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); - op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - op_names.push_back(builtin_name("fp.to_real", OP_FLOAT_TO_REAL)); + op_names.push_back(builtin_name("fp", OP_FPA_FP)); + op_names.push_back(builtin_name("fp.to_ubv", OP_FPA_TO_UBV)); + op_names.push_back(builtin_name("fp.to_sbv", OP_FPA_TO_SBV)); + op_names.push_back(builtin_name("fp.to_real", OP_FPA_TO_REAL)); - op_names.push_back(builtin_name("to_fp", OP_FLOAT_TO_FP)); - op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); + op_names.push_back(builtin_name("to_fp", OP_FPA_TO_FP)); + op_names.push_back(builtin_name("to_fp_unsigned", OP_FPA_TO_FP_UNSIGNED)); /* Extensions */ - op_names.push_back(builtin_name("to_ieee_bv", OP_FLOAT_TO_IEEE_BV)); + op_names.push_back(builtin_name("to_ieee_bv", OP_FPA_TO_IEEE_BV)); } -void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { - sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); +void fpa_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { + sort_names.push_back(builtin_name("FloatingPoint", FLOATING_POINT_SORT)); sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT)); // The final theory supports three common FloatingPoint sorts @@ -846,8 +846,8 @@ void float_decl_plugin::get_sort_names(svector & sort_names, symbo sort_names.push_back(builtin_name("Float128", FLOAT128_SORT)); } -expr * float_decl_plugin::get_some_value(sort * s) { - SASSERT(s->is_sort_of(m_family_id, FLOAT_SORT)); +expr * fpa_decl_plugin::get_some_value(sort * s) { + SASSERT(s->is_sort_of(m_family_id, FLOATING_POINT_SORT)); mpf tmp; m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp); expr * res = this->mk_value(tmp); @@ -855,23 +855,23 @@ expr * float_decl_plugin::get_some_value(sort * s) { return res; } -bool float_decl_plugin::is_value(app * e) const { +bool fpa_decl_plugin::is_value(app * e) const { if (e->get_family_id() != m_family_id) return false; switch (e->get_decl_kind()) { - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: - case OP_FLOAT_RM_TOWARD_POSITIVE: - case OP_FLOAT_RM_TOWARD_NEGATIVE: - case OP_FLOAT_RM_TOWARD_ZERO: - case OP_FLOAT_VALUE: - case OP_FLOAT_PLUS_INF: - case OP_FLOAT_MINUS_INF: - case OP_FLOAT_PLUS_ZERO: - case OP_FLOAT_MINUS_ZERO: - case OP_FLOAT_NAN: + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_ZERO: + case OP_FPA_VALUE: + case OP_FPA_PLUS_INF: + case OP_FPA_MINUS_INF: + case OP_FPA_PLUS_ZERO: + case OP_FPA_MINUS_ZERO: + case OP_FPA_NAN: return true; - case OP_FLOAT_FP: + case OP_FPA_FP: return m_manager->is_value(e->get_arg(0)) && m_manager->is_value(e->get_arg(1)) && m_manager->is_value(e->get_arg(2)); @@ -880,24 +880,24 @@ bool float_decl_plugin::is_value(app * e) const { } } -bool float_decl_plugin::is_unique_value(app* e) const { +bool fpa_decl_plugin::is_unique_value(app* e) const { if (e->get_family_id() != m_family_id) return false; switch (e->get_decl_kind()) { - case OP_FLOAT_RM_NEAREST_TIES_TO_EVEN: - case OP_FLOAT_RM_NEAREST_TIES_TO_AWAY: - case OP_FLOAT_RM_TOWARD_POSITIVE: - case OP_FLOAT_RM_TOWARD_NEGATIVE: - case OP_FLOAT_RM_TOWARD_ZERO: + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_ZERO: return true; - case OP_FLOAT_PLUS_INF: /* No; +oo == fp(#b0 #b11 #b00) */ - case OP_FLOAT_MINUS_INF: /* No; -oo == fp #b1 #b11 #b00) */ - case OP_FLOAT_PLUS_ZERO: /* No; +zero == fp #b0 #b00 #b000) */ - case OP_FLOAT_MINUS_ZERO: /* No; -zero == fp #b1 #b00 #b000) */ - case OP_FLOAT_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */ - case OP_FLOAT_VALUE: /* see NaN */ + case OP_FPA_PLUS_INF: /* No; +oo == fp(#b0 #b11 #b00) */ + case OP_FPA_MINUS_INF: /* No; -oo == fp #b1 #b11 #b00) */ + case OP_FPA_PLUS_ZERO: /* No; +zero == fp #b0 #b00 #b000) */ + case OP_FPA_MINUS_ZERO: /* No; -zero == fp #b1 #b00 #b000) */ + case OP_FPA_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */ + case OP_FPA_VALUE: /* see NaN */ return false; - case OP_FLOAT_FP: + case OP_FPA_FP: return m_manager->is_unique_value(e->get_arg(0)) && m_manager->is_unique_value(e->get_arg(1)) && m_manager->is_unique_value(e->get_arg(2)); @@ -908,10 +908,10 @@ bool float_decl_plugin::is_unique_value(app* e) const { float_util::float_util(ast_manager & m): m_manager(m), - m_fid(m.mk_family_id("float")), + m_fid(m.mk_family_id("fpa")), m_a_util(m), m_bv_util(m) { - m_plugin = static_cast(m.get_plugin(m_fid)); + m_plugin = static_cast(m.get_plugin(m_fid)); } float_util::~float_util() { @@ -919,7 +919,7 @@ float_util::~float_util() { sort * float_util::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { parameter(ebits), parameter(sbits) }; - return m().mk_sort(m_fid, FLOAT_SORT, 2, ps); + return m().mk_sort(m_fid, FLOATING_POINT_SORT, 2, ps); } unsigned float_util::get_ebits(sort * s) { @@ -965,16 +965,16 @@ app * float_util::mk_nzero(unsigned ebits, unsigned sbits) { app * float_util::mk_internal_to_ubv_unspecified(unsigned width) { parameter ps[] = { parameter(width) }; sort * range = m_bv_util.mk_sort(width); - return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED, 1, ps, 0, 0, range); + return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, 1, ps, 0, 0, range); } app * float_util::mk_internal_to_sbv_unspecified(unsigned width) { parameter ps[] = { parameter(width) }; sort * range = m_bv_util.mk_sort(width); - return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range); + return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range); } app * float_util::mk_internal_to_real_unspecified() { sort * range = m_a_util.mk_real(); - return m().mk_app(get_family_id(), OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED, 0, 0, 0, 0, range); + return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, 0, 0, 0, 0, range); } \ No newline at end of file diff --git a/src/ast/float_decl_plugin.h b/src/ast/fpa_decl_plugin.h similarity index 77% rename from src/ast/float_decl_plugin.h rename to src/ast/fpa_decl_plugin.h index cbcd706cd..b7d59a6af 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - float_decl_plugin.h + fpa_decl_plugin.h Abstract: @@ -16,8 +16,8 @@ Author: Revision History: --*/ -#ifndef _FLOAT_DECL_PLUGIN_H_ -#define _FLOAT_DECL_PLUGIN_H_ +#ifndef _fpa_decl_plugin_H_ +#define _fpa_decl_plugin_H_ #include"ast.h" #include"id_gen.h" @@ -25,8 +25,8 @@ Revision History: #include"bv_decl_plugin.h" #include"mpf.h" -enum float_sort_kind { - FLOAT_SORT, +enum fpa_sort_kind { + FLOATING_POINT_SORT, ROUNDING_MODE_SORT, FLOAT16_SORT, FLOAT32_SORT, @@ -34,69 +34,69 @@ enum float_sort_kind { FLOAT128_SORT }; -enum float_op_kind { - OP_FLOAT_RM_NEAREST_TIES_TO_EVEN, - OP_FLOAT_RM_NEAREST_TIES_TO_AWAY, - OP_FLOAT_RM_TOWARD_POSITIVE, - OP_FLOAT_RM_TOWARD_NEGATIVE, - OP_FLOAT_RM_TOWARD_ZERO, +enum fpa_op_kind { + OP_FPA_RM_NEAREST_TIES_TO_EVEN, + OP_FPA_RM_NEAREST_TIES_TO_AWAY, + OP_FPA_RM_TOWARD_POSITIVE, + OP_FPA_RM_TOWARD_NEGATIVE, + OP_FPA_RM_TOWARD_ZERO, - OP_FLOAT_VALUE, - OP_FLOAT_PLUS_INF, - OP_FLOAT_MINUS_INF, - OP_FLOAT_NAN, - OP_FLOAT_PLUS_ZERO, - OP_FLOAT_MINUS_ZERO, + OP_FPA_VALUE, + OP_FPA_PLUS_INF, + OP_FPA_MINUS_INF, + OP_FPA_NAN, + OP_FPA_PLUS_ZERO, + OP_FPA_MINUS_ZERO, - OP_FLOAT_ADD, - OP_FLOAT_SUB, - OP_FLOAT_NEG, - OP_FLOAT_MUL, - OP_FLOAT_DIV, - OP_FLOAT_REM, - OP_FLOAT_ABS, - OP_FLOAT_MIN, - OP_FLOAT_MAX, - OP_FLOAT_FMA, // x*y + z - OP_FLOAT_SQRT, - OP_FLOAT_ROUND_TO_INTEGRAL, + OP_FPA_ADD, + OP_FPA_SUB, + OP_FPA_NEG, + OP_FPA_MUL, + OP_FPA_DIV, + OP_FPA_REM, + OP_FPA_ABS, + OP_FPA_MIN, + OP_FPA_MAX, + OP_FPA_FMA, // x*y + z + OP_FPA_SQRT, + OP_FPA_ROUND_TO_INTEGRAL, - OP_FLOAT_EQ, - OP_FLOAT_LT, - OP_FLOAT_GT, - OP_FLOAT_LE, - OP_FLOAT_GE, - OP_FLOAT_IS_NAN, - OP_FLOAT_IS_INF, - OP_FLOAT_IS_ZERO, - OP_FLOAT_IS_NORMAL, - OP_FLOAT_IS_SUBNORMAL, - OP_FLOAT_IS_PZERO, - OP_FLOAT_IS_NZERO, - OP_FLOAT_IS_NEGATIVE, - OP_FLOAT_IS_POSITIVE, + OP_FPA_EQ, + OP_FPA_LT, + OP_FPA_GT, + OP_FPA_LE, + OP_FPA_GE, + OP_FPA_IS_NAN, + OP_FPA_IS_INF, + OP_FPA_IS_ZERO, + OP_FPA_IS_NORMAL, + OP_FPA_IS_SUBNORMAL, + OP_FPA_IS_PZERO, + OP_FPA_IS_NZERO, + OP_FPA_IS_NEGATIVE, + OP_FPA_IS_POSITIVE, - OP_FLOAT_FP, - OP_FLOAT_TO_FP, - OP_FLOAT_TO_FP_UNSIGNED, - OP_FLOAT_TO_UBV, - OP_FLOAT_TO_SBV, - OP_FLOAT_TO_REAL, + OP_FPA_FP, + OP_FPA_TO_FP, + OP_FPA_TO_FP_UNSIGNED, + OP_FPA_TO_UBV, + OP_FPA_TO_SBV, + OP_FPA_TO_REAL, /* Extensions */ - OP_FLOAT_TO_IEEE_BV, + OP_FPA_TO_IEEE_BV, /* Internal use only */ - OP_FLOAT_INTERNAL_BVWRAP, - OP_FLOAT_INTERNAL_BVUNWRAP, - OP_FLOAT_INTERNAL_TO_UBV_UNSPECIFIED, - OP_FLOAT_INTERNAL_TO_SBV_UNSPECIFIED, - OP_FLOAT_INTERNAL_TO_REAL_UNSPECIFIED, + OP_FPA_INTERNAL_BVWRAP, + OP_FPA_INTERNAL_BVUNWRAP, + OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, + OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, + OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, LAST_FLOAT_OP }; -class float_decl_plugin : public decl_plugin { +class fpa_decl_plugin : public decl_plugin { struct mpf_hash_proc { scoped_mpf_vector const & m_values; mpf_hash_proc(scoped_mpf_vector const & values):m_values(values) {} @@ -172,12 +172,12 @@ class float_decl_plugin : public decl_plugin { unsigned mk_id(mpf const & v); void recycled_id(unsigned id); public: - float_decl_plugin(); + fpa_decl_plugin(); - bool is_float_sort(sort * s) const { return is_sort_of(s, m_family_id, FLOAT_SORT); } + bool is_float_sort(sort * s) const { return is_sort_of(s, m_family_id, FLOATING_POINT_SORT); } bool is_rm_sort(sort * s) const { return is_sort_of(s, m_family_id, ROUNDING_MODE_SORT); } - virtual ~float_decl_plugin(); + virtual ~fpa_decl_plugin(); virtual void finalize(); virtual decl_plugin * mk_fresh(); @@ -193,7 +193,7 @@ public: mpf_manager & fm() { return m_fm; } func_decl * mk_value_decl(mpf const & v); app * mk_value(mpf const & v); - bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FLOAT_VALUE); } + bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FPA_VALUE); } bool is_value(expr * n, mpf & val); bool is_rm_value(expr * n, mpf_rounding_mode & val); bool is_rm_value(expr * n) { mpf_rounding_mode t; return is_rm_value(n, t); } @@ -209,7 +209,7 @@ public: class float_util { ast_manager & m_manager; - float_decl_plugin * m_plugin; + fpa_decl_plugin * m_plugin; family_id m_fid; arith_util m_a_util; bv_util m_bv_util; @@ -222,22 +222,22 @@ public: family_id get_fid() const { return m_fid; } family_id get_family_id() const { return m_fid; } arith_util & au() { return m_a_util; } - float_decl_plugin & plugin() { return *m_plugin; } + fpa_decl_plugin & plugin() { return *m_plugin; } sort * mk_float_sort(unsigned ebits, unsigned sbits); sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); } - bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOAT_SORT); } + bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOATING_POINT_SORT); } bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); } bool is_float(expr * e) { return is_float(m_manager.get_sort(e)); } bool is_rm(expr * e) { return is_rm(m_manager.get_sort(e)); } unsigned get_ebits(sort * s); unsigned get_sbits(sort * s); - app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_FLOAT_RM_NEAREST_TIES_TO_EVEN); } - app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_FLOAT_RM_NEAREST_TIES_TO_AWAY); } - app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_POSITIVE); } - app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_NEGATIVE); } - app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_FLOAT_RM_TOWARD_ZERO); } + app * mk_round_nearest_ties_to_even() { return m().mk_const(m_fid, OP_FPA_RM_NEAREST_TIES_TO_EVEN); } + app * mk_round_nearest_ties_to_away() { return m().mk_const(m_fid, OP_FPA_RM_NEAREST_TIES_TO_AWAY); } + app * mk_round_toward_positive() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_POSITIVE); } + app * mk_round_toward_negative() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_NEGATIVE); } + app * mk_round_toward_zero() { return m().mk_const(m_fid, OP_FPA_RM_TOWARD_ZERO); } app * mk_nan(unsigned ebits, unsigned sbits); app * mk_pinf(unsigned ebits, unsigned sbits); @@ -264,83 +264,83 @@ public: bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } - app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_FP, arg1, arg2, arg3); } + app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_FP, arg1, arg2, arg3); } app * mk_to_fp(sort * s, expr * bv_t) { SASSERT(is_float(s) && s->get_num_parameters() == 2); - return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 1, &bv_t); + return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 1, &bv_t); } app * mk_to_fp(sort * s, expr * rm, expr * t) { SASSERT(is_float(s) && s->get_num_parameters() == 2); expr * args[] = { rm, t }; - return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 2, args); + return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 2, args); } app * mk_to_fp(sort * s, expr * rm, expr * sig, expr * exp) { SASSERT(is_float(s) && s->get_num_parameters() == 2); expr * args[] = { rm, sig, exp }; - return m().mk_app(m_fid, OP_FLOAT_TO_FP, 2, s->get_parameters(), 3, args); + return m().mk_app(m_fid, OP_FPA_TO_FP, 2, s->get_parameters(), 3, args); } app * mk_to_fp_unsigned(sort * s, expr * rm, expr * t) { SASSERT(is_float(s) && s->get_num_parameters() == 2); expr * args[] = { rm, t }; - return m().mk_app(m_fid, OP_FLOAT_TO_FP_UNSIGNED, 2, s->get_parameters(), 2, args); + return m().mk_app(m_fid, OP_FPA_TO_FP_UNSIGNED, 2, s->get_parameters(), 2, args); } - bool is_to_fp(expr * n) { return is_app_of(n, m_fid, OP_FLOAT_TO_FP); } + bool is_to_fp(expr * n) { return is_app_of(n, m_fid, OP_FPA_TO_FP); } app * mk_to_ubv(expr * rm, expr * t, unsigned sz) { parameter ps[] = { parameter(sz) }; expr * args[] = { rm, t }; - return m().mk_app(m_fid, OP_FLOAT_TO_UBV, 1, ps, 2, args); } + return m().mk_app(m_fid, OP_FPA_TO_UBV, 1, ps, 2, args); } app * mk_to_sbv(expr * rm, expr * t, unsigned sz) { parameter ps[] = { parameter(sz) }; expr * args[] = { rm, t }; - return m().mk_app(m_fid, OP_FLOAT_TO_SBV, 1, ps, 2, args); + return m().mk_app(m_fid, OP_FPA_TO_SBV, 1, ps, 2, args); } - app * mk_to_real(expr * t) { return m().mk_app(m_fid, OP_FLOAT_TO_REAL, t); } + app * mk_to_real(expr * t) { return m().mk_app(m_fid, OP_FPA_TO_REAL, t); } - app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_ADD, arg1, arg2, arg3); } - app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } - app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } - app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_DIV, arg1, arg2, arg3); } - app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_NEG, arg1); } - app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); } - app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); } - app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); } - app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); } - app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); } - app * mk_round_to_integral(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); } + app * mk_add(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_ADD, arg1, arg2, arg3); } + app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_MUL, arg1, arg2, arg3); } + app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_SUB, arg1, arg2, arg3); } + app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_DIV, arg1, arg2, arg3); } + app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FPA_NEG, arg1); } + app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_REM, arg1, arg2); } + app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_MAX, arg1, arg2); } + app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_MIN, arg1, arg2); } + app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FPA_ABS, arg1); } + app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_SQRT, arg1, arg2); } + app * mk_round_to_integral(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_ROUND_TO_INTEGRAL, arg1, arg2); } app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) { expr * args[4] = { arg1, arg2, arg3, arg4 }; - return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args); + return m().mk_app(m_fid, OP_FPA_FMA, 4, args); } - app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_EQ, arg1, arg2); } - app * mk_lt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LT, arg1, arg2); } - app * mk_gt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GT, arg1, arg2); } - app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); } - app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); } + app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_EQ, arg1, arg2); } + app * mk_lt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_LT, arg1, arg2); } + app * mk_gt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_GT, arg1, arg2); } + app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_LE, arg1, arg2); } + app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FPA_GE, arg1, arg2); } - app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); } - app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); } - app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); } - app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); } - app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); } - app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); } - app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); } - app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } - app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_POSITIVE, arg1); } - app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } + app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NAN, arg1); } + app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_INF, arg1); } + app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_ZERO, arg1); } + app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NORMAL, arg1); } + app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_SUBNORMAL, arg1); } + app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NZERO, arg1); } + app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_PZERO, arg1); } + app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } + app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_POSITIVE, arg1); } + app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } - bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } + bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FPA_NEG); } - app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } + app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FPA_TO_IEEE_BV, arg1); } app * mk_internal_to_ubv_unspecified(unsigned width); app * mk_internal_to_sbv_unspecified(unsigned width); app * mk_internal_to_real_unspecified(); - bool is_wrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FLOAT_INTERNAL_BVWRAP); } - bool is_unwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP); } + bool is_wrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); } + bool is_unwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVUNWRAP); } }; #endif diff --git a/src/ast/reg_decl_plugins.cpp b/src/ast/reg_decl_plugins.cpp index ab1844e07..f46dd76d4 100644 --- a/src/ast/reg_decl_plugins.cpp +++ b/src/ast/reg_decl_plugins.cpp @@ -24,7 +24,7 @@ Revision History: #include"datatype_decl_plugin.h" #include"dl_decl_plugin.h" #include"seq_decl_plugin.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" void reg_decl_plugins(ast_manager & m) { if (!m.get_plugin(m.mk_family_id(symbol("arith")))) { @@ -45,7 +45,7 @@ void reg_decl_plugins(ast_manager & m) { if (!m.get_plugin(m.mk_family_id(symbol("seq")))) { m.register_plugin(symbol("seq"), alloc(seq_decl_plugin)); } - if (!m.get_plugin(m.mk_family_id(symbol("float")))) { - m.register_plugin(symbol("float"), alloc(float_decl_plugin)); + if (!m.get_plugin(m.mk_family_id(symbol("fpa")))) { + m.register_plugin(symbol("fpa"), alloc(fpa_decl_plugin)); } } diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp similarity index 69% rename from src/ast/rewriter/float_rewriter.cpp rename to src/ast/rewriter/fpa_rewriter.cpp index 96561395e..2977b7ab2 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - float_rewriter.cpp + fpa_rewriter.cpp Abstract: @@ -16,65 +16,65 @@ Author: Notes: --*/ -#include"float_rewriter.h" +#include"fpa_rewriter.h" -float_rewriter::float_rewriter(ast_manager & m, params_ref const & p): +fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p): m_util(m) { updt_params(p); } -float_rewriter::~float_rewriter() { +fpa_rewriter::~fpa_rewriter() { } -void float_rewriter::updt_params(params_ref const & p) { +void fpa_rewriter::updt_params(params_ref const & p) { } -void float_rewriter::get_param_descrs(param_descrs & r) { +void fpa_rewriter::get_param_descrs(param_descrs & r) { } -br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { - case OP_FLOAT_TO_FP: st = mk_to_fp(f, num_args, args, result); break; - case OP_FLOAT_TO_FP_UNSIGNED: st = mk_to_fp_unsigned(f, num_args, args, result); break; - case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; - case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; - case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; - case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; - case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; - case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; - case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; - case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; - case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; - case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; - case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; - case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break; + case OP_FPA_TO_FP: st = mk_to_fp(f, num_args, args, result); break; + case OP_FPA_TO_FP_UNSIGNED: st = mk_to_fp_unsigned(f, num_args, args, result); break; + case OP_FPA_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; + case OP_FPA_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; + case OP_FPA_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; + case OP_FPA_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; + case OP_FPA_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; + case OP_FPA_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; + case OP_FPA_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; + case OP_FPA_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; + case OP_FPA_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; + case OP_FPA_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; + case OP_FPA_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; + case OP_FPA_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break; - case OP_FLOAT_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break; - case OP_FLOAT_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break; - case OP_FLOAT_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break; - case OP_FLOAT_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break; - case OP_FLOAT_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break; - case OP_FLOAT_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break; - case OP_FLOAT_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break; - case OP_FLOAT_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break; - case OP_FLOAT_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break; - case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; - case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; - case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; - case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; - case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; - case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; - case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; - case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; - case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; - case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + case OP_FPA_EQ: SASSERT(num_args == 2); st = mk_float_eq(args[0], args[1], result); break; + case OP_FPA_LT: SASSERT(num_args == 2); st = mk_lt(args[0], args[1], result); break; + case OP_FPA_GT: SASSERT(num_args == 2); st = mk_gt(args[0], args[1], result); break; + case OP_FPA_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break; + case OP_FPA_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break; + case OP_FPA_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break; + case OP_FPA_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break; + case OP_FPA_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break; + case OP_FPA_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break; + case OP_FPA_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; + case OP_FPA_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; + case OP_FPA_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; + case OP_FPA_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; + case OP_FPA_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; + case OP_FPA_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; + case OP_FPA_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; + case OP_FPA_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; + case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; + case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; } return st; } -br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); SASSERT(f->get_parameter(1).is_int()); @@ -159,7 +159,7 @@ br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * cons return BR_FAILED; } -br_status float_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); SASSERT(f->get_parameter(1).is_int()); @@ -169,7 +169,7 @@ br_status float_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, ex return BR_FAILED; } -br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { +br_status fpa_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); @@ -184,13 +184,13 @@ br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { +br_status fpa_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { // a - b = a + (-b) result = m_util.mk_add(arg1, arg2, m_util.mk_neg(arg3)); return BR_REWRITE2; } -br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { +br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); @@ -205,7 +205,7 @@ br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { +br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); @@ -220,7 +220,7 @@ br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) { if (m_util.is_nan(arg1)) { // -nan --> nan result = arg1; @@ -253,7 +253,7 @@ br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { scoped_mpf t(m_util.fm()); @@ -265,7 +265,7 @@ br_status float_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_abs(expr * arg1, expr_ref & result) { if (m_util.is_nan(arg1)) { result = arg1; return BR_DONE; @@ -276,7 +276,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) { return BR_REWRITE2; } -br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) { if (m_util.is_nan(arg1)) { result = arg2; return BR_DONE; @@ -296,7 +296,7 @@ br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) { return BR_REWRITE_FULL; } -br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { if (m_util.is_nan(arg1)) { result = arg2; return BR_DONE; @@ -316,7 +316,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { return BR_REWRITE_FULL; } -br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { +br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm()); @@ -331,7 +331,7 @@ br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * a return BR_FAILED; } -br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()); @@ -346,7 +346,7 @@ br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()); @@ -362,7 +362,7 @@ br_status float_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) } // This the floating point theory == -br_status float_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { result = (m_util.fm().eq(v1, v2)) ? m().mk_true() : m().mk_false(); @@ -373,16 +373,16 @@ br_status float_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & resul } // Return (= arg NaN) -app * float_rewriter::mk_eq_nan(expr * arg) { +app * fpa_rewriter::mk_eq_nan(expr * arg) { return m().mk_eq(arg, m_util.mk_nan(m().get_sort(arg))); } // Return (not (= arg NaN)) -app * float_rewriter::mk_neq_nan(expr * arg) { +app * fpa_rewriter::mk_neq_nan(expr * arg) { return m().mk_not(mk_eq_nan(arg)); } -br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) { result = m().mk_false(); return BR_DONE; @@ -418,12 +418,12 @@ br_status float_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_gt(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_gt(expr * arg1, expr * arg2, expr_ref & result) { result = m_util.mk_lt(arg2, arg1); return BR_REWRITE1; } -br_status float_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) { if (m_util.is_nan(arg1) || m_util.is_nan(arg2)) { result = m().mk_false(); return BR_DONE; @@ -437,12 +437,12 @@ br_status float_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) { result = m_util.mk_le(arg2, arg1); return BR_REWRITE1; } -br_status float_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_zero(v)) ? m().mk_true() : m().mk_false(); @@ -452,7 +452,7 @@ br_status float_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_nzero(v)) ? m().mk_true() : m().mk_false(); @@ -462,7 +462,7 @@ br_status float_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_pzero(v)) ? m().mk_true() : m().mk_false(); @@ -472,7 +472,7 @@ br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false(); @@ -482,7 +482,7 @@ br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false(); @@ -492,7 +492,7 @@ br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false(); @@ -502,7 +502,7 @@ br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false(); @@ -512,7 +512,7 @@ br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false(); @@ -522,7 +522,7 @@ br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true(); @@ -534,7 +534,7 @@ br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { // This the SMT = -br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { // Note: == is the floats-equality, here we need normal equality. @@ -548,11 +548,11 @@ br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result return BR_FAILED; } -br_status float_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { +br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { bv_util bu(m()); rational r1, r2, r3; unsigned bvs1, bvs2, bvs3; @@ -575,15 +575,15 @@ br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) { +br_status fpa_rewriter::mk_to_real(expr * arg1, expr_ref & result) { scoped_mpf fv(m_util.fm()); if (m_util.is_value(arg1, fv)) { @@ -599,4 +599,4 @@ br_status float_rewriter::mk_to_real(expr * arg1, expr_ref & result) { } return BR_FAILED; -} \ No newline at end of file +} diff --git a/src/ast/rewriter/float_rewriter.h b/src/ast/rewriter/fpa_rewriter.h similarity index 95% rename from src/ast/rewriter/float_rewriter.h rename to src/ast/rewriter/fpa_rewriter.h index 31c571f32..34a34b293 100644 --- a/src/ast/rewriter/float_rewriter.h +++ b/src/ast/rewriter/fpa_rewriter.h @@ -22,10 +22,10 @@ Notes: #include"ast.h" #include"rewriter.h" #include"params.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"mpf.h" -class float_rewriter { +class fpa_rewriter { float_util m_util; mpf_manager m_fm; @@ -33,8 +33,8 @@ class float_rewriter { app * mk_neq_nan(expr * arg); public: - float_rewriter(ast_manager & m, params_ref const & p = params_ref()); - ~float_rewriter(); + fpa_rewriter(ast_manager & m, params_ref const & p = params_ref()); + ~fpa_rewriter(); ast_manager & m() const { return m_util.m(); } family_id get_fid() const { return m_util.get_fid(); } diff --git a/src/ast/rewriter/mk_simplified_app.cpp b/src/ast/rewriter/mk_simplified_app.cpp index a46e71582..45245ce1b 100644 --- a/src/ast/rewriter/mk_simplified_app.cpp +++ b/src/ast/rewriter/mk_simplified_app.cpp @@ -22,7 +22,7 @@ Notes: #include"bv_rewriter.h" #include"datatype_rewriter.h" #include"array_rewriter.h" -#include"float_rewriter.h" +#include"fpa_rewriter.h" struct mk_simplified_app::imp { ast_manager & m; @@ -31,7 +31,7 @@ struct mk_simplified_app::imp { bv_rewriter m_bv_rw; array_rewriter m_ar_rw; datatype_rewriter m_dt_rw; - float_rewriter m_f_rw; + fpa_rewriter m_f_rw; imp(ast_manager & _m, params_ref const & p): m(_m), diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 0e2c8e781..f35c3b134 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -23,7 +23,7 @@ Notes: #include"bv_rewriter.h" #include"datatype_rewriter.h" #include"array_rewriter.h" -#include"float_rewriter.h" +#include"fpa_rewriter.h" #include"dl_rewriter.h" #include"rewriter_def.h" #include"expr_substitution.h" @@ -39,7 +39,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { bv_rewriter m_bv_rw; array_rewriter m_ar_rw; datatype_rewriter m_dt_rw; - float_rewriter m_f_rw; + fpa_rewriter m_f_rw; dl_rewriter m_dl_rw; arith_util m_a_util; bv_util m_bv_util; diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 4dd0cc614..d5ee9ff88 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -24,7 +24,7 @@ Notes: #include"array_decl_plugin.h" #include"datatype_decl_plugin.h" #include"seq_decl_plugin.h" -#include"float_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"ast_pp.h" #include"var_subst.h" #include"pp.h" @@ -556,7 +556,7 @@ bool cmd_context::logic_has_seq() const { return !has_logic() || logic_has_seq_core(m_logic); } -bool cmd_context::logic_has_floats() const { +bool cmd_context::logic_has_fpa() const { return !has_logic() || m_logic == "QF_FP" || m_logic == "QF_FPBV"; } @@ -601,7 +601,7 @@ void cmd_context::init_manager_core(bool new_manager) { register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype()); register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq()); - register_plugin(symbol("float"), alloc(float_decl_plugin), logic_has_floats()); + register_plugin(symbol("fpa"), alloc(fpa_decl_plugin), logic_has_fpa()); } else { // the manager was created by an external module @@ -614,7 +614,7 @@ void cmd_context::init_manager_core(bool new_manager) { load_plugin(symbol("array"), logic_has_array(), fids); load_plugin(symbol("datatype"), logic_has_datatype(), fids); load_plugin(symbol("seq"), logic_has_seq(), fids); - load_plugin(symbol("float"), logic_has_floats(), fids); + load_plugin(symbol("fpa"), logic_has_fpa(), fids); svector::iterator it = fids.begin(); svector::iterator end = fids.end(); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 1c8dba21a..f9e50e611 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -241,7 +241,7 @@ protected: bool logic_has_seq() const; bool logic_has_array() const; bool logic_has_datatype() const; - bool logic_has_floats() const; + bool logic_has_fpa() const; bool supported_logic(symbol const & s) const; void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; } diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index 41bca940d..02c43eaad 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -25,7 +25,7 @@ Revision History: #include"bv_rewriter.h" #include"datatype_rewriter.h" #include"array_rewriter.h" -#include"float_rewriter.h" +#include"fpa_rewriter.h" #include"rewriter_def.h" #include"cooperate.h" @@ -36,7 +36,7 @@ struct evaluator_cfg : public default_rewriter_cfg { bv_rewriter m_bv_rw; array_rewriter m_ar_rw; datatype_rewriter m_dt_rw; - float_rewriter m_f_rw; + fpa_rewriter m_f_rw; unsigned long long m_max_memory; unsigned m_max_steps; bool m_model_completion; diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index bec9cf235..7c4fce5cd 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -82,7 +82,7 @@ namespace smt { } theory_fpa::theory_fpa(ast_manager & m) : - theory(m.mk_family_id("float")), + theory(m.mk_family_id("fpa")), m_converter(m, this), m_rw(m, m_converter, params_ref()), m_th_rw(m), @@ -91,6 +91,9 @@ namespace smt { m_bv_util(m_converter.bu()), m_arith_util(m_converter.au()) { + params_ref p; + p.set_bool("arith_lhs", true); + m_th_rw.updt_params(p); } theory_fpa::~theory_fpa() @@ -207,7 +210,7 @@ namespace smt { bv_srt = m_bv_util.mk_sort(ebits + sbits); } - w = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt); + w = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt); m_wraps.insert(e_srt, w); m.inc_ref(w); } @@ -226,7 +229,7 @@ namespace smt { if (!m_unwraps.find(e_srt, u)) { SASSERT(!m_unwraps.contains(e_srt)); sort * bv_srt = m.get_sort(e); - u = m.mk_func_decl(get_family_id(), OP_FLOAT_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); + u = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); m_unwraps.insert(s, u); m.inc_ref(u); } @@ -268,10 +271,10 @@ namespace smt { } else if (m_float_util.is_float(e)) { SASSERT(eca->get_family_id() == get_family_id()); - float_op_kind k = (float_op_kind)(eca->get_decl_kind()); - SASSERT(k == OP_FLOAT_TO_FP || k == OP_FLOAT_INTERNAL_BVUNWRAP); + fpa_op_kind k = (fpa_op_kind)(eca->get_decl_kind()); + SASSERT(k == OP_FPA_TO_FP || k == OP_FPA_INTERNAL_BVUNWRAP); switch (k) { - case OP_FLOAT_TO_FP: { + case OP_FPA_TO_FP: { SASSERT(eca->get_num_args() == 3); SASSERT(is_sort_of(m.get_sort(eca->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); SASSERT(is_sort_of(m.get_sort(eca->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); @@ -388,6 +391,8 @@ namespace smt { res = m.mk_and(res, t); } m_converter.m_extra_assertions.reset(); + + m_th_rw(res); CTRACE("t_fpa", !m.is_true(res), tout << "side condition: " << mk_ismt2_pp(res, m) << "\n";); return res; @@ -460,11 +465,11 @@ namespace smt { // The corresponding constraints will not be translated and added // via convert(...) and assert_cnstr(...) in initialize_atom(...). // Therefore, we translate and assert them here. - float_op_kind k = (float_op_kind)term->get_decl_kind(); + fpa_op_kind k = (fpa_op_kind)term->get_decl_kind(); switch (k) { - case OP_FLOAT_TO_UBV: - case OP_FLOAT_TO_SBV: - case OP_FLOAT_TO_REAL: { + case OP_FPA_TO_UBV: + case OP_FPA_TO_SBV: + case OP_FPA_TO_REAL: { expr_ref conv(m); conv = convert(term); assert_cnstr(m.mk_eq(term, conv)); @@ -546,7 +551,7 @@ namespace smt { c = m.mk_and(m.mk_eq(x_sgn, y_sgn), m.mk_eq(x_sig, y_sig), - m.mk_eq(x_exp, y_exp)); + m.mk_eq(x_exp, y_exp)); } else c = m.mk_eq(xc, yc); diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 989ad64ff..78ba64111 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -116,7 +116,7 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { bv_mdl->eval(a->get_arg(1), exp, true); bv_mdl->eval(a->get_arg(2), sig, true); - SASSERT(a->is_app_of(fu.get_family_id(), OP_FLOAT_TO_FP)); + SASSERT(a->is_app_of(fu.get_family_id(), OP_FPA_TO_FP)); #ifdef Z3DEBUG SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffpa_tactic.cpp index 919cf0c1b..c02166c18 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffpa_tactic.cpp @@ -26,21 +26,23 @@ Notes: #include"qffpa_tactic.h" tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { - params_ref sat_simp_p = p; - sat_simp_p .set_bool("elim_and", true); + params_ref simp_p = p; + simp_p.set_bool("arith_lhs", true); + simp_p.set_bool("elim_and", true); - tactic * st = - cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), - and_then(mk_simplify_tactic(m), - mk_smt_tactic()), - and_then( - mk_simplify_tactic(m, p), - mk_fpa2bv_tactic(m, p), - using_params(mk_simplify_tactic(m, p), sat_simp_p), - mk_bit_blaster_tactic(m, p), - using_params(mk_simplify_tactic(m, p), sat_simp_p), - mk_sat_tactic(m, p), - mk_fail_if_undecided_tactic())); + tactic * st = cond( mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), + and_then(mk_simplify_tactic(m, simp_p), + mk_smt_tactic()), + and_then( + mk_simplify_tactic(m, p), + mk_fpa2bv_tactic(m, p), + using_params(mk_simplify_tactic(m, p), simp_p), + mk_bit_blaster_tactic(m, p), + using_params(mk_simplify_tactic(m, p), simp_p), + cond(mk_is_propositional_probe(), + mk_sat_tactic(m, p), + mk_smt_tactic(p)), + mk_fail_if_undecided_tactic())); st->updt_params(p); return st; @@ -70,6 +72,8 @@ struct is_non_qffp_predicate { return; if (is_uninterp_const(n)) return; + if (au.is_real(s) && au.is_numeral(n)) + return; throw found(); } diff --git a/src/tactic/fpa/qffpa_tactic.h b/src/tactic/fpa/qffpa_tactic.h index 660622fb8..3ab95798f 100644 --- a/src/tactic/fpa/qffpa_tactic.h +++ b/src/tactic/fpa/qffpa_tactic.h @@ -3,11 +3,11 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - qffpa_tactic.h + qffp_tactic.h Abstract: - Tactic QF_FPA benchmarks. + Tactic for QF_FP benchmarks. Author: From 5e5758bb25e080cb45ae0bd7c6e0a3593e1f6606 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 13:37:18 +0000 Subject: [PATCH 152/646] More float -> fpa renaming Signed-off-by: Christoph M. Wintersteiger --- src/api/api_context.cpp | 2 +- src/api/api_context.h | 4 +- src/api/api_fpa.cpp | 146 +++++++++--------- src/api/api_numeral.cpp | 10 +- src/ast/ast_smt2_pp.h | 6 +- src/ast/fpa_decl_plugin.cpp | 26 ++-- src/ast/fpa_decl_plugin.h | 6 +- src/ast/rewriter/fpa_rewriter.h | 2 +- src/cmd_context/cmd_context.cpp | 4 +- src/smt/theory_fpa.cpp | 68 ++++---- src/smt/theory_fpa.h | 14 +- src/tactic/fpa/fpa2bv_model_converter.cpp | 2 +- .../fpa/{qffpa_tactic.cpp => qffp_tactic.cpp} | 8 +- .../fpa/{qffpa_tactic.h => qffp_tactic.h} | 8 +- src/tactic/portfolio/default_tactic.cpp | 2 +- src/tactic/portfolio/smt_strategic_solver.cpp | 6 +- 16 files changed, 158 insertions(+), 156 deletions(-) rename src/tactic/fpa/{qffpa_tactic.cpp => qffp_tactic.cpp} (96%) rename src/tactic/fpa/{qffpa_tactic.h => qffp_tactic.h} (82%) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index b83b72e35..3408cdf3c 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -88,7 +88,7 @@ namespace api { m_arith_util(m()), m_bv_util(m()), m_datalog_util(m()), - m_float_util(m()), + m_fpa_util(m()), m_last_result(m()), m_ast_trail(m()), m_replay_stack() { diff --git a/src/api/api_context.h b/src/api/api_context.h index c71b88b61..6312b3f69 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -57,7 +57,7 @@ namespace api { arith_util m_arith_util; bv_util m_bv_util; datalog::dl_decl_util m_datalog_util; - float_util m_float_util; + fpa_util m_fpa_util; // Support for old solver API smt_params m_fparams; @@ -118,7 +118,7 @@ namespace api { arith_util & autil() { return m_arith_util; } bv_util & bvutil() { return m_bv_util; } datalog::dl_decl_util & datalog_util() { return m_datalog_util; } - float_util & float_util() { return m_float_util; } + fpa_util & fpa_util() { return m_fpa_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; } diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 0f0f68ae1..94dfaaa68 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -29,7 +29,7 @@ extern "C" { LOG_Z3_mk_fpa_rounding_mode_sort(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->float_util().mk_rm_sort()); + Z3_sort r = of_sort(ctx->fpa_util().mk_rm_sort()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -40,7 +40,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_even()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -50,7 +50,7 @@ extern "C" { LOG_Z3_mk_fpa_rne(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_even()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -61,7 +61,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_away(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_away()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -71,7 +71,7 @@ extern "C" { LOG_Z3_mk_fpa_rna(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_nearest_ties_to_away()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -82,7 +82,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_positive(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -92,7 +92,7 @@ extern "C" { LOG_Z3_mk_fpa_rtp(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_positive()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -103,7 +103,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_negative(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -113,7 +113,7 @@ extern "C" { LOG_Z3_mk_fpa_rtn(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_negative()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -124,7 +124,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_zero(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -134,7 +134,7 @@ extern "C" { LOG_Z3_mk_fpa_rtz(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_toward_zero()); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -148,7 +148,7 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); } api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->float_util().mk_float_sort(ebits, sbits)); + Z3_sort r = of_sort(ctx->fpa_util().mk_float_sort(ebits, sbits)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -190,7 +190,7 @@ extern "C" { LOG_Z3_mk_fpa_nan(c, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_nan(to_sort(s))); + Z3_ast r = of_ast(ctx->fpa_util().mk_nan(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -200,7 +200,7 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_ninf(to_sort(s)) : ctx->float_util().mk_pinf(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_ninf(to_sort(s)) : ctx->fpa_util().mk_pinf(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -210,7 +210,7 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->float_util().mk_nzero(to_sort(s)) : ctx->float_util().mk_pzero(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_nzero(to_sort(s)) : ctx->fpa_util().mk_pzero(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -220,7 +220,7 @@ extern "C" { LOG_Z3_mk_fpa_fp(c, sgn, sig, exp); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); + Z3_ast r = of_ast(ctx->fpa_util().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -230,9 +230,9 @@ extern "C" { LOG_Z3_mk_fpa_numeral_float(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->float_util().fm()); - ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + scoped_mpf tmp(ctx->fpa_util().fm()); + ctx->fpa_util().fm().set(tmp, ctx->fpa_util().get_ebits(to_sort(ty)), ctx->fpa_util().get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -242,9 +242,9 @@ extern "C" { LOG_Z3_mk_fpa_numeral_double(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->float_util().fm()); - ctx->float_util().fm().set(tmp, ctx->float_util().get_ebits(to_sort(ty)), ctx->float_util().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + scoped_mpf tmp(ctx->fpa_util().fm()); + ctx->fpa_util().fm().set(tmp, ctx->fpa_util().get_ebits(to_sort(ty)), ctx->fpa_util().get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -254,12 +254,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_int(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->float_util().fm()); - ctx->float_util().fm().set(tmp, - ctx->float_util().get_ebits(to_sort(ty)), - ctx->float_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpa_util().fm()); + ctx->fpa_util().fm().set(tmp, + ctx->fpa_util().get_ebits(to_sort(ty)), + ctx->fpa_util().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -269,12 +269,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->float_util().fm()); - ctx->float_util().fm().set(tmp, - ctx->float_util().get_ebits(to_sort(ty)), - ctx->float_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpa_util().fm()); + ctx->fpa_util().fm().set(tmp, + ctx->fpa_util().get_ebits(to_sort(ty)), + ctx->fpa_util().get_sbits(to_sort(ty)), sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -284,12 +284,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->float_util().fm()); - ctx->float_util().fm().set(tmp, - ctx->float_util().get_ebits(to_sort(ty)), - ctx->float_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpa_util().fm()); + ctx->fpa_util().fm().set(tmp, + ctx->fpa_util().get_ebits(to_sort(ty)), + ctx->fpa_util().get_sbits(to_sort(ty)), sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->float_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -299,7 +299,7 @@ extern "C" { LOG_Z3_mk_fpa_abs(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_abs(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_abs(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -309,7 +309,7 @@ extern "C" { LOG_Z3_mk_fpa_neg(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_neg(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_neg(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -319,7 +319,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -329,7 +329,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -339,7 +339,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -349,7 +349,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -359,7 +359,7 @@ extern "C" { LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); + Z3_ast r = of_ast(ctx->fpa_util().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -369,7 +369,7 @@ extern "C" { LOG_Z3_mk_fpa_sqrt(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_sqrt(to_expr(rm), to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_sqrt(to_expr(rm), to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -379,7 +379,7 @@ extern "C" { LOG_Z3_mk_fpa_rem(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_rem(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_rem(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -389,7 +389,7 @@ extern "C" { LOG_Z3_mk_fpa_round_to_integral(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_round_to_integral(to_expr(rm), to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_round_to_integral(to_expr(rm), to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -399,7 +399,7 @@ extern "C" { LOG_Z3_mk_fpa_min(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_min(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_min(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -409,7 +409,7 @@ extern "C" { LOG_Z3_mk_fpa_max(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_max(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_max(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -419,7 +419,7 @@ extern "C" { LOG_Z3_mk_fpa_leq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_le(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_le(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -429,7 +429,7 @@ extern "C" { LOG_Z3_mk_fpa_lt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_lt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_lt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -439,7 +439,7 @@ extern "C" { LOG_Z3_mk_fpa_geq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_ge(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_ge(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -449,7 +449,7 @@ extern "C" { LOG_Z3_mk_fpa_gt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_gt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_gt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -459,7 +459,7 @@ extern "C" { LOG_Z3_mk_fpa_eq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_float_eq(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpa_util().mk_float_eq(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -469,7 +469,7 @@ extern "C" { LOG_Z3_mk_fpa_is_normal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_normal(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_normal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -479,7 +479,7 @@ extern "C" { LOG_Z3_mk_fpa_is_subnormal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_subnormal(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_subnormal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -489,7 +489,7 @@ extern "C" { LOG_Z3_mk_fpa_is_zero(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_zero(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_zero(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -499,7 +499,7 @@ extern "C" { LOG_Z3_mk_fpa_is_infinite(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_inf(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_inf(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -509,7 +509,7 @@ extern "C" { LOG_Z3_mk_fpa_is_nan(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_nan(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_nan(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -519,7 +519,7 @@ extern "C" { LOG_Z3_mk_fpa_is_negative(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_negative(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_negative(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -529,7 +529,7 @@ extern "C" { LOG_Z3_mk_fpa_is_positive(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_is_positive(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_is_positive(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -540,7 +540,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_bv(c, bv, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!ctx->bvutil().is_bv(to_expr(bv)) || !fu.is_float(to_sort(s))) { SET_ERROR_CODE(Z3_INVALID_ARG); @@ -556,7 +556,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_float(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!fu.is_rm(to_expr(rm)) || !fu.is_float(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -573,7 +573,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_real(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!fu.is_rm(to_expr(rm)) || !ctx->autil().is_real(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -590,7 +590,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_signed(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!fu.is_rm(to_expr(rm)) || !ctx->bvutil().is_bv(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -607,7 +607,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_unsigned(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!fu.is_rm(to_expr(rm)) || !ctx->bvutil().is_bv(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -624,7 +624,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ubv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_to_ubv(to_expr(rm), to_expr(t), sz)); + Z3_ast r = of_ast(ctx->fpa_util().mk_to_ubv(to_expr(rm), to_expr(t), sz)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -634,7 +634,7 @@ extern "C" { LOG_Z3_mk_fpa_to_sbv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_to_sbv(to_expr(rm), to_expr(t), sz)); + Z3_ast r = of_ast(ctx->fpa_util().mk_to_sbv(to_expr(rm), to_expr(t), sz)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -644,7 +644,7 @@ extern "C" { LOG_Z3_mk_fpa_to_real(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_to_real(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_to_real(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -654,7 +654,7 @@ extern "C" { LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); CHECK_NON_NULL(s, 0); - return mk_c(c)->float_util().get_ebits(to_sort(s)); + return mk_c(c)->fpa_util().get_ebits(to_sort(s)); Z3_CATCH_RETURN(0); } @@ -663,7 +663,7 @@ extern "C" { LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); CHECK_NON_NULL(s, 0); - return mk_c(c)->float_util().get_sbits(to_sort(s)); + return mk_c(c)->fpa_util().get_sbits(to_sort(s)); Z3_CATCH_RETURN(0); } @@ -672,7 +672,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ieee_bv(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->float_util().mk_float_to_ieee_bv(to_expr(t))); + Z3_ast r = of_ast(ctx->fpa_util().mk_float_to_ieee_bv(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -682,7 +682,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_real_int(c, rm, sig, exp, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - float_util & fu = ctx->float_util(); + fpa_util & fu = ctx->fpa_util(); if (!fu.is_rm(to_expr(rm)) || !ctx->autil().is_real(to_expr(sig)) || !ctx->autil().is_int(to_expr(exp)) || diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 17a743880..89f01707e 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -59,7 +59,7 @@ extern "C" { RETURN_Z3(0); } sort * _ty = to_sort(ty); - bool is_float = mk_c(c)->float_util().is_float(_ty); + bool is_float = mk_c(c)->fpa_util().is_float(_ty); std::string fixed_num; char const* m = n; while (*m) { @@ -79,7 +79,7 @@ extern "C" { if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) { // avoid expanding floats into huge rationals. - float_util & fu = mk_c(c)->float_util(); + fpa_util & fu = mk_c(c)->fpa_util(); scoped_mpf t(fu.fm()); fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n); a = fu.mk_value(t); @@ -149,7 +149,7 @@ extern "C" { return mk_c(c)->autil().is_numeral(e) || mk_c(c)->bvutil().is_numeral(e) || - mk_c(c)->float_util().is_value(e); + mk_c(c)->fpa_util().is_value(e); Z3_CATCH_RETURN(Z3_FALSE); } @@ -191,9 +191,9 @@ extern "C" { } else { // floats are separated from all others to avoid huge rationals. - float_util & fu = mk_c(c)->float_util(); + fpa_util & fu = mk_c(c)->fpa_util(); scoped_mpf tmp(fu.fm()); - if (mk_c(c)->float_util().is_value(to_expr(a), tmp)) { + if (mk_c(c)->fpa_util().is_value(to_expr(a), tmp)) { return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); } else { diff --git a/src/ast/ast_smt2_pp.h b/src/ast/ast_smt2_pp.h index bc62448c7..8aac71b8c 100644 --- a/src/ast/ast_smt2_pp.h +++ b/src/ast/ast_smt2_pp.h @@ -46,7 +46,7 @@ public: virtual arith_util & get_autil() = 0; virtual bv_util & get_bvutil() = 0; virtual array_util & get_arutil() = 0; - virtual float_util & get_futil() = 0; + virtual fpa_util & get_futil() = 0; virtual datalog::dl_decl_util& get_dlutil() = 0; virtual bool uses(symbol const & s) const = 0; virtual format_ns::format * pp_fdecl(func_decl * f, unsigned & len); @@ -69,7 +69,7 @@ class smt2_pp_environment_dbg : public smt2_pp_environment { arith_util m_autil; bv_util m_bvutil; array_util m_arutil; - float_util m_futil; + fpa_util m_futil; datalog::dl_decl_util m_dlutil; public: smt2_pp_environment_dbg(ast_manager & m):m_manager(m), m_autil(m), m_bvutil(m), m_arutil(m), m_futil(m), m_dlutil(m) {} @@ -77,7 +77,7 @@ public: virtual arith_util & get_autil() { return m_autil; } virtual bv_util & get_bvutil() { return m_bvutil; } virtual array_util & get_arutil() { return m_arutil; } - virtual float_util & get_futil() { return m_futil; } + virtual fpa_util & get_futil() { return m_futil; } virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; } virtual bool uses(symbol const & s) const { return false; } }; diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index be3e5f3ec..90bbd4901 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -906,7 +906,7 @@ bool fpa_decl_plugin::is_unique_value(app* e) const { } } -float_util::float_util(ast_manager & m): +fpa_util::fpa_util(ast_manager & m): m_manager(m), m_fid(m.mk_family_id("fpa")), m_a_util(m), @@ -914,67 +914,67 @@ float_util::float_util(ast_manager & m): m_plugin = static_cast(m.get_plugin(m_fid)); } -float_util::~float_util() { +fpa_util::~fpa_util() { } -sort * float_util::mk_float_sort(unsigned ebits, unsigned sbits) { +sort * fpa_util::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { parameter(ebits), parameter(sbits) }; return m().mk_sort(m_fid, FLOATING_POINT_SORT, 2, ps); } -unsigned float_util::get_ebits(sort * s) { +unsigned fpa_util::get_ebits(sort * s) { SASSERT(is_float(s)); return static_cast(s->get_parameter(0).get_int()); } -unsigned float_util::get_sbits(sort * s) { +unsigned fpa_util::get_sbits(sort * s) { SASSERT(is_float(s)); return static_cast(s->get_parameter(1).get_int()); } -app * float_util::mk_nan(unsigned ebits, unsigned sbits) { +app * fpa_util::mk_nan(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_nan(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_pinf(unsigned ebits, unsigned sbits) { +app * fpa_util::mk_pinf(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_pinf(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_ninf(unsigned ebits, unsigned sbits) { +app * fpa_util::mk_ninf(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_ninf(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_pzero(unsigned ebits, unsigned sbits) { +app * fpa_util::mk_pzero(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_pzero(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_nzero(unsigned ebits, unsigned sbits) { +app * fpa_util::mk_nzero(unsigned ebits, unsigned sbits) { scoped_mpf v(fm()); fm().mk_nzero(ebits, sbits, v); return mk_value(v); } -app * float_util::mk_internal_to_ubv_unspecified(unsigned width) { +app * fpa_util::mk_internal_to_ubv_unspecified(unsigned width) { parameter ps[] = { parameter(width) }; sort * range = m_bv_util.mk_sort(width); return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, 1, ps, 0, 0, range); } -app * float_util::mk_internal_to_sbv_unspecified(unsigned width) { +app * fpa_util::mk_internal_to_sbv_unspecified(unsigned width) { parameter ps[] = { parameter(width) }; sort * range = m_bv_util.mk_sort(width); return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range); } -app * float_util::mk_internal_to_real_unspecified() { +app * fpa_util::mk_internal_to_real_unspecified() { sort * range = m_a_util.mk_real(); return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, 0, 0, 0, 0, range); } \ No newline at end of file diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index b7d59a6af..b8d0c0c3e 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -207,15 +207,15 @@ public: virtual parameter translate(parameter const & p, decl_plugin & target); }; -class float_util { +class fpa_util { ast_manager & m_manager; fpa_decl_plugin * m_plugin; family_id m_fid; arith_util m_a_util; bv_util m_bv_util; public: - float_util(ast_manager & m); - ~float_util(); + fpa_util(ast_manager & m); + ~fpa_util(); ast_manager & m() const { return m_manager; } mpf_manager & fm() const { return m_plugin->fm(); } diff --git a/src/ast/rewriter/fpa_rewriter.h b/src/ast/rewriter/fpa_rewriter.h index 34a34b293..a10df95ca 100644 --- a/src/ast/rewriter/fpa_rewriter.h +++ b/src/ast/rewriter/fpa_rewriter.h @@ -26,7 +26,7 @@ Notes: #include"mpf.h" class fpa_rewriter { - float_util m_util; + fpa_util m_util; mpf_manager m_fm; app * mk_eq_nan(expr * arg); diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index d5ee9ff88..f5937955d 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -240,7 +240,7 @@ protected: arith_util m_autil; bv_util m_bvutil; array_util m_arutil; - float_util m_futil; + fpa_util m_futil; datalog::dl_decl_util m_dlutil; format_ns::format * pp_fdecl_name(symbol const & s, func_decls const & fs, func_decl * f, unsigned & len) { @@ -267,7 +267,7 @@ public: virtual arith_util & get_autil() { return m_autil; } virtual bv_util & get_bvutil() { return m_bvutil; } virtual array_util & get_arutil() { return m_arutil; } - virtual float_util & get_futil() { return m_futil; } + virtual fpa_util & get_futil() { return m_futil; } virtual datalog::dl_decl_util& get_dlutil() { return m_dlutil; } virtual bool uses(symbol const & s) const { return diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 7c4fce5cd..055f79b9d 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -51,8 +51,8 @@ namespace smt { expr_ref bv(m); bv = m_th.wrap(m.mk_const(f)); unsigned bv_sz = m_th.m_bv_util.get_bv_size(bv); - unsigned ebits = m_th.m_float_util.get_ebits(s); - unsigned sbits = m_th.m_float_util.get_sbits(s); + unsigned ebits = m_th.m_fpa_util.get_ebits(s); + unsigned sbits = m_th.m_fpa_util.get_sbits(s); SASSERT(bv_sz == ebits + sbits); m_th.m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), m_bv_util.mk_extract(sbits - 2, 0, bv), @@ -87,7 +87,7 @@ namespace smt { m_rw(m, m_converter, params_ref()), m_th_rw(m), m_trail_stack(*this), - m_float_util(m_converter.fu()), + m_fpa_util(m_converter.fu()), m_bv_util(m_converter.bu()), m_arith_util(m_converter.au()) { @@ -189,7 +189,7 @@ namespace smt { } app_ref theory_fpa::wrap(expr * e) { - SASSERT(!m_float_util.is_wrap(e)); + SASSERT(!m_fpa_util.is_wrap(e)); ast_manager & m = get_manager(); context & ctx = get_context(); sort * e_srt = m.get_sort(e); @@ -205,8 +205,8 @@ namespace smt { bv_srt = m_bv_util.mk_sort(3); else { SASSERT(m_converter.is_float(e_srt)); - unsigned ebits = m_float_util.get_ebits(e_srt); - unsigned sbits = m_float_util.get_sbits(e_srt); + unsigned ebits = m_fpa_util.get_ebits(e_srt); + unsigned sbits = m_fpa_util.get_sbits(e_srt); bv_srt = m_bv_util.mk_sort(ebits + sbits); } @@ -219,7 +219,7 @@ namespace smt { } app_ref theory_fpa::unwrap(expr * e, sort * s) { - SASSERT(!m_float_util.is_unwrap(e)); + SASSERT(!m_fpa_util.is_unwrap(e)); ast_manager & m = get_manager(); context & ctx = get_context(); sort * e_srt = m.get_sort(e); @@ -261,7 +261,7 @@ namespace smt { app_ref eca(to_app(ec), m); TRACE("t_fpa_detail", tout << "eca = " << mk_ismt2_pp(eca, m) << " sort is: " << mk_ismt2_pp(m.get_sort(eca), m) << std::endl;); - if (m_float_util.is_rm(e)) { + if (m_fpa_util.is_rm(e)) { expr_ref bv_rm(m); bv_rm = eca; TRACE("t_fpa_detail", tout << "bvrm = " << mk_ismt2_pp(bv_rm, m) << " sort is: " << mk_ismt2_pp(m.get_sort(bv_rm), m) << std::endl;); @@ -269,7 +269,7 @@ namespace smt { SASSERT(m_bv_util.get_bv_size(bv_rm) == 3); m_th_rw(bv_rm, res); } - else if (m_float_util.is_float(e)) { + else if (m_fpa_util.is_float(e)) { SASSERT(eca->get_family_id() == get_family_id()); fpa_op_kind k = (fpa_op_kind)(eca->get_decl_kind()); SASSERT(k == OP_FPA_TO_FP || k == OP_FPA_INTERNAL_BVUNWRAP); @@ -316,17 +316,17 @@ namespace smt { } expr_ref theory_fpa::convert_unwrap(expr * e) { - SASSERT(m_float_util.is_unwrap(e)); + SASSERT(m_fpa_util.is_unwrap(e)); ast_manager & m = get_manager(); sort * srt = m.get_sort(e); expr_ref res(m); - if (m_float_util.is_rm(srt)) { + if (m_fpa_util.is_rm(srt)) { res = to_app(e)->get_arg(0); } else { - SASSERT(m_float_util.is_float(srt)); - unsigned ebits = m_float_util.get_ebits(srt); - unsigned sbits = m_float_util.get_sbits(srt); + SASSERT(m_fpa_util.is_float(srt)); + unsigned ebits = m_fpa_util.get_ebits(srt); + unsigned sbits = m_fpa_util.get_sbits(srt); expr * bv = to_app(e)->get_arg(0); unsigned bv_sz = m_bv_util.get_bv_size(bv); m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), @@ -351,11 +351,11 @@ namespace smt { return res; } else { - if (m_float_util.is_unwrap(e)) + if (m_fpa_util.is_unwrap(e)) res = convert_unwrap(e); else if (m.is_bool(e)) res = convert_atom(e); - else if (m_float_util.is_float(e) || m_float_util.is_rm(e)) + else if (m_fpa_util.is_float(e) || m_fpa_util.is_rm(e)) res = convert_term(e); else if (m_arith_util.is_real(e) || m_bv_util.is_bv(e)) res = convert_conversion_term(e); @@ -499,10 +499,10 @@ namespace smt { owner = n->get_owner(); owner_sort = m.get_sort(owner); - if (m_float_util.is_rm(owner_sort)) { + if (m_fpa_util.is_rm(owner_sort)) { // For every RM term, we need to make sure that it's // associated bit-vector is within the valid range. - if (!m_float_util.is_unwrap(owner)) + if (!m_fpa_util.is_unwrap(owner)) { expr_ref valid(m), limit(m); limit = m_bv_util.mk_numeral(4, 3); @@ -511,7 +511,7 @@ namespace smt { } } - if (!ctx.relevancy() && !m_float_util.is_unwrap(owner)) + if (!ctx.relevancy() && !m_fpa_util.is_unwrap(owner)) assert_cnstr(m.mk_eq(unwrap(wrap(owner), owner_sort), owner)); } @@ -523,7 +523,7 @@ namespace smt { mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); context & ctx = get_context(); - float_util & fu = m_float_util; + fpa_util & fu = m_fpa_util; bv_util & bu = m_bv_util; mpf_manager & mpfm = fu.fm(); @@ -570,7 +570,7 @@ namespace smt { mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); context & ctx = get_context(); - mpf_manager & mpfm = m_float_util.fm(); + mpf_manager & mpfm = m_fpa_util.fm(); app * xe = get_enode(x)->get_owner(); app * ye = get_enode(y)->get_owner(); @@ -587,7 +587,7 @@ namespace smt { expr_ref c(m); - if (m_float_util.is_float(xe) && m_float_util.is_float(ye)) + if (m_fpa_util.is_float(xe) && m_fpa_util.is_float(ye)) { expr *x_sgn, *x_sig, *x_exp; m_converter.split_triple(xc, x_sgn, x_sig, x_exp); @@ -636,22 +636,22 @@ namespace smt { ast_manager & m = get_manager(); TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, m) << "\n";); - mpf_manager & mpfm = m_float_util.fm(); + mpf_manager & mpfm = m_fpa_util.fm(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - if (m_float_util.is_float(n) || m_float_util.is_rm(n)) { + if (m_fpa_util.is_float(n) || m_fpa_util.is_rm(n)) { sort * s = m.get_sort(n); - if (!m_float_util.is_unwrap(n)) { + if (!m_fpa_util.is_unwrap(n)) { expr_ref wrapped(m), c(m); wrapped = wrap(n); mpf_rounding_mode rm; scoped_mpf val(mpfm); - if (m_float_util.is_rm_value(n, rm)) { + if (m_fpa_util.is_rm_value(n, rm)) { c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3)); assert_cnstr(c); } - else if (m_float_util.is_value(n, val)) { + else if (m_fpa_util.is_value(n, val)) { unsigned sz = val.get().get_ebits() + val.get().get_sbits(); expr_ref bv_val_e(m); bv_val_e = convert(n); @@ -670,7 +670,7 @@ namespace smt { } } else if (n->get_family_id() == get_family_id()) { - SASSERT(!m_float_util.is_float(n) && !m_float_util.is_rm(n)); + SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n)); // These are the conversion functions fp.to_* */ } else @@ -714,8 +714,8 @@ namespace smt { // If the owner is not internalized, it doesn't have an enode associated. SASSERT(ctx.e_internalized(owner)); - if (m_float_util.is_rm_value(owner) || - m_float_util.is_value(owner)) + if (m_fpa_util.is_rm_value(owner) || + m_fpa_util.is_value(owner)) return alloc(expr_wrapper_proc, owner); model_value_proc * res = 0; @@ -729,14 +729,14 @@ namespace smt { " (owner " << (!ctx.e_internalized(owner) ? "not" : "is") << " internalized)" << std::endl;); - if (m_float_util.is_rm(owner)) { + if (m_fpa_util.is_rm(owner)) { fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); vp->add_dependency(ctx.get_enode(wrapped)); res = vp; } - else if (m_float_util.is_float(owner)) { - unsigned ebits = m_float_util.get_ebits(m.get_sort(owner)); - unsigned sbits = m_float_util.get_sbits(m.get_sort(owner)); + else if (m_fpa_util.is_float(owner)) { + unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner)); + unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner)); fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits); vp->add_dependency(ctx.get_enode(wrapped)); res = vp; diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index c51b02c28..58af5ad1c 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -29,8 +29,8 @@ Revision History: namespace smt { - class fpa_factory : public value_factory { - float_util m_util; + class fpa_value_actory : public value_factory { + fpa_util m_util; virtual app * mk_value_core(mpf const & val, sort * s) { SASSERT(m_util.get_ebits(s) == val.get_ebits()); @@ -39,11 +39,11 @@ namespace smt { } public: - fpa_factory(ast_manager & m, family_id fid) : + fpa_value_actory(ast_manager & m, family_id fid) : value_factory(m, fid), m_util(m) {} - virtual ~fpa_factory() {} + virtual ~fpa_value_actory() {} virtual expr * get_some_value(sort * s) { mpf_manager & mpfm = m_util.fm(); @@ -87,10 +87,10 @@ namespace smt { class fpa_value_proc : public model_value_proc { protected: - theory_fpa & m_th; + theory_fpa & m_th; ast_manager & m; - float_util & m_fu; - bv_util & m_bu; + fpa_util & m_fu; + bv_util & m_bu; buffer m_deps; unsigned m_ebits; unsigned m_sbits; diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 78ba64111..dfddfd12f 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -85,7 +85,7 @@ model_converter * fpa2bv_model_converter::translate(ast_translation & translator } void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { - float_util fu(m); + fpa_util fu(m); bv_util bu(m); mpf fp_val; unsynch_mpz_manager & mpzm = fu.fm().mpz_manager(); diff --git a/src/tactic/fpa/qffpa_tactic.cpp b/src/tactic/fpa/qffp_tactic.cpp similarity index 96% rename from src/tactic/fpa/qffpa_tactic.cpp rename to src/tactic/fpa/qffp_tactic.cpp index c02166c18..e205a6c5e 100644 --- a/src/tactic/fpa/qffpa_tactic.cpp +++ b/src/tactic/fpa/qffp_tactic.cpp @@ -7,7 +7,7 @@ Module Name: Abstract: - Tactic for QF_FPA benchmarks. + Tactic for QF_FP benchmarks. Author: @@ -23,7 +23,7 @@ Notes: #include"fpa2bv_tactic.h" #include"smt_tactic.h" -#include"qffpa_tactic.h" +#include"qffp_tactic.h" tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { params_ref simp_p = p; @@ -52,7 +52,7 @@ struct is_non_qffp_predicate { struct found {}; ast_manager & m; bv_util bu; - float_util fu; + fpa_util fu; arith_util au; is_non_qffp_predicate(ast_manager & _m) : m(_m), bu(m), fu(m), au(m) {} @@ -89,4 +89,4 @@ public: probe * mk_is_qffp_probe() { return alloc(is_qffp_probe); } - \ No newline at end of file + diff --git a/src/tactic/fpa/qffpa_tactic.h b/src/tactic/fpa/qffp_tactic.h similarity index 82% rename from src/tactic/fpa/qffpa_tactic.h rename to src/tactic/fpa/qffp_tactic.h index 3ab95798f..2842e3f73 100644 --- a/src/tactic/fpa/qffpa_tactic.h +++ b/src/tactic/fpa/qffp_tactic.h @@ -17,8 +17,8 @@ Notes: --*/ -#ifndef _QFFPA_TACTIC_H_ -#define _QFFPA_TACTIC_H_ +#ifndef _QFFP_TACTIC_H_ +#define _QFFP_TACTIC_H_ #include"params.h" class ast_manager; @@ -27,14 +27,14 @@ class tactic; tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p = params_ref()); /* ADD_TACTIC("qffp", "(try to) solve goal using the tactic for QF_FP.", "mk_qffp_tactic(m, p)") - ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPBV (floats+bit-vectors).", "mk_qffp_tactic(m, p)") + ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPBV (floats+bit-vectors).", "mk_qffpbv_tactic(m, p)") */ probe * mk_is_qffp_probe(); probe * mk_is_qffpbv_probe(); /* ADD_PROBE("is-qffp", "true if the goal is in QF_FP (floats).", "mk_is_qffp_probe()") - ADD_PROBE("is-qffpbv", "true if the goal is in QF_FPBV (floats+bit-vectors).", "mk_is_qffp_probe()") + ADD_PROBE("is-qffpbv", "true if the goal is in QF_FPBV (floats+bit-vectors).", "mk_is_qffpbv_probe()") */ #endif diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index a01b547df..79b3e0e95 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -27,7 +27,7 @@ Notes: #include"nra_tactic.h" #include"probe_arith.h" #include"quant_tactics.h" -#include"qffpa_tactic.h" +#include"qffp_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 9e0ce6e89..3c62bc80c 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -33,7 +33,7 @@ Notes: #include"qfidl_tactic.h" #include"default_tactic.h" #include"ufbv_tactic.h" -#include"qffpa_tactic.h" +#include"qffp_tactic.h" #include"horn_tactic.h" #include"smt_solver.h" @@ -78,8 +78,10 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const return mk_ufbv_tactic(m, p); else if (logic=="BV") return mk_ufbv_tactic(m, p); - else if (logic=="QF_FP" || logic=="QF_FPBV") + else if (logic=="QF_FP") return mk_qffp_tactic(m, p); + else if (logic == "QF_FPBV") + return mk_qffpbv_tactic(m, p); else if (logic=="HORN") return mk_horn_tactic(m, p); else From 0cedd32ea2663961d2f439d3858e525ff7a9f9dc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 13:47:26 +0000 Subject: [PATCH 153/646] More renaming floats -> fpa Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.h | 4 ++-- src/smt/theory_fpa.cpp | 2 +- src/smt/theory_fpa.h | 20 ++++++++++---------- src/tactic/fpa/qffp_tactic.cpp | 7 +++++++ src/tactic/fpa/qffp_tactic.h | 1 + 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index f81edb653..efc4d9179 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -45,7 +45,7 @@ class fpa2bv_converter { protected: ast_manager & m; basic_simplifier_plugin m_simp; - float_util m_util; + fpa_util m_util; bv_util m_bv_util; arith_util m_arith_util; mpf_manager & m_mpf_manager; @@ -62,7 +62,7 @@ public: fpa2bv_converter(ast_manager & m); ~fpa2bv_converter(); - float_util & fu() { return m_util; } + fpa_util & fu() { return m_util; } bv_util & bu() { return m_bv_util; } arith_util & au() { return m_arith_util; } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 055f79b9d..487908173 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -700,7 +700,7 @@ namespace smt { void theory_fpa::init_model(model_generator & mg) { TRACE("t_fpa", tout << "initializing model" << std::endl; display(tout);); - m_factory = alloc(fpa_factory, get_manager(), get_family_id()); + m_factory = alloc(fpa_value_factory, get_manager(), get_family_id()); mg.register_factory(m_factory); } diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 58af5ad1c..33733d7d9 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -29,7 +29,7 @@ Revision History: namespace smt { - class fpa_value_actory : public value_factory { + class fpa_value_factory : public value_factory { fpa_util m_util; virtual app * mk_value_core(mpf const & val, sort * s) { @@ -39,11 +39,11 @@ namespace smt { } public: - fpa_value_actory(ast_manager & m, family_id fid) : + fpa_value_factory(ast_manager & m, family_id fid) : value_factory(m, fid), m_util(m) {} - virtual ~fpa_value_actory() {} + virtual ~fpa_value_factory() {} virtual expr * get_some_value(sort * s) { mpf_manager & mpfm = m_util.fm(); @@ -97,7 +97,7 @@ namespace smt { public: fpa_value_proc(theory_fpa * th, unsigned ebits, unsigned sbits) : - m_th(*th), m_fu(th->m_float_util), m_bu(th->m_bv_util), m(th->get_manager()), + m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()), m_ebits(ebits), m_sbits(sbits) {} virtual ~fpa_value_proc() {} @@ -112,15 +112,15 @@ namespace smt { }; class fpa_rm_value_proc : public model_value_proc { - theory_fpa & m_th; + theory_fpa & m_th; ast_manager & m; - float_util & m_fu; - bv_util & m_bu; + fpa_util & m_fu; + bv_util & m_bu; buffer m_deps; public: fpa_rm_value_proc(theory_fpa * th) : - m_th(*th), m_fu(th->m_float_util), m_bu(th->m_bv_util), m(th->get_manager()) {} + m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()) {} void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); } @@ -137,8 +137,8 @@ namespace smt { fpa2bv_rewriter m_rw; th_rewriter m_th_rw; th_trail_stack m_trail_stack; - fpa_factory * m_factory; - float_util & m_float_util; + fpa_value_factory * m_factory; + fpa_util & m_fpa_util; bv_util & m_bv_util; arith_util & m_arith_util; obj_map m_wraps; diff --git a/src/tactic/fpa/qffp_tactic.cpp b/src/tactic/fpa/qffp_tactic.cpp index e205a6c5e..5bc006f00 100644 --- a/src/tactic/fpa/qffp_tactic.cpp +++ b/src/tactic/fpa/qffp_tactic.cpp @@ -48,6 +48,10 @@ tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { return st; } +tactic * mk_qffpbv_tactic(ast_manager & m, params_ref const & p) { + return mk_qffp_tactic(m, p); +} + struct is_non_qffp_predicate { struct found {}; ast_manager & m; @@ -90,3 +94,6 @@ probe * mk_is_qffp_probe() { return alloc(is_qffp_probe); } +probe * mk_is_qffpbv_probe() { + return alloc(is_qffp_probe); +} diff --git a/src/tactic/fpa/qffp_tactic.h b/src/tactic/fpa/qffp_tactic.h index 2842e3f73..5c8caba2b 100644 --- a/src/tactic/fpa/qffp_tactic.h +++ b/src/tactic/fpa/qffp_tactic.h @@ -25,6 +25,7 @@ class ast_manager; class tactic; tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p = params_ref()); +tactic * mk_qffpbv_tactic(ast_manager & m, params_ref const & p = params_ref()); /* ADD_TACTIC("qffp", "(try to) solve goal using the tactic for QF_FP.", "mk_qffp_tactic(m, p)") ADD_TACTIC("qffpbv", "(try to) solve goal using the tactic for QF_FPBV (floats+bit-vectors).", "mk_qffpbv_tactic(m, p)") From c0a027fc809ba2f205b60571f4d5c16115379835 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 14:07:47 +0000 Subject: [PATCH 154/646] FPA: Elminated nzero/pzero AST kinds Signed-off-by: Christoph M. Wintersteiger --- src/api/api_ast.cpp | 2 -- src/ast/fpa/fpa2bv_rewriter.h | 4 +--- src/ast/fpa_decl_plugin.cpp | 4 ---- src/ast/fpa_decl_plugin.h | 4 ---- src/ast/rewriter/fpa_rewriter.cpp | 2 -- 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index c6b413dd4..eed5f7553 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -1155,8 +1155,6 @@ extern "C" { case OP_FPA_IS_ZERO: return Z3_OP_FPA_IS_ZERO; case OP_FPA_IS_NORMAL: return Z3_OP_FPA_IS_NORMAL; case OP_FPA_IS_SUBNORMAL: return Z3_OP_FPA_IS_SUBNORMAL; - case OP_FPA_IS_PZERO: return Z3_OP_FPA_IS_PZERO; - case OP_FPA_IS_NZERO: return Z3_OP_FPA_IS_NZERO; case OP_FPA_IS_NEGATIVE: return Z3_OP_FPA_IS_NEGATIVE; case OP_FPA_IS_POSITIVE: return Z3_OP_FPA_IS_POSITIVE; case OP_FPA_FP: return Z3_OP_FPA_FP; diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index cbbd9e8a7..c7a987b83 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -143,9 +143,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE; case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE; case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE; - case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE; - case OP_FPA_IS_NZERO: m_conv.mk_is_nzero(f, num, args, result); return BR_DONE; - case OP_FPA_IS_PZERO: m_conv.mk_is_pzero(f, num, args, result); return BR_DONE; + case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE; case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE; case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 90bbd4901..52a1a95f7 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -294,8 +294,6 @@ func_decl * fpa_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_paramet symbol name; switch (k) { case OP_FPA_IS_ZERO: name = "fp.isZero"; break; - case OP_FPA_IS_NZERO: name = "fp.isNZero"; break; - case OP_FPA_IS_PZERO: name = "fp.isPZero"; break; case OP_FPA_IS_NEGATIVE: name = "fp.isNegative"; break; case OP_FPA_IS_POSITIVE: name = "fp.isPositive"; break; case OP_FPA_IS_NAN: name = "fp.isNaN"; break; @@ -717,8 +715,6 @@ func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, case OP_FPA_GE: return mk_bin_rel_decl(k, num_parameters, parameters, arity, domain, range); case OP_FPA_IS_ZERO: - case OP_FPA_IS_NZERO: - case OP_FPA_IS_PZERO: case OP_FPA_IS_NEGATIVE: case OP_FPA_IS_POSITIVE: case OP_FPA_IS_NAN: diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index b8d0c0c3e..44f0e62c4 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -71,8 +71,6 @@ enum fpa_op_kind { OP_FPA_IS_ZERO, OP_FPA_IS_NORMAL, OP_FPA_IS_SUBNORMAL, - OP_FPA_IS_PZERO, - OP_FPA_IS_NZERO, OP_FPA_IS_NEGATIVE, OP_FPA_IS_POSITIVE, @@ -325,8 +323,6 @@ public: app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_ZERO, arg1); } app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NORMAL, arg1); } app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_SUBNORMAL, arg1); } - app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NZERO, arg1); } - app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_PZERO, arg1); } app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_POSITIVE, arg1); } app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index 2977b7ab2..e7b8c7b34 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -57,8 +57,6 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con case OP_FPA_LE: SASSERT(num_args == 2); st = mk_le(args[0], args[1], result); break; case OP_FPA_GE: SASSERT(num_args == 2); st = mk_ge(args[0], args[1], result); break; case OP_FPA_IS_ZERO: SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break; - case OP_FPA_IS_NZERO: SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break; - case OP_FPA_IS_PZERO: SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break; case OP_FPA_IS_NAN: SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break; case OP_FPA_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; case OP_FPA_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; From c5b220cc124739d0a5498bed7b079a14975d5af5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 14:07:59 +0000 Subject: [PATCH 155/646] FPA: Added AST kind descriptions Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_api.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 3c3a5d1c2..c719354b6 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -877,6 +877,90 @@ typedef enum - Z3_OP_DT_ACCESSOR: datatype accessor. + - Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN: Floating-point rounding mode RNE + + - Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY: Floating-point rounding mode RNA + + - Z3_OP_FPA_RM_TOWARD_POSITIVE: Floating-point rounding mode RTP + + - Z3_OP_FPA_RM_TOWARD_NEGATIVE: Floating-point rounding mode RTN + + - Z3_OP_FPA_RM_TOWARD_ZERO: Floating-point rounding mode RTZ + + - Z3_OP_FPA_VALUE: Floating-point value + + - Z3_OP_FPA_PLUS_INF: Floating-point +oo + + - Z3_OP_FPA_MINUS_INF: Floating-point -oo + + - Z3_OP_FPA_NAN: Floating-point NaN + + - Z3_OP_FPA_PLUS_ZERO: Floating-point +zero + + - Z3_OP_FPA_MINUS_ZERO: Floating-point -zero + + - Z3_OP_FPA_ADD: Floating-point addition + + - Z3_OP_FPA_SUB: Floating-point subtraction + + - Z3_OP_FPA_NEG: Floating-point negation + + - Z3_OP_FPA_MUL: Floating-point multiplication + + - Z3_OP_FPA_DIV: Floating-point division + + - Z3_OP_FPA_REM: Floating-point remainder + + - Z3_OP_FPA_ABS: Floating-point absolute value + + - Z3_OP_FPA_MIN: Floating-point minimum + + - Z3_OP_FPA_MAX: Floating-point maximum + + - Z3_OP_FPA_FMA: Floating-point fused multiply-add + + - Z3_OP_FPA_SQRT: Floating-point square root + + - Z3_OP_FPA_ROUND_TO_INTEGRAL: Floating-point round to integral + + - Z3_OP_FPA_EQ: Floating-point equality + + - Z3_OP_FPA_LT: Floating-point less than + + - Z3_OP_FPA_GT: Floating-point greater than + + - Z3_OP_FPA_LE: Floating-point less than or equal + + - Z3_OP_FPA_GE: Floating-point greater than or equal + + - Z3_OP_FPA_IS_NAN: Floating-point isNaN + + - Z3_OP_FPA_IS_INF: Floating-point isInfinite + + - Z3_OP_FPA_IS_ZERO: Floating-point isZero + + - Z3_OP_FPA_IS_NORMAL: Floating-point isNormal + + - Z3_OP_FPA_IS_SUBNORMAL: Floating-point isSubnormal + + - Z3_OP_FPA_IS_NEGATIVE: Floating-point isNegative + + - Z3_OP_FPA_IS_POSITIVE: Floating-point isPositive + + - Z3_OP_FPA_FP: Floating-point constructor from 3 bit-vectors + + - Z3_OP_FPA_TO_FP: Floating-point conversion (various) + + - Z3_OP_FPA_TO_FP_UNSIGNED: Floating-point conversion from unsigend bit-vector + + - Z3_OP_FPA_TO_UBV: Floating-point conversion to unsigned bit-vector + + - Z3_OP_FPA_TO_SBV: Floating-point conversion to signed bit-vector + + - Z3_OP_FPA_TO_REAL: Floating-point conversion to real number + + - Z3_OP_FPA_TO_IEEE_BV: Floating-point conversion to IEEE-754 bit-vector + - Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols. */ typedef enum { @@ -1095,8 +1179,6 @@ typedef enum { Z3_OP_FPA_IS_ZERO, Z3_OP_FPA_IS_NORMAL, Z3_OP_FPA_IS_SUBNORMAL, - Z3_OP_FPA_IS_PZERO, - Z3_OP_FPA_IS_NZERO, Z3_OP_FPA_IS_NEGATIVE, Z3_OP_FPA_IS_POSITIVE, From c0bc2518b007184ad18aa486f8e4f4e61d800fcc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 14:22:44 +0000 Subject: [PATCH 156/646] Renaming for consistency mk_value -> mk_numeral Signed-off-by: Christoph M. Wintersteiger --- src/api/api_ast.cpp | 2 +- src/api/api_numeral.cpp | 4 +- src/api/z3_api.h | 4 +- src/ast/fpa/fpa2bv_converter.cpp | 22 +++++------ src/ast/fpa_decl_plugin.cpp | 8 ++-- src/ast/fpa_decl_plugin.h | 36 +++++++++--------- src/ast/rewriter/fpa_rewriter.cpp | 62 +++++++++++++++---------------- src/smt/theory_fpa.cpp | 8 ++-- 8 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index eed5f7553..b9c6230b7 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -1127,7 +1127,7 @@ extern "C" { case OP_FPA_RM_TOWARD_POSITIVE: return Z3_OP_FPA_RM_TOWARD_POSITIVE; case OP_FPA_RM_TOWARD_NEGATIVE: return Z3_OP_FPA_RM_TOWARD_NEGATIVE; case OP_FPA_RM_TOWARD_ZERO: return Z3_OP_FPA_RM_TOWARD_ZERO; - case OP_FPA_VALUE: return Z3_OP_FPA_VALUE; + case OP_FPA_NUM: return Z3_OP_FPA_NUM; case OP_FPA_PLUS_INF: return Z3_OP_FPA_PLUS_INF; case OP_FPA_MINUS_INF: return Z3_OP_FPA_MINUS_INF; case OP_FPA_NAN: return Z3_OP_FPA_NAN; diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 89f01707e..7789f1157 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -149,7 +149,7 @@ extern "C" { return mk_c(c)->autil().is_numeral(e) || mk_c(c)->bvutil().is_numeral(e) || - mk_c(c)->fpa_util().is_value(e); + mk_c(c)->fpa_util().is_numeral(e); Z3_CATCH_RETURN(Z3_FALSE); } @@ -193,7 +193,7 @@ extern "C" { // floats are separated from all others to avoid huge rationals. fpa_util & fu = mk_c(c)->fpa_util(); scoped_mpf tmp(fu.fm()); - if (mk_c(c)->fpa_util().is_value(to_expr(a), tmp)) { + if (mk_c(c)->fpa_util().is_numeral(to_expr(a), tmp)) { return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); } else { diff --git a/src/api/z3_api.h b/src/api/z3_api.h index c719354b6..a4ad8d90d 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -887,7 +887,7 @@ typedef enum - Z3_OP_FPA_RM_TOWARD_ZERO: Floating-point rounding mode RTZ - - Z3_OP_FPA_VALUE: Floating-point value + - Z3_OP_FPA_NUM: Floating-point value - Z3_OP_FPA_PLUS_INF: Floating-point +oo @@ -1149,7 +1149,7 @@ typedef enum { Z3_OP_FPA_RM_TOWARD_NEGATIVE, Z3_OP_FPA_RM_TOWARD_ZERO, - Z3_OP_FPA_VALUE, + Z3_OP_FPA_NUM, Z3_OP_FPA_PLUS_INF, Z3_OP_FPA_MINUS_INF, Z3_OP_FPA_NAN, diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index dc1a255e8..4c570c1ba 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -80,7 +80,7 @@ void fpa2bv_converter::mk_ite(expr * c, expr * t, expr * f, expr_ref & result) { mk_triple(sgn, s, e, result); } -void fpa2bv_converter::mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 0); SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_external()); @@ -2177,18 +2177,18 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator()); app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); - a_nte = m_plugin->mk_value(nte); - a_nta = m_plugin->mk_value(nta); - a_tp = m_plugin->mk_value(tp); - a_tn = m_plugin->mk_value(tn); - a_tz = m_plugin->mk_value(tz); + a_nte = m_plugin->mk_numeral(nte); + a_nta = m_plugin->mk_numeral(nta); + a_tp = m_plugin->mk_numeral(tp); + a_tn = m_plugin->mk_numeral(tn); + a_tz = m_plugin->mk_numeral(tz); expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); - mk_value(a_nte->get_decl(), 0, 0, bv_nte); - mk_value(a_nta->get_decl(), 0, 0, bv_nta); - mk_value(a_tp->get_decl(), 0, 0, bv_tp); - mk_value(a_tn->get_decl(), 0, 0, bv_tn); - mk_value(a_tz->get_decl(), 0, 0, bv_tz); + mk_numeral(a_nte->get_decl(), 0, 0, bv_nte); + mk_numeral(a_nta->get_decl(), 0, 0, bv_nta); + mk_numeral(a_tp->get_decl(), 0, 0, bv_tp); + mk_numeral(a_tn->get_decl(), 0, 0, bv_tn); + mk_numeral(a_tz->get_decl(), 0, 0, bv_tz); expr_ref c1(m), c2(m), c3(m), c4(m); c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 52a1a95f7..7d4a77d1c 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -72,7 +72,7 @@ func_decl * fpa_decl_plugin::mk_value_decl(mpf const & v) { parameter p(mk_id(v), true); SASSERT(p.is_external()); sort * s = mk_float_sort(v.get_ebits(), v.get_sbits()); - return m_manager->mk_const_decl(symbol("fpa"), s, func_decl_info(m_family_id, OP_FPA_VALUE, 1, &p)); + return m_manager->mk_const_decl(symbol("fpa"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p)); } app * fpa_decl_plugin::mk_value(mpf const & v) { @@ -80,7 +80,7 @@ app * fpa_decl_plugin::mk_value(mpf const & v) { } bool fpa_decl_plugin::is_value(expr * n, mpf & val) { - if (is_app_of(n, m_family_id, OP_FPA_VALUE)) { + if (is_app_of(n, m_family_id, OP_FPA_NUM)) { m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]); return true; } @@ -860,7 +860,7 @@ bool fpa_decl_plugin::is_value(app * e) const { case OP_FPA_RM_TOWARD_POSITIVE: case OP_FPA_RM_TOWARD_NEGATIVE: case OP_FPA_RM_TOWARD_ZERO: - case OP_FPA_VALUE: + case OP_FPA_NUM: case OP_FPA_PLUS_INF: case OP_FPA_MINUS_INF: case OP_FPA_PLUS_ZERO: @@ -891,7 +891,7 @@ bool fpa_decl_plugin::is_unique_value(app* e) const { case OP_FPA_PLUS_ZERO: /* No; +zero == fp #b0 #b00 #b000) */ case OP_FPA_MINUS_ZERO: /* No; -zero == fp #b1 #b00 #b000) */ case OP_FPA_NAN: /* No; NaN == (fp #b0 #b111111 #b0000001) */ - case OP_FPA_VALUE: /* see NaN */ + case OP_FPA_NUM: /* see NaN */ return false; case OP_FPA_FP: return m_manager->is_unique_value(e->get_arg(0)) && diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index 44f0e62c4..24481d348 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -41,7 +41,7 @@ enum fpa_op_kind { OP_FPA_RM_TOWARD_NEGATIVE, OP_FPA_RM_TOWARD_ZERO, - OP_FPA_VALUE, + OP_FPA_NUM, OP_FPA_PLUS_INF, OP_FPA_MINUS_INF, OP_FPA_NAN, @@ -189,12 +189,12 @@ public: virtual bool is_unique_value(app* e) const; mpf_manager & fm() { return m_fm; } - func_decl * mk_value_decl(mpf const & v); - app * mk_value(mpf const & v); - bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FPA_VALUE); } - bool is_value(expr * n, mpf & val); - bool is_rm_value(expr * n, mpf_rounding_mode & val); - bool is_rm_value(expr * n) { mpf_rounding_mode t; return is_rm_value(n, t); } + func_decl * mk_numeral_decl(mpf const & v); + app * mk_numeral(mpf const & v); + bool is_numeral(expr * n) { return is_app_of(n, m_family_id, OP_FPA_NUM); } + bool is_numeral(expr * n, mpf & val); + bool is_rm_numeral(expr * n, mpf_rounding_mode & val); + bool is_rm_numeral(expr * n) { mpf_rounding_mode t; return is_rm_numeral(n, t); } mpf const & get_value(unsigned id) const { SASSERT(m_value_table.contains(id)); @@ -244,23 +244,23 @@ public: app * mk_pinf(sort * s) { return mk_pinf(get_ebits(s), get_sbits(s)); } app * mk_ninf(sort * s) { return mk_ninf(get_ebits(s), get_sbits(s)); } - app * mk_value(mpf const & v) { return m_plugin->mk_value(v); } - bool is_value(expr * n) { return m_plugin->is_value(n); } - bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); } - bool is_rm_value(expr * n) { return m_plugin->is_rm_value(n); } - bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); } + app * mk_value(mpf const & v) { return m_plugin->mk_numeral(v); } + bool is_numeral(expr * n) { return m_plugin->is_numeral(n); } + bool is_numeral(expr * n, mpf & v) { return m_plugin->is_numeral(n, v); } + bool is_rm_numeral(expr * n) { return m_plugin->is_rm_numeral(n); } + bool is_rm_numeral(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_numeral(n, v); } app * mk_pzero(unsigned ebits, unsigned sbits); app * mk_nzero(unsigned ebits, unsigned sbits); app * mk_pzero(sort * s) { return mk_pzero(get_ebits(s), get_sbits(s)); } app * mk_nzero(sort * s) { return mk_nzero(get_ebits(s), get_sbits(s)); } - bool is_nan(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nan(v); } - bool is_pinf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pinf(v); } - bool is_ninf(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_ninf(v); } - bool is_zero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_zero(v); } - bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_pzero(v); } - bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_value(n, v) && fm().is_nzero(v); } + bool is_nan(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nan(v); } + bool is_pinf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pinf(v); } + bool is_ninf(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_ninf(v); } + bool is_zero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_zero(v); } + bool is_pzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_pzero(v); } + bool is_nzero(expr * n) { scoped_mpf v(fm()); return is_numeral(n, v) && fm().is_nzero(v); } app * mk_fp(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FPA_FP, arg1, arg2, arg3); } app * mk_to_fp(sort * s, expr * bv_t) { diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index e7b8c7b34..915d25e50 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -81,7 +81,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const if (num_args == 2) { mpf_rounding_mode rm; - if (!m_util.is_rm_value(args[0], rm)) + if (!m_util.is_rm_numeral(args[0], rm)) return BR_FAILED; rational q; @@ -95,7 +95,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const // TRACE("fp_rewriter", tout << "result: " << result << std::endl; ); return BR_DONE; } - else if (m_util.is_value(args[1], q_mpf)) { + else if (m_util.is_numeral(args[1], q_mpf)) { TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; ); scoped_mpf v(m_util.fm()); m_util.fm().set(v, ebits, sbits, rm, q_mpf); @@ -116,7 +116,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const m_util.au().is_real(args[1]) && m_util.au().is_int(args[2])) { mpf_rounding_mode rm; - if (!m_util.is_rm_value(args[0], rm)) + if (!m_util.is_rm_numeral(args[0], rm)) return BR_FAILED; rational q; @@ -169,9 +169,9 @@ br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr br_status fpa_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); - if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) { + if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { scoped_mpf t(m_util.fm()); m_util.fm().add(rm, v2, v3, t); result = m_util.mk_value(t); @@ -190,9 +190,9 @@ br_status fpa_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); - if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) { + if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { scoped_mpf t(m_util.fm()); m_util.fm().mul(rm, v2, v3, t); result = m_util.mk_value(t); @@ -205,9 +205,9 @@ br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()); - if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) { + if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { scoped_mpf t(m_util.fm()); m_util.fm().div(rm, v2, v3, t); result = m_util.mk_value(t); @@ -241,7 +241,7 @@ br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) { } scoped_mpf v1(m_util.fm()); - if (m_util.is_value(arg1, v1)) { + if (m_util.is_numeral(arg1, v1)) { m_util.fm().neg(v1); result = m_util.mk_value(v1); return BR_DONE; @@ -253,7 +253,7 @@ br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); - if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { scoped_mpf t(m_util.fm()); m_util.fm().rem(v1, v2, t); result = m_util.mk_value(t); @@ -316,9 +316,9 @@ br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm()); - if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3) && m_util.is_value(arg4, v4)) { + if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3) && m_util.is_numeral(arg4, v4)) { scoped_mpf t(m_util.fm()); m_util.fm().fused_mul_add(rm, v2, v3, v4, t); result = m_util.mk_value(t); @@ -331,9 +331,9 @@ br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()); - if (m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg2, v2)) { scoped_mpf t(m_util.fm()); m_util.fm().sqrt(rm, v2, t); result = m_util.mk_value(t); @@ -346,9 +346,9 @@ br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; - if (m_util.is_rm_value(arg1, rm)) { + if (m_util.is_rm_numeral(arg1, rm)) { scoped_mpf v2(m_util.fm()); - if (m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg2, v2)) { scoped_mpf t(m_util.fm()); m_util.fm().round_to_integral(rm, v2, t); result = m_util.mk_value(t); @@ -362,7 +362,7 @@ br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { // This the floating point theory == br_status fpa_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); - if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { result = (m_util.fm().eq(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -407,7 +407,7 @@ br_status fpa_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { } scoped_mpf v1(m_util.fm()), v2(m_util.fm()); - if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { result = (m_util.fm().lt(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -427,7 +427,7 @@ br_status fpa_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) { return BR_DONE; } scoped_mpf v1(m_util.fm()), v2(m_util.fm()); - if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { result = (m_util.fm().le(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -442,7 +442,7 @@ br_status fpa_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_zero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -452,7 +452,7 @@ br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_nzero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -462,7 +462,7 @@ br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_pzero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -472,7 +472,7 @@ br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -482,7 +482,7 @@ br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -492,7 +492,7 @@ br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -502,7 +502,7 @@ br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -512,7 +512,7 @@ br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -522,7 +522,7 @@ br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); - if (m_util.is_value(arg1, v)) { + if (m_util.is_numeral(arg1, v)) { result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true(); return BR_DONE; } @@ -534,7 +534,7 @@ br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { // This the SMT = br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); - if (m_util.is_value(arg1, v1) && m_util.is_value(arg2, v2)) { + if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { // Note: == is the floats-equality, here we need normal equality. result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() : (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1)!=m_fm.sgn(v2)) ? m().mk_false() : @@ -584,7 +584,7 @@ br_status fpa_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_to_real(expr * arg1, expr_ref & result) { scoped_mpf fv(m_util.fm()); - if (m_util.is_value(arg1, fv)) { + if (m_util.is_numeral(arg1, fv)) { if (m_fm.is_nan(fv) || m_fm.is_inf(fv)) { result = m_util.mk_internal_to_real_unspecified(); } diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 487908173..158622428 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -647,11 +647,11 @@ namespace smt { wrapped = wrap(n); mpf_rounding_mode rm; scoped_mpf val(mpfm); - if (m_fpa_util.is_rm_value(n, rm)) { + if (m_fpa_util.is_rm_numeral(n, rm)) { c = m.mk_eq(wrapped, m_bv_util.mk_numeral(rm, 3)); assert_cnstr(c); } - else if (m_fpa_util.is_value(n, val)) { + else if (m_fpa_util.is_numeral(n, val)) { unsigned sz = val.get().get_ebits() + val.get().get_sbits(); expr_ref bv_val_e(m); bv_val_e = convert(n); @@ -714,8 +714,8 @@ namespace smt { // If the owner is not internalized, it doesn't have an enode associated. SASSERT(ctx.e_internalized(owner)); - if (m_fpa_util.is_rm_value(owner) || - m_fpa_util.is_value(owner)) + if (m_fpa_util.is_rm_numeral(owner) || + m_fpa_util.is_numeral(owner)) return alloc(expr_wrapper_proc, owner); model_value_proc * res = 0; From 33dc6340e16ef1ae15b47495b5472a98edcb2128 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 14:23:13 +0000 Subject: [PATCH 157/646] More renaming mk_value -> mk_numeral Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast_smt2_pp.cpp | 4 ++-- src/ast/fpa/fpa2bv_converter.h | 4 ++-- src/ast/fpa/fpa2bv_rewriter.h | 2 +- src/ast/fpa_decl_plugin.cpp | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index 982b80d37..035e228fb 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -228,7 +228,7 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool u ast_manager & m = get_manager(); format * body = 0; string_buffer<> buf; - VERIFY(get_futil().is_value(t, v)); + VERIFY(get_futil().is_numeral(t, v)); if (fm.is_nan(v)) { buf << "(_ NaN " << v.get().get_ebits() << " " << v.get().get_sbits() << ")"; return mk_string(m, buf.c_str()); @@ -575,7 +575,7 @@ class smt2_printer { else if (m_env.get_bvutil().is_numeral(c)) { f = m_env.pp_bv_literal(c, m_pp_bv_lits, m_pp_bv_neg); } - else if (m_env.get_futil().is_value(c)) { + else if (m_env.get_futil().is_numeral(c)) { f = m_env.pp_float_literal(c, m_pp_bv_lits, m_pp_float_real_lits); } else if (m_env.get_dlutil().is_numeral(c)) { diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index efc4d9179..062c56ef2 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -50,7 +50,7 @@ protected: arith_util m_arith_util; mpf_manager & m_mpf_manager; unsynch_mpz_manager & m_mpz_manager; - fpa_decl_plugin * m_plugin; + fpa_decl_plugin * m_plugin; bool m_hi_fp_unspecified; obj_map m_const2bv; @@ -86,7 +86,7 @@ public: void mk_ite(expr * c, expr * t, expr * f, expr_ref & result); void mk_rounding_mode(func_decl * f, expr_ref & result); - void mk_value(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result); virtual void mk_const(func_decl * f, expr_ref & result); virtual void mk_rm_const(func_decl * f, expr_ref & result); void mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index c7a987b83..75176c9c4 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -120,7 +120,7 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FPA_RM_TOWARD_NEGATIVE: case OP_FPA_RM_TOWARD_POSITIVE: case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE; - case OP_FPA_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; + case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE; case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE; case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE; case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 7d4a77d1c..a8e805066 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -68,18 +68,18 @@ void fpa_decl_plugin::recycled_id(unsigned id) { m_fm.del(m_values[id]); } -func_decl * fpa_decl_plugin::mk_value_decl(mpf const & v) { +func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) { parameter p(mk_id(v), true); SASSERT(p.is_external()); sort * s = mk_float_sort(v.get_ebits(), v.get_sbits()); return m_manager->mk_const_decl(symbol("fpa"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p)); } -app * fpa_decl_plugin::mk_value(mpf const & v) { - return m_manager->mk_const(mk_value_decl(v)); +app * fpa_decl_plugin::mk_numeral(mpf const & v) { + return m_manager->mk_const(mk_numeral_decl(v)); } -bool fpa_decl_plugin::is_value(expr * n, mpf & val) { +bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) { if (is_app_of(n, m_family_id, OP_FPA_NUM)) { m_fm.set(val, m_values[to_app(n)->get_decl()->get_parameter(0).get_ext_id()]); return true; @@ -117,7 +117,7 @@ bool fpa_decl_plugin::is_value(expr * n, mpf & val) { return false; } -bool fpa_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) { +bool fpa_decl_plugin::is_rm_numeral(expr * n, mpf_rounding_mode & val) { if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_AWAY)) { val = MPF_ROUND_NEAREST_TAWAY; return true; @@ -260,7 +260,7 @@ func_decl * fpa_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_param case OP_FPA_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break; } - return mk_value_decl(val); + return mk_numeral_decl(val); } func_decl * fpa_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -846,7 +846,7 @@ expr * fpa_decl_plugin::get_some_value(sort * s) { SASSERT(s->is_sort_of(m_family_id, FLOATING_POINT_SORT)); mpf tmp; m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp); - expr * res = this->mk_value(tmp); + expr * res = this->mk_numeral(tmp); m_fm.del(tmp); return res; } From bcbce8f190d93117abaaefe0a6de94cccda468a7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 16:31:09 +0000 Subject: [PATCH 158/646] FPA Java and .NET API updates Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 1 - src/api/dotnet/Expr.cs | 270 ++++++++++++++++++++++++++++ src/api/dotnet/FPExpr.cs | 12 +- src/api/dotnet/FPNum.cs | 1 - src/api/dotnet/FPRMNum.cs | 49 +++++ src/api/java/Expr.java | 366 +++++++++++++++++++++++++++++++++++++- 6 files changed, 693 insertions(+), 6 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 609db802d..9eb544f8a 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4161,7 +4161,6 @@ namespace Microsoft.Z3 Contract.Ensures(Contract.Result() != null); return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); } - #endregion #region Conversions from FloatingPoint terms diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 826860eec..5f0c4218c 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1448,6 +1448,276 @@ namespace Microsoft.Z3 /// Indicates whether the term is a less than predicate over a finite domain. /// public bool IsFiniteDomainLT { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FD_LT; } } + #endregion + + #region Floating-point terms + /// + /// Indicates whether the terms is of floating-point sort. + /// + public bool IsFP + { + get { return Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_sort(Context.nCtx, NativeObject)) == (uint)Z3_sort_kind.Z3_FLOATING_POINT_SORT; } + } + + /// + /// Indicates whether the terms is of floating-point rounding mode sort. + /// + public bool IsFPRM + { + get { return Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_sort(Context.nCtx, NativeObject)) == (uint)Z3_sort_kind.Z3_ROUNDING_MODE_SORT; } + } + + /// + /// Indicates whether the term is a floating-point numeral + /// + public bool IsFPNumeral { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NUM; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool IsFPRMNumRoundNearestTiesToEven{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool IsFPRMNumRoundNearestTiesToAway{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool IsFPRMNumRoundTowardNegative{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool IsFPRMNumRoundTowardPositive{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool IsFPRMNumRoundTowardZero{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool IsFPRMNumRNE{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool IsFPRMNumRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool IsFPRMNumRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool IsFPRMNumRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool IsFPRMNumRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Indicates whether the term is a floating-point rounding mode numeral + /// + public bool IsFPRMNum { + get { + return IsApp && + (FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY|| + FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN || + FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE || + FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE || + FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO); + } + } + + /// + /// Indicates whether the term is a floating-point +oo + /// + public bool IsFPPlusInfinity{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_PLUS_INF; } } + + /// + /// Indicates whether the term is a floating-point -oo + /// + public bool IsFPMinusInfinity{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MINUS_INF; } } + + /// + /// Indicates whether the term is a floating-point NaN + /// + public bool IsFPNaN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NAN; } } + + /// + /// Indicates whether the term is a floating-point +zero + /// + public bool IsFPPlusZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO; } } + + /// + /// Indicates whether the term is a floating-point -zero + /// + public bool IsFPMinusZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO; } } + + /// + /// Indicates whether the term is a floating-point addition term + /// + public bool IsFPAdd { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ADD; } } + + + /// + /// Indicates whether the term is a floating-point subtraction term + /// + public bool IsFPSub { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_SUB; } } + + /// + /// Indicates whether the term is a floating-point negation term + /// + public bool IsFPNeg { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NEG; } } + + /// + /// Indicates whether the term is a floating-point multiplication term + /// + public bool IsFPMul { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MUL; } } + + /// + /// Indicates whether the term is a floating-point divison term + /// + public bool IsFPDiv { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_DIV; } } + + /// + /// Indicates whether the term is a floating-point remainder term + /// + public bool IsFPRem { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_REM; } } + + /// + /// Indicates whether the term is a floating-point term absolute value term + /// + public bool IsFPAbs { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ABS; } } + + /// + /// Indicates whether the term is a floating-point minimum term + /// + public bool IsFPMin { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MIN; } } + + /// + /// Indicates whether the term is a floating-point maximum term + /// + public bool IsFPMax { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_MAX; } } + + /// + /// Indicates whether the term is a floating-point fused multiply-add term + /// + public bool IsFPFMA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_FMA; } } + + /// + /// Indicates whether the term is a floating-point square root term + /// + public bool IsFPSqrt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_SQRT; } } + + /// + /// Indicates whether the term is a floating-point roundToIntegral term + /// + public bool IsFPRoundToIntegral { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL; } } + + /// + /// Indicates whether the term is a floating-point equality term + /// + public bool IsFPEq { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_EQ; } } + + /// + /// Indicates whether the term is a floating-point less-than term + /// + public bool IsFPLt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_LT; } } + + /// + /// Indicates whether the term is a floating-point greater-than term + /// + public bool IsFPGt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_GT; } } + + /// + /// Indicates whether the term is a floating-point less-than or equal term + /// + public bool IsFPLe { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_LE; } } + + /// + /// Indicates whether the term is a floating-point greater-than or erqual term + /// + public bool IsFPGe { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_GE; } } + + /// + /// Indicates whether the term is a floating-point isNaN predicate term + /// + public bool IsFPisNaN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NAN; } } + + /// + /// Indicates whether the term is a floating-point isInf predicate term + /// + public bool IsFPisInf { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_INF; } } + + /// + /// Indicates whether the term is a floating-point isZero predicate term + /// + public bool IsFPisZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_ZERO; } } + + /// + /// Indicates whether the term is a floating-point isNormal term + /// + public bool IsFPisNormal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NORMAL; } } + + /// + /// Indicates whether the term is a floating-point isSubnormal predicate term + /// + public bool IsFPisSubnormal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL; } } + + /// + /// Indicates whether the term is a floating-point isNegative predicate term + /// + public bool IsFPisNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE; } } + + /// + /// Indicates whether the term is a floating-point isPositive predicate term + /// + public bool IsFPisPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE; } } + + /// + /// Indicates whether the term is a floating-point constructor term + /// + public bool IsFPFP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_FP; } } + + /// + /// Indicates whether the term is a floating-point conversion term + /// + public bool IsFPToFp { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_FP; } } + + /// + /// Indicates whether the term is a floating-point conversion from unsigned bit-vector term + /// + public bool IsFPToFpUnsigned { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED; } } + + /// + /// Indicates whether the term is a floating-point conversion to unsigned bit-vector term + /// + public bool IsFPToUBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_UBV; } } + + /// + /// Indicates whether the term is a floating-point conversion to signed bit-vector term + /// + public bool IsFPToSBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_SBV; } } + + /// + /// Indicates whether the term is a floating-point conversion to real term + /// + public bool IsFPToReal { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_REAL; } } + + + /// + /// Indicates whether the term is a floating-point conversion to IEEE-754 bit-vector term + /// + public bool IsFPToIEEEBV { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV; } } + #endregion #endregion diff --git a/src/api/dotnet/FPExpr.cs b/src/api/dotnet/FPExpr.cs index cbba272d1..bbd557017 100644 --- a/src/api/dotnet/FPExpr.cs +++ b/src/api/dotnet/FPExpr.cs @@ -24,12 +24,22 @@ using System.Text; using System.Diagnostics.Contracts; namespace Microsoft.Z3 -{ +{ /// /// FloatingPoint Expressions /// public class FPExpr : Expr { + /// + /// The number of exponent bits. + /// + public uint EBits { get { return ((FPSort)Sort).EBits; } } + + /// + /// The number of significand bits. + /// + public uint SBits { get { return ((FPSort)Sort).EBits; } } + #region Internal /// Constructor for FPExpr internal protected FPExpr(Context ctx) diff --git a/src/api/dotnet/FPNum.cs b/src/api/dotnet/FPNum.cs index ab57d57c3..14c089198 100644 --- a/src/api/dotnet/FPNum.cs +++ b/src/api/dotnet/FPNum.cs @@ -27,7 +27,6 @@ namespace Microsoft.Z3 [ContractVerification(true)] public class FPNum : FPExpr { - #region Internal internal FPNum(Context ctx, IntPtr obj) : base(ctx, obj) diff --git a/src/api/dotnet/FPRMNum.cs b/src/api/dotnet/FPRMNum.cs index 7caa56f9f..628480d96 100644 --- a/src/api/dotnet/FPRMNum.cs +++ b/src/api/dotnet/FPRMNum.cs @@ -27,6 +27,55 @@ namespace Microsoft.Z3 [ContractVerification(true)] public class FPRMNum : FPRMExpr { + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } #region Internal internal FPRMNum(Context ctx, IntPtr obj) diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 233076516..4bd522b51 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -1709,6 +1709,366 @@ public class Expr extends AST return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FD_LT; } + + /** + * Indicates whether the terms is of floating-point sort. + * @throws Z3Exception + */ + public boolean IsFP() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_FLOATING_POINT_SORT; } + + /** + * Indicates whether the terms is of floating-point rounding mode sort. + * @return + * @throws Z3Exception + */ + public boolean IsFPRM() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_ROUNDING_MODE_SORT; } + + /** + * Indicates whether the term is a floating-point numeral + * @return + * @throws Z3Exception + */ + public boolean IsFPNumeral() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NUM; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRoundNearestTiesToEven() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRoundNearestTiesToAway() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardNegative + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRoundTowardNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardPositive + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRoundTowardPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardZero + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRoundTowardZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRNE() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRNA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardNegative + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRTN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardPositive + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRTP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardZero + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNumRTZ() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + + /** + * Indicates whether the term is a floating-point rounding mode numeral + * @return + * @throws Z3Exception + */ + public boolean IsFPRMNum() throws Z3Exception { + return isApp() && + (getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY || + getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN || + getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE || + getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE || + getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO); + } + + /** + * Indicates whether the term is a floating-point +oo + * @return + * @throws Z3Exception + */ + public boolean IsFPPlusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_INF; } + + /** + * Indicates whether the term is a floating-point -oo + * @return + * @throws Z3Exception + */ + public boolean IsFPMinusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_INF; } + + /** + * Indicates whether the term is a floating-point NaN + * @return + * @throws Z3Exception + */ + public boolean IsFPNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NAN; } + + /** + * Indicates whether the term is a floating-point +zero + * @return + * @throws Z3Exception + */ + public boolean IsFPPlusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO; } + + /** + * Indicates whether the term is a floating-point -zero + * @return + * @throws Z3Exception + */ + public boolean IsFPMinusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO; } + + /** + * Indicates whether the term is a floating-point addition term + * @return + * @throws Z3Exception + */ + public boolean IsFPAdd() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ADD; } + + + /** + * Indicates whether the term is a floating-point subtraction term + * @return + * @throws Z3Exception + */ + public boolean IsFPSub() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SUB; } + + /** + * Indicates whether the term is a floating-point negation term + * @return + * @throws Z3Exception + */ + public boolean IsFPNeg() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NEG; } + + /** + * Indicates whether the term is a floating-point multiplication term + * @return + * @throws Z3Exception + */ + public boolean IsFPMul() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MUL; } + + /** + * Indicates whether the term is a floating-point divison term + * @return + * @throws Z3Exception + */ + public boolean IsFPDiv() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_DIV; } + + /** + * Indicates whether the term is a floating-point remainder term + * @return + * @throws Z3Exception + */ + public boolean IsFPRem() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_REM; } + + /** + * Indicates whether the term is a floating-point term absolute value term + * @return + * @throws Z3Exception + */ + public boolean IsFPAbs() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ABS; } + + /** + * Indicates whether the term is a floating-point minimum term + * @return + * @throws Z3Exception + */ + public boolean IsFPMin() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MIN; } + + /** + * Indicates whether the term is a floating-point maximum term + * @return + * @throws Z3Exception + */ + public boolean IsFPMax() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MAX; } + + /** + * Indicates whether the term is a floating-point fused multiply-add term + * @return + * @throws Z3Exception + */ + public boolean IsFPFMA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FMA; } + + /** + * Indicates whether the term is a floating-point square root term + * @return + * @throws Z3Exception + */ + public boolean IsFPSqrt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SQRT; } + + /** + * Indicates whether the term is a floating-point roundToIntegral term + * @return + * @throws Z3Exception + */ + public boolean IsFPRoundToIntegral() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL; } + + /** + * Indicates whether the term is a floating-point equality term + * @return + * @throws Z3Exception + */ + public boolean IsFPEq() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_EQ; } + + /** + * Indicates whether the term is a floating-point less-than term + * @return + * @throws Z3Exception + */ + public boolean IsFPLt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LT; } + + /** + * Indicates whether the term is a floating-point greater-than term + * @return + * @throws Z3Exception + */ + public boolean IsFPGt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GT; } + + /** + * Indicates whether the term is a floating-point less-than or equal term + * @return + * @throws Z3Exception + */ + public boolean IsFPLe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LE; } + + /** + * Indicates whether the term is a floating-point greater-than or erqual term + * @return + * @throws Z3Exception + */ + public boolean IsFPGe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GE; } + + /** + * Indicates whether the term is a floating-point isNaN predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NAN; } + + /** + * Indicates whether the term is a floating-point isInf predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisInf() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_INF; } + + /** + * Indicates whether the term is a floating-point isZero predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_ZERO; } + + /** + * Indicates whether the term is a floating-point isNormal term + * @return + * @throws Z3Exception + */ + public boolean IsFPisNormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NORMAL; } + + /** + * Indicates whether the term is a floating-point isSubnormal predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisSubnormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL; } + + /** + * Indicates whether the term is a floating-point isNegative predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE; } + + /** + * Indicates whether the term is a floating-point isPositive predicate term + * @return + * @throws Z3Exception + */ + public boolean IsFPisPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE; } + + /** + * Indicates whether the term is a floating-point constructor term + * @return + * @throws Z3Exception + */ + public boolean IsFPFP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FP; } + + /** + * Indicates whether the term is a floating-point conversion term + * @return + * @throws Z3Exception + */ + public boolean IsFPToFp() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP; } + + /** + * Indicates whether the term is a floating-point conversion from unsigned bit-vector term + * @return + * @throws Z3Exception + */ + public boolean IsFPToFpUnsigned() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED; } + + /** + * Indicates whether the term is a floating-point conversion to unsigned bit-vector term + * @return + * @throws Z3Exception + */ + public boolean IsFPToUBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_UBV; } + + /** + * Indicates whether the term is a floating-point conversion to signed bit-vector term + * @return + * @throws Z3Exception + */ + public boolean IsFPToSBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_SBV; } + + /** + * Indicates whether the term is a floating-point conversion to real term + * @return + * @throws Z3Exception + */ + public boolean IsFPToReal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_REAL; } + + + /** + * Indicates whether the term is a floating-point conversion to IEEE-754 bit-vector term1 + * @return + * @throws Z3Exception + */ + public boolean IsFPToIEEEBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV; } + + /** * The de-Burijn index of a bound variable. Bound variables are * indexed by de-Bruijn indices. It is perhaps easiest to explain the @@ -1793,8 +2153,8 @@ public class Expr extends AST return new BitVecNum(ctx, obj); case Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); - case Z3_FLOATING_POINT_ROUNDING_MODE_SORT: - return new FPRMNum(ctx, obj); + case Z3_ROUNDING_MODE_SORT: + return new FPRMNum(ctx, obj); default: ; } } @@ -1815,7 +2175,7 @@ public class Expr extends AST return new DatatypeExpr(ctx, obj); case Z3_FLOATING_POINT_SORT: return new FPExpr(ctx, obj); - case Z3_FLOATING_POINT_ROUNDING_MODE_SORT: + case Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); default: ; } From ee2c9095c67bd8fee43b1d92a2b1db4d32b0d29c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 17:21:29 +0000 Subject: [PATCH 159/646] .NET FPA API overhaul Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 21 +++++++++++---------- src/api/dotnet/AST.cs | 12 ++++-------- src/api/dotnet/ArithExpr.cs | 5 ----- src/api/dotnet/ArrayExpr.cs | 5 ----- src/api/dotnet/BitVecExpr.cs | 1 - src/api/dotnet/BoolExpr.cs | 2 -- src/api/dotnet/DatatypeExpr.cs | 5 ----- src/api/dotnet/EnumSort.cs | 2 +- src/api/dotnet/Expr.cs | 4 ---- src/api/dotnet/FPExpr.cs | 5 ----- src/api/dotnet/FPRMExpr.cs | 5 ----- src/api/dotnet/IntExpr.cs | 5 ----- src/api/dotnet/ListSort.cs | 4 ++-- src/api/dotnet/Quantifier.cs | 4 ++-- src/api/dotnet/RealExpr.cs | 5 ----- src/api/dotnet/Sort.cs | 5 +++-- src/api/dotnet/TupleSort.cs | 2 +- 17 files changed, 24 insertions(+), 68 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index b03cfd28c..0c33d6793 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2084,25 +2084,26 @@ namespace test_mapi FPRMExpr rm = (FPRMExpr)ctx.MkConst(ctx.MkSymbol("rm"), rm_sort); BitVecExpr x = (BitVecExpr)ctx.MkConst(ctx.MkSymbol("x"), ctx.MkBitVecSort(64)); - FPExpr y = (FPExpr)ctx.MkConst(ctx.MkSymbol("y"), double_sort); - RealExpr real_val = ctx.MkReal(42); - BitVecExpr bv_val = ctx.MkBV(42, 64); + FPExpr y = (FPExpr)ctx.MkConst(ctx.MkSymbol("y"), double_sort); FPExpr fp_val = ctx.MkFP(42, double_sort); - BoolExpr c1 = ctx.MkEq(x, ctx.MkFPToIEEEBV(fp_val)); - BoolExpr c2 = ctx.MkEq(x, ctx.MkBV(42, 64)); - BoolExpr c3 = ctx.MkEq(fp_val, ctx.MkFPToFP(rm, real_val, double_sort)); - BoolExpr c4 = ctx.MkAnd(c1, c2); - Console.WriteLine("c3 = " + c3); + BoolExpr c1 = ctx.MkEq(y, fp_val); + BoolExpr c2 = ctx.MkEq(x, ctx.MkFPToBV(rm, y, 64, false)); + BoolExpr c3 = ctx.MkEq(x, ctx.MkBV(42, 64)); + BoolExpr c4 = ctx.MkEq(ctx.MkNumeral(42, ctx.RealSort), ctx.MkFPToReal(fp_val)); + BoolExpr c5 = ctx.MkAnd(c1, c2, c3, c4); + Console.WriteLine("c5 = " + c5); /* Generic solver */ Solver s = ctx.MkSolver(); - s.Assert(c3); + s.Assert(c5); + + Console.WriteLine(s); if (s.Check() != Status.SATISFIABLE) throw new TestFailedException(); - Console.WriteLine("OK, model: ", s.Model.ToString()); + Console.WriteLine("OK, model: {0}", s.Model.ToString()); } static void Main(string[] args) diff --git a/src/api/dotnet/AST.cs b/src/api/dotnet/AST.cs index 7bc4f6dfb..d3b31a325 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -227,10 +227,8 @@ namespace Microsoft.Z3 internal override void IncRef(IntPtr o) { // Console.WriteLine("AST IncRef()"); - if (Context == null) - throw new Z3Exception("inc() called on null context"); - if (o == IntPtr.Zero) - throw new Z3Exception("inc() called on null AST"); + if (Context == null || o == IntPtr.Zero) + return; Context.AST_DRQ.IncAndClear(Context, o); base.IncRef(o); } @@ -238,10 +236,8 @@ namespace Microsoft.Z3 internal override void DecRef(IntPtr o) { // Console.WriteLine("AST DecRef()"); - if (Context == null) - throw new Z3Exception("dec() called on null context"); - if (o == IntPtr.Zero) - throw new Z3Exception("dec() called on null AST"); + if (Context == null || o == IntPtr.Zero) + return; Context.AST_DRQ.Add(o); base.DecRef(o); } diff --git a/src/api/dotnet/ArithExpr.cs b/src/api/dotnet/ArithExpr.cs index bdfa7a3f0..7858ff3e1 100644 --- a/src/api/dotnet/ArithExpr.cs +++ b/src/api/dotnet/ArithExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for ArithExpr - internal protected ArithExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal ArithExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/ArrayExpr.cs b/src/api/dotnet/ArrayExpr.cs index 915bfd0f1..e14bb1083 100644 --- a/src/api/dotnet/ArrayExpr.cs +++ b/src/api/dotnet/ArrayExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for ArrayExpr - internal protected ArrayExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal ArrayExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/BitVecExpr.cs b/src/api/dotnet/BitVecExpr.cs index a146e7a19..b019f8845 100644 --- a/src/api/dotnet/BitVecExpr.cs +++ b/src/api/dotnet/BitVecExpr.cs @@ -41,7 +41,6 @@ namespace Microsoft.Z3 #region Internal /// Constructor for BitVecExpr - internal protected BitVecExpr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); } internal BitVecExpr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #endregion } diff --git a/src/api/dotnet/BoolExpr.cs b/src/api/dotnet/BoolExpr.cs index cbe3b1868..a9a15e4dc 100644 --- a/src/api/dotnet/BoolExpr.cs +++ b/src/api/dotnet/BoolExpr.cs @@ -32,8 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for BoolExpr - internal protected BoolExpr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); } - /// Constructor for BoolExpr internal BoolExpr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #endregion } diff --git a/src/api/dotnet/DatatypeExpr.cs b/src/api/dotnet/DatatypeExpr.cs index 93cea54f5..ba3a9d478 100644 --- a/src/api/dotnet/DatatypeExpr.cs +++ b/src/api/dotnet/DatatypeExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for DatatypeExpr - internal protected DatatypeExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal DatatypeExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/EnumSort.cs b/src/api/dotnet/EnumSort.cs index e62043078..f7ba98222 100644 --- a/src/api/dotnet/EnumSort.cs +++ b/src/api/dotnet/EnumSort.cs @@ -78,7 +78,7 @@ namespace Microsoft.Z3 #region Internal internal EnumSort(Context ctx, Symbol name, Symbol[] enumNames) - : base(ctx) + : base(ctx, IntPtr.Zero) { Contract.Requires(ctx != null); Contract.Requires(name != null); diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 5f0c4218c..97e57b920 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1759,10 +1759,6 @@ namespace Microsoft.Z3 /// /// Constructor for Expr /// - internal protected Expr(Context ctx) : base(ctx) { Contract.Requires(ctx != null); } - /// - /// Constructor for Expr - /// internal protected Expr(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #if DEBUG diff --git a/src/api/dotnet/FPExpr.cs b/src/api/dotnet/FPExpr.cs index bbd557017..85fdf2603 100644 --- a/src/api/dotnet/FPExpr.cs +++ b/src/api/dotnet/FPExpr.cs @@ -42,11 +42,6 @@ namespace Microsoft.Z3 #region Internal /// Constructor for FPExpr - internal protected FPExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal FPExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs index 92fea1ad4..896c3e6b9 100644 --- a/src/api/dotnet/FPRMExpr.cs +++ b/src/api/dotnet/FPRMExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for FPRMExpr - internal protected FPRMExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal FPRMExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/IntExpr.cs b/src/api/dotnet/IntExpr.cs index 58bf1b973..622be7bd5 100644 --- a/src/api/dotnet/IntExpr.cs +++ b/src/api/dotnet/IntExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for IntExpr - internal protected IntExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal IntExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/ListSort.cs b/src/api/dotnet/ListSort.cs index 7dbafb385..e860e4d4b 100644 --- a/src/api/dotnet/ListSort.cs +++ b/src/api/dotnet/ListSort.cs @@ -113,9 +113,9 @@ namespace Microsoft.Z3 } } - #region Internal + #region Internal internal ListSort(Context ctx, Symbol name, Sort elemSort) - : base(ctx) + : base(ctx, IntPtr.Zero) { Contract.Requires(ctx != null); Contract.Requires(name != null); diff --git a/src/api/dotnet/Quantifier.cs b/src/api/dotnet/Quantifier.cs index f59d0bda2..38e435309 100644 --- a/src/api/dotnet/Quantifier.cs +++ b/src/api/dotnet/Quantifier.cs @@ -160,7 +160,7 @@ namespace Microsoft.Z3 #region Internal [ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug internal Quantifier(Context ctx, bool isForall, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - : base(ctx) + : base(ctx, IntPtr.Zero) { Contract.Requires(ctx != null); Contract.Requires(sorts != null); @@ -203,7 +203,7 @@ namespace Microsoft.Z3 [ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug internal Quantifier(Context ctx, bool isForall, Expr[] bound, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - : base(ctx) + : base(ctx, IntPtr.Zero) { Contract.Requires(ctx != null); Contract.Requires(body != null); diff --git a/src/api/dotnet/RealExpr.cs b/src/api/dotnet/RealExpr.cs index 26adc1fc6..8ee8c8e76 100644 --- a/src/api/dotnet/RealExpr.cs +++ b/src/api/dotnet/RealExpr.cs @@ -32,11 +32,6 @@ namespace Microsoft.Z3 { #region Internal /// Constructor for RealExpr - internal protected RealExpr(Context ctx) - : base(ctx) - { - Contract.Requires(ctx != null); - } internal RealExpr(Context ctx, IntPtr obj) : base(ctx, obj) { diff --git a/src/api/dotnet/Sort.cs b/src/api/dotnet/Sort.cs index 9dc23ea09..412398ddd 100644 --- a/src/api/dotnet/Sort.cs +++ b/src/api/dotnet/Sort.cs @@ -116,8 +116,7 @@ namespace Microsoft.Z3 #region Internal /// /// Sort constructor - /// - internal protected Sort(Context ctx) : base(ctx) { Contract.Requires(ctx != null); } + /// internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); } #if DEBUG @@ -146,6 +145,8 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_UNINTERPRETED_SORT: return new UninterpretedSort(ctx, obj); case Z3_sort_kind.Z3_FINITE_DOMAIN_SORT: return new FiniteDomainSort(ctx, obj); case Z3_sort_kind.Z3_RELATION_SORT: return new RelationSort(ctx, obj); + case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPSort(ctx, obj); + case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMSort(ctx, obj); default: throw new Z3Exception("Unknown sort kind"); } diff --git a/src/api/dotnet/TupleSort.cs b/src/api/dotnet/TupleSort.cs index 81a0eaf60..ea99f3855 100644 --- a/src/api/dotnet/TupleSort.cs +++ b/src/api/dotnet/TupleSort.cs @@ -68,7 +68,7 @@ namespace Microsoft.Z3 #region Internal internal TupleSort(Context ctx, Symbol name, uint numFields, Symbol[] fieldNames, Sort[] fieldSorts) - : base(ctx) + : base(ctx, IntPtr.Zero) { Contract.Requires(ctx != null); Contract.Requires(name != null); From 7fe9ad5cb4a7829374e04f318d8b1b7bfd8b5b21 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 17:22:02 +0000 Subject: [PATCH 160/646] Java FPA API overhaul Signed-off-by: Christoph M. Wintersteiger --- examples/java/JavaExample.java | 20 ++++++++++---------- src/api/java/AST.java | 12 ++++-------- src/api/java/ArithExpr.java | 5 ----- src/api/java/ArrayExpr.java | 5 ----- src/api/java/BitVecExpr.java | 5 ----- src/api/java/BoolExpr.java | 8 -------- src/api/java/Context.java | 6 +----- src/api/java/DatatypeExpr.java | 5 ----- src/api/java/EnumSort.java | 2 +- src/api/java/Expr.java | 15 +-------------- src/api/java/IntExpr.java | 5 ----- src/api/java/ListSort.java | 2 +- src/api/java/Quantifier.java | 4 ++-- src/api/java/RealExpr.java | 5 ----- src/api/java/Sort.java | 13 ++++--------- src/api/java/TupleSort.java | 2 +- 16 files changed, 25 insertions(+), 89 deletions(-) diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 878ec4693..af8662700 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -2212,29 +2212,29 @@ class JavaExample { System.out.println("FloatingPointExample2"); Log.append("FloatingPointExample2"); - FPSort double_sort = ctx.mkFPSort(11, 53); FPRMSort rm_sort = ctx.mkFPRoundingModeSort(); FPRMExpr rm = (FPRMExpr)ctx.mkConst(ctx.mkSymbol("rm"), rm_sort); BitVecExpr x = (BitVecExpr)ctx.mkConst(ctx.mkSymbol("x"), ctx.mkBitVecSort(64)); - RealExpr real_val = ctx.mkReal(42); + FPExpr y = (FPExpr)ctx.mkConst(ctx.mkSymbol("y"), double_sort); FPExpr fp_val = ctx.mkFP(42, double_sort); - - BoolExpr c1 = ctx.mkEq(x, ctx.mkFPToIEEEBV(fp_val)); - BoolExpr c2 = ctx.mkEq(x, ctx.mkBV(42, 64)); - BoolExpr c3 = ctx.mkEq(fp_val, ctx.mkFPToFP(rm, real_val, double_sort)); - BoolExpr c4 = ctx.mkAnd(c1, c2); - System.out.println("c3 = " + c3); + + BoolExpr c1 = ctx.mkEq(y, fp_val); + BoolExpr c2 = ctx.mkEq(x, ctx.mkFPToBV(rm, y, 64, false)); + BoolExpr c3 = ctx.mkEq(x, ctx.mkBV(42, 64)); + BoolExpr c4 = ctx.mkEq(ctx.mkNumeral(42, ctx.getRealSort()), ctx.mkFPToReal(fp_val)); + BoolExpr c5 = ctx.mkAnd(c1, c2, c3, c4); + System.out.println("c5 = " + c5); /* Generic solver */ Solver s = ctx.mkSolver(); - s.add(c3); + s.add(c5); if (s.check() != Status.SATISFIABLE) throw new TestFailedException(); - System.out.println("OK, model: " + s.getModel().toString()); + System.out.println("OK, model: " + s.getModel().toString()); } public static void main(String[] args) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 579d4b24d..5bea58054 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -213,10 +213,8 @@ public class AST extends Z3Object void incRef(long o) throws Z3Exception { // Console.WriteLine("AST IncRef()"); - if (getContext() == null) - throw new Z3Exception("inc() called on null context"); - if (o == 0) - throw new Z3Exception("inc() called on null AST"); + if (getContext() == null || o == 0) + return; getContext().ast_DRQ().incAndClear(getContext(), o); super.incRef(o); } @@ -224,10 +222,8 @@ public class AST extends Z3Object void decRef(long o) throws Z3Exception { // Console.WriteLine("AST DecRef()"); - if (getContext() == null) - throw new Z3Exception("dec() called on null context"); - if (o == 0) - throw new Z3Exception("dec() called on null AST"); + if (getContext() == null || o == 0) + return; getContext().ast_DRQ().add(o); super.decRef(o); } diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index 83ec35d01..97873f0b0 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -25,11 +25,6 @@ public class ArithExpr extends Expr /** * Constructor for ArithExpr **/ - protected ArithExpr(Context ctx) - { - super(ctx); - } - ArithExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index 2d5a5a273..2985d19a2 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -26,11 +26,6 @@ public class ArrayExpr extends Expr /** * Constructor for ArrayExpr **/ - protected ArrayExpr(Context ctx) - { - super(ctx); - } - ArrayExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 24b1cfdf3..a7c704497 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -35,11 +35,6 @@ public class BitVecExpr extends Expr /** * Constructor for BitVecExpr **/ - BitVecExpr(Context ctx) - { - super(ctx); - } - BitVecExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index 99453496a..8f9d10d18 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -22,14 +22,6 @@ package com.microsoft.z3; **/ public class BoolExpr extends Expr { - /** - * Constructor for BoolExpr - **/ - protected BoolExpr(Context ctx) - { - super(ctx); - } - /** * Constructor for BoolExpr * @throws Z3Exception diff --git a/src/api/java/Context.java b/src/api/java/Context.java index cd3b9bebd..cfbd7c2c8 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -504,14 +504,10 @@ public class Context extends IDisposable **/ public Expr mkConst(Symbol name, Sort range) throws Z3Exception { - checkContextMatch(name); checkContextMatch(range); - return Expr.create( - this, - Native.mkConst(nCtx(), name.getNativeObject(), - range.getNativeObject())); + return Expr.create(this, Native.mkConst(nCtx(), name.getNativeObject(), range.getNativeObject())); } /** diff --git a/src/api/java/DatatypeExpr.java b/src/api/java/DatatypeExpr.java index 806ceacab..d4612e6ff 100644 --- a/src/api/java/DatatypeExpr.java +++ b/src/api/java/DatatypeExpr.java @@ -25,11 +25,6 @@ public class DatatypeExpr extends Expr /** * Constructor for DatatypeExpr **/ - protected DatatypeExpr(Context ctx) - { - super(ctx); - } - DatatypeExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/EnumSort.java b/src/api/java/EnumSort.java index 9715b9a97..51bdfe0e8 100644 --- a/src/api/java/EnumSort.java +++ b/src/api/java/EnumSort.java @@ -60,7 +60,7 @@ public class EnumSort extends Sort EnumSort(Context ctx, Symbol name, Symbol[] enumNames) throws Z3Exception { - super(ctx); + super(ctx, 0); int n = enumNames.length; long[] n_constdecls = new long[n]; diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 4bd522b51..886c69f08 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -2092,24 +2092,12 @@ public class Expr extends AST return Native.getIndexValue(getContext().nCtx(), getNativeObject()); } - /** - * Constructor for Expr - **/ - protected Expr(Context ctx) - { - super(ctx); - { - } - } - /** * Constructor for Expr **/ protected Expr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); - { - } } void checkNativeObject(long obj) throws Z3Exception @@ -2135,8 +2123,7 @@ public class Expr extends AST if (k == Z3_ast_kind.Z3_QUANTIFIER_AST) return new Quantifier(ctx, obj); long s = Native.getSort(ctx.nCtx(), obj); - Z3_sort_kind sk = Z3_sort_kind - .fromInt(Native.getSortKind(ctx.nCtx(), s)); + Z3_sort_kind sk = Z3_sort_kind.fromInt(Native.getSortKind(ctx.nCtx(), s)); if (Native.isAlgebraicNumber(ctx.nCtx(), obj)) // is this a numeral ast? return new AlgebraicNum(ctx, obj); diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index 2e90c3cbf..de3ae222a 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -25,11 +25,6 @@ public class IntExpr extends ArithExpr /** * Constructor for IntExpr **/ - protected IntExpr(Context ctx) throws Z3Exception - { - super(ctx); - } - IntExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/ListSort.java b/src/api/java/ListSort.java index 52cb1a179..a7ad0403b 100644 --- a/src/api/java/ListSort.java +++ b/src/api/java/ListSort.java @@ -88,7 +88,7 @@ public class ListSort extends Sort ListSort(Context ctx, Symbol name, Sort elemSort) throws Z3Exception { - super(ctx); + super(ctx, 0); Native.LongPtr inil = new Native.LongPtr(), iisnil = new Native.LongPtr(); Native.LongPtr icons = new Native.LongPtr(), iiscons = new Native.LongPtr(); diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index e9aeefcca..58245d723 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -149,7 +149,7 @@ public class Quantifier extends BoolExpr Expr body, int weight, Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID, Symbol skolemID) throws Z3Exception { - super(ctx); + super(ctx, 0); getContext().checkContextMatch(patterns); getContext().checkContextMatch(noPatterns); @@ -185,7 +185,7 @@ public class Quantifier extends BoolExpr int weight, Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID, Symbol skolemID) throws Z3Exception { - super(ctx); + super(ctx, 0); getContext().checkContextMatch(noPatterns); getContext().checkContextMatch(patterns); diff --git a/src/api/java/RealExpr.java b/src/api/java/RealExpr.java index 6188e2999..c699e13e2 100644 --- a/src/api/java/RealExpr.java +++ b/src/api/java/RealExpr.java @@ -25,11 +25,6 @@ public class RealExpr extends ArithExpr /** * Constructor for RealExpr **/ - protected RealExpr(Context ctx) - { - super(ctx); - } - RealExpr(Context ctx, long obj) throws Z3Exception { super(ctx, obj); diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 7d89428c6..fa556e67f 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -98,18 +98,9 @@ public class Sort extends AST /** * Sort constructor **/ - protected Sort(Context ctx) throws Z3Exception - { - super(ctx); - { - } - } - Sort(Context ctx, long obj) throws Z3Exception { super(ctx, obj); - { - } } void checkNativeObject(long obj) throws Z3Exception @@ -143,6 +134,10 @@ public class Sort extends AST return new FiniteDomainSort(ctx, obj); case Z3_RELATION_SORT: return new RelationSort(ctx, obj); + case Z3_FLOATING_POINT_SORT: + return new FPSort(ctx, obj); + case Z3_ROUNDING_MODE_SORT: + return new FPRMSort(ctx, obj); default: throw new Z3Exception("Unknown sort kind"); } diff --git a/src/api/java/TupleSort.java b/src/api/java/TupleSort.java index 523f8d676..87572b9ee 100644 --- a/src/api/java/TupleSort.java +++ b/src/api/java/TupleSort.java @@ -59,7 +59,7 @@ public class TupleSort extends Sort TupleSort(Context ctx, Symbol name, int numFields, Symbol[] fieldNames, Sort[] fieldSorts) throws Z3Exception { - super(ctx); + super(ctx, 0); Native.LongPtr t = new Native.LongPtr(); setNativeObject(Native.mkTupleSort(ctx.nCtx(), name.getNativeObject(), From cad841cff46cd380cec19fff5fc2a66dbef4aa29 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 17:23:13 +0000 Subject: [PATCH 161/646] to_fp_real marked as NIY for now Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 4c570c1ba..743434341 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2064,7 +2064,7 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * unsigned ebits = m_util.get_ebits(s); unsigned sbits = m_util.get_sbits(s); - if (false && m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) { + if (m_bv_util.is_numeral(rm) && m_util.au().is_numeral(x)) { rational tmp_rat; unsigned sz; m_bv_util.is_numeral(to_expr(rm), tmp_rat, sz); SASSERT(tmp_rat.is_int32()); @@ -2096,6 +2096,8 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * mk_triple(sgn, s, e, result); } else { + NOT_IMPLEMENTED_YET(); + mpf_manager & fm = fu().fm(); bv_util & bu = m_bv_util; arith_util & au = m_arith_util; @@ -2135,16 +2137,16 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * //dbg_decouple("fpa2bv_to_float_real_inc", inc); //sig = m.mk_ite(inc, bu.mk_bv_add(sig, bv1_s4), sig); - SASSERT(bu.get_bv_size(sgn) == 1); - SASSERT(bu.get_bv_size(sig) == sbits + 4); - SASSERT(bu.get_bv_size(exp) == ebits + 2); + //SASSERT(bu.get_bv_size(sgn) == 1); + //SASSERT(bu.get_bv_size(sig) == sbits + 4); + //SASSERT(bu.get_bv_size(exp) == ebits + 2); - dbg_decouple("fpa2bv_to_float_real_sgn", sgn); - dbg_decouple("fpa2bv_to_float_real_sig", sig); - dbg_decouple("fpa2bv_to_float_real_exp", exp); + //dbg_decouple("fpa2bv_to_float_real_sgn", sgn); + //dbg_decouple("fpa2bv_to_float_real_sig", sig); + //dbg_decouple("fpa2bv_to_float_real_exp", exp); - expr_ref rmr(rm, m); - round(s, rmr, sgn, sig, exp, result); + //expr_ref rmr(rm, m); + //round(s, rmr, sgn, sig, exp, result); } SASSERT(is_well_sorted(m, result)); From 0381e4317ab7e5e2212ac4b36c1ed384456adf39 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 17:54:04 +0000 Subject: [PATCH 162/646] Formatting, mostly tabs. Signed-off-by: Christoph M. Wintersteiger --- src/api/api_numeral.cpp | 2 +- src/ast/ast.cpp | 52 +- src/ast/fpa/fpa2bv_converter.cpp | 2 +- src/ast/rewriter/dl_rewriter.cpp | 48 +- src/duality/duality_profiling.cpp | 22 +- src/duality/duality_rpfp.cpp | 2686 +++++++++++----------- src/muz/base/dl_context.cpp | 12 +- src/muz/duality/duality_dl_interface.cpp | 86 +- src/muz/transforms/dl_transforms.cpp | 2 +- src/tactic/aig/aig.cpp | 14 +- 10 files changed, 1448 insertions(+), 1478 deletions(-) diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 7789f1157..0745a8709 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -173,7 +173,7 @@ extern "C" { 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); } diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 09965be85..5679c951b 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -413,16 +413,16 @@ sort * get_sort(expr const * n) { // // ----------------------------------- -unsigned get_node_size(ast const * n) { - switch(n->get_kind()) { - case AST_SORT: return to_sort(n)->get_size(); - case AST_FUNC_DECL: return to_func_decl(n)->get_size(); - case AST_APP: return to_app(n)->get_size(); - case AST_VAR: return to_var(n)->get_size(); - case AST_QUANTIFIER: return to_quantifier(n)->get_size(); - default: UNREACHABLE(); - } - return 0; +unsigned get_node_size(ast const * n) { + switch(n->get_kind()) { + case AST_SORT: return to_sort(n)->get_size(); + case AST_FUNC_DECL: return to_func_decl(n)->get_size(); + case AST_APP: return to_app(n)->get_size(); + case AST_VAR: return to_var(n)->get_size(); + case AST_QUANTIFIER: return to_quantifier(n)->get_size(); + default: UNREACHABLE(); + } + return 0; } bool compare_nodes(ast const * n1, ast const * n2) { @@ -737,7 +737,7 @@ func_decl * basic_decl_plugin::mk_proof_decl( for (unsigned i = 0; i < num_parents; i++) domain.push_back(m_proof_sort); domain.push_back(m_bool_sort); - func_decl_info info(m_family_id, k, num_parameters, params); + func_decl_info info(m_family_id, k, num_parameters, params); return m_manager->mk_func_decl(symbol(name), num_parents+1, domain.c_ptr(), m_proof_sort, info); } @@ -1643,12 +1643,12 @@ ast * ast_manager::register_node_core(ast * n) { to_func_decl(n)->m_info = alloc(func_decl_info, *(to_func_decl(n)->get_info())); to_func_decl(n)->m_info->init_eh(*this); } - inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain()); - inc_ref(to_func_decl(n)->get_range()); - break; + inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain()); + inc_ref(to_func_decl(n)->get_range()); + break; case AST_APP: { app * t = to_app(n); - inc_ref(t->get_decl()); + inc_ref(t->get_decl()); unsigned num_args = t->get_num_args(); if (num_args > 0) { app_flags * f = t->flags(); @@ -1696,19 +1696,19 @@ ast * ast_manager::register_node_core(ast * n) { f->m_depth = depth; SASSERT(t->get_depth() == depth); } - break; + break; } case AST_VAR: inc_ref(to_var(n)->get_sort()); break; case AST_QUANTIFIER: - inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts()); - inc_ref(to_quantifier(n)->get_expr()); + inc_array_ref(to_quantifier(n)->get_num_decls(), to_quantifier(n)->get_decl_sorts()); + inc_ref(to_quantifier(n)->get_expr()); inc_array_ref(to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns()); inc_array_ref(to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns()); - break; + break; default: - break; + break; } return n; } @@ -1721,7 +1721,7 @@ void ast_manager::delete_node(ast * n) { while (!worklist.empty()) { n = worklist.back(); worklist.pop_back(); - + TRACE("ast", tout << "Deleting object " << n->m_id << " " << n << "\n";); CTRACE("del_quantifier", is_quantifier(n), tout << "deleting quantifier " << n->m_id << " " << n << "\n";); TRACE("mk_var_bug", tout << "del_ast: " << n->m_id << "\n";); @@ -1770,8 +1770,8 @@ void ast_manager::delete_node(ast * n) { dec_array_ref(worklist, to_quantifier(n)->get_num_patterns(), to_quantifier(n)->get_patterns()); dec_array_ref(worklist, to_quantifier(n)->get_num_no_patterns(), to_quantifier(n)->get_no_patterns()); break; - default: - break; + default: + break; } if (m_debug_ref_count) { m_debug_free_indices.insert(n->m_id,0); @@ -2567,9 +2567,9 @@ proof * ast_manager::mk_transitivity(proof * p1, proof * p2) { (is_eq(get_fact(p2)) || is_oeq(get_fact(p2))))); CTRACE("mk_transitivity", to_app(get_fact(p1))->get_arg(1) != to_app(get_fact(p2))->get_arg(0), tout << mk_pp(get_fact(p1), *this) << "\n\n" << mk_pp(get_fact(p2), *this) << "\n"; - tout << mk_bounded_pp(p1, *this, 5) << "\n\n"; - tout << mk_bounded_pp(p2, *this, 5) << "\n\n"; - ); + tout << mk_bounded_pp(p1, *this, 5) << "\n\n"; + tout << mk_bounded_pp(p2, *this, 5) << "\n\n"; + ); SASSERT(to_app(get_fact(p1))->get_arg(1) == to_app(get_fact(p2))->get_arg(0)); if (is_reflexivity(p1)) return p2; diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 743434341..f6ce259f2 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -3197,7 +3197,7 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { #ifdef Z3DEBUG - // return; + return; // CMW: This works only for quantifier-free formulas. expr_ref new_e(m); new_e = m.mk_fresh_const(prefix, m.get_sort(e)); diff --git a/src/ast/rewriter/dl_rewriter.cpp b/src/ast/rewriter/dl_rewriter.cpp index 9b79775d5..ddae6c9eb 100644 --- a/src/ast/rewriter/dl_rewriter.cpp +++ b/src/ast/rewriter/dl_rewriter.cpp @@ -24,31 +24,31 @@ Revision History: ast_manager& m = result.get_manager(); uint64 v1, v2; switch(f->get_decl_kind()) { - case datalog::OP_DL_LT: - if (m_util.is_numeral_ext(args[0], v1) && - m_util.is_numeral_ext(args[1], v2)) { - result = (v1 < v2)?m.mk_true():m.mk_false(); - return BR_DONE; - } - // x < x <=> false - if (args[0] == args[1]) { - result = m.mk_false(); - return BR_DONE; - } - // x < 0 <=> false - if (m_util.is_numeral_ext(args[1], v2) && v2 == 0) { - result = m.mk_false(); - return BR_DONE; - } - // 0 < x <=> 0 != x - if (m_util.is_numeral_ext(args[1], v1) && v1 == 0) { - result = m.mk_not(m.mk_eq(args[0], args[1])); - return BR_DONE; - } - break; + case datalog::OP_DL_LT: + if (m_util.is_numeral_ext(args[0], v1) && + m_util.is_numeral_ext(args[1], v2)) { + result = (v1 < v2)?m.mk_true():m.mk_false(); + return BR_DONE; + } + // x < x <=> false + if (args[0] == args[1]) { + result = m.mk_false(); + return BR_DONE; + } + // x < 0 <=> false + if (m_util.is_numeral_ext(args[1], v2) && v2 == 0) { + result = m.mk_false(); + return BR_DONE; + } + // 0 < x <=> 0 != x + if (m_util.is_numeral_ext(args[1], v1) && v1 == 0) { + result = m.mk_not(m.mk_eq(args[0], args[1])); + return BR_DONE; + } + break; - default: - break; + default: + break; } return BR_FAILED; } diff --git a/src/duality/duality_profiling.cpp b/src/duality/duality_profiling.cpp index 5bcda972a..13a379946 100755 --- a/src/duality/duality_profiling.cpp +++ b/src/duality/duality_profiling.cpp @@ -124,20 +124,20 @@ namespace Duality { } void timer_stop(const char *name){ - if(current->name != name || !current->parent){ + if (current->name != name || !current->parent) { #if 0 - std::cerr << "imbalanced timer_start and timer_stop"; - exit(1); + std::cerr << "imbalanced timer_start and timer_stop"; + exit(1); #endif - // in case we lost a timer stop due to an exception - while(current->name != name && current->parent) - current = current->parent; - if(current->parent){ - current->time += (current_time() - current->start_time); - current = current->parent; + // in case we lost a timer stop due to an exception + while (current->name != name && current->parent) + current = current->parent; + if (current->parent) { + current->time += (current_time() - current->start_time); + current = current->parent; + } + return; } - return; - } current->time += (current_time() - current->start_time); current = current->parent; } diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index cdc8fb3b2..6ef6d623a 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -97,12 +97,12 @@ namespace Duality { memo.insert(t); if(t.is_app()){ decl_kind k = t.decl().get_decl_kind(); - if(k == And || k == Or || k == Not || k == Implies || k == Iff){ - ops++; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - SummarizeRec(memo,lits,ops,t.arg(i)); - return; + if (k == And || k == Or || k == Not || k == Implies || k == Iff) { + ops++; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + SummarizeRec(memo, lits, ops, t.arg(i)); + return; } } lits.push_back(t); @@ -137,12 +137,12 @@ namespace Duality { memo.insert(t); if(t.is_app()){ decl_kind k = t.decl().get_decl_kind(); - if(k == And || k == Or){ - int count = 1; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - count += CountOperatorsRec(memo,t.arg(i)); - return count; + if (k == And || k == Or) { + int count = 1; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + count += CountOperatorsRec(memo, t.arg(i)); + return count; } return 0; } @@ -172,13 +172,12 @@ namespace Duality { Term b(ctx); std::vector v; RedVars(child, b, v); - for (unsigned i = 0; i < args.size(); i++) - { - if (eq(args[i].get_sort(),ctx.bool_sort())) - args[i] = ctx.make(Iff,args[i], v[i]); - else - args[i] = args[i] == v[i]; - } + for (unsigned i = 0; i < args.size(); i++) { + if (eq(args[i].get_sort(), ctx.bool_sort())) + args[i] = ctx.make(Iff, args[i], v[i]); + else + args[i] = args[i] == v[i]; + } return args.size() > 0 ? (b && conjoin(args)) : b; } @@ -202,18 +201,18 @@ namespace Duality { names.push_back(Z3_get_quantifier_bound_name(c,a,i)); } Z3_ast foo = Z3_mk_quantifier_ex(c, - Z3_is_quantifier_forall(c,a), - Z3_get_quantifier_weight(c,a), - 0, - 0, - num_pats, - &pats[0], - num_no_pats, - &no_pats[0], - bound, - &sorts[0], - &names[0], - new_body); + Z3_is_quantifier_forall(c,a), + Z3_get_quantifier_weight(c,a), + 0, + 0, + num_pats, + &pats[0], + num_no_pats, + &no_pats[0], + bound, + &sorts[0], + &names[0], + new_body); return expr(ctx,foo); #endif return clone_quantifier(t,new_body); @@ -231,36 +230,32 @@ namespace Duality { res = it->second; return res; } - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(LocalizeRec(e, memo, t.arg(i))); - hash_map::iterator rit = e->relMap.find(f); - if(rit != e->relMap.end()) - res = RedDualRela(e,args,(rit->second)); - else { - if (args.size() == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)) - { - res = HideVariable(t,e->number); - } - else - { - res = f(args.size(),&args[0]); - } - } - } - else if (t.is_quantifier()) - { - std::vector pats; - t.get_patterns(pats); - for(unsigned i = 0; i < pats.size(); i++) - pats[i] = LocalizeRec(e,memo,pats[i]); - Term body = LocalizeRec(e,memo,t.body()); - res = clone_quantifier(t, body, pats); - } + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(LocalizeRec(e, memo, t.arg(i))); + hash_map::iterator rit = e->relMap.find(f); + if (rit != e->relMap.end()) + res = RedDualRela(e, args, (rit->second)); + else { + if (args.size() == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)) { + res = HideVariable(t, e->number); + } + else { + res = f(args.size(), &args[0]); + } + } + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = LocalizeRec(e, memo, pats[i]); + Term body = LocalizeRec(e, memo, t.body()); + res = clone_quantifier(t, body, pats); + } else res = t; return res; } @@ -353,24 +348,22 @@ namespace Duality { std::pair::iterator, bool> bar = memo.insert(foo); Term &res = bar.first->second; if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, t.arg(i))); - res = f(args.size(),&args[0]); - } - else if (t.is_quantifier()) - { - std::vector pats; - t.get_patterns(pats); - for(unsigned i = 0; i < pats.size(); i++) - pats[i] = SubstRec(memo,pats[i]); - Term body = SubstRec(memo,t.body()); - res = clone_quantifier(t, body, pats); - } + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(SubstRec(memo, t.arg(i))); + res = f(args.size(), &args[0]); + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = SubstRec(memo, pats[i]); + Term body = SubstRec(memo, t.body()); + res = clone_quantifier(t, body, pats); + } // res = CloneQuantifier(t,SubstRec(memo, t.body())); else res = t; return res; @@ -382,27 +375,25 @@ namespace Duality { std::pair::iterator, bool> bar = memo.insert(foo); Term &res = bar.first->second; if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, map, t.arg(i))); - hash_map::iterator it = map.find(f); - if(it != map.end()) - f = it->second; - res = f(args.size(),&args[0]); - } - else if (t.is_quantifier()) - { - std::vector pats; - t.get_patterns(pats); - for(unsigned i = 0; i < pats.size(); i++) - pats[i] = SubstRec(memo, map, pats[i]); - Term body = SubstRec(memo, map, t.body()); - res = clone_quantifier(t, body, pats); - } + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(SubstRec(memo, map, t.arg(i))); + hash_map::iterator it = map.find(f); + if (it != map.end()) + f = it->second; + res = f(args.size(), &args[0]); + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = SubstRec(memo, map, pats[i]); + Term body = SubstRec(memo, map, t.body()); + res = clone_quantifier(t, body, pats); + } // res = CloneQuantifier(t,SubstRec(memo, t.body())); else res = t; return res; @@ -415,20 +406,20 @@ namespace Duality { Term &res = bar.first->second; if(!bar.second) return res; if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(ExtractStores(memo, t.arg(i),cnstrs,renaming)); - res = f(args.size(),&args[0]); - if(f.get_decl_kind() == Store){ - func_decl fresh = ctx.fresh_func_decl("@arr", res.get_sort()); - expr y = fresh(); - expr equ = ctx.make(Equal,y,res); - cnstrs.push_back(equ); - renaming[y] = res; - res = y; - } + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(ExtractStores(memo, t.arg(i), cnstrs, renaming)); + res = f(args.size(), &args[0]); + if (f.get_decl_kind() == Store) { + func_decl fresh = ctx.fresh_func_decl("@arr", res.get_sort()); + expr y = fresh(); + expr equ = ctx.make(Equal, y, res); + cnstrs.push_back(equ); + renaming[y] = res; + res = y; + } } else res = t; return res; @@ -436,20 +427,20 @@ namespace Duality { bool Z3User::IsLiteral(const expr &lit, expr &atom, expr &val){ - if(!(lit.is_quantifier() && IsClosedFormula(lit))){ - if(!lit.is_app()) - return false; - decl_kind k = lit.decl().get_decl_kind(); - if(k == Not){ - if(IsLiteral(lit.arg(0),atom,val)){ - val = eq(val,ctx.bool_val(true)) ? ctx.bool_val(false) : ctx.bool_val(true); - return true; - } - return false; + if (!(lit.is_quantifier() && IsClosedFormula(lit))) { + if (!lit.is_app()) + return false; + decl_kind k = lit.decl().get_decl_kind(); + if (k == Not) { + if (IsLiteral(lit.arg(0), atom, val)) { + val = eq(val, ctx.bool_val(true)) ? ctx.bool_val(false) : ctx.bool_val(true); + return true; + } + return false; + } + if (k == And || k == Or || k == Iff || k == Implies) + return false; } - if(k == And || k == Or || k == Iff || k == Implies) - return false; - } atom = lit; val = ctx.bool_val(true); return true; @@ -467,11 +458,11 @@ namespace Duality { expr Z3User::ReduceAndOr(const std::vector &args, bool is_and, std::vector &res){ for(unsigned i = 0; i < args.size(); i++) - if(!eq(args[i],ctx.bool_val(is_and))){ - if(eq(args[i],ctx.bool_val(!is_and))) - return ctx.bool_val(!is_and); - res.push_back(args[i]); - } + if (!eq(args[i], ctx.bool_val(is_and))) { + if (eq(args[i], ctx.bool_val(!is_and))) + return ctx.bool_val(!is_and); + res.push_back(args[i]); + } return expr(); } @@ -495,36 +486,36 @@ namespace Duality { // first check if there's anything to do... if(args.size() < 2) return FinishAndOr(args,is_and); - for(unsigned i = 0; i < args.size(); i++){ - const expr &a = args[i]; - if(!(a.is_app() && a.decl().get_decl_kind() == (is_and ? Or : And))) - return FinishAndOr(args,is_and); + for (unsigned i = 0; i < args.size(); i++) { + const expr &a = args[i]; + if (!(a.is_app() && a.decl().get_decl_kind() == (is_and ? Or : And))) + return FinishAndOr(args, is_and); } std::vector common; - for(unsigned i = 0; i < args.size(); i++){ - unsigned n = args[i].num_args(); - std::vector v(n),w; - for(unsigned j = 0; j < n; j++) - v[j] = args[i].arg(j); - std::less comp; - std::sort(v.begin(),v.end(),comp); - if(i == 0) - common.swap(v); - else { - std::set_intersection(common.begin(),common.end(),v.begin(),v.end(),std::inserter(w,w.begin()),comp); - common.swap(w); - } - } + for (unsigned i = 0; i < args.size(); i++) { + unsigned n = args[i].num_args(); + std::vector v(n), w; + for (unsigned j = 0; j < n; j++) + v[j] = args[i].arg(j); + std::less comp; + std::sort(v.begin(), v.end(), comp); + if (i == 0) + common.swap(v); + else { + std::set_intersection(common.begin(), common.end(), v.begin(), v.end(), std::inserter(w, w.begin()), comp); + common.swap(w); + } + } if(common.empty()) return FinishAndOr(args,is_and); std::set common_set(common.begin(),common.end()); for(unsigned i = 0; i < args.size(); i++){ unsigned n = args[i].num_args(); std::vector lits; - for(unsigned j = 0; j < n; j++){ - const expr b = args[i].arg(j); - if(common_set.find(b) == common_set.end()) - lits.push_back(b); + for (unsigned j = 0; j < n; j++) { + const expr b = args[i].arg(j); + if (common_set.find(b) == common_set.end()) + lits.push_back(b); } args[i] = SimplifyAndOr(lits,!is_and); } @@ -549,148 +540,145 @@ namespace Duality { } Z3User::Term Z3User::PushQuantifier(const expr &t, const expr &body, bool is_forall){ - if(t.get_quantifier_num_bound() == 1){ - std::vector fmlas,free,not_free; - CollectJuncts(body,fmlas, is_forall ? Or : And, false); - for(unsigned i = 0; i < fmlas.size(); i++){ - const expr &fmla = fmlas[i]; - if(fmla.has_free(0)) - free.push_back(fmla); - else - not_free.push_back(fmla); + if (t.get_quantifier_num_bound() == 1) { + std::vector fmlas, free, not_free; + CollectJuncts(body, fmlas, is_forall ? Or : And, false); + for (unsigned i = 0; i < fmlas.size(); i++) { + const expr &fmla = fmlas[i]; + if (fmla.has_free(0)) + free.push_back(fmla); + else + not_free.push_back(fmla); + } + decl_kind op = is_forall ? Or : And; + if (free.empty()) + return DeleteBound(0, 1, SimplifyAndOr(not_free, op == And)); + expr q = clone_quantifier(is_forall ? Forall : Exists, t, SimplifyAndOr(free, op == And)); + if (!not_free.empty()) + q = ctx.make(op, q, DeleteBound(0, 1, SimplifyAndOr(not_free, op == And))); + return q; } - decl_kind op = is_forall ? Or : And; - if(free.empty()) - return DeleteBound(0,1,SimplifyAndOr(not_free,op == And)); - expr q = clone_quantifier(is_forall ? Forall : Exists,t, SimplifyAndOr(free, op == And)); - if(!not_free.empty()) - q = ctx.make(op,q,DeleteBound(0,1,SimplifyAndOr(not_free, op == And))); - return q; - } return clone_quantifier(is_forall ? Forall : Exists,t,body); } - Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall){ - if(body.is_app()){ - if(body.decl().get_decl_kind() == (is_forall ? And : Or)){ // quantifier distributes - int nargs = body.num_args(); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = CloneQuantAndSimp(t, body.arg(i), is_forall); - return SimplifyAndOr(args, body.decl().get_decl_kind() == And); + Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall) { + if (body.is_app()) { + if (body.decl().get_decl_kind() == (is_forall ? And : Or)) { // quantifier distributes + int nargs = body.num_args(); + std::vector args(nargs); + for (int i = 0; i < nargs; i++) + args[i] = CloneQuantAndSimp(t, body.arg(i), is_forall); + return SimplifyAndOr(args, body.decl().get_decl_kind() == And); + } + else if (body.decl().get_decl_kind() == (is_forall ? Or : And)) { // quantifier distributes + return PushQuantifier(t, body, is_forall); // may distribute partially + } + else if (body.decl().get_decl_kind() == Not) { + return ctx.make(Not, CloneQuantAndSimp(t, body.arg(0), !is_forall)); + } } - else if(body.decl().get_decl_kind() == (is_forall ? Or : And)){ // quantifier distributes - return PushQuantifier(t,body,is_forall); // may distribute partially - } - else if(body.decl().get_decl_kind() == Not){ - return ctx.make(Not,CloneQuantAndSimp(t,body.arg(0),!is_forall)); - } - } - if(t.get_quantifier_num_bound() == 1 && !body.has_free(0)) - return DeleteBound(0,1,body); // drop the quantifier - return clone_quantifier(is_forall ? Forall : Exists,t,body); + if (t.get_quantifier_num_bound() == 1 && !body.has_free(0)) + return DeleteBound(0, 1, body); // drop the quantifier + return clone_quantifier(is_forall ? Forall : Exists, t, body); } Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body){ return CloneQuantAndSimp(t,body,t.is_quantifier_forall()); } - Z3User::Term Z3User::SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val){ - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()){ - func_decl f = t.decl(); - decl_kind k = f.get_decl_kind(); - - // TODO: recur here, but how much? We don't want to be quadractic in formula size - - if(k == And || k == Or){ - int nargs = t.num_args(); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = SubstAtom(memo,t.arg(i),atom,val); - res = ReallySimplifyAndOr(args, k==And); - return res; + Z3User::Term Z3User::SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + decl_kind k = f.get_decl_kind(); + + // TODO: recur here, but how much? We don't want to be quadractic in formula size + + if (k == And || k == Or) { + int nargs = t.num_args(); + std::vector args(nargs); + for (int i = 0; i < nargs; i++) + args[i] = SubstAtom(memo, t.arg(i), atom, val); + res = ReallySimplifyAndOr(args, k == And); + return res; + } } - } - else if(t.is_quantifier() && atom.is_quantifier()){ - if(eq(t,atom)) - res = val; - else - res = clone_quantifier(t,SubstAtom(memo,t.body(),atom,val)); + else if (t.is_quantifier() && atom.is_quantifier()) { + if (eq(t, atom)) + res = val; + else + res = clone_quantifier(t, SubstAtom(memo, t.body(), atom, val)); + return res; + } + res = SubstAtomTriv(t, atom, val); return res; - } - res = SubstAtomTriv(t,atom,val); - return res; } - void Z3User::RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo){ - for(unsigned i = 0; i < args.size(); i++){ - const expr &lit = args[i]; - expr atom, val; - if(IsLiteral(lit,atom,val)){ - if(atom.is_app() && atom.decl().get_decl_kind() == Equal) - if(pol ? eq(val,ctx.bool_val(true)) : eq(val,ctx.bool_val(false))){ - expr lhs = atom.arg(0), rhs = atom.arg(1); - if(lhs.is_numeral()) - std::swap(lhs,rhs); - if(rhs.is_numeral() && lhs.is_app()){ - for(unsigned j = 0; j < args.size(); j++) - if(j != i){ - smemo.clear(); - smemo[lhs] = rhs; - args[j] = SubstRec(smemo,args[j]); - } - } - } - for(unsigned j = 0; j < args.size(); j++) - if(j != i){ - smemo.clear(); - args[j] = SubstAtom(smemo,args[j],atom,pol ? val : !val); - } + void Z3User::RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo) { + for (unsigned i = 0; i < args.size(); i++) { + const expr &lit = args[i]; + expr atom, val; + if (IsLiteral(lit, atom, val)) { + if (atom.is_app() && atom.decl().get_decl_kind() == Equal) + if (pol ? eq(val, ctx.bool_val(true)) : eq(val, ctx.bool_val(false))) { + expr lhs = atom.arg(0), rhs = atom.arg(1); + if (lhs.is_numeral()) + std::swap(lhs, rhs); + if (rhs.is_numeral() && lhs.is_app()) { + for (unsigned j = 0; j < args.size(); j++) + if (j != i) { + smemo.clear(); + smemo[lhs] = rhs; + args[j] = SubstRec(smemo, args[j]); + } + } + } + for (unsigned j = 0; j < args.size(); j++) + if (j != i) { + smemo.clear(); + args[j] = SubstAtom(smemo, args[j], atom, pol ? val : !val); + } + } } - } } - Z3User::Term Z3User::RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(RemoveRedundancyRec(memo, smemo, t.arg(i))); + Z3User::Term Z3User::RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(RemoveRedundancyRec(memo, smemo, t.arg(i))); - decl_kind k = f.get_decl_kind(); - if(k == And){ - RemoveRedundancyOp(true,args,smemo); - res = ReallySimplifyAndOr(args, true); - } - else if(k == Or){ - RemoveRedundancyOp(false,args,smemo); - res = ReallySimplifyAndOr(args, false); - } - else { - if(k == Equal && args[0].get_id() > args[1].get_id()) - std::swap(args[0],args[1]); - res = f(args.size(),&args[0]); - } + decl_kind k = f.get_decl_kind(); + if (k == And) { + RemoveRedundancyOp(true, args, smemo); + res = ReallySimplifyAndOr(args, true); + } + else if (k == Or) { + RemoveRedundancyOp(false, args, smemo); + res = ReallySimplifyAndOr(args, false); + } + else { + if (k == Equal && args[0].get_id() > args[1].get_id()) + std::swap(args[0], args[1]); + res = f(args.size(), &args[0]); + } } - else if (t.is_quantifier()) - { - Term body = RemoveRedundancyRec(memo,smemo,t.body()); - res = CloneQuantAndSimp(t, body); + else if (t.is_quantifier()) { + Term body = RemoveRedundancyRec(memo, smemo, t.body()); + res = CloneQuantAndSimp(t, body); } - else res = t; - return res; + else res = t; + return res; } Z3User::Term Z3User::RemoveRedundancy(const Term &t){ @@ -706,43 +694,40 @@ namespace Duality { return t; } - Z3User::Term Z3User::IneqToEqRec(hash_map &memo, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(IneqToEqRec(memo, t.arg(i))); + Z3User::Term Z3User::IneqToEqRec(hash_map &memo, const Term &t) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(IneqToEqRec(memo, t.arg(i))); - decl_kind k = f.get_decl_kind(); - if(k == And){ - for(int i = 0; i < nargs-1; i++){ - if((args[i].is_app() && args[i].decl().get_decl_kind() == Geq && - args[i+1].is_app() && args[i+1].decl().get_decl_kind() == Leq) - || - (args[i].is_app() && args[i].decl().get_decl_kind() == Leq && - args[i+1].is_app() && args[i+1].decl().get_decl_kind() == Geq)) - if(eq(args[i].arg(0),args[i+1].arg(0)) && eq(args[i].arg(1),args[i+1].arg(1))){ - args[i] = ctx.make(Equal,args[i].arg(0),args[i].arg(1)); - args[i+1] = ctx.bool_val(true); - } - } - } - res = f(args.size(),&args[0]); + decl_kind k = f.get_decl_kind(); + if (k == And) { + for (int i = 0; i < nargs - 1; i++) { + if ((args[i].is_app() && args[i].decl().get_decl_kind() == Geq && + args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Leq) + || + (args[i].is_app() && args[i].decl().get_decl_kind() == Leq && + args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Geq)) + if (eq(args[i].arg(0), args[i + 1].arg(0)) && eq(args[i].arg(1), args[i + 1].arg(1))) { + args[i] = ctx.make(Equal, args[i].arg(0), args[i].arg(1)); + args[i + 1] = ctx.bool_val(true); + } + } + } + res = f(args.size(), &args[0]); } - else if (t.is_quantifier()) - { - Term body = IneqToEqRec(memo,t.body()); - res = clone_quantifier(t, body); + else if (t.is_quantifier()) { + Term body = IneqToEqRec(memo, t.body()); + res = clone_quantifier(t, body); } - else res = t; - return res; + else res = t; + return res; } Z3User::Term Z3User::IneqToEq(const Term &t){ @@ -750,87 +735,85 @@ namespace Duality { return IneqToEqRec(memo,t); } - Z3User::Term Z3User::SubstRecHide(hash_map &memo, const Term &t, int number) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if (nargs == 0 && f.get_decl_kind() == Uninterpreted){ - std::string name = std::string("@q_") + t.decl().name().str() + "_" + string_of_int(number); - res = ctx.constant(name.c_str(), t.get_sort()); - return res; - } - for(int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, t.arg(i))); - res = f(args.size(),&args[0]); + Z3User::Term Z3User::SubstRecHide(hash_map &memo, const Term &t, int number) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if (nargs == 0 && f.get_decl_kind() == Uninterpreted) { + std::string name = std::string("@q_") + t.decl().name().str() + "_" + string_of_int(number); + res = ctx.constant(name.c_str(), t.get_sort()); + return res; + } + for (int i = 0; i < nargs; i++) + args.push_back(SubstRec(memo, t.arg(i))); + res = f(args.size(), &args[0]); } - else if (t.is_quantifier()) - res = CloneQuantifier(t,SubstRec(memo, t.body())); - else res = t; - return res; + else if (t.is_quantifier()) + res = CloneQuantifier(t, SubstRec(memo, t.body())); + else res = t; + return res; } RPFP::Term RPFP::SubstParams(const std::vector &from, - const std::vector &to, const Term &t){ - hash_map memo; - bool some_diff = false; - for(unsigned i = 0; i < from.size(); i++) - if(i < to.size() && !eq(from[i],to[i])){ - memo[from[i]] = to[i]; - some_diff = true; - } - return some_diff ? SubstRec(memo,t) : t; + const std::vector &to, const Term &t) { + hash_map memo; + bool some_diff = false; + for (unsigned i = 0; i < from.size(); i++) + if (i < to.size() && !eq(from[i], to[i])) { + memo[from[i]] = to[i]; + some_diff = true; + } + return some_diff ? SubstRec(memo, t) : t; } RPFP::Term RPFP::SubstParamsNoCapture(const std::vector &from, - const std::vector &to, const Term &t){ - hash_map memo; - bool some_diff = false; - for(unsigned i = 0; i < from.size(); i++) - if(i < to.size() && !eq(from[i],to[i])){ - memo[from[i]] = to[i]; - // if the new param is not being mapped to anything else, we need to rename it to prevent capture - // note, if the new param *is* mapped later in the list, it will override this substitution - const expr &w = to[i]; - if(memo.find(w) == memo.end()){ - std::string old_name = w.decl().name().str(); - func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); - expr y = fresh(); - memo[w] = y; - } - some_diff = true; - } - return some_diff ? SubstRec(memo,t) : t; + const std::vector &to, const Term &t) { + hash_map memo; + bool some_diff = false; + for (unsigned i = 0; i < from.size(); i++) + if (i < to.size() && !eq(from[i], to[i])) { + memo[from[i]] = to[i]; + // if the new param is not being mapped to anything else, we need to rename it to prevent capture + // note, if the new param *is* mapped later in the list, it will override this substitution + const expr &w = to[i]; + if (memo.find(w) == memo.end()) { + std::string old_name = w.decl().name().str(); + func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); + expr y = fresh(); + memo[w] = y; + } + some_diff = true; + } + return some_diff ? SubstRec(memo, t) : t; } - RPFP::Transformer RPFP::Fuse(const std::vector &trs){ - assert(!trs.empty()); - const std::vector ¶ms = trs[0]->IndParams; - std::vector fmlas(trs.size()); - fmlas[0] = trs[0]->Formula; - for(unsigned i = 1; i < trs.size(); i++) - fmlas[i] = SubstParamsNoCapture(trs[i]->IndParams,params,trs[i]->Formula); - std::vector rel_params = trs[0]->RelParams; - for(unsigned i = 1; i < trs.size(); i++){ - const std::vector ¶ms2 = trs[i]->RelParams; - hash_map map; - for(unsigned j = 0; j < params2.size(); j++){ - func_decl rel = RenumberPred(params2[j],rel_params.size()); - rel_params.push_back(rel); - map[params2[j]] = rel; + RPFP::Transformer RPFP::Fuse(const std::vector &trs) { + assert(!trs.empty()); + const std::vector ¶ms = trs[0]->IndParams; + std::vector fmlas(trs.size()); + fmlas[0] = trs[0]->Formula; + for (unsigned i = 1; i < trs.size(); i++) + fmlas[i] = SubstParamsNoCapture(trs[i]->IndParams, params, trs[i]->Formula); + std::vector rel_params = trs[0]->RelParams; + for (unsigned i = 1; i < trs.size(); i++) { + const std::vector ¶ms2 = trs[i]->RelParams; + hash_map map; + for (unsigned j = 0; j < params2.size(); j++) { + func_decl rel = RenumberPred(params2[j], rel_params.size()); + rel_params.push_back(rel); + map[params2[j]] = rel; + } + hash_map memo; + fmlas[i] = SubstRec(memo, map, fmlas[i]); } - hash_map memo; - fmlas[i] = SubstRec(memo,map,fmlas[i]); - } - return Transformer(rel_params,params,ctx.make(Or,fmlas),trs[0]->owner); + return Transformer(rel_params, params, ctx.make(Or, fmlas), trs[0]->owner); } @@ -855,19 +838,17 @@ namespace Duality { root->Annotation.Formula = annot; } - void RPFP::DecodeTree(Node *root, TermTree *interp, int persist) - { - std::vector &ic = interp->getChildren(); - if (ic.size() > 0) - { - std::vector &nc = root->Outgoing->Children; - for (unsigned i = 0; i < nc.size(); i++) - DecodeTree(nc[i], ic[i], persist); + void RPFP::DecodeTree(Node *root, TermTree *interp, int persist) { + std::vector &ic = interp->getChildren(); + if (ic.size() > 0) { + std::vector &nc = root->Outgoing->Children; + for (unsigned i = 0; i < nc.size(); i++) + DecodeTree(nc[i], ic[i], persist); } - SetAnnotation(root,interp->getTerm()); + SetAnnotation(root, interp->getTerm()); #if 0 - if(persist != 0) - Z3_persist_ast(ctx,root->Annotation.Formula,persist); + if(persist != 0) + Z3_persist_ast(ctx,root->Annotation.Formula,persist); #endif } @@ -926,31 +907,30 @@ namespace Duality { #endif - expr RPFP::GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox) - { - if (e->dual.null()) { - timer_start("ReducedDualEdge"); - e->dual = ReducedDualEdge(e); - timer_stop("ReducedDualEdge"); - timer_start("getting children"); - if(underapprox){ - std::vector cus(e->Children.size()); - for(unsigned i = 0; i < e->Children.size(); i++) - cus[i] = !UnderapproxFlag(e->Children[i]) || GetUnderapprox(e->Children[i]); - expr cnst = conjoin(cus); - e->dual = e->dual && cnst; + expr RPFP::GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox) { + if (e->dual.null()) { + timer_start("ReducedDualEdge"); + e->dual = ReducedDualEdge(e); + timer_stop("ReducedDualEdge"); + timer_start("getting children"); + if (underapprox) { + std::vector cus(e->Children.size()); + for (unsigned i = 0; i < e->Children.size(); i++) + cus[i] = !UnderapproxFlag(e->Children[i]) || GetUnderapprox(e->Children[i]); + expr cnst = conjoin(cus); + e->dual = e->dual && cnst; + } + timer_stop("getting children"); + timer_start("Persisting"); + std::list::reverse_iterator it = stack.rbegin(); + for (int i = 0; i < persist && it != stack.rend(); i++) + it++; + if (it != stack.rend()) + it->edges.push_back(e); + timer_stop("Persisting"); + //Console.WriteLine("{0}", cnst); } - timer_stop("getting children"); - timer_start("Persisting"); - std::list::reverse_iterator it = stack.rbegin(); - for(int i = 0; i < persist && it != stack.rend(); i++) - it++; - if(it != stack.rend()) - it->edges.push_back(e); - timer_stop("Persisting"); - //Console.WriteLine("{0}", cnst); - } - return e->dual; + return e->dual; } /** For incremental solving, asserts the constraint associated @@ -970,47 +950,46 @@ namespace Duality { * */ - void RPFP::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) - { - if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); - timer_start("solver add"); - slvr_add(e->dual); - timer_stop("solver add"); - if(with_children) - for(unsigned i = 0; i < e->Children.size(); i++) - ConstrainParent(e,e->Children[i]); + void RPFP::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) { + if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) + return; + expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); + timer_start("solver add"); + slvr_add(e->dual); + timer_stop("solver add"); + if (with_children) + for (unsigned i = 0; i < e->Children.size(); i++) + ConstrainParent(e, e->Children[i]); } #ifdef LIMIT_STACK_WEIGHT void RPFP_caching::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) { - unsigned old_new_alits = new_alits.size(); - if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); - timer_start("solver add"); - slvr_add(e->dual); - timer_stop("solver add"); - if(old_new_alits < new_alits.size()) - weight_added.val++; - if(with_children) - for(unsigned i = 0; i < e->Children.size(); i++) - ConstrainParent(e,e->Children[i]); + unsigned old_new_alits = new_alits.size(); + if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) + return; + expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); + timer_start("solver add"); + slvr_add(e->dual); + timer_stop("solver add"); + if(old_new_alits < new_alits.size()) + weight_added.val++; + if(with_children) + for(unsigned i = 0; i < e->Children.size(); i++) + ConstrainParent(e,e->Children[i]); } #endif // caching verion of above - void RPFP_caching::AssertEdgeCache(Edge *e, std::vector &lits, bool with_children){ - if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, 0, with_children, false); - GetAssumptionLits(fmla,lits); - if(with_children) - for(unsigned i = 0; i < e->Children.size(); i++) - ConstrainParentCache(e,e->Children[i],lits); + void RPFP_caching::AssertEdgeCache(Edge *e, std::vector &lits, bool with_children) { + if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) + return; + expr fmla = GetEdgeFormula(e, 0, with_children, false); + GetAssumptionLits(fmla, lits); + if (with_children) + for (unsigned i = 0; i < e->Children.size(); i++) + ConstrainParentCache(e, e->Children[i], lits); } void RPFP::slvr_add(const expr &e){ @@ -1032,23 +1011,23 @@ namespace Duality { void RPFP_caching::slvr_pop(int i){ for(int j = 0; j < i; j++){ #ifdef LIMIT_STACK_WEIGHT - if(alit_stack_sizes.empty()){ - if(big_stack.empty()) - throw "stack underflow"; - for(unsigned k = 0; k < new_alits.size(); k++){ - if(AssumptionLits.find(new_alits[k]) == AssumptionLits.end()) - throw "foo!"; - AssumptionLits.erase(new_alits[k]); - } - big_stack_entry &bsb = big_stack.back(); - bsb.alit_stack_sizes.swap(alit_stack_sizes); - bsb.alit_stack.swap(alit_stack); - bsb.new_alits.swap(new_alits); - bsb.weight_added.swap(weight_added); - big_stack.pop_back(); - slvr().pop(1); - continue; - } + if(alit_stack_sizes.empty()){ + if(big_stack.empty()) + throw "stack underflow"; + for(unsigned k = 0; k < new_alits.size(); k++){ + if(AssumptionLits.find(new_alits[k]) == AssumptionLits.end()) + throw "foo!"; + AssumptionLits.erase(new_alits[k]); + } + big_stack_entry &bsb = big_stack.back(); + bsb.alit_stack_sizes.swap(alit_stack_sizes); + bsb.alit_stack.swap(alit_stack); + bsb.new_alits.swap(new_alits); + bsb.weight_added.swap(weight_added); + big_stack.pop_back(); + slvr().pop(1); + continue; + } #endif alit_stack.resize(alit_stack_sizes.back()); alit_stack_sizes.pop_back(); @@ -1057,18 +1036,18 @@ namespace Duality { void RPFP_caching::slvr_push(){ #ifdef LIMIT_STACK_WEIGHT - if(weight_added.val > LIMIT_STACK_WEIGHT){ - big_stack.resize(big_stack.size()+1); - big_stack_entry &bsb = big_stack.back(); - bsb.alit_stack_sizes.swap(alit_stack_sizes); - bsb.alit_stack.swap(alit_stack); - bsb.new_alits.swap(new_alits); - bsb.weight_added.swap(weight_added); - slvr().push(); - for(unsigned i = 0; i < bsb.alit_stack.size(); i++) - slvr().add(bsb.alit_stack[i]); - return; - } + if(weight_added.val > LIMIT_STACK_WEIGHT){ + big_stack.resize(big_stack.size()+1); + big_stack_entry &bsb = big_stack.back(); + bsb.alit_stack_sizes.swap(alit_stack_sizes); + bsb.alit_stack.swap(alit_stack); + bsb.new_alits.swap(new_alits); + bsb.weight_added.swap(weight_added); + slvr().push(); + for(unsigned i = 0; i < bsb.alit_stack.size(); i++) + slvr().add(bsb.alit_stack[i]); + return; + } #endif alit_stack_sizes.push_back(alit_stack.size()); } @@ -1082,16 +1061,16 @@ namespace Duality { if(n && assumptions) std::copy(assumptions,assumptions+n,std::inserter(alit_stack,alit_stack.end())); check_result res; - if(core_size && core){ - std::vector full_core(alit_stack.size()), core1(n); - std::copy(assumptions,assumptions+n,core1.begin()); - res = slvr().check(alit_stack.size(), &alit_stack[0], core_size, &full_core[0]); - full_core.resize(*core_size); - if(res == unsat){ - FilterCore(core1,full_core); - *core_size = core1.size(); - std::copy(core1.begin(),core1.end(),core); - } + if (core_size && core) { + std::vector full_core(alit_stack.size()), core1(n); + std::copy(assumptions, assumptions + n, core1.begin()); + res = slvr().check(alit_stack.size(), &alit_stack[0], core_size, &full_core[0]); + full_core.resize(*core_size); + if (res == unsat) { + FilterCore(core1, full_core); + *core_size = core1.size(); + std::copy(core1.begin(), core1.end(), core); + } } else res = slvr().check(alit_stack.size(), &alit_stack[0]); @@ -1100,20 +1079,20 @@ namespace Duality { } lbool RPFP::ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals, - bool weak){ - return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); + TermTree *&interpolants, + model &_model, + TermTree *goals, + bool weak) { + return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); } lbool RPFP_caching::ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals, - bool weak){ - GetTermTreeAssertionLiterals(assumptions); - return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); + TermTree *&interpolants, + model &_model, + TermTree *goals, + bool weak) { + GetTermTreeAssertionLiterals(assumptions); + return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); } void RPFP_caching::GetTermTreeAssertionLiteralsRec(TermTree *assumptions){ @@ -1132,34 +1111,34 @@ namespace Duality { return; } - void RPFP_caching::GetTermTreeAssertionLiterals(TermTree *assumptions){ - // optimize binary case - if(assumptions->getChildren().size() == 1 - && assumptions->getChildren()[0]->getChildren().size() == 0){ - hash_map map; - TermTree *child = assumptions->getChildren()[0]; - std::vector dummy; - GetAssumptionLits(child->getTerm(),dummy,&map); - std::vector &ts = child->getTerms(); - for(unsigned i = 0; i < ts.size(); i++) - GetAssumptionLits(ts[i],dummy,&map); - std::vector assumps; - slvr().get_proof().get_assumptions(assumps); - if(!proof_core){ // save the proof core for later use - proof_core = new hash_set; - for(unsigned i = 0; i < assumps.size(); i++) - proof_core->insert(assumps[i]); + void RPFP_caching::GetTermTreeAssertionLiterals(TermTree *assumptions) { + // optimize binary case + if (assumptions->getChildren().size() == 1 + && assumptions->getChildren()[0]->getChildren().size() == 0) { + hash_map map; + TermTree *child = assumptions->getChildren()[0]; + std::vector dummy; + GetAssumptionLits(child->getTerm(), dummy, &map); + std::vector &ts = child->getTerms(); + for (unsigned i = 0; i < ts.size(); i++) + GetAssumptionLits(ts[i], dummy, &map); + std::vector assumps; + slvr().get_proof().get_assumptions(assumps); + if (!proof_core) { // save the proof core for later use + proof_core = new hash_set < ast > ; + for (unsigned i = 0; i < assumps.size(); i++) + proof_core->insert(assumps[i]); + } + std::vector *cnsts[2] = { &child->getTerms(), &assumptions->getTerms() }; + for (unsigned i = 0; i < assumps.size(); i++) { + expr &ass = assumps[i]; + expr alit = (ass.is_app() && ass.decl().get_decl_kind() == Implies) ? ass.arg(0) : ass; + bool isA = map.find(alit) != map.end(); + cnsts[isA ? 0 : 1]->push_back(ass); + } } - std::vector *cnsts[2] = {&child->getTerms(),&assumptions->getTerms()}; - for(unsigned i = 0; i < assumps.size(); i++){ - expr &ass = assumps[i]; - expr alit = (ass.is_app() && ass.decl().get_decl_kind() == Implies) ? ass.arg(0) : ass; - bool isA = map.find(alit) != map.end(); - cnsts[isA ? 0 : 1]->push_back(ass); - } - } - else - GetTermTreeAssertionLiteralsRec(assumptions); + else + GetTermTreeAssertionLiteralsRec(assumptions); } void RPFP::AddToProofCore(hash_set &core){ @@ -1177,27 +1156,27 @@ namespace Duality { } - void RPFP_caching::GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map){ - std::vector conjs; - CollectConjuncts(fmla,conjs); - for(unsigned i = 0; i < conjs.size(); i++){ - const expr &conj = conjs[i]; - std::pair foo(conj,expr(ctx)); - std::pair::iterator, bool> bar = AssumptionLits.insert(foo); - Term &res = bar.first->second; - if(bar.second){ - func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); - res = pred(); + void RPFP_caching::GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map) { + std::vector conjs; + CollectConjuncts(fmla, conjs); + for (unsigned i = 0; i < conjs.size(); i++) { + const expr &conj = conjs[i]; + std::pair foo(conj, expr(ctx)); + std::pair::iterator, bool> bar = AssumptionLits.insert(foo); + Term &res = bar.first->second; + if (bar.second) { + func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); + res = pred(); #ifdef LIMIT_STACK_WEIGHT - new_alits.push_back(conj); + new_alits.push_back(conj); #endif - slvr().add(ctx.make(Implies,res,conj)); - // std::cout << res << ": " << conj << "\n"; + slvr().add(ctx.make(Implies, res, conj)); + // std::cout << res << ": " << conj << "\n"; + } + if (opt_map) + (*opt_map)[res] = conj; + lits.push_back(res); } - if(opt_map) - (*opt_map)[res] = conj; - lits.push_back(res); - } } void RPFP::ConstrainParent(Edge *parent, Node *child){ @@ -1215,39 +1194,37 @@ namespace Duality { void RPFP::AssertNode(Node *n) { - if (n->dual.null()) - { - n->dual = GetUpperBound(n); - stack.back().nodes.push_back(n); - slvr_add(n->dual); + if (n->dual.null()) { + n->dual = GetUpperBound(n); + stack.back().nodes.push_back(n); + slvr_add(n->dual); } } // caching version of above void RPFP_caching::AssertNodeCache(Node *n, std::vector lits){ - if (n->dual.null()) - { - n->dual = GetUpperBound(n); - stack.back().nodes.push_back(n); - GetAssumptionLits(n->dual,lits); + if (n->dual.null()) { + n->dual = GetUpperBound(n); + stack.back().nodes.push_back(n); + GetAssumptionLits(n->dual, lits); } } /** Clone another RPFP into this one, keeping a map */ - void RPFP_caching::Clone(RPFP *other){ + void RPFP_caching::Clone(RPFP *other) { #if 0 - for(unsigned i = 0; i < other->nodes.size(); i++) - NodeCloneMap[other->nodes[i]] = CloneNode(other->nodes[i]); + for(unsigned i = 0; i < other->nodes.size(); i++) + NodeCloneMap[other->nodes[i]] = CloneNode(other->nodes[i]); #endif - for(unsigned i = 0; i < other->edges.size(); i++){ - Edge *edge = other->edges[i]; - Node *parent = CloneNode(edge->Parent); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++) - // cs.push_back(NodeCloneMap[edge->Children[j]]); - cs.push_back(CloneNode(edge->Children[j])); - EdgeCloneMap[edge] = CreateEdge(parent,edge->F,cs); - } + for (unsigned i = 0; i < other->edges.size(); i++) { + Edge *edge = other->edges[i]; + Node *parent = CloneNode(edge->Parent); + std::vector cs; + for (unsigned j = 0; j < edge->Children.size(); j++) + // cs.push_back(NodeCloneMap[edge->Children[j]]); + cs.push_back(CloneNode(edge->Children[j])); + EdgeCloneMap[edge] = CreateEdge(parent, edge->F, cs); + } } /** Get the clone of a node */ @@ -1373,11 +1350,10 @@ namespace Duality { timer_start("interpolate_tree"); lbool res = ls_interpolate_tree(tree, interpolant, dualModel,goals,true); timer_stop("interpolate_tree"); - if (res == l_false) - { - DecodeTree(root, interpolant->getChildren()[0], persist); - delete interpolant; - } + if (res == l_false) { + DecodeTree(root, interpolant->getChildren()[0], persist); + delete interpolant; + } delete tree; if(goals) @@ -1419,11 +1395,10 @@ namespace Duality { timer_start("interpolate_tree"); lbool res = ls_interpolate_tree(tree, interpolant, dualModel,0,true); timer_stop("interpolate_tree"); - if (res == l_false) - { - DecodeTree(node, interpolant->getChildren()[0], 0); - delete interpolant; - } + if (res == l_false) { + DecodeTree(node, interpolant->getChildren()[0], 0); + delete interpolant; + } delete tree; timer_stop("Solve"); @@ -1461,44 +1436,43 @@ namespace Duality { * */ - check_result RPFP::Check(Node *root, std::vector underapproxes, std::vector *underapprox_core ) - { - timer_start("Check"); - ClearProofCore(); - // if (dualModel != null) dualModel.Dispose(); - check_result res; - if(!underapproxes.size()) - res = slvr_check(); - else { - std::vector us(underapproxes.size()); - for(unsigned i = 0; i < underapproxes.size(); i++) - us[i] = UnderapproxFlag(underapproxes[i]); - slvr_check(); // TODO: no idea why I need to do this - if(underapprox_core){ - std::vector unsat_core(us.size()); - unsigned core_size = 0; - res = slvr_check(us.size(),&us[0],&core_size,&unsat_core[0]); - underapprox_core->resize(core_size); - for(unsigned i = 0; i < core_size; i++) - (*underapprox_core)[i] = UnderapproxFlagRev(unsat_core[i]); - } - else { - res = slvr_check(us.size(),&us[0]); - bool dump = false; - if(dump){ - std::vector cnsts; - // cnsts.push_back(axioms[0]); - cnsts.push_back(root->dual); - cnsts.push_back(root->Outgoing->dual); - ls->write_interpolation_problem("temp.smt",cnsts,std::vector()); - } - } - // check_result temp = slvr_check(); - } - dualModel = slvr().get_model(); - timer_stop("Check"); - return res; - } + check_result RPFP::Check(Node *root, std::vector underapproxes, std::vector *underapprox_core) { + timer_start("Check"); + ClearProofCore(); + // if (dualModel != null) dualModel.Dispose(); + check_result res; + if (!underapproxes.size()) + res = slvr_check(); + else { + std::vector us(underapproxes.size()); + for (unsigned i = 0; i < underapproxes.size(); i++) + us[i] = UnderapproxFlag(underapproxes[i]); + slvr_check(); // TODO: no idea why I need to do this + if (underapprox_core) { + std::vector unsat_core(us.size()); + unsigned core_size = 0; + res = slvr_check(us.size(), &us[0], &core_size, &unsat_core[0]); + underapprox_core->resize(core_size); + for (unsigned i = 0; i < core_size; i++) + (*underapprox_core)[i] = UnderapproxFlagRev(unsat_core[i]); + } + else { + res = slvr_check(us.size(), &us[0]); + bool dump = false; + if (dump) { + std::vector cnsts; + // cnsts.push_back(axioms[0]); + cnsts.push_back(root->dual); + cnsts.push_back(root->Outgoing->dual); + ls->write_interpolation_problem("temp.smt", cnsts, std::vector()); + } + } + // check_result temp = slvr_check(); + } + dualModel = slvr().get_model(); + timer_stop("Check"); + return res; + } check_result RPFP::CheckUpdateModel(Node *root, std::vector assumps){ // check_result temp1 = slvr_check(); // no idea why I need to do this @@ -1545,54 +1519,54 @@ namespace Duality { } void RPFP::EvalArrayTerm(const RPFP::Term &t, ArrayValue &res){ - if(t.is_app()){ - decl_kind k = t.decl().get_decl_kind(); - if(k == AsArray){ - func_decl fd = t.decl().get_func_decl_parameter(0); - func_interp r = dualModel.get_func_interp(fd); - int num = r.num_entries(); - res.defined = true; - for(int i = 0; i < num; i++){ - expr arg = r.get_arg(i,0); - expr value = r.get_value(i); - res.entries[arg] = value; - } - res.def_val = r.else_value(); - return; + if (t.is_app()) { + decl_kind k = t.decl().get_decl_kind(); + if (k == AsArray) { + func_decl fd = t.decl().get_func_decl_parameter(0); + func_interp r = dualModel.get_func_interp(fd); + int num = r.num_entries(); + res.defined = true; + for (int i = 0; i < num; i++) { + expr arg = r.get_arg(i, 0); + expr value = r.get_value(i); + res.entries[arg] = value; + } + res.def_val = r.else_value(); + return; + } + else if (k == Store) { + EvalArrayTerm(t.arg(0), res); + if (!res.defined)return; + expr addr = t.arg(1); + expr val = t.arg(2); + if (addr.is_numeral() && val.is_numeral()) { + if (eq(val, res.def_val)) + res.entries.erase(addr); + else + res.entries[addr] = val; + } + else + res.defined = false; + return; + } } - else if(k == Store){ - EvalArrayTerm(t.arg(0),res); - if(!res.defined)return; - expr addr = t.arg(1); - expr val = t.arg(2); - if(addr.is_numeral() && val.is_numeral()){ - if(eq(val,res.def_val)) - res.entries.erase(addr); - else - res.entries[addr] = val; - } - else - res.defined = false; - return; - } - } res.defined = false; } int eae_count = 0; - RPFP::Term RPFP::EvalArrayEquality(const RPFP::Term &f){ - ArrayValue lhs,rhs; - eae_count++; - EvalArrayTerm(f.arg(0),lhs); - EvalArrayTerm(f.arg(1),rhs); - if(lhs.defined && rhs.defined){ - if(eq(lhs.def_val,rhs.def_val)) - if(lhs.entries == rhs.entries) - return ctx.bool_val(true); - return ctx.bool_val(false); - } - return f; + RPFP::Term RPFP::EvalArrayEquality(const RPFP::Term &f) { + ArrayValue lhs, rhs; + eae_count++; + EvalArrayTerm(f.arg(0), lhs); + EvalArrayTerm(f.arg(1), rhs); + if (lhs.defined && rhs.defined) { + if (eq(lhs.def_val, rhs.def_val)) + if (lhs.entries == rhs.entries) + return ctx.bool_val(true); + return ctx.bool_val(false); + } + return f; } /** Compute truth values of all boolean subterms in current model. @@ -1600,75 +1574,75 @@ namespace Duality { ands and, or, not. Returns result in memo. */ - int RPFP::SubtermTruth(hash_map &memo, const Term &f){ - if(memo.find(f) != memo.end()){ - return memo[f]; - } - int res; - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies){ - res = SubtermTruth(memo,!f.arg(0) || f.arg(1)); - goto done; + int RPFP::SubtermTruth(hash_map &memo, const Term &f) { + if (memo.find(f) != memo.end()) { + return memo[f]; } - if(k == And) { - res = 1; - for(int i = 0; i < nargs; i++){ - int ar = SubtermTruth(memo,f.arg(i)); - if(ar == 0){ - res = 0; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Or) { - res = 0; - for(int i = 0; i < nargs; i++){ - int ar = SubtermTruth(memo,f.arg(i)); - if(ar == 1){ - res = 1; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Not) { - int ar = SubtermTruth(memo,f.arg(0)); - res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); - goto done; + int res; + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + res = SubtermTruth(memo, !f.arg(0) || f.arg(1)); + goto done; + } + if (k == And) { + res = 1; + for (int i = 0; i < nargs; i++) { + int ar = SubtermTruth(memo, f.arg(i)); + if (ar == 0) { + res = 0; + goto done; + } + if (ar == 2)res = 2; + } + goto done; + } + else if (k == Or) { + res = 0; + for (int i = 0; i < nargs; i++) { + int ar = SubtermTruth(memo, f.arg(i)); + if (ar == 1) { + res = 1; + goto done; + } + if (ar == 2)res = 2; + } + goto done; + } + else if (k == Not) { + int ar = SubtermTruth(memo, f.arg(0)); + res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); + goto done; + } } + { + bool pos; std::vector names; + if (f.is_label(pos, names)) { + res = SubtermTruth(memo, f.arg(0)); + goto done; + } } { - bool pos; std::vector names; - if(f.is_label(pos,names)){ - res = SubtermTruth(memo,f.arg(0)); - goto done; - } + expr bv = dualModel.eval(f); + if (bv.is_app() && bv.decl().get_decl_kind() == Equal && + bv.arg(0).is_array()) { + bv = EvalArrayEquality(bv); + } + // Hack!!!! array equalities can occur negatively! + if (bv.is_app() && bv.decl().get_decl_kind() == Not && + bv.arg(0).decl().get_decl_kind() == Equal && + bv.arg(0).arg(0).is_array()) { + bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); + } + if (eq(bv, ctx.bool_val(true))) + res = 1; + else if (eq(bv, ctx.bool_val(false))) + res = 0; + else + res = 2; } - { - expr bv = dualModel.eval(f); - if(bv.is_app() && bv.decl().get_decl_kind() == Equal && - bv.arg(0).is_array()){ - bv = EvalArrayEquality(bv); - } - // Hack!!!! array equalities can occur negatively! - if(bv.is_app() && bv.decl().get_decl_kind() == Not && - bv.arg(0).decl().get_decl_kind() == Equal && - bv.arg(0).arg(0).is_array()){ - bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); - } - if(eq(bv,ctx.bool_val(true))) - res = 1; - else if(eq(bv,ctx.bool_val(false))) - res = 0; - else - res = 2; - } - done: +done: memo[f] = res; return res; } @@ -1685,137 +1659,137 @@ namespace Duality { #if 0 int RPFP::GetLabelsRec(hash_map *memo, const Term &f, std::vector &labels, bool labpos){ - if(memo[labpos].find(f) != memo[labpos].end()){ - return memo[labpos][f]; - } - int res; - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies){ - res = GetLabelsRec(memo,f.arg(1) || !f.arg(0), labels, labpos); - goto done; + if(memo[labpos].find(f) != memo[labpos].end()){ + return memo[labpos][f]; } - if(k == And) { - res = 1; - for(int i = 0; i < nargs; i++){ - int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); - if(ar == 0){ - res = 0; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Or) { - res = 0; - for(int i = 0; i < nargs; i++){ - int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); - if(ar == 1){ - res = 1; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Not) { - int ar = GetLabelsRec(memo,f.arg(0), labels, !labpos); - res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); - goto done; + int res; + if(f.is_app()){ + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if(k == Implies){ + res = GetLabelsRec(memo,f.arg(1) || !f.arg(0), labels, labpos); + goto done; + } + if(k == And) { + res = 1; + for(int i = 0; i < nargs; i++){ + int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); + if(ar == 0){ + res = 0; + goto done; + } + if(ar == 2)res = 2; + } + goto done; + } + else if(k == Or) { + res = 0; + for(int i = 0; i < nargs; i++){ + int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); + if(ar == 1){ + res = 1; + goto done; + } + if(ar == 2)res = 2; + } + goto done; + } + else if(k == Not) { + int ar = GetLabelsRec(memo,f.arg(0), labels, !labpos); + res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); + goto done; + } } + { + bool pos; std::vector names; + if(f.is_label(pos,names)){ + res = GetLabelsRec(memo,f.arg(0), labels, labpos); + if(pos == labpos && res == (pos ? 1 : 0)) + for(unsigned i = 0; i < names.size(); i++) + labels.push_back(names[i]); + goto done; + } } { - bool pos; std::vector names; - if(f.is_label(pos,names)){ - res = GetLabelsRec(memo,f.arg(0), labels, labpos); - if(pos == labpos && res == (pos ? 1 : 0)) - for(unsigned i = 0; i < names.size(); i++) - labels.push_back(names[i]); - goto done; - } + expr bv = dualModel.eval(f); + if(bv.is_app() && bv.decl().get_decl_kind() == Equal && + bv.arg(0).is_array()){ + bv = EvalArrayEquality(bv); + } + // Hack!!!! array equalities can occur negatively! + if(bv.is_app() && bv.decl().get_decl_kind() == Not && + bv.arg(0).decl().get_decl_kind() == Equal && + bv.arg(0).arg(0).is_array()){ + bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); + } + if(eq(bv,ctx.bool_val(true))) + res = 1; + else if(eq(bv,ctx.bool_val(false))) + res = 0; + else + res = 2; } - { - expr bv = dualModel.eval(f); - if(bv.is_app() && bv.decl().get_decl_kind() == Equal && - bv.arg(0).is_array()){ - bv = EvalArrayEquality(bv); - } - // Hack!!!! array equalities can occur negatively! - if(bv.is_app() && bv.decl().get_decl_kind() == Not && - bv.arg(0).decl().get_decl_kind() == Equal && - bv.arg(0).arg(0).is_array()){ - bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); - } - if(eq(bv,ctx.bool_val(true))) - res = 1; - else if(eq(bv,ctx.bool_val(false))) - res = 0; - else - res = 2; - } - done: +done: memo[labpos][f] = res; return res; } #endif - void RPFP::GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, - hash_set *done, bool truth){ - if(done[truth].find(f) != done[truth].end()) - return; /* already processed */ - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies){ - GetLabelsRec(memo,f.arg(1) || !f.arg(0) ,labels,done,truth); - goto done; + void RPFP::GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, + hash_set *done, bool truth) { + if (done[truth].find(f) != done[truth].end()) + return; /* already processed */ + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + GetLabelsRec(memo, f.arg(1) || !f.arg(0), labels, done, truth); + goto done; + } + if (k == Iff) { + int b = SubtermTruth(memo, f.arg(0)); + if (b == 2) + throw "disaster in GetLabelsRec"; + GetLabelsRec(memo, f.arg(1), labels, done, truth ? b : !b); + goto done; + } + if (truth ? k == And : k == Or) { + for (int i = 0; i < nargs; i++) + GetLabelsRec(memo, f.arg(i), labels, done, truth); + goto done; + } + if (truth ? k == Or : k == And) { + for (int i = 0; i < nargs; i++) { + Term a = f.arg(i); + timer_start("SubtermTruth"); + int b = SubtermTruth(memo, a); + timer_stop("SubtermTruth"); + if (truth ? (b == 1) : (b == 0)) { + GetLabelsRec(memo, a, labels, done, truth); + goto done; + } + } + /* Unreachable! */ + // throw "error in RPFP::GetLabelsRec"; + goto done; + } + else if (k == Not) { + GetLabelsRec(memo, f.arg(0), labels, done, !truth); + goto done; + } + else { + bool pos; std::vector names; + if (f.is_label(pos, names)) { + GetLabelsRec(memo, f.arg(0), labels, done, truth); + if (pos == truth) + for (unsigned i = 0; i < names.size(); i++) + labels.push_back(names[i]); + goto done; + } + } } - if(k == Iff){ - int b = SubtermTruth(memo,f.arg(0)); - if(b == 2) - throw "disaster in GetLabelsRec"; - GetLabelsRec(memo,f.arg(1),labels,done,truth ? b : !b); - goto done; - } - if(truth ? k == And : k == Or) { - for(int i = 0; i < nargs; i++) - GetLabelsRec(memo,f.arg(i),labels,done,truth); - goto done; - } - if(truth ? k == Or : k == And) { - for(int i = 0; i < nargs; i++){ - Term a = f.arg(i); - timer_start("SubtermTruth"); - int b = SubtermTruth(memo,a); - timer_stop("SubtermTruth"); - if(truth ? (b == 1) : (b == 0)){ - GetLabelsRec(memo,a,labels,done,truth); - goto done; - } - } - /* Unreachable! */ - // throw "error in RPFP::GetLabelsRec"; - goto done; - } - else if(k == Not) { - GetLabelsRec(memo,f.arg(0),labels,done,!truth); - goto done; - } - else { - bool pos; std::vector names; - if(f.is_label(pos,names)){ - GetLabelsRec(memo,f.arg(0), labels, done, truth); - if(pos == truth) - for(unsigned i = 0; i < names.size(); i++) - labels.push_back(names[i]); - goto done; - } - } - } done: - done[truth].insert(f); + done[truth].insert(f); } void RPFP::GetLabels(Edge *e, std::vector &labels){ @@ -1833,185 +1807,184 @@ namespace Duality { int ir_count = 0; - void RPFP::ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set *done, bool truth, hash_set &dont_cares){ - if(done[truth].find(f) != done[truth].end()) - return; /* already processed */ + void RPFP::ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set *done, bool truth, hash_set &dont_cares) { + if (done[truth].find(f) != done[truth].end()) + return; /* already processed */ #if 0 - int this_count = ir_count++; - if(this_count == 50092) - std::cout << "foo!\n"; + int this_count = ir_count++; + if(this_count == 50092) + std::cout << "foo!\n"; #endif - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies){ - ImplicantRed(memo,f.arg(1) || !f.arg(0) ,lits,done,truth,dont_cares); - goto done; - } - if(k == Iff){ - int b = SubtermTruth(memo,f.arg(0)); - if(b == 2) - throw "disaster in ImplicantRed"; - ImplicantRed(memo,f.arg(1),lits,done,truth ? b : !b,dont_cares); - goto done; - } - if(truth ? k == And : k == Or) { - for(int i = 0; i < nargs; i++) - ImplicantRed(memo,f.arg(i),lits,done,truth,dont_cares); - goto done; - } - if(truth ? k == Or : k == And) { - for(int i = 0; i < nargs; i++){ - Term a = f.arg(i); + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + ImplicantRed(memo, f.arg(1) || !f.arg(0), lits, done, truth, dont_cares); + goto done; + } + if (k == Iff) { + int b = SubtermTruth(memo, f.arg(0)); + if (b == 2) + throw "disaster in ImplicantRed"; + ImplicantRed(memo, f.arg(1), lits, done, truth ? b : !b, dont_cares); + goto done; + } + if (truth ? k == And : k == Or) { + for (int i = 0; i < nargs; i++) + ImplicantRed(memo, f.arg(i), lits, done, truth, dont_cares); + goto done; + } + if (truth ? k == Or : k == And) { + for (int i = 0; i < nargs; i++) { + Term a = f.arg(i); #if 0 - if(i == nargs - 1){ // last chance! - ImplicantRed(memo,a,lits,done,truth,dont_cares); - goto done; - } + if(i == nargs - 1){ // last chance! + ImplicantRed(memo,a,lits,done,truth,dont_cares); + goto done; + } #endif - timer_start("SubtermTruth"); + timer_start("SubtermTruth"); #ifdef Z3OPS - bool b = stt->eval(a); + bool b = stt->eval(a); #else - int b = SubtermTruth(memo,a); + int b = SubtermTruth(memo, a); #endif - timer_stop("SubtermTruth"); - if(truth ? (b == 1) : (b == 0)){ - ImplicantRed(memo,a,lits,done,truth,dont_cares); - goto done; - } - } - /* Unreachable! */ - // TODO: need to indicate this failure to caller - // std::cerr << "error in RPFP::ImplicantRed"; - goto done; + timer_stop("SubtermTruth"); + if (truth ? (b == 1) : (b == 0)) { + ImplicantRed(memo, a, lits, done, truth, dont_cares); + goto done; + } + } + /* Unreachable! */ + // TODO: need to indicate this failure to caller + // std::cerr << "error in RPFP::ImplicantRed"; + goto done; + } + else if (k == Not) { + ImplicantRed(memo, f.arg(0), lits, done, !truth, dont_cares); + goto done; + } } - else if(k == Not) { - ImplicantRed(memo,f.arg(0),lits,done,!truth,dont_cares); - goto done; - } - } { - if(dont_cares.find(f) == dont_cares.end()){ - expr rf = ResolveIte(memo,f,lits,done,dont_cares); - expr bv = truth ? rf : !rf; - lits.push_back(bv); - } + if (dont_cares.find(f) == dont_cares.end()) { + expr rf = ResolveIte(memo, f, lits, done, dont_cares); + expr bv = truth ? rf : !rf; + lits.push_back(bv); + } } - done: +done: done[truth].insert(f); } - void RPFP::ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set &done, hash_set &dont_cares, bool extensional){ - if(done.find(f) != done.end()) - return; /* already processed */ - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies || k == Iff || k == And || k == Or || k == Not){ - for(int i = 0; i < nargs; i++) - ImplicantFullRed(memo,f.arg(i),lits,done,dont_cares, extensional); - goto done; + void RPFP::ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set &done, hash_set &dont_cares, bool extensional) { + if (done.find(f) != done.end()) + return; /* already processed */ + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies || k == Iff || k == And || k == Or || k == Not) { + for (int i = 0; i < nargs; i++) + ImplicantFullRed(memo, f.arg(i), lits, done, dont_cares, extensional); + goto done; + } } - } { - if(dont_cares.find(f) == dont_cares.end()){ - int b = SubtermTruth(memo,f); - if(b != 0 && b != 1) goto done; - if(f.is_app() && f.decl().get_decl_kind() == Equal && f.arg(0).is_array()){ - if(b == 1 && !extensional){ - expr x = dualModel.eval(f.arg(0)); expr y = dualModel.eval(f.arg(1)); - if(!eq(x,y)) - b = 0; - } - if(b == 0) - goto done; - } - expr bv = (b==1) ? f : !f; - lits.push_back(bv); - } + if (dont_cares.find(f) == dont_cares.end()) { + int b = SubtermTruth(memo, f); + if (b != 0 && b != 1) goto done; + if (f.is_app() && f.decl().get_decl_kind() == Equal && f.arg(0).is_array()) { + if (b == 1 && !extensional) { + expr x = dualModel.eval(f.arg(0)); expr y = dualModel.eval(f.arg(1)); + if (!eq(x, y)) + b = 0; + } + if (b == 0) + goto done; + } + expr bv = (b == 1) ? f : !f; + lits.push_back(bv); + } } - done: +done: done.insert(f); } - RPFP::Term RPFP::ResolveIte(hash_map &memo, const Term &t, std::vector &lits, - hash_set *done, hash_set &dont_cares){ - if(resolve_ite_memo.find(t) != resolve_ite_memo.end()) - return resolve_ite_memo[t]; - Term res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if(f.get_decl_kind() == Ite){ - timer_start("SubtermTruth"); + RPFP::Term RPFP::ResolveIte(hash_map &memo, const Term &t, std::vector &lits, + hash_set *done, hash_set &dont_cares) { + if (resolve_ite_memo.find(t) != resolve_ite_memo.end()) + return resolve_ite_memo[t]; + Term res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if (f.get_decl_kind() == Ite) { + timer_start("SubtermTruth"); #ifdef Z3OPS - bool sel = stt->eval(t.arg(0)); + bool sel = stt->eval(t.arg(0)); #else - int xval = SubtermTruth(memo,t.arg(0)); - bool sel; - if(xval == 0)sel = false; - else if(xval == 1)sel = true; - else - throw "unresolved ite in model"; + int xval = SubtermTruth(memo, t.arg(0)); + bool sel; + if (xval == 0)sel = false; + else if (xval == 1)sel = true; + else + throw "unresolved ite in model"; #endif - timer_stop("SubtermTruth"); - ImplicantRed(memo,t.arg(0),lits,done,sel,dont_cares); - res = ResolveIte(memo,t.arg(sel?1:2),lits,done,dont_cares); - } - else { - for(int i = 0; i < nargs; i++) - args.push_back(ResolveIte(memo,t.arg(i),lits,done,dont_cares)); - res = f(args.size(),&args[0]); - } + timer_stop("SubtermTruth"); + ImplicantRed(memo, t.arg(0), lits, done, sel, dont_cares); + res = ResolveIte(memo, t.arg(sel ? 1 : 2), lits, done, dont_cares); + } + else { + for (int i = 0; i < nargs; i++) + args.push_back(ResolveIte(memo, t.arg(i), lits, done, dont_cares)); + res = f(args.size(), &args[0]); + } } - else res = t; - resolve_ite_memo[t] = res; - return res; + else res = t; + resolve_ite_memo[t] = res; + return res; } - RPFP::Term RPFP::ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts){ - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(bar.second){ - if(t.is_app()){ - int nargs = t.num_args(); - std::vector args; - if(t.decl().get_decl_kind() == Equal){ - expr lhs = t.arg(0); - expr rhs = t.arg(1); - if(rhs.decl().get_decl_kind() == Ite){ - expr rhs_args[3]; - lhs = ElimIteRec(memo,lhs,cnsts); - for(int i = 0; i < 3; i++) - rhs_args[i] = ElimIteRec(memo,rhs.arg(i),cnsts); - res = (rhs_args[0] && (lhs == rhs_args[1])) || ((!rhs_args[0]) && (lhs == rhs_args[2])); - goto done; - } - } - if(t.decl().get_decl_kind() == Ite){ - func_decl sym = ctx.fresh_func_decl("@ite", t.get_sort()); - res = sym(); - cnsts.push_back(ElimIteRec(memo,ctx.make(Equal,res,t),cnsts)); - } - else { - for(int i = 0; i < nargs; i++) - args.push_back(ElimIteRec(memo,t.arg(i),cnsts)); - res = t.decl()(args.size(),&args[0]); - } + RPFP::Term RPFP::ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (bar.second) { + if (t.is_app()) { + int nargs = t.num_args(); + std::vector args; + if (t.decl().get_decl_kind() == Equal) { + expr lhs = t.arg(0); + expr rhs = t.arg(1); + if (rhs.decl().get_decl_kind() == Ite) { + expr rhs_args[3]; + lhs = ElimIteRec(memo, lhs, cnsts); + for (int i = 0; i < 3; i++) + rhs_args[i] = ElimIteRec(memo, rhs.arg(i), cnsts); + res = (rhs_args[0] && (lhs == rhs_args[1])) || ((!rhs_args[0]) && (lhs == rhs_args[2])); + goto done; + } + } + if (t.decl().get_decl_kind() == Ite) { + func_decl sym = ctx.fresh_func_decl("@ite", t.get_sort()); + res = sym(); + cnsts.push_back(ElimIteRec(memo, ctx.make(Equal, res, t), cnsts)); + } + else { + for (int i = 0; i < nargs; i++) + args.push_back(ElimIteRec(memo, t.arg(i), cnsts)); + res = t.decl()(args.size(), &args[0]); + } + } + else if (t.is_quantifier()) + res = clone_quantifier(t, ElimIteRec(memo, t.body(), cnsts)); + else + res = t; } - else if(t.is_quantifier()) - res = clone_quantifier(t,ElimIteRec(memo,t.body(),cnsts)); - else - res = t; - } done: - return res; + return res; } RPFP::Term RPFP::ElimIte(const Term &t){ @@ -2084,169 +2057,166 @@ namespace Duality { hash_map cand_map; params simp_params; - VariableProjector(Z3User &_user, std::vector &keep_vec) : - Z3User(_user), simp_params() - { - num_vars = 0; - for(unsigned i = 0; i < keep_vec.size(); i++){ - keep.insert(keep_vec[i]); - var_ord[keep_vec[i]] = num_vars++; - } + VariableProjector(Z3User &_user, std::vector &keep_vec) : + Z3User(_user), simp_params() { + num_vars = 0; + for (unsigned i = 0; i < keep_vec.size(); i++) { + keep.insert(keep_vec[i]); + var_ord[keep_vec[i]] = num_vars++; + } } - - int VarNum(const Term &v){ - if(var_ord.find(v) == var_ord.end()) - var_ord[v] = num_vars++; - return var_ord[v]; + int VarNum(const Term &v) { + if (var_ord.find(v) == var_ord.end()) + var_ord[v] = num_vars++; + return var_ord[v]; } bool IsVar(const Term &t){ return t.is_app() && t.num_args() == 0 && t.decl().get_decl_kind() == Uninterpreted; } - bool IsPropLit(const Term &t, Term &a){ - if(IsVar(t)){ - a = t; - return true; - } - else if(t.is_app() && t.decl().get_decl_kind() == Not) - return IsPropLit(t.arg(0),a); - return false; + bool IsPropLit(const Term &t, Term &a) { + if (IsVar(t)) { + a = t; + return true; + } + else if (t.is_app() && t.decl().get_decl_kind() == Not) + return IsPropLit(t.arg(0), a); + return false; } - void CountOtherVarsRec(hash_map &memo, - const Term &t, - int id, - int &count){ - std::pair foo(t,0); - std::pair::iterator, bool> bar = memo.insert(foo); - // int &res = bar.first->second; - if(!bar.second) return; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if (nargs == 0 && f.get_decl_kind() == Uninterpreted){ - if(cand_map.find(t) != cand_map.end()){ - count++; - sup_map[t].push_back(id); - } - } - for(int i = 0; i < nargs; i++) - CountOtherVarsRec(memo, t.arg(i), id, count); - } - else if (t.is_quantifier()) - CountOtherVarsRec(memo, t.body(), id, count); - } + void CountOtherVarsRec(hash_map &memo, + const Term &t, + int id, + int &count) { + std::pair foo(t, 0); + std::pair::iterator, bool> bar = memo.insert(foo); + // int &res = bar.first->second; + if (!bar.second) return; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if (nargs == 0 && f.get_decl_kind() == Uninterpreted) { + if (cand_map.find(t) != cand_map.end()) { + count++; + sup_map[t].push_back(id); + } + } + for (int i = 0; i < nargs; i++) + CountOtherVarsRec(memo, t.arg(i), id, count); + } + else if (t.is_quantifier()) + CountOtherVarsRec(memo, t.body(), id, count); + } - void NewElimCand(const Term &lhs, const Term &rhs){ - if(debug_gauss){ - std::cout << "mapping " << lhs << " to " << rhs << std::endl; - } - elim_cand cand; - cand.var = lhs; - cand.sup = 0; - cand.val = rhs; - elim_cands.push_back(cand); - cand_map[lhs] = elim_cands.size()-1; + void NewElimCand(const Term &lhs, const Term &rhs) { + if (debug_gauss) { + std::cout << "mapping " << lhs << " to " << rhs << std::endl; + } + elim_cand cand; + cand.var = lhs; + cand.sup = 0; + cand.val = rhs; + elim_cands.push_back(cand); + cand_map[lhs] = elim_cands.size() - 1; } - void MakeElimCand(const Term &lhs, const Term &rhs){ - if(eq(lhs,rhs)) - return; - if(!IsVar(lhs)){ - if(IsVar(rhs)){ - MakeElimCand(rhs,lhs); - return; - } - else{ - std::cout << "would have mapped a non-var\n"; - return; - } - } - if(IsVar(rhs) && VarNum(rhs) > VarNum(lhs)){ - MakeElimCand(rhs,lhs); - return; - } - if(keep.find(lhs) != keep.end()) - return; - if(cand_map.find(lhs) == cand_map.end()) - NewElimCand(lhs,rhs); - else { - int cand_idx = cand_map[lhs]; - if(IsVar(rhs) && cand_map.find(rhs) == cand_map.end() - && keep.find(rhs) == keep.end()) - NewElimCand(rhs,elim_cands[cand_idx].val); - elim_cands[cand_idx].val = rhs; - } + void MakeElimCand(const Term &lhs, const Term &rhs) { + if (eq(lhs, rhs)) + return; + if (!IsVar(lhs)) { + if (IsVar(rhs)) { + MakeElimCand(rhs, lhs); + return; + } + else { + std::cout << "would have mapped a non-var\n"; + return; + } + } + if (IsVar(rhs) && VarNum(rhs) > VarNum(lhs)) { + MakeElimCand(rhs, lhs); + return; + } + if (keep.find(lhs) != keep.end()) + return; + if (cand_map.find(lhs) == cand_map.end()) + NewElimCand(lhs, rhs); + else { + int cand_idx = cand_map[lhs]; + if (IsVar(rhs) && cand_map.find(rhs) == cand_map.end() + && keep.find(rhs) == keep.end()) + NewElimCand(rhs, elim_cands[cand_idx].val); + elim_cands[cand_idx].val = rhs; + } } - Term FindRep(const Term &t){ - if(cand_map.find(t) == cand_map.end()) - return t; - Term &res = elim_cands[cand_map[t]].val; - if(IsVar(res)){ - assert(VarNum(res) < VarNum(t)); - res = FindRep(res); - return res; - } - return t; + Term FindRep(const Term &t) { + if (cand_map.find(t) == cand_map.end()) + return t; + Term &res = elim_cands[cand_map[t]].val; + if (IsVar(res)) { + assert(VarNum(res) < VarNum(t)); + res = FindRep(res); + return res; + } + return t; } void GaussElimCheap(const std::vector &lits_in, - std::vector &lits_out){ - for(unsigned i = 0; i < lits_in.size(); i++){ - Term lit = lits_in[i]; - if(lit.is_app()){ - decl_kind k = lit.decl().get_decl_kind(); - if(k == Equal || k == Iff) - MakeElimCand(FindRep(lit.arg(0)),FindRep(lit.arg(1))); - } - } - - for(unsigned i = 0; i < elim_cands.size(); i++){ - elim_cand &cand = elim_cands[i]; - hash_map memo; - CountOtherVarsRec(memo,cand.val,i,cand.sup); - if(cand.sup == 0) - ready_cands.push_back(i); - } - - while(!ready_cands.empty()){ - elim_cand &cand = elim_cands[ready_cands.back()]; - ready_cands.pop_back(); - Term rep = FindRep(cand.var); - if(!eq(rep,cand.var)) - if(cand_map.find(rep) != cand_map.end()){ - int rep_pos = cand_map[rep]; - cand.val = elim_cands[rep_pos].val; - } - Term val = SubstRec(elim_map,cand.val); - if(debug_gauss){ - std::cout << "subbing " << cand.var << " --> " << val << std::endl; - } - elim_map[cand.var] = val; - std::vector &sup = sup_map[cand.var]; - for(unsigned i = 0; i < sup.size(); i++){ - int c = sup[i]; - if((--elim_cands[c].sup) == 0) - ready_cands.push_back(c); - } - } - - for(unsigned i = 0; i < lits_in.size(); i++){ - Term lit = lits_in[i]; - lit = SubstRec(elim_map,lit); - lit = lit.simplify(); - if(eq(lit,ctx.bool_val(true))) - continue; - Term a; - if(IsPropLit(lit,a)) - if(keep.find(lit) == keep.end()) - continue; - lits_out.push_back(lit); - } + std::vector &lits_out) { + for (unsigned i = 0; i < lits_in.size(); i++) { + Term lit = lits_in[i]; + if (lit.is_app()) { + decl_kind k = lit.decl().get_decl_kind(); + if (k == Equal || k == Iff) + MakeElimCand(FindRep(lit.arg(0)), FindRep(lit.arg(1))); + } + } + + for (unsigned i = 0; i < elim_cands.size(); i++) { + elim_cand &cand = elim_cands[i]; + hash_map memo; + CountOtherVarsRec(memo, cand.val, i, cand.sup); + if (cand.sup == 0) + ready_cands.push_back(i); + } + + while (!ready_cands.empty()) { + elim_cand &cand = elim_cands[ready_cands.back()]; + ready_cands.pop_back(); + Term rep = FindRep(cand.var); + if (!eq(rep, cand.var)) + if (cand_map.find(rep) != cand_map.end()) { + int rep_pos = cand_map[rep]; + cand.val = elim_cands[rep_pos].val; + } + Term val = SubstRec(elim_map, cand.val); + if (debug_gauss) { + std::cout << "subbing " << cand.var << " --> " << val << std::endl; + } + elim_map[cand.var] = val; + std::vector &sup = sup_map[cand.var]; + for (unsigned i = 0; i < sup.size(); i++) { + int c = sup[i]; + if ((--elim_cands[c].sup) == 0) + ready_cands.push_back(c); + } + } + + for (unsigned i = 0; i < lits_in.size(); i++) { + Term lit = lits_in[i]; + lit = SubstRec(elim_map, lit); + lit = lit.simplify(); + if (eq(lit, ctx.bool_val(true))) + continue; + Term a; + if (IsPropLit(lit, a)) + if (keep.find(lit) == keep.end()) + continue; + lits_out.push_back(lit); + } } // maps variables to constrains in which the occur pos, neg @@ -2255,88 +2225,88 @@ namespace Duality { std::vector la_pos_vars; bool fixing; - void IndexLAcoeff(const Term &coeff1, const Term &coeff2, Term t, int id){ - Term coeff = coeff1 * coeff2; - coeff = coeff.simplify(); - Term is_pos = (coeff >= ctx.int_val(0)); - is_pos = is_pos.simplify(); - if(eq(is_pos,ctx.bool_val(true))) - IndexLA(true,coeff,t, id); - else - IndexLA(false,coeff,t, id); + void IndexLAcoeff(const Term &coeff1, const Term &coeff2, Term t, int id) { + Term coeff = coeff1 * coeff2; + coeff = coeff.simplify(); + Term is_pos = (coeff >= ctx.int_val(0)); + is_pos = is_pos.simplify(); + if (eq(is_pos, ctx.bool_val(true))) + IndexLA(true, coeff, t, id); + else + IndexLA(false, coeff, t, id); } - void IndexLAremove(const Term &t){ - if(IsVar(t)){ - la_index[0][t] = -1; // means ineligible to be eliminated - la_index[1][t] = -1; // (more that one occurrence, or occurs not in linear comb) - } - else if(t.is_app()){ - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - IndexLAremove(t.arg(i)); - } - // TODO: quantifiers? + void IndexLAremove(const Term &t) { + if (IsVar(t)) { + la_index[0][t] = -1; // means ineligible to be eliminated + la_index[1][t] = -1; // (more that one occurrence, or occurs not in linear comb) + } + else if (t.is_app()) { + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + IndexLAremove(t.arg(i)); + } + // TODO: quantifiers? } - void IndexLA(bool pos, const Term &coeff, const Term &t, int id){ - if(t.is_numeral()) - return; - if(t.is_app()){ - int nargs = t.num_args(); - switch(t.decl().get_decl_kind()){ - case Plus: - for(int i = 0; i < nargs; i++) - IndexLA(pos,coeff,t.arg(i), id); - break; - case Sub: - IndexLA(pos,coeff,t.arg(0), id); - IndexLA(!pos,coeff,t.arg(1), id); - break; - case Times: - if(t.arg(0).is_numeral()) - IndexLAcoeff(coeff,t.arg(0),t.arg(1), id); - else if(t.arg(1).is_numeral()) - IndexLAcoeff(coeff,t.arg(1),t.arg(0), id); - break; - default: - if(IsVar(t) && (fixing || la_index[pos].find(t) == la_index[pos].end())){ - la_index[pos][t] = id; - la_coeffs[pos][t] = coeff; - if(pos && !fixing) - la_pos_vars.push_back(t); // this means we only add a var once - } - else - IndexLAremove(t); - } - } + void IndexLA(bool pos, const Term &coeff, const Term &t, int id) { + if (t.is_numeral()) + return; + if (t.is_app()) { + int nargs = t.num_args(); + switch (t.decl().get_decl_kind()) { + case Plus: + for (int i = 0; i < nargs; i++) + IndexLA(pos, coeff, t.arg(i), id); + break; + case Sub: + IndexLA(pos, coeff, t.arg(0), id); + IndexLA(!pos, coeff, t.arg(1), id); + break; + case Times: + if (t.arg(0).is_numeral()) + IndexLAcoeff(coeff, t.arg(0), t.arg(1), id); + else if (t.arg(1).is_numeral()) + IndexLAcoeff(coeff, t.arg(1), t.arg(0), id); + break; + default: + if (IsVar(t) && (fixing || la_index[pos].find(t) == la_index[pos].end())) { + la_index[pos][t] = id; + la_coeffs[pos][t] = coeff; + if (pos && !fixing) + la_pos_vars.push_back(t); // this means we only add a var once + } + else + IndexLAremove(t); + } + } } void IndexLAstart(bool pos, const Term &t, int id){ IndexLA(pos,(pos ? ctx.int_val(1) : ctx.int_val(-1)), t, id); } - void IndexLApred(bool pos, const Term &p, int id){ - if(p.is_app()){ - switch(p.decl().get_decl_kind()){ - case Not: - IndexLApred(!pos, p.arg(0),id); - break; - case Leq: - case Lt: - IndexLAstart(!pos, p.arg(0), id); - IndexLAstart(pos, p.arg(1), id); - break; - case Geq: - case Gt: - IndexLAstart(pos,p.arg(0), id); - IndexLAstart(!pos,p.arg(1), id); - break; - default: - IndexLAremove(p); - } - } + void IndexLApred(bool pos, const Term &p, int id) { + if (p.is_app()) { + switch (p.decl().get_decl_kind()) { + case Not: + IndexLApred(!pos, p.arg(0), id); + break; + case Leq: + case Lt: + IndexLAstart(!pos, p.arg(0), id); + IndexLAstart(pos, p.arg(1), id); + break; + case Geq: + case Gt: + IndexLAstart(pos, p.arg(0), id); + IndexLAstart(!pos, p.arg(1), id); + break; + default: + IndexLAremove(p); + } + } } void IndexLAfix(const Term &p, int id){ @@ -2345,51 +2315,51 @@ namespace Duality { fixing = false; } - bool IsCanonIneq(const Term &lit, Term &term, Term &bound){ - // std::cout << Z3_simplify_get_help(ctx) << std::endl; - bool pos = lit.decl().get_decl_kind() != Not; - Term atom = pos ? lit : lit.arg(0); - if(atom.decl().get_decl_kind() == Leq){ - if(pos){ - bound = atom.arg(0); - term = atom.arg(1).simplify(simp_params); + bool IsCanonIneq(const Term &lit, Term &term, Term &bound) { + // std::cout << Z3_simplify_get_help(ctx) << std::endl; + bool pos = lit.decl().get_decl_kind() != Not; + Term atom = pos ? lit : lit.arg(0); + if (atom.decl().get_decl_kind() == Leq) { + if (pos) { + bound = atom.arg(0); + term = atom.arg(1).simplify(simp_params); #if Z3_MAJOR_VERSION < 4 - term = SortSum(term); + term = SortSum(term); #endif - } - else { - bound = (atom.arg(1) + ctx.int_val(1)); - term = atom.arg(0); - // std::cout << "simplifying bound: " << bound << std::endl; - bound = bound.simplify(); - term = term.simplify(simp_params); + } + else { + bound = (atom.arg(1) + ctx.int_val(1)); + term = atom.arg(0); + // std::cout << "simplifying bound: " << bound << std::endl; + bound = bound.simplify(); + term = term.simplify(simp_params); #if Z3_MAJOR_VERSION < 4 - term = SortSum(term); + term = SortSum(term); #endif - } - return true; - } - else if(atom.decl().get_decl_kind() == Geq){ - if(pos){ - bound = atom.arg(1); // integer axiom - term = atom.arg(0).simplify(simp_params); + } + return true; + } + else if (atom.decl().get_decl_kind() == Geq) { + if (pos) { + bound = atom.arg(1); // integer axiom + term = atom.arg(0).simplify(simp_params); #if Z3_MAJOR_VERSION < 4 - term = SortSum(term); + term = SortSum(term); #endif - return true; - } - else{ - bound = -(atom.arg(1) - ctx.int_val(1)); // integer axiom - term = -atom.arg(0); - bound = bound.simplify(); - term = term.simplify(simp_params); + return true; + } + else { + bound = -(atom.arg(1) - ctx.int_val(1)); // integer axiom + term = -atom.arg(0); + bound = bound.simplify(); + term = term.simplify(simp_params); #if Z3_MAJOR_VERSION < 4 - term = SortSum(term); + term = SortSum(term); #endif - } - return true; - } - return false; + } + return true; + } + return false; } Term CanonIneqTerm(const Term &p){ @@ -2400,64 +2370,64 @@ namespace Duality { return term - bound; } - void ElimRedundantBounds(std::vector &lits){ - hash_map best_bound; - for(unsigned i = 0; i < lits.size(); i++){ - lits[i] = lits[i].simplify(simp_params); - Term term,bound; - if(IsCanonIneq(lits[i],term,bound)){ - if(best_bound.find(term) == best_bound.end()) - best_bound[term] = i; - else { - int best = best_bound[term]; - Term bterm,bbound; - IsCanonIneq(lits[best],bterm,bbound); - Term comp = bound > bbound; - comp = comp.simplify(); - if(eq(comp,ctx.bool_val(true))){ - lits[best] = ctx.bool_val(true); - best_bound[term] = i; - } - else { - lits[i] = ctx.bool_val(true); - } - } - } - } + void ElimRedundantBounds(std::vector &lits) { + hash_map best_bound; + for (unsigned i = 0; i < lits.size(); i++) { + lits[i] = lits[i].simplify(simp_params); + Term term, bound; + if (IsCanonIneq(lits[i], term, bound)) { + if (best_bound.find(term) == best_bound.end()) + best_bound[term] = i; + else { + int best = best_bound[term]; + Term bterm, bbound; + IsCanonIneq(lits[best], bterm, bbound); + Term comp = bound > bbound; + comp = comp.simplify(); + if (eq(comp, ctx.bool_val(true))) { + lits[best] = ctx.bool_val(true); + best_bound[term] = i; + } + else { + lits[i] = ctx.bool_val(true); + } + } + } + } } void FourierMotzkinCheap(const std::vector &lits_in, - std::vector &lits_out){ - simp_params.set(":som",true); - simp_params.set(":sort-sums",true); - fixing = false; lits_out = lits_in; - ElimRedundantBounds(lits_out); - for(unsigned i = 0; i < lits_out.size(); i++) - IndexLApred(true,lits_out[i],i); + std::vector &lits_out) { + simp_params.set(":som", true); + simp_params.set(":sort-sums", true); + fixing = false; lits_out = lits_in; + ElimRedundantBounds(lits_out); + for (unsigned i = 0; i < lits_out.size(); i++) + IndexLApred(true, lits_out[i], i); - for(unsigned i = 0; i < la_pos_vars.size(); i++){ - Term var = la_pos_vars[i]; - if(la_index[false].find(var) != la_index[false].end()){ - int pos_idx = la_index[true][var]; - int neg_idx = la_index[false][var]; - if(pos_idx >= 0 && neg_idx >= 0){ - if(keep.find(var) != keep.end()){ - std::cout << "would have eliminated keep var\n"; - continue; - } - Term tpos = CanonIneqTerm(lits_out[pos_idx]); - Term tneg = CanonIneqTerm(lits_out[neg_idx]); - Term pos_coeff = la_coeffs[true][var]; - Term neg_coeff = -la_coeffs[false][var]; - Term comb = neg_coeff * tpos + pos_coeff * tneg; - Term ineq = ctx.int_val(0) <= comb; - ineq = ineq.simplify(); - lits_out[pos_idx] = ineq; - lits_out[neg_idx] = ctx.bool_val(true); - IndexLAfix(ineq,pos_idx); - } - } - } + for (unsigned i = 0; i < la_pos_vars.size(); i++) { + Term var = la_pos_vars[i]; + if (la_index[false].find(var) != la_index[false].end()) { + int pos_idx = la_index[true][var]; + int neg_idx = la_index[false][var]; + if (pos_idx >= 0 && neg_idx >= 0) { + if (keep.find(var) != keep.end()) { + std::cout << "would have eliminated keep var\n"; + continue; + } + Term tpos = CanonIneqTerm(lits_out[pos_idx]); + Term tneg = CanonIneqTerm(lits_out[neg_idx]); + Term pos_coeff = la_coeffs[true][var]; + Term neg_coeff = -la_coeffs[false][var]; + Term comb = neg_coeff * tpos + pos_coeff * tneg; + Term ineq = ctx.int_val(0) <= comb; + ineq = ineq.simplify(); + lits_out[pos_idx] = ineq; + lits_out[neg_idx] = ctx.bool_val(true); + IndexLAfix(ineq, pos_idx); + } + } + } } Term ProjectFormula(const Term &f){ @@ -2473,42 +2443,42 @@ namespace Duality { } }; - void Z3User::CollectConjuncts(const Term &f, std::vector &lits, bool pos){ - if(f.is_app() && f.decl().get_decl_kind() == Not) - CollectConjuncts(f.arg(0), lits, !pos); - else if(pos && f.is_app() && f.decl().get_decl_kind() == And){ - int num_args = f.num_args(); - for(int i = 0; i < num_args; i++) - CollectConjuncts(f.arg(i),lits,true); - } - else if(!pos && f.is_app() && f.decl().get_decl_kind() == Or){ - int num_args = f.num_args(); - for(int i = 0; i < num_args; i++) - CollectConjuncts(f.arg(i),lits,false); - } - else if(pos){ - if(!eq(f,ctx.bool_val(true))) - lits.push_back(f); - } - else { - if(!eq(f,ctx.bool_val(false))) - lits.push_back(!f); - } + void Z3User::CollectConjuncts(const Term &f, std::vector &lits, bool pos) { + if (f.is_app() && f.decl().get_decl_kind() == Not) + CollectConjuncts(f.arg(0), lits, !pos); + else if (pos && f.is_app() && f.decl().get_decl_kind() == And) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectConjuncts(f.arg(i), lits, true); + } + else if (!pos && f.is_app() && f.decl().get_decl_kind() == Or) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectConjuncts(f.arg(i), lits, false); + } + else if (pos) { + if (!eq(f, ctx.bool_val(true))) + lits.push_back(f); + } + else { + if (!eq(f, ctx.bool_val(false))) + lits.push_back(!f); + } } - void Z3User::CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate){ - if(f.is_app() && f.decl().get_decl_kind() == Not) - CollectJuncts(f.arg(0), lits, (op == And) ? Or : And, !negate); - else if(f.is_app() && f.decl().get_decl_kind() == op){ - int num_args = f.num_args(); - for(int i = 0; i < num_args; i++) - CollectJuncts(f.arg(i),lits,op,negate); - } - else { - expr junct = negate ? Negate(f) : f; - lits.push_back(junct); - } - } + void Z3User::CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate) { + if (f.is_app() && f.decl().get_decl_kind() == Not) + CollectJuncts(f.arg(0), lits, (op == And) ? Or : And, !negate); + else if (f.is_app() && f.decl().get_decl_kind() == op) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectJuncts(f.arg(i), lits, op, negate); + } + else { + expr junct = negate ? Negate(f) : f; + lits.push_back(junct); + } + }| struct TermLt { bool operator()(const expr &x, const expr &y){ @@ -2591,7 +2561,7 @@ namespace Duality { hash_map memo; int res = SubtermTruth(memo, eu); if(res != 1) - throw "inconsistent projection"; + throw "inconsistent projection"; } #endif @@ -2622,16 +2592,16 @@ namespace Duality { if(memo[under].find(f) != memo[under].end()) return; memo[under].insert(f); - if(f.is_app()){ - if(!under && !f.has_quantifiers()) - return; - decl_kind k = f.decl().get_decl_kind(); - if(k == And || k == Or || k == Implies || k == Iff){ - int num_args = f.num_args(); - for(int i = 0; i < num_args; i++) - GetGroundLitsUnderQuants(memo,f.arg(i),res,under); - return; - } + if (f.is_app()) { + if (!under && !f.has_quantifiers()) + return; + decl_kind k = f.decl().get_decl_kind(); + if (k == And || k == Or || k == Implies || k == Iff) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + GetGroundLitsUnderQuants(memo, f.arg(i), res, under); + return; + } } else if (f.is_quantifier()){ #if 0 @@ -2712,28 +2682,28 @@ namespace Duality { return g; } - RPFP::Term RPFP::ModelValueAsConstraint(const Term &t){ - if(t.is_array()){ - ArrayValue arr; - Term e = dualModel.eval(t); - EvalArrayTerm(e, arr); - if(arr.defined){ - std::vector cs; - for(std::map::iterator it = arr.entries.begin(), en = arr.entries.end(); it != en; ++it){ - expr foo = select(t,expr(ctx,it->first)) == expr(ctx,it->second); - cs.push_back(foo); - } - return conjoin(cs); + RPFP::Term RPFP::ModelValueAsConstraint(const Term &t) { + if (t.is_array()) { + ArrayValue arr; + Term e = dualModel.eval(t); + EvalArrayTerm(e, arr); + if (arr.defined) { + std::vector cs; + for (std::map::iterator it = arr.entries.begin(), en = arr.entries.end(); it != en; ++it) { + expr foo = select(t, expr(ctx, it->first)) == expr(ctx, it->second); + cs.push_back(foo); + } + return conjoin(cs); + } } - } - else { - expr r = dualModel.get_const_interp(t.decl()); - if(!r.null()){ - expr res = t == expr(ctx,r); - return res; + else { + expr r = dualModel.get_const_interp(t.decl()); + if (!r.null()) { + expr res = t == expr(ctx, r); + return res; + } } - } - return ctx.bool_val(true); + return ctx.bool_val(true); } void RPFP::EvalNodeAsConstraint(Node *p, Transformer &res) diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 2548d1180..2129a1810 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -187,10 +187,10 @@ namespace datalog { if (m_trail.get_num_scopes() == 0) { throw default_exception("there are no backtracking points to pop to"); } - if(m_engine.get()){ - if(get_engine() != DUALITY_ENGINE) - throw default_exception("operation is not supported by engine"); - } + if(m_engine.get()){ + if(get_engine() != DUALITY_ENGINE) + throw default_exception("operation is not supported by engine"); + } m_trail.pop_scope(1); } @@ -478,7 +478,7 @@ namespace datalog { void context::add_rule(expr* rl, symbol const& name, unsigned bound) { m_rule_fmls.push_back(rl); m_rule_names.push_back(name); - m_rule_bounds.push_back(bound); + m_rule_bounds.push_back(bound); } void context::flush_add_rules() { @@ -706,7 +706,7 @@ namespace datalog { check_existential_tail(r); check_positive_predicates(r); break; - case DUALITY_ENGINE: + case DUALITY_ENGINE: check_existential_tail(r); check_positive_predicates(r); break; diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 7666b39cf..0ab9762b0 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -77,12 +77,12 @@ namespace Duality { old_rs = 0; } ~duality_data(){ - if(old_rs) - dealloc(old_rs); - if(rpfp) - dealloc(rpfp); - if(ls) - dealloc(ls); + if(old_rs) + dealloc(old_rs); + if(rpfp) + dealloc(rpfp); + if(ls) + (ls); } }; @@ -171,16 +171,16 @@ lbool dl_interface::query(::expr * query) { query_ref = m_ctx.get_manager().mk_false(); else { func_decl_ref query_pred(m_ctx.get_manager()); - query_pred = m_ctx.get_rules().get_output_predicate(); - ptr_vector sorts; - unsigned nargs = query_pred.get()->get_arity(); - expr_ref_vector vars(m_ctx.get_manager()); - for(unsigned i = 0; i < nargs; i++){ - ::sort *s = query_pred.get()->get_domain(i); - vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s)); - } - query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr()); - query = query_ref.get(); + query_pred = m_ctx.get_rules().get_output_predicate(); + ptr_vector sorts; + unsigned nargs = query_pred.get()->get_arity(); + expr_ref_vector vars(m_ctx.get_manager()); + for(unsigned i = 0; i < nargs; i++){ + ::sort *s = query_pred.get()->get_domain(i); + vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s)); + } + query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr()); + query = query_ref.get(); } unsigned nrules = rs.get_num_rules(); for(unsigned i = 0; i < nrules; i++){ @@ -250,16 +250,16 @@ lbool dl_interface::query(::expr * query) { while(true){ if(cl.is_app()){ - decl_kind k = cl.decl().get_decl_kind(); - if(k == Implies) - cl = cl.arg(1); - else { - heads.insert(cl.decl()); - break; - } + decl_kind k = cl.decl().get_decl_kind(); + if(k == Implies) + cl = cl.arg(1); + else { + heads.insert(cl.decl()); + break; + } } else if(cl.is_quantifier()) - cl = cl.body(); + cl = cl.body(); else break; } } @@ -268,18 +268,18 @@ lbool dl_interface::query(::expr * query) { ::ast *fa = pinned[i]; if(is_func_decl(fa)){ ::func_decl *fd = to_func_decl(fa); - if(m_ctx.is_predicate(fd)) { - func_decl f(_d->ctx,fd); - if(!heads.contains(fd)){ - int arity = f.arity(); - std::vector args; - for(int j = 0; j < arity; j++) - args.push_back(_d->ctx.fresh_func_decl("X",f.domain(j))()); - expr c = implies(_d->ctx.bool_val(false),f(args)); - c = _d->ctx.make_quant(Forall,args,c); - clauses.push_back(c); - bounds.push_back(UINT_MAX); - } + if (m_ctx.is_predicate(fd)) { + func_decl f(_d->ctx, fd); + if (!heads.contains(fd)) { + int arity = f.arity(); + std::vector args; + for (int j = 0; j < arity; j++) + args.push_back(_d->ctx.fresh_func_decl("X", f.domain(j))()); + expr c = implies(_d->ctx.bool_val(false), f(args)); + c = _d->ctx.make_quant(Forall, args, c); + clauses.push_back(c); + bounds.push_back(UINT_MAX); + } } } } @@ -483,17 +483,17 @@ void dl_interface::display_certificate_non_const(std::ostream& out) { model orig_model = _d->cex.get_tree()->dualModel; for(unsigned i = 0; i < orig_model.num_consts(); i++){ func_decl cnst = orig_model.get_const_decl(i); - if(locals.find(cnst) == locals.end()){ - expr thing = orig_model.get_const_interp(cnst); - mod.register_decl(to_func_decl(cnst.raw()),to_expr(thing.raw())); + if (locals.find(cnst) == locals.end()) { + expr thing = orig_model.get_const_interp(cnst); + mod.register_decl(to_func_decl(cnst.raw()), to_expr(thing.raw())); } } for(unsigned i = 0; i < orig_model.num_funcs(); i++){ func_decl cnst = orig_model.get_func_decl(i); - if(locals.find(cnst) == locals.end()){ - func_interp thing = orig_model.get_func_interp(cnst); - ::func_interp *thing_raw = thing; - mod.register_decl(to_func_decl(cnst.raw()),thing_raw->copy()); + if (locals.find(cnst) == locals.end()) { + func_interp thing = orig_model.get_func_interp(cnst); + ::func_interp *thing_raw = thing; + mod.register_decl(to_func_decl(cnst.raw()), thing_raw->copy()); } } model_v2_pp(out,mod); diff --git a/src/muz/transforms/dl_transforms.cpp b/src/muz/transforms/dl_transforms.cpp index 9a4667f2c..08404b6e5 100644 --- a/src/muz/transforms/dl_transforms.cpp +++ b/src/muz/transforms/dl_transforms.cpp @@ -72,7 +72,7 @@ namespace datalog { transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000)); if (!ctx.get_params().quantify_arrays()) - transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); + transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010)); if (ctx.get_params().magic()) { transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020)); diff --git a/src/tactic/aig/aig.cpp b/src/tactic/aig/aig.cpp index 9fdce96e9..991c4714b 100644 --- a/src/tactic/aig/aig.cpp +++ b/src/tactic/aig/aig.cpp @@ -27,7 +27,7 @@ Notes: struct aig; class aig_lit { - friend class aig_ref; + friend class aig_ref; aig * m_ref; public: aig_lit(aig * n = 0):m_ref(n) {} @@ -1508,10 +1508,10 @@ public: template aig_lit mk_aig(S const & s) { aig_lit r; - r = m_true; - inc_ref(r); + r = m_true; + inc_ref(r); try { - expr2aig proc(*this); + expr2aig proc(*this); unsigned sz = s.size(); for (unsigned i = 0; i < sz; i++) { SASSERT(ref_count(r) >= 1); @@ -1528,9 +1528,9 @@ public: } SASSERT(ref_count(r) >= 1); } - catch (aig_exception ex) { - dec_ref(r); - throw ex; + catch (aig_exception ex) { + dec_ref(r); + throw ex; } dec_ref_result(r); return r; From 71912830f13f991261220a427fcf06382bb62bfd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 8 Jan 2015 17:54:44 +0000 Subject: [PATCH 163/646] Formatting, mostly tabs Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast.cpp | 2 +- src/ast/ast_smt_pp.cpp | 2 +- src/ast/bv_decl_plugin.cpp | 14 ++++++------- src/ast/datatype_decl_plugin.cpp | 8 ++++---- src/ast/simplifier/distribute_forall.cpp | 2 +- src/cmd_context/basic_cmds.cpp | 2 +- src/muz/base/dl_boogie_proof.cpp | 2 +- src/muz/base/dl_context.cpp | 26 ++++++++++++------------ src/muz/fp/dl_cmds.cpp | 12 +++++------ src/muz/transforms/dl_mk_bit_blast.cpp | 2 +- src/tactic/aig/aig.cpp | 2 +- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 5679c951b..b134d38cb 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -2848,7 +2848,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro SASSERT(is_or(f1)); app * cls = to_app(f1); unsigned cls_sz = cls->get_num_args(); - CTRACE("cunit_bug", !(num_proofs == cls_sz || (num_proofs == cls_sz + 1 && is_false(new_fact))), + CTRACE("cunit_bug", !(num_proofs == cls_sz || (num_proofs == cls_sz + 1 && is_false(new_fact))), for (unsigned i = 0; i < num_proofs; i++) tout << mk_pp(get_fact(proofs[i]), *this) << "\n"; tout << "===>\n"; tout << mk_pp(new_fact, *this) << "\n";); diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 59e5c04b9..b28b640bb 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -1003,7 +1003,7 @@ public: visit_sort(d->get_domain(i), true); } m_out << ")"; - } + } }; diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index f1c61619a..b056ded36 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -136,7 +136,7 @@ void bv_decl_plugin::finalize() { for (; it != end; ++it) { ptr_vector & ds = *it; DEC_REF(ds); - } + } DEC_REF(m_mkbv); } @@ -157,13 +157,13 @@ void bv_decl_plugin::mk_bv_sort(unsigned bv_size) { } inline sort * bv_decl_plugin::get_bv_sort(unsigned bv_size) { - if (bv_size < (1 << 12)) { - mk_bv_sort(bv_size); + if (bv_size < (1 << 12)) { + mk_bv_sort(bv_size); return m_bv_sorts[bv_size]; - } - parameter p(bv_size); - sort_size sz(sort_size::mk_very_big()); - return m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p)); + } + parameter p(bv_size); + sort_size sz(sort_size::mk_very_big()); + return m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p)); } sort * bv_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) { diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index ee3271b9b..00f026f55 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -919,9 +919,9 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) { todo.push_back(s0); mark.mark(s0, true); while (!todo.empty()) { - sort* s = todo.back(); + sort* s = todo.back(); todo.pop_back(); - strm << s->get_name() << " =\n"; + strm << s->get_name() << " =\n"; ptr_vector const * cnstrs = get_datatype_constructors(s); for (unsigned i = 0; i < cnstrs->size(); ++i) { @@ -931,14 +931,14 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) { ptr_vector const * accs = get_constructor_accessors(cns); for (unsigned j = 0; j < accs->size(); ++j) { func_decl* acc = (*accs)[j]; - sort* s1 = acc->get_range(); + sort* s1 = acc->get_range(); strm << "(" << acc->get_name() << ": " << s1->get_name() << ") "; if (is_datatype(s1) && are_siblings(s1, s0) && !mark.is_marked(s1)) { mark.mark(s1, true); todo.push_back(s1); } } - strm << "\n"; + strm << "\n"; } } diff --git a/src/ast/simplifier/distribute_forall.cpp b/src/ast/simplifier/distribute_forall.cpp index 5e2958579..bd2af5675 100644 --- a/src/ast/simplifier/distribute_forall.cpp +++ b/src/ast/simplifier/distribute_forall.cpp @@ -148,7 +148,7 @@ void distribute_forall::operator()(expr * f, expr_ref & result) { while (!m_todo.empty()) { expr * e = m_todo.back(); - if (visit_children(e)) { + if (visit_children(e)) { m_todo.pop_back(); reduce1(e); } diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index a80c5bc6c..94bd4f5e1 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -255,7 +255,7 @@ protected: s == m_print_success || s == m_print_warning || s == m_expand_definitions || s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores || s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants || - s == m_regular_output_channel || s == m_diagnostic_output_channel || + s == m_regular_output_channel || s == m_diagnostic_output_channel || s == m_random_seed || s == m_verbosity || s == m_global_decls; } diff --git a/src/muz/base/dl_boogie_proof.cpp b/src/muz/base/dl_boogie_proof.cpp index d11e4a932..42d21dfb9 100644 --- a/src/muz/base/dl_boogie_proof.cpp +++ b/src/muz/base/dl_boogie_proof.cpp @@ -142,7 +142,7 @@ namespace datalog { steps.push_back(step()); obj_map index; index.insert(m_proof, 0); - + for (unsigned j = 0; j < rules.size(); ++j) { proof* p = rules[j]; proof_ref_vector premises(m); diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 2129a1810..7c9c5813b 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -963,12 +963,12 @@ namespace datalog { // TODO: what? if(get_engine() != DUALITY_ENGINE) { new_query(); - rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end(); - rule_ref r(m_rule_manager); - for (; it != end; ++it) { + rule_set::iterator it = m_rule_set.begin(), end = m_rule_set.end(); + rule_ref r(m_rule_manager); + for (; it != end; ++it) { r = *it; check_rule(r); - } + } } #endif m_mc = mk_skip_model_converter(); @@ -985,10 +985,10 @@ namespace datalog { flush_add_rules(); break; case DUALITY_ENGINE: - // this lets us use duality with SAS 2013 abstraction - if(quantify_arrays()) - flush_add_rules(); - break; + // this lets us use duality with SAS 2013 abstraction + if(quantify_arrays()) + flush_add_rules(); + break; default: UNREACHABLE(); } @@ -1109,11 +1109,11 @@ namespace datalog { void context::get_raw_rule_formulas(expr_ref_vector& rules, svector& names, vector &bounds){ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) { - expr_ref r = bind_variables(m_rule_fmls[i].get(), true); - rules.push_back(r.get()); - // rules.push_back(m_rule_fmls[i].get()); - names.push_back(m_rule_names[i]); - bounds.push_back(m_rule_bounds[i]); + expr_ref r = bind_variables(m_rule_fmls[i].get(), true); + rules.push_back(r.get()); + // rules.push_back(m_rule_fmls[i].get()); + names.push_back(m_rule_names[i]); + bounds.push_back(m_rule_bounds[i]); } } diff --git a/src/muz/fp/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp index e2e3680cc..a0af94953 100644 --- a/src/muz/fp/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -110,7 +110,7 @@ struct dl_context { m_trail.push(push_back_vector >(m_collected_cmds->m_names)); } else { - m_context->add_rule(rule, name, bound); + m_context->add_rule(rule, name, bound); } } @@ -260,11 +260,11 @@ public: print_certificate(ctx); break; case l_undef: - if(dlctx.get_status() == datalog::BOUNDED){ - ctx.regular_stream() << "bounded\n"; - print_certificate(ctx); - break; - } + if(dlctx.get_status() == datalog::BOUNDED){ + ctx.regular_stream() << "bounded\n"; + print_certificate(ctx); + break; + } ctx.regular_stream() << "unknown\n"; switch(dlctx.get_status()) { case datalog::INPUT_ERROR: diff --git a/src/muz/transforms/dl_mk_bit_blast.cpp b/src/muz/transforms/dl_mk_bit_blast.cpp index fd1dbb205..9b451811c 100644 --- a/src/muz/transforms/dl_mk_bit_blast.cpp +++ b/src/muz/transforms/dl_mk_bit_blast.cpp @@ -219,7 +219,7 @@ namespace datalog { class mk_bit_blast::impl { - context & m_context; + context & m_context; ast_manager & m; params_ref m_params; mk_interp_tail_simplifier m_simplifier; diff --git a/src/tactic/aig/aig.cpp b/src/tactic/aig/aig.cpp index 991c4714b..e3101ad67 100644 --- a/src/tactic/aig/aig.cpp +++ b/src/tactic/aig/aig.cpp @@ -1531,7 +1531,7 @@ public: catch (aig_exception ex) { dec_ref(r); throw ex; - } + } dec_ref_result(r); return r; } From 46e236487be2fa172a021afce577f133e09acd06 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 9 Jan 2015 11:53:18 +0000 Subject: [PATCH 164/646] Eliminated FPRMNum classes Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 86 +++++++++++++++++----------------- src/api/dotnet/Expr.cs | 24 +++++----- src/api/dotnet/FPRMExpr.cs | 50 ++++++++++++++++++++ src/api/dotnet/FPRMNum.cs | 96 -------------------------------------- src/api/java/Context.java | 40 ++++++++-------- src/api/java/Expr.java | 2 - 6 files changed, 125 insertions(+), 173 deletions(-) delete mode 100644 src/api/dotnet/FPRMNum.cs diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 9eb544f8a..89a89b959 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3456,91 +3456,91 @@ namespace Microsoft.Z3 /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// - public FPRMNum MkFPRoundNearestTiesToEven() + public FPRMExpr MkFPRoundNearestTiesToEven() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// - public FPRMNum MkFPRNE() + public FPRMExpr MkFPRNE() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_rne(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_rne(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// - public FPRMNum MkFPRoundNearestTiesToAway() + public FPRMExpr MkFPRoundNearestTiesToAway() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// - public FPRMNum MkFPRNA() + public FPRMExpr MkFPRNA() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_rna(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_rna(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// - public FPRMNum MkFPRoundTowardPositive() + public FPRMExpr MkFPRoundTowardPositive() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// - public FPRMNum MkFPRTP() + public FPRMExpr MkFPRTP() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_rtp(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_rtp(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// - public FPRMNum MkFPRoundTowardNegative() + public FPRMExpr MkFPRoundTowardNegative() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// - public FPRMNum MkFPRTN() + public FPRMExpr MkFPRTN() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_rtn(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_rtn(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// - public FPRMNum MkFPRoundTowardZero() + public FPRMExpr MkFPRoundTowardZero() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// - public FPRMNum MkFPRTZ() + public FPRMExpr MkFPRTZ() { - Contract.Ensures(Contract.Result() != null); - return new FPRMNum(this, Native.Z3_mk_fpa_rtz(nCtx)); + Contract.Ensures(Contract.Result() != null); + return new FPRMExpr(this, Native.Z3_mk_fpa_rtz(nCtx)); } #endregion #endregion @@ -3637,7 +3637,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNaN(FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_nan(nCtx, s.NativeObject)); } @@ -3648,7 +3648,7 @@ namespace Microsoft.Z3 /// indicates whether the result should be negative. public FPNum MkFPInf(FPSort s, bool negative) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_inf(nCtx, s.NativeObject, negative ? 1 : 0)); } @@ -3659,7 +3659,7 @@ namespace Microsoft.Z3 /// indicates whether the result should be negative. public FPNum MkFPZero(FPSort s, bool negative) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, negative ? 1 : 0)); } @@ -3670,7 +3670,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNumeral(float v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_numeral_float(nCtx, v, s.NativeObject)); } @@ -3681,7 +3681,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNumeral(double v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_numeral_double(nCtx, v, s.NativeObject)); } @@ -3692,7 +3692,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNumeral(int v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_numeral_int(nCtx, v, s.NativeObject)); } @@ -3705,7 +3705,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_numeral_uint_int(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); } @@ -3718,7 +3718,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFPNumeral(bool sgn, UInt64 sig, Int64 exp, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return new FPNum(this, Native.Z3_mk_fpa_numeral_uint64_int64(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); } @@ -3729,7 +3729,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFP(float v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return MkFPNumeral(v, s); } @@ -3740,7 +3740,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFP(double v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return MkFPNumeral(v, s); } @@ -3751,7 +3751,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFP(int v, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return MkFPNumeral(v, s); } @@ -3764,7 +3764,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFP(bool sgn, uint sig, int exp, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return MkFPNumeral(sgn, sig, exp, s); } @@ -3777,7 +3777,7 @@ namespace Microsoft.Z3 /// FloatingPoint sort. public FPNum MkFP(bool sgn, UInt64 sig, Int64 exp, FPSort s) { - Contract.Ensures(Contract.Result() != null); + Contract.Ensures(Contract.Result() != null); return MkFPNumeral(sgn, sig, exp, s); } diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index 97e57b920..eb1d1c02d 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1475,57 +1475,57 @@ namespace Microsoft.Z3 /// /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven /// - public bool IsFPRMNumRoundNearestTiesToEven{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + public bool IsFPRMRoundNearestTiesToEven{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } /// /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway /// - public bool IsFPRMNumRoundNearestTiesToAway{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + public bool IsFPRMRoundNearestTiesToAway{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative /// - public bool IsFPRMNumRoundTowardNegative{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + public bool IsFPRMRoundTowardNegative{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive /// - public bool IsFPRMNumRoundTowardPositive{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + public bool IsFPRMRoundTowardPositive{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardZero /// - public bool IsFPRMNumRoundTowardZero{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + public bool IsFPRMRoundTowardZero{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } /// /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven /// - public bool IsFPRMNumRNE{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + public bool IsFPRMExprRNE{ get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } /// /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway /// - public bool IsFPRMNumRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + public bool IsFPRMExprRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative /// - public bool IsFPRMNumRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + public bool IsFPRMExprRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive /// - public bool IsFPRMNumRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + public bool IsFPRMExprRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } /// /// Indicates whether the term is the floating-point rounding numeral roundTowardZero /// - public bool IsFPRMNumRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + public bool IsFPRMExprRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } /// /// Indicates whether the term is a floating-point rounding mode numeral /// - public bool IsFPRMNum { + public bool IsFPRMExpr { get { return IsApp && (FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY|| @@ -1809,7 +1809,7 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_REAL_SORT: return new RatNum(ctx, obj); case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj); case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); - case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj); + case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); } } diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs index 896c3e6b9..47ea3e670 100644 --- a/src/api/dotnet/FPRMExpr.cs +++ b/src/api/dotnet/FPRMExpr.cs @@ -30,6 +30,56 @@ namespace Microsoft.Z3 /// public class FPRMExpr : Expr { + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + #region Internal /// Constructor for FPRMExpr internal FPRMExpr(Context ctx, IntPtr obj) diff --git a/src/api/dotnet/FPRMNum.cs b/src/api/dotnet/FPRMNum.cs deleted file mode 100644 index 628480d96..000000000 --- a/src/api/dotnet/FPRMNum.cs +++ /dev/null @@ -1,96 +0,0 @@ -/*++ -Copyright (c) 2013 Microsoft Corporation - -Module Name: - - FPRMNum.cs - -Abstract: - - Z3 Managed API: Floating Point Rounding Mode Numerals - -Author: - - Christoph Wintersteiger (cwinter) 2013-06-10 - -Notes: - ---*/ -using System; -using System.Diagnostics.Contracts; - -namespace Microsoft.Z3 -{ - /// - /// FloatingPoint RoundingMode Numerals - /// - [ContractVerification(true)] - public class FPRMNum : FPRMExpr - { - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven - /// - public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven - /// - public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway - /// - public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway - /// - public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive - /// - public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive - /// - public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative - /// - public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative - /// - public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardZero - /// - public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardZero - /// - public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } - - #region Internal - internal FPRMNum(Context ctx, IntPtr obj) - : base(ctx, obj) - { - Contract.Requires(ctx != null); - } - #endregion - - /// - /// Returns a string representation of the numeral. - /// - public override string ToString() - { - return Native.Z3_get_numeral_string(Context.nCtx, NativeObject); - } - } -} diff --git a/src/api/java/Context.java b/src/api/java/Context.java index cfbd7c2c8..29be4aae8 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -2865,90 +2865,90 @@ public class Context extends IDisposable * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. * @throws Z3Exception on error **/ - public FPRMNum mkFPRoundNearestTiesToEven() throws Z3Exception + public FPRMExpr mkFPRoundNearestTiesToEven() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); + return new FPRMExpr(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRNE() throws Z3Exception + public FPRMExpr mkFPRNE() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRne(nCtx())); + return new FPRMExpr(this, Native.mkFpaRne(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRoundNearestTiesToAway() throws Z3Exception + public FPRMExpr mkFPRoundNearestTiesToAway() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); + return new FPRMExpr(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRNA() throws Z3Exception + public FPRMExpr mkFPRNA() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRna(nCtx())); + return new FPRMExpr(this, Native.mkFpaRna(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRoundTowardPositive() throws Z3Exception + public FPRMExpr mkFPRoundTowardPositive() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRoundTowardPositive(nCtx())); + return new FPRMExpr(this, Native.mkFpaRoundTowardPositive(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRTP() throws Z3Exception + public FPRMExpr mkFPRTP() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRtp(nCtx())); + return new FPRMExpr(this, Native.mkFpaRtp(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRoundTowardNegative() throws Z3Exception + public FPRMExpr mkFPRoundTowardNegative() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRoundTowardNegative(nCtx())); + return new FPRMExpr(this, Native.mkFpaRoundTowardNegative(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRTN() throws Z3Exception + public FPRMExpr mkFPRTN() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRtn(nCtx())); + return new FPRMExpr(this, Native.mkFpaRtn(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRoundTowardZero() throws Z3Exception + public FPRMExpr mkFPRoundTowardZero() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRoundTowardZero(nCtx())); + return new FPRMExpr(this, Native.mkFpaRoundTowardZero(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. * @throws Z3Exception **/ - public FPRMNum mkFPRTZ() throws Z3Exception + public FPRMExpr mkFPRTZ() throws Z3Exception { - return new FPRMNum(this, Native.mkFpaRtz(nCtx())); + return new FPRMExpr(this, Native.mkFpaRtz(nCtx())); } /** FloatingPoint Sorts **/ diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 886c69f08..49f49a295 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -2140,8 +2140,6 @@ public class Expr extends AST return new BitVecNum(ctx, obj); case Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); - case Z3_ROUNDING_MODE_SORT: - return new FPRMNum(ctx, obj); default: ; } } From 3391c9c44c40057eba47d92cc7deceb782de35d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 9 Jan 2015 11:53:24 +0000 Subject: [PATCH 165/646] typo fix Signed-off-by: Christoph M. Wintersteiger --- src/duality/duality_rpfp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index 6ef6d623a..764fc72ad 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -2478,7 +2478,7 @@ done: expr junct = negate ? Negate(f) : f; lits.push_back(junct); } - }| + } struct TermLt { bool operator()(const expr &x, const expr &y){ From ee0ec7fe3a05e569bcc3906d7721af08d621db46 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 10 Jan 2015 17:28:07 +0000 Subject: [PATCH 166/646] FPA API: numerals, .NET and Java Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 89 +++++++++++++++++++++++++++++- src/api/api_numeral.cpp | 83 +++++++++++++++++----------- src/api/dotnet/Context.cs | 36 ++++++------ src/api/dotnet/Expr.cs | 9 ++- src/api/dotnet/FPNum.cs | 57 +++++++++++++++++++ src/api/dotnet/FPRMExpr.cs | 50 ----------------- src/api/dotnet/FPRMNum.cs | 100 +++++++++++++++++++++++++++++++++ src/api/java/Context.java | 40 +++++++------- src/api/java/Expr.java | 110 ++++++++++++++++++++----------------- src/api/java/FPExpr.java | 41 ++++++++++++++ src/api/java/FPNum.java | 86 +++++++++++++++++++++++++++++ src/api/java/FPRMExpr.java | 29 ++++++++++ src/api/java/FPRMNum.java | 90 ++++++++++++++++++++++++++++++ src/api/java/FPRMSort.java | 35 ++++++++++++ src/api/java/FPSort.java | 49 +++++++++++++++++ src/api/z3_fpa.h | 41 ++++++++++++++ 16 files changed, 770 insertions(+), 175 deletions(-) create mode 100644 src/api/dotnet/FPRMNum.cs create mode 100644 src/api/java/FPExpr.java create mode 100644 src/api/java/FPNum.java create mode 100644 src/api/java/FPRMExpr.java create mode 100644 src/api/java/FPRMNum.java create mode 100644 src/api/java/FPRMSort.java create mode 100644 src/api/java/FPSort.java diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 94dfaaa68..219f9b166 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -200,7 +200,8 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_ninf(to_sort(s)) : ctx->fpa_util().mk_pinf(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_ninf(to_sort(s)) : + ctx->fpa_util().mk_pinf(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -210,7 +211,8 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_nzero(to_sort(s)) : ctx->fpa_util().mk_pzero(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_nzero(to_sort(s)) : + ctx->fpa_util().mk_pzero(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -231,7 +233,10 @@ extern "C" { RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, ctx->fpa_util().get_ebits(to_sort(ty)), ctx->fpa_util().get_sbits(to_sort(ty)), v); + ctx->fpa_util().fm().set(tmp, + ctx->fpa_util().get_ebits(to_sort(ty)), + ctx->fpa_util().get_sbits(to_sort(ty)), + v); Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); @@ -667,6 +672,84 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_bool Z3_API Z3_fpa_get_numeral_sign(Z3_context c, Z3_ast t, int * sgn) { + Z3_TRY; + LOG_Z3_fpa_get_numeral_sign(c, t, sgn); + RESET_ERROR_CODE(); + ast_manager & m = mk_c(c)->m(); + mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); + scoped_mpf val(mpfm); + bool r = plugin->is_numeral(to_expr(t), val); + *sgn = (mpfm.is_nan(val)) ? 0 : mpfm.sgn(val); + return r; + Z3_CATCH_RETURN(0); + } + + Z3_string Z3_API Z3_fpa_get_numeral_significand_string(__in Z3_context c, __in Z3_ast t) { + Z3_TRY; + LOG_Z3_fpa_get_numeral_significand_string(c, t); + RESET_ERROR_CODE(); + ast_manager & m = mk_c(c)->m(); + mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); + scoped_mpf val(mpfm); + if (!plugin->is_numeral(to_expr(t), val)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return ""; + } + unsigned sbits = val.get().get_sbits(); + scoped_mpq q(mpqm); + mpqm.set(q, mpfm.sig(val)); + mpqm.div(q, mpfm.m_powers2(sbits - 1), q); + std::stringstream ss; + mpqm.display_decimal(ss, q, sbits); + return mk_c(c)->mk_external_string(ss.str()); + Z3_CATCH_RETURN(""); + + } + + Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(__in Z3_context c, __in Z3_ast t) { + Z3_TRY; + LOG_Z3_fpa_get_numeral_exponent_string(c, t); + RESET_ERROR_CODE(); + ast_manager & m = mk_c(c)->m(); + mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); + scoped_mpf val(mpfm); + bool r = plugin->is_numeral(to_expr(t), val); + if (!r) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return ""; + } + const mpf_exp_t exp = mpfm.exp(val); + std::stringstream ss; + ss << exp; + return mk_c(c)->mk_external_string(ss.str()); + Z3_CATCH_RETURN(""); + } + + Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(__in Z3_context c, __in Z3_ast t, __out __int64 * n) { + Z3_TRY; + LOG_Z3_fpa_get_numeral_exponent_string(c, t); + RESET_ERROR_CODE(); + ast_manager & m = mk_c(c)->m(); + mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); + scoped_mpf val(mpfm); + bool r = plugin->is_numeral(to_expr(t), val); + if (!r) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + *n = mpfm.exp(val); + return 1; + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_fpa_to_ieee_bv(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_to_ieee_bv(c, t); diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 0745a8709..d5a25dfc2 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -50,7 +50,7 @@ extern "C" { 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(); + RESET_ERROR_CODE(); if (!check_numeral_sort(c, ty)) { RETURN_Z3(0); } @@ -64,20 +64,19 @@ extern "C" { char const* m = n; while (*m) { if (!(('0' <= *m && *m <= '9') || - ('/' == *m) || ('-' == *m) || - (' ' == *m) || ('\n' == *m) || - ('.' == *m) || ('e' == *m) || - ('E' == *m) || - (('p' == *m) && is_float) || - (('P' == *m)) && is_float)) { + ('/' == *m) || ('-' == *m) || + (' ' == *m) || ('\n' == *m) || + ('.' == *m) || ('e' == *m) || + ('E' == *m) || + (('p' == *m) && is_float) || + (('P' == *m)) && is_float)) { SET_ERROR_CODE(Z3_PARSER_ERROR); return 0; } ++m; } - ast * a = 0; - if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) - { + ast * a = 0; + if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) { // avoid expanding floats into huge rationals. fpa_util & fu = mk_c(c)->fpa_util(); scoped_mpf t(fu.fm()); @@ -90,23 +89,11 @@ extern "C" { 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(); + RESET_ERROR_CODE(); if (!check_numeral_sort(c, ty)) { RETURN_Z3(0); } @@ -114,11 +101,23 @@ extern "C" { 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(); + RESET_ERROR_CODE(); if (!check_numeral_sort(c, ty)) { RETURN_Z3(0); } @@ -127,11 +126,11 @@ extern "C" { 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(); + RESET_ERROR_CODE(); if (!check_numeral_sort(c, ty)) { RETURN_Z3(0); } @@ -146,10 +145,11 @@ extern "C" { LOG_Z3_is_numeral_ast(c, a); RESET_ERROR_CODE(); expr* e = to_expr(a); - return + return mk_c(c)->autil().is_numeral(e) || mk_c(c)->bvutil().is_numeral(e) || - mk_c(c)->fpa_util().is_numeral(e); + mk_c(c)->fpa_util().is_numeral(e) || + mk_c(c)->fpa_util().is_rm_numeral(e); Z3_CATCH_RETURN(Z3_FALSE); } @@ -193,7 +193,28 @@ extern "C" { // floats are separated from all others to avoid huge rationals. fpa_util & fu = mk_c(c)->fpa_util(); scoped_mpf tmp(fu.fm()); - if (mk_c(c)->fpa_util().is_numeral(to_expr(a), tmp)) { + mpf_rounding_mode rm; + if (mk_c(c)->fpa_util().is_rm_numeral(to_expr(a), rm)) { + switch (rm) { + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + return mk_c(c)->mk_external_string("roundNearestTiesToEven"); + break; + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + return mk_c(c)->mk_external_string("roundNearestTiesToAway"); + break; + case OP_FPA_RM_TOWARD_POSITIVE: + return mk_c(c)->mk_external_string("roundTowardPositive"); + break; + case OP_FPA_RM_TOWARD_NEGATIVE: + return mk_c(c)->mk_external_string("roundTowardNegative"); + break; + case OP_FPA_RM_TOWARD_ZERO: + default: + return mk_c(c)->mk_external_string("roundTowardZero"); + break; + } + } + else if (mk_c(c)->fpa_util().is_numeral(to_expr(a), tmp)) { return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); } else { diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 89a89b959..70777a6e8 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3465,82 +3465,82 @@ namespace Microsoft.Z3 /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// - public FPRMExpr MkFPRNE() + public FPRMNum MkFPRNE() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_rne(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_rne(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// - public FPRMExpr MkFPRoundNearestTiesToAway() + public FPRMNum MkFPRoundNearestTiesToAway() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// - public FPRMExpr MkFPRNA() + public FPRMNum MkFPRNA() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_rna(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_rna(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// - public FPRMExpr MkFPRoundTowardPositive() + public FPRMNum MkFPRoundTowardPositive() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// - public FPRMExpr MkFPRTP() + public FPRMNum MkFPRTP() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_rtp(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_rtp(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// - public FPRMExpr MkFPRoundTowardNegative() + public FPRMNum MkFPRoundTowardNegative() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// - public FPRMExpr MkFPRTN() + public FPRMNum MkFPRTN() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_rtn(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_rtn(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// - public FPRMExpr MkFPRoundTowardZero() + public FPRMNum MkFPRoundTowardZero() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// - public FPRMExpr MkFPRTZ() + public FPRMNum MkFPRTZ() { Contract.Ensures(Contract.Result() != null); - return new FPRMExpr(this, Native.Z3_mk_fpa_rtz(nCtx)); + return new FPRMNum(this, Native.Z3_mk_fpa_rtz(nCtx)); } #endregion #endregion diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index eb1d1c02d..e3ff27da1 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1470,7 +1470,12 @@ namespace Microsoft.Z3 /// /// Indicates whether the term is a floating-point numeral /// - public bool IsFPNumeral { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_NUM; } } + public bool IsFPNumeral { get { return IsFP && IsNumeral; } } + + /// + /// Indicates whether the term is a floating-point rounding mode numeral + /// + public bool IsFPRMNumeral { get { return IsFPRM && IsNumeral; } } /// /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven @@ -1809,7 +1814,7 @@ namespace Microsoft.Z3 case Z3_sort_kind.Z3_REAL_SORT: return new RatNum(ctx, obj); case Z3_sort_kind.Z3_BV_SORT: return new BitVecNum(ctx, obj); case Z3_sort_kind.Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); - case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMExpr(ctx, obj); + case Z3_sort_kind.Z3_ROUNDING_MODE_SORT: return new FPRMNum(ctx, obj); } } diff --git a/src/api/dotnet/FPNum.cs b/src/api/dotnet/FPNum.cs index 14c089198..e85687ccf 100644 --- a/src/api/dotnet/FPNum.cs +++ b/src/api/dotnet/FPNum.cs @@ -27,6 +27,63 @@ namespace Microsoft.Z3 [ContractVerification(true)] public class FPNum : FPExpr { + /// + /// Retrieves the sign of a floating-point literal + /// + /// + /// Remarks: returns true if the numeral is negative + /// + public bool Sign + { + get + { + int res = 0; + if (Native.Z3_fpa_get_numeral_sign(Context.nCtx, NativeObject, ref res) == 0) + throw new Z3Exception("Sign is not a Boolean value"); + return res != 0; + } + } + + /// + /// The significand value of a floating-point numeral as a string + /// + /// + /// The significand s is always 0 < s < 2.0; the resulting string is long + /// enough to represent the real significand precisely. + /// + public string Significand + { + get + { + return Native.Z3_fpa_get_numeral_significand_string(Context.nCtx, NativeObject); + } + } + + /// + /// Return the exponent value of a floating-point numeral as a string + /// + public string Exponent + { + get + { + return Native.Z3_fpa_get_numeral_exponent_string(Context.nCtx, NativeObject); + } + } + + /// + /// Return the exponent value of a floating-point numeral as a signed 64-bit integer + /// + public Int64 ExponentInt64 + { + get + { + Int64 result = 0; + if (Native.Z3_fpa_get_numeral_exponent_int64(Context.nCtx, NativeObject, ref result) == 0) + throw new Z3Exception("Exponent is not a 64 bit integer"); + return result; + } + } + #region Internal internal FPNum(Context ctx, IntPtr obj) : base(ctx, obj) diff --git a/src/api/dotnet/FPRMExpr.cs b/src/api/dotnet/FPRMExpr.cs index 47ea3e670..896c3e6b9 100644 --- a/src/api/dotnet/FPRMExpr.cs +++ b/src/api/dotnet/FPRMExpr.cs @@ -30,56 +30,6 @@ namespace Microsoft.Z3 /// public class FPRMExpr : Expr { - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven - /// - public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven - /// - public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway - /// - public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway - /// - public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive - /// - public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive - /// - public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative - /// - public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative - /// - public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardZero - /// - public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } - - /// - /// Indicates whether the term is the floating-point rounding numeral roundTowardZero - /// - public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } - #region Internal /// Constructor for FPRMExpr internal FPRMExpr(Context ctx, IntPtr obj) diff --git a/src/api/dotnet/FPRMNum.cs b/src/api/dotnet/FPRMNum.cs new file mode 100644 index 000000000..81cff167e --- /dev/null +++ b/src/api/dotnet/FPRMNum.cs @@ -0,0 +1,100 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMExpr.cs + +Abstract: + + Z3 Managed API: Floating Point Rounding Mode Numerals + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using System.Diagnostics.Contracts; + +namespace Microsoft.Z3 +{ + /// + /// Floating-point rounding mode numerals + /// + public class FPRMNum : FPRMExpr + { + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRoundNearestTiesToEven { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + /// + public bool isRNE { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRoundNearestTiesToAway { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + /// + public bool isRNA { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRoundTowardPositive { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardPositive + /// + public bool isRTP { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRoundTowardNegative { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardNegative + /// + public bool isRTN { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRoundTowardZero { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Indicates whether the term is the floating-point rounding numeral roundTowardZero + /// + public bool isRTZ { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } } + + /// + /// Returns a string representation of the numeral. + /// + public override string ToString() + { + return Native.Z3_get_numeral_string(Context.nCtx, NativeObject); + } + + #region Internal + /// Constructor for FPRMNum + internal FPRMNum(Context ctx, IntPtr obj) + : base(ctx, obj) + { + Contract.Requires(ctx != null); + } + #endregion + } +} diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 29be4aae8..cfbd7c2c8 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -2865,90 +2865,90 @@ public class Context extends IDisposable * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. * @throws Z3Exception on error **/ - public FPRMExpr mkFPRoundNearestTiesToEven() throws Z3Exception + public FPRMNum mkFPRoundNearestTiesToEven() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); + return new FPRMNum(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRNE() throws Z3Exception + public FPRMNum mkFPRNE() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRne(nCtx())); + return new FPRMNum(this, Native.mkFpaRne(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRoundNearestTiesToAway() throws Z3Exception + public FPRMNum mkFPRoundNearestTiesToAway() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); + return new FPRMNum(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRNA() throws Z3Exception + public FPRMNum mkFPRNA() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRna(nCtx())); + return new FPRMNum(this, Native.mkFpaRna(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRoundTowardPositive() throws Z3Exception + public FPRMNum mkFPRoundTowardPositive() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRoundTowardPositive(nCtx())); + return new FPRMNum(this, Native.mkFpaRoundTowardPositive(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRTP() throws Z3Exception + public FPRMNum mkFPRTP() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRtp(nCtx())); + return new FPRMNum(this, Native.mkFpaRtp(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRoundTowardNegative() throws Z3Exception + public FPRMNum mkFPRoundTowardNegative() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRoundTowardNegative(nCtx())); + return new FPRMNum(this, Native.mkFpaRoundTowardNegative(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRTN() throws Z3Exception + public FPRMNum mkFPRTN() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRtn(nCtx())); + return new FPRMNum(this, Native.mkFpaRtn(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRoundTowardZero() throws Z3Exception + public FPRMNum mkFPRoundTowardZero() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRoundTowardZero(nCtx())); + return new FPRMNum(this, Native.mkFpaRoundTowardZero(nCtx())); } /** * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. * @throws Z3Exception **/ - public FPRMExpr mkFPRTZ() throws Z3Exception + public FPRMNum mkFPRTZ() throws Z3Exception { - return new FPRMExpr(this, Native.mkFpaRtz(nCtx())); + return new FPRMNum(this, Native.mkFpaRtz(nCtx())); } /** FloatingPoint Sorts **/ diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 49f49a295..57f53ec6b 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -1714,98 +1714,105 @@ public class Expr extends AST * Indicates whether the terms is of floating-point sort. * @throws Z3Exception */ - public boolean IsFP() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_FLOATING_POINT_SORT; } + public boolean isFP() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_FLOATING_POINT_SORT; } /** * Indicates whether the terms is of floating-point rounding mode sort. * @return * @throws Z3Exception */ - public boolean IsFPRM() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_ROUNDING_MODE_SORT; } + public boolean isFPRM() throws Z3Exception { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), Native.getSort(getContext().nCtx(), getNativeObject()))) == Z3_sort_kind.Z3_ROUNDING_MODE_SORT; } /** * Indicates whether the term is a floating-point numeral * @return * @throws Z3Exception */ - public boolean IsFPNumeral() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NUM; } + public boolean isFPNumeral() throws Z3Exception { return isFP() && isNumeral(); } + + /** + * Indicates whether the term is a floating-point rounding mode numeral + * @return + * @throws Z3Exception + */ + public boolean isFPRMNumeral() throws Z3Exception { return isFPRM() && isNumeral(); } /** * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven * @return * @throws Z3Exception */ - public boolean IsFPRMNumRoundNearestTiesToEven() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + public boolean isFPRMNumRoundNearestTiesToEven() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } /** * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway * @return * @throws Z3Exception */ - public boolean IsFPRMNumRoundNearestTiesToAway() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + public boolean isFPRMNumRoundNearestTiesToAway() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardNegative * @return * @throws Z3Exception */ - public boolean IsFPRMNumRoundTowardNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + public boolean isFPRMNumRoundTowardNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardPositive * @return * @throws Z3Exception */ - public boolean IsFPRMNumRoundTowardPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + public boolean isFPRMNumRoundTowardPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardZero * @return * @throws Z3Exception */ - public boolean IsFPRMNumRoundTowardZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + public boolean isFPRMNumRoundTowardZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } /** * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven * @return * @throws Z3Exception */ - public boolean IsFPRMNumRNE() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + public boolean isFPRMNumRNE() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } /** * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway * @return * @throws Z3Exception */ - public boolean IsFPRMNumRNA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + public boolean isFPRMNumRNA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardNegative * @return * @throws Z3Exception */ - public boolean IsFPRMNumRTN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + public boolean isFPRMNumRTN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardPositive * @return * @throws Z3Exception */ - public boolean IsFPRMNumRTP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + public boolean isFPRMNumRTP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } /** * Indicates whether the term is the floating-point rounding numeral roundTowardZero * @return * @throws Z3Exception */ - public boolean IsFPRMNumRTZ() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + public boolean isFPRMNumRTZ() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } /** * Indicates whether the term is a floating-point rounding mode numeral * @return * @throws Z3Exception */ - public boolean IsFPRMNum() throws Z3Exception { + public boolean isFPRMNum() throws Z3Exception { return isApp() && (getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY || getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN || @@ -1819,42 +1826,42 @@ public class Expr extends AST * @return * @throws Z3Exception */ - public boolean IsFPPlusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_INF; } + public boolean isFPPlusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_INF; } /** * Indicates whether the term is a floating-point -oo * @return * @throws Z3Exception */ - public boolean IsFPMinusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_INF; } + public boolean isFPMinusInfinity() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_INF; } /** * Indicates whether the term is a floating-point NaN * @return * @throws Z3Exception */ - public boolean IsFPNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NAN; } + public boolean isFPNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NAN; } /** * Indicates whether the term is a floating-point +zero * @return * @throws Z3Exception */ - public boolean IsFPPlusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO; } + public boolean isFPPlusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_PLUS_ZERO; } /** * Indicates whether the term is a floating-point -zero * @return * @throws Z3Exception */ - public boolean IsFPMinusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO; } + public boolean isFPMinusZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MINUS_ZERO; } /** * Indicates whether the term is a floating-point addition term * @return * @throws Z3Exception */ - public boolean IsFPAdd() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ADD; } + public boolean isFPAdd() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ADD; } /** @@ -1862,211 +1869,210 @@ public class Expr extends AST * @return * @throws Z3Exception */ - public boolean IsFPSub() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SUB; } + public boolean isFPSub() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SUB; } /** * Indicates whether the term is a floating-point negation term * @return * @throws Z3Exception */ - public boolean IsFPNeg() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NEG; } + public boolean isFPNeg() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_NEG; } /** * Indicates whether the term is a floating-point multiplication term * @return * @throws Z3Exception */ - public boolean IsFPMul() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MUL; } + public boolean isFPMul() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MUL; } /** * Indicates whether the term is a floating-point divison term * @return * @throws Z3Exception */ - public boolean IsFPDiv() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_DIV; } + public boolean isFPDiv() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_DIV; } /** * Indicates whether the term is a floating-point remainder term * @return * @throws Z3Exception */ - public boolean IsFPRem() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_REM; } + public boolean isFPRem() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_REM; } /** * Indicates whether the term is a floating-point term absolute value term * @return * @throws Z3Exception */ - public boolean IsFPAbs() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ABS; } + public boolean isFPAbs() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ABS; } /** * Indicates whether the term is a floating-point minimum term * @return * @throws Z3Exception */ - public boolean IsFPMin() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MIN; } + public boolean isFPMin() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MIN; } /** * Indicates whether the term is a floating-point maximum term * @return * @throws Z3Exception */ - public boolean IsFPMax() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MAX; } + public boolean isFPMax() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_MAX; } /** * Indicates whether the term is a floating-point fused multiply-add term * @return * @throws Z3Exception */ - public boolean IsFPFMA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FMA; } + public boolean isFPFMA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FMA; } /** * Indicates whether the term is a floating-point square root term * @return * @throws Z3Exception */ - public boolean IsFPSqrt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SQRT; } + public boolean isFPSqrt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_SQRT; } /** * Indicates whether the term is a floating-point roundToIntegral term * @return * @throws Z3Exception */ - public boolean IsFPRoundToIntegral() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL; } + public boolean isFPRoundToIntegral() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_ROUND_TO_INTEGRAL; } /** * Indicates whether the term is a floating-point equality term * @return * @throws Z3Exception */ - public boolean IsFPEq() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_EQ; } + public boolean isFPEq() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_EQ; } /** * Indicates whether the term is a floating-point less-than term * @return * @throws Z3Exception */ - public boolean IsFPLt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LT; } + public boolean isFPLt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LT; } /** * Indicates whether the term is a floating-point greater-than term * @return * @throws Z3Exception */ - public boolean IsFPGt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GT; } + public boolean isFPGt() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GT; } /** * Indicates whether the term is a floating-point less-than or equal term * @return * @throws Z3Exception */ - public boolean IsFPLe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LE; } + public boolean isFPLe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_LE; } /** * Indicates whether the term is a floating-point greater-than or erqual term * @return * @throws Z3Exception */ - public boolean IsFPGe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GE; } + public boolean isFPGe() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_GE; } /** * Indicates whether the term is a floating-point isNaN predicate term * @return * @throws Z3Exception */ - public boolean IsFPisNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NAN; } + public boolean isFPisNaN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NAN; } /** * Indicates whether the term is a floating-point isInf predicate term * @return * @throws Z3Exception */ - public boolean IsFPisInf() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_INF; } + public boolean isFPisInf() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_INF; } /** * Indicates whether the term is a floating-point isZero predicate term * @return * @throws Z3Exception */ - public boolean IsFPisZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_ZERO; } + public boolean isFPisZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_ZERO; } /** * Indicates whether the term is a floating-point isNormal term * @return * @throws Z3Exception */ - public boolean IsFPisNormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NORMAL; } + public boolean isFPisNormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NORMAL; } /** * Indicates whether the term is a floating-point isSubnormal predicate term * @return * @throws Z3Exception */ - public boolean IsFPisSubnormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL; } + public boolean isFPisSubnormal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_SUBNORMAL; } /** * Indicates whether the term is a floating-point isNegative predicate term * @return * @throws Z3Exception */ - public boolean IsFPisNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE; } + public boolean isFPisNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_NEGATIVE; } /** * Indicates whether the term is a floating-point isPositive predicate term * @return * @throws Z3Exception */ - public boolean IsFPisPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE; } + public boolean isFPisPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_IS_POSITIVE; } /** * Indicates whether the term is a floating-point constructor term * @return * @throws Z3Exception */ - public boolean IsFPFP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FP; } + public boolean isFPFP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_FP; } /** * Indicates whether the term is a floating-point conversion term * @return * @throws Z3Exception */ - public boolean IsFPToFp() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP; } + public boolean isFPToFp() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP; } /** * Indicates whether the term is a floating-point conversion from unsigned bit-vector term * @return * @throws Z3Exception */ - public boolean IsFPToFpUnsigned() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED; } + public boolean isFPToFpUnsigned() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_FP_UNSIGNED; } /** * Indicates whether the term is a floating-point conversion to unsigned bit-vector term * @return * @throws Z3Exception */ - public boolean IsFPToUBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_UBV; } + public boolean isFPToUBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_UBV; } /** * Indicates whether the term is a floating-point conversion to signed bit-vector term * @return * @throws Z3Exception */ - public boolean IsFPToSBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_SBV; } + public boolean isFPToSBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_SBV; } /** * Indicates whether the term is a floating-point conversion to real term * @return * @throws Z3Exception */ - public boolean IsFPToReal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_REAL; } - + public boolean isFPToReal() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_REAL; } /** * Indicates whether the term is a floating-point conversion to IEEE-754 bit-vector term1 * @return * @throws Z3Exception */ - public boolean IsFPToIEEEBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV; } + public boolean isFPToIEEEBV() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_TO_IEEE_BV; } /** @@ -2140,6 +2146,8 @@ public class Expr extends AST return new BitVecNum(ctx, obj); case Z3_FLOATING_POINT_SORT: return new FPNum(ctx, obj); + case Z3_ROUNDING_MODE_SORT: + return new FPRMNum(ctx, obj); default: ; } } diff --git a/src/api/java/FPExpr.java b/src/api/java/FPExpr.java new file mode 100644 index 000000000..e5193a042 --- /dev/null +++ b/src/api/java/FPExpr.java @@ -0,0 +1,41 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPExpr.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +/** + * FloatingPoint Expressions + */ +public class FPExpr extends Expr +{ + /** + * The number of exponent bits. + * @throws Z3Exception + */ + public int getEBits() throws Z3Exception { return ((FPSort)getSort()).getEBits(); } + + /** + * The number of significand bits. + * @throws Z3Exception + */ + public int getSBits() throws Z3Exception { return ((FPSort)getSort()).getSBits(); } + + public FPExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } + +} diff --git a/src/api/java/FPNum.java b/src/api/java/FPNum.java new file mode 100644 index 000000000..f2c9b7f98 --- /dev/null +++ b/src/api/java/FPNum.java @@ -0,0 +1,86 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPNum.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +/** + * FloatingPoint Numerals + */ +public class FPNum extends FPExpr +{ + /** + * Retrieves the sign of a floating-point literal + * Remarks: returns true if the numeral is negative + * @throws Z3Exception + */ + public boolean getSign() throws Z3Exception { + Native.IntPtr res = new Native.IntPtr(); + if (Native.fpaGetNumeralSign(getContext().nCtx(), getNativeObject(), res) ^ true) + throw new Z3Exception("Sign is not a Boolean value"); + return res.value != 0; + + + } + + /** + * The significand value of a floating-point numeral as a string + * Remarks: The significand s is always 0 < s < 2.0; the resulting string is long + * enough to represent the real significand precisely. + * @throws Z3Exception + **/ + public String getSignificand() throws Z3Exception { + return Native.fpaGetNumeralSignificandString(getContext().nCtx(), getNativeObject()); + } + + /** + * Return the exponent value of a floating-point numeral as a string + * @throws Z3Exception + */ + public String getExponent() throws Z3Exception { + return Native.fpaGetNumeralExponentString(getContext().nCtx(), getNativeObject()); + } + + /** + * Return the exponent value of a floating-point numeral as a signed 64-bit integer + * @throws Z3Exception + */ + public long getExponentInt64() throws Z3Exception { + Native.LongPtr res = new Native.LongPtr(); + if (Native.fpaGetNumeralExponentInt64(getContext().nCtx(), getNativeObject(), res) ^ true) + throw new Z3Exception("Exponent is not a 64 bit integer"); + return res.value; + } + + public FPNum(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } + + /** + * Returns a string representation of the numeral. + */ + public String toString() + { + try + { + return Native.getNumeralString(getContext().nCtx(), getNativeObject()); + } catch (Z3Exception e) + { + return "Z3Exception: " + e.getMessage(); + } + } + +} diff --git a/src/api/java/FPRMExpr.java b/src/api/java/FPRMExpr.java new file mode 100644 index 000000000..482c3b899 --- /dev/null +++ b/src/api/java/FPRMExpr.java @@ -0,0 +1,29 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMExpr.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +/** + * FloatingPoint RoundingMode Expressions + */ +public class FPRMExpr extends Expr +{ + public FPRMExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } + +} diff --git a/src/api/java/FPRMNum.java b/src/api/java/FPRMNum.java new file mode 100644 index 000000000..04e7727e2 --- /dev/null +++ b/src/api/java/FPRMNum.java @@ -0,0 +1,90 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMNum.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +import com.microsoft.z3.enumerations.Z3_decl_kind; + +/** + * FloatingPoint RoundingMode Numerals + */ +public class FPRMNum extends FPRMExpr { + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + * @throws Z3Exception + * **/ + public boolean isRoundNearestTiesToEven() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToEven + * @throws Z3Exception + */ + public boolean isRNE() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + * @throws Z3Exception + */ + public boolean isRoundNearestTiesToAway() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundNearestTiesToAway + * @throws Z3Exception + */ + public boolean isRNA() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardPositive + * @throws Z3Exception + */ + public boolean isRoundTowardPositive() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardPositive + * @throws Z3Exception + */ + public boolean isRTP() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_POSITIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardNegative + * @throws Z3Exception + */ + public boolean isRoundTowardNegative() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardNegative + * @throws Z3Exception + */ + public boolean isRTN() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_NEGATIVE; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardZero + * @throws Z3Exception + */ + public boolean isRoundTowardZero() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + + /** + * Indicates whether the term is the floating-point rounding numeral roundTowardZero + * @throws Z3Exception + */ + public boolean isRTZ() throws Z3Exception { return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_FPA_RM_TOWARD_ZERO; } + + public FPRMNum(Context ctx, long obj) throws Z3Exception { + super(ctx, obj); + } + +} diff --git a/src/api/java/FPRMSort.java b/src/api/java/FPRMSort.java new file mode 100644 index 000000000..ff6422ef6 --- /dev/null +++ b/src/api/java/FPRMSort.java @@ -0,0 +1,35 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPRMExpr.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +/** + * The FloatingPoint RoundingMode sort + **/ +public class FPRMSort extends Sort +{ + + public FPRMSort(Context ctx) throws Z3Exception + { + super(ctx, Native.mkFpaRoundingModeSort(ctx.nCtx())); + } + + public FPRMSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } + +} \ No newline at end of file diff --git a/src/api/java/FPSort.java b/src/api/java/FPSort.java new file mode 100644 index 000000000..284979524 --- /dev/null +++ b/src/api/java/FPSort.java @@ -0,0 +1,49 @@ +/*++ +Copyright (c) 2013 Microsoft Corporation + +Module Name: + + FPSort.java + +Abstract: + +Author: + + Christoph Wintersteiger (cwinter) 2013-06-10 + +Notes: + +--*/ +package com.microsoft.z3; + +/** + * A FloatingPoint sort + **/ +public class FPSort extends Sort +{ + + public FPSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } + + public FPSort(Context ctx, int ebits, int sbits) throws Z3Exception + { + super(ctx, Native.mkFpaSort(ctx.nCtx(), ebits, sbits)); + } + + /** + * The number of exponent bits. + */ + public int getEBits() throws Z3Exception { + return Native.fpaGetEbits(getContext().nCtx(), getNativeObject()); + } + + /** + * The number of significand bits. + */ + public int getSBits() throws Z3Exception { + return Native.fpaGetEbits(getContext().nCtx(), getNativeObject()); + } + +} diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 043d43e2f..7457ed9a3 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -834,6 +834,47 @@ extern "C" { */ unsigned Z3_API Z3_fpa_get_sbits(__in Z3_context c, __in Z3_sort s); + /** + \brief Retrieves the sign of a floating-point literal + + Remarks: sets \c sgn to 0 if the literal is NaN or positive and to 1 otherwise. + + \param t a floating-point numeral. + + def_API('Z3_fpa_get_numeral_sign', BOOL, (_in(CONTEXT), _in(AST), _out(INT))) + */ + Z3_bool Z3_API Z3_fpa_get_numeral_sign(__in Z3_context c, __in Z3_ast t, __out int * sgn); + + /** + \brief Return the significand value of a floating-point numeral as a string + + Remarks: The significand s is always 0 < s < 2.0; the resulting string is long + enough to represent the real significand precisely. + + \param t a floating-point numeral. + + def_API('Z3_fpa_get_numeral_significand_string', STRING, (_in(CONTEXT), _in(AST))) + */ + Z3_string Z3_API Z3_fpa_get_numeral_significand_string(__in Z3_context c, __in Z3_ast t); + + /** + \brief Return the exponent value of a floating-point numeral as a string + + \param t a floating-point numeral. + + def_API('Z3_fpa_get_numeral_exponent_string', STRING, (_in(CONTEXT), _in(AST))) + */ + Z3_string Z3_API Z3_fpa_get_numeral_exponent_string(__in Z3_context c, __in Z3_ast t); + + /** + \brief Return the exponent value of a floating-point numeral as a signed 64-bit integer + + \param t a floating-point numeral. + + def_API('Z3_fpa_get_numeral_exponent_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) + */ + Z3_bool Z3_API Z3_fpa_get_numeral_exponent_int64(__in Z3_context c, __in Z3_ast t, __out __int64 * n); + /** \brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. From 4bd8e0f4979c7cebad17207d268ba2e15f27de28 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 11 Jan 2015 18:28:07 +0000 Subject: [PATCH 167/646] FPA API cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 12 ++++++------ src/api/java/Context.java | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 70777a6e8..1a36a35dc 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3758,11 +3758,11 @@ namespace Microsoft.Z3 /// /// Create a numeral of FloatingPoint sort from a sign bit and two integers. /// - /// the sign. - /// the significand. + /// the sign. /// the exponent. + /// the significand. /// FloatingPoint sort. - public FPNum MkFP(bool sgn, uint sig, int exp, FPSort s) + public FPNum MkFP(bool sgn, int exp, uint sig, FPSort s) { Contract.Ensures(Contract.Result() != null); return MkFPNumeral(sgn, sig, exp, s); @@ -3771,11 +3771,11 @@ namespace Microsoft.Z3 /// /// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. /// - /// the sign. - /// the significand. + /// the sign. /// the exponent. + /// the significand. /// FloatingPoint sort. - public FPNum MkFP(bool sgn, UInt64 sig, Int64 exp, FPSort s) + public FPNum MkFP(bool sgn, Int64 exp, UInt64 sig, FPSort s) { Contract.Ensures(Contract.Result() != null); return MkFPNumeral(sgn, sig, exp, s); diff --git a/src/api/java/Context.java b/src/api/java/Context.java index cfbd7c2c8..2b4c47d76 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3170,7 +3170,7 @@ public class Context extends IDisposable * @param s FloatingPoint sort. * @throws Z3Exception **/ - public FPNum mkFP(boolean sgn, int sig, int exp, FPSort s) throws Z3Exception + public FPNum mkFP(boolean sgn, int exp, int sig, FPSort s) throws Z3Exception { return mkFPNumeral(sgn, sig, exp, s); } @@ -3183,7 +3183,7 @@ public class Context extends IDisposable * @param s FloatingPoint sort. * @throws Z3Exception **/ - public FPNum mkFP(boolean sgn, long sig, long exp, FPSort s) throws Z3Exception + public FPNum mkFP(boolean sgn, long exp, long sig, FPSort s) throws Z3Exception { return mkFPNumeral(sgn, sig, exp, s); } From e0bc704106e15595856ec81419fb299dcb51aa87 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 11 Jan 2015 18:29:12 +0000 Subject: [PATCH 168/646] FPA API bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 26 +++++++++++++++++++------- src/api/z3_fpa.h | 6 +++--- src/ast/fpa_decl_plugin.cpp | 16 +++++++++++++++- src/util/mpf.h | 17 +++++++++++++++++ 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 219f9b166..67ffe12d9 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -217,7 +217,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast sig, Z3_ast exp) { + Z3_ast Z3_API Z3_mk_fpa_fp(Z3_context c, Z3_ast sgn, Z3_ast exp, Z3_ast sig) { Z3_TRY; LOG_Z3_mk_fpa_fp(c, sgn, sig, exp); RESET_ERROR_CODE(); @@ -680,7 +680,11 @@ extern "C" { mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); - bool r = plugin->is_numeral(to_expr(t), val); + bool r = plugin->is_numeral(to_expr(t), val); + if (!r || mpfm.is_nan(val)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } *sgn = (mpfm.is_nan(val)) ? 0 : mpfm.sgn(val); return r; Z3_CATCH_RETURN(0); @@ -694,14 +698,18 @@ extern "C" { mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); - scoped_mpf val(mpfm); - if (!plugin->is_numeral(to_expr(t), val)) { + scoped_mpf val(mpfm); + if (!plugin->is_numeral(to_expr(t), val)) { SET_ERROR_CODE(Z3_INVALID_ARG); return ""; } + else if (!mpfm.is_regular(val)) { + SET_ERROR_CODE(Z3_INVALID_ARG) + return ""; + } unsigned sbits = val.get().get_sbits(); scoped_mpq q(mpqm); - mpqm.set(q, mpfm.sig(val)); + mpqm.set(q, mpfm.sig_normalized(val)); mpqm.div(q, mpfm.m_powers2(sbits - 1), q); std::stringstream ss; mpqm.display_decimal(ss, q, sbits); @@ -724,7 +732,11 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return ""; } - const mpf_exp_t exp = mpfm.exp(val); + else if (!mpfm.is_normal(val) && !mpfm.is_denormal(val)) { + SET_ERROR_CODE(Z3_INVALID_ARG) + return ""; + } + mpf_exp_t exp = mpfm.exp_normalized(val); std::stringstream ss; ss << exp; return mk_c(c)->mk_external_string(ss.str()); @@ -740,7 +752,7 @@ extern "C" { unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); - bool r = plugin->is_numeral(to_expr(t), val); + bool r = plugin->is_numeral(to_expr(t), val); if (!r) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 7457ed9a3..75002e1a5 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -273,13 +273,13 @@ extern "C" { of the arguments. \params c logical context. - \params sgn sign - \params sig significand + \params sgn sign \params exp exponent + \params sig significand def_API('Z3_mk_fpa_fp', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) */ - Z3_ast Z3_API Z3_mk_fpa_fp(__in Z3_context c, __in Z3_ast sgn, __in Z3_ast sig, __in Z3_ast exp); + Z3_ast Z3_API Z3_mk_fpa_fp(__in Z3_context c, __in Z3_ast sgn, __in Z3_ast exp, __in Z3_ast sig); /** \brief Create a numeral of FloatingPoint sort from a float. diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index a8e805066..9900812dd 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -76,7 +76,21 @@ func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) { } app * fpa_decl_plugin::mk_numeral(mpf const & v) { - return m_manager->mk_const(mk_numeral_decl(v)); + sort * s = mk_float_sort(v.get_ebits(), v.get_sbits()); + func_decl * d; + if (m_fm.is_nan(v)) + d = m_manager->mk_const_decl(symbol("NaN"), s, func_decl_info(m_family_id, OP_FPA_NAN)); + else if (m_fm.is_pinf(v)) + d = m_manager->mk_const_decl(symbol("+oo"), s, func_decl_info(m_family_id, OP_FPA_PLUS_INF)); + else if (m_fm.is_ninf(v)) + d = m_manager->mk_const_decl(symbol("-oo"), s, func_decl_info(m_family_id, OP_FPA_MINUS_INF)); + else if (m_fm.is_pzero(v)) + d = m_manager->mk_const_decl(symbol("+zero"), s, func_decl_info(m_family_id, OP_FPA_PLUS_ZERO)); + else if (m_fm.is_nzero(v)) + d = m_manager->mk_const_decl(symbol("-zero"), s, func_decl_info(m_family_id, OP_FPA_MINUS_ZERO)); + else + d = mk_numeral_decl(v); + return m_manager->mk_const(d); } bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) { diff --git a/src/util/mpf.h b/src/util/mpf.h index b919e0371..599e8e743 100644 --- a/src/util/mpf.h +++ b/src/util/mpf.h @@ -146,7 +146,24 @@ public: bool sgn(mpf const & x) const { return x.sign; } const mpz & sig(mpf const & x) const { return x.significand; } + mpz sig_normalized(mpf const & x) { + mpf t; + set(t, x); + unpack(t, true); + mpz r; + mpz_manager().set(r, t.significand); + del(t); + return r; + } const mpf_exp_t & exp(mpf const & x) const { return x.exponent; } + mpf_exp_t exp_normalized(mpf const & x) { + mpf t; + set(t, x); + unpack(t, true); + mpf_exp_t r = t.exponent; + del(t); + return r; + } bool is_nan(mpf const & x); bool is_inf(mpf const & x); From 6c971b130132c8774d5e92b2a331a5a702485382 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 11 Jan 2015 18:29:40 +0000 Subject: [PATCH 169/646] Beginnings of a Python API for FPA Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 912 ++++++++++++++++++++++++++++++++++++ src/api/python/z3printer.py | 207 +++++++- 2 files changed, 1114 insertions(+), 5 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index bb0212820..a2f0191cf 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -555,6 +555,10 @@ def _to_sort_ref(s, ctx): return ArraySortRef(s, ctx) elif k == Z3_DATATYPE_SORT: return DatatypeSortRef(s, ctx) + elif k == Z3_FLOATING_POINT_SORT: + return FPSortRef(s, ctx) + elif k == Z3_ROUNDING_MODE_SORT: + return FPRMSortRef(s, ctx) return SortRef(s, ctx) def _sort(ctx, a): @@ -899,6 +903,17 @@ def _to_expr_ref(a, ctx): return ArrayRef(a, ctx) if sk == Z3_DATATYPE_SORT: return DatatypeRef(a, ctx) + if sk == Z3_FLOATING_POINT_SORT: + if k == Z3_APP_AST: + e = ExprRef(a, ctx) + if e.decl().kind() == Z3_OP_FPA_NUM: + return FPNumRef(a, ctx) + else: + return FPRef(a, ctx) + else: + return FPRef(a, ctx) + if sk == Z3_ROUNDING_MODE_SORT: + return FPRMRef(a, ctx) return ExprRef(a, ctx) def _coerce_expr_merge(s, a): @@ -7429,3 +7444,900 @@ def sequence_interpolant(v,p=None,ctx=None): f = And(Interpolant(f),v[i]) return tree_interpolant(f,p,ctx) +######################################### +# +# Floating-Point Arithmetic +# +######################################### + + +# Global default rounding mode +_dflt_rounding_mode = Z3_OP_FPA_RM_TOWARD_ZERO +_dflt_fpsort_ebits = 11 +_dflt_fpsort_sbits = 53 + +def get_default_rounding_mode(ctx=None): + """Retrieves the global default rounding mode.""" + global _dflt_rounding_mode + if _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO: + return RTZ(ctx) + elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE: + return RTN(ctx) + elif _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE: + return RTP(ctx) + elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN: + return RNE(ctx) + elif _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY: + return RNA(ctx) + +def set_default_rounding_mode(rm, ctx=None): + global _dflt_rounding_mode + if is_fprm_value(rm): + _dflt_rounding_mode = rm.decl().kind() + else: + _z3_assert(_dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_ZERO or + _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_NEGATIVE or + _dflt_rounding_mode == Z3_OP_FPA_RM_TOWARD_POSITIVE or + _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN or + _dflt_rounding_mode == Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY, + "illegal rounding mode") + _dflt_rounding_mode = rm + +def get_default_fp_sort(ctx=None): + return FPSort(_dflt_fpsort_ebits, _dflt_fpsort_sbits, ctx) + +def set_default_fp_sort(ebits, sbits, ctx=None): + global _dflt_fpsort_ebits + global _dflt_fpsort_sbits + _dflt_fpsort_ebits = ebits + _dflt_fpsort_sbits = sbits + +def _dflt_rm(ctx=None): + return get_default_rounding_mode(ctx) + +def _dflt_fps(ctx=None): + return get_default_fp_sort(ctx) + +### FP Sorts + +class FPSortRef(SortRef): + """Floating-point sort.""" + + def ebits(self): + """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`. + >>> b = FPSort(8, 24) + >>> b.ebits() + 8 + """ + return int(Z3_fpa_get_ebits(self.ctx_ref(), self.ast)) + + def sbits(self): + """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`. + >>> b = FloatingPointSort(8, 24) + >>> b.sbits() + 24 + """ + return int(Z3_fpa_get_sbits(self.ctx_ref(), self.ast)) + + def cast(self, val): + """Try to cast `val` as a Floating-point expression + + >>> b = FPSort(8, 24) + >>> b.cast(1.0) + 1.0 + >>> b.cast(1.0).sexpr() + '1.0' + """ + if is_expr(val): + if __debug__: + _z3_assert(self.ctx == val.ctx, "Context mismatch") + return val + else: + return FPVal(val, None, self, self.ctx) + + +def Float16(ctx=None): + """Floating-point 16-bit (half) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_16(ctx.ref()), ctx) + +def FloatHalf(ctx=None): + """Floating-point 16-bit (half) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_half(ctx.ref()), ctx) + +def Float32(ctx=None): + """Floating-point 32-bit (single) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_32(ctx.ref()), ctx) + +def FloatSingle(ctx=None): + """Floating-point 32-bit (single) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_single(ctx.ref()), ctx) + +def Float64(ctx=None): + """Floating-point 64-bit (double) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_64(ctx.ref()), ctx) + +def FloatSingle(ctx=None): + """Floating-point 64-bit (double) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_double(ctx.ref()), ctx) + +def Float128(ctx=None): + """Floating-point 128-bit (quadruple) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_128(ctx.ref()), ctx) + +def FloatSingle(ctx=None): + """Floating-point 128-bit (quadruple) sort.""" + ctx = _get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort_quadruple(ctx.ref()), ctx) + +class FPRMSortRef(SortRef): + """"Floating-point rounding mode sort.""" + + +def is_fp_sort(s): + """Return True if `s` is a Z3 floating-point sort. + + >>> is_fp_sort(FloatingPointSort(8, 24)) + True + >>> is_fp_sort(IntSort()) + False + """ + return isinstance(s, FPSortRef) + +def is_fprm_sort(s): + """Return True if `s` is a Z3 floating-point rounding mode sort. + + >>> is_fprm_sort(FPSort(8, 24)) + False + >>> is_fprm_sort() + False + """ + return isinstance(s, FPSortRef) + +### FP Expressions + +class FPRef(ExprRef): + """Floating-point expressions.""" + + def sort(self): + """Return the sort of the floating-point expression `self`. + + >>> x = FP('1.0', FPSort(8, 24)) + >>> x.sort() + (_ FloatingPoint 8 24) + >>> x.sort() == FloatingPointSort(8, 24) + True + """ + return FPSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) + + def ebits(self): + """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. + >>> b = FloatingPointSort(8, 24) + >>> b.ebits() + 8 + """ + return self.sort().ebits(); + + def sbits(self): + """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. + >>> b = FloatingPointSort(8, 24) + >>> b.sbits() + 24 + """ + return self.sort().sbits(); + + def as_string(self): + """Return a Z3 floating point expression as a Python string.""" + return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) + + def __le__(self, other): + return fpLEQ(self, other) + + def __lt__(self, other): + return fpLEQ(self, other) + + def __ge__(self, other): + return fpGEQ(self, other) + + def __gt__(self, other): + return fpGT(self, other) + + def __ne__(self, other): + return fpNEQ(self, other) + + + def __add__(self, other): + """Create the Z3 expression `self + other`. + + >>> x = FP('x', 8, 24) + >>> y = FP('y', 8, 24) + >>> x + y + x + y + >>> (x + y).sort() + FloatingPoint(8 24) + """ + a, b = z3._coerce_exprs(self, other) + return fpAdd(_dflt_rm(), self, other) + + def __radd__(self, other): + """Create the Z3 expression `other + self`. + + >>> x = FP('x', FPSort(8, 24)) + >>> 10 + x + 10 + x + """ + a, b = _coerce_exprs(self, other) + return fpAdd(_dflt_rm(), other, self) + + def __sub__(self, other): + """Create the Z3 expression `self - other`. + + >>> x = FP('x', 8, 24) + >>> y = FP('y', 8, 24) + >>> x - y + x - y + >>> (x - y).sort() + FloatingPoint(8 24) + """ + a, b = z3._coerce_exprs(self, other) + return fpSub(_dflt_rm(), self, other) + + def __rsub__(self, other): + """Create the Z3 expression `other - self`. + + >>> x = FP('x', FPSort(8, 24)) + >>> 10 - x + 10 - x + """ + a, b = _coerce_exprs(self, other) + return fpSub(_dflt_rm(), other, self) + + def __mul__(self, other): + """Create the Z3 expression `self * other`. + + >>> x = FP('x', 8, 24) + >>> y = FP('y', 8, 24) + >>> x * y + x * y + >>> (x * y).sort() + FloatingPoint(8 24) + """ + a, b = z3._coerce_exprs(self, other) + return fpMul(_dflt_rm(), self, other) + + def __rmul_(self, other): + """Create the Z3 expression `other * self`. + + >>> x = FP('x', FPSort(8, 24)) + >>> 10 * x + 10 * x + """ + a, b = _coerce_exprs(self, other) + return fpMul(_dflt_rm(), other, self) + + def __pos__(self): + """Create the Z3 expression `+self`.""" + return self + + def __neg__(self): + """Create the Z3 expression `-self`.""" + return FPRef(fpNeg(self)) + + def __truediv__(self, other): + """Create the Z3 expression division `self / other`.""" + return self.__div__(other) + + def __rtruediv__(self, other): + """Create the Z3 expression division `other / self`.""" + return self.__rdiv__(other) + + def __mod__(self, other): + """Create the Z3 expression mod `self % other`.""" + return fpRem(self, other) + + def __rmod__(self, other): + """Create the Z3 expression mod `other % self`.""" + return fpRem(other, self) + +class FPRMRef(ExprRef): + """Floating-point rounding mode expressions""" + + def as_string(self): + """Return a Z3 floating point expression as a Python string.""" + return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) + + +def RoundNearestTiesToEven (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) + +def RNE (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) + +def RoundNearestTiesToAway (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) + +def RNA (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) + +def RoundTowardPositive (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) + +def RTP (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) + +def RoundTowardNegative (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) + +def RTN (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) + +def RoundTowardZero (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) + +def RTZ (ctx=None): + ctx = _get_ctx(ctx) + return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) + +def is_fprm(a): + """Return `True` if `a` is a Z3 floating-point rounding mode expression. + + >>> rm = ? + """ + return isinstance(a, FPRMRef) + +def is_fprm_value(a): + """Return `True` if `a` is a Z3 floating-point rounding mode numeral value.""" + return is_fprm(a) and _is_numeral(a.ctx, a.ast) + +### FP Numerals + +class FPNumRef(FPRef): + def isNaN(self): + return self.decl().kind() == Z3_OP_FPA_NAN + + def isInf(self): + return self.decl().kind() == Z3_OP_FPA_PLUS_INF or self.decl().kind() == Z3_OP_FPA_MINUS_INF + + def isZero(self): + return self.decl().kind() == Z3_OP_FPA_PLUS_ZERO or self.decl().kind() == Z3_OP_FPA_MINUS_ZERO + + def isNegative(self): + return (self.num_args() == 0 and (Z3_OP_FPA_MINUS_INF or Z3_OP_FPA_MINUS_ZERO)) or (self.num_args() == 3 and self.arg(0) == BitVecVal(1)) + +def _to_fpnum(num, ctx=None): + if isinstance(num, FPNum): + return num + else: + return FPNum(num, ctx) + +def is_fp(a): + """Return `True` if `a` is a Z3 floating-point expression. + + >>> b = FP('b', FPSort(8, 24)) + >>> is_fp(b) + True + >>> is_fp(b + 1.0) + True + >>> is_fp(Int('x')) + False + """ + return isinstance(a, FPRef) + +def is_fp_value(a): + """Return `True` if `a` is a Z3 floating-point numeral value. + + >>> b = FP('b', FPSort(8, 24)) + >>> is_fp_value(b) + False + >>> b = FPVal(1.0, FPSort(8, 24)) + >>> b + 1.0p0 + >>> is_fp_value(b) + True + """ + return is_fp(a) and _is_numeral(a.ctx, a.ast) + +def FPSort(ebits, sbits, ctx=None): + """Return a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used. + + >>> Single = FPSort(8, 24) + >>> Double = FPSort(11, 53) + >>> Single + (_ FloatingPoint 8 24) + >>> x = Const('x', Single) + >>> eq(x, FP('x', 8, 24)) + True + """ + ctx = z3._get_ctx(ctx) + return FPSortRef(Z3_mk_fpa_sort(ctx.ref(), ebits, sbits), ctx) + +def _to_float_str(val): + if isinstance(val, float): + return str(val) + elif isinstance(val, bool): + if val: + return "1.0" + else: + return "0.0" + elif _is_int(val): + return str(val) + elif isinstance(val, str): + return val + if __debug__: + _z3_assert(False, "Python value cannot be used as a double") + +def fpNaN(s): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + return FPNumRef(Z3_mk_fpa_nan(s.ctx_ref(), s.ast), s.ctx) + +def fpPlusInfinity(s): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, False), s.ctx) + +def fpMinusInfinity(s): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, True), s.ctx) + +def fpInfinity(s, negative): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + _z3_assert(isinstance(negative, bool), "expected Boolean flag") + return FPNumRef(Z3_mk_fpa_inf(s.ctx_ref(), s.ast, negative), s.ctx) + +def fpPlusZero(s): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, False), s.ctx) + +def fpMinusZero(s): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, True), s.ctx) + +def fpZero(s, negative): + _z3_assert(isinstance(s, FPSortRef), "sort mismatch") + _z3_assert(isinstance(negative, bool), "expected Boolean flag") + return FPNumRef(Z3_mk_fpa_zero(s.ctx_ref(), s.ast, negative), s.ctx) + +def FPVal(sig, exp=None, fps=None, ctx=None): + """Return a floating-point value of value `val` and sort `fps`. If `ctx=None`, then the global context is used. + + >>> v = FPVal(1.0, FPSort(8, 24))) + >>> v + 1.0 + >>> print("0x%.8x" % v.as_long()) + 0x0000000a + """ + ctx = _get_ctx(ctx) + if is_fp_sort(exp): + fps = exp + exp = None + elif fps == None: + fps = _dflt_fps(ctx) + _z3_assert(is_fp_sort(fps), "sort mismatch") + if exp == None: + exp = 0 + val = _to_float_str(sig) + val = val + 'p' + val = val + _to_int_str(exp) + return FPNumRef(Z3_mk_numeral(ctx.ref(), val, fps.ast), ctx) + +def FP(name, fpsort, ctx=None): + """Return a floating-point constant named `name`. + `fpsort` is the floating-point sort. + If `ctx=None`, then the global context is used. + + >>> x = FP('x', FPSort(8, 24)) + >>> is_fp(x) + True + >>> x.ebits() + 8 + >>> x.sort() + (_ FloatingPoint 8 24) + >>> word = FPSort(8, 24) + >>> x2 = FP('x', word) + >>> eq(x, x2) + True + """ + ctx = fpsort.ctx + return FPRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), fpsort.ast), ctx) + +def FPs(names, fpsort, ctx=None): + """Return an array of floating-point constants. + + >>> x, y, z = BitVecs('x y z', 16) + >>> x.size() + 16 + >>> x.sort() + BitVec(16) + >>> Sum(x, y, z) + 0 + x + y + z + >>> Product(x, y, z) + 1*x*y*z + >>> simplify(Product(x, y, z)) + x*y*z + """ + ctx = z3._get_ctx(ctx) + if isinstance(names, str): + names = names.split(" ") + return [FP(name, fpsort, ctx) for name in names] + +def fpAbs(a): + """Create a Z3 floating-point absolute value expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FPVal(1.0, s) + >>> fpAbs(x) + 1.0 + >>> x = FPVal(-1.0, s) + >>> fpAbs(x) + 1.0 + >>> fpAbs(x).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fp(a), "First argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_abs(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpNeg(a): + """Create a Z3 floating-point addition expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FP('x', s) + >>> y = FP('y', s) + fp.add(rm, x, y) + >>> fp.add(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fp(a), "First argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_neg(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpAdd(rm, a, b): + """Create a Z3 floating-point addition expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FP('x', s) + >>> y = FP('y', s) + fp.add(rm, x, y) + >>> fp.add(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_add(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) + +def fpSub(rm, a, b): + """Create a Z3 floating-point subtraction expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FP('x', s) + >>> y = FP('y', s) + fp.add(rm, x, y) + >>> fp.add(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_sub(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) + +def fpMul(rm, a, b): + """Create a Z3 floating-point multiplication expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FP('x', s) + >>> y = FP('y', s) + fp.add(rm, x, y) + >>> fp.add(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) + +def fpDiv(rm, a, b): + """Create a Z3 floating-point divison expression. + + >>> s = FPSort(8, 24) + >>> rm = FPRM.RNE + >>> x = FP('x', s) + >>> y = FP('y', s) + fpAdd(rm, x, y) + >>> fp.add(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) + +def fpRem(a, b): + """Create a Z3 floating-point remainder expression. + + >>> s = FPSort(8, 24) + >>> rm = RNE() + >>> x = FP('x', s) + >>> y = FP('y', s) + fpRem(x, y) + >>> fpRem(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_rem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpMin(a, b): + """Create a Z3 floating-point minimium expression. + + >>> s = FPSort(8, 24) + >>> rm = RNE() + >>> x = FP('x', s) + >>> y = FP('y', s) + fpMin(x, y) + >>> fpMin(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_min(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpMax(a, b): + """Create a Z3 floating-point maximum expression. + + >>> s = FPSort(8, 24) + >>> rm = RNE() + >>> x = FP('x', s) + >>> y = FP('y', s) + fpMin(x, y) + >>> fpMin(rm, x, y).sort() + FloatingPoint(8, 24) + """ + if __debug__: + _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_max(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpFMA(rm, a, b, c): + """Create a Z3 floating-point fused multiply-add expression. + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a) and is_fp(b) and is_fp(c), "Second, third, and fourth argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_fma(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast(), c.as_ast()), rm.ctx) + +def fpSqrt(rm, a): + """Create a Z3 floating-point square root expression. + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_sqrt(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx) + +def fpRoundToIntegral(rm, a): + """Create a Z3 floating-point roundToIntegral expression. + """ + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_round_to_integral(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx) + +def fpIsNaN(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_nan(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsInfinite(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_infinite(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsZero(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_zero(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsNormal(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_normal(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsSubnormal(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_subnormal(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsNegative(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_negative(a.ctx_ref(), a.as_ast()), a.ctx) + +def fpIsPositive(a): + """Create a Z3 floating-point isNaN expression. + """ + if __debug__: + _z3_assert(is_fp(a), "Argument must be Z3 floating-point expressions") + return FPRef(Z3_mk_fpa_is_positive(a.ctx_ref(), a.as_ast()), a.ctx) + +def _check_fp_args(a, b): + if __debug__: + _z3_assert(is_fp(a) or is_fp(b), "At least one of the arguments must be a Z3 floating-point expression") + +def fpLT(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fpLT(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fpLT(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return BoolRef(Z3_mk_fpa_lt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpLEQ(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fpLEQ(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fpLEQ(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return BoolRef(Z3_mk_fpa_leq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpGT(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fpGT(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fpGT(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return BoolRef(Z3_mk_fpa_gt(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + + +def fpGEQ(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fp_geq(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fp_geq(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return BoolRef(Z3_mk_fpa_geq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpEQ(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fpEQ(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fpEQ(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) + +def fpNEQ(a, b): + """Create the Z3 floating-point expression `other <= self`. + + >>> x, y = FPs('x y', FPSort(8, 24)) + >>> fpNEQ(x, y) + x <= y + >>> (x <= y).sexpr() + '?' + >>> fpNEQ(x, y).sexpr() + '?' + """ + _check_fp_args(a, b) + a, b = _coerce_exprs(a, b) + return Not(BoolRef(Z3_mk_fpa_eq(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx), a.ctx) + + + +def fpFP(sgn, exp, sig): + """Create the Z3 floating-point value `fpFP(sgn, sig, exp)` from the three bit-vectorssgn, sig, and exp.""" + _z3_assert(is_bv(sgn) and is_bv(exp) and is_bv(sig), "sort mismatch") + _z3_assert(sgn.sort().size() == 1, "sort mismatch") + return FPRef(Z3_mk_fpa_fp(sgn.ctx_ref(), sgn.ast, exp.ast, sig.ast), sgn.ctx) + + +def fpToFP(a1, a2=None, a3=None): + """Create a Z3 floating-point conversion expression from other terms.""" + if is_bv(a1) and is_fp_sort(a2): + return FPRef(Z3_mk_fpa_to_fp_bv(a1.ctx_ref(), a1.ast, a2.ast), a1.ctx) + elif is_fprm(a1) and is_fp(a2) and is_fp_sort(a3): + return FPRef(Z3_mk_fpa_to_fp_float(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx) + elif is_fprm(a1) and is_real(a2) and is_fp_sort(a3): + return FPRef(Z3_mk_fpa_to_fp_real(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx) + elif is_fprm(a1) and is_bv(a2) and is_fp_sort(a3): + return FPRef(Z3_mk_fpa_to_fp_signed(a1.ctx_ref(), a1.ast, a2.ast, a3.ast), a1.ctx) + else: + raise Z3Exception("Unsupported combination of arguments for conversion to floating-point term.") + +def fpToFPUnsigned(rm, x, s): + """Create a Z3 floating-point conversion expression, from unsigned bit-vector to floating-point expression.""" + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_bv(x), "Second argument must be a Z3 bit-vector expression") + _z3_assert(is_fp_sort(s), "Third argument must be Z3 floating-point sort") + return FPRef(Z3_mk_fpa_to_fp_unsigned(rm.ctx_ref(), rm.ast, x.ast, s.ast), rm.ctx) + +def fpToSBV(rm, x, s): + """Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector.""" + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") + _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") + return FPRef(Z3_mk_fpa_to_sbv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) + +def fpToUBV(rm, x, s): + """Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector.""" + if __debug__: + _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") + _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") + _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") + return FPRef(Z3_mk_fpa_to_ubv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) + +def fpToReal(x): + """Create a Z3 floating-point conversion expression, from floating-point expression to real.""" + if __debug__: + _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") + return FPRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx) + +def fpToIEEEBV(x): + """Create a Z3 floating-point conversion expression, from floating-point expression to IEEE bit-vector.""" + if __debug__: + _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") + return FPRef(Z3_mk_fpa_to_ieee_bv(x.ctx_ref(), x.ast), x.ctx) \ No newline at end of file diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index d1d85d30e..a74a67fa8 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -8,6 +8,7 @@ import sys, io, z3 from z3consts import * from z3core import * +from ctypes import * ############################## # @@ -30,7 +31,7 @@ _z3_op_to_str = { Z3_OP_BASHR : '>>', Z3_OP_BSHL : '<<', Z3_OP_BLSHR : 'LShR', Z3_OP_CONCAT : 'Concat', Z3_OP_EXTRACT : 'Extract', Z3_OP_BV2INT : 'BV2Int', Z3_OP_ARRAY_MAP : 'Map', Z3_OP_SELECT : 'Select', Z3_OP_STORE : 'Store', - Z3_OP_CONST_ARRAY : 'K' + Z3_OP_CONST_ARRAY : 'K' } # List of infix operators @@ -45,17 +46,65 @@ _z3_unary = [ Z3_OP_UMINUS, Z3_OP_BNOT, Z3_OP_BNEG ] # Precedence _z3_precedence = { Z3_OP_POWER : 0, - Z3_OP_UMINUS : 1, Z3_OP_BNEG : 1, Z3_OP_BNOT : 1, + Z3_OP_UMINUS : 1, Z3_OP_BNEG : 1, Z3_OP_BNOT : 1, Z3_OP_MUL : 2, Z3_OP_DIV : 2, Z3_OP_IDIV : 2, Z3_OP_MOD : 2, Z3_OP_BMUL : 2, Z3_OP_BSDIV : 2, Z3_OP_BSMOD : 2, - Z3_OP_ADD : 3, Z3_OP_SUB : 3, Z3_OP_BADD : 3, Z3_OP_BSUB : 3, + Z3_OP_ADD : 3, Z3_OP_SUB : 3, Z3_OP_BADD : 3, Z3_OP_BSUB : 3, Z3_OP_BASHR : 4, Z3_OP_BSHL : 4, Z3_OP_BAND : 5, Z3_OP_BXOR : 6, Z3_OP_BOR : 7, Z3_OP_LE : 8, Z3_OP_LT : 8, Z3_OP_GE : 8, Z3_OP_GT : 8, Z3_OP_EQ : 8, Z3_OP_SLEQ : 8, Z3_OP_SLT : 8, Z3_OP_SGEQ : 8, Z3_OP_SGT : 8, - Z3_OP_IFF : 8 + Z3_OP_IFF : 8, + + Z3_OP_FPA_NEG : 1, + Z3_OP_FPA_MUL : 2, Z3_OP_FPA_DIV : 2, Z3_OP_FPA_REM : 2, Z3_OP_FPA_FMA : 2, + Z3_OP_FPA_ADD: 3, Z3_OP_FPA_SUB : 3, + Z3_OP_FPA_LE : 8, Z3_OP_FPA_LT : 8, Z3_OP_FPA_GE : 8, Z3_OP_FPA_GT : 8, Z3_OP_FPA_EQ : 8 } +# FPA operators +_z3_op_to_fpa_normal_str = { + Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RNE()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RNA()', + Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RTP()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RTN()', + Z3_OP_FPA_RM_TOWARD_ZERO : 'RTZ()', + Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo', + Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : 'PZero', Z3_OP_FPA_MINUS_ZERO : 'NZero', + Z3_OP_FPA_ADD : 'fpAdd', Z3_OP_FPA_SUB : 'fpSub', Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MUL : 'fpMul', + Z3_OP_FPA_DIV : 'fpDiv', Z3_OP_FPA_REM : 'fpRem', Z3_OP_FPA_ABS : 'fpAbs', + Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MIN : 'fpMin', Z3_OP_FPA_MAX : 'fpMax', + Z3_OP_FPA_FMA : 'fpFMA', Z3_OP_FPA_SQRT : 'fpSqrt', Z3_OP_FPA_ROUND_TO_INTEGRAL : 'fpRoundToIntegral', + + Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : 'fpLT', Z3_OP_FPA_GT : 'fpGT', Z3_OP_FPA_LE : 'fpLEQ', + Z3_OP_FPA_GE : 'fpGEQ', + + Z3_OP_FPA_IS_NAN : 'fpIsNaN', Z3_OP_FPA_IS_INF : 'fpIsInf', Z3_OP_FPA_IS_ZERO : 'fpIsZero', + Z3_OP_FPA_IS_NORMAL : 'fpIsNormal', Z3_OP_FPA_IS_SUBNORMAL : 'fpIsSubnormal', + Z3_OP_FPA_IS_NEGATIVE : 'fpIsNegative', Z3_OP_FPA_IS_POSITIVE : 'fpIsPositive', + + Z3_OP_FPA_FP : 'fpFP', Z3_OP_FPA_TO_FP : 'fpToFP', Z3_OP_FPA_TO_FP_UNSIGNED: 'fpToFPUnsigned', + Z3_OP_FPA_TO_UBV : 'fpToUBV', Z3_OP_FPA_TO_SBV : 'fpToSBV', Z3_OP_FPA_TO_REAL: 'fpToReal', + Z3_OP_FPA_TO_IEEE_BV : 'fpToIEEEBV' + } + +_z3_op_to_fpa_pretty_str = { + Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RNE()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RNA()', + Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RTP()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RTN()', + Z3_OP_FPA_RM_TOWARD_ZERO : 'RTZ()', + Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo', + Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : '+0.0', Z3_OP_FPA_MINUS_ZERO : '-0.0', + + Z3_OP_FPA_ADD : '+', Z3_OP_FPA_SUB : '-', Z3_OP_FPA_NEG : '-', Z3_OP_FPA_MUL : '*', + Z3_OP_FPA_DIV : '/', Z3_OP_FPA_REM : '%', + Z3_OP_FPA_NEG: '-', + + Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : '<', Z3_OP_FPA_GT : '>', Z3_OP_FPA_LE : '<=', Z3_OP_FPA_GE : '>=' +} + +_z3_fpa_infix = [ + Z3_OP_FPA_ADD, Z3_OP_FPA_SUB, Z3_OP_FPA_MUL, Z3_OP_FPA_DIV, Z3_OP_FPA_REM, + Z3_OP_FPA_LT, Z3_OP_FPA_GT, Z3_OP_FPA_LE, Z3_OP_FPA_GE +] + def _is_assoc(k): return k == Z3_OP_BOR or k == Z3_OP_BXOR or k == Z3_OP_BAND or k == Z3_OP_ADD or k == Z3_OP_BADD or k == Z3_OP_MUL or k == Z3_OP_BMUL @@ -134,10 +183,14 @@ _infix_map = {} _unary_map = {} _infix_compact_map = {} +for (_k,_v) in _z3_op_to_fpa_normal_str.items(): + _z3_op_to_str[_k] = _v + for _k in _z3_infix: _infix_map[_k] = True for _k in _z3_unary: _unary_map[_k] = True + for _k in _z3_infix_compact: _infix_compact_map[_k] = True @@ -463,6 +516,7 @@ class Formatter: self.precision = 10 self.ellipses = to_format(_ellipses) self.max_visited = 10000 + self.fpa_pretty = False def pp_ellipses(self): return self.ellipses @@ -499,6 +553,8 @@ class Formatter: return seq1('Array', (self.pp_sort(s.domain()), self.pp_sort(s.range()))) elif isinstance(s, z3.BitVecSortRef): return seq1('BitVec', (to_format(s.size()), )) + elif isinstance(s, z3.FPSortRef): + return seq1('FPSort', (to_format(s.ebits()), to_format(s.sbits()))) else: return to_format(s.name()) @@ -520,6 +576,118 @@ class Formatter: def pp_bv(self, a): return to_format(a.as_string()) + def pp_fprm_value(self, a): + z3._z3_assert(z3.is_fprm_value(a), 'expected FPRMNumRef') + if self.fpa_pretty and _z3_op_to_fpa_pretty_str.has_key(a.decl().kind()): + return to_format(_z3_op_to_fpa_pretty_str.get(a.decl().kind())) + else: + return to_format(a.as_string()) + + def pp_fp_value(self, a): + z3._z3_assert(isinstance(a, z3.FPNumRef), 'type mismatch') + if not self.fpa_pretty: + if (a.isNaN()): + return to_format('NaN') + elif (a.isInf()): + if (a.isNegative()): + return to_format('-oo') + else: + return to_format('+oo') + elif (a.isZero()): + if (a.isNegative()): + return to_format('-zero') + else: + return to_format('+zero') + else: + z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast') + r = [] + sgn = c_long(0) + sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) + sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) + exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast) + r.append(to_format('FPVal(')) + if not sgnb and sgn: + r.append(to_format('-')) + r.append(to_format(sig)) + r.append(to_format('*(2**')) + r.append(to_format(exp)) + r.append(to_format(', ')) + r.append(to_format(a.sort())) + r.append(to_format('))')) + return compose(r) + else: + if (a.isNaN()): + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_NAN]) + elif (a.isInf()): + if (a.isNegative()): + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_MINUS_INF]) + else: + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_PLUS_INF]) + elif (a.isZero()): + if (a.isNegative()): + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_MINUS_ZERO]) + else: + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_PLUS_ZERO]) + else: + z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast') + r = [] + sgn = c_long(0) + sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) + sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) + exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast) + if not sgnb and sgn != 0: + r.append(to_format('-')) + r.append(to_format(sig)) + if (exp != '0'): + r.append(to_format('*(2**')) + r.append(to_format(exp)) + r.append(to_format(')')) + return compose(r) + + + def pp_fp(self, a, d, xs): + z3._z3_assert(isinstance(a, z3.FPRef), "type mismatch") + k = a.decl().kind() + op = '?' + if self.fpa_pretty: + op = _z3_op_to_fpa_pretty_str.get(k, None) + if (op == None): + op = _z3_op_to_str.get(k, None) + + n = a.num_args() + + if self.fpa_pretty and self.is_infix(k) and n >= 3: + rm = a.arg(0) + if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm): + arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs)) + arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs)) + r = [] + r.append(arg1) + r.append(to_format(' ')) + r.append(to_format(op)) + r.append(to_format(' ')) + r.append(arg2) + return compose(r) + + if _z3_op_to_fpa_normal_str.has_key(k): + op = _z3_op_to_fpa_normal_str.get(k, None) + + r = [] + r.append(to_format(op)) + if not z3.is_const(a): + r.append(to_format('(')) + first = True + for c in a.children(): + if first: + first = False + else: + r.append(to_format(', ')) + r.append(self.pp_expr(c, d+1, xs)) + r.append(to_format(')')) + return compose(r) + else: + return to_format(a.as_string()) + def pp_prefix(self, a, d, xs): r = [] sz = 0 @@ -678,9 +846,15 @@ class Formatter: elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): - return self.pp_algebraic(a) + return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) + elif z3.is_fprm_value(a): + return self.pp_fprm_value(a) + elif z3.is_fp_value(a): + return self.pp_fp_value(a) + elif z3.is_fp(a): + return self.pp_fp(a, d, xs) elif z3.is_const(a): return self.pp_const(a) else: @@ -939,6 +1113,12 @@ def set_pp_option(k, v): else: set_html_mode(False) return True + if k == 'fpa_pretty': + if v: + set_fpa_pretty(True) + else: + set_fpa_pretty(False) + return True val = getattr(_PP, k, None) if val != None: z3._z3_assert(type(v) == type(val), "Invalid pretty print option value") @@ -965,6 +1145,23 @@ def set_html_mode(flag=True): else: _Formatter = Formatter() +def set_fpa_pretty(flag=True): + global _Formatter + global _z3_op_to_str + _Formatter.fpa_pretty = flag + if flag: + for (_k,_v) in _z3_op_to_fpa_pretty_str.items(): + _z3_op_to_str[_k] = _v + for _k in _z3_fpa_infix: + _infix_map[_k] = True + else: + for (_k,_v) in _z3_op_to_fpa_normal_str.items(): + _z3_op_to_str[_k] = _v + for _k in _z3_fpa_infix: + _infix_map[_k] = False + + + def in_html_mode(): return isinstance(_Formatter, HTMLFormatter) From d4ecc3c1be6f3fe4ecd1e018581795cbcdd98573 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 15:59:20 +0000 Subject: [PATCH 170/646] Disabled BV-SLS as default tactic in anticipation for integration with the unstable branch. Signed-off-by: Christoph M. Wintersteiger --- src/tactic/portfolio/default_tactic.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 53da9a159..5a5cbcf94 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -32,8 +32,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), - // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), From 66abc1c65eae3cec95d362ae849e689ce6d2113a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 17:03:27 +0000 Subject: [PATCH 171/646] Removed unnecessary file Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Properties/AssemblyInfo.cs | 38 ----------------------- 1 file changed, 38 deletions(-) delete mode 100644 src/api/dotnet/Properties/AssemblyInfo.cs diff --git a/src/api/dotnet/Properties/AssemblyInfo.cs b/src/api/dotnet/Properties/AssemblyInfo.cs deleted file mode 100644 index ee0e3f354..000000000 --- a/src/api/dotnet/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Security.Permissions; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Z3 .NET Interface")] -[assembly: AssemblyDescription(".NET Interface to the Z3 Theorem Prover")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft Corporation")] -[assembly: AssemblyProduct("Z3")] -[assembly: AssemblyCopyright("Copyright © Microsoft Corporation 2006")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4853ed71-2078-40f4-8117-bc46646bce0e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("4.2.0.0")] -[assembly: AssemblyVersion("4.3.2.0")] -[assembly: AssemblyFileVersion("4.3.2.0")] From 40014d019ca8e656a3bc1e6c2966b716e597cc99 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 11 Feb 2014 17:44:59 +0000 Subject: [PATCH 172/646] sls tactic default --- src/tactic/portfolio/smt_strategic_solver.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index ae79446e3..52b0a3c90 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,11 +37,13 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" +#include"sls_tactic.h" + tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - return mk_qfbv_tactic(m, p); + return mk_qfbv_sls_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") From b002697e038554d0986fc974ed81bf2da0a62727 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 18 Feb 2014 14:01:47 +0000 Subject: [PATCH 173/646] some extensions/modifications. versions added. --- src/tactic/portfolio/default_tactic.cpp | 3 +- src/tactic/sls/sls_evaluator.h | 4 +- src/tactic/sls/sls_tactic.cpp | 146 ++++++++++++-- src/tactic/sls/sls_tracker.h | 249 +++++++++++++++++++++--- versions/z3-crsat-0.01.txt | 12 ++ versions/z3-gsat-0.01.txt | 10 + versions/z3-gsat-res-0.01.txt | 10 + versions/z3-wsat-0.01.txt | 12 ++ versions/z3-wsat-0.01b.txt | 12 ++ versions/z3-wsat-0.01c.txt | 12 ++ versions/z3-wsat-0.01d.txt | 11 ++ versions/z3-wsat-0.01e.txt | 11 ++ versions/z3-wsat-0.02.txt | 13 ++ versions/z3-wsat-res-0.01.txt | 13 ++ 14 files changed, 470 insertions(+), 48 deletions(-) create mode 100644 versions/z3-crsat-0.01.txt create mode 100644 versions/z3-gsat-0.01.txt create mode 100644 versions/z3-gsat-res-0.01.txt create mode 100644 versions/z3-wsat-0.01.txt create mode 100644 versions/z3-wsat-0.01b.txt create mode 100644 versions/z3-wsat-0.01c.txt create mode 100644 versions/z3-wsat-0.01d.txt create mode 100644 versions/z3-wsat-0.01e.txt create mode 100644 versions/z3-wsat-0.02.txt create mode 100644 versions/z3-wsat-res-0.01.txt diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 9ecc16ecf..b28b7bec0 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -28,10 +28,11 @@ Notes: #include"probe_arith.h" #include"quant_tactics.h" #include"qffpa_tactic.h" +#include"sls_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 77ff50454..61305386e 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -584,8 +584,8 @@ public: run_update(cur_depth); } - void randomize_local(goal_ref const & g) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); + void randomize_local(goal_ref const & g, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); // Randomize _all_ candidates: diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 6783d9621..c194af267 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -35,6 +35,17 @@ Notes: #include"sls_tactic.h" #include"nnf_tactic.h" +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 30 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 +#define _VNS_ 0 +#define _WEIGHT_DIST_ 3 +#define _WEIGHT_DIST_FACTOR_ 0.1 + #include"sls_params.hpp" #include"sls_evaluator.h" #include"sls_tracker.h" @@ -257,7 +268,7 @@ class sls_tactic : public tactic { // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g); + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; @@ -303,6 +314,82 @@ class sls_tactic : public tactic { m_mpz_manager.del(new_value); } + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -372,22 +459,29 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - while (plateau_cnt < m_plateau_limit) { - + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif do { checkpoint(); old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); - +#endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; for (unsigned i = 0; i < g->size(); i++) { @@ -400,9 +494,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -441,6 +537,7 @@ class sls_tactic : public tactic { if (score >= 1.0) { // score could theoretically be imprecise. + // Andreas: Can it only be imprecise in one direction? bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -451,19 +548,30 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - if (score != old_score) + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - else { + } else { + m_stats.m_moves++; plateau_cnt++; - if (plateau_cnt < m_plateau_limit) { + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); - m_evaluator.randomize_local(g); + m_evaluator.randomize_local(g, m_stats.m_moves); //mk_random_move(g); score = top_score(g); - } + //} } } @@ -484,7 +592,8 @@ class sls_tactic : public tactic { do { checkpoint(); - if ((m_stats.m_restarts % 100) == 0) + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + //if ((m_stats.m_restarts % 100) == 0) report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); res = search(g); @@ -492,9 +601,12 @@ class sls_tactic : public tactic { if (res == l_undef) m_tracker.randomize(); } - while (res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - if (res == l_true) { + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -628,7 +740,13 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), +#if _CNF_ + // Andreas: We will probably never use this. CNF sucks. + mk_cnf_tactic(m, p)); +#else + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); +#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7fbafec60..1061bd90e 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -28,8 +28,8 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; - + mpz m_zero, m_one, m_two; + struct value_score { value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; ~value_score() { if (m) m->del(value); } @@ -249,12 +249,46 @@ public: } } - void initialize(goal_ref const & g) { + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } + + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; + m_constants_occ.insert_if_not_there(e, t); + find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); + expr_fast_mark1 visited; + quick_for_each_expr(ffd_proc, visited, e); + } + + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(proc, visited, e); +#endif for_each_expr(proc, visited, e); } @@ -262,6 +296,10 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(e); +#endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -382,8 +420,6 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } -#define _SCORE_AND_MIN - double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -400,30 +436,41 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - #ifdef _SCORE_AND_MIN - double min = 1.0; + // Andreas: Seems to have no effect. Probably it does not even occur. +#if _SCORE_AND_AVG_ + double sum = 0.0; + for (unsigned i = 0; i < a->get_num_args(); i++) + sum += get_score(args[i]); + res = sum / (double) a->get_num_args(); +#else + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; } res = min; - #else - double sum = 0.0; - for (unsigned i = 0; i < a->get_num_args(); i++) - sum += get_score(args[i]); - res = sum / (double) a->get_num_args(); - #endif +#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - double max = 0.0; + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. +#if _SCORE_OR_MUL_ + double inv = 1.0; + for (unsigned i = 0; i < a->get_num_args(); i++) { + double cur = get_score(args[i]); + inv *= (1.0 - get_score(args[i])); + } + res = 1.0 - inv; +#else + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; } res = max; +#endif } else if (m_manager.is_ite(n)) { SASSERT(!negated); @@ -468,7 +515,7 @@ public: } m_mpz_manager.machine_div(diff, m_two, diff); } - res = 1.0 - (hamming_distance / (double) bv_sz); + res = 1.0 - (hamming_distance / (double) bv_sz); #else rational r(diff); r /= m_powers(bv_sz); @@ -503,7 +550,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -564,7 +611,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -598,6 +645,20 @@ public: SASSERT(res >= 0.0 && res <= 1.0); +#if _WEIGHT_DIST_ + app * a = to_app(n); + family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) +#endif +#if _WEIGHT_DIST_ == 1 + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#elif _WEIGHT_DIST_ == 2 + res *= res; +#elif _WEIGHT_DIST_ == 3 + if (res < 1.0) res = 0.0; +#endif + + TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } @@ -647,7 +708,111 @@ public: NOT_IMPLEMENTED_YET(); } - ptr_vector & get_unsat_constants(goal_ref const & g) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + for (unsigned i = 0; i < sz; i++) { + expr * q = g->form(i); + if (m_mpz_manager.eq(get_value(q), m_one)) + continue; + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + return m_temp_constants; + } + + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } + + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. + if (!q) + return m_temp_constants; + + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + if (!q) + return m_temp_constants; + + return go_deeper(q); + } + + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { @@ -655,19 +820,41 @@ public: } else { m_temp_constants.reset(); - for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); - if (m_mpz_manager.eq(get_value(q), m_one)) - continue; - ptr_vector const & this_decls = m_constants_occ.find(q); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } +#if _FOCUS_ == 1 +#if _BFS_ == 3 + unsigned int pos = 0; + double max = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - return m_temp_constants; +#elif _BFS_ == 2 + unsigned int pos = 0; + double min = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } +#elif _BFS_ == 1 + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_walksat(g, sz, pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_crsat(g, sz, pos); +#else + return get_unsat_constants_gsat(g, sz); +#endif } } }; diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt new file mode 100644 index 000000000..49e1a1525 --- /dev/null +++ b/versions/z3-crsat-0.01.txt @@ -0,0 +1,12 @@ +More focused (_FOCUS_ == 2) WalkSAT version. +Variables are chosen among candidates in only one unsatisfied bit-vector term. +Flip rate slightly slower; probably due to larger hash-table and recursive formula structure. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 3 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt new file mode 100644 index 000000000..eb806a67f --- /dev/null +++ b/versions/z3-gsat-0.01.txt @@ -0,0 +1,10 @@ +Basic GSAT version. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 0 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt new file mode 100644 index 000000000..6a211f2bc --- /dev/null +++ b/versions/z3-gsat-res-0.01.txt @@ -0,0 +1,10 @@ +Basic GSAT version corresponding to Christoph's original code. +Restarts after 100 plateaus. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 0 +#define _RESTARTS_ 1 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt new file mode 100644 index 000000000..141193f76 --- /dev/null +++ b/versions/z3-wsat-0.01.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Flip rate increased by roughly 10%-300%. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt new file mode 100644 index 000000000..2c0c0e7ad --- /dev/null +++ b/versions/z3-wsat-0.01b.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0). +No restarts. + +#define _CNF_ 0 +#define _BFS_ 0 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt new file mode 100644 index 000000000..223560e08 --- /dev/null +++ b/versions/z3-wsat-0.01c.txt @@ -0,0 +1,12 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +AND is scored by average; OR is scored by inverse multiplication. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 1 +#define _SCORE_OR_MUL_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt new file mode 100644 index 000000000..072191370 --- /dev/null +++ b/versions/z3-wsat-0.01d.txt @@ -0,0 +1,11 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 2 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt new file mode 100644 index 000000000..b018c5e0d --- /dev/null +++ b/versions/z3-wsat-0.01e.txt @@ -0,0 +1,11 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 3 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt new file mode 100644 index 000000000..34dcb157c --- /dev/null +++ b/versions/z3-wsat-0.02.txt @@ -0,0 +1,13 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Score function reduced to 0/1. +No restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 +#define _WEIGHTED_DIST_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt new file mode 100644 index 000000000..575180a59 --- /dev/null +++ b/versions/z3-wsat-res-0.01.txt @@ -0,0 +1,13 @@ +Basic WalkSAT version. +Variables are chosen among candidates in only ONE top level assertion. +Flip rate increased by roughly 10%-300% compared to GSAT. +Restarts after 100 plateaus. +Fps slightly decreased due to restarts. + +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 1 +#define _TIMELIMIT_ 300 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 \ No newline at end of file From e310ab5cd793d16e8a37e1a76023b5c477e2fb2e Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 9 Mar 2014 15:42:51 +0000 Subject: [PATCH 174/646] plenty of new stuff --- src/sat/tactic/sat_tactic.cpp | 4 +- src/tactic/portfolio/default_tactic.cpp | 1 + src/tactic/portfolio/smt_strategic_solver.cpp | 1 + src/tactic/sls/sls_evaluator.h | 323 ++++++++- src/tactic/sls/sls_tactic.cpp | 661 ++++++++++++++++-- src/tactic/sls/sls_tracker.h | 345 ++++++++- versions/z3-wsat-0.01.txt | 4 +- versions/z3-wsat-0.01b.txt | 4 +- 8 files changed, 1235 insertions(+), 108 deletions(-) diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index d48994861..717bf7007 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -66,7 +66,9 @@ class sat_tactic : public tactic { CASSERT("sat_solver", m_solver.check_invariant()); IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream());); TRACE("sat_dimacs", m_solver.display_dimacs(tout);); - + //m_solver.display_dimacs(std::cerr); + //exit(0); + lbool r = m_solver.check(); if (r == l_false) { g->assert_expr(m.mk_false(), 0, 0); diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index b28b7bec0..53da9a159 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -33,6 +33,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), + // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 52b0a3c90..f63b4fd8c 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -43,6 +43,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") + // return mk_qfbv_tactic(m, p); return mk_qfbv_sls_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 61305386e..eec9524a9 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -34,6 +34,9 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; +#if _EARLY_PRUNE_ + vector > m_traversal_stack_bool; +#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -519,11 +522,15 @@ public: } } - void run_update(unsigned cur_depth) { + void run_serious_update(unsigned cur_depth) { // precondition: m_traversal_stack contains the entry point(s) expr_fast_mark1 visited; mpz new_value; +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -533,8 +540,92 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - m_tracker.set_score(cur, m_tracker.score(cur)); +#if _REAL_RS_ || _REAL_PBFS_ + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } +#endif + +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + void run_update(unsigned cur_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -569,8 +660,11 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } - +#if _REAL_RS_ || _REAL_PBFS_ + run_serious_update(max_depth); +#else run_update(max_depth); +#endif } void update(func_decl * fd, const mpz & new_value) { @@ -584,6 +678,196 @@ public: run_update(cur_depth); } + void serious_update(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + m_traversal_stack[cur_depth].push_back(ep); + + run_serious_update(cur_depth); + } + +#if _EARLY_PRUNE_ + unsigned run_update_bool_prune(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + void run_update_prune(unsigned max_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + + unsigned cur_depth = max_depth; + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); + // should always have uplinks ... + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + unsigned update_prune(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); + } +#endif + + void randomize_local(expr * e, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_constants(e); + + // Randomize _one_ candidate: + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + update(fd, temp); + m_mpz_manager.del(temp); + } + void randomize_local(goal_ref const & g, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); @@ -603,8 +887,37 @@ public: // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; - mpz temp = m_tracker.get_random(fd->get_range()); - update(fd, temp); +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + +#if _REAL_RS_ || _REAL_PBFS_ + serious_update(fd, temp); +#else + update(fd, temp); +#endif m_mpz_manager.del(temp); TRACE("sls", /*tout << "Randomization candidates: "; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index c194af267..a08588a51 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -35,16 +35,102 @@ Notes: #include"sls_tactic.h" #include"nnf_tactic.h" -#define _CNF_ 0 -#define _BFS_ 1 +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 + +// do we use restarts? +// 0 = no, otherwise the value defines the maximum number of moves #define _RESTARTS_ 0 -#define _TIMELIMIT_ 30 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? #define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? #define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 -#define _WEIGHT_DIST_ 3 -#define _WEIGHT_DIST_FACTOR_ 0.1 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 0 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 0 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 0.01 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +#define _PROBABILISTIC_UCT_ 0 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 1 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 1 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 1 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 1 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) + InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) + InvalidConfiguration; +#endif + #include"sls_params.hpp" #include"sls_evaluator.h" @@ -57,12 +143,17 @@ class sls_tactic : public tactic { stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -92,7 +183,9 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : m_manager(m), @@ -174,13 +267,20 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - top_sum += m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + return top_sum / (double) sz; #endif } @@ -191,22 +291,54 @@ class sls_tactic : public tactic { return top_score(g); } - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else return top_score(g); +#endif } + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; + } +#endif + + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { - + #ifdef Z3DEBUG mpz old_value; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else double r = incremental_score(g, fd, temp); - +#endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl; ); @@ -214,6 +346,22 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); #endif +// if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // same as what_if, but only applied to the score of a specific atom, not the total score + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -224,7 +372,35 @@ class sls_tactic : public tactic { return false; } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + + } + + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + } + + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -261,59 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + if (m_stats.m_moves > 10000) + rnd_mv = 0; ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; - unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range()); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + mpz new_value; - m_evaluator.update(fd, new_value); + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; - m_mpz_manager.del(new_value); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } + + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -359,6 +549,7 @@ class sls_tactic : public tactic { SASSERT(check == score); } + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else @@ -390,9 +581,13 @@ class sls_tactic : public tactic { return new_score; } + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif unsigned bv_sz; double new_score = score; @@ -403,8 +598,12 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // first try to flip every bit - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { - // What would happen if we flipped bit #i ? +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -414,7 +613,8 @@ class sls_tactic : public tactic { } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -426,16 +626,99 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } - +#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif } // reset to what it was before double check = incremental_score(g, fd, old_value); - SASSERT(check == score); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; + } + + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -443,7 +726,150 @@ class sls_tactic : public tactic { return new_score; } - lbool search(goal_ref const & g) { + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + + m_old_values.reset(); + + return 0; + } + + // what_if version needed in the context of 2nd intensification try, combining local and global score + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // find_best_move version needed in the context of 2nd intensification try + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) + { + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; + } + + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; + } + + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -463,16 +889,48 @@ class sls_tactic : public tactic { #if _RESTARTS_ while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { + if (m_stats.m_moves == 5590) checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif old_score = score; new_const = (unsigned)-1; ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -525,9 +983,17 @@ class sls_tactic : public tactic { case MV_INC: m_stats.m_incs++; break; case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - score = incremental_score(g, fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif TRACE("sls", tout << "Score distribution:"; for (unsigned i = 0; i < g->size(); i++) @@ -535,9 +1001,10 @@ class sls_tactic : public tactic { tout << " TOP: " << score << std::endl; ); } - if (score >= 1.0) { + if (score >= 0.99999) { +// if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: Can it only be imprecise in one direction? + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -568,10 +1035,26 @@ class sls_tactic : public tactic { // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else m_evaluator.randomize_local(g, m_stats.m_moves); - //mk_random_move(g); +#endif + //mk_random_move(g); score = top_score(g); - //} + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } } } @@ -587,6 +1070,37 @@ class sls_tactic : public tactic { return; } + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif m_tracker.initialize(g); lbool res = l_undef; @@ -740,13 +1254,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), -#if _CNF_ - // Andreas: We will probably never use this. CNF sucks. - mk_cnf_tactic(m, p)); -#else // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); -#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1061bd90e..b26912e5c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -28,21 +28,32 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; + mpz m_zero, m_one, m_two; struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; +#if _EARLY_PRUNE_ + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; +#else + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; +#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; +#if _EARLY_PRUNE_ + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; +#endif unsigned distance; // max distance from any root + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; + touched = other.touched; return *this; } }; @@ -60,6 +71,20 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; +#if _UCT_ + unsigned m_touched; +#endif +#if _REAL_RS_ || _REAL_PBFS_ + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; +#endif +#if _CACHE_TOP_SCORE_ + double m_top_sum; +#endif +#if _WEIGHT_DIST_ == 4 + double m_weight_dist_factor; +#endif public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -79,6 +104,26 @@ public: m_mpz_manager.del(m_two); } +#if _WEIGHT_DIST_ == 4 + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } +#endif + +#if _CACHE_TOP_SCORE_ + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } + + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } + + inline double get_top_sum() { + return m_top_sum; + } +#endif + inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); m_mpz_manager.set(m_scores.find(n).value, r); @@ -123,6 +168,28 @@ public: return get_score(ep); } +#if _EARLY_PRUNE_ + inline void set_score_prune(expr * n, double score) { + SASSERT(m_scores.contains(n)); + m_scores.find(n).score_prune = score; + } + + inline double & get_score_prune(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).score_prune; + } + + inline unsigned has_pos_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_pos_occ; + } + + inline unsigned has_neg_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_neg_occ; + } +#endif + inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).distance; @@ -297,7 +364,7 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 +#if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); #endif ptr_vector t; @@ -310,8 +377,57 @@ public: calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); + +#if _REAL_RS_ || _REAL_PBFS_ + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); +#endif + +#if _EARLY_PRUNE_ + for (unsigned i = 0; i < sz; i++) + setup_occs(g->form(i)); +#endif + +#if _UCT_ + m_touched = 1; +#endif } +#if _REAL_RS_ || _REAL_PBFS_ + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } + + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } +#endif + void show_model(std::ostream & out) { unsigned sz = get_num_constants(); for (unsigned i = 0; i < sz; i++) { @@ -420,10 +536,45 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } +#if _EARLY_PRUNE_ + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } + else + NOT_IMPLEMENTED_YET(); + } +#endif + double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -488,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -648,6 +799,7 @@ public: #if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 @@ -656,13 +808,14 @@ public: res *= res; #elif _WEIGHT_DIST_ == 3 if (res < 1.0) res = 0.0; +#elif _WEIGHT_DIST_ == 4 + if (res < 1.0) res *= m_weight_dist_factor; #endif - TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -708,6 +861,44 @@ public: NOT_IMPLEMENTED_YET(); } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } + + ptr_vector & get_constants(expr * e) { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); @@ -743,7 +934,6 @@ public: // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { @@ -754,6 +944,19 @@ public: return m_temp_constants; } + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned j = 0; j < sz; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & go_deeper(expr * e) { if (m_manager.is_bool(e)) { if (m_manager.is_and(e)) { @@ -812,44 +1015,138 @@ public: return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 -#if _BFS_ == 3 - unsigned int pos = 0; - double max = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return m_temp_constants; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif + expr * e = g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = 0; - double min = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(g, sz, pos); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif return get_unsat_constants_crsat(g, sz, pos); #else diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt index 141193f76..fec38518d 100644 --- a/versions/z3-wsat-0.01.txt +++ b/versions/z3-wsat-0.01.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt index 2c0c0e7ad..8bcf2ffeb 100644 --- a/versions/z3-wsat-0.01b.txt +++ b/versions/z3-wsat-0.01b.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file From e33e637ad8b08528593f685f29f0dfec2015ce42 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 09:40:01 +0000 Subject: [PATCH 175/646] removed tabs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_evaluator.h | 268 ++++++------- src/tactic/sls/sls_tactic.cpp | 572 ++++++++++++++-------------- src/tactic/sls/sls_tracker.h | 672 ++++++++++++++++----------------- 3 files changed, 756 insertions(+), 756 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index eec9524a9..cdb08038f 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -528,7 +528,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -542,33 +542,33 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) - { - if (m_mpz_manager.eq(new_value,m_one)) - m_tracker.make_assertion(cur); - else - m_tracker.break_assertion(cur); - } + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } #endif #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -596,7 +596,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -609,23 +609,23 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -661,7 +661,7 @@ public: if (cur_depth > max_depth) max_depth = cur_depth; } #if _REAL_RS_ || _REAL_PBFS_ - run_serious_update(max_depth); + run_serious_update(max_depth); #else run_update(max_depth); #endif @@ -693,27 +693,27 @@ public: unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { expr * cur = cur_depth_exprs[i]; - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - prune_score = m_tracker.get_score_prune(cur); + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); - if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -722,54 +722,54 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); + m_traversal_stack_bool[next_d].push_back(next); visited.mark(next); } } } - else - { - } - } + else + { + } + } - cur_depth_exprs.reset(); + cur_depth_exprs.reset(); cur_depth--; - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } - return pot_benefits; + return pot_benefits; } void run_update_prune(unsigned max_depth) { @@ -777,7 +777,7 @@ public: expr_fast_mark1 visited; mpz new_value; - unsigned cur_depth = max_depth; + unsigned cur_depth = max_depth; SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -787,7 +787,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // should always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -795,10 +795,10 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - if (m_manager.is_bool(next)) - m_traversal_stack_bool[max_depth].push_back(next); - else - m_traversal_stack[next_d].push_back(next); + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); visited.mark(next); } } @@ -817,23 +817,23 @@ public: expr * ep = m_tracker.get_entry_point(fd); unsigned cur_depth = m_tracker.get_distance(ep); - if (m_traversal_stack_bool.size() <= cur_depth) + if (m_traversal_stack_bool.size() <= cur_depth) m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune(cur_depth); + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); } #endif - void randomize_local(expr * e, unsigned int flip) { + void randomize_local(expr * e, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_constants(e); // Randomize _one_ candidate: @@ -841,30 +841,30 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif - update(fd, temp); + update(fd, temp); m_mpz_manager.del(temp); } @@ -889,34 +889,34 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif #if _REAL_RS_ || _REAL_PBFS_ - serious_update(fd, temp); + serious_update(fd, temp); #else - update(fd, temp); + update(fd, temp); #endif m_mpz_manager.del(temp); diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index a08588a51..553acc35a 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -125,10 +125,10 @@ Notes: #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) - InvalidConfiguration; + InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; + InvalidConfiguration; #endif @@ -150,10 +150,10 @@ class sls_tactic : public tactic { m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -183,8 +183,8 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - ptr_vector m_old_values; - + ptr_vector m_old_values; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : @@ -267,18 +267,18 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); #if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); + m_tracker.set_top_sum(top_sum); #endif return top_sum / (double) sz; @@ -292,20 +292,20 @@ class sls_tactic : public tactic { } double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif } double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif @@ -314,18 +314,18 @@ class sls_tactic : public tactic { #if _EARLY_PRUNE_ double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) + if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(g); + return top_score(g); #endif - else - return 0.0; + else + return 0.0; } #endif - // checks whether the score outcome of a given move is better than the previous score + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { @@ -357,11 +357,11 @@ class sls_tactic : public tactic { return false; } - // same as what_if, but only applied to the score of a specific atom, not the total score + // same as what_if, but only applied to the score of a specific atom, not the total score bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -378,29 +378,29 @@ class sls_tactic : public tactic { m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); - } + } - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { mpz temp, mask, mask2; m_mpz_manager.mul(old_value, m_two, temp); m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); } void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { m_mpz_manager.div(old_value, m_two, result); } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -437,73 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; + if (m_stats.m_moves > 10000) + rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; + mpz new_value; - sort * srt = fd->get_range(); + sort * srt = fd->get_range(); if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { #if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + mt = MV_FLIP; #endif - unsigned bit = 0; + unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } - // will use VNS to ignore some possible moves and increase the flips per second + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -514,7 +514,7 @@ class sls_tactic : public tactic { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -536,12 +536,12 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } } // reset to what it was before @@ -549,12 +549,12 @@ class sls_tactic : public tactic { SASSERT(check == score); } - // we can either check the condition once in the beginning or check it repeatedly after every bit + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) #endif for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { func_decl * fd = to_evaluate[i]; @@ -563,30 +563,30 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } // reset to what it was before double check = incremental_score(g, fd, old_value); SASSERT(check == score); } - m_mpz_manager.del(old_value); + m_mpz_manager.del(old_value); m_mpz_manager.del(temp); return new_score; } - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; + mpz temp2; #endif unsigned bv_sz; double new_score = score; @@ -599,11 +599,11 @@ class sls_tactic : public tactic { // first try to flip every bit #if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { #endif - // What would happen if we flipped bit #i ? + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -614,7 +614,7 @@ class sls_tactic : public tactic { if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { #if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -660,7 +660,7 @@ class sls_tactic : public tactic { // reset to what it was before double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching + // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -669,17 +669,17 @@ class sls_tactic : public tactic { #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif - return new_score; + return new_score; } - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -718,7 +718,7 @@ class sls_tactic : public tactic { } // reset to what it was before - m_evaluator.update(fd, old_value); + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -726,37 +726,37 @@ class sls_tactic : public tactic { return new_score; } - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); #if _BFS_ - unsigned pos = m_stats.m_moves % sz; + unsigned pos = m_stats.m_moves % sz; #else - unsigned pos = m_tracker.get_random_uint(16) % sz; + unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); } else { m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -767,35 +767,35 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); } - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - m_old_values.reset(); + m_old_values.reset(); - return 0; - } + return 0; + } - // what_if version needed in the context of 2nd intensification try, combining local and global score + // what_if version needed in the context of 2nd intensification try, combining local and global score bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, double & best_score, mpz & best_value, unsigned i) { double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); + double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - if (new_score >= best_score) { + if (new_score >= best_score) { best_score = new_score; m_mpz_manager.set(best_value, temp); return true; @@ -804,17 +804,17 @@ class sls_tactic : public tactic { return false; } - // find_best_move version needed in the context of 2nd intensification try + // find_best_move version needed in the context of 2nd intensification try double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; + { + mpz old_value, temp; double best_score = 0; sort * srt = fd->get_range(); unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); what_if(g, e, fd, temp, best_score, best_value, i); } @@ -822,54 +822,54 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - return best_score; + return best_score; } - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); #if _BFS_ - unsigned new_const = m_stats.m_moves % sz; + unsigned new_const = m_stats.m_moves % sz; #else - unsigned new_const = m_tracker.get_random_uint(16) % sz; + unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - return 0; - } + return 0; + } - // main search loop - lbool search(goal_ref const & g) { + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -885,52 +885,52 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - // Andreas: Why do we only allow so few plateaus? + // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) + if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif #if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { #if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #elif _TYPE_RSTEP_ == 2 - mk_random_move(g); + mk_random_move(g); #endif score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } #endif old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -952,11 +952,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { - // Andreas: Why does randomizing not count as a move? (Now it does.) + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -984,15 +984,15 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; @@ -1004,7 +1004,7 @@ class sls_tactic : public tactic { if (score >= 0.99999) { // if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -1015,43 +1015,43 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - } else { - m_stats.m_moves++; + } else { + m_stats.m_moves++; plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); #if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); + handle_plateau(g, score); + //handle_plateau(g); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(g); + //mk_random_move(g); score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } @@ -1070,43 +1070,43 @@ class sls_tactic : public tactic { return; } - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif m_tracker.initialize(g); lbool res = l_undef; do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... //if ((m_stats.m_restarts % 100) == 0) report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); @@ -1115,12 +1115,12 @@ class sls_tactic : public tactic { if (res == l_undef) m_tracker.randomize(); } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); + report_tactic_progress("Number of flips:", m_stats.m_moves); if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1254,7 +1254,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index b26912e5c..006bbb888 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -29,31 +29,31 @@ class sls_tracker { unsigned m_random_bits; unsigned m_random_bits_cnt; mpz m_zero, m_one, m_two; - + struct value_score { #if _EARLY_PRUNE_ - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; #else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; #endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; #if _EARLY_PRUNE_ - double score_prune; - unsigned has_pos_occ; - unsigned has_neg_occ; + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; #endif unsigned distance; // max distance from any root - unsigned touched; + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; - touched = other.touched; + touched = other.touched; return *this; } }; @@ -72,18 +72,18 @@ private: ptr_vector m_temp_constants; occ_type m_constants_occ; #if _UCT_ - unsigned m_touched; + unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; + double m_weight_dist_factor; #endif public: @@ -105,23 +105,23 @@ public: } #if _WEIGHT_DIST_ == 4 - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } #endif #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { - m_top_sum += add - sub; - } + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } - inline void set_top_sum(double new_score) { - m_top_sum = new_score; - } + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } - inline double get_top_sum() { - return m_top_sum; - } + inline double get_top_sum() { + return m_top_sum; + } #endif inline void set_value(expr * n, const mpz & r) { @@ -174,20 +174,20 @@ public: m_scores.find(n).score_prune = score; } - inline double & get_score_prune(expr * n) { + inline double & get_score_prune(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).score_prune; } - inline unsigned has_pos_occ(expr * n) { + inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } - inline unsigned has_neg_occ(expr * n) { + inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -316,45 +316,45 @@ public: } } - void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(proc, visited, q); - } - } - for_each_expr(proc, visited, e); - } + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } - void initialize_recursive(expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(q); - } - } - ptr_vector t; + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } - void initialize(goal_ref const & g) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); + initialize_recursive(proc, visited, e); #endif for_each_expr(proc, visited, e); } @@ -363,9 +363,9 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); + initialize_recursive(e); #endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); @@ -379,53 +379,53 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); #if _REAL_RS_ || _REAL_PBFS_ - m_list_false = new expr*[sz]; + m_list_false = new expr*[sz]; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = 1; #endif } #if _REAL_RS_ || _REAL_PBFS_ - void make_assertion(expr * e) - { - if (m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) - { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - } -// printf("Going in %d\n", m_where_false.size()); - } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); - } + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } - void break_assertion(expr * e) - { - if (!m_where_false.contains(e)) - { - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); - } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); - } + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } #endif void show_model(std::ostream & out) { @@ -537,35 +537,35 @@ public: } #if _EARLY_PRUNE_ - void setup_occs(expr * n, bool negated = false) { - if (m_manager.is_bool(n)) - { - if (m_manager.is_and(n) || m_manager.is_or(n)) - { - SASSERT(!negated); - app * a = to_app(n); - expr * const * args = a->get_args(); - for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); - } - else if (m_manager.is_not(n)) - { - SASSERT(!negated); - app * a = to_app(n); - SASSERT(a->get_num_args() == 1); - expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); - setup_occs(child, true); - } - else - { - if (negated) - m_scores.find(n).has_neg_occ = 1; - else - m_scores.find(n).has_pos_occ = 1; - } - } + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } else NOT_IMPLEMENTED_YET(); } @@ -574,7 +574,7 @@ public: double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -587,14 +587,14 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. + // Andreas: Seems to have no effect. Probably it does not even occur. #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) sum += get_score(args[i]); res = sum / (double) a->get_num_args(); #else - double min = 1.0; + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; @@ -606,16 +606,16 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. #if _SCORE_OR_MUL_ - double inv = 1.0; + double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else - double max = 0.0; + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; @@ -639,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -701,7 +701,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -762,7 +762,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -797,25 +797,25 @@ public: SASSERT(res >= 0.0 && res <= 1.0); #if _WEIGHT_DIST_ - app * a = to_app(n); - family_id afid = a->get_family_id(); + app * a = to_app(n); + family_id afid = a->get_family_id(); - if (afid == m_bv_util.get_family_id()) + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; #elif _WEIGHT_DIST_ == 2 - res *= res; + res *= res; #elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; + if (res < 1.0) res = 0.0; #elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; + if (res < 1.0) res *= m_weight_dist_factor; #endif TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -861,34 +861,34 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } - ptr_vector & get_constants(expr * e) { + ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned i = 0; i < sz; i++) { @@ -897,9 +897,9 @@ public: m_temp_constants.push_back(fd); } return m_temp_constants; - } + } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -913,244 +913,244 @@ public: } } return m_temp_constants; - } + } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; + return q; } - return 0; - } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); + if (!q) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned j = 0; j < sz; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) - return m_temp_constants; + return m_temp_constants; - return go_deeper(q); - } + return go_deeper(q); + } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) - return m_temp_constants; - else - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 #if _UCT_ - unsigned pos = -1; - value_score vscore; + unsigned pos = -1; + value_score vscore; #if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } #else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - vscore = m_scores.find(e); + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); #elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } #endif - if (pos == static_cast(-1)) - return m_temp_constants; + if (pos == static_cast(-1)) + return m_temp_constants; #if _UCT_ == 1 - m_scores.find(g->form(pos)).touched++; - m_touched++; + m_scores.find(g->form(pos)).touched++; + m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = g->form(pos); + expr * e = g->form(pos); #elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; + unsigned int pos = -1; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; + unsigned int pos = -1; + double min = 2.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); #elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(e); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif - return get_unsat_constants_crsat(g, sz, pos); + return get_unsat_constants_crsat(g, sz, pos); #else - return get_unsat_constants_gsat(g, sz); + return get_unsat_constants_gsat(g, sz); #endif } } From aa6f8a4b8a1cb68933b420f053b487971dfb2d28 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 19 Mar 2014 11:49:44 +0000 Subject: [PATCH 176/646] Current version for relocating. --- src/tactic/sls/sls_evaluator.h | 92 +++++----- src/tactic/sls/sls_tactic.cpp | 295 +++++++++++++++++++++++++++--- src/tactic/sls/sls_tracker.h | 315 ++++++++++++++++++++++++++++++--- 3 files changed, 600 insertions(+), 102 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index cdb08038f..696d7664a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -78,7 +78,11 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_zero); break; } @@ -86,7 +90,11 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_one); break; } @@ -94,9 +102,16 @@ public: } case OP_NOT: { SASSERT(n_args == 1); +#if _DIRTY_UP_ + if (m_tracker.is_top_expr(args[0])) + m_mpz_manager.set(result, m_zero); + else + m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); +#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); - m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); + m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); +#endif break; } case OP_EQ: { @@ -542,7 +557,8 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) { if (m_mpz_manager.eq(new_value,m_one)) m_tracker.make_assertion(cur); @@ -554,7 +570,8 @@ public: #if _EARLY_PRUNE_ new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); @@ -562,13 +579,14 @@ public: #else #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -611,7 +629,8 @@ public: #if _EARLY_PRUNE_ new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); @@ -619,13 +638,14 @@ public: #else #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -695,7 +715,7 @@ public: double prune_score, new_score; unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; @@ -704,7 +724,8 @@ public: new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif prune_score = m_tracker.get_score_prune(cur); @@ -745,7 +766,8 @@ public: #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else @@ -833,44 +855,7 @@ public: } #endif - void randomize_local(expr * e, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_constants(e); - - // Randomize _one_ candidate: - unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); - func_decl * fd = unsat_constants[r]; -#if _PERC_CHANGE_ - sort * srt = fd->get_range(); - mpz temp; - - if (m_manager.is_bool(srt)) - m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); - - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } -#else - mpz temp = m_tracker.get_random(fd->get_range()); -#endif - update(fd, temp); - m_mpz_manager.del(temp); - } - - void randomize_local(goal_ref const & g, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); - + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: //// bool did_something = false; @@ -927,6 +912,15 @@ public: tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + + } + + void randomize_local(expr * e) { + randomize_local(m_tracker.get_constants(e)); + } + + void randomize_local(goal_ref const & g, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(g, flip)); } }; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 553acc35a..ada0ec359 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -34,6 +34,8 @@ Notes: #include"propagate_values_tactic.h" #include"sls_tactic.h" #include"nnf_tactic.h" +#include"luby.h" +#include "ctx_simplify_tactic.h" // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score @@ -43,9 +45,23 @@ Notes: // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + // do we use restarts? -// 0 = no, otherwise the value defines the maximum number of moves -#define _RESTARTS_ 0 +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 // timelimit #define _TIMELIMIT_ 3600 @@ -66,38 +82,58 @@ Notes: // 2 = yes, by squaring it // 3 = yes, by setting it to zero // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 0 +#define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 #define _WEIGHT_DIST_FACTOR_ 0.25 +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + // do we use intensification steps in local minima? if so, how many? #define _INTENSIFICATION_ 0 #define _INTENSIFICATION_TRIES_ 0 +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 0 +#define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 0.01 +#define _UCT_CONSTANT_ 10.0 // is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score #define _PROBABILISTIC_UCT_ 0 +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 // shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 1 +#define _USE_MUL2DIV2_ 0 // shall we try multiplication by 3? -#define _USE_MUL3_ 1 +#define _USE_MUL3_ 0 // shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 1 +#define _USE_UNARY_MINUS_ 0 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 1 +#define _UNIFORM_RANDOM_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 @@ -124,13 +160,21 @@ Notes: #define _CACHE_TOP_SCORE_ 1 -#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) InvalidConfiguration; #endif - +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) + InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) + InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) + InvalidConfiguration; +#endif #include"sls_params.hpp" #include"sls_evaluator.h" @@ -180,6 +224,7 @@ class sls_tactic : public tactic { sls_tracker m_tracker; sls_evaluator m_evaluator; + unsigned m_restart_limit; unsigned m_max_restarts; unsigned m_plateau_limit; @@ -208,6 +253,41 @@ class sls_tactic : public tactic { m_mpz_manager.del(m_two); } + double get_restart_armin(unsigned cnt_restarts) + { + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow(_RESTART_CONST_ARMIN_, inner_id + 1); + } + + inline unsigned check_restart(unsigned curr_value) + { + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; + } + ast_manager & m() const { return m_manager; } void set_cancel(bool f) { m_cancel = f; } @@ -435,12 +515,10 @@ class sls_tactic : public tactic { NOT_IMPLEMENTED_YET(); } - void mk_random_move(goal_ref const & g) { + void mk_random_move(ptr_vector & unsat_constants) + { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; @@ -503,6 +581,10 @@ class sls_tactic : public tactic { m_mpz_manager.del(new_value); } + void mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); + } + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { @@ -857,7 +939,7 @@ class sls_tactic : public tactic { m_stats.m_flips++; global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -875,6 +957,130 @@ class sls_tactic : public tactic { unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + // main search loop + lbool search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; score = rescore(g); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; @@ -887,12 +1093,12 @@ class sls_tactic : public tactic { // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 @@ -1072,7 +1278,11 @@ class sls_tactic : public tactic { verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; @@ -1081,9 +1291,14 @@ class sls_tactic : public tactic { verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; verbose_stream() << "_UCT_ " << _UCT_ << std::endl; verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; @@ -1099,21 +1314,30 @@ class sls_tactic : public tactic { verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif m_tracker.initialize(g); lbool res = l_undef; + m_restart_limit = _RESTART_LIMIT_; + do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... - //if ((m_stats.m_restarts % 100) == 0) - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); res = search(g); if (res == l_undef) - m_tracker.randomize(); + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); @@ -1121,6 +1345,13 @@ class sls_tactic : public tactic { if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1183,12 +1414,17 @@ public: } virtual void cleanup() { - imp * d = alloc(imp, m, m_params, m_stats); + imp * d = m_imp; #pragma omp critical (tactic_cancel) { - std::swap(d, m_imp); + d = m_imp; } dealloc(d); + d = alloc(imp, m, m_params, m_stats); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } } virtual void collect_statistics(statistics & st) const { @@ -1246,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // conservative gaussian elimination. gaussian_p.set_uint("gaussian_max_occs", 2); + params_ref ctx_p; + ctx_p.set_uint("max_depth", 32); + ctx_p.set_uint("max_steps", 5000000); return and_then(and_then(mk_simplify_tactic(m), mk_propagate_values_tactic(m), using_params(mk_solve_eqs_tactic(m), gaussian_p), @@ -1254,6 +1493,10 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), + // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? + //mk_ctx_simplify_tactic(m, ctx_p), + // Andreas: This one at least eliminates top level duplicates ... + mk_simplify_tactic(m), // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 006bbb888..0aca1f59c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -65,6 +65,7 @@ private: typedef obj_map scores_type; typedef obj_map > uplinks_type; typedef obj_map > occ_type; + obj_hashtable m_top_expr; scores_type m_scores; uplinks_type m_uplinks; entry_point_type m_entry_points; @@ -75,15 +76,15 @@ private: unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif -#if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ + double m_weight_dist_factor; #endif public: @@ -104,7 +105,7 @@ public: m_mpz_manager.del(m_two); } -#if _WEIGHT_DIST_ == 4 +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ inline void set_weight_dist_factor(double val) { m_weight_dist_factor = val; } @@ -182,12 +183,12 @@ public: inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -213,11 +214,62 @@ public: return m_uplinks.contains(n); } + inline bool is_top_expr(expr * n) { + return m_top_expr.contains(n); + } + inline ptr_vector & get_uplinks(expr * n) { SASSERT(m_uplinks.contains(n)); return m_uplinks.find(n); } +#if _REAL_RS_ || _REAL_PBFS_ + void debug_real(goal_ref const & g, unsigned flip) + { + unsigned count = 0; + for (unsigned i = 0; i < g->size(); i++) + { + expr * e = g->form(i); + if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is unsat but not in unsat list\n", i); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + expr * q = m_list_false[pos]; + if (q != e) + { + printf("iteration %d: ", flip); + printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); + exit(4); + } + } + + if (m_mpz_manager.eq(get_value(e),m_zero)) + count++; + } + + // should be true now that duplicate assertions are removed + if (count != m_where_false.size()) + { + printf("iteration %d: ", flip); + printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); + exit(4); + } + } +#endif + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -327,7 +379,7 @@ public: } } for_each_expr(proc, visited, e); - } + } void initialize_recursive(expr * e) { if (m_manager.is_and(e) || m_manager.is_or(e)) { @@ -344,7 +396,7 @@ public: find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); @@ -352,6 +404,10 @@ public: unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); + if (!m_top_expr.contains(e)) + m_top_expr.insert(e); + else + printf("this is already in ...\n"); // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 initialize_recursive(proc, visited, e); @@ -380,18 +436,20 @@ public: #if _REAL_RS_ || _REAL_PBFS_ m_list_false = new expr*[sz]; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + //for (unsigned i = 0; i < sz; i++) + //{ + // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + // break_assertion(g->form(i)); + //} #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; #endif } @@ -407,8 +465,12 @@ public: expr * q = m_list_false[m_where_false.size()]; m_list_false[pos] = q; m_where_false.find(q) = pos; + //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); } -// printf("Going in %d\n", m_where_false.size()); + //else + //printf("Erasing %d from %d to %d\n", e, pos); +// m_list_false[m_where_false.size()] = 0; +// printf("Going in %d\n", m_where_false.size()); } //if (m_unsat_expr.contains(e)) //m_unsat_expr.erase(e); @@ -416,12 +478,14 @@ public: void break_assertion(expr * e) { + //printf("I'm broken... that's still fine.\n"); if (!m_where_false.contains(e)) { + //printf("This however is not so cool...\n"); unsigned pos = m_where_false.size(); m_list_false[pos] = e; m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); + // printf("Going in %d\n", m_where_false.size()); } //if (!m_unsat_expr.contains(e)) //m_unsat_expr.push_back(e); @@ -522,7 +586,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize() { + void randomize(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -534,6 +598,28 @@ public: } TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif + } + + void reset(goal_ref const & g) { + TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); + + for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { + mpz temp = m_zero; + set_value(it->m_value, temp); + m_mpz_manager.del(temp); + } + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif } #if _EARLY_PRUNE_ @@ -591,12 +677,20 @@ public: #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) +#if _DIRTY_UP_ + sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else sum += get_score(args[i]); +#endif res = sum / (double) a->get_num_args(); #else double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur < min) min = cur; } res = min; @@ -610,14 +704,22 @@ public: #if _SCORE_OR_MUL_ double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur > max) max = cur; } res = max; @@ -772,7 +874,11 @@ public: expr * child = a->get_arg(0); if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); +#if _DIRTY_UP_ + res = is_top_expr(child) ? 0.0 : score_bool(child, true); +#else res = score_bool(child, true); +#endif } else if (m_manager.is_distinct(n)) { app * a = to_app(n); @@ -803,7 +909,11 @@ public: if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 +#if _WEIGHT_TOGGLE_ + if (res < 1.0) res *= m_weight_dist_factor; +#else if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#endif #elif _WEIGHT_DIST_ == 2 res *= res; #elif _WEIGHT_DIST_ == 3 @@ -900,6 +1010,10 @@ public: } ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + if (sz == 1) + return get_constants(); + m_temp_constants.reset(); + for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -945,7 +1059,7 @@ public: } ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) + if (!e || m_temp_constants.size()) return m_temp_constants; ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); @@ -1033,32 +1147,43 @@ public: #if _PROBABILISTIC_UCT_ double sum_score = 0.0; unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) { expr * e = g->form(i); vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { sum_score += q; if (rand() <= (q * RAND_MAX / sum_score) + 1) pos = i; - } + } } for (unsigned i = 0; i < start_index; i++) { expr * e = g->form(i); vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { sum_score += q; if (rand() <= (q * RAND_MAX / sum_score) + 1) pos = i; - } + } } #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); @@ -1078,6 +1203,7 @@ public: m_scores.find(g->form(pos)).touched = flip; #endif expr * e = g->form(pos); +// expr * e = m_list_false[pos]; #elif _BFS_ == 3 unsigned int pos = -1; @@ -1109,7 +1235,7 @@ public: #elif _UNIFORM_RANDOM_ unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; if (pos == static_cast(-1)) return m_temp_constants; expr * e = g->form(pos); @@ -1120,8 +1246,7 @@ public: sz = m_where_false.size(); if (sz == 0) return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ //unsigned pos = m_false_list[flip % m_cnt_false]; //expr * e = get_unsat_assertion(g, sz, pos); @@ -1154,6 +1279,142 @@ public: #endif } } + + + expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); + + if (sz == 1) + return g->form(0); + + m_temp_constants.reset(); +#if _FOCUS_ == 1 +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return 0; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif +// return m_list_false[pos]; + return g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 2 + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 1 + unsigned int pos = flip % sz; + return get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return0; + else + return m_list_false[flip % sz]; +#else + unsigned int pos = get_random_uint(16) % sz; + return get_unsat_assertion(g, sz, pos); +#endif + return g->form(pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % sz; +#else + unsigned int pos = get_random_uint(16) % sz; +#endif + return get_unsat_constants_crsat(g, sz, pos); +#endif + } }; #endif \ No newline at end of file From b1eeb9adf409da3188f0380a0b7280e5d6a428eb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:04:38 +0000 Subject: [PATCH 177/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 158 +++ src/tactic/sls/sls_engine.cpp | 1160 +++++++++++++++++ src/tactic/sls/sls_engine.h | 159 +++ src/tactic/sls/sls_evaluator.h | 3 + src/tactic/sls/sls_tactic.cpp | 1397 +-------------------- src/tactic/sls/sls_tracker.h | 10 +- 6 files changed, 1520 insertions(+), 1367 deletions(-) create mode 100644 src/tactic/sls/sls_compilation_settings.h create mode 100644 src/tactic/sls/sls_engine.cpp create mode 100644 src/tactic/sls/sls_engine.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h new file mode 100644 index 000000000..aea4787b0 --- /dev/null +++ b/src/tactic/sls/sls_compilation_settings.h @@ -0,0 +1,158 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_compilation_constants.h + +Abstract: + + Stochastic Local Search (SLS) compilation constants + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + + This file should go away completely once we have evaluated all options. + +--*/ +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom +#define _FOCUS_ 1 + +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + +// do we use restarts? +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? +#define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? +#define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained +#define _VNS_ 0 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 1 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 1 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 10.0 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score +#define _PROBABILISTIC_UCT_ 0 + +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 0 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 0 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 0 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 0 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) +InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) +InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) +InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) +InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) +InvalidConfiguration; +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp new file mode 100644 index 000000000..92471aad8 --- /dev/null +++ b/src/tactic/sls/sls_engine.cpp @@ -0,0 +1,1160 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + sls_engine.cpp + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#include + +#include"map.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"tactic.h" +#include"cooperate.h" +#include"luby.h" + +#include"sls_compilation_settings.h" +#include"sls_params.hpp" +#include"sls_engine.h" + + +sls_engine::sls_engine(ast_manager & m, params_ref const & p) : + m_manager(m), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) +{ + updt_params(p); +} + +sls_engine::~sls_engine() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); +} + +double sls_engine::get_restart_armin(unsigned cnt_restarts) +{ + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} + +void sls_engine::updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_plateau_limit = p.plateau_limit(); +} + +void sls_engine::checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); +} + +bool sls_engine::full_eval(goal_ref const & g, model & mdl) { + bool res = true; + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(g->form(i), o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; +} + +double sls_engine::top_score(goal_ref const & g) { +#if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl;); + return min; +#else + double top_sum = 0.0; + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); + } + + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " AVG: " << top_sum / (double)sz << std::endl;); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + + return top_sum / (double)sz; +#endif +} + +double sls_engine::rescore(goal_ref const & g) { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(g); +} + +double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif +} + +double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif +} + +double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +#if _EARLY_PRUNE_ + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; +#else + NOT_IMPLEMENTED_YET(); +#endif +} + +// checks whether the score outcome of a given move is better than the previous score +bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + +#ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); +#endif + +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else + double r = incremental_score(g, fd, temp); +#endif +#ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl;); + + m_mpz_manager.del(old_value); +#endif + + // if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +// same as what_if, but only applied to the score of a specific atom, not the total score +bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + +} + +// Andreas: do we really need all those temporary mpzs? +void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); +} + +void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); +} + +void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); +} + +void sls_engine::mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); +} + +void sls_engine::mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); +} + +void sls_engine::mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); +} + +void sls_engine::mk_random_move(ptr_vector & unsat_constants) +{ + unsigned rnd_mv = 0; + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + + mpz new_value; + + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type)rnd_mv; + + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); +} + +void sls_engine::mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +} + +// will use VNS to ignore some possible moves and increase the flips per second +double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + // we can either check the condition once in the beginning or check it repeatedly after every bit +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; +} + +// same as find_best_move but only considers the score of the current expression instead of the overall score +double sls_engine::find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// first try of intensification ... does not seem to be efficient +bool sls_engine::handle_plateau(goal_ref const & g) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back(&m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } + else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], *m_old_values[i]); + + m_old_values.reset(); + + return 0; +} + +// what_if version needed in the context of 2nd intensification try, combining local and global score +bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +// find_best_move version needed in the context of 2nd intensification try +double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +{ + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; +} + +// second try to use intensification ... also not very effective +bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; +} + +// main search loop +lbool sls_engine::search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +// main search loop +lbool sls_engine::search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { +#endif + do { + checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl;); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl;); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl;); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + } + + if (score >= 0.99999) { + // if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } + else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else + m_evaluator.randomize_local(g, m_stats.m_moves); +#endif + //mk_random_move(g); + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + m_produce_models = g->models_enabled(); + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; +} \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h new file mode 100644 index 000000000..878354c6d --- /dev/null +++ b/src/tactic/sls/sls_engine.h @@ -0,0 +1,159 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_engine.h + +Abstract: + + A Stochastic Local Search (SLS) engine + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + +--*/ +#ifndef _SLS_ENGINE_H_ +#define _SLS_ENGINE_H_ + +#include"stopwatch.h" +#include"lbool.h" +#include"model_converter.h" + +#include"sls_compilation_settings.h" +#include"sls_tracker.h" +#include"sls_evaluator.h" + +class sls_engine { +public: + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + +protected: + ast_manager & m_manager; + stats m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + + unsigned m_restart_limit; + unsigned m_max_restarts; + unsigned m_plateau_limit; + + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + +public: + sls_engine(ast_manager & m, params_ref const & p); + ~sls_engine(); + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + void updt_params(params_ref const & _p); + + stats const & get_stats(void) { return m_stats; } + void reset_statistics(void) { m_stats.reset(); } + + bool full_eval(goal_ref const & g, model & mdl); + + + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result); + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + + + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); + + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); + + + lbool search(goal_ref const & g); + + void operator()(goal_ref const & g, model_converter_ref & mc); + +protected: + void checkpoint(); + lbool search_old(goal_ref const & g); + double get_restart_armin(unsigned cnt_restarts); + + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + + double top_score(goal_ref const & g); + double rescore(goal_ref const & g); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); +#endif + + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + void mk_random_move(ptr_vector & unsat_constants); + void mk_random_move(goal_ref const & g); + + bool handle_plateau(goal_ref const & g); + bool handle_plateau(goal_ref const & g, double old_score); + + inline unsigned check_restart(unsigned curr_value); +}; + +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 696d7664a..9daf93c32 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -20,6 +20,9 @@ Notes: #ifndef _SLS_EVALUATOR_H_ #define _SLS_EVALUATOR_H_ +#include"model_evaluator.h" + +#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index ada0ec359..0f157d3a6 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,1364 +16,31 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" -#include"luby.h" -#include "ctx_simplify_tactic.h" - -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick clause when randomizing in a plateau or use the current one? -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 - -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 - -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? -#define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) - InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) - InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) - InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) - InvalidConfiguration; -#endif +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; - - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_restart_limit; - unsigned m_max_restarts; - unsigned m_plateau_limit; - - ptr_vector m_old_values; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - double get_restart_armin(unsigned cnt_restarts) - { - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow(_RESTART_CONST_ARMIN_, inner_id + 1); - } - - inline unsigned check_restart(unsigned curr_value) - { - if (curr_value > m_restart_limit) - { -#if _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); -#elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 1 - if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; - else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; -#else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif - return 0; - } - return 1; - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - top_sum += m_tracker.get_score(e); - } - - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - -#if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); -#endif - - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; - } -#endif - - // checks whether the score outcome of a given move is better than the previous score - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - -#if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); -#else - double r = incremental_score(g, fd, temp); -#endif - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - -// if (r >= best_score) { - if (r > best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // same as what_if, but only applied to the score of a specific atom, not the total score - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.add(old_value, add_value, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - - } - - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - } - - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(ptr_vector & unsat_constants) - { - unsigned rnd_mv = 0; - - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - - mpz new_value; - - sort * srt = fd->get_range(); - if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { -#if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; -#else - mt = MV_FLIP; -#endif - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } - - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } - - void mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); - } - - // will use VNS to ignore some possible moves and increase the flips per second - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } -#endif - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - return new_score; - } - - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - - m_old_values.reset(); - - return 0; - } - - // what_if version needed in the context of 2nd intensification try, combining local and global score - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // find_best_move version needed in the context of 2nd intensification try - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; - } - - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; - } - - // main search loop - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - unsigned plateau_cnt = 0; - - score = rescore(g); - unsigned sz = g->size(); -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - checkpoint(); - m_stats.m_moves++; - -#if _REAL_RS_ || _REAL_PBFS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } - continue; -#endif - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - old_score = score; - new_const = (unsigned)-1; - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - - if (new_const == static_cast(-1)) { - score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); - else -#endif -#if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); -#else - m_evaluator.randomize_local(to_evaluate); -#endif -#endif - -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } else { - func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - // main search loop - lbool search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 0.99999) { -// if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } - while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -1381,16 +48,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -1398,14 +65,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -1414,40 +80,41 @@ public: } virtual void cleanup() { - imp * d = m_imp; + sls_engine * d = m_engine; #pragma omp critical (tactic_cancel) { - d = m_imp; + d = m_engine; } dealloc(d); - d = alloc(imp, m, m_params, m_stats); + d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - m_imp = d; + m_engine = d; } } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + sls_engine::stats const & stats = m_engine->get_stats(); + double seconds = stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", stats.m_restarts); + st.update("sls full evals", stats.m_full_evals); + st.update("sls incr evals", stats.m_incr_evals); + st.update("sls incr evals/sec", stats.m_incr_evals / seconds); + st.update("sls FLIP moves", stats.m_flips); + st.update("sls INC moves", stats.m_incs); + st.update("sls DEC moves", stats.m_decs); + st.update("sls INV moves", stats.m_invs); + st.update("sls moves", stats.m_moves); + st.update("sls moves/sec", stats.m_moves / seconds); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 0aca1f59c..3675265ee 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,12 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"goal.h" +#include"model.h" + +#include"sls_compilation_settings.h" +#include"sls_powers.h" + class sls_tracker { ast_manager & m_manager; unsynch_mpz_manager & m_mpz_manager; @@ -1186,7 +1192,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif @@ -1334,7 +1340,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif From a6227d5446d206a2d264f2305a08953288a4eae7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:26:05 +0000 Subject: [PATCH 178/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index aea4787b0..8e52596e0 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -18,6 +18,10 @@ Notes: This file should go away completely once we have evaluated all options. --*/ + +#ifndef _SLS_COMPILATION_SETTINGS_H_ +#define _SLS_COMPILATION_SETTINGS_H_ + // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score #define _BFS_ 0 @@ -155,4 +159,6 @@ InvalidConfiguration; #endif #if (_PERC_STICKY_ && !_FOCUS_) InvalidConfiguration; +#endif + #endif \ No newline at end of file From 1e55b3bfb5035e1fa8b44014cab58a036a727216 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Thu, 20 Mar 2014 15:58:53 +0000 Subject: [PATCH 179/646] uct forget and minisat restarts added --- src/tactic/sls/sls_tactic.cpp | 1417 ++++++++++++++++++++++++++++++++- src/tactic/sls/sls_tracker.h | 22 +- 2 files changed, 1402 insertions(+), 37 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 0f157d3a6..b2b7035e0 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,31 +16,1378 @@ Author: Notes: --*/ +#include +#include"map.h" #include"nnf.h" +#include"cooperate.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"model_evaluator.h" #include"solve_eqs_tactic.h" +#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"propagate_values_tactic.h" -#include"ctx_simplify_tactic.h" -#include"elim_uncnstr_tactic.h" -#include"nnf_tactic.h" #include"stopwatch.h" - +#include"propagate_values_tactic.h" #include"sls_tactic.h" -#include"sls_params.hpp" -#include"sls_engine.h" +#include"nnf_tactic.h" +#include"luby.h" +#include "ctx_simplify_tactic.h" -class sls_tactic : public tactic { +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom +#define _FOCUS_ 1 + +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 1 + +// do we use restarts? +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 4.0 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? +#define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? +#define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained +#define _VNS_ 0 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 1 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.5 + +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 1 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 20.0 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score +#define _PROBABILISTIC_UCT_ 0 + +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// do we gradually reduce the touched values of _UCT_? +#define _UCT_FORGET_ 0 +#define _UCT_FORGET_FACTOR_ 0.5 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 0 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 0 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 0 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 0 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 0 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) + InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) + InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) + InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) + InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) + InvalidConfiguration; +#endif + +#include"sls_params.hpp" +#include"sls_evaluator.h" +#include"sls_tracker.h" + +class sls_tactic : public tactic { + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + + struct imp { + ast_manager & m_manager; + stats & m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + + unsigned m_restart_limit; + unsigned m_max_restarts; + unsigned m_plateau_limit; + + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + + imp(ast_manager & m, params_ref const & p, stats & s) : + m_manager(m), + m_stats(s), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) + { + updt_params(p); + } + + ~imp() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); + } + + double get_restart_armin(unsigned cnt_restarts) + { + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow(_RESTART_CONST_ARMIN_, inner_id + 1); + } + + inline unsigned check_restart(unsigned curr_value) + { + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; + } + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + static void collect_param_descrs(param_descrs & r) { + sls_params::collect_param_descrs(r); + } + + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_plateau_limit = p.plateau_limit(); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); + } + + bool full_eval(goal_ref const & g, model & mdl) { + bool res = true; + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(g->form(i), o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; + } + + double top_score(goal_ref const & g) { + #if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl; ); + return min; + #else + double top_sum = 0.0; + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); + } + + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " AVG: " << top_sum / (double) sz << std::endl; ); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + + return top_sum / (double) sz; + #endif + } + + double rescore(goal_ref const & g) { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(g); + } + + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; + } +#endif + + // checks whether the score outcome of a given move is better than the previous score + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + #ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + #endif + +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else + double r = incremental_score(g, fd, temp); +#endif + #ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl; ); + + m_mpz_manager.del(old_value); + #endif + +// if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // same as what_if, but only applied to the score of a specific atom, not the total score + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + + } + + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + } + + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); + } + + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); + } + + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); + } + + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); + } + + void mk_random_move(ptr_vector & unsat_constants) + { + unsigned rnd_mv = 0; + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + + mpz new_value; + + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; + + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } + + void mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); + } + + // will use VNS to ignore some possible moves and increase the flips per second + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + // we can either check the condition once in the beginning or check it repeatedly after every bit +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; + } + + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + + m_old_values.reset(); + + return 0; + } + + // what_if version needed in the context of 2nd intensification try, combining local and global score + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // find_best_move version needed in the context of 2nd intensification try + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) + { + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; + } + + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; + } + + // main search loop + lbool search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _UCT_FORGET_ + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + // main search loop + lbool search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { +#endif + do { + checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0 ; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl; ); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl; ); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + } + + if (score >= 0.99999) { +// if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } + while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else + m_evaluator.randomize_local(g, m_stats.m_moves); +#endif + //mk_random_move(g); + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + void operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout); ); + } + g->reset(); + } + else + mc = 0; + } + }; + ast_manager & m; params_ref m_params; - sls_engine * m_engine; + imp * m_imp; + stats m_stats; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_engine = alloc(sls_engine, m, p); + m_imp = alloc(imp, m, p, m_stats); } virtual tactic * translate(ast_manager & m) { @@ -48,16 +1395,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_engine); + dealloc(m_imp); } virtual void updt_params(params_ref const & p) { m_params = p; - m_engine->updt_params(p); + m_imp->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); + imp::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -65,13 +1412,14 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); + SASSERT(g->is_well_sorted()); + m_imp->m_produce_models = g->models_enabled(); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_engine->operator()(g, mc); + m_imp->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -80,41 +1428,40 @@ public: } virtual void cleanup() { - sls_engine * d = m_engine; + imp * d = m_imp; #pragma omp critical (tactic_cancel) { - d = m_engine; + d = m_imp; } dealloc(d); - d = alloc(sls_engine, m, m_params); + d = alloc(imp, m, m_params, m_stats); #pragma omp critical (tactic_cancel) { - m_engine = d; + m_imp = d; } } virtual void collect_statistics(statistics & st) const { - sls_engine::stats const & stats = m_engine->get_stats(); - double seconds = stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", stats.m_restarts); - st.update("sls full evals", stats.m_full_evals); - st.update("sls incr evals", stats.m_incr_evals); - st.update("sls incr evals/sec", stats.m_incr_evals / seconds); - st.update("sls FLIP moves", stats.m_flips); - st.update("sls INC moves", stats.m_incs); - st.update("sls DEC moves", stats.m_decs); - st.update("sls INV moves", stats.m_invs); - st.update("sls moves", stats.m_moves); - st.update("sls moves/sec", stats.m_moves / seconds); + double seconds = m_stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", m_stats.m_restarts); + st.update("sls full evals", m_stats.m_full_evals); + st.update("sls incr evals", m_stats.m_incr_evals); + st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); + st.update("sls FLIP moves", m_stats.m_flips); + st.update("sls INC moves", m_stats.m_incs); + st.update("sls DEC moves", m_stats.m_decs); + st.update("sls INV moves", m_stats.m_invs); + st.update("sls moves", m_stats.m_moves); + st.update("sls moves/sec", m_stats.m_moves / seconds); } virtual void reset_statistics() { - m_engine->reset_statistics(); + m_stats.reset(); } virtual void set_cancel(bool f) { - if (m_engine) - m_engine->set_cancel(f); + if (m_imp) + m_imp->set_cancel(f); } }; @@ -163,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), // Andreas: This one at least eliminates top level duplicates ... - mk_simplify_tactic(m), + //mk_simplify_tactic(m), // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 3675265ee..1c33d42a7 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -276,6 +276,20 @@ public: } #endif + void uct_forget(goal_ref const & g) { + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < g->size(); i++) + { + e = g->form(i); + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } + } + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -1195,6 +1209,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1202,7 +1218,7 @@ public: if (pos == static_cast(-1)) return m_temp_constants; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 @@ -1343,6 +1359,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1350,7 +1368,7 @@ public: if (pos == static_cast(-1)) return 0; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 From dfd2566e256d52cc3179137f3ee4f942d732d643 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 26 Mar 2014 17:26:06 +0000 Subject: [PATCH 180/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 219 +++++++++++++++++++-------------- src/tactic/sls/sls_engine.h | 58 ++++----- src/tactic/sls/sls_evaluator.h | 4 +- src/tactic/sls/sls_tracker.h | 84 ++++++------- 4 files changed, 195 insertions(+), 170 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 92471aad8..9fa2cc263 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -74,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(goal_ref const & g, model & mdl) { +bool sls_engine::full_eval(model & mdl) { bool res = true; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(g->form(i), o, true)) + if (!mdl.eval(m_assertions[i], o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) { return res; } -double sls_engine::top_score(goal_ref const & g) { +double sls_engine::top_score() { #if 0 double min = m_tracker.get_score(g->form(0)); unsigned sz = g->size(); @@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) { return min; #else double top_sum = 0.0; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = m_assertions[i]; top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); + tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); #if _CACHE_TOP_SCORE_ @@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) { #endif } -double sls_engine::rescore(goal_ref const & g) { +double sls_engine::rescore() { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(g); + return top_score(); } -double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { #if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif else return 0.0; @@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); + double r = incremental_score_prune(fd, temp); #else - double r = incremental_score(g, fd, temp); + double r = incremental_score(fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd } // same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if_local( + expr * e, + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) +{ m_evaluator.update(fd, temp); double r = m_tracker.get_score(e); if (r >= best_score) { @@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +void sls_engine::mk_random_move() { + mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves)); } // will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move_vns( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; unsigned bv_sz, max_bv_sz = 0; double new_score = score; @@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; // try to flip lsb mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = 0; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } @@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector { mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } m_mpz_manager.del(old_value); @@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector } // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ mpz temp2; @@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } @@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; #if _USE_UNARY_MINUS_ @@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector & to_eva } // first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau(goal_ref const & g) +bool sls_engine::handle_plateau() { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned pos = m_stats.m_moves % sz; #else unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + expr * e = m_tracker.get_unsat_assertion(sz, pos); if (!e) return 0; @@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g) } // what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); +bool sls_engine::what_if( + expr * e, + func_decl * fd, + const mpz & temp, + double & best_score, + mpz & best_value, + unsigned i) +{ + double global_score = incremental_score(fd, temp); double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; @@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz } // find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i) { mpz old_value, temp; double best_score = 0; @@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); + what_if(e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); @@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl } // second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +bool sls_engine::handle_plateau(double old_score) { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned new_const = m_stats.m_moves % sz; #else unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const); if (!e) return 0; @@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) { - new_score = find_best_move_local(g, q, fd, new_value, i); + new_score = find_best_move_local(q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); + global_score = incremental_score(fd, new_value); local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) } // main search loop -lbool sls_engine::search(goal_ref const & g) { +lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) { move_type move; unsigned plateau_cnt = 0; - score = rescore(g); - unsigned sz = g->size(); + score = rescore(); + unsigned sz = m_assertions.size(); #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) { if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves); #endif if (!e) { @@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { @@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) { else #endif #if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #else m_evaluator.randomize_local(to_evaluate); #endif #endif #if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); + score = m_tracker.get_top_sum() / m_assertions.size(); #else score = top_score(g); #endif @@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _REAL_RS_ || _REAL_PBFS_ score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif } } @@ -840,18 +869,18 @@ bailout: } // main search loop -lbool sls_engine::search_old(goal_ref const & g) { +lbool sls_engine::search_old() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - score = rescore(g); + score = rescore(); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); unsigned plateau_cnt = 0; @@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) { old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves); if (!to_evaluate.size()) { res = l_true; @@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) { tout << to_evaluate[i]->get_name() << std::endl;); #if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + for (unsigned i = 0; i < m_assertions.size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl; }); TRACE("sls_max", m_tracker.show_model(tout); tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl;); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " << + m_tracker.get_score(m_assertions[i]) << std::endl;); // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } @@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) { } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); } @@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) { // score could theoretically be imprecise. // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); #if _INTENSIFICATION_ handle_plateau(g, score); - //handle_plateau(g); + //handle_plateau(); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #endif - //mk_random_move(g); - score = top_score(g); + //mk_random_move(); + score = top_score(); if (score >= 1.0) { bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; @@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { #if _WEIGHT_TOGGLE_ m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif - m_tracker.initialize(g); + m_tracker.initialize(m_assertions); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; @@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { checkpoint(); report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); + res = search(); if (res == l_undef) { #if _RESTART_INIT_ - m_tracker.randomize(g); + m_tracker.randomize(); #else - m_tracker.reset(g); + m_tracker.reset(m_assertions); #endif } } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 878354c6d..8458817b6 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -71,6 +71,7 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; + ptr_vector m_assertions; unsigned m_restart_limit; unsigned m_max_restarts; @@ -92,11 +93,12 @@ public: void updt_params(params_ref const & _p); + void assert_expr(expr * e) { m_assertions.push_back(e); } + stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(goal_ref const & g, model & mdl); - + bool full_eval(model & mdl); void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); @@ -104,54 +106,44 @@ public: void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - - - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); - - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); - - - lbool search(goal_ref const & g); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); - lbool search_old(goal_ref const & g); + lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - + bool what_if(expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(goal_ref const & g); - double rescore(goal_ref const & g); - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); #if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score_prune(func_decl * fd, const mpz & new_value); #endif - - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i); + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_vns(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(goal_ref const & g); + void mk_random_move(); - bool handle_plateau(goal_ref const & g); - bool handle_plateau(goal_ref const & g, double old_score); + bool handle_plateau(void); + bool handle_plateau(double old_score); inline unsigned check_restart(unsigned curr_value); }; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 9daf93c32..7638ba5f4 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -922,8 +922,8 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(g, flip)); + void randomize_local(ptr_vector const & as, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(as, flip)); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1c33d42a7..c49257692 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,7 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"goal.h" +#include"bv_decl_plugin.h" #include"model.h" #include"sls_compilation_settings.h" @@ -365,12 +365,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -418,12 +418,12 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(goal_ref const & g) { + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); else @@ -438,7 +438,7 @@ public: visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); @@ -450,7 +450,7 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); @@ -465,11 +465,11 @@ public: #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(as[i]); #endif #if _UCT_ - m_touched = _UCT_INIT_ ? g->size() : 1; + m_touched = _UCT_INIT_ ? as.size() : 1; #endif } @@ -606,7 +606,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(goal_ref const & g) { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -620,13 +620,13 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } - void reset(goal_ref const & g) { + void reset(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -636,9 +636,9 @@ public: } #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } @@ -1029,13 +1029,13 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { if (sz == 1) return get_constants(); m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1049,22 +1049,22 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * get_unsat_assertion(ptr_vector const & as, unsigned sz, unsigned int pos) { for (unsigned i = pos; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } return 0; } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; @@ -1141,19 +1141,19 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); if (!q) return m_temp_constants; return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + ptr_vector & get_unsat_constants(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + if (m_mpz_manager.eq(get_value(as[0]), m_one)) return m_temp_constants; else return get_constants(); @@ -1201,7 +1201,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1219,12 +1219,12 @@ public: return m_temp_constants; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(as[pos]).touched = flip; #endif - expr * e = g->form(pos); + expr * e = as[pos]; // expr * e = m_list_false[pos]; #elif _BFS_ == 3 @@ -1303,11 +1303,11 @@ public: } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + expr * get_unsat_assertion(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) - return g->form(0); + return as[0]; m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1351,7 +1351,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1369,13 +1369,13 @@ public: return 0; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 m_scores.find(g->form(pos)).touched = flip; #endif // return m_list_false[pos]; - return g->form(pos); + return as[pos]; #elif _BFS_ == 3 unsigned int pos = -1; @@ -1429,7 +1429,7 @@ public: unsigned int pos = get_random_uint(16) % sz; return get_unsat_assertion(g, sz, pos); #endif - return g->form(pos); + return as[pos]; #elif _FOCUS_ == 2 #if _BFS_ unsigned int pos = flip % sz; From e9482a1447bcc552521fa5b9851b79f707629ec1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:34:21 +0000 Subject: [PATCH 181/646] disabled old code --- src/tactic/sls/sls_engine.cpp | 4 +++- src/tactic/sls/sls_engine.h | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 9fa2cc263..cc06e4f78 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -868,6 +868,7 @@ bailout: return res; } +#if 0 // Old code. // main search loop lbool sls_engine::search_old() { lbool res = l_undef; @@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() { } } } +#endif bailout: m_mpz_manager.del(new_value); @@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value) return 0; } return 1; -} \ No newline at end of file +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8458817b6..5d4c9a0fc 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -114,7 +114,6 @@ public: protected: void checkpoint(); - lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, @@ -148,4 +147,4 @@ protected: inline unsigned check_restart(unsigned curr_value); }; -#endif \ No newline at end of file +#endif From cf1a600fb981bfae72dd895e9fef9a9f79f3c5fb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:37:04 +0000 Subject: [PATCH 182/646] bugfix --- src/tactic/sls/sls_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index cc06e4f78..10aaf6601 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() { } } } -#endif bailout: m_mpz_manager.del(new_value); return res; } +#endif void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { From beef8198a42b18ce5d5f86df0729c2c0b5628a48 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:27:06 +0000 Subject: [PATCH 183/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index c49257692..cf1ad9ea3 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -276,13 +276,13 @@ public: } #endif - void uct_forget(goal_ref const & g) { + void uct_forget(ptr_vector & as) { expr * e; unsigned touched_old, touched_new; - for (unsigned i = 0; i < g->size(); i++) + for (unsigned i = 0; i < as.size(); i++) { - e = g->form(i); + e = as[i]; touched_old = m_scores.find(e).touched; touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); m_scores.find(e).touched = touched_new; From ff7af2680de792f2ac1deacc84cb0687b9d48f14 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:28:40 +0000 Subject: [PATCH 184/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index cf1ad9ea3..fac080ee7 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"for_each_expr.h" #include"bv_decl_plugin.h" #include"model.h" From 4e8c0c14188a0d1a315379cc0a42090f3c48f47c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:30:15 +0000 Subject: [PATCH 185/646] compilation fixes Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_tracker.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 5d4c9a0fc..96041d09e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,6 +22,7 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" +#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index fac080ee7..537492213 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -21,6 +21,7 @@ Notes: #define _SLS_TRACKER_H_ #include"for_each_expr.h" +#include"ast_smt2_pp.h" #include"bv_decl_plugin.h" #include"model.h" From c541694f403cd185f6ec09f8e5ab6c3fb149cdd4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 14:58:59 +0000 Subject: [PATCH 186/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 21 ++++++++++++--------- src/tactic/sls/sls_engine.h | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 10aaf6601..e7ee2abbd 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1069,6 +1069,16 @@ bailout: } #endif +void sls_engine::init_tracker() { +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(m_assertions); +} + void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { mc = 0; @@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); - + assert_expr(g->form(i)); verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; @@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(m_assertions); + init_tracker(); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 96041d09e..c56d6ec40 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -109,6 +109,8 @@ public: void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void init_tracker(void); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); From 239849957a9f120994b453c1f4fa4ff5df3d7c10 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:26:52 +0000 Subject: [PATCH 187/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++---------------- src/tactic/sls/sls_engine.h | 1 + 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index e7ee2abbd..2b359608a 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + lbool res = operator()(); + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +lbool sls_engine::operator()() { init_tracker(); lbool res = l_undef; @@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout);); - } - g->reset(); - } - else - mc = 0; } unsigned sls_engine::check_restart(unsigned curr_value) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index c56d6ec40..c6e3af155 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -113,6 +113,7 @@ public: lbool search(void); + lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: From f88b034b8b04e27773a5e2c476fe52884a3cd56d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:28:02 +0000 Subject: [PATCH 188/646] bvsls bugfix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 2b359608a..dc4451bb5 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; } unsigned sls_engine::check_restart(unsigned curr_value) From 42702c8d8a9be639f3962cacc61bd3103cbe77f4 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 20 Apr 2014 16:38:49 +0100 Subject: [PATCH 189/646] Current version before integration ... --- src/tactic/sls/sls_compilation_settings.h | 40 +- src/tactic/sls/sls_engine.cpp | 586 +++++++++++++++------- src/tactic/sls/sls_engine.h | 73 +-- src/tactic/sls/sls_evaluator.h | 152 +++++- src/tactic/sls/sls_tactic.cpp | 4 +- src/tactic/sls/sls_tracker.h | 472 ++++++++++++++--- src/tactic/smtlogics/qfbv_tactic.cpp | 28 ++ 7 files changed, 1068 insertions(+), 287 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 8e52596e0..d2b899dd8 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -36,17 +36,21 @@ Notes: // do we use dirty unit propagation to get rid of nested top level assertions? #define _DIRTY_UP_ 0 +// shall we use additive weighting scheme? +#define _PAWS_ 5 +#define _PAWS_INIT_ 40 + // do we use restarts? // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 +#define _RESTARTS_ 1 // limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 +#define _RESTART_LIMIT_ 100 // 0 = initialize with all zero, 1 initialize with random value #define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat #define _RESTART_SCHEME_ 1 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 +#define _RESTART_CONST_ARMIN_ 2.0 // timelimit #define _TIMELIMIT_ 3600 @@ -61,6 +65,21 @@ Notes: // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 +// shall we check 2-bit flips in plateaus using Monte Carlo? +#define _VNS_MC_ 0 + +// how many 2-bit flips shall we try per bit? +#define _VNS_MC_TRIES_ 1 + +// shall we check another assertion if no improving step was found in the first one? +#define _VNS_REPICK_ 0 + +// what is the probability of doing so (percentage)? +#define _VNS_PERC_ 100 + +// do a decreasing move with percentage ... +#define _INSIST_PERC_ 0 + // do we reduce the score of unsatisfied literals? // 0 = no // 1 = yes, by multiplying it with some factor @@ -70,7 +89,7 @@ Notes: #define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 +#define _WEIGHT_DIST_FACTOR_ 0.5 // shall we toggle the weight after each restart? #define _WEIGHT_TOGGLE_ 0 @@ -82,14 +101,15 @@ Notes: // what is the percentage of random moves in plateaus (instead of full randomization)? #define _PERC_PLATEAU_MOVES_ 0 -// shall we repick clause when randomizing in a plateau or use the current one? +// shall we repick assertion when randomizing in a plateau or use the current one? +// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one #define _REPICK_ 1 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ #define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 +#define _UCT_CONSTANT_ 20.0 // is uct clause selection probabilistic similar to variable selection in sparrow? // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score @@ -103,7 +123,11 @@ Notes: // how shall we initialize the _UCT_ total touched counter? // 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 +#define _UCT_INIT_ 0 + +// do we gradually reduce the touched values of _UCT_? +#define _UCT_FORGET_ 0 +#define _UCT_FORGET_FACTOR_ 0.9 // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index dc4451bb5..342e649af 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -74,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(model & mdl) { +bool sls_engine::full_eval(goal_ref const & g, model & mdl) { bool res = true; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(m_assertions[i], o, true)) + if (!mdl.eval(g->form(i), o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,7 +93,7 @@ bool sls_engine::full_eval(model & mdl) { return res; } -double sls_engine::top_score() { +double sls_engine::top_score(goal_ref const & g) { #if 0 double min = m_tracker.get_score(g->form(0)); unsigned sz = g->size(); @@ -108,15 +108,15 @@ double sls_engine::top_score() { return min; #else double top_sum = 0.0; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = m_assertions[i]; + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(m_assertions[i]); + tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double)sz << std::endl;); #if _CACHE_TOP_SCORE_ @@ -127,40 +127,40 @@ double sls_engine::top_score() { #endif } -double sls_engine::rescore() { +double sls_engine::rescore(goal_ref const & g) { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(); + return top_score(g); } -double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif } -double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif } -double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { #if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif else return 0.0; @@ -169,14 +169,17 @@ double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value #endif } +double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune_new(fd, new_value)) + return (m_tracker.get_top_sum() / g->size()); + else + return 0.0; +} + // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if( - func_decl * fd, - const unsigned & fd_inx, - const mpz & temp, - double & best_score, - unsigned & best_const, - mpz & best_value) { +bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -184,9 +187,9 @@ bool sls_engine::what_if( #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(fd, temp); + double r = incremental_score_prune(g, fd, temp); #else - double r = incremental_score(fd, temp); + double r = incremental_score(g, fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -195,8 +198,33 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif - // if (r >= best_score) { + //if (r >= best_score) { if (r > best_score) { + m_tracker.reset_equal_scores(); + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + /*else if (r == best_score) { + if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0) + { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + }*/ + + return false; +} + +bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + double r = incremental_score_prune_new(g, fd, temp); + + if (r >= best_score) { best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -207,15 +235,8 @@ bool sls_engine::what_if( } // same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local( - expr * e, - func_decl * fd, - const unsigned & fd_inx, - const mpz & temp, - double & best_score, - unsigned & best_const, - mpz & best_value) -{ +bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); double r = m_tracker.get_score(e); if (r >= best_score) { @@ -356,19 +377,13 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move() { - mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves)); +void sls_engine::mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); } // will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns( - ptr_vector & to_evaluate, - double score, - unsigned & best_const, - mpz & best_value, - unsigned & new_bit, - move_type & move) -{ +double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz, max_bv_sz = 0; double new_score = score; @@ -384,31 +399,31 @@ double sls_engine::find_best_move_vns( if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; // try to flip lsb mk_flip(srt, old_value, 0, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = 0; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); SASSERT(check == score); } @@ -430,13 +445,13 @@ double sls_engine::find_best_move_vns( { mk_flip(srt, old_value, j, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); SASSERT(check == score); } m_mpz_manager.del(old_value); @@ -444,23 +459,99 @@ double sls_engine::find_best_move_vns( return new_score; } +double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + for (unsigned j = 1; j < max_bv_sz; j++) + { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move( - ptr_vector & to_evaluate, - double score, - unsigned & best_const, - mpz & best_value, - unsigned & new_bit, - move_type & move) -{ +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ mpz temp2; #endif unsigned bv_sz; +#if _INSIST_PERC_ + double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score; +#else double new_score = score; +#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + m_tracker.reset_equal_scores(); + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { +// for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) { +// for (unsigned i = to_evaluate.size(); i-- > 0; ) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -470,15 +561,28 @@ double sls_engine::find_best_move( #if _SKIP_BITS_ for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { +// for (unsigned j = bv_sz; j-- > 0; ) { #endif // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + //if (m_tracker.get_random_uint(1)) + //if ((move != MV_FLIP) || (new_bit > j)) + //{ + //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) { + // new_bit = j; + // move = MV_FLIP; + //} + //} + //else + //{ + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } + //} } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -486,19 +590,22 @@ double sls_engine::find_best_move( if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; #if _USE_UNARY_MINUS_ @@ -528,7 +635,7 @@ double sls_engine::find_best_move( } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -538,6 +645,50 @@ double sls_engine::find_best_move( #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif + + if ((new_score == score) && 1)// (m_tracker.get_random_uint(1))) + best_const = -1; + + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value) { + mpz old_value, temp, temp2; + unsigned bv_sz; + double new_score = score; + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { + mk_flip(srt, old_value, j, temp); + for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + { + unsigned k = m_tracker.get_random_uint(16) % bv_sz; + while (k == j) + k = m_tracker.get_random_uint(16) % bv_sz; + mk_flip(srt, temp, k, temp2); + what_if(g, fd, i, temp2, new_score, best_const, best_value); + } + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + m_mpz_manager.del(temp2); + return new_score; } @@ -596,15 +747,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector & to_eva } // first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau() +bool sls_engine::handle_plateau(goal_ref const & g) { - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); #if _BFS_ unsigned pos = m_stats.m_moves % sz; #else unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(sz, pos); + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); if (!e) return 0; @@ -658,15 +809,10 @@ bool sls_engine::handle_plateau() } // what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if( - expr * e, - func_decl * fd, - const mpz & temp, - double & best_score, - mpz & best_value, - unsigned i) -{ - double global_score = incremental_score(fd, temp); +bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; @@ -680,7 +826,7 @@ bool sls_engine::what_if( } // find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i) +double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) { mpz old_value, temp; double best_score = 0; @@ -691,7 +837,7 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); - what_if(e, fd, temp, best_score, best_value, i); + what_if(g, e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); @@ -701,15 +847,15 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val } // second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(double old_score) +bool sls_engine::handle_plateau(goal_ref const & g, double old_score) { - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); #if _BFS_ unsigned new_const = m_stats.m_moves % sz; #else unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const); + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); if (!e) return 0; @@ -726,12 +872,12 @@ bool sls_engine::handle_plateau(double old_score) for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) { - new_score = find_best_move_local(q, fd, new_value, i); + new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(fd, new_value); + global_score = incremental_score(g, fd, new_value); local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -744,7 +890,7 @@ bool sls_engine::handle_plateau(double old_score) } // main search loop -lbool sls_engine::search() { +lbool sls_engine::search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -752,8 +898,15 @@ lbool sls_engine::search() { move_type move; unsigned plateau_cnt = 0; - score = rescore(); - unsigned sz = m_assertions.size(); + score = rescore(g); + unsigned sz = g->size(); + + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -767,9 +920,18 @@ lbool sls_engine::search() { #else while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #endif + //if (m_stats.m_stopwatch.get_current_seconds() > 10.0) + //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);} + checkpoint(); m_stats.m_moves++; +#if _UCT_FORGET_ + //if (m_stats.m_moves % sz == 0) + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + #if _REAL_RS_ || _REAL_PBFS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif @@ -779,13 +941,14 @@ lbool sls_engine::search() { if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #else - expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves); + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif if (!e) { res = l_true; goto bailout; } + //ptr_vector & to_evaluate = m_tracker.get_unsat_constants_only(e); ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); #else ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); @@ -818,13 +981,69 @@ lbool sls_engine::search() { #endif old_score = score; new_const = (unsigned)-1; + move = MV_FLIP; + new_bit = 0; #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); #endif +#if _VNS_MC_ > _VNS_REPICK_ +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#endif + +#if _VNS_MC_ < _VNS_REPICK_ +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#endif + +#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_ + if (new_const == static_cast(-1)) { + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); + else { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } + } +#endif + + if (new_const == static_cast(-1)) { score = old_score; plateau_cnt++; @@ -839,25 +1058,52 @@ lbool sls_engine::search() { mk_random_move(to_evaluate); else #endif -#if _REPICK_ - m_evaluator.randomize_local(m_assertions, m_stats.m_moves); +#if _REPICK_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _REPICK_ == 2 + { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + m_evaluator.randomize_local(q); + else + m_evaluator.randomize_local(e); + } #else - m_evaluator.randomize_local(to_evaluate); + m_evaluator.randomize_local_n(g, to_evaluate); + //m_evaluator.randomize_local(to_evaluate); #endif #endif #if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / m_assertions.size(); + score = m_tracker.get_top_sum() / g->size(); #else score = top_score(g); #endif + +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * q = g->form(i); + if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } + } +#endif + } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ score = serious_score(g, fd, new_value); #else - score = incremental_score(fd, new_value); + score = incremental_score(g, fd, new_value); #endif } } @@ -868,20 +1114,19 @@ bailout: return res; } -#if 0 // Old code. // main search loop -lbool sls_engine::search_old() { +lbool sls_engine::search_old(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - score = rescore(); + score = rescore(g); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; tout << "Score distribution:"; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); tout << " TOP: " << score << std::endl;); unsigned plateau_cnt = 0; @@ -927,7 +1172,7 @@ lbool sls_engine::search_old() { old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); if (!to_evaluate.size()) { res = l_true; @@ -938,22 +1183,22 @@ lbool sls_engine::search_old() { tout << to_evaluate[i]->get_name() << std::endl;); #if _VNS_ - score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < m_assertions.size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) - tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; }); TRACE("sls_max", m_tracker.show_model(tout); tout << "Scores: " << std::endl; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " << - m_tracker.get_score(m_assertions[i]) << std::endl;); + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl;); // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } @@ -991,15 +1236,15 @@ lbool sls_engine::search_old() { case MV_DIV2: m_stats.m_div2s++; break; } -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ + score = serious_score(g, fd, new_value); #else - score = incremental_score(fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); tout << " TOP: " << score << std::endl;); } @@ -1008,8 +1253,8 @@ lbool sls_engine::search_old() { // score could theoretically be imprecise. // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; - for (unsigned i = 0; i < m_assertions.size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) all_true = false; if (all_true) { res = l_true; // sat @@ -1040,17 +1285,17 @@ lbool sls_engine::search_old() { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); #if _INTENSIFICATION_ handle_plateau(g, score); - //handle_plateau(); + //handle_plateau(g); #else - m_evaluator.randomize_local(m_assertions, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(); - score = top_score(); + //mk_random_move(g); + score = top_score(g); if (score >= 1.0) { bool all_true = true; - for (unsigned i = 0; i < m_assertions.size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) all_true = false; if (all_true) { res = l_true; // sat @@ -1067,17 +1312,6 @@ bailout: return res; } -#endif - -void sls_engine::init_tracker() { -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(m_assertions); -} void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { @@ -1087,9 +1321,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); - for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; @@ -1100,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; + verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; + verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; + verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; + verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl; + verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl; verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; @@ -1111,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; @@ -1125,9 +1365,36 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - lbool res = operator()(); +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); @@ -1149,38 +1416,13 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -lbool sls_engine::operator()() { - init_tracker(); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(); -#else - m_tracker.reset(m_assertions); -#endif - } - } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - return res; -} - unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_limit) { -#if _RESTART_SCHEME_ == 4 +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; @@ -1188,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value) m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) + //if (m_stats.m_restarts % 3 == 2) m_restart_limit += _RESTART_LIMIT_; else m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; + //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_; #else m_restart_limit += _RESTART_LIMIT_; #endif @@ -1201,4 +1445,4 @@ unsigned sls_engine::check_restart(unsigned curr_value) return 0; } return 1; -} +} \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index c6e3af155..902c6b7a0 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,7 +22,6 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" -#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" @@ -72,7 +71,6 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; - ptr_vector m_assertions; unsigned m_restart_limit; unsigned m_max_restarts; @@ -94,12 +92,11 @@ public: void updt_params(params_ref const & _p); - void assert_expr(expr * e) { m_assertions.push_back(e); } - stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(model & mdl); + bool full_eval(goal_ref const & g, model & mdl); + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); @@ -107,48 +104,66 @@ public: void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - void init_tracker(void); + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - lbool search(void); + double find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); + + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + + + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); + + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); + + + lbool search(goal_ref const & g); - lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); + lbool search_old(goal_ref const & g); double get_restart_armin(unsigned cnt_restarts); - bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - bool what_if(expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); + + bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value); + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(); - double rescore(); - double serious_score(func_decl * fd, const mpz & new_value); - double incremental_score(func_decl * fd, const mpz & new_value); + double top_score(goal_ref const & g); + double rescore(goal_ref const & g); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); #if _EARLY_PRUNE_ - double incremental_score_prune(func_decl * fd, const mpz & new_value); + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); #endif - double find_best_move(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i); - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double find_best_move_vns(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(); - bool handle_plateau(void); - bool handle_plateau(double old_score); + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + void mk_random_move(ptr_vector & unsat_constants); + void mk_random_move(goal_ref const & g); + + bool handle_plateau(goal_ref const & g); + bool handle_plateau(goal_ref const & g, double old_score); inline unsigned check_restart(unsigned curr_value); }; -#endif +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 7638ba5f4..78f2cb79a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -575,7 +575,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -584,12 +584,13 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -634,7 +635,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -643,12 +644,12 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -683,7 +684,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ run_serious_update(max_depth); #else run_update(max_depth); @@ -729,14 +730,16 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) pot_benefits = 1; if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { @@ -771,7 +774,7 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); @@ -858,6 +861,104 @@ public: } #endif + unsigned run_update_bool_prune_new(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + unsigned update_prune_new(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune_new(cur_depth); + } + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: @@ -901,7 +1002,7 @@ public: mpz temp = m_tracker.get_random(fd->get_range()); #endif -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ serious_update(fd, temp); #else update(fd, temp); @@ -922,9 +1023,36 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(ptr_vector const & as, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(as, flip)); + void randomize_local(goal_ref const & g, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(g, flip)); } + + void randomize_local_n(goal_ref const & g, ptr_vector & unsat_constants) { + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; + sort * srt = fd->get_range(); + unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); + mpz max_val = m_tracker.get_random(srt); + update(fd, max_val); + double max_score = m_tracker.get_top_sum() / g->size(); + mpz temp_val; + double temp_score; + for (unsigned i = 1; i < 2; i++) + //for (unsigned i = 1; i < bv_sz; i++) + { + m_mpz_manager.set(temp_val, m_tracker.get_random(srt)); + update(fd, temp_val); + temp_score = m_tracker.get_top_sum() / g->size(); + if (temp_score > max_score) + { + m_mpz_manager.set(max_val, temp_val); + max_score = temp_score; + } + } + update(fd, max_val); + m_mpz_manager.del(temp_val); + m_mpz_manager.del(max_val); + } }; #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index b2b7035e0..0b6b01e7c 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -1509,14 +1509,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { mk_max_bv_sharing_tactic(m), // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... + // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! //mk_simplify_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); +// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 537492213..87c90f1f8 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,9 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"for_each_expr.h" -#include"ast_smt2_pp.h" -#include"bv_decl_plugin.h" +#include"goal.h" #include"model.h" #include"sls_compilation_settings.h" @@ -88,12 +86,17 @@ private: obj_map m_where_false; expr** m_list_false; #endif +#if _PAWS_ + obj_map m_weights; + //obj_map m_weights; +#endif #if _CACHE_TOP_SCORE_ double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ double m_weight_dist_factor; #endif + unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -113,15 +116,52 @@ public: m_mpz_manager.del(m_two); } + unsigned get_formula_size() { + return m_scores.size(); + } + + double get_avg_bw(goal_ref const & g) { + double sum = 0.0; + unsigned count = 0; + + for (unsigned i = 0; i < g->size(); i++) + { + m_temp_constants.reset(); + ptr_vector const & this_decls = m_constants_occ.find(g->form(i)); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + m_temp_constants.push_back(fd); + sort * srt = fd->get_range(); + sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + count++; + } + } + + return sum / count; + } + #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ inline void set_weight_dist_factor(double val) { m_weight_dist_factor = val; } #endif + void reset_equal_scores() { + m_equal_scores = 1; + } + + unsigned inc_equal_scores() { + return ++m_equal_scores; + } + #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { + inline void adapt_top_sum(expr * e, double add, double sub) { +#if _PAWS_ + m_top_sum += m_weights.find(e) * (add - sub); +#else m_top_sum += add - sub; +#endif } inline void set_top_sum(double new_score) { @@ -278,19 +318,21 @@ public: } #endif - void uct_forget(ptr_vector & as) { +#if _UCT_ + void uct_forget(goal_ref const & g) { expr * e; unsigned touched_old, touched_new; - for (unsigned i = 0; i < as.size(); i++) + for (unsigned i = 0; i < g->size(); i++) { - e = as[i]; + e = g->form(i); touched_old = m_scores.find(e).touched; touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); m_scores.find(e).touched = touched_new; m_touched += touched_new - touched_old; } } +#endif void initialize(app * n) { // Build score table @@ -367,12 +409,12 @@ public: } }; - void calculate_expr_distances(ptr_vector const & as) { + void calculate_expr_distances(goal_ref const & g) { // precondition: m_scores is set up. - unsigned sz = as.size(); + unsigned sz = g->size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(as[i])); + stack.push_back(to_app(g->form(i))); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -420,12 +462,12 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(ptr_vector const & as) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = as.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); if (!m_top_expr.contains(e)) m_top_expr.insert(e); else @@ -440,7 +482,7 @@ public: visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); @@ -452,7 +494,7 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(as); + calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); @@ -465,16 +507,49 @@ public: //} #endif +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * e = g->form(i); + if (!m_weights.contains(e)) + m_weights.insert(e, _PAWS_INIT_); + } +#endif + #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(as[i]); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = _UCT_INIT_ ? as.size() : 1; + m_touched = _UCT_INIT_ ? g->size() : 1; #endif } +#if _PAWS_ + void increase_weight(expr * e) + { + //printf("Increasing %d to", m_weights.find(e)); + m_weights.find(e)++; + //m_weights.find(e) *= 1.1; + //printf(" %d\n", m_weights.find(e)); + } + + void decrease_weight(expr * e) + { + unsigned old_weight = m_weights.find(e); + m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; + //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1; + //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e)); + } + + unsigned get_weight(expr * e) + //double get_weight(expr * e) + { + return m_weights.find(e); + } +#endif + #if _REAL_RS_ || _REAL_PBFS_ void make_assertion(expr * e) { @@ -608,7 +683,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(ptr_vector const & as) { + void randomize(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -622,13 +697,13 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? as.size() : 1; - for (unsigned i = 0; i < as.size(); i++) - m_scores.find(as[i]).touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; #endif } - void reset(ptr_vector const & as) { + void reset(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -638,9 +713,9 @@ public: } #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? as.size() : 1; - for (unsigned i = 0; i < as.size(); i++) - m_scores.find(as[i]).touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; #endif } @@ -765,6 +840,7 @@ public: const mpz & v1 = get_value(arg1); if (negated) { + //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -811,40 +887,209 @@ public: SASSERT(a->get_num_args() == 2); const mpz & x = get_value(a->get_arg(0)); const mpz & y = get_value(a->get_arg(1)); - unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); if (negated) { if (m_mpz_manager.gt(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy);*/ +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= rational(m_powers(bv_sz)); + double dbl = 1.0 - n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + m_mpz_manager.del(diff); +#endif + } + } + else { + if (m_mpz_manager.le(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); - } - } - else { - if (m_mpz_manager.le(x, y)) + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/ +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - else if (m_bv_util.is_bv_sle(n)) { // x <= y +/* else if (m_bv_util.is_bv_sle(n)) { // x <= y + app * a = to_app(n); + SASSERT(a->get_num_args() == 2); + const mpz & x = get_value(a->get_arg(0)); + const mpz & y = get_value(a->get_arg(1)); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + + mpz x_unsigned; + mpz y_unsigned; + const mpz & p = m_powers(bv_sz); + const mpz & p_half = m_powers(bv_sz-1); + if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } + if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); } + + if (negated) { + if (x_unsigned > y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy); + } + } + else { + if (x_unsigned <= y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2); + } + } + TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << + m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); + + m_mpz_manager.del(x_unsigned); + m_mpz_manager.del(y_unsigned); + }*/ + else if (m_bv_util.is_bv_sle(n)) { // x <= y app * a = to_app(n); SASSERT(a->get_num_args() == 2); mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0))); @@ -857,31 +1102,61 @@ public: if (negated) { if (x > y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= p; - double dbl = n.get_double(); - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + double dbl = 1.0 - n.get_double(); + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } else { if (x <= y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); + SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); @@ -1031,13 +1306,13 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { if (sz == 1) return get_constants(); m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1051,22 +1326,22 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { for (unsigned i = pos; i < sz; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) return q; } for (unsigned i = 0; i < pos; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) return q; } return 0; } - ptr_vector & get_unsat_constants_walksat(ptr_vector const & as, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(as, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; @@ -1143,20 +1418,66 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_crsat(ptr_vector const & as, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(as, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) return m_temp_constants; return go_deeper(q); } - ptr_vector & get_unsat_constants(ptr_vector const & as, unsigned int flip) { - unsigned sz = as.size(); + void go_deeper_only(expr * e) { + //if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q); + } + go_deeper(args[pos]); + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + go_deeper(q); + } + } + //} + else + { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + } + + ptr_vector & get_unsat_constants_only(expr * e) { + if (e && !m_temp_constants.size()) + go_deeper_only(e); + + return m_temp_constants; + } + + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(as[0]), m_one)) + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + { + m_temp_constants.reset(); return m_temp_constants; + } else return get_constants(); } @@ -1169,11 +1490,12 @@ public: #if _PROBABILISTIC_UCT_ double sum_score = 0.0; unsigned start_index = get_random_uint(16) % sz; - + for (unsigned i = start_index; i < sz; i++) { expr * e = g->form(i); vscore = m_scores.find(e); + #if _PROBABILISTIC_UCT_ == 2 double q = vscore.score * vscore.score; #else @@ -1203,7 +1525,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1221,12 +1543,12 @@ public: return m_temp_constants; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(as[pos]).touched++; + m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 - m_scores.find(as[pos]).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = as[pos]; + expr * e = g->form(pos); // expr * e = m_list_false[pos]; #elif _BFS_ == 3 @@ -1304,12 +1626,15 @@ public: } } + expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); - expr * get_unsat_assertion(ptr_vector const & as, unsigned int flip) { - unsigned sz = as.size(); - - if (sz == 1) - return as[0]; + if (sz == 1) { + if (m_mpz_manager.eq(get_value(g->form(0)), m_zero)) + return g->form(0); + else + return 0; + } m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1353,12 +1678,12 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #elif _UCT_ == 3 @@ -1371,13 +1696,13 @@ public: return 0; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(as[pos]).touched++; + m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 m_scores.find(g->form(pos)).touched = flip; #endif // return m_list_false[pos]; - return as[pos]; + return g->form(pos); #elif _BFS_ == 3 unsigned int pos = -1; @@ -1431,7 +1756,7 @@ public: unsigned int pos = get_random_uint(16) % sz; return get_unsat_assertion(g, sz, pos); #endif - return as[pos]; + return g->form(pos); #elif _FOCUS_ == 2 #if _BFS_ unsigned int pos = flip % sz; @@ -1441,6 +1766,23 @@ public: return get_unsat_constants_crsat(g, sz, pos); #endif } + + expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { + unsigned sz = g->size(); + + if (sz == 1) + return 0; + + m_temp_constants.reset(); + + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + + if (pos == static_cast(-1)) + return 0; + return g->form(pos); + } }; #endif \ No newline at end of file diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index ac53ca0c8..a7870176d 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -28,6 +28,8 @@ Notes: #include"bv_size_reduction_tactic.h" #include"aig_tactic.h" #include"sat_tactic.h" +//#include"nnf_tactic.h" +//#include"sls_tactic.h" #define MEMLIMIT 300 @@ -93,6 +95,32 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { mk_sat_tactic(m)); #endif + /* use full sls + tactic * st = using_params(and_then(preamble_st, + cond(mk_is_qfbv_probe(), + cond(mk_is_qfbv_eq_probe(), + and_then(mk_bv1_blaster_tactic(m), + using_params(mk_smt_tactic(), solver_p)), + and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))), + mk_smt_tactic())), + main_p);*/ + + /* use pure dpll + tactic * st = using_params(and_then(mk_simplify_tactic(m), + cond(mk_is_qfbv_probe(), + and_then(mk_bit_blaster_tactic(m), + when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), + and_then(using_params(and_then(mk_simplify_tactic(m), + mk_solve_eqs_tactic(m)), + local_ctx_p), + if_no_proofs(cond(mk_produce_unsat_cores_probe(), + mk_aig_tactic(), + using_params(mk_aig_tactic(), + big_aig_p))))), + new_sat), + mk_smt_tactic())), + main_p);*/ + tactic * st = using_params(and_then(preamble_st, // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function // symbols. In this case, we should not use From 8a30a2caa9f6644866d855a247f621e47cee95e4 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 00:32:45 +0100 Subject: [PATCH 190/646] Almost cleaned up version. --- src/tactic/sls/sls_compilation_settings.h | 156 +-- src/tactic/sls/sls_engine.cpp | 1168 +++------------------ src/tactic/sls/sls_engine.h | 89 +- src/tactic/sls/sls_evaluator.h | 262 +---- src/tactic/sls/sls_tactic.cpp | 6 +- src/tactic/sls/sls_tracker.h | 904 ++-------------- 6 files changed, 315 insertions(+), 2270 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index d2b899dd8..9add78daa 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,167 +22,13 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 - -// shall we use additive weighting scheme? -#define _PAWS_ 5 -#define _PAWS_INIT_ 40 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 1 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 100 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 2.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// shall we check 2-bit flips in plateaus using Monte Carlo? -#define _VNS_MC_ 0 - -// how many 2-bit flips shall we try per bit? -#define _VNS_MC_TRIES_ 1 - -// shall we check another assertion if no improving step was found in the first one? -#define _VNS_REPICK_ 0 - -// what is the probability of doing so (percentage)? -#define _VNS_PERC_ 100 - -// do a decreasing move with percentage ... -#define _INSIST_PERC_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.5 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick assertion when randomizing in a plateau or use the current one? -// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 20.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 0 - -// do we gradually reduce the touched values of _UCT_? -#define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.9 - // shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 +#define _USE_ADDSUB_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 // shall we use early pruning for incremental update? #define _EARLY_PRUNE_ 1 -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) -InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) -InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) -InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) -InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) -InvalidConfiguration; -#endif - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 342e649af..c240a0c51 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) : m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) { updt_params(p); + m_tracker.updt_params(p); } sls_engine::~sls_engine() { @@ -52,20 +53,21 @@ sls_engine::~sls_engine() { m_mpz_manager.del(m_two); } -double sls_engine::get_restart_armin(unsigned cnt_restarts) -{ - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); -} - void sls_engine::updt_params(params_ref const & _p) { sls_params p(_p); m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); + m_max_restarts = p.max_restarts(); m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); + m_walksat = p.walksat(); + m_walksat_repick = p.walksat_repick(); + m_paws_sp = p.paws_sp(); + m_wp = p.wp(); + m_vns_mc = p.vns_mc(); + m_vns_repick = p.vns_repick(); + + m_restart_base = p.restart_base(); + m_restart_next = m_restart_base; + m_restart_init = p.restart_init(); } void sls_engine::checkpoint() { @@ -74,15 +76,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(goal_ref const & g, model & mdl) { +bool sls_engine::full_eval(model & mdl) { bool res = true; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(g->form(i), o, true)) + if (!mdl.eval(m_assertions[i], o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,93 +95,58 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) { return res; } -double sls_engine::top_score(goal_ref const & g) { -#if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl;); - return min; -#else +double sls_engine::top_score() { double top_sum = 0.0; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = m_assertions[i]; top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); + tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); -#if _CACHE_TOP_SCORE_ m_tracker.set_top_sum(top_sum); -#endif return top_sum / (double)sz; -#endif } -double sls_engine::rescore(goal_ref const & g) { +double sls_engine::rescore() { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(g); + return top_score(); } -double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif + return (m_tracker.get_top_sum() / m_assertions.size()); } -double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif + return (m_tracker.get_top_sum() / m_assertions.size()); } -double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { -#if _EARLY_PRUNE_ +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; -#else - NOT_IMPLEMENTED_YET(); -#endif -} - -double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune_new(fd, new_value)) - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); else return 0.0; } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -187,9 +154,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); + double r = incremental_score_prune(fd, temp); #else - double r = incremental_score(g, fd, temp); + double r = incremental_score(fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -198,7 +165,7 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd m_mpz_manager.del(old_value); #endif - //if (r >= best_score) { + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { m_tracker.reset_equal_scores(); best_score = r; @@ -206,45 +173,6 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd m_mpz_manager.set(best_value, temp); return true; } - /*else if (r == best_score) { - if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0) - { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - }*/ - - return false; -} - -bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - double r = incremental_score_prune_new(g, fd, temp); - - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; -} - -// same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } return false; } @@ -261,22 +189,6 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, } -// Andreas: do we really need all those temporary mpzs? -void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); -} - -void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); -} - void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); @@ -334,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + move_type mt = MV_FLIP; #endif unsigned bit = 0; @@ -373,216 +285,40 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); } - m_evaluator.update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); -} - -// will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - -double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - for (unsigned j = 1; j < max_bv_sz; j++) - { - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif unsigned bv_sz; -#if _INSIST_PERC_ - double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score; -#else double new_score = score; -#endif m_tracker.reset_equal_scores(); -// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { for (unsigned i = 0; i < to_evaluate.size(); i++) { -// for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) { -// for (unsigned i = to_evaluate.size(); i-- > 0; ) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { -#else -// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { for (unsigned j = 0; j < bv_sz; j++) { -// for (unsigned j = bv_sz; j-- > 0; ) { -#endif // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - //if (m_tracker.get_random_uint(1)) - //if ((move != MV_FLIP) || (new_bit > j)) - //{ - //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) { - // new_bit = j; - // move = MV_FLIP; - //} - //} - //else - //{ - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } - //} } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -590,76 +326,41 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } m_mpz_manager.del(old_value); m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - - if ((new_score == score) && 1)// (m_tracker.get_random_uint(1))) - best_const = -1; return new_score; } // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, +double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value) { mpz old_value, temp, temp2; unsigned bv_sz; double new_score = score; -// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -667,22 +368,21 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { -// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { for (unsigned j = 0; j < bv_sz; j++) { mk_flip(srt, old_value, j, temp); - for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++) { unsigned k = m_tracker.get_random_uint(16) % bv_sz; while (k == j) k = m_tracker.get_random_uint(16) % bv_sz; mk_flip(srt, temp, k, temp2); - what_if(g, fd, i, temp2, new_score, best_const, best_value); + what_if(fd, i, temp2, new_score, best_const, best_value); } } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -692,618 +392,89 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & return new_score; } -// same as find_best_move but only considers the score of the current expression instead of the overall score -double sls_engine::find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - -// first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau(goal_ref const & g) -{ - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back(&m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } - else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], *m_old_values[i]); - - m_old_values.reset(); - - return 0; -} - -// what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; -} - -// find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) -{ - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; -} - -// second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(goal_ref const & g, double old_score) -{ - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; -} - // main search loop -lbool sls_engine::search(goal_ref const & g) { +lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; + unsigned new_const = (unsigned)-1, new_bit; mpz new_value; move_type move; - unsigned plateau_cnt = 0; - score = rescore(g); - unsigned sz = g->size(); - - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - //if (m_stats.m_stopwatch.get_current_seconds() > 10.0) - //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);} + score = rescore(); + unsigned sz = m_assertions.size(); + while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; + if (m_stats.m_moves % m_restart_base == 0) + m_tracker.ucb_forget(m_assertions); -#if _UCT_FORGET_ - //if (m_stats.m_moves % sz == 0) - if (m_stats.m_moves % _UCT_FORGET_ == 0) - m_tracker.uct_forget(g); -#endif - -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - //ptr_vector & to_evaluate = m_tracker.get_unsat_constants_only(e); - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { res = l_true; goto bailout; } -#endif -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + if (m_wp && m_tracker.get_random_uint(10) < m_wp) { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif + score = m_tracker.get_top_sum() / sz; + continue; } - continue; -#endif -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif old_score = score; new_const = (unsigned)-1; - move = MV_FLIP; - new_bit = 0; -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); -#if _VNS_MC_ > _VNS_REPICK_ -#if _VNS_MC_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } + if (m_vns_mc && (new_const == static_cast(-1))) + score = find_best_move_mc(to_evaluate, score, new_const, new_value); + + /*if (m_vns_repick && (new_const == static_cast(-1))) + { + expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); } -#endif -#endif - -#if _VNS_MC_ < _VNS_REPICK_ -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } - } -#endif -#if _VNS_MC_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#endif - -#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_ - if (new_const == static_cast(-1)) { - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); - else { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } - } - } -#endif - + }*/ if (new_const == static_cast(-1)) { score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); + if (m_walksat && m_walksat_repick) + m_evaluator.randomize_local(m_assertions); else -#endif -#if _REPICK_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _REPICK_ == 2 - { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - m_evaluator.randomize_local(q); - else - m_evaluator.randomize_local(e); - } -#else - m_evaluator.randomize_local_n(g, to_evaluate); - //m_evaluator.randomize_local(to_evaluate); -#endif -#endif + m_evaluator.randomize_local(to_evaluate); -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif + score = m_tracker.get_top_sum() / m_assertions.size(); -#if _PAWS_ - for (unsigned i = 0; i < sz; i++) + if (m_paws_sp < 1024) { - expr * q = g->form(i); - if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + for (unsigned i = 0; i < sz; i++) { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) - m_tracker.decrease_weight(q); - } - else - { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) - m_tracker.increase_weight(q); + expr * q = m_assertions[i]; + if (m_tracker.get_random_uint(10) < m_paws_sp) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } } } -#endif - } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - -bailout: - m_mpz_manager.del(new_value); - - return res; -} - -// main search loop -lbool sls_engine::search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl;); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl;); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl;); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - } - - if (score >= 0.99999) { - // if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } - else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } + score = serious_score(fd, new_value); } } @@ -1321,80 +492,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; - verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; - verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; - verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; - verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl; - verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; - verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + lbool res = operator()(); if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); @@ -1416,33 +521,66 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -unsigned sls_engine::check_restart(unsigned curr_value) +lbool sls_engine::operator()() { + m_tracker.initialize(m_assertions); + lbool res = l_undef; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(); + + if (res == l_undef) + { + if (m_restart_init) + m_tracker.randomize(m_assertions); + else + m_tracker.reset(m_assertions); + } + } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; +} + +/* Andreas: Needed for Armin's restart scheme if we don't want to use loops. +inline double sls_engine::get_restart_armin(unsigned cnt_restarts) { - if (curr_value > m_restart_limit) + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} +*/ + +inline unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_next) { + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 - m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); + m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); #elif _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); + m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) - //if (m_stats.m_restarts % 3 == 2) - m_restart_limit += _RESTART_LIMIT_; + m_restart_next += m_restart_base; else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; - //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_; + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; #else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif + m_restart_limit += m_restart_base; +#endif */ + if (m_stats.m_restarts & 1) + m_restart_next += m_restart_base; + else + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; return 0; } return 1; -} \ No newline at end of file +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 902c6b7a0..ff0e55f24 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,6 +22,7 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" +#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" @@ -35,17 +36,13 @@ public: stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs; stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -71,14 +68,22 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; + ptr_vector m_assertions; - unsigned m_restart_limit; unsigned m_max_restarts; - unsigned m_plateau_limit; + unsigned m_walksat; + unsigned m_walksat_repick; + unsigned m_wp; + unsigned m_vns_mc; + unsigned m_vns_repick; + unsigned m_paws_sp; + unsigned m_restart_base; + unsigned m_restart_next; + unsigned m_restart_init; ptr_vector m_old_values; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; public: sls_engine(ast_manager & m, params_ref const & p); @@ -92,78 +97,46 @@ public: void updt_params(params_ref const & _p); + void assert_expr(expr * e) { m_assertions.push_back(e); } + stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(goal_ref const & g, model & mdl); - + bool full_eval(model & mdl); void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result); void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value); - - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - - - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); - - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); - - - lbool search(goal_ref const & g); + lbool search(void); + lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); - lbool search_old(goal_ref const & g); - double get_restart_armin(unsigned cnt_restarts); - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value); - double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value); + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value); + double incremental_score_prune(func_decl * fd, const mpz & new_value); + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double top_score(goal_ref const & g); - double rescore(goal_ref const & g); - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); -#endif - - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_mc(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(goal_ref const & g); - - bool handle_plateau(goal_ref const & g); - bool handle_plateau(goal_ref const & g, double old_score); + //inline double get_restart_armin(unsigned cnt_restarts); inline unsigned check_restart(unsigned curr_value); }; -#endif \ No newline at end of file +#endif diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 78f2cb79a..37bfa5a2d 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -81,11 +81,7 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_zero); break; } @@ -93,11 +89,7 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_one); break; } @@ -105,16 +97,9 @@ public: } case OP_NOT: { SASSERT(n_args == 1); -#if _DIRTY_UP_ - if (m_tracker.is_top_expr(args[0])) - m_mpz_manager.set(result, m_zero); - else - m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); -#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); -#endif break; } case OP_EQ: { @@ -545,9 +530,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -559,8 +542,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); -#if _REAL_RS_ || _REAL_PBFS_ - //if (!m_tracker.has_uplinks(cur)) +#if _REAL_RS_ if (m_tracker.is_top_expr(cur)) { if (m_mpz_manager.eq(new_value,m_one)) @@ -570,25 +552,12 @@ public: } #endif + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { @@ -617,9 +586,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -630,25 +597,12 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -684,11 +638,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ run_serious_update(max_depth); -#else - run_update(max_depth); -#endif } void update(func_decl * fd, const mpz & new_value) { @@ -713,7 +663,6 @@ public: run_serious_update(cur_depth); } -#if _EARLY_PRUNE_ unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; @@ -727,19 +676,15 @@ public: expr * cur = cur_depth_exprs[i]; new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) pot_benefits = 1; if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { @@ -754,9 +699,6 @@ public: } } } - else - { - } } cur_depth_exprs.reset(); @@ -770,15 +712,11 @@ public: for (unsigned i = 0; i < cur_size; i++) { expr * cur = cur_depth_exprs[i]; -#if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -859,161 +797,18 @@ public: } return run_update_bool_prune(cur_depth); } -#endif - - unsigned run_update_bool_prune_new(unsigned cur_depth) { - expr_fast_mark1 visited; - - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); - - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - prune_score = m_tracker.get_score_prune(cur); - m_tracker.set_score(cur, new_score); - - if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - else - { - } - } - - cur_depth_exprs.reset(); - cur_depth--; - - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } - - return pot_benefits; - } - - unsigned update_prune_new(func_decl * fd, const mpz & new_value) { - m_tracker.set_value(fd, new_value); - expr * ep = m_tracker.get_entry_point(fd); - unsigned cur_depth = m_tracker.get_distance(ep); - - if (m_traversal_stack_bool.size() <= cur_depth) - m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); - - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune_new(cur_depth); - } void randomize_local(ptr_vector & unsat_constants) { - // Randomize _all_ candidates: - - //// bool did_something = false; - //for (unsigned i = 0; i < unsat_constants.size(); i++) { - // func_decl * fd = unsat_constants[i]; - // mpz temp = m_tracker.get_random(fd->get_range()); - // // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) { - // // did_something = true; - // // } - // update(fd, temp); - // m_mpz_manager.del(temp); - //} - // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; -#if _PERC_CHANGE_ - sort * srt = fd->get_range(); - mpz temp; - - if (m_manager.is_bool(srt)) - m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); - - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } -#else mpz temp = m_tracker.get_random(fd->get_range()); -#endif -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ serious_update(fd, temp); -#else - update(fd, temp); -#endif + m_mpz_manager.del(temp); - TRACE("sls", /*tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl;*/ - tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; + TRACE("sls", tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); @@ -1023,36 +818,9 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(g, flip)); + void randomize_local(ptr_vector const & as) { + randomize_local(m_tracker.get_unsat_constants(as)); } - - void randomize_local_n(goal_ref const & g, ptr_vector & unsat_constants) { - unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); - func_decl * fd = unsat_constants[r]; - sort * srt = fd->get_range(); - unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); - mpz max_val = m_tracker.get_random(srt); - update(fd, max_val); - double max_score = m_tracker.get_top_sum() / g->size(); - mpz temp_val; - double temp_score; - for (unsigned i = 1; i < 2; i++) - //for (unsigned i = 1; i < bv_sz; i++) - { - m_mpz_manager.set(temp_val, m_tracker.get_random(srt)); - update(fd, temp_val); - temp_score = m_tracker.get_top_sum() / g->size(); - if (temp_score > max_score) - { - m_mpz_manager.set(max_val, temp_val); - max_score = temp_score; - } - } - update(fd, max_val); - m_mpz_manager.del(temp_val); - m_mpz_manager.del(max_val); - } }; #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 0b6b01e7c..6e1102dd2 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -1507,16 +1507,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? - //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! - //mk_simplify_tactic(m), mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); -// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); + //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 87c90f1f8..65011dc8d 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,7 +20,9 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"goal.h" +#include"for_each_expr.h" +#include"ast_smt2_pp.h" +#include"bv_decl_plugin.h" #include"model.h" #include"sls_compilation_settings.h" @@ -37,11 +39,7 @@ class sls_tracker { mpz m_zero, m_one, m_two; struct value_score { -#if _EARLY_PRUNE_ value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; -#else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; -#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; @@ -78,24 +76,22 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; -#if _UCT_ + + unsigned m_walksat; + unsigned m_ucb; + double m_ucb_constant; + unsigned m_ucb_init; + double m_ucb_forget; unsigned m_touched; -#endif -#if _REAL_RS_ || _REAL_PBFS_ + double m_scale_unsat; + unsigned m_paws_init; +#if _REAL_RS_ ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; #endif -#if _PAWS_ obj_map m_weights; - //obj_map m_weights; -#endif -#if _CACHE_TOP_SCORE_ double m_top_sum; -#endif -#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ - double m_weight_dist_factor; -#endif unsigned m_equal_scores; public: @@ -116,6 +112,17 @@ public: m_mpz_manager.del(m_two); } + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_walksat = p.walksat(); + m_ucb = p.walksat_ucb(); + m_ucb_constant = p.walksat_ucb_constant(); + m_ucb_init = p.walksat_ucb_init(); + m_ucb_forget = p.walksat_ucb_forget(); + m_scale_unsat = p.scale_unsat(); + m_paws_init = p.paws_init(); + } + unsigned get_formula_size() { return m_scores.size(); } @@ -141,12 +148,6 @@ public: return sum / count; } -#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } -#endif - void reset_equal_scores() { m_equal_scores = 1; } @@ -155,13 +156,8 @@ public: return ++m_equal_scores; } -#if _CACHE_TOP_SCORE_ inline void adapt_top_sum(expr * e, double add, double sub) { -#if _PAWS_ m_top_sum += m_weights.find(e) * (add - sub); -#else - m_top_sum += add - sub; -#endif } inline void set_top_sum(double new_score) { @@ -171,7 +167,6 @@ public: inline double get_top_sum() { return m_top_sum; } -#endif inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); @@ -217,7 +212,6 @@ public: return get_score(ep); } -#if _EARLY_PRUNE_ inline void set_score_prune(expr * n, double score) { SASSERT(m_scores.contains(n)); m_scores.find(n).score_prune = score; @@ -237,7 +231,6 @@ public: SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; } -#endif inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); @@ -271,7 +264,7 @@ public: return m_uplinks.find(n); } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ void debug_real(goal_ref const & g, unsigned flip) { unsigned count = 0; @@ -318,21 +311,22 @@ public: } #endif -#if _UCT_ - void uct_forget(goal_ref const & g) { - expr * e; - unsigned touched_old, touched_new; - - for (unsigned i = 0; i < g->size(); i++) + inline void ucb_forget(ptr_vector & as) { + if (m_ucb_forget < 1.0) { - e = g->form(i); - touched_old = m_scores.find(e).touched; - touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); - m_scores.find(e).touched = touched_new; - m_touched += touched_new - touched_old; + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < as.size(); i++) + { + e = as[i]; + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } } } -#endif void initialize(app * n) { // Build score table @@ -409,12 +403,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -462,31 +456,24 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(goal_ref const & g) { + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); else printf("this is already in ...\n"); - // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); -#endif for_each_expr(proc, visited, e); } visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); -#endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -494,11 +481,11 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ m_list_false = new expr*[sz]; //for (unsigned i = 0; i < sz; i++) //{ @@ -507,50 +494,38 @@ public: //} #endif -#if _PAWS_ for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_weights.contains(e)) - m_weights.insert(e, _PAWS_INIT_); + m_weights.insert(e, m_paws_init); } -#endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(as[i]); #endif -#if _UCT_ - m_touched = _UCT_INIT_ ? g->size() : 1; -#endif + m_touched = m_ucb_init ? as.size() : 1; } -#if _PAWS_ void increase_weight(expr * e) { - //printf("Increasing %d to", m_weights.find(e)); m_weights.find(e)++; - //m_weights.find(e) *= 1.1; - //printf(" %d\n", m_weights.find(e)); } void decrease_weight(expr * e) { unsigned old_weight = m_weights.find(e); - m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; - //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1; - //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e)); + m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init; } unsigned get_weight(expr * e) - //double get_weight(expr * e) { return m_weights.find(e); } -#endif -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ void make_assertion(expr * e) { if (m_where_false.contains(e)) @@ -683,7 +658,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(goal_ref const & g) { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -695,15 +670,9 @@ public: } TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); - -#if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; -#endif } - void reset(goal_ref const & g) { + void reset(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -711,15 +680,8 @@ public: set_value(it->m_value, temp); m_mpz_manager.del(temp); } - -#if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; -#endif } -#if _EARLY_PRUNE_ void setup_occs(expr * n, bool negated = false) { if (m_manager.is_bool(n)) { @@ -752,7 +714,6 @@ public: else NOT_IMPLEMENTED_YET(); } -#endif double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -770,57 +731,29 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. -#if _SCORE_AND_AVG_ + /* Andreas: Seems to have no effect. But maybe you want to try it again at some point. double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) -#if _DIRTY_UP_ - sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else sum += get_score(args[i]); -#endif - res = sum / (double) a->get_num_args(); -#else + res = sum / (double) a->get_num_args(); */ double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else double cur = get_score(args[i]); -#endif if (cur < min) min = cur; } res = min; -#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); // Andreas: Seems to have no effect. Probably it is still too similar to the original version. -#if _SCORE_OR_MUL_ - double inv = 1.0; - for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else - double cur = get_score(args[i]); -#endif - inv *= (1.0 - get_score(args[i])); - } - res = 1.0 - inv; -#else double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else double cur = get_score(args[i]); -#endif if (cur > max) max = cur; } res = max; -#endif } else if (m_manager.is_ite(n)) { SASSERT(!negated); @@ -855,24 +788,14 @@ public: m_mpz_manager.bitwise_xor(v0, v1, diff); unsigned hamming_distance = 0; unsigned bv_sz = m_bv_util.get_bv_size(arg0); - #if 1 // unweighted hamming distance + // unweighted hamming distance while (!m_mpz_manager.is_zero(diff)) { - //m_mpz_manager.set(diff_m1, diff); - //m_mpz_manager.dec(diff_m1); - //m_mpz_manager.bitwise_and(diff, diff_m1, diff); - //hamming_distance++; if (!m_mpz_manager.is_even(diff)) { hamming_distance++; } m_mpz_manager.machine_div(diff, m_two, diff); } res = 1.0 - (hamming_distance / (double) bv_sz); - #else - rational r(diff); - r /= m_powers(bv_sz); - double dbl = r.get_double(); - res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl; - #endif TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << " ; SZ = " << bv_sz << std::endl; ); @@ -891,205 +814,36 @@ public: if (negated) { if (m_mpz_manager.gt(x, y)) - { - /*mpz diff; - m_mpz_manager.sub(x, y, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -/* mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_gt = 0; - unsigned curr_gt = 0; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 1; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 0; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); - m_mpz_manager.del(x_copy); - m_mpz_manager.del(y_copy);*/ -#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = 1.0 - n.get_double(); + double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; - //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } } else { if (m_mpz_manager.le(x, y)) - { - /*mpz diff; - m_mpz_manager.sub(y, x, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -/* mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_le = 1; - unsigned curr_le = 1; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_le = curr_le; - curr_le = 0; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_le = curr_le; - curr_le = 1; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/ -#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = 1.0 - n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } -/* else if (m_bv_util.is_bv_sle(n)) { // x <= y - app * a = to_app(n); - SASSERT(a->get_num_args() == 2); - const mpz & x = get_value(a->get_arg(0)); - const mpz & y = get_value(a->get_arg(1)); - int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); - - mpz x_unsigned; - mpz y_unsigned; - const mpz & p = m_powers(bv_sz); - const mpz & p_half = m_powers(bv_sz-1); - if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } - if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); } - - if (negated) { - if (x_unsigned > y_unsigned) - res = 1.0; - else { - mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_gt = 0; - unsigned curr_gt = 0; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 1; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 0; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); - m_mpz_manager.del(x_copy); - m_mpz_manager.del(y_copy); - } - } - else { - if (x_unsigned <= y_unsigned) - res = 1.0; - else { - mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_le = 1; - unsigned curr_le = 1; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_le = curr_le; - curr_le = 0; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_le = curr_le; - curr_le = 1; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2); - } - } - TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << - m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); - - m_mpz_manager.del(x_unsigned); - m_mpz_manager.del(y_unsigned); - }*/ - else if (m_bv_util.is_bv_sle(n)) { // x <= y + else if (m_bv_util.is_bv_sle(n)) { // x <= y app * a = to_app(n); SASSERT(a->get_num_args() == 2); mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0))); @@ -1102,61 +856,32 @@ public: if (negated) { if (x > y) - { - /*mpz diff; - m_mpz_manager.sub(x, y, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= p; - double dbl = 1.0 - n.get_double(); - //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } else { if (x <= y) - { - /*mpz diff; - m_mpz_manager.sub(y, x, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; - double dbl = 1.0 - n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); @@ -1171,11 +896,7 @@ public: expr * child = a->get_arg(0); if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); -#if _DIRTY_UP_ - res = is_top_expr(child) ? 0.0 : score_bool(child, true); -#else res = score_bool(child, true); -#endif } else if (m_manager.is_distinct(n)) { app * a = to_app(n); @@ -1199,25 +920,11 @@ public: SASSERT(res >= 0.0 && res <= 1.0); -#if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); if (afid == m_bv_util.get_family_id()) -#endif -#if _WEIGHT_DIST_ == 1 -#if _WEIGHT_TOGGLE_ - if (res < 1.0) res *= m_weight_dist_factor; -#else - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; -#endif -#elif _WEIGHT_DIST_ == 2 - res *= res; -#elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; -#elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; -#endif + if (res < 1.0) res *= m_scale_unsat; TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; @@ -1268,33 +975,6 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } - ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); @@ -1306,13 +986,17 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { - if (sz == 1) - return get_constants(); + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as) { + unsigned sz = as.size(); + if (sz == 1) { + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return get_constants(); + } + m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1326,35 +1010,6 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - return 0; - } - - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); - // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - return m_temp_constants; - } - ptr_vector & get_unsat_constants_walksat(expr * e) { if (!e || m_temp_constants.size()) return m_temp_constants; @@ -1368,420 +1023,89 @@ public: return m_temp_constants; } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - return m_temp_constants; - } + ptr_vector & get_unsat_constants(ptr_vector const & as) { + if (m_walksat) + { + expr * e = get_unsat_assertion(as); - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); - if (!q) - return m_temp_constants; - - return go_deeper(q); - } - - void go_deeper_only(expr * e) { - //if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned cnt_unsat = 0, pos = -1; - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q); - } - go_deeper(args[pos]); - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - go_deeper(q); - } - } - //} - else - { - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - } - } - - ptr_vector & get_unsat_constants_only(expr * e) { - if (e && !m_temp_constants.size()) - go_deeper_only(e); - - return m_temp_constants; - } - - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); - - if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + if (!e) { m_temp_constants.reset(); return m_temp_constants; } - else - return get_constants(); - } - else { - m_temp_constants.reset(); -#if _FOCUS_ == 1 -#if _UCT_ - unsigned pos = -1; - value_score vscore; -#if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); - -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } -#else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); -// for (unsigned i = 0; i < m_where_false.size(); i++) { -// expr * e = m_list_false[i]; - vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); -#elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; -#elif _UCT_ == 3 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); -#endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - } -#endif - if (pos == static_cast(-1)) - return m_temp_constants; - -#if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; - m_touched++; -#elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; -#endif - expr * e = g->form(pos); -// expr * e = m_list_false[pos]; - -#elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } - } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); -#elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - expr * e = m_list_false[get_random_uint(16) % sz]; -#elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; -#else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); -#endif return get_unsat_constants_walksat(e); -#elif _FOCUS_ == 2 -#if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; -#else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; -#endif - return get_unsat_constants_crsat(g, sz, pos); -#else - return get_unsat_constants_gsat(g, sz); -#endif } + else + return get_unsat_constants_gsat(as); } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); - + expr * get_unsat_assertion(ptr_vector const & as) { + unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_zero)) - return g->form(0); + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return as[0]; else return 0; } - m_temp_constants.reset(); -#if _FOCUS_ == 1 -#if _UCT_ + unsigned pos = -1; - value_score vscore; -#if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - - for (unsigned i = start_index; i < sz; i++) + if (m_ucb) { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score + _UCT_EPS_; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score + _UCT_EPS_; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } -#else - double max = -1.0; + value_score vscore; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); -#elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; -#elif _UCT_ == 3 + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); +#if _UCT_ == 3 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } -#endif - if (pos == static_cast(-1)) - return 0; + if (pos == static_cast(-1)) + return 0; -#if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; - m_touched++; -#elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; -#endif + m_scores.find(as[pos]).touched++; + m_touched++; // return m_list_false[pos]; - return g->form(pos); - -#elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _BFS_ == 1 - unsigned int pos = flip % sz; - return get_unsat_assertion(g, sz, pos); -#elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _REAL_RS_ + else + { + unsigned cnt_unsat = 0; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + } + + return as[pos]; +#if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; sz = m_where_false.size(); if (sz == 0) return 0; return m_list_false[get_random_uint(16) % sz]; -#elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return0; - else - return m_list_false[flip % sz]; -#else - unsigned int pos = get_random_uint(16) % sz; - return get_unsat_assertion(g, sz, pos); -#endif - return g->form(pos); -#elif _FOCUS_ == 2 -#if _BFS_ - unsigned int pos = flip % sz; -#else - unsigned int pos = get_random_uint(16) % sz; -#endif - return get_unsat_constants_crsat(g, sz, pos); #endif } - expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { - unsigned sz = g->size(); - + expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + unsigned sz = as.size(); if (sz == 1) return 0; - m_temp_constants.reset(); - + unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; if (pos == static_cast(-1)) return 0; - return g->form(pos); + return as[pos]; } }; From 39ea6234a4ae1b3588d1c4b6750c21382cae6b4d Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 01:07:30 +0100 Subject: [PATCH 191/646] Fixed bug with VNS repick. --- src/tactic/sls/sls_compilation_settings.h | 2 +- src/tactic/sls/sls_engine.cpp | 22 +++++++++++++++++----- src/tactic/sls/sls_tracker.h | 7 ++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 9add78daa..a649bc9ed 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -23,7 +23,7 @@ Notes: #define _SLS_COMPILATION_SETTINGS_H_ // shall we use addition/subtraction? -#define _USE_ADDSUB_ 0 +#define _USE_ADDSUB_ 1 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index c240a0c51..af8ae1df2 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_base = p.restart_base(); m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. + if (m_walksat_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); + if (m_vns_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); } void sls_engine::checkpoint() { @@ -435,19 +441,25 @@ lbool sls_engine::search() { if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); - /*if (m_vns_repick && (new_const == static_cast(-1))) + if (m_vns_repick && (new_const == static_cast(-1))) { - expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); + expr * q = m_tracker.get_new_unsat_assertion(m_assertions); if (q) { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); + + if (new_const != static_cast(-1)) { + func_decl * fd = to_evaluate2[new_const]; + score = serious_score(fd, new_value); + continue; + } } - }*/ + } if (new_const == static_cast(-1)) { score = old_score; - if (m_walksat && m_walksat_repick) + if (m_walksat_repick) m_evaluator.randomize_local(m_assertions); else m_evaluator.randomize_local(to_evaluate); diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 65011dc8d..7b48057d4 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -76,7 +76,7 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; - + unsigned m_last_pos; unsigned m_walksat; unsigned m_ucb; double m_ucb_constant; @@ -1082,6 +1082,7 @@ public: return 0; } + m_last_pos = pos; return as[pos]; #if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; @@ -1093,7 +1094,7 @@ public: #endif } - expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + expr * get_new_unsat_assertion(ptr_vector const & as) { unsigned sz = as.size(); if (sz == 1) return 0; @@ -1101,7 +1102,7 @@ public: unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; + if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; if (pos == static_cast(-1)) return 0; From b5a9e0a1f5ab1cf5df67baa068eec0963df55be2 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 16:10:44 +0100 Subject: [PATCH 192/646] Backup before I touch early pruning ... --- src/tactic/sls/sls_compilation_settings.h | 3 --- src/tactic/sls/sls_engine.cpp | 30 +++++++++++++---------- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_evaluator.h | 4 +-- src/tactic/sls/sls_tracker.h | 9 ------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index a649bc9ed..5c837b4b2 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,9 +22,6 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index af8ae1df2..5d4df237e 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) { m_walksat = p.walksat(); m_walksat_repick = p.walksat_repick(); m_paws_sp = p.paws_sp(); + m_paws = m_paws_sp < 1024; m_wp = p.wp(); m_vns_mc = p.vns_mc(); m_vns_repick = p.vns_repick(); @@ -173,7 +174,6 @@ bool sls_engine::what_if( // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { - m_tracker.reset_equal_scores(); best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); else { -#if _USE_ADDSUB_ if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; move_type mt = (move_type)rnd_mv; // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; -#else - move_type mt = MV_FLIP; -#endif unsigned bit = 0; switch (mt) @@ -308,8 +304,9 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - m_tracker.reset_equal_scores(); - + //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); + //for (unsigned j = 0; j < to_evaluate.size(); j++) { + //unsigned i = (j + offset) % to_evaluate.size(); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -328,7 +325,6 @@ double sls_engine::find_best_move( } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); @@ -341,7 +337,6 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } -#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(fd, i, temp, new_score, best_const, best_value)) @@ -418,7 +413,7 @@ lbool sls_engine::search() { #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - + // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { @@ -426,6 +421,7 @@ lbool sls_engine::search() { goto bailout; } + // random walk with probability wp / 1024 if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); @@ -436,14 +432,18 @@ lbool sls_engine::search() { old_score = score; new_const = (unsigned)-1; + // find best increasing move score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); + // repick assertion if no increasing move was found previously if (m_vns_repick && (new_const == static_cast(-1))) { expr * q = m_tracker.get_new_unsat_assertion(m_assertions); + // only apply if another unsatisfied assertion actually exists if (q) { ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); @@ -457,6 +457,7 @@ lbool sls_engine::search() { } } + // randomize if no increasing move was found if (new_const == static_cast(-1)) { score = old_score; if (m_walksat_repick) @@ -466,16 +467,19 @@ lbool sls_engine::search() { score = m_tracker.get_top_sum() / m_assertions.size(); - if (m_paws_sp < 1024) + // update assertion weights if a weigthing is enabled (sp < 1024) + if (m_paws) { for (unsigned i = 0; i < sz; i++) { expr * q = m_assertions[i]; + // smooth weights with probability sp / 1024 if (m_tracker.get_random_uint(10) < m_paws_sp) { if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) m_tracker.decrease_weight(q); } + // increase weights otherwise else { if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) @@ -484,6 +488,7 @@ lbool sls_engine::search() { } } } + // otherwise, apply most increasing move else { func_decl * fd = to_evaluate[new_const]; score = serious_score(fd, new_value); @@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; @@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { - /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter. I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ff0e55f24..94f3fa626 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -76,6 +76,7 @@ protected: unsigned m_wp; unsigned m_vns_mc; unsigned m_vns_repick; + unsigned m_paws; unsigned m_paws_sp; unsigned m_restart_base; unsigned m_restart_next; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 37bfa5a2d..200a0e380 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -37,9 +37,7 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; -#if _EARLY_PRUNE_ vector > m_traversal_stack_bool; -#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -753,7 +751,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // Andreas: Should actually always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7b48057d4..a815c9ad3 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -92,7 +92,6 @@ private: #endif obj_map m_weights; double m_top_sum; - unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -148,14 +147,6 @@ public: return sum / count; } - void reset_equal_scores() { - m_equal_scores = 1; - } - - unsigned inc_equal_scores() { - return ++m_equal_scores; - } - inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); } From c4fb21cca1e1d01cddb2690bc3fa6a91746f36a5 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 23 Apr 2014 14:52:18 +0100 Subject: [PATCH 193/646] Moved parameters to the right file. Almost clean. --- src/tactic/sls/sls_compilation_settings.h | 5 +-- src/tactic/sls/sls_engine.cpp | 38 +++++++++++------------ src/tactic/sls/sls_engine.h | 3 +- src/tactic/sls/sls_evaluator.h | 5 --- src/tactic/sls/sls_params.pyg | 20 ++++++++++-- src/tactic/sls/sls_tracker.h | 33 +++++++++----------- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 5c837b4b2..707802cf4 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,10 +22,7 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +// should we use unsat-structures as done in SLS 4 SAT? #define _REAL_RS_ 0 -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5d4df237e..a1c72609c 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + m_early_prune = p.early_prune(); + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) NOT_IMPLEMENTED_YET(); @@ -117,7 +119,7 @@ double sls_engine::top_score() { m_tracker.set_top_sum(top_sum); - return top_sum / (double)sz; + return top_sum; } double sls_engine::rescore() { @@ -129,21 +131,21 @@ double sls_engine::rescore() { double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); else - return 0.0; + return -DBL_MAX; } // checks whether the score outcome of a given move is better than the previous score @@ -160,11 +162,11 @@ bool sls_engine::what_if( m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif -#if _EARLY_PRUNE_ - double r = incremental_score_prune(fd, temp); -#else - double r = incremental_score(fd, temp); -#endif + double r; + if (m_early_prune) + r = incremental_score_prune(fd, temp); + else + r = incremental_score(fd, temp); #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl;); @@ -342,11 +344,8 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; } - // reset to what it was before - double check = incremental_score(fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double } } } - // reset to what it was before - double check = incremental_score(fd, old_value); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -408,7 +406,10 @@ lbool sls_engine::search() { checkpoint(); m_stats.m_moves++; if (m_stats.m_moves % m_restart_base == 0) + { m_tracker.ucb_forget(m_assertions); + //score = rescore(); + } #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); @@ -425,7 +426,7 @@ lbool sls_engine::search() { if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); - score = m_tracker.get_top_sum() / sz; + score = m_tracker.get_top_sum(); continue; } @@ -465,7 +466,7 @@ lbool sls_engine::search() { else m_evaluator.randomize_local(to_evaluate); - score = m_tracker.get_top_sum() / m_assertions.size(); + score = m_tracker.get_top_sum(); // update assertion weights if a weigthing is enabled (sp < 1024) if (m_paws) @@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { assert_expr(g->form(i)); verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; lbool res = operator()(); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 94f3fa626..ac8610871 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -81,8 +81,7 @@ protected: unsigned m_restart_base; unsigned m_restart_next; unsigned m_restart_init; - - ptr_vector m_old_values; + unsigned m_early_prune; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 200a0e380..e4cf3c466 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -554,9 +554,7 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -599,9 +597,6 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ - m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index cc3e05966..98875b20d 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -2,7 +2,21 @@ def_module_params('sls', export=True, description='Experimental Stochastic Local Search Solver (for QFBV only).', params=(max_memory_param(), - ('restarts', UINT, UINT_MAX, '(max) number of restarts'), - ('plateau_limit', UINT, 10, 'pleateau limit'), - ('random_seed', UINT, 0, 'random seed') + ('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'), + ('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'), + ('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'), + ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), + ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), + ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), + ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), + ('paws_init', UINT, 40, 'initial/minimum assertion weights'), + ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), + ('wp', UINT, 0, 'random walk with probability wp / 1024'), + ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), + ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), + ('restart_base', UINT, 100, 'base restart interval given by moves per run'), + ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), + ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index a815c9ad3..507596273 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -44,11 +44,9 @@ class sls_tracker { unsynch_mpz_manager * m; mpz value; double score; -#if _EARLY_PRUNE_ double score_prune; unsigned has_pos_occ; unsigned has_neg_occ; -#endif unsigned distance; // max distance from any root unsigned touched; value_score & operator=(const value_score & other) { @@ -122,6 +120,7 @@ public: m_paws_init = p.paws_init(); } + /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. unsigned get_formula_size() { return m_scores.size(); } @@ -145,7 +144,7 @@ public: } return sum / count; - } + }*/ inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); @@ -417,6 +416,8 @@ public: } } + /* Andreas: Used this at some point to have values for the non-top-level expressions. + However, it did not give better performance but even cause some additional m/o - is not used currently. void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { if (m_manager.is_and(e) || m_manager.is_or(e)) { app * a = to_app(e); @@ -445,7 +446,7 @@ public: find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + }*/ void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); @@ -455,8 +456,6 @@ public: expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); - else - printf("this is already in ...\n"); for_each_expr(proc, visited, e); } @@ -464,7 +463,6 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - // Andreas: Maybe not fully correct. ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -488,15 +486,16 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - if (!m_weights.contains(e)) + + // initialize weights + if (!m_weights.contains(e)) m_weights.insert(e, m_paws_init); + + // positive/negative occurences used for early pruning + setup_occs(as[i]); } -#if _EARLY_PRUNE_ - for (unsigned i = 0; i < sz; i++) - setup_occs(as[i]); -#endif - + // initialize ucb total touched value (individual ones are always initialized to 1) m_touched = m_ucb_init ? as.size() : 1; } @@ -738,7 +737,6 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); @@ -764,7 +762,6 @@ public: const mpz & v1 = get_value(arg1); if (negated) { - //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -1051,10 +1048,8 @@ public: // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); -#if _UCT_ == 3 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); -#endif + //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } if (pos == static_cast(-1)) From b3924d85ed2e0db2daddc5ea31234685d9e84fc7 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Fri, 25 Apr 2014 13:56:15 +0100 Subject: [PATCH 194/646] Cleaned up final SLS version. Enjoy! --- src/tactic/sls/sls_compilation_settings.h | 28 ---- src/tactic/sls/sls_engine.cpp | 43 ++++-- src/tactic/sls/sls_engine.h | 2 + src/tactic/sls/sls_evaluator.h | 8 +- src/tactic/sls/sls_params.pyg | 6 +- src/tactic/sls/sls_tracker.h | 153 ++++++++-------------- 6 files changed, 94 insertions(+), 146 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 707802cf4..e69de29bb 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -1,28 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sls_compilation_constants.h - -Abstract: - - Stochastic Local Search (SLS) compilation constants - -Author: - - Christoph (cwinter) 2014-03-19 - -Notes: - - This file should go away completely once we have evaluated all options. - ---*/ - -#ifndef _SLS_COMPILATION_SETTINGS_H_ -#define _SLS_COMPILATION_SETTINGS_H_ - -// should we use unsat-structures as done in SLS 4 SAT? -#define _REAL_RS_ 0 - -#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index a1c72609c..269790902 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_init = p.restart_init(); m_early_prune = p.early_prune(); + m_random_offset = p.random_offset(); + m_rescore = p.rescore(); // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) @@ -174,6 +176,9 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif + // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection. + // r += 0.0001 * m_tracker.get_random_uint(8); + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { best_score = r; @@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) { if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + + // Andreas: The other option would be to scale the probability for flips according to the bit-width. + /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt); + rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3); + if (rnd_mv > 3) rnd_mv = 0; */ + move_type mt = (move_type)rnd_mv; - // inversion doesn't make sense, let's do a flip instead. + // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true? if (mt == MV_INV) mt = MV_FLIP; unsigned bit = 0; @@ -306,10 +317,13 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); - //for (unsigned j = 0; j < to_evaluate.size(); j++) { - //unsigned i = (j + offset) % to_evaluate.size(); - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double unsigned bv_sz; double new_score = score; - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -405,15 +425,16 @@ lbool sls_engine::search() { while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; + + // Andreas: Every base restart interval ... if (m_stats.m_moves % m_restart_base == 0) { + // ... potentially smooth the touched counters ... m_tracker.ucb_forget(m_assertions); - //score = rescore(); + // ... or normalize the top-level score. + if (m_rescore) score = rescore(); } -#if _REAL_RS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) @@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - lbool res = operator()(); if (res == l_true) { diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ac8610871..8158808fa 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -82,6 +82,8 @@ protected: unsigned m_restart_next; unsigned m_restart_init; unsigned m_early_prune; + unsigned m_random_offset; + unsigned m_rescore; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index e4cf3c466..61afb7457 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -22,7 +22,6 @@ Notes: #include"model_evaluator.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" @@ -540,19 +539,16 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); -#if _REAL_RS_ + new_score = m_tracker.score(cur); if (m_tracker.is_top_expr(cur)) { + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); if (m_mpz_manager.eq(new_value,m_one)) m_tracker.make_assertion(cur); else m_tracker.break_assertion(cur); } -#endif - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index 98875b20d..ad7a22675 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -8,15 +8,19 @@ def_module_params('sls', ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'), ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), ('paws_init', UINT, 40, 'initial/minimum assertion weights'), ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), - ('wp', UINT, 0, 'random walk with probability wp / 1024'), + ('wp', UINT, 100, 'random walk with probability wp / 1024'), ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), + ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 507596273..4356bcc9b 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -80,14 +80,13 @@ private: double m_ucb_constant; unsigned m_ucb_init; double m_ucb_forget; + double m_ucb_noise; unsigned m_touched; double m_scale_unsat; unsigned m_paws_init; -#if _REAL_RS_ - ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; -#endif + unsigned m_track_unsat; obj_map m_weights; double m_top_sum; @@ -116,8 +115,12 @@ public: m_ucb_constant = p.walksat_ucb_constant(); m_ucb_init = p.walksat_ucb_init(); m_ucb_forget = p.walksat_ucb_forget(); + m_ucb_noise = p.walksat_ucb_noise(); m_scale_unsat = p.scale_unsat(); m_paws_init = p.paws_init(); + // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy. + // If you want to use it, you will also need to change comments in the assertion selection. + m_track_unsat = 0;//p.track_unsat(); } /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. @@ -254,53 +257,6 @@ public: return m_uplinks.find(n); } -#if _REAL_RS_ - void debug_real(goal_ref const & g, unsigned flip) - { - unsigned count = 0; - for (unsigned i = 0; i < g->size(); i++) - { - expr * e = g->form(i); - if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is unsat but not in unsat list\n", i); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - expr * q = m_list_false[pos]; - if (q != e) - { - printf("iteration %d: ", flip); - printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); - exit(4); - } - } - - if (m_mpz_manager.eq(get_value(e),m_zero)) - count++; - } - - // should be true now that duplicate assertions are removed - if (count != m_where_false.size()) - { - printf("iteration %d: ", flip); - printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); - exit(4); - } - } -#endif - inline void ucb_forget(ptr_vector & as) { if (m_ucb_forget < 1.0) { @@ -474,14 +430,15 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); -#if _REAL_RS_ - m_list_false = new expr*[sz]; - //for (unsigned i = 0; i < sz; i++) - //{ - // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - // break_assertion(g->form(i)); - //} -#endif + if (m_track_unsat) + { + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + { + if (m_mpz_manager.eq(get_value(as[i]), m_zero)) + break_assertion(as[i]); + } + } for (unsigned i = 0; i < sz; i++) { @@ -515,44 +472,36 @@ public: return m_weights.find(e); } -#if _REAL_RS_ void make_assertion(expr * e) { - if (m_where_false.contains(e)) + if (m_track_unsat) { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) + if (m_where_false.contains(e)) { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } } - //else - //printf("Erasing %d from %d to %d\n", e, pos); -// m_list_false[m_where_false.size()] = 0; -// printf("Going in %d\n", m_where_false.size()); } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); } void break_assertion(expr * e) { - //printf("I'm broken... that's still fine.\n"); - if (!m_where_false.contains(e)) + if (m_track_unsat) { - //printf("This however is not so cool...\n"); - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + } } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); } -#endif void show_model(std::ostream & out) { unsigned sz = get_num_constants(); @@ -1043,24 +992,38 @@ public: { value_score vscore; double max = -1.0; + // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit. + /* for (unsigned i = 0; i < m_where_false.size(); i++) { + expr * e = m_list_false[i]; */ for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; -// for (unsigned i = 0; i < m_where_false.size(); i++) { -// expr * e = m_list_false[i]; - vscore = m_scores.find(e); - //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (m_mpz_manager.neq(get_value(e), m_one)) + { + vscore = m_scores.find(e); + // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise. + // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); + if (q > max) { max = q; pos = i; } + } } if (pos == static_cast(-1)) return 0; - m_scores.find(as[pos]).touched++; m_touched++; -// return m_list_false[pos]; + m_scores.find(as[pos]).touched++; + // Andreas: Also part of track_unsat data structures. Additionally disable the previous line! + /* m_last_pos = pos; + m_scores.find(m_list_false[pos]).touched++; + return m_list_false[pos]; */ } else { + // Andreas: The track_unsat data structures for random assertion selection. + /* sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; */ + unsigned cnt_unsat = 0; for (unsigned i = 0; i < sz; i++) if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; @@ -1070,14 +1033,6 @@ public: m_last_pos = pos; return as[pos]; -#if _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return 0; - return m_list_false[get_random_uint(16) % sz]; -#endif } expr * get_new_unsat_assertion(ptr_vector const & as) { From e34b5edf27d91e5546264313c7027781dfac2c72 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 17:17:47 +0100 Subject: [PATCH 195/646] BVSLS comments Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_params.pyg | 2 +- src/tactic/sls/sls_tracker.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index ad7a22675..bf5bd181a 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -19,7 +19,7 @@ def_module_params('sls', ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), - ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('random_offset', BOOL, 1, 'use random offset for candidate evaluation'), ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 4356bcc9b..d58f94af2 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -831,7 +831,9 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. + // Precondition: Assertion set is in NNF. + // Also: careful about the unsat assertion scaling further down. + if (m_manager.is_and(child) || m_manager.is_or(child)) NOT_IMPLEMENTED_YET(); res = score_bool(child, true); } From a02c59c1bc76efe5c9905f073fd9ffcac2b7b617 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:03:35 +0100 Subject: [PATCH 196/646] removed unused file Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 0 src/tactic/sls/sls_engine.cpp | 1 - src/tactic/sls/sls_engine.h | 1 - src/tactic/sls/sls_tracker.h | 1 - 4 files changed, 3 deletions(-) delete mode 100644 src/tactic/sls/sls_compilation_settings.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 269790902..67dba0237 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -27,7 +27,6 @@ Notes: #include"cooperate.h" #include"luby.h" -#include"sls_compilation_settings.h" #include"sls_params.hpp" #include"sls_engine.h" diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8158808fa..8a8a57e0e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -24,7 +24,6 @@ Notes: #include"model_converter.h" #include"goal.h" -#include"sls_compilation_settings.h" #include"sls_tracker.h" #include"sls_evaluator.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index d58f94af2..186fae250 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,7 +25,6 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" class sls_tracker { From fc0cdcfd2968b95bce0c9aee9a4363b5e0b9af9b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:11:30 +0100 Subject: [PATCH 197/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 186fae250..73355197a 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,6 +25,7 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" +#include"sls_params.hpp" #include"sls_powers.h" class sls_tracker { @@ -1052,4 +1053,4 @@ public: } }; -#endif \ No newline at end of file +#endif From 60753bf46b822191969e6cd70fbb9e3d1aec0d06 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:49:35 +0100 Subject: [PATCH 198/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8a8a57e0e..b056c438e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -136,8 +136,8 @@ protected: void mk_random_move(ptr_vector & unsat_constants); - //inline double get_restart_armin(unsigned cnt_restarts); - inline unsigned check_restart(unsigned curr_value); + //double get_restart_armin(unsigned cnt_restarts); + unsigned check_restart(unsigned curr_value); }; #endif From 54cd1ea5e6ae90e0150ca712d190594c3812e451 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:54:08 +0100 Subject: [PATCH 199/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 67dba0237..5b32e5790 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,6 +16,7 @@ Author: Notes: --*/ +#include #include #include"map.h" From 6b9c5dbfc061eaa40a2e3a02a9505119ec8b71e2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 22:03:26 +0100 Subject: [PATCH 200/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5b32e5790..c0c319ab4 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -581,7 +581,7 @@ lbool sls_engine::operator()() { } /* Andreas: Needed for Armin's restart scheme if we don't want to use loops. -inline double sls_engine::get_restart_armin(unsigned cnt_restarts) +double sls_engine::get_restart_armin(unsigned cnt_restarts) { unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; @@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts) } */ -inline unsigned sls_engine::check_restart(unsigned curr_value) +unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { From aa0980b83b8d981e754e738d18ea1036391806a1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 11 Sep 2014 00:27:37 +0100 Subject: [PATCH 201/646] merge fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tactic.cpp | 1413 +-------------------------------- 1 file changed, 30 insertions(+), 1383 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 6e1102dd2..9bbed20bb 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,1378 +16,30 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" -#include"luby.h" -#include "ctx_simplify_tactic.h" - -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 1 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 4.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.5 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick clause when randomizing in a plateau or use the current one? -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 20.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// do we gradually reduce the touched values of _UCT_? -#define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.5 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 0 - -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 - -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? -#define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) - InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) - InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) - InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) - InvalidConfiguration; -#endif - +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; - - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_restart_limit; - unsigned m_max_restarts; - unsigned m_plateau_limit; - - ptr_vector m_old_values; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - double get_restart_armin(unsigned cnt_restarts) - { - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow(_RESTART_CONST_ARMIN_, inner_id + 1); - } - - inline unsigned check_restart(unsigned curr_value) - { - if (curr_value > m_restart_limit) - { -#if _RESTART_SCHEME_ == 5 - m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); -#elif _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); -#elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 1 - if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; - else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; -#else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif - return 0; - } - return 1; - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - top_sum += m_tracker.get_score(e); - } - - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - -#if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); -#endif - - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; - } -#endif - - // checks whether the score outcome of a given move is better than the previous score - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - -#if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); -#else - double r = incremental_score(g, fd, temp); -#endif - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - -// if (r >= best_score) { - if (r > best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // same as what_if, but only applied to the score of a specific atom, not the total score - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.add(old_value, add_value, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - - } - - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - } - - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(ptr_vector & unsat_constants) - { - unsigned rnd_mv = 0; - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - - mpz new_value; - - sort * srt = fd->get_range(); - if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { -#if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; -#else - mt = MV_FLIP; -#endif - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } - - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } - - void mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); - } - - // will use VNS to ignore some possible moves and increase the flips per second - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } -#endif - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - return new_score; - } - - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - - m_old_values.reset(); - - return 0; - } - - // what_if version needed in the context of 2nd intensification try, combining local and global score - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // find_best_move version needed in the context of 2nd intensification try - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; - } - - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; - } - - // main search loop - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - unsigned plateau_cnt = 0; - - score = rescore(g); - unsigned sz = g->size(); -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - checkpoint(); - m_stats.m_moves++; - -#if _UCT_FORGET_ - if (m_stats.m_moves % _UCT_FORGET_ == 0) - m_tracker.uct_forget(g); -#endif - -#if _REAL_RS_ || _REAL_PBFS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } - continue; -#endif - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - old_score = score; - new_const = (unsigned)-1; - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - - if (new_const == static_cast(-1)) { - score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); - else -#endif -#if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); -#else - m_evaluator.randomize_local(to_evaluate); -#endif -#endif - -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } else { - func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - // main search loop - lbool search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 0.99999) { -// if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } - while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; - verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -1395,16 +47,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -1412,14 +64,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -1428,40 +79,36 @@ public: } virtual void cleanup() { - imp * d = m_imp; + sls_engine * d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - d = m_imp; + std::swap(d, m_engine); } dealloc(d); - d = alloc(imp, m, m_params, m_stats); - #pragma omp critical (tactic_cancel) - { - m_imp = d; - } } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + sls_engine::stats const & stats = m_engine->get_stats(); + double seconds = stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", stats.m_restarts); + st.update("sls full evals", stats.m_full_evals); + st.update("sls incr evals", stats.m_incr_evals); + st.update("sls incr evals/sec", stats.m_incr_evals / seconds); + st.update("sls FLIP moves", stats.m_flips); + st.update("sls INC moves", stats.m_incs); + st.update("sls DEC moves", stats.m_decs); + st.update("sls INV moves", stats.m_invs); + st.update("sls moves", stats.m_moves); + st.update("sls moves/sec", stats.m_moves / seconds); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; From 387f036f93287e912650b3738ef896d730b98152 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 19 Dec 2014 12:32:57 +0000 Subject: [PATCH 202/646] BV-SLS optimization Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 73355197a..89ef57871 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -89,6 +89,7 @@ private: unsigned m_track_unsat; obj_map m_weights; double m_top_sum; + obj_hashtable m_temp_seen; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -440,6 +441,7 @@ public: } } + m_temp_seen.reset(); for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; @@ -630,7 +632,14 @@ public: app * a = to_app(n); expr * const * args = a->get_args(); for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); + { + expr * child = args[i]; + if (!m_temp_seen.contains(child)) + { + setup_occs(child, false); + m_temp_seen.insert(child); + } + } } else if (m_manager.is_not(n)) { @@ -638,8 +647,7 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); + SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child)); setup_occs(child, true); } else From 6818e850e99faf6d6c63a44e5aadddeaa2e992a2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 15:59:20 +0000 Subject: [PATCH 203/646] Disabled BV-SLS as default tactic in anticipation for integration with the unstable branch. Signed-off-by: Christoph M. Wintersteiger --- src/tactic/portfolio/default_tactic.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 53da9a159..5a5cbcf94 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -32,8 +32,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), - // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), From c982f870255edeed04c1e274fa0ff3213d358587 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 11 Feb 2014 17:44:59 +0000 Subject: [PATCH 204/646] sls tactic default --- src/tactic/portfolio/smt_strategic_solver.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index f63b4fd8c..586c3a349 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,14 +37,11 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -#include"sls_tactic.h" - tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - // return mk_qfbv_tactic(m, p); - return mk_qfbv_sls_tactic(m, p); + return mk_qfbv_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") From dfe2d945e94eb22b1e59958525a3ca0731f6aedb Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 18 Feb 2014 14:01:47 +0000 Subject: [PATCH 205/646] some extensions/modifications. versions added. --- src/tactic/portfolio/default_tactic.cpp | 2 +- src/tactic/sls/sls_evaluator.h | 243 +-------- src/tactic/sls/sls_tactic.cpp | 661 ++++++++++++++++++++++-- src/tactic/sls/sls_tracker.h | 640 ++++++++--------------- versions/z3-wsat-0.01.txt | 4 +- versions/z3-wsat-0.01b.txt | 4 +- 6 files changed, 872 insertions(+), 682 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 5a5cbcf94..b28b7bec0 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -32,7 +32,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 61afb7457..61305386e 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -20,8 +20,6 @@ Notes: #ifndef _SLS_EVALUATOR_H_ #define _SLS_EVALUATOR_H_ -#include"model_evaluator.h" - #include"sls_powers.h" #include"sls_tracker.h" @@ -36,7 +34,6 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; - vector > m_traversal_stack_bool; public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -96,7 +93,7 @@ public: SASSERT(n_args == 1); const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); - m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); + m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); break; } case OP_EQ: { @@ -522,64 +519,11 @@ public: } } - void run_serious_update(unsigned cur_depth) { - // precondition: m_traversal_stack contains the entry point(s) - expr_fast_mark1 visited; - mpz new_value; - - double new_score; - - SASSERT(cur_depth < m_traversal_stack.size()); - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - (*this)(to_app(cur), new_value); - m_tracker.set_value(cur, new_value); - - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - { - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - if (m_mpz_manager.eq(new_value,m_one)) - m_tracker.make_assertion(cur); - else - m_tracker.break_assertion(cur); - } - - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack[next_d].push_back(next); - visited.mark(next); - } - } - } - } - - cur_depth_exprs.reset(); - cur_depth--; - } - - m_mpz_manager.del(new_value); - } - void run_update(unsigned cur_depth) { // precondition: m_traversal_stack contains the entry point(s) expr_fast_mark1 visited; mpz new_value; - double new_score; - SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -589,10 +533,8 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + m_tracker.set_score(cur, m_tracker.score(cur)); + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -627,7 +569,8 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } - run_serious_update(max_depth); + + run_update(max_depth); } void update(func_decl * fd, const mpz & new_value) { @@ -641,174 +584,36 @@ public: run_update(cur_depth); } - void serious_update(func_decl * fd, const mpz & new_value) { - m_tracker.set_value(fd, new_value); - expr * ep = m_tracker.get_entry_point(fd); - unsigned cur_depth = m_tracker.get_distance(ep); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); - m_traversal_stack[cur_depth].push_back(ep); + void randomize_local(goal_ref const & g, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); - run_serious_update(cur_depth); - } + // Randomize _all_ candidates: - unsigned run_update_bool_prune(unsigned cur_depth) { - expr_fast_mark1 visited; + //// bool did_something = false; + //for (unsigned i = 0; i < unsat_constants.size(); i++) { + // func_decl * fd = unsat_constants[i]; + // mpz temp = m_tracker.get_random(fd->get_range()); + // // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) { + // // did_something = true; + // // } + // update(fd, temp); + // m_mpz_manager.del(temp); + //} - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); - - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - - prune_score = m_tracker.get_score_prune(cur); - m_tracker.set_score(cur, new_score); - - if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - - cur_depth_exprs.reset(); - cur_depth--; - - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } - - return pot_benefits; - } - - void run_update_prune(unsigned max_depth) { - // precondition: m_traversal_stack contains the entry point(s) - expr_fast_mark1 visited; - mpz new_value; - - unsigned cur_depth = max_depth; - SASSERT(cur_depth < m_traversal_stack.size()); - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - (*this)(to_app(cur), new_value); - m_tracker.set_value(cur, new_value); - // Andreas: Should actually always have uplinks ... - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - if (m_manager.is_bool(next)) - m_traversal_stack_bool[max_depth].push_back(next); - else - m_traversal_stack[next_d].push_back(next); - visited.mark(next); - } - } - } - } - - cur_depth_exprs.reset(); - cur_depth--; - } - - m_mpz_manager.del(new_value); - } - - unsigned update_prune(func_decl * fd, const mpz & new_value) { - m_tracker.set_value(fd, new_value); - expr * ep = m_tracker.get_entry_point(fd); - unsigned cur_depth = m_tracker.get_distance(ep); - - if (m_traversal_stack_bool.size() <= cur_depth) - m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); - - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune(cur_depth); - } - - void randomize_local(ptr_vector & unsat_constants) { // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; mpz temp = m_tracker.get_random(fd->get_range()); - - serious_update(fd, temp); - + update(fd, temp); m_mpz_manager.del(temp); - TRACE("sls", tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; + TRACE("sls", /*tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl;*/ + tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - - } - - void randomize_local(expr * e) { - randomize_local(m_tracker.get_constants(e)); - } - - void randomize_local(ptr_vector const & as) { - randomize_local(m_tracker.get_unsat_constants(as)); } }; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 9bbed20bb..c194af267 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,30 +16,619 @@ Author: Notes: --*/ +#include +#include"map.h" #include"nnf.h" +#include"cooperate.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"model_evaluator.h" #include"solve_eqs_tactic.h" +#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"propagate_values_tactic.h" -#include"ctx_simplify_tactic.h" -#include"elim_uncnstr_tactic.h" -#include"nnf_tactic.h" #include"stopwatch.h" +#include"propagate_values_tactic.h" #include"sls_tactic.h" -#include"sls_params.hpp" -#include"sls_engine.h" +#include"nnf_tactic.h" -class sls_tactic : public tactic { +#define _CNF_ 0 +#define _BFS_ 1 +#define _FOCUS_ 1 +#define _RESTARTS_ 0 +#define _TIMELIMIT_ 30 +#define _SCORE_AND_AVG_ 0 +#define _SCORE_OR_MUL_ 0 +#define _VNS_ 0 +#define _WEIGHT_DIST_ 3 +#define _WEIGHT_DIST_FACTOR_ 0.1 + +#include"sls_params.hpp" +#include"sls_evaluator.h" +#include"sls_tracker.h" + +class sls_tactic : public tactic { + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + + struct imp { + ast_manager & m_manager; + stats & m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + + unsigned m_max_restarts; + unsigned m_plateau_limit; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + + imp(ast_manager & m, params_ref const & p, stats & s) : + m_manager(m), + m_stats(s), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) + { + updt_params(p); + } + + ~imp() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); + } + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + static void collect_param_descrs(param_descrs & r) { + sls_params::collect_param_descrs(r); + } + + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_plateau_limit = p.plateau_limit(); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); + } + + bool full_eval(goal_ref const & g, model & mdl) { + bool res = true; + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(g->form(i), o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; + } + + double top_score(goal_ref const & g) { + #if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl; ); + return min; + #else + double top_sum = 0.0; + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + top_sum += m_tracker.get_score(g->form(i)); + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " AVG: " << top_sum / (double) sz << std::endl; ); + return top_sum / (double) sz; + #endif + } + + double rescore(goal_ref const & g) { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(g); + } + + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; + return top_score(g); + } + + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + #ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + #endif + + double r = incremental_score(g, fd, temp); + + #ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl; ); + + m_mpz_manager.del(old_value); + #endif + + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); + } + + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); + } + + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); + } + + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); + } + + void mk_random_move(goal_ref const & g) { + unsigned rnd_mv = 0; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; + + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; + + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + mpz new_value; + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range()); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + m_evaluator.update(fd, new_value); + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + + m_mpz_manager.del(new_value); + } + + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + lbool search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + do { + checkpoint(); + + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0 ; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl; ); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl; ); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + } + + score = incremental_score(g, fd, new_value); + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + } + + if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: Can it only be imprecise in one direction? + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } + while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); + m_evaluator.randomize_local(g, m_stats.m_moves); + //mk_random_move(g); + score = top_score(g); + //} + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + void operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + m_tracker.initialize(g); + lbool res = l_undef; + + do { + checkpoint(); + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + //if ((m_stats.m_restarts % 100) == 0) + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + + res = search(g); + + if (res == l_undef) + m_tracker.randomize(); + } + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout); ); + } + g->reset(); + } + else + mc = 0; + } + }; + ast_manager & m; params_ref m_params; - sls_engine * m_engine; + imp * m_imp; + stats m_stats; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_engine = alloc(sls_engine, m, p); + m_imp = alloc(imp, m, p, m_stats); } virtual tactic * translate(ast_manager & m) { @@ -47,16 +636,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_engine); + dealloc(m_imp); } virtual void updt_params(params_ref const & p) { m_params = p; - m_engine->updt_params(p); + m_imp->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); + imp::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -64,13 +653,14 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); + SASSERT(g->is_well_sorted()); + m_imp->m_produce_models = g->models_enabled(); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_engine->operator()(g, mc); + m_imp->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -79,36 +669,35 @@ public: } virtual void cleanup() { - sls_engine * d = alloc(sls_engine, m, m_params); + imp * d = alloc(imp, m, m_params, m_stats); #pragma omp critical (tactic_cancel) { - std::swap(d, m_engine); + std::swap(d, m_imp); } dealloc(d); } virtual void collect_statistics(statistics & st) const { - sls_engine::stats const & stats = m_engine->get_stats(); - double seconds = stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", stats.m_restarts); - st.update("sls full evals", stats.m_full_evals); - st.update("sls incr evals", stats.m_incr_evals); - st.update("sls incr evals/sec", stats.m_incr_evals / seconds); - st.update("sls FLIP moves", stats.m_flips); - st.update("sls INC moves", stats.m_incs); - st.update("sls DEC moves", stats.m_decs); - st.update("sls INV moves", stats.m_invs); - st.update("sls moves", stats.m_moves); - st.update("sls moves/sec", stats.m_moves / seconds); + double seconds = m_stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", m_stats.m_restarts); + st.update("sls full evals", m_stats.m_full_evals); + st.update("sls incr evals", m_stats.m_incr_evals); + st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); + st.update("sls FLIP moves", m_stats.m_flips); + st.update("sls INC moves", m_stats.m_incs); + st.update("sls DEC moves", m_stats.m_decs); + st.update("sls INV moves", m_stats.m_invs); + st.update("sls moves", m_stats.m_moves); + st.update("sls moves/sec", m_stats.m_moves / seconds); } virtual void reset_statistics() { - m_engine->reset_statistics(); + m_stats.reset(); } virtual void set_cancel(bool f) { - if (m_engine) - m_engine->set_cancel(f); + if (m_imp) + m_imp->set_cancel(f); } }; @@ -143,9 +732,6 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // conservative gaussian elimination. gaussian_p.set_uint("gaussian_max_occs", 2); - params_ref ctx_p; - ctx_p.set_uint("max_depth", 32); - ctx_p.set_uint("max_steps", 5000000); return and_then(and_then(mk_simplify_tactic(m), mk_propagate_values_tactic(m), using_params(mk_solve_eqs_tactic(m), gaussian_p), @@ -154,12 +740,17 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), +#if _CNF_ + // Andreas: We will probably never use this. CNF sucks. + mk_cnf_tactic(m, p)); +#else + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); +#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); - //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 89ef57871..1061bd90e 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,14 +20,6 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"for_each_expr.h" -#include"ast_smt2_pp.h" -#include"bv_decl_plugin.h" -#include"model.h" - -#include"sls_params.hpp" -#include"sls_powers.h" - class sls_tracker { ast_manager & m_manager; unsynch_mpz_manager & m_mpz_manager; @@ -36,26 +28,21 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; - + mpz m_zero, m_one, m_two; + struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; - double score_prune; - unsigned has_pos_occ; - unsigned has_neg_occ; unsigned distance; // max distance from any root - unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; - touched = other.touched; return *this; } }; @@ -67,29 +54,12 @@ private: typedef obj_map scores_type; typedef obj_map > uplinks_type; typedef obj_map > occ_type; - obj_hashtable m_top_expr; scores_type m_scores; uplinks_type m_uplinks; entry_point_type m_entry_points; ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; - unsigned m_last_pos; - unsigned m_walksat; - unsigned m_ucb; - double m_ucb_constant; - unsigned m_ucb_init; - double m_ucb_forget; - double m_ucb_noise; - unsigned m_touched; - double m_scale_unsat; - unsigned m_paws_init; - obj_map m_where_false; - expr** m_list_false; - unsigned m_track_unsat; - obj_map m_weights; - double m_top_sum; - obj_hashtable m_temp_seen; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -109,59 +79,6 @@ public: m_mpz_manager.del(m_two); } - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_walksat = p.walksat(); - m_ucb = p.walksat_ucb(); - m_ucb_constant = p.walksat_ucb_constant(); - m_ucb_init = p.walksat_ucb_init(); - m_ucb_forget = p.walksat_ucb_forget(); - m_ucb_noise = p.walksat_ucb_noise(); - m_scale_unsat = p.scale_unsat(); - m_paws_init = p.paws_init(); - // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy. - // If you want to use it, you will also need to change comments in the assertion selection. - m_track_unsat = 0;//p.track_unsat(); - } - - /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. - unsigned get_formula_size() { - return m_scores.size(); - } - - double get_avg_bw(goal_ref const & g) { - double sum = 0.0; - unsigned count = 0; - - for (unsigned i = 0; i < g->size(); i++) - { - m_temp_constants.reset(); - ptr_vector const & this_decls = m_constants_occ.find(g->form(i)); - unsigned sz = this_decls.size(); - for (unsigned i = 0; i < sz; i++) { - func_decl * fd = this_decls[i]; - m_temp_constants.push_back(fd); - sort * srt = fd->get_range(); - sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - count++; - } - } - - return sum / count; - }*/ - - inline void adapt_top_sum(expr * e, double add, double sub) { - m_top_sum += m_weights.find(e) * (add - sub); - } - - inline void set_top_sum(double new_score) { - m_top_sum = new_score; - } - - inline double get_top_sum() { - return m_top_sum; - } - inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); m_mpz_manager.set(m_scores.find(n).value, r); @@ -206,26 +123,6 @@ public: return get_score(ep); } - inline void set_score_prune(expr * n, double score) { - SASSERT(m_scores.contains(n)); - m_scores.find(n).score_prune = score; - } - - inline double & get_score_prune(expr * n) { - SASSERT(m_scores.contains(n)); - return m_scores.find(n).score_prune; - } - - inline unsigned has_pos_occ(expr * n) { - SASSERT(m_scores.contains(n)); - return m_scores.find(n).has_pos_occ; - } - - inline unsigned has_neg_occ(expr * n) { - SASSERT(m_scores.contains(n)); - return m_scores.find(n).has_neg_occ; - } - inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).distance; @@ -249,32 +146,11 @@ public: return m_uplinks.contains(n); } - inline bool is_top_expr(expr * n) { - return m_top_expr.contains(n); - } - inline ptr_vector & get_uplinks(expr * n) { SASSERT(m_uplinks.contains(n)); return m_uplinks.find(n); } - inline void ucb_forget(ptr_vector & as) { - if (m_ucb_forget < 1.0) - { - expr * e; - unsigned touched_old, touched_new; - - for (unsigned i = 0; i < as.size(); i++) - { - e = as[i]; - touched_old = m_scores.find(e).touched; - touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1); - m_scores.find(e).touched = touched_new; - m_touched += touched_new - touched_old; - } - } - } - void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -350,12 +226,12 @@ public: } }; - void calculate_expr_distances(ptr_vector const & as) { + void calculate_expr_distances(goal_ref const & g) { // precondition: m_scores is set up. - unsigned sz = as.size(); + unsigned sz = g->size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(as[i])); + stack.push_back(to_app(g->form(i))); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -373,53 +249,57 @@ public: } } - /* Andreas: Used this at some point to have values for the non-top-level expressions. - However, it did not give better performance but even cause some additional m/o - is not used currently. - void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(proc, visited, q); - } - } - for_each_expr(proc, visited, e); - } + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } - void initialize_recursive(expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(q); - } - } - ptr_vector t; + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - }*/ + } - void initialize(ptr_vector const & as) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = as.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; - if (!m_top_expr.contains(e)) - m_top_expr.insert(e); + expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(proc, visited, e); +#endif for_each_expr(proc, visited, e); } visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); + // Andreas: Maybe not fully correct. +#if _FOCUS_ == 2 + initialize_recursive(e); +#endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -427,82 +307,9 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(as); + calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); - - if (m_track_unsat) - { - m_list_false = new expr*[sz]; - for (unsigned i = 0; i < sz; i++) - { - if (m_mpz_manager.eq(get_value(as[i]), m_zero)) - break_assertion(as[i]); - } - } - - m_temp_seen.reset(); - for (unsigned i = 0; i < sz; i++) - { - expr * e = as[i]; - - // initialize weights - if (!m_weights.contains(e)) - m_weights.insert(e, m_paws_init); - - // positive/negative occurences used for early pruning - setup_occs(as[i]); - } - - // initialize ucb total touched value (individual ones are always initialized to 1) - m_touched = m_ucb_init ? as.size() : 1; - } - - void increase_weight(expr * e) - { - m_weights.find(e)++; - } - - void decrease_weight(expr * e) - { - unsigned old_weight = m_weights.find(e); - m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init; - } - - unsigned get_weight(expr * e) - { - return m_weights.find(e); - } - - void make_assertion(expr * e) - { - if (m_track_unsat) - { - if (m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) - { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - } - } - } - } - - void break_assertion(expr * e) - { - if (m_track_unsat) - { - if (!m_where_false.contains(e)) - { - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - } - } } void show_model(std::ostream & out) { @@ -599,7 +406,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(ptr_vector const & as) { + void randomize() { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -613,55 +420,6 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } - void reset(ptr_vector const & as) { - TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); - - for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { - mpz temp = m_zero; - set_value(it->m_value, temp); - m_mpz_manager.del(temp); - } - } - - void setup_occs(expr * n, bool negated = false) { - if (m_manager.is_bool(n)) - { - if (m_manager.is_and(n) || m_manager.is_or(n)) - { - SASSERT(!negated); - app * a = to_app(n); - expr * const * args = a->get_args(); - for (unsigned i = 0; i < a->get_num_args(); i++) - { - expr * child = args[i]; - if (!m_temp_seen.contains(child)) - { - setup_occs(child, false); - m_temp_seen.insert(child); - } - } - } - else if (m_manager.is_not(n)) - { - SASSERT(!negated); - app * a = to_app(n); - SASSERT(a->get_num_args() == 1); - expr * child = a->get_arg(0); - SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child)); - setup_occs(child, true); - } - else - { - if (negated) - m_scores.find(n).has_neg_occ = 1; - else - m_scores.find(n).has_pos_occ = 1; - } - } - else - NOT_IMPLEMENTED_YET(); - } - double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -678,28 +436,41 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - /* Andreas: Seems to have no effect. But maybe you want to try it again at some point. + // Andreas: Seems to have no effect. Probably it does not even occur. +#if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) sum += get_score(args[i]); - res = sum / (double) a->get_num_args(); */ - double min = 1.0; + res = sum / (double) a->get_num_args(); +#else + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; } res = min; +#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - double max = 0.0; + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. +#if _SCORE_OR_MUL_ + double inv = 1.0; + for (unsigned i = 0; i < a->get_num_args(); i++) { + double cur = get_score(args[i]); + inv *= (1.0 - get_score(args[i])); + } + res = 1.0 - inv; +#else + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; } res = max; +#endif } else if (m_manager.is_ite(n)) { SASSERT(!negated); @@ -717,7 +488,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -733,14 +504,24 @@ public: m_mpz_manager.bitwise_xor(v0, v1, diff); unsigned hamming_distance = 0; unsigned bv_sz = m_bv_util.get_bv_size(arg0); - // unweighted hamming distance + #if 1 // unweighted hamming distance while (!m_mpz_manager.is_zero(diff)) { + //m_mpz_manager.set(diff_m1, diff); + //m_mpz_manager.dec(diff_m1); + //m_mpz_manager.bitwise_and(diff, diff_m1, diff); + //hamming_distance++; if (!m_mpz_manager.is_even(diff)) { hamming_distance++; } m_mpz_manager.machine_div(diff, m_two, diff); } res = 1.0 - (hamming_distance / (double) bv_sz); + #else + rational r(diff); + r /= m_powers(bv_sz); + double dbl = r.get_double(); + res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl; + #endif TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << " ; SZ = " << bv_sz << std::endl; ); @@ -755,7 +536,7 @@ public: SASSERT(a->get_num_args() == 2); const mpz & x = get_value(a->get_arg(0)); const mpz & y = get_value(a->get_arg(1)); - int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); if (negated) { if (m_mpz_manager.gt(x, y)) @@ -769,7 +550,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -781,7 +562,7 @@ public: rational n(diff); n /= rational(m_powers(bv_sz)); double dbl = n.get_double(); - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); } } @@ -801,7 +582,7 @@ public: if (negated) { if (x > y) - res = 1.0; + res = 1.0; else { mpz diff; m_mpz_manager.sub(y, x, diff); @@ -817,21 +598,20 @@ public: } else { if (x <= y) - res = 1.0; + res = 1.0; else { mpz diff; m_mpz_manager.sub(x, y, diff); - SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; double dbl = n.get_double(); - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -839,9 +619,7 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - // Precondition: Assertion set is in NNF. - // Also: careful about the unsat assertion scaling further down. - if (m_manager.is_and(child) || m_manager.is_or(child)) + if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); res = score_bool(child, true); } @@ -867,16 +645,24 @@ public: SASSERT(res >= 0.0 && res <= 1.0); - app * a = to_app(n); - family_id afid = a->get_family_id(); +#if _WEIGHT_DIST_ + app * a = to_app(n); + family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) +#endif +#if _WEIGHT_DIST_ == 1 + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#elif _WEIGHT_DIST_ == 2 + res *= res; +#elif _WEIGHT_DIST_ == 3 + if (res < 1.0) res = 0.0; +#endif - if (afid == m_bv_util.get_family_id()) - if (res < 1.0) res *= m_scale_unsat; TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -922,28 +708,9 @@ public: NOT_IMPLEMENTED_YET(); } - ptr_vector & get_constants(expr * e) { - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz = this_decls.size(); + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { - func_decl * fd = this_decls[i]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - return m_temp_constants; - } - - ptr_vector & get_unsat_constants_gsat(ptr_vector const & as) { - unsigned sz = as.size(); - if (sz == 1) { - if (m_mpz_manager.neq(get_value(as[0]), m_one)) - return get_constants(); - } - - m_temp_constants.reset(); - - for (unsigned i = 0; i < sz; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -955,110 +722,141 @@ public: } } return m_temp_constants; - } + } - ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e || m_temp_constants.size()) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz = this_decls.size(); - for (unsigned j = 0; j < sz; j++) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } + + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. + if (!q) + return m_temp_constants; + + ptr_vector const & this_decls = m_constants_occ.find(q); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants(ptr_vector const & as) { - if (m_walksat) - { - expr * e = get_unsat_assertion(as); - - if (!e) - { - m_temp_constants.reset(); - return m_temp_constants; + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); } + return m_temp_constants; + } + + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); + if (!q) + return m_temp_constants; + + return go_deeper(q); + } + + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); - return get_unsat_constants_walksat(e); - } - else - return get_unsat_constants_gsat(as); - } - - expr * get_unsat_assertion(ptr_vector const & as) { - unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.neq(get_value(as[0]), m_one)) - return as[0]; - else - return 0; + return get_constants(); } - m_temp_constants.reset(); - - unsigned pos = -1; - if (m_ucb) - { - value_score vscore; - double max = -1.0; - // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit. - /* for (unsigned i = 0; i < m_where_false.size(); i++) { - expr * e = m_list_false[i]; */ - for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; - if (m_mpz_manager.neq(get_value(e), m_one)) - { - vscore = m_scores.find(e); - // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise. - // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); - if (q > max) { max = q; pos = i; } - } + else { + m_temp_constants.reset(); +#if _FOCUS_ == 1 +#if _BFS_ == 3 + unsigned int pos = 0; + double max = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return 0; - - m_touched++; - m_scores.find(as[pos]).touched++; - // Andreas: Also part of track_unsat data structures. Additionally disable the previous line! - /* m_last_pos = pos; - m_scores.find(m_list_false[pos]).touched++; - return m_list_false[pos]; */ +#elif _BFS_ == 2 + unsigned int pos = 0; + double min = get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } +#elif _BFS_ == 1 + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_walksat(g, sz, pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % m_constants.size(); +#else + unsigned int pos = get_random_uint(16) % m_constants.size(); +#endif + return get_unsat_constants_crsat(g, sz, pos); +#else + return get_unsat_constants_gsat(g, sz); +#endif } - else - { - // Andreas: The track_unsat data structures for random assertion selection. - /* sz = m_where_false.size(); - if (sz == 0) - return 0; - return m_list_false[get_random_uint(16) % sz]; */ - - unsigned cnt_unsat = 0; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return 0; - } - - m_last_pos = pos; - return as[pos]; - } - - expr * get_new_unsat_assertion(ptr_vector const & as) { - unsigned sz = as.size(); - if (sz == 1) - return 0; - m_temp_constants.reset(); - - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - - if (pos == static_cast(-1)) - return 0; - return as[pos]; } }; -#endif +#endif \ No newline at end of file diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt index fec38518d..141193f76 100644 --- a/versions/z3-wsat-0.01.txt +++ b/versions/z3-wsat-0.01.txt @@ -9,6 +9,4 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 - -BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file +#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt index 8bcf2ffeb..2c0c0e7ad 100644 --- a/versions/z3-wsat-0.01b.txt +++ b/versions/z3-wsat-0.01b.txt @@ -9,6 +9,4 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 - -BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file +#define _SCORE_OR_MUL_ 0 \ No newline at end of file From 140d28b6b3165ad4b2b3ccd7ff5eea203481cc34 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 9 Mar 2014 15:42:51 +0000 Subject: [PATCH 206/646] plenty of new stuff --- src/tactic/portfolio/default_tactic.cpp | 1 + src/tactic/portfolio/smt_strategic_solver.cpp | 5 +- src/tactic/sls/sls_evaluator.h | 323 ++++++++- src/tactic/sls/sls_tactic.cpp | 661 ++++++++++++++++-- src/tactic/sls/sls_tracker.h | 345 ++++++++- versions/z3-wsat-0.01.txt | 4 +- versions/z3-wsat-0.01b.txt | 4 +- 7 files changed, 1235 insertions(+), 108 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index b28b7bec0..53da9a159 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -33,6 +33,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), + // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 586c3a349..f63b4fd8c 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,11 +37,14 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" +#include"sls_tactic.h" + tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - return mk_qfbv_tactic(m, p); + // return mk_qfbv_tactic(m, p); + return mk_qfbv_sls_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 61305386e..eec9524a9 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -34,6 +34,9 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; +#if _EARLY_PRUNE_ + vector > m_traversal_stack_bool; +#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -519,11 +522,15 @@ public: } } - void run_update(unsigned cur_depth) { + void run_serious_update(unsigned cur_depth) { // precondition: m_traversal_stack contains the entry point(s) expr_fast_mark1 visited; mpz new_value; +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -533,8 +540,92 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - m_tracker.set_score(cur, m_tracker.score(cur)); +#if _REAL_RS_ || _REAL_PBFS_ + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } +#endif + +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + void run_update(unsigned cur_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + +#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ + double new_score; +#endif + + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); +#if _EARLY_PRUNE_ + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); +#else +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -569,8 +660,11 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } - +#if _REAL_RS_ || _REAL_PBFS_ + run_serious_update(max_depth); +#else run_update(max_depth); +#endif } void update(func_decl * fd, const mpz & new_value) { @@ -584,6 +678,196 @@ public: run_update(cur_depth); } + void serious_update(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + m_traversal_stack[cur_depth].push_back(ep); + + run_serious_update(cur_depth); + } + +#if _EARLY_PRUNE_ + unsigned run_update_bool_prune(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); +#if _CACHE_TOP_SCORE_ + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); +#endif + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + +#if _CACHE_TOP_SCORE_ + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); +#else + m_tracker.set_score(cur, m_tracker.score(cur)); +#endif + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + void run_update_prune(unsigned max_depth) { + // precondition: m_traversal_stack contains the entry point(s) + expr_fast_mark1 visited; + mpz new_value; + + unsigned cur_depth = max_depth; + SASSERT(cur_depth < m_traversal_stack.size()); + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + (*this)(to_app(cur), new_value); + m_tracker.set_value(cur, new_value); + // should always have uplinks ... + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); + visited.mark(next); + } + } + } + } + + cur_depth_exprs.reset(); + cur_depth--; + } + + m_mpz_manager.del(new_value); + } + + unsigned update_prune(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); + } +#endif + + void randomize_local(expr * e, unsigned int flip) { + ptr_vector & unsat_constants = m_tracker.get_constants(e); + + // Randomize _one_ candidate: + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + update(fd, temp); + m_mpz_manager.del(temp); + } + void randomize_local(goal_ref const & g, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); @@ -603,8 +887,37 @@ public: // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; - mpz temp = m_tracker.get_random(fd->get_range()); - update(fd, temp); +#if _PERC_CHANGE_ + sort * srt = fd->get_range(); + mpz temp; + + if (m_manager.is_bool(srt)) + m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); + + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } +#else + mpz temp = m_tracker.get_random(fd->get_range()); +#endif + +#if _REAL_RS_ || _REAL_PBFS_ + serious_update(fd, temp); +#else + update(fd, temp); +#endif m_mpz_manager.del(temp); TRACE("sls", /*tout << "Randomization candidates: "; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index c194af267..a08588a51 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -35,16 +35,102 @@ Notes: #include"sls_tactic.h" #include"nnf_tactic.h" -#define _CNF_ 0 -#define _BFS_ 1 +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 + +// do we use restarts? +// 0 = no, otherwise the value defines the maximum number of moves #define _RESTARTS_ 0 -#define _TIMELIMIT_ 30 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? #define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? #define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 -#define _WEIGHT_DIST_ 3 -#define _WEIGHT_DIST_FACTOR_ 0.1 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 0 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 0 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 0.01 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +#define _PROBABILISTIC_UCT_ 0 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 1 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 1 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 1 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 1 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) + InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) + InvalidConfiguration; +#endif + #include"sls_params.hpp" #include"sls_evaluator.h" @@ -57,12 +143,17 @@ class sls_tactic : public tactic { stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -92,7 +183,9 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : m_manager(m), @@ -174,13 +267,20 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - top_sum += m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + return top_sum / (double) sz; #endif } @@ -191,22 +291,54 @@ class sls_tactic : public tactic { return top_score(g); } - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else return top_score(g); +#endif } + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; + } +#endif + + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { - + #ifdef Z3DEBUG mpz old_value; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else double r = incremental_score(g, fd, temp); - +#endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl; ); @@ -214,6 +346,22 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); #endif +// if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // same as what_if, but only applied to the score of a specific atom, not the total score + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -224,7 +372,35 @@ class sls_tactic : public tactic { return false; } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + + } + + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + } + + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -261,59 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + if (m_stats.m_moves > 10000) + rnd_mv = 0; ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; - unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range()); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + mpz new_value; - m_evaluator.update(fd, new_value); + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; - m_mpz_manager.del(new_value); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } + + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -359,6 +549,7 @@ class sls_tactic : public tactic { SASSERT(check == score); } + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else @@ -390,9 +581,13 @@ class sls_tactic : public tactic { return new_score; } + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif unsigned bv_sz; double new_score = score; @@ -403,8 +598,12 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // first try to flip every bit - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { - // What would happen if we flipped bit #i ? +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -414,7 +613,8 @@ class sls_tactic : public tactic { } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -426,16 +626,99 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } - +#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif } // reset to what it was before double check = incremental_score(g, fd, old_value); - SASSERT(check == score); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; + } + + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -443,7 +726,150 @@ class sls_tactic : public tactic { return new_score; } - lbool search(goal_ref const & g) { + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + + m_old_values.reset(); + + return 0; + } + + // what_if version needed in the context of 2nd intensification try, combining local and global score + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // find_best_move version needed in the context of 2nd intensification try + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) + { + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; + } + + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; + } + + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -463,16 +889,48 @@ class sls_tactic : public tactic { #if _RESTARTS_ while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { + if (m_stats.m_moves == 5590) checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif old_score = score; new_const = (unsigned)-1; ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -525,9 +983,17 @@ class sls_tactic : public tactic { case MV_INC: m_stats.m_incs++; break; case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - score = incremental_score(g, fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif TRACE("sls", tout << "Score distribution:"; for (unsigned i = 0; i < g->size(); i++) @@ -535,9 +1001,10 @@ class sls_tactic : public tactic { tout << " TOP: " << score << std::endl; ); } - if (score >= 1.0) { + if (score >= 0.99999) { +// if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: Can it only be imprecise in one direction? + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -568,10 +1035,26 @@ class sls_tactic : public tactic { // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else m_evaluator.randomize_local(g, m_stats.m_moves); - //mk_random_move(g); +#endif + //mk_random_move(g); score = top_score(g); - //} + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } } } @@ -587,6 +1070,37 @@ class sls_tactic : public tactic { return; } + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif m_tracker.initialize(g); lbool res = l_undef; @@ -740,13 +1254,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), -#if _CNF_ - // Andreas: We will probably never use this. CNF sucks. - mk_cnf_tactic(m, p)); -#else // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); -#endif } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1061bd90e..b26912e5c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -28,21 +28,32 @@ class sls_tracker { random_gen m_rng; unsigned m_random_bits; unsigned m_random_bits_cnt; - mpz m_zero, m_one, m_two; + mpz m_zero, m_one, m_two; struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { }; +#if _EARLY_PRUNE_ + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; +#else + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; +#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; +#if _EARLY_PRUNE_ + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; +#endif unsigned distance; // max distance from any root + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; + touched = other.touched; return *this; } }; @@ -60,6 +71,20 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; +#if _UCT_ + unsigned m_touched; +#endif +#if _REAL_RS_ || _REAL_PBFS_ + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; +#endif +#if _CACHE_TOP_SCORE_ + double m_top_sum; +#endif +#if _WEIGHT_DIST_ == 4 + double m_weight_dist_factor; +#endif public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -79,6 +104,26 @@ public: m_mpz_manager.del(m_two); } +#if _WEIGHT_DIST_ == 4 + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } +#endif + +#if _CACHE_TOP_SCORE_ + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } + + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } + + inline double get_top_sum() { + return m_top_sum; + } +#endif + inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); m_mpz_manager.set(m_scores.find(n).value, r); @@ -123,6 +168,28 @@ public: return get_score(ep); } +#if _EARLY_PRUNE_ + inline void set_score_prune(expr * n, double score) { + SASSERT(m_scores.contains(n)); + m_scores.find(n).score_prune = score; + } + + inline double & get_score_prune(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).score_prune; + } + + inline unsigned has_pos_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_pos_occ; + } + + inline unsigned has_neg_occ(expr * n) { + SASSERT(m_scores.contains(n)); + return m_scores.find(n).has_neg_occ; + } +#endif + inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).distance; @@ -297,7 +364,7 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 +#if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); #endif ptr_vector t; @@ -310,8 +377,57 @@ public: calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); + +#if _REAL_RS_ || _REAL_PBFS_ + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); +#endif + +#if _EARLY_PRUNE_ + for (unsigned i = 0; i < sz; i++) + setup_occs(g->form(i)); +#endif + +#if _UCT_ + m_touched = 1; +#endif } +#if _REAL_RS_ || _REAL_PBFS_ + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } + + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } +#endif + void show_model(std::ostream & out) { unsigned sz = get_num_constants(); for (unsigned i = 0; i < sz; i++) { @@ -420,10 +536,45 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); } +#if _EARLY_PRUNE_ + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } + else + NOT_IMPLEMENTED_YET(); + } +#endif + double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -488,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -648,6 +799,7 @@ public: #if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 @@ -656,13 +808,14 @@ public: res *= res; #elif _WEIGHT_DIST_ == 3 if (res < 1.0) res = 0.0; +#elif _WEIGHT_DIST_ == 4 + if (res < 1.0) res *= m_weight_dist_factor; #endif - TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -708,6 +861,44 @@ public: NOT_IMPLEMENTED_YET(); } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } + + ptr_vector & get_constants(expr * e) { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); @@ -743,7 +934,6 @@ public: // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { @@ -754,6 +944,19 @@ public: return m_temp_constants; } + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz = this_decls.size(); + for (unsigned j = 0; j < sz; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + return m_temp_constants; + } + ptr_vector & go_deeper(expr * e) { if (m_manager.is_bool(e)) { if (m_manager.is_and(e)) { @@ -812,44 +1015,138 @@ public: return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 -#if _BFS_ == 3 - unsigned int pos = 0; - double max = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return m_temp_constants; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif + expr * e = g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = 0; - double min = get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); double q = get_score(e); if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(g, sz, pos); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - unsigned int pos = flip % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - unsigned int pos = get_random_uint(16) % m_constants.size(); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif return get_unsat_constants_crsat(g, sz, pos); #else diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt index 141193f76..fec38518d 100644 --- a/versions/z3-wsat-0.01.txt +++ b/versions/z3-wsat-0.01.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt index 2c0c0e7ad..8bcf2ffeb 100644 --- a/versions/z3-wsat-0.01b.txt +++ b/versions/z3-wsat-0.01b.txt @@ -9,4 +9,6 @@ No restarts. #define _RESTARTS_ 0 #define _TIMELIMIT_ 300 #define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file +#define _SCORE_OR_MUL_ 0 + +BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file From 664fa82c6cb752b08a3788af542a999464f0b930 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 09:40:01 +0000 Subject: [PATCH 207/646] removed tabs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_evaluator.h | 268 ++++++------- src/tactic/sls/sls_tactic.cpp | 572 ++++++++++++++-------------- src/tactic/sls/sls_tracker.h | 672 ++++++++++++++++----------------- 3 files changed, 756 insertions(+), 756 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index eec9524a9..cdb08038f 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -528,7 +528,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -542,33 +542,33 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) - { - if (m_mpz_manager.eq(new_value,m_one)) - m_tracker.make_assertion(cur); - else - m_tracker.break_assertion(cur); - } + if (!m_tracker.has_uplinks(cur)) + { + if (m_mpz_manager.eq(new_value,m_one)) + m_tracker.make_assertion(cur); + else + m_tracker.break_assertion(cur); + } #endif #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -596,7 +596,7 @@ public: mpz new_value; #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ - double new_score; + double new_score; #endif SASSERT(cur_depth < m_traversal_stack.size()); @@ -609,23 +609,23 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - m_tracker.set_score(cur, new_score); - m_tracker.set_score_prune(cur, new_score); + m_tracker.set_score(cur, new_score); + m_tracker.set_score_prune(cur, new_score); #else #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -661,7 +661,7 @@ public: if (cur_depth > max_depth) max_depth = cur_depth; } #if _REAL_RS_ || _REAL_PBFS_ - run_serious_update(max_depth); + run_serious_update(max_depth); #else run_update(max_depth); #endif @@ -693,27 +693,27 @@ public: unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { expr * cur = cur_depth_exprs[i]; - new_score = m_tracker.score(cur); + new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif - prune_score = m_tracker.get_score_prune(cur); + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); - if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; + if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -722,54 +722,54 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); + m_traversal_stack_bool[next_d].push_back(next); visited.mark(next); } } } - else - { - } - } + else + { + } + } - cur_depth_exprs.reset(); + cur_depth_exprs.reset(); cur_depth--; - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; #if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); + new_score = m_tracker.score(cur); + if (!m_tracker.has_uplinks(cur)) + m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #else - m_tracker.set_score(cur, m_tracker.score(cur)); + m_tracker.set_score(cur, m_tracker.score(cur)); #endif - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } - return pot_benefits; + return pot_benefits; } void run_update_prune(unsigned max_depth) { @@ -777,7 +777,7 @@ public: expr_fast_mark1 visited; mpz new_value; - unsigned cur_depth = max_depth; + unsigned cur_depth = max_depth; SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { ptr_vector & cur_depth_exprs = m_traversal_stack[cur_depth]; @@ -787,7 +787,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // should always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -795,10 +795,10 @@ public: unsigned next_d = m_tracker.get_distance(next); SASSERT(next_d < cur_depth); if (!visited.is_marked(next)) { - if (m_manager.is_bool(next)) - m_traversal_stack_bool[max_depth].push_back(next); - else - m_traversal_stack[next_d].push_back(next); + if (m_manager.is_bool(next)) + m_traversal_stack_bool[max_depth].push_back(next); + else + m_traversal_stack[next_d].push_back(next); visited.mark(next); } } @@ -817,23 +817,23 @@ public: expr * ep = m_tracker.get_entry_point(fd); unsigned cur_depth = m_tracker.get_distance(ep); - if (m_traversal_stack_bool.size() <= cur_depth) + if (m_traversal_stack_bool.size() <= cur_depth) m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune(cur_depth); + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune(cur_depth); } #endif - void randomize_local(expr * e, unsigned int flip) { + void randomize_local(expr * e, unsigned int flip) { ptr_vector & unsat_constants = m_tracker.get_constants(e); // Randomize _one_ candidate: @@ -841,30 +841,30 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif - update(fd, temp); + update(fd, temp); m_mpz_manager.del(temp); } @@ -889,34 +889,34 @@ public: func_decl * fd = unsat_constants[r]; #if _PERC_CHANGE_ sort * srt = fd->get_range(); - mpz temp; + mpz temp; - if (m_manager.is_bool(srt)) + if (m_manager.is_bool(srt)) m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else + else { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); + mpz temp2, mask; + unsigned bv_sz = m_bv_util.get_bv_size(srt); + m_mpz_manager.set(temp, m_tracker.get_value(fd)); - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } + for (unsigned bit = 0; bit < bv_sz; bit++) + if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) + { + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(temp, mask, temp2); + m_mpz_manager.set(temp, temp2); + } + m_mpz_manager.del(mask); + m_mpz_manager.del(temp2); + } #else - mpz temp = m_tracker.get_random(fd->get_range()); + mpz temp = m_tracker.get_random(fd->get_range()); #endif #if _REAL_RS_ || _REAL_PBFS_ - serious_update(fd, temp); + serious_update(fd, temp); #else - update(fd, temp); + update(fd, temp); #endif m_mpz_manager.del(temp); diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index a08588a51..553acc35a 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -125,10 +125,10 @@ Notes: #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) - InvalidConfiguration; + InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; + InvalidConfiguration; #endif @@ -150,10 +150,10 @@ class sls_tactic : public tactic { m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -183,8 +183,8 @@ class sls_tactic : public tactic { unsigned m_max_restarts; unsigned m_plateau_limit; - ptr_vector m_old_values; - + ptr_vector m_old_values; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; imp(ast_manager & m, params_ref const & p, stats & s) : @@ -267,18 +267,18 @@ class sls_tactic : public tactic { #else double top_sum = 0.0; unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } - TRACE("sls_top", tout << "Score distribution:"; + TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double) sz << std::endl; ); #if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); + m_tracker.set_top_sum(top_sum); #endif return top_sum / (double) sz; @@ -292,20 +292,20 @@ class sls_tactic : public tactic { } double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif } double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else return top_score(g); #endif @@ -314,18 +314,18 @@ class sls_tactic : public tactic { #if _EARLY_PRUNE_ double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) + if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(g); + return top_score(g); #endif - else - return 0.0; + else + return 0.0; } #endif - // checks whether the score outcome of a given move is better than the previous score + // checks whether the score outcome of a given move is better than the previous score bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { @@ -357,11 +357,11 @@ class sls_tactic : public tactic { return false; } - // same as what_if, but only applied to the score of a specific atom, not the total score + // same as what_if, but only applied to the score of a specific atom, not the total score bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); + double r = m_tracker.get_score(e); if (r >= best_score) { best_score = r; best_const = fd_inx; @@ -378,29 +378,29 @@ class sls_tactic : public tactic { m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); - } + } - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { mpz temp, mask, mask2; m_mpz_manager.mul(old_value, m_two, temp); m_mpz_manager.set(mask, m_powers(bv_sz)); m_mpz_manager.bitwise_not(bv_sz, mask, mask2); m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); } void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { m_mpz_manager.div(old_value, m_two, result); } - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) @@ -437,73 +437,73 @@ class sls_tactic : public tactic { void mk_random_move(goal_ref const & g) { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; + if (m_stats.m_moves > 10000) + rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; - mpz new_value; + mpz new_value; - sort * srt = fd->get_range(); + sort * srt = fd->get_range(); if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { #if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + mt = MV_FLIP; #endif - unsigned bit = 0; + unsigned bit = 0; - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } - // will use VNS to ignore some possible moves and increase the flips per second + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; @@ -514,7 +514,7 @@ class sls_tactic : public tactic { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -536,12 +536,12 @@ class sls_tactic : public tactic { if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } } // reset to what it was before @@ -549,12 +549,12 @@ class sls_tactic : public tactic { SASSERT(check == score); } - // we can either check the condition once in the beginning or check it repeatedly after every bit + // we can either check the condition once in the beginning or check it repeatedly after every bit #if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) #else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) #endif for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { func_decl * fd = to_evaluate[i]; @@ -563,30 +563,30 @@ class sls_tactic : public tactic { m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } // reset to what it was before double check = incremental_score(g, fd, old_value); SASSERT(check == score); } - m_mpz_manager.del(old_value); + m_mpz_manager.del(old_value); m_mpz_manager.del(temp); return new_score; } - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; + mpz temp2; #endif unsigned bv_sz; double new_score = score; @@ -599,11 +599,11 @@ class sls_tactic : public tactic { // first try to flip every bit #if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { #endif - // What would happen if we flipped bit #i ? + // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { @@ -614,7 +614,7 @@ class sls_tactic : public tactic { if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { #if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { + if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); if (what_if(g, fd, i, temp, new_score, best_const, best_value)) @@ -660,7 +660,7 @@ class sls_tactic : public tactic { // reset to what it was before double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching + // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -669,17 +669,17 @@ class sls_tactic : public tactic { #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif - return new_score; + return new_score; } - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -718,7 +718,7 @@ class sls_tactic : public tactic { } // reset to what it was before - m_evaluator.update(fd, old_value); + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); @@ -726,37 +726,37 @@ class sls_tactic : public tactic { return new_score; } - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); #if _BFS_ - unsigned pos = m_stats.m_moves % sz; + unsigned pos = m_stats.m_moves % sz; #else - unsigned pos = m_tracker.get_random_uint(16) % sz; + unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); } else { m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -767,35 +767,35 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } - m_evaluator.update(fd, new_value); + m_evaluator.update(fd, new_value); } - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - m_old_values.reset(); + m_old_values.reset(); - return 0; - } + return 0; + } - // what_if version needed in the context of 2nd intensification try, combining local and global score + // what_if version needed in the context of 2nd intensification try, combining local and global score bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, double & best_score, mpz & best_value, unsigned i) { double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); + double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - if (new_score >= best_score) { + if (new_score >= best_score) { best_score = new_score; m_mpz_manager.set(best_value, temp); return true; @@ -804,17 +804,17 @@ class sls_tactic : public tactic { return false; } - // find_best_move version needed in the context of 2nd intensification try + // find_best_move version needed in the context of 2nd intensification try double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; + { + mpz old_value, temp; double best_score = 0; sort * srt = fd->get_range(); unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); what_if(g, e, fd, temp, best_score, best_value, i); } @@ -822,54 +822,54 @@ class sls_tactic : public tactic { m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - return best_score; + return best_score; } - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); #if _BFS_ - unsigned new_const = m_stats.m_moves % sz; + unsigned new_const = m_stats.m_moves % sz; #else - unsigned new_const = m_tracker.get_random_uint(16) % sz; + unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } - return 0; - } + return 0; + } - // main search loop - lbool search(goal_ref const & g) { + // main search loop + lbool search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -885,52 +885,52 @@ class sls_tactic : public tactic { unsigned plateau_cnt = 0; - // Andreas: Why do we only allow so few plateaus? + // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) + if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif #if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { #if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #elif _TYPE_RSTEP_ == 2 - mk_random_move(g); + mk_random_move(g); #endif score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } #endif old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; for (unsigned i = 0 ; i < to_evaluate.size(); i++) tout << to_evaluate[i]->get_name() << std::endl; ); @@ -952,11 +952,11 @@ class sls_tactic : public tactic { for (unsigned i = 0; i < g->size(); i++) tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? + // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } else { - // Andreas: Why does randomizing not count as a move? (Now it does.) + // Andreas: Why does randomizing not count as a move? (Now it does.) m_stats.m_moves++; func_decl * fd = to_evaluate[new_const]; @@ -984,15 +984,15 @@ class sls_tactic : public tactic { case MV_DEC: m_stats.m_decs++; break; case MV_INV: m_stats.m_invs++; break; case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; @@ -1004,7 +1004,7 @@ class sls_tactic : public tactic { if (score >= 0.99999) { // if (score >= 1.0) { // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; for (unsigned i = 0; i < g->size() && all_true; i++) if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) @@ -1015,43 +1015,43 @@ class sls_tactic : public tactic { } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); + report_tactic_progress("This should not happen I guess.", plateau_cnt); plateau_cnt = 0; - } else { - m_stats.m_moves++; + } else { + m_stats.m_moves++; plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. //if (plateau_cnt < m_plateau_limit) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); #if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); + handle_plateau(g, score); + //handle_plateau(g); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(g); + //mk_random_move(g); score = top_score(g); - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; } else TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); } @@ -1070,43 +1070,43 @@ class sls_tactic : public tactic { return; } - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); #endif m_tracker.initialize(g); lbool res = l_undef; do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... + // Andreas: I think restarts are too impotant to ignore 99% of them are happening... //if ((m_stats.m_restarts % 100) == 0) report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); @@ -1115,12 +1115,12 @@ class sls_tactic : public tactic { if (res == l_undef) m_tracker.randomize(); } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); + report_tactic_progress("Number of flips:", m_stats.m_moves); if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1254,7 +1254,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? + // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index b26912e5c..006bbb888 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -29,31 +29,31 @@ class sls_tracker { unsigned m_random_bits; unsigned m_random_bits_cnt; mpz m_zero, m_one, m_two; - + struct value_score { #if _EARLY_PRUNE_ - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; #else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; #endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; double score; #if _EARLY_PRUNE_ - double score_prune; - unsigned has_pos_occ; - unsigned has_neg_occ; + double score_prune; + unsigned has_pos_occ; + unsigned has_neg_occ; #endif unsigned distance; // max distance from any root - unsigned touched; + unsigned touched; value_score & operator=(const value_score & other) { SASSERT(m == 0 || m == other.m); if (m) m->set(value, 0); else m = other.m; m->set(value, other.value); score = other.score; distance = other.distance; - touched = other.touched; + touched = other.touched; return *this; } }; @@ -72,18 +72,18 @@ private: ptr_vector m_temp_constants; occ_type m_constants_occ; #if _UCT_ - unsigned m_touched; + unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; + double m_weight_dist_factor; #endif public: @@ -105,23 +105,23 @@ public: } #if _WEIGHT_DIST_ == 4 - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } + inline void set_weight_dist_factor(double val) { + m_weight_dist_factor = val; + } #endif #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { - m_top_sum += add - sub; - } + inline void adapt_top_sum(double add, double sub) { + m_top_sum += add - sub; + } - inline void set_top_sum(double new_score) { - m_top_sum = new_score; - } + inline void set_top_sum(double new_score) { + m_top_sum = new_score; + } - inline double get_top_sum() { - return m_top_sum; - } + inline double get_top_sum() { + return m_top_sum; + } #endif inline void set_value(expr * n, const mpz & r) { @@ -174,20 +174,20 @@ public: m_scores.find(n).score_prune = score; } - inline double & get_score_prune(expr * n) { + inline double & get_score_prune(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).score_prune; } - inline unsigned has_pos_occ(expr * n) { + inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } - inline unsigned has_neg_occ(expr * n) { + inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -316,45 +316,45 @@ public: } } - void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(proc, visited, q); - } - } - for_each_expr(proc, visited, e); - } + void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(proc, visited, q); + } + } + for_each_expr(proc, visited, e); + } - void initialize_recursive(expr * e) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - initialize_recursive(q); - } - } - ptr_vector t; + void initialize_recursive(expr * e) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + initialize_recursive(q); + } + } + ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } - void initialize(goal_ref const & g) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); + initialize_recursive(proc, visited, e); #endif for_each_expr(proc, visited, e); } @@ -363,9 +363,9 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); - // Andreas: Maybe not fully correct. + // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); + initialize_recursive(e); #endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); @@ -379,53 +379,53 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); #if _REAL_RS_ || _REAL_PBFS_ - m_list_false = new expr*[sz]; + m_list_false = new expr*[sz]; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + break_assertion(g->form(i)); #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = 1; #endif } #if _REAL_RS_ || _REAL_PBFS_ - void make_assertion(expr * e) - { - if (m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) - { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - } -// printf("Going in %d\n", m_where_false.size()); - } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); - } + void make_assertion(expr * e) + { + if (m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } +// printf("Going in %d\n", m_where_false.size()); + } + //if (m_unsat_expr.contains(e)) + //m_unsat_expr.erase(e); + } - void break_assertion(expr * e) - { - if (!m_where_false.contains(e)) - { - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); - } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); - } + void break_assertion(expr * e) + { + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + // printf("Going in %d\n", m_where_false.size()); + } + //if (!m_unsat_expr.contains(e)) + //m_unsat_expr.push_back(e); + } #endif void show_model(std::ostream & out) { @@ -537,35 +537,35 @@ public: } #if _EARLY_PRUNE_ - void setup_occs(expr * n, bool negated = false) { - if (m_manager.is_bool(n)) - { - if (m_manager.is_and(n) || m_manager.is_or(n)) - { - SASSERT(!negated); - app * a = to_app(n); - expr * const * args = a->get_args(); - for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); - } - else if (m_manager.is_not(n)) - { - SASSERT(!negated); - app * a = to_app(n); - SASSERT(a->get_num_args() == 1); - expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); - setup_occs(child, true); - } - else - { - if (negated) - m_scores.find(n).has_neg_occ = 1; - else - m_scores.find(n).has_pos_occ = 1; - } - } + void setup_occs(expr * n, bool negated = false) { + if (m_manager.is_bool(n)) + { + if (m_manager.is_and(n) || m_manager.is_or(n)) + { + SASSERT(!negated); + app * a = to_app(n); + expr * const * args = a->get_args(); + for (unsigned i = 0; i < a->get_num_args(); i++) + setup_occs(args[i]); + } + else if (m_manager.is_not(n)) + { + SASSERT(!negated); + app * a = to_app(n); + SASSERT(a->get_num_args() == 1); + expr * child = a->get_arg(0); + if (m_manager.is_and(child) || m_manager.is_or(child)) + NOT_IMPLEMENTED_YET(); + setup_occs(child, true); + } + else + { + if (negated) + m_scores.find(n).has_neg_occ = 1; + else + m_scores.find(n).has_pos_occ = 1; + } + } else NOT_IMPLEMENTED_YET(); } @@ -574,7 +574,7 @@ public: double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); - double res = 0.0; + double res = 0.0; if (is_uninterp_const(n)) { const mpz & r = get_value(n); @@ -587,14 +587,14 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. + // Andreas: Seems to have no effect. Probably it does not even occur. #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) sum += get_score(args[i]); res = sum / (double) a->get_num_args(); #else - double min = 1.0; + double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur < min) min = cur; @@ -606,16 +606,16 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. + // Andreas: Seems to have no effect. Probably it is still too similar to the original version. #if _SCORE_OR_MUL_ - double inv = 1.0; + double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else - double max = 0.0; + double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); if (cur > max) max = cur; @@ -639,7 +639,7 @@ public: expr * arg1 = a->get_arg(1); const mpz & v0 = get_value(arg0); const mpz & v1 = get_value(arg1); - + if (negated) { res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << @@ -701,7 +701,7 @@ public: double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - m_mpz_manager.del(diff); + m_mpz_manager.del(diff); } } else { @@ -762,7 +762,7 @@ public: TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - m_mpz_manager.del(x); + m_mpz_manager.del(x); m_mpz_manager.del(y); } else if (m_manager.is_not(n)) { @@ -797,25 +797,25 @@ public: SASSERT(res >= 0.0 && res <= 1.0); #if _WEIGHT_DIST_ - app * a = to_app(n); - family_id afid = a->get_family_id(); + app * a = to_app(n); + family_id afid = a->get_family_id(); - if (afid == m_bv_util.get_family_id()) + if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; + if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; #elif _WEIGHT_DIST_ == 2 - res *= res; + res *= res; #elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; + if (res < 1.0) res = 0.0; #elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; + if (res < 1.0) res *= m_weight_dist_factor; #endif TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; } - + double score_bv(expr * n) { return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores. } @@ -861,34 +861,34 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } + expr * get_unsat_expression(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e) || m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return get_unsat_expression(q); + } + } + } + return e; + } - ptr_vector & get_constants(expr * e) { + ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned i = 0; i < sz; i++) { @@ -897,9 +897,9 @@ public: m_temp_constants.push_back(fd); } return m_temp_constants; - } + } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -913,244 +913,244 @@ public: } } return m_temp_constants; - } + } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + for (unsigned i = pos; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; + return q; } - return 0; - } + for (unsigned i = 0; i < pos; i++) { + expr * q = g->form(i); + if (m_mpz_manager.neq(get_value(q), m_one)) + return q; + } + return 0; + } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); + if (!q) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(q); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & get_unsat_constants_walksat(expr * e) { + if (!e) + return m_temp_constants; + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); for (unsigned j = 0; j < sz; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); + ptr_vector & go_deeper(expr * e) { + if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + // Andreas: might be used for guided branching + //for (unsigned i = 0; i < a->get_num_args(); i++) { + //double cur = get_score(args[i]); + //} + // Andreas: A random number is better here since reusing flip will cause patterns. + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned int pos = get_random_uint(16) % sz; + for (unsigned int i = pos; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + for (unsigned int i = 0; i < pos; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one)) + return go_deeper(q); + } + } + } + ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz2 = this_decls.size(); for (unsigned j = 0; j < sz2; j++) { func_decl * fd = this_decls[j]; if (!m_temp_constants.contains(fd)) m_temp_constants.push_back(fd); } - return m_temp_constants; - } + return m_temp_constants; + } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) - return m_temp_constants; + return m_temp_constants; - return go_deeper(q); - } + return go_deeper(q); + } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) - return m_temp_constants; - else - return get_constants(); + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + return m_temp_constants; + else + return get_constants(); } else { m_temp_constants.reset(); #if _FOCUS_ == 1 #if _UCT_ - unsigned pos = -1; - value_score vscore; + unsigned pos = -1; + value_score vscore; #if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } #else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - vscore = m_scores.find(e); + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); #elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } #endif - if (pos == static_cast(-1)) - return m_temp_constants; + if (pos == static_cast(-1)) + return m_temp_constants; #if _UCT_ == 1 - m_scores.find(g->form(pos)).touched++; - m_touched++; + m_scores.find(g->form(pos)).touched++; + m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = g->form(pos); + expr * e = g->form(pos); #elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; + unsigned int pos = -1; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; + unsigned int pos = -1; + double min = 2.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = g->form(i); double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; + expr * e = get_unsat_assertion(g, sz, pos); #elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return m_temp_constants; + expr * e = g->form(pos); #elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return m_temp_constants; + else + expr * e = m_list_false[flip % sz]; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; + expr * e = get_unsat_assertion(g, sz, pos); #endif - return get_unsat_constants_walksat(e); + return get_unsat_constants_walksat(e); #elif _FOCUS_ == 2 #if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; + // I guess it was buggy ... + // unsigned int pos = flip % m_constants.size(); + unsigned int pos = flip % sz; #else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; + // I guess it was buggy ... + // unsigned int pos = get_random_uint(16) % m_constants.size(); + unsigned int pos = get_random_uint(16) % sz; #endif - return get_unsat_constants_crsat(g, sz, pos); + return get_unsat_constants_crsat(g, sz, pos); #else - return get_unsat_constants_gsat(g, sz); + return get_unsat_constants_gsat(g, sz); #endif } } From 442827e5236f2152b498f2cabe42a50d3b095a1c Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 19 Mar 2014 11:49:44 +0000 Subject: [PATCH 208/646] Current version for relocating. --- src/tactic/sls/sls_evaluator.h | 92 +++++----- src/tactic/sls/sls_tactic.cpp | 295 +++++++++++++++++++++++++++--- src/tactic/sls/sls_tracker.h | 315 ++++++++++++++++++++++++++++++--- 3 files changed, 600 insertions(+), 102 deletions(-) diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index cdb08038f..696d7664a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -78,7 +78,11 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_zero); break; } @@ -86,7 +90,11 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) +#if _DIRTY_UP_ + if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { +#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { +#endif m_mpz_manager.set(result, m_one); break; } @@ -94,9 +102,16 @@ public: } case OP_NOT: { SASSERT(n_args == 1); +#if _DIRTY_UP_ + if (m_tracker.is_top_expr(args[0])) + m_mpz_manager.set(result, m_zero); + else + m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); +#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); - m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); + m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); +#endif break; } case OP_EQ: { @@ -542,7 +557,8 @@ public: m_tracker.set_value(cur, new_value); #if _REAL_RS_ || _REAL_PBFS_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) { if (m_mpz_manager.eq(new_value,m_one)) m_tracker.make_assertion(cur); @@ -554,7 +570,8 @@ public: #if _EARLY_PRUNE_ new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); @@ -562,13 +579,14 @@ public: #else #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -611,7 +629,8 @@ public: #if _EARLY_PRUNE_ new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); @@ -619,13 +638,14 @@ public: #else #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -695,7 +715,7 @@ public: double prune_score, new_score; unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); + SASSERT(cur_depth < m_traversal_stack_bool.size()); ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; @@ -704,7 +724,8 @@ public: new_score = m_tracker.score(cur); #if _CACHE_TOP_SCORE_ - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); #endif prune_score = m_tracker.get_score_prune(cur); @@ -745,7 +766,8 @@ public: #if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - if (!m_tracker.has_uplinks(cur)) + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else @@ -833,44 +855,7 @@ public: } #endif - void randomize_local(expr * e, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_constants(e); - - // Randomize _one_ candidate: - unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); - func_decl * fd = unsat_constants[r]; -#if _PERC_CHANGE_ - sort * srt = fd->get_range(); - mpz temp; - - if (m_manager.is_bool(srt)) - m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); - - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } -#else - mpz temp = m_tracker.get_random(fd->get_range()); -#endif - update(fd, temp); - m_mpz_manager.del(temp); - } - - void randomize_local(goal_ref const & g, unsigned int flip) { - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, flip); - + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: //// bool did_something = false; @@ -927,6 +912,15 @@ public: tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + + } + + void randomize_local(expr * e) { + randomize_local(m_tracker.get_constants(e)); + } + + void randomize_local(goal_ref const & g, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(g, flip)); } }; diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 553acc35a..ada0ec359 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -34,6 +34,8 @@ Notes: #include"propagate_values_tactic.h" #include"sls_tactic.h" #include"nnf_tactic.h" +#include"luby.h" +#include "ctx_simplify_tactic.h" // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score @@ -43,9 +45,23 @@ Notes: // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom #define _FOCUS_ 1 +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + // do we use restarts? -// 0 = no, otherwise the value defines the maximum number of moves -#define _RESTARTS_ 0 +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 // timelimit #define _TIMELIMIT_ 3600 @@ -66,38 +82,58 @@ Notes: // 2 = yes, by squaring it // 3 = yes, by setting it to zero // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 0 +#define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 #define _WEIGHT_DIST_FACTOR_ 0.25 +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + // do we use intensification steps in local minima? if so, how many? #define _INTENSIFICATION_ 0 #define _INTENSIFICATION_TRIES_ 0 +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 0 +#define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 0.01 +#define _UCT_CONSTANT_ 10.0 // is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score #define _PROBABILISTIC_UCT_ 0 +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 // shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 1 +#define _USE_MUL2DIV2_ 0 // shall we try multiplication by 3? -#define _USE_MUL3_ 1 +#define _USE_MUL3_ 0 // shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 1 +#define _USE_UNARY_MINUS_ 0 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 1 +#define _UNIFORM_RANDOM_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 @@ -124,13 +160,21 @@ Notes: #define _CACHE_TOP_SCORE_ 1 -#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_) +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) InvalidConfiguration; #endif #if (_PROBABILISTIC_UCT_ && !_UCT_) InvalidConfiguration; #endif - +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) + InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) + InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) + InvalidConfiguration; +#endif #include"sls_params.hpp" #include"sls_evaluator.h" @@ -180,6 +224,7 @@ class sls_tactic : public tactic { sls_tracker m_tracker; sls_evaluator m_evaluator; + unsigned m_restart_limit; unsigned m_max_restarts; unsigned m_plateau_limit; @@ -208,6 +253,41 @@ class sls_tactic : public tactic { m_mpz_manager.del(m_two); } + double get_restart_armin(unsigned cnt_restarts) + { + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow(_RESTART_CONST_ARMIN_, inner_id + 1); + } + + inline unsigned check_restart(unsigned curr_value) + { + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; + } + ast_manager & m() const { return m_manager; } void set_cancel(bool f) { m_cancel = f; } @@ -435,12 +515,10 @@ class sls_tactic : public tactic { NOT_IMPLEMENTED_YET(); } - void mk_random_move(goal_ref const & g) { + void mk_random_move(ptr_vector & unsat_constants) + { unsigned rnd_mv = 0; - if (m_stats.m_moves > 10000) - rnd_mv = 0; - ptr_vector & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves); unsigned ucc = unsat_constants.size(); unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; func_decl * fd = unsat_constants[rc]; @@ -503,6 +581,10 @@ class sls_tactic : public tactic { m_mpz_manager.del(new_value); } + void mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); + } + // will use VNS to ignore some possible moves and increase the flips per second double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { @@ -857,7 +939,7 @@ class sls_tactic : public tactic { m_stats.m_flips++; global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); + local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -875,6 +957,130 @@ class sls_tactic : public tactic { unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + // main search loop + lbool search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; score = rescore(g); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; @@ -887,12 +1093,12 @@ class sls_tactic : public tactic { // Andreas: Why do we only allow so few plateaus? #if _RESTARTS_ - while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #else while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { #endif do { - if (m_stats.m_moves == 5590) checkpoint(); #if _WEIGHT_DIST_ == 4 @@ -1072,7 +1278,11 @@ class sls_tactic : public tactic { verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; @@ -1081,9 +1291,14 @@ class sls_tactic : public tactic { verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; verbose_stream() << "_UCT_ " << _UCT_ << std::endl; verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; @@ -1099,21 +1314,30 @@ class sls_tactic : public tactic { verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; #if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif m_tracker.initialize(g); lbool res = l_undef; + m_restart_limit = _RESTART_LIMIT_; + do { checkpoint(); - // Andreas: I think restarts are too impotant to ignore 99% of them are happening... - //if ((m_stats.m_restarts % 100) == 0) - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); res = search(g); if (res == l_undef) - m_tracker.randomize(); + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); @@ -1121,6 +1345,13 @@ class sls_tactic : public tactic { if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + if (m_produce_models) { model_ref mdl = m_tracker.get_model(); mc = model2model_converter(mdl.get()); @@ -1183,12 +1414,17 @@ public: } virtual void cleanup() { - imp * d = alloc(imp, m, m_params, m_stats); + imp * d = m_imp; #pragma omp critical (tactic_cancel) { - std::swap(d, m_imp); + d = m_imp; } dealloc(d); + d = alloc(imp, m, m_params, m_stats); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } } virtual void collect_statistics(statistics & st) const { @@ -1246,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // conservative gaussian elimination. gaussian_p.set_uint("gaussian_max_occs", 2); + params_ref ctx_p; + ctx_p.set_uint("max_depth", 32); + ctx_p.set_uint("max_steps", 5000000); return and_then(and_then(mk_simplify_tactic(m), mk_propagate_values_tactic(m), using_params(mk_solve_eqs_tactic(m), gaussian_p), @@ -1254,6 +1493,10 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), + // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? + //mk_ctx_simplify_tactic(m, ctx_p), + // Andreas: This one at least eliminates top level duplicates ... + mk_simplify_tactic(m), // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 006bbb888..0aca1f59c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -65,6 +65,7 @@ private: typedef obj_map scores_type; typedef obj_map > uplinks_type; typedef obj_map > occ_type; + obj_hashtable m_top_expr; scores_type m_scores; uplinks_type m_uplinks; entry_point_type m_entry_points; @@ -75,15 +76,15 @@ private: unsigned m_touched; #endif #if _REAL_RS_ || _REAL_PBFS_ - ptr_vector m_unsat_expr; - obj_map m_where_false; - expr** m_list_false; + ptr_vector m_unsat_expr; + obj_map m_where_false; + expr** m_list_false; #endif #if _CACHE_TOP_SCORE_ - double m_top_sum; + double m_top_sum; #endif -#if _WEIGHT_DIST_ == 4 - double m_weight_dist_factor; +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ + double m_weight_dist_factor; #endif public: @@ -104,7 +105,7 @@ public: m_mpz_manager.del(m_two); } -#if _WEIGHT_DIST_ == 4 +#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ inline void set_weight_dist_factor(double val) { m_weight_dist_factor = val; } @@ -182,12 +183,12 @@ public: inline unsigned has_pos_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_pos_occ; - } + } inline unsigned has_neg_occ(expr * n) { SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; - } + } #endif inline unsigned get_distance(expr * n) { @@ -213,11 +214,62 @@ public: return m_uplinks.contains(n); } + inline bool is_top_expr(expr * n) { + return m_top_expr.contains(n); + } + inline ptr_vector & get_uplinks(expr * n) { SASSERT(m_uplinks.contains(n)); return m_uplinks.find(n); } +#if _REAL_RS_ || _REAL_PBFS_ + void debug_real(goal_ref const & g, unsigned flip) + { + unsigned count = 0; + for (unsigned i = 0; i < g->size(); i++) + { + expr * e = g->form(i); + if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) + { + printf("iteration %d: ", flip); + printf("form %d is unsat but not in unsat list\n", i); + exit(4); + } + + if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) + { + unsigned pos = m_where_false.find(e); + expr * q = m_list_false[pos]; + if (q != e) + { + printf("iteration %d: ", flip); + printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); + exit(4); + } + } + + if (m_mpz_manager.eq(get_value(e),m_zero)) + count++; + } + + // should be true now that duplicate assertions are removed + if (count != m_where_false.size()) + { + printf("iteration %d: ", flip); + printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); + exit(4); + } + } +#endif + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -327,7 +379,7 @@ public: } } for_each_expr(proc, visited, e); - } + } void initialize_recursive(expr * e) { if (m_manager.is_and(e) || m_manager.is_or(e)) { @@ -344,7 +396,7 @@ public: find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + } void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); @@ -352,6 +404,10 @@ public: unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); + if (!m_top_expr.contains(e)) + m_top_expr.insert(e); + else + printf("this is already in ...\n"); // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 initialize_recursive(proc, visited, e); @@ -380,18 +436,20 @@ public: #if _REAL_RS_ || _REAL_PBFS_ m_list_false = new expr*[sz]; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - break_assertion(g->form(i)); + //for (unsigned i = 0; i < sz; i++) + //{ + // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) + // break_assertion(g->form(i)); + //} #endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; #endif } @@ -407,8 +465,12 @@ public: expr * q = m_list_false[m_where_false.size()]; m_list_false[pos] = q; m_where_false.find(q) = pos; + //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); } -// printf("Going in %d\n", m_where_false.size()); + //else + //printf("Erasing %d from %d to %d\n", e, pos); +// m_list_false[m_where_false.size()] = 0; +// printf("Going in %d\n", m_where_false.size()); } //if (m_unsat_expr.contains(e)) //m_unsat_expr.erase(e); @@ -416,12 +478,14 @@ public: void break_assertion(expr * e) { + //printf("I'm broken... that's still fine.\n"); if (!m_where_false.contains(e)) { + //printf("This however is not so cool...\n"); unsigned pos = m_where_false.size(); m_list_false[pos] = e; m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); + // printf("Going in %d\n", m_where_false.size()); } //if (!m_unsat_expr.contains(e)) //m_unsat_expr.push_back(e); @@ -522,7 +586,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize() { + void randomize(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -534,6 +598,28 @@ public: } TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif + } + + void reset(goal_ref const & g) { + TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); + + for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { + mpz temp = m_zero; + set_value(it->m_value, temp); + m_mpz_manager.del(temp); + } + +#if _UCT_RESET_ + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; +#endif } #if _EARLY_PRUNE_ @@ -591,12 +677,20 @@ public: #if _SCORE_AND_AVG_ double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) +#if _DIRTY_UP_ + sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else sum += get_score(args[i]); +#endif res = sum / (double) a->get_num_args(); #else double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur < min) min = cur; } res = min; @@ -610,14 +704,22 @@ public: #if _SCORE_OR_MUL_ double inv = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif inv *= (1.0 - get_score(args[i])); } res = 1.0 - inv; #else double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { +#if _DIRTY_UP_ + double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); +#else double cur = get_score(args[i]); +#endif if (cur > max) max = cur; } res = max; @@ -772,7 +874,11 @@ public: expr * child = a->get_arg(0); if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); +#if _DIRTY_UP_ + res = is_top_expr(child) ? 0.0 : score_bool(child, true); +#else res = score_bool(child, true); +#endif } else if (m_manager.is_distinct(n)) { app * a = to_app(n); @@ -803,7 +909,11 @@ public: if (afid == m_bv_util.get_family_id()) #endif #if _WEIGHT_DIST_ == 1 +#if _WEIGHT_TOGGLE_ + if (res < 1.0) res *= m_weight_dist_factor; +#else if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; +#endif #elif _WEIGHT_DIST_ == 2 res *= res; #elif _WEIGHT_DIST_ == 3 @@ -900,6 +1010,10 @@ public: } ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + if (sz == 1) + return get_constants(); + m_temp_constants.reset(); + for (unsigned i = 0; i < sz; i++) { expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) @@ -945,7 +1059,7 @@ public: } ptr_vector & get_unsat_constants_walksat(expr * e) { - if (!e) + if (!e || m_temp_constants.size()) return m_temp_constants; ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); @@ -1033,32 +1147,43 @@ public: #if _PROBABILISTIC_UCT_ double sum_score = 0.0; unsigned start_index = get_random_uint(16) % sz; + for (unsigned i = start_index; i < sz; i++) { expr * e = g->form(i); vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { sum_score += q; if (rand() <= (q * RAND_MAX / sum_score) + 1) pos = i; - } + } } for (unsigned i = 0; i < start_index; i++) { expr * e = g->form(i); vscore = m_scores.find(e); - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { sum_score += q; if (rand() <= (q * RAND_MAX / sum_score) + 1) pos = i; - } + } } #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); @@ -1078,6 +1203,7 @@ public: m_scores.find(g->form(pos)).touched = flip; #endif expr * e = g->form(pos); +// expr * e = m_list_false[pos]; #elif _BFS_ == 3 unsigned int pos = -1; @@ -1109,7 +1235,7 @@ public: #elif _UNIFORM_RANDOM_ unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; if (pos == static_cast(-1)) return m_temp_constants; expr * e = g->form(pos); @@ -1120,8 +1246,7 @@ public: sz = m_where_false.size(); if (sz == 0) return m_temp_constants; - else - expr * e = m_list_false[get_random_uint(16) % sz]; + expr * e = m_list_false[get_random_uint(16) % sz]; #elif _REAL_PBFS_ //unsigned pos = m_false_list[flip % m_cnt_false]; //expr * e = get_unsat_assertion(g, sz, pos); @@ -1154,6 +1279,142 @@ public: #endif } } + + + expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); + + if (sz == 1) + return g->form(0); + + m_temp_constants.reset(); +#if _FOCUS_ == 1 +#if _UCT_ + unsigned pos = -1; + value_score vscore; +#if _PROBABILISTIC_UCT_ + double sum_score = 0.0; + unsigned start_index = get_random_uint(16) % sz; + + for (unsigned i = start_index; i < sz; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } + for (unsigned i = 0; i < start_index; i++) + { + expr * e = g->form(i); + vscore = m_scores.find(e); +#if _PROBABILISTIC_UCT_ == 2 + double q = vscore.score * vscore.score + _UCT_EPS_; +#else + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; +#endif + if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { + sum_score += q; + if (rand() <= (q * RAND_MAX / sum_score) + 1) + pos = i; + } + } +#else + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); +// for (unsigned i = 0; i < m_where_false.size(); i++) { +// expr * e = m_list_false[i]; + vscore = m_scores.find(e); +#if _UCT_ == 1 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); +#elif _UCT_ == 2 + double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#endif + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + } +#endif + if (pos == static_cast(-1)) + return 0; + +#if _UCT_ == 1 + m_scores.find(g->form(pos)).touched++; + m_touched++; +#elif _UCT_ == 2 + m_scores.find(g->form(pos)).touched = flip; +#endif +// return m_list_false[pos]; + return g->form(pos); + +#elif _BFS_ == 3 + unsigned int pos = -1; + double max = -1.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 2 + unsigned int pos = -1; + double min = 2.0; + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + double q = get_score(e); + if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } + } + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _BFS_ == 1 + unsigned int pos = flip % sz; + return get_unsat_assertion(g, sz, pos); +#elif _UNIFORM_RANDOM_ + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + return g->form(pos); +#elif _REAL_RS_ + //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; +#elif _REAL_PBFS_ + //unsigned pos = m_false_list[flip % m_cnt_false]; + //expr * e = get_unsat_assertion(g, sz, pos); + //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; + sz = m_where_false.size(); + if (sz == 0) + return0; + else + return m_list_false[flip % sz]; +#else + unsigned int pos = get_random_uint(16) % sz; + return get_unsat_assertion(g, sz, pos); +#endif + return g->form(pos); +#elif _FOCUS_ == 2 +#if _BFS_ + unsigned int pos = flip % sz; +#else + unsigned int pos = get_random_uint(16) % sz; +#endif + return get_unsat_constants_crsat(g, sz, pos); +#endif + } }; #endif \ No newline at end of file From 7451e5cae0ccdf110065453d8918f7f2e7726d4a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:04:38 +0000 Subject: [PATCH 209/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 158 +++ src/tactic/sls/sls_engine.cpp | 1027 +++++++++++---- src/tactic/sls/sls_engine.h | 88 +- src/tactic/sls/sls_evaluator.h | 3 + src/tactic/sls/sls_tactic.cpp | 1397 +-------------------- src/tactic/sls/sls_tracker.h | 10 +- 6 files changed, 1036 insertions(+), 1647 deletions(-) create mode 100644 src/tactic/sls/sls_compilation_settings.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h new file mode 100644 index 000000000..aea4787b0 --- /dev/null +++ b/src/tactic/sls/sls_compilation_settings.h @@ -0,0 +1,158 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + sls_compilation_constants.h + +Abstract: + + Stochastic Local Search (SLS) compilation constants + +Author: + + Christoph (cwinter) 2014-03-19 + +Notes: + + This file should go away completely once we have evaluated all options. + +--*/ +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom +#define _FOCUS_ 1 + +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 0 + +// do we use restarts? +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 3.0 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? +#define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? +#define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained +#define _VNS_ 0 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 1 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.25 + +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 1 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 10.0 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score +#define _PROBABILISTIC_UCT_ 0 + +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 1 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 0 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 0 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 0 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 0 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) +InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) +InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) +InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) +InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) +InvalidConfiguration; +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index c0c319ab4..92471aad8 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,7 +16,6 @@ Author: Notes: --*/ -#include #include #include"map.h" @@ -28,6 +27,7 @@ Notes: #include"cooperate.h" #include"luby.h" +#include"sls_compilation_settings.h" #include"sls_params.hpp" #include"sls_engine.h" @@ -44,7 +44,6 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) : m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) { updt_params(p); - m_tracker.updt_params(p); } sls_engine::~sls_engine() { @@ -53,32 +52,20 @@ sls_engine::~sls_engine() { m_mpz_manager.del(m_two); } +double sls_engine::get_restart_armin(unsigned cnt_restarts) +{ + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} + void sls_engine::updt_params(params_ref const & _p) { sls_params p(_p); m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.max_restarts(); + m_max_restarts = p.restarts(); m_tracker.set_random_seed(p.random_seed()); - m_walksat = p.walksat(); - m_walksat_repick = p.walksat_repick(); - m_paws_sp = p.paws_sp(); - m_paws = m_paws_sp < 1024; - m_wp = p.wp(); - m_vns_mc = p.vns_mc(); - m_vns_repick = p.vns_repick(); - - m_restart_base = p.restart_base(); - m_restart_next = m_restart_base; - m_restart_init = p.restart_init(); - - m_early_prune = p.early_prune(); - m_random_offset = p.random_offset(); - m_rescore = p.rescore(); - - // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. - if (m_walksat_repick && !m_walksat) - NOT_IMPLEMENTED_YET(); - if (m_vns_repick && !m_walksat) - NOT_IMPLEMENTED_YET(); + m_plateau_limit = p.plateau_limit(); } void sls_engine::checkpoint() { @@ -87,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(model & mdl) { +bool sls_engine::full_eval(goal_ref const & g, model & mdl) { bool res = true; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(m_assertions[i], o, true)) + if (!mdl.eval(g->form(i), o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -106,69 +93,96 @@ bool sls_engine::full_eval(model & mdl) { return res; } -double sls_engine::top_score() { +double sls_engine::top_score(goal_ref const & g) { +#if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl;); + return min; +#else double top_sum = 0.0; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = m_assertions[i]; + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(m_assertions[i]); + tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double)sz << std::endl;); +#if _CACHE_TOP_SCORE_ m_tracker.set_top_sum(top_sum); +#endif - return top_sum; + return top_sum / (double)sz; +#endif } -double sls_engine::rescore() { +double sls_engine::rescore(goal_ref const & g) { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(); + return top_score(g); } -double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; - return m_tracker.get_top_sum(); +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif } -double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; - return m_tracker.get_top_sum(); +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif } -double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +#if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) - return m_tracker.get_top_sum(); +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif else - return -DBL_MAX; + return 0.0; +#else + NOT_IMPLEMENTED_YET(); +#endif } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if( - func_decl * fd, - const unsigned & fd_inx, - const mpz & temp, - double & best_score, - unsigned & best_const, - mpz & best_value) { +bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { #ifdef Z3DEBUG mpz old_value; m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif - double r; - if (m_early_prune) - r = incremental_score_prune(fd, temp); - else - r = incremental_score(fd, temp); +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else + double r = incremental_score(g, fd, temp); +#endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl;); @@ -176,10 +190,7 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif - // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection. - // r += 0.0001 * m_tracker.get_random_uint(8); - - // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. + // if (r >= best_score) { if (r > best_score) { best_score = r; best_const = fd_inx; @@ -190,6 +201,21 @@ bool sls_engine::what_if( return false; } +// same as what_if, but only applied to the score of a specific atom, not the total score +bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { mpz temp, mask, mask2; m_mpz_manager.add(old_value, add_value, temp); @@ -202,6 +228,22 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, } +// Andreas: do we really need all those temporary mpzs? +void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); +} + +void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); +} + void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); @@ -251,18 +293,16 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); else { +#if _USE_ADDSUB_ if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - - // Andreas: The other option would be to scale the probability for flips according to the bit-width. - /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt); - rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3); - if (rnd_mv > 3) rnd_mv = 0; */ - move_type mt = (move_type)rnd_mv; - // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true? + // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif unsigned bit = 0; switch (mt) @@ -300,30 +340,192 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); } - m_evaluator.serious_update(fd, new_value); + m_evaluator.update(fd, new_value); m_mpz_manager.del(new_value); } -// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move( - ptr_vector & to_evaluate, - double score, - unsigned & best_const, - mpz & best_value, - unsigned & new_bit, - move_type & move) -{ +void sls_engine::mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +} + +// will use VNS to ignore some possible moves and increase the flips per second +double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + // we can either check the condition once in the beginning or check it repeatedly after every bit +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif unsigned bv_sz; double new_score = score; - // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. - unsigned sz = to_evaluate.size(); - unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; - for (unsigned j = 0; j < sz; j++) { - unsigned i = j + offset; - if (i >= sz) i -= sz; - //for (unsigned i = 0; i < to_evaluate.size(); i++) { + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; +} + +// same as find_best_move but only considers the score of the current expression instead of the overall score +double sls_engine::find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -334,7 +536,7 @@ double sls_engine::find_best_move( // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } @@ -344,176 +546,489 @@ double sls_engine::find_best_move( if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } + // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; } + // reset to what it was before - incremental_score(fd, old_value); + m_evaluator.update(fd, old_value); } m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - return new_score; } -// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value) { - mpz old_value, temp, temp2; - unsigned bv_sz; - double new_score = score; +// first try of intensification ... does not seem to be efficient +bool sls_engine::handle_plateau(goal_ref const & g) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; - // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. - unsigned sz = to_evaluate.size(); - unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; - for (unsigned j = 0; j < sz; j++) { - unsigned i = j + offset; - if (i >= sz) i -= sz; - //for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back(&m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { - for (unsigned j = 0; j < bv_sz; j++) { - mk_flip(srt, old_value, j, temp); - for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++) - { - unsigned k = m_tracker.get_random_uint(16) % bv_sz; - while (k == j) - k = m_tracker.get_random_uint(16) % bv_sz; - mk_flip(srt, temp, k, temp2); - what_if(fd, i, temp2, new_score, best_const, best_value); - } - } + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); } - // reset to what it was before - incremental_score(fd, old_value); + else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], *m_old_values[i]); + + m_old_values.reset(); + + return 0; +} + +// what_if version needed in the context of 2nd intensification try, combining local and global score +bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; +} + +// find_best_move version needed in the context of 2nd intensification try +double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +{ + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); m_mpz_manager.del(temp); - m_mpz_manager.del(temp2); - return new_score; + return best_score; +} + +// second try to use intensification ... also not very effective +bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +{ + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; } // main search loop -lbool sls_engine::search() { +lbool sls_engine::search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit; + unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; + unsigned plateau_cnt = 0; - score = rescore(); - unsigned sz = m_assertions.size(); + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif - while (check_restart(m_stats.m_moves)) { +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif checkpoint(); m_stats.m_moves++; - // Andreas: Every base restart interval ... - if (m_stats.m_moves % m_restart_base == 0) - { - // ... potentially smooth the touched counters ... - m_tracker.ucb_forget(m_assertions); - // ... or normalize the top-level score. - if (m_rescore) score = rescore(); - } +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif - // get candidate variables - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); if (!to_evaluate.size()) { res = l_true; goto bailout; } +#endif - // random walk with probability wp / 1024 - if (m_wp && m_tracker.get_random_uint(10) < m_wp) +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 mk_random_move(to_evaluate); - score = m_tracker.get_top_sum(); - continue; +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif } + continue; +#endif +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif old_score = score; new_const = (unsigned)-1; - // find best increasing move - score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif - // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously - if (m_vns_mc && (new_const == static_cast(-1))) - score = find_best_move_mc(to_evaluate, score, new_const, new_value); - - // repick assertion if no increasing move was found previously - if (m_vns_repick && (new_const == static_cast(-1))) - { - expr * q = m_tracker.get_new_unsat_assertion(m_assertions); - // only apply if another unsatisfied assertion actually exists - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); - score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); - - if (new_const != static_cast(-1)) { - func_decl * fd = to_evaluate2[new_const]; - score = serious_score(fd, new_value); - continue; - } - } - } - - // randomize if no increasing move was found if (new_const == static_cast(-1)) { score = old_score; - if (m_walksat_repick) - m_evaluator.randomize_local(m_assertions); + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else m_evaluator.randomize_local(to_evaluate); +#endif +#endif - score = m_tracker.get_top_sum(); - - // update assertion weights if a weigthing is enabled (sp < 1024) - if (m_paws) - { - for (unsigned i = 0; i < sz; i++) - { - expr * q = m_assertions[i]; - // smooth weights with probability sp / 1024 - if (m_tracker.get_random_uint(10) < m_paws_sp) - { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) - m_tracker.decrease_weight(q); - } - // increase weights otherwise - else - { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) - m_tracker.increase_weight(q); - } - } - } +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif } - // otherwise, apply most increasing move else { func_decl * fd = to_evaluate[new_const]; - score = serious_score(fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + +bailout: + m_mpz_manager.del(new_value); + + return res; +} + +// main search loop +lbool sls_engine::search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { +#endif + do { + checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl;); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl;); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl;); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + } + + if (score >= 0.99999) { + // if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } + else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else + m_evaluator.randomize_local(g, m_stats.m_moves); +#endif + //mk_random_move(g); + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true = false; + if (all_true) { + res = l_true; // sat + goto bailout; + } + else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } } } @@ -531,10 +1046,71 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); - for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - lbool res = operator()(); +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); @@ -556,66 +1132,29 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -lbool sls_engine::operator()() { - m_tracker.initialize(m_assertions); - lbool res = l_undef; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(); - - if (res == l_undef) - { - if (m_restart_init) - m_tracker.randomize(m_assertions); - else - m_tracker.reset(m_assertions); - } - } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - return res; -} - -/* Andreas: Needed for Armin's restart scheme if we don't want to use loops. -double sls_engine::get_restart_armin(unsigned cnt_restarts) -{ - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); -} -*/ - unsigned sls_engine::check_restart(unsigned curr_value) { - if (curr_value > m_restart_next) + if (curr_value > m_restart_limit) { - /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter. - I leave the other versions as comments in case you want to try it again somewhen. -#if _RESTART_SCHEME_ == 5 - m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); -#elif _RESTART_SCHEME_ == 4 - m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1); +#if _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 - m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base; + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; #elif _RESTART_SCHEME_ == 2 - m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base; + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) - m_restart_next += m_restart_base; + m_restart_limit += _RESTART_LIMIT_; else - m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; #else - m_restart_limit += m_restart_base; -#endif */ - if (m_stats.m_restarts & 1) - m_restart_next += m_restart_base; - else - m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif return 0; } return 1; -} +} \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index b056c438e..878354c6d 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,8 +22,8 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" -#include"goal.h" +#include"sls_compilation_settings.h" #include"sls_tracker.h" #include"sls_evaluator.h" @@ -35,13 +35,17 @@ public: stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -67,24 +71,14 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; - ptr_vector m_assertions; + unsigned m_restart_limit; unsigned m_max_restarts; - unsigned m_walksat; - unsigned m_walksat_repick; - unsigned m_wp; - unsigned m_vns_mc; - unsigned m_vns_repick; - unsigned m_paws; - unsigned m_paws_sp; - unsigned m_restart_base; - unsigned m_restart_next; - unsigned m_restart_init; - unsigned m_early_prune; - unsigned m_random_offset; - unsigned m_rescore; + unsigned m_plateau_limit; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; public: sls_engine(ast_manager & m, params_ref const & p); @@ -98,46 +92,68 @@ public: void updt_params(params_ref const & _p); - void assert_expr(expr * e) { m_assertions.push_back(e); } - stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(model & mdl); + bool full_eval(goal_ref const & g, model & mdl); + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result); void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - lbool search(void); + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + + + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); + + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); + + + lbool search(goal_ref const & g); - lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); + lbool search_old(goal_ref const & g); + double get_restart_armin(unsigned cnt_restarts); - bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(); - double rescore(); - double serious_score(func_decl * fd, const mpz & new_value); - double incremental_score(func_decl * fd, const mpz & new_value); + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); - double incremental_score_prune(func_decl * fd, const mpz & new_value); - double find_best_move(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double top_score(goal_ref const & g); + double rescore(goal_ref const & g); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double find_best_move_mc(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value); +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); +#endif + + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); void mk_random_move(ptr_vector & unsat_constants); + void mk_random_move(goal_ref const & g); - //double get_restart_armin(unsigned cnt_restarts); - unsigned check_restart(unsigned curr_value); + bool handle_plateau(goal_ref const & g); + bool handle_plateau(goal_ref const & g, double old_score); + + inline unsigned check_restart(unsigned curr_value); }; -#endif +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 696d7664a..9daf93c32 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -20,6 +20,9 @@ Notes: #ifndef _SLS_EVALUATOR_H_ #define _SLS_EVALUATOR_H_ +#include"model_evaluator.h" + +#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index ada0ec359..0f157d3a6 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,1364 +16,31 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" -#include"luby.h" -#include "ctx_simplify_tactic.h" - -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick clause when randomizing in a plateau or use the current one? -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 - -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 - -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? -#define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) - InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) - InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) - InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) - InvalidConfiguration; -#endif +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; - - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_restart_limit; - unsigned m_max_restarts; - unsigned m_plateau_limit; - - ptr_vector m_old_values; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - double get_restart_armin(unsigned cnt_restarts) - { - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow(_RESTART_CONST_ARMIN_, inner_id + 1); - } - - inline unsigned check_restart(unsigned curr_value) - { - if (curr_value > m_restart_limit) - { -#if _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); -#elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 1 - if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; - else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; -#else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif - return 0; - } - return 1; - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - top_sum += m_tracker.get_score(e); - } - - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - -#if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); -#endif - - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; - } -#endif - - // checks whether the score outcome of a given move is better than the previous score - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - -#if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); -#else - double r = incremental_score(g, fd, temp); -#endif - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - -// if (r >= best_score) { - if (r > best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // same as what_if, but only applied to the score of a specific atom, not the total score - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.add(old_value, add_value, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - - } - - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - } - - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(ptr_vector & unsat_constants) - { - unsigned rnd_mv = 0; - - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - - mpz new_value; - - sort * srt = fd->get_range(); - if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { -#if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; -#else - mt = MV_FLIP; -#endif - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } - - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } - - void mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); - } - - // will use VNS to ignore some possible moves and increase the flips per second - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } -#endif - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - return new_score; - } - - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - - m_old_values.reset(); - - return 0; - } - - // what_if version needed in the context of 2nd intensification try, combining local and global score - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // find_best_move version needed in the context of 2nd intensification try - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; - } - - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; - } - - // main search loop - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - unsigned plateau_cnt = 0; - - score = rescore(g); - unsigned sz = g->size(); -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - checkpoint(); - m_stats.m_moves++; - -#if _REAL_RS_ || _REAL_PBFS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } - continue; -#endif - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - old_score = score; - new_const = (unsigned)-1; - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - - if (new_const == static_cast(-1)) { - score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); - else -#endif -#if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); -#else - m_evaluator.randomize_local(to_evaluate); -#endif -#endif - -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } else { - func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - // main search loop - lbool search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 0.99999) { -// if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } - while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -1381,16 +48,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -1398,14 +65,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -1414,40 +80,41 @@ public: } virtual void cleanup() { - imp * d = m_imp; + sls_engine * d = m_engine; #pragma omp critical (tactic_cancel) { - d = m_imp; + d = m_engine; } dealloc(d); - d = alloc(imp, m, m_params, m_stats); + d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - m_imp = d; + m_engine = d; } } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + sls_engine::stats const & stats = m_engine->get_stats(); + double seconds = stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", stats.m_restarts); + st.update("sls full evals", stats.m_full_evals); + st.update("sls incr evals", stats.m_incr_evals); + st.update("sls incr evals/sec", stats.m_incr_evals / seconds); + st.update("sls FLIP moves", stats.m_flips); + st.update("sls INC moves", stats.m_incs); + st.update("sls DEC moves", stats.m_decs); + st.update("sls INV moves", stats.m_invs); + st.update("sls moves", stats.m_moves); + st.update("sls moves/sec", stats.m_moves / seconds); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 0aca1f59c..3675265ee 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,12 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"goal.h" +#include"model.h" + +#include"sls_compilation_settings.h" +#include"sls_powers.h" + class sls_tracker { ast_manager & m_manager; unsynch_mpz_manager & m_mpz_manager; @@ -1186,7 +1192,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif @@ -1334,7 +1340,7 @@ public: // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #endif From 13307a1d51c1c21e421b6a1e28fc8b5476f7b53e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Mar 2014 17:26:05 +0000 Subject: [PATCH 210/646] SLS refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index aea4787b0..8e52596e0 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -18,6 +18,10 @@ Notes: This file should go away completely once we have evaluated all options. --*/ + +#ifndef _SLS_COMPILATION_SETTINGS_H_ +#define _SLS_COMPILATION_SETTINGS_H_ + // which unsatisfied assertion is selected? only works with _FOCUS_ > 0 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score #define _BFS_ 0 @@ -155,4 +159,6 @@ InvalidConfiguration; #endif #if (_PERC_STICKY_ && !_FOCUS_) InvalidConfiguration; +#endif + #endif \ No newline at end of file From ad8cac7d886d1dc6e9255990fc192c83662c2277 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Thu, 20 Mar 2014 15:58:53 +0000 Subject: [PATCH 211/646] uct forget and minisat restarts added --- src/tactic/sls/sls_tactic.cpp | 1417 ++++++++++++++++++++++++++++++++- src/tactic/sls/sls_tracker.h | 22 +- 2 files changed, 1402 insertions(+), 37 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 0f157d3a6..b2b7035e0 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,31 +16,1378 @@ Author: Notes: --*/ +#include +#include"map.h" #include"nnf.h" +#include"cooperate.h" +#include"ast_smt2_pp.h" +#include"ast_pp.h" +#include"var_subst.h" +#include"model_pp.h" +#include"model_evaluator.h" #include"solve_eqs_tactic.h" +#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"propagate_values_tactic.h" -#include"ctx_simplify_tactic.h" -#include"elim_uncnstr_tactic.h" -#include"nnf_tactic.h" #include"stopwatch.h" - +#include"propagate_values_tactic.h" #include"sls_tactic.h" -#include"sls_params.hpp" -#include"sls_engine.h" +#include"nnf_tactic.h" +#include"luby.h" +#include "ctx_simplify_tactic.h" -class sls_tactic : public tactic { +// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 +// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score +#define _BFS_ 0 + +// how many terms are considered for variable selection? +// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom +#define _FOCUS_ 1 + +// probability of choosing the same assertion again in the next step +#define _PERC_STICKY_ 0 + +// do we use dirty unit propagation to get rid of nested top level assertions? +#define _DIRTY_UP_ 1 + +// do we use restarts? +// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time +#define _RESTARTS_ 3 +// limit of moves/plateaus/seconds until first restart occurs +#define _RESTART_LIMIT_ 10 +// 0 = initialize with all zero, 1 initialize with random value +#define _RESTART_INIT_ 0 +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat +#define _RESTART_SCHEME_ 1 +// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 +#define _RESTART_CONST_ARMIN_ 4.0 + +// timelimit +#define _TIMELIMIT_ 3600 + +// should score of conjunctions be calculated by average rather than max? +#define _SCORE_AND_AVG_ 0 + +// should score of discunctions be calculated by multiplication of the inverse score rather than min? +#define _SCORE_OR_MUL_ 0 + +// do we use some kind of variable neighbourhood-search? +// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained +#define _VNS_ 0 + +// do we reduce the score of unsatisfied literals? +// 0 = no +// 1 = yes, by multiplying it with some factor +// 2 = yes, by squaring it +// 3 = yes, by setting it to zero +// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) +#define _WEIGHT_DIST_ 1 + +// the factor used for _WEIGHT_DIST_ = 1 +#define _WEIGHT_DIST_FACTOR_ 0.5 + +// shall we toggle the weight after each restart? +#define _WEIGHT_TOGGLE_ 0 + +// do we use intensification steps in local minima? if so, how many? +#define _INTENSIFICATION_ 0 +#define _INTENSIFICATION_TRIES_ 0 + +// what is the percentage of random moves in plateaus (instead of full randomization)? +#define _PERC_PLATEAU_MOVES_ 0 + +// shall we repick clause when randomizing in a plateau or use the current one? +#define _REPICK_ 1 + +// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ +#define _UCT_ 1 + +// how much diversification is used in the UCT-scheme? +#define _UCT_CONSTANT_ 20.0 + +// is uct clause selection probabilistic similar to variable selection in sparrow? +// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score +#define _PROBABILISTIC_UCT_ 0 + +// additive constants for probabilistic uct > 0 +#define _UCT_EPS_ 0.0001 + +// shall we reset _UCT_ touched values after restart? +#define _UCT_RESET_ 0 + +// do we gradually reduce the touched values of _UCT_? +#define _UCT_FORGET_ 0 +#define _UCT_FORGET_FACTOR_ 0.5 + +// how shall we initialize the _UCT_ total touched counter? +// 0 = initialize with one, 1 = initialize with number of assertions +#define _UCT_INIT_ 0 + +// shall we use addition/subtraction? +#define _USE_ADDSUB_ 1 + +// shall we try multilication and division by 2? +#define _USE_MUL2DIV2_ 0 + +// shall we try multiplication by 3? +#define _USE_MUL3_ 0 + +// shall we try unary minus (= inverting and incrementing) +#define _USE_UNARY_MINUS_ 0 + +// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 +#define _UNIFORM_RANDOM_ 0 + +// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +#define _REAL_RS_ 0 +#define _REAL_PBFS_ 0 + +// how many bits do we neglect in each iteration? +#define _SKIP_BITS_ 0 + +// when randomizing local, what is the probability for changing a single bit? +// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage +#define _PERC_CHANGE_ 0 + +// do we use random steps for noise? +// 0 = no, 1 = randomize local, 2 = make random move +#define _TYPE_RSTEP_ 0 + +// with what probability _PERM_STEP_/1000 will the random step happen? +#define _PERM_RSTEP_ 0 + +// shall we use early pruning for incremental update? +#define _EARLY_PRUNE_ 1 + +// shall we use caching for top_score? +#define _CACHE_TOP_SCORE_ 1 + + +#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) + InvalidConfiguration; +#endif +#if (_PROBABILISTIC_UCT_ && !_UCT_) + InvalidConfiguration; +#endif +#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) + InvalidConfiguration; +#endif +#if (_PERC_CHANGE_ == 50) + InvalidConfiguration; +#endif +#if (_PERC_STICKY_ && !_FOCUS_) + InvalidConfiguration; +#endif + +#include"sls_params.hpp" +#include"sls_evaluator.h" +#include"sls_tracker.h" + +class sls_tactic : public tactic { + class stats { + public: + unsigned m_restarts; + stopwatch m_stopwatch; + unsigned m_full_evals; + unsigned m_incr_evals; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + + stats() : + m_restarts(0), + m_full_evals(0), + m_incr_evals(0), + m_moves(0), + m_umins(0), + m_mul2s(0), + m_mul3s(0), + m_div2s(0), + m_flips(0), + m_incs(0), + m_decs(0), + m_invs(0) { + m_stopwatch.reset(); + m_stopwatch.start(); + } + void reset() { + m_full_evals = m_flips = m_incr_evals = 0; + m_stopwatch.reset(); + m_stopwatch.start(); + } + }; + + struct imp { + ast_manager & m_manager; + stats & m_stats; + unsynch_mpz_manager m_mpz_manager; + powers m_powers; + mpz m_zero, m_one, m_two; + bool m_produce_models; + volatile bool m_cancel; + bv_util m_bv_util; + sls_tracker m_tracker; + sls_evaluator m_evaluator; + + unsigned m_restart_limit; + unsigned m_max_restarts; + unsigned m_plateau_limit; + + ptr_vector m_old_values; + + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + + imp(ast_manager & m, params_ref const & p, stats & s) : + m_manager(m), + m_stats(s), + m_powers(m_mpz_manager), + m_zero(m_mpz_manager.mk_z(0)), + m_one(m_mpz_manager.mk_z(1)), + m_two(m_mpz_manager.mk_z(2)), + m_cancel(false), + m_bv_util(m), + m_tracker(m, m_bv_util, m_mpz_manager, m_powers), + m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) + { + updt_params(p); + } + + ~imp() { + m_mpz_manager.del(m_zero); + m_mpz_manager.del(m_one); + m_mpz_manager.del(m_two); + } + + double get_restart_armin(unsigned cnt_restarts) + { + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + //printf("armin: %f\n", pow(1.1, inner_id + 1)); + return pow(_RESTART_CONST_ARMIN_, inner_id + 1); + } + + inline unsigned check_restart(unsigned curr_value) + { + if (curr_value > m_restart_limit) + { +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 + m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); +#elif _RESTART_SCHEME_ == 3 + m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 2 + m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; +#elif _RESTART_SCHEME_ == 1 + if (m_stats.m_restarts & 1) + m_restart_limit += _RESTART_LIMIT_; + else + m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; +#else + m_restart_limit += _RESTART_LIMIT_; +#endif +#if _WEIGHT_TOGGLE_ + printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); +#endif + return 0; + } + return 1; + } + + ast_manager & m() const { return m_manager; } + + void set_cancel(bool f) { m_cancel = f; } + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } + + static void collect_param_descrs(param_descrs & r) { + sls_params::collect_param_descrs(r); + } + + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_produce_models = _p.get_bool("model", false); + m_max_restarts = p.restarts(); + m_tracker.set_random_seed(p.random_seed()); + m_plateau_limit = p.plateau_limit(); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("sls"); + } + + bool full_eval(goal_ref const & g, model & mdl) { + bool res = true; + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz && res; i++) { + checkpoint(); + expr_ref o(m_manager); + + if (!mdl.eval(g->form(i), o, true)) + exit(ERR_INTERNAL_FATAL); + + res = m_manager.is_true(o.get()); + } + + TRACE("sls", tout << "Evaluation: " << res << std::endl;); + + return res; + } + + double top_score(goal_ref const & g) { + #if 0 + double min = m_tracker.get_score(g->form(0)); + unsigned sz = g->size(); + for (unsigned i = 1; i < sz; i++) { + double q = m_tracker.get_score(g->form(i)); + if (q < min) min = q; + } + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " MIN: " << min << std::endl; ); + return min; + #else + double top_sum = 0.0; + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + expr * e = g->form(i); + top_sum += m_tracker.get_score(e); + } + + TRACE("sls_top", tout << "Score distribution:"; + for (unsigned i = 0; i < sz; i++) + tout << " " << m_tracker.get_score(g->form(i)); + tout << " AVG: " << top_sum / (double) sz << std::endl; ); + +#if _CACHE_TOP_SCORE_ + m_tracker.set_top_sum(top_sum); +#endif + + return top_sum / (double) sz; + #endif + } + + double rescore(goal_ref const & g) { + m_evaluator.update_all(); + m_stats.m_full_evals++; + return top_score(g); + } + + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.serious_update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_evaluator.update(fd, new_value); + m_stats.m_incr_evals++; +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + } + +#if _EARLY_PRUNE_ + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune(fd, new_value)) +#if _CACHE_TOP_SCORE_ + return (m_tracker.get_top_sum() / g->size()); +#else + return top_score(g); +#endif + else + return 0.0; + } +#endif + + // checks whether the score outcome of a given move is better than the previous score + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + #ifdef Z3DEBUG + mpz old_value; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + #endif + +#if _EARLY_PRUNE_ + double r = incremental_score_prune(g, fd, temp); +#else + double r = incremental_score(g, fd, temp); +#endif + #ifdef Z3DEBUG + TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << + " --> " << r << std::endl; ); + + m_mpz_manager.del(old_value); + #endif + +// if (r >= best_score) { + if (r > best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // same as what_if, but only applied to the score of a specific atom, not the total score + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + m_evaluator.update(fd, temp); + double r = m_tracker.get_score(e); + if (r >= best_score) { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.add(old_value, add_value, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + + } + + // Andreas: do we really need all those temporary mpzs? + void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { + mpz temp, mask, mask2; + m_mpz_manager.mul(old_value, m_two, temp); + m_mpz_manager.set(mask, m_powers(bv_sz)); + m_mpz_manager.bitwise_not(bv_sz, mask, mask2); + m_mpz_manager.bitwise_and(temp, mask2, result); + m_mpz_manager.del(temp); + m_mpz_manager.del(mask); + m_mpz_manager.del(mask2); + } + + void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { + m_mpz_manager.div(old_value, m_two, result); + } + + void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { + unsigned shift; + m_mpz_manager.add(old_value, m_one, incremented); + if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) + m_mpz_manager.set(incremented, m_zero); + } + + void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { + if (m_mpz_manager.is_zero(old_value)) { + m_mpz_manager.set(decremented, m_powers(bv_sz)); + m_mpz_manager.dec(decremented); + } + else + m_mpz_manager.sub(old_value, m_one, decremented); + } + + void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { + m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); + } + + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { + m_mpz_manager.set(flipped, m_zero); + + if (m_bv_util.is_bv_sort(s)) { + mpz mask; + m_mpz_manager.set(mask, m_powers(bit)); + m_mpz_manager.bitwise_xor(old_value, mask, flipped); + m_mpz_manager.del(mask); + } + else if (m_manager.is_bool(s)) + m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); + else + NOT_IMPLEMENTED_YET(); + } + + void mk_random_move(ptr_vector & unsat_constants) + { + unsigned rnd_mv = 0; + unsigned ucc = unsat_constants.size(); + unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; + func_decl * fd = unsat_constants[rc]; + + mpz new_value; + + sort * srt = fd->get_range(); + if (m_manager.is_bool(srt)) + m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); + else + { +#if _USE_ADDSUB_ + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; + if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + move_type mt = (move_type) rnd_mv; + + // inversion doesn't make sense, let's do a flip instead. + if (mt == MV_INV) mt = MV_FLIP; +#else + mt = MV_FLIP; +#endif + unsigned bit = 0; + + switch (mt) + { + case MV_FLIP: { + unsigned bv_sz = m_bv_util.get_bv_size(srt); + bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; + mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); + break; + } + case MV_INC: + mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_DEC: + mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + case MV_INV: + mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); + break; + default: + NOT_IMPLEMENTED_YET(); + } + + TRACE("sls", tout << "Randomization candidates: "; + for (unsigned i = 0; i < unsat_constants.size(); i++) + tout << unsat_constants[i]->get_name() << ", "; + tout << std::endl; + tout << "Random move: "; + switch (mt) { + case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; + case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; + case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; + case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; + } + tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); + } + + m_evaluator.update(fd, new_value); + m_mpz_manager.del(new_value); + } + + void mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); + } + + // will use VNS to ignore some possible moves and increase the flips per second + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + // we can either check the condition once in the beginning or check it repeatedly after every bit +#if _VNS_ == 1 + for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) +#else + if (new_score <= score) + for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) +#endif + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; +#if _USE_MUL3_ || _USE_UNARY_MINUS_ + mpz temp2; +#endif + unsigned bv_sz; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit +#if _SKIP_BITS_ + for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { +#else + for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +#endif + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { +#if _USE_ADDSUB_ + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } +#endif + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + +#if _USE_UNARY_MINUS_ + mk_inc(bv_sz, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_UMIN; +#endif + +#if _USE_MUL2DIV2_ + // try multiplication by 2 + mk_mul2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_MUL2; + +#if _USE_MUL3_ + // try multiplication by 3 + mk_add(bv_sz, old_value, temp, temp2); + if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) + move = MV_MUL3; +#endif + + // try division by 2 + mk_div2(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DIV2; +#endif + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + // Andreas: does not hold anymore now that we use top level score caching + //SASSERT(check == score); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); +#if _USE_MUL3_ + m_mpz_manager.del(temp2); +#endif + return new_score; + } + + // same as find_best_move but only considers the score of the current expression instead of the overall score + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz; + double new_score = m_tracker.get_score(e); + // Andreas: tie breaking not implemented yet + // double tie_score = top_score(g); + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // first try to flip every bit + for (unsigned j = 0; j < bv_sz; j++) { + // What would happen if we flipped bit #i ? + mk_flip(srt, old_value, j, temp); + + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + } + + // reset to what it was before + m_evaluator.update(fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; + } + + // first try of intensification ... does not seem to be efficient + bool handle_plateau(goal_ref const & g) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned pos = m_stats.m_moves % sz; +#else + unsigned pos = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + for (unsigned i = 0; i < to_evaluate.size(); i++) + { + m_tracker.get_value(to_evaluate[i]); + m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); + } + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) + { + // Andreas: Could be extended to use (best) score but this is computationally more expensive. + find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); + + if (new_const == static_cast(-1)) { + // Andreas: Actually this should never happen. + NOT_IMPLEMENTED_YET(); + } else { + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + + m_evaluator.update(fd, new_value); + } + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + for (unsigned i = 0; i < to_evaluate.size(); i++) + m_tracker.set_value(to_evaluate[i], * m_old_values[i]); + + m_old_values.reset(); + + return 0; + } + + // what_if version needed in the context of 2nd intensification try, combining local and global score + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); + double local_score = m_tracker.get_score(e); + double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; + + if (new_score >= best_score) { + best_score = new_score; + m_mpz_manager.set(best_value, temp); + return true; + } + + return false; + } + + // find_best_move version needed in the context of 2nd intensification try + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) + { + mpz old_value, temp; + double best_score = 0; + + sort * srt = fd->get_range(); + unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { + mk_flip(srt, old_value, j, temp); + what_if(g, e, fd, temp, best_score, best_value, i); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + + return best_score; + } + + // second try to use intensification ... also not very effective + bool handle_plateau(goal_ref const & g, double old_score) + { + unsigned sz = g->size(); +#if _BFS_ + unsigned new_const = m_stats.m_moves % sz; +#else + unsigned new_const = m_tracker.get_random_uint(16) % sz; +#endif + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + if (!e) + return 0; + + expr * q = m_tracker.get_unsat_expression(e); + ptr_vector & to_evaluate = m_tracker.get_constants(q); + + new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); + func_decl * fd = to_evaluate[new_const]; + + mpz new_value; + //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); + unsigned new_bit = 0; + double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; + + for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) + { + new_score = find_best_move_local(g, q, fd, new_value, i); + + m_stats.m_moves++; + m_stats.m_flips++; + + global_score = incremental_score(g, fd, new_value); + local_score = m_tracker.get_score(q); + + SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); + + if (m_mpz_manager.is_one(m_tracker.get_value(q))) + return 1; + } + + return 0; + } + + // main search loop + lbool search(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + unsigned plateau_cnt = 0; + + score = rescore(g); + unsigned sz = g->size(); +#if _PERC_STICKY_ + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + +#if _RESTARTS_ == 1 + while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 2 + while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#elif _RESTARTS_ == 3 + while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#endif + checkpoint(); + m_stats.m_moves++; + +#if _UCT_FORGET_ + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + +#if _REAL_RS_ || _REAL_PBFS_ + //m_tracker.debug_real(g, m_stats.m_moves); +#endif + +#if _FOCUS_ +#if _PERC_STICKY_ + if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) + e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#else + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); +#endif + if (!e) + { + res = l_true; + goto bailout; + } + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else + ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(to_evaluate); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(to_evaluate); +#endif +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } + continue; +#endif + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + old_score = score; + new_const = (unsigned)-1; + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + + if (new_const == static_cast(-1)) { + score = old_score; + plateau_cnt++; +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); + //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + //to_evaluate = m_tracker.get_unsat_constants_walksat(e); +#else +#if _PERC_PLATEAU_MOVES_ + if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) + mk_random_move(to_evaluate); + else +#endif +#if _REPICK_ + m_evaluator.randomize_local(g, m_stats.m_moves); +#else + m_evaluator.randomize_local(to_evaluate); +#endif +#endif + +#if _CACHE_TOP_SCORE_ + score = m_tracker.get_top_sum() / g->size(); +#else + score = top_score(g); +#endif + } else { + func_decl * fd = to_evaluate[new_const]; +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + // main search loop + lbool search_old(goal_ref const & g) { + lbool res = l_undef; + double score = 0.0, old_score = 0.0; + unsigned new_const = (unsigned)-1, new_bit = 0; + mpz new_value; + move_type move; + + score = rescore(g); + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + + unsigned plateau_cnt = 0; + + // Andreas: Why do we only allow so few plateaus? +#if _RESTARTS_ + while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { + //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { +#else + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { +#endif + do { + checkpoint(); + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif + +#if _TYPE_RSTEP_ + if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + { +#if _TYPE_RSTEP_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _TYPE_RSTEP_ == 2 + mk_random_move(g); +#endif + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } +#endif + old_score = score; + new_const = (unsigned)-1; + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + if (!to_evaluate.size()) + { + res = l_true; + goto bailout; + } + TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; + for (unsigned i = 0 ; i < to_evaluate.size(); i++) + tout << to_evaluate[i]->get_name() << std::endl; ); + +#if _VNS_ + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); +#else + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); +#endif + if (new_const == static_cast(-1)) { + TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + }); + + TRACE("sls_max", m_tracker.show_model(tout); + tout << "Scores: " << std::endl; + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl; ); + // Andreas: If new_const == -1, shouldn't score = old_score anyway? + score = old_score; + } + else { + // Andreas: Why does randomizing not count as a move? (Now it does.) + m_stats.m_moves++; + func_decl * fd = to_evaluate[new_const]; + + TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; + switch (move) { + case MV_FLIP: + tout << "Flip"; + if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; + break; + case MV_INC: + tout << "+1"; + break; + case MV_DEC: + tout << "-1"; + break; + case MV_INV: + tout << "NEG"; + break; + }; + tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); + + switch (move) { + case MV_FLIP: m_stats.m_flips++; break; + case MV_INC: m_stats.m_incs++; break; + case MV_DEC: m_stats.m_decs++; break; + case MV_INV: m_stats.m_invs++; break; + case MV_UMIN: m_stats.m_umins++; break; + case MV_MUL2: m_stats.m_mul2s++; break; + case MV_MUL3: m_stats.m_mul3s++; break; + case MV_DIV2: m_stats.m_div2s++; break; + } + +#if _REAL_RS_ || _REAL_PBFS_ + score = serious_score(g, fd, new_value); +#else + score = incremental_score(g, fd, new_value); +#endif + + TRACE("sls", tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl; ); + } + + if (score >= 0.99999) { +// if (score >= 1.0) { + // score could theoretically be imprecise. + // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + /* + if (m_stats.m_moves % 100 == 0) + { + verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; + verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + }*/ + } + while (score > old_score && res == l_undef); + + // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. + if (score != old_score) { + report_tactic_progress("This should not happen I guess.", plateau_cnt); + plateau_cnt = 0; + } else { + m_stats.m_moves++; + plateau_cnt++; + //report_tactic_progress("Plateau.", plateau_cnt); + // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. + //if (plateau_cnt < m_plateau_limit) { + TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); +#if _INTENSIFICATION_ + handle_plateau(g, score); + //handle_plateau(g); +#else + m_evaluator.randomize_local(g, m_stats.m_moves); +#endif + //mk_random_move(g); + score = top_score(g); + + if (score >= 1.0) { + bool all_true = true; + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + all_true=false; + if (all_true) { + res = l_true; // sat + goto bailout; + } else + TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); + } + } + } + + bailout: + m_mpz_manager.del(new_value); + + return res; + } + + void operator()(goal_ref const & g, model_converter_ref & mc) { + if (g->inconsistent()) { + mc = 0; + return; + } + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; + verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; + verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl; + verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; + verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; + verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; + verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; + verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; + verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl; + verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; + verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; + verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; + verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; + verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; + verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; + verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; + verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; + verbose_stream() << "_UCT_ " << _UCT_ << std::endl; + verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; + verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; + verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; + verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; + verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; + verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; + verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; + verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; + verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; + verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; + verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; + verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; + verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; + verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; + verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; + verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } + while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout); ); + } + g->reset(); + } + else + mc = 0; + } + }; + ast_manager & m; params_ref m_params; - sls_engine * m_engine; + imp * m_imp; + stats m_stats; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_engine = alloc(sls_engine, m, p); + m_imp = alloc(imp, m, p, m_stats); } virtual tactic * translate(ast_manager & m) { @@ -48,16 +1395,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_engine); + dealloc(m_imp); } virtual void updt_params(params_ref const & p) { m_params = p; - m_engine->updt_params(p); + m_imp->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); + imp::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -65,13 +1412,14 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); + SASSERT(g->is_well_sorted()); + m_imp->m_produce_models = g->models_enabled(); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_engine->operator()(g, mc); + m_imp->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -80,41 +1428,40 @@ public: } virtual void cleanup() { - sls_engine * d = m_engine; + imp * d = m_imp; #pragma omp critical (tactic_cancel) { - d = m_engine; + d = m_imp; } dealloc(d); - d = alloc(sls_engine, m, m_params); + d = alloc(imp, m, m_params, m_stats); #pragma omp critical (tactic_cancel) { - m_engine = d; + m_imp = d; } } virtual void collect_statistics(statistics & st) const { - sls_engine::stats const & stats = m_engine->get_stats(); - double seconds = stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", stats.m_restarts); - st.update("sls full evals", stats.m_full_evals); - st.update("sls incr evals", stats.m_incr_evals); - st.update("sls incr evals/sec", stats.m_incr_evals / seconds); - st.update("sls FLIP moves", stats.m_flips); - st.update("sls INC moves", stats.m_incs); - st.update("sls DEC moves", stats.m_decs); - st.update("sls INV moves", stats.m_invs); - st.update("sls moves", stats.m_moves); - st.update("sls moves/sec", stats.m_moves / seconds); + double seconds = m_stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", m_stats.m_restarts); + st.update("sls full evals", m_stats.m_full_evals); + st.update("sls incr evals", m_stats.m_incr_evals); + st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); + st.update("sls FLIP moves", m_stats.m_flips); + st.update("sls INC moves", m_stats.m_incs); + st.update("sls DEC moves", m_stats.m_decs); + st.update("sls INV moves", m_stats.m_invs); + st.update("sls moves", m_stats.m_moves); + st.update("sls moves/sec", m_stats.m_moves / seconds); } virtual void reset_statistics() { - m_engine->reset_statistics(); + m_stats.reset(); } virtual void set_cancel(bool f) { - if (m_engine) - m_engine->set_cancel(f); + if (m_imp) + m_imp->set_cancel(f); } }; @@ -163,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), // Andreas: This one at least eliminates top level duplicates ... - mk_simplify_tactic(m), + //mk_simplify_tactic(m), // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 3675265ee..1c33d42a7 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -276,6 +276,20 @@ public: } #endif + void uct_forget(goal_ref const & g) { + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < g->size(); i++) + { + e = g->form(i); + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } + } + void initialize(app * n) { // Build score table if (!m_scores.contains(n)) { @@ -1195,6 +1209,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1202,7 +1218,7 @@ public: if (pos == static_cast(-1)) return m_temp_constants; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 @@ -1343,6 +1359,8 @@ public: double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; +#elif _UCT_ == 3 + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } @@ -1350,7 +1368,7 @@ public: if (pos == static_cast(-1)) return 0; -#if _UCT_ == 1 +#if _UCT_ == 1 || _UCT_ == 3 m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 From 1f326d9e72157ec15d617ac804533809f8803573 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 26 Mar 2014 17:26:06 +0000 Subject: [PATCH 212/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 219 +++++++++++++++++++-------------- src/tactic/sls/sls_engine.h | 58 ++++----- src/tactic/sls/sls_evaluator.h | 4 +- src/tactic/sls/sls_tracker.h | 84 ++++++------- 4 files changed, 195 insertions(+), 170 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 92471aad8..9fa2cc263 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -74,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(goal_ref const & g, model & mdl) { +bool sls_engine::full_eval(model & mdl) { bool res = true; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(g->form(i), o, true)) + if (!mdl.eval(m_assertions[i], o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) { return res; } -double sls_engine::top_score(goal_ref const & g) { +double sls_engine::top_score() { #if 0 double min = m_tracker.get_score(g->form(0)); unsigned sz = g->size(); @@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) { return min; #else double top_sum = 0.0; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = m_assertions[i]; top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); + tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); #if _CACHE_TOP_SCORE_ @@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) { #endif } -double sls_engine::rescore(goal_ref const & g) { +double sls_engine::rescore() { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(g); + return top_score(); } -double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif } -double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { #if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); #else - return top_score(g); + return top_score(); #endif else return 0.0; @@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); + double r = incremental_score_prune(fd, temp); #else - double r = incremental_score(g, fd, temp); + double r = incremental_score(fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd } // same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if_local( + expr * e, + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) +{ m_evaluator.update(fd, temp); double r = m_tracker.get_score(e); if (r >= best_score) { @@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); +void sls_engine::mk_random_move() { + mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves)); } // will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move_vns( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; unsigned bv_sz, max_bv_sz = 0; double new_score = score; @@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; // try to flip lsb mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = 0; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } @@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector { mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); SASSERT(check == score); } m_mpz_manager.del(old_value); @@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector } // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ mpz temp2; @@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } @@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; #if _USE_UNARY_MINUS_ @@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector & to_eva } // first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau(goal_ref const & g) +bool sls_engine::handle_plateau() { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned pos = m_stats.m_moves % sz; #else unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); + expr * e = m_tracker.get_unsat_assertion(sz, pos); if (!e) return 0; @@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g) } // what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); +bool sls_engine::what_if( + expr * e, + func_decl * fd, + const mpz & temp, + double & best_score, + mpz & best_value, + unsigned i) +{ + double global_score = incremental_score(fd, temp); double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; @@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz } // find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) +double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i) { mpz old_value, temp; double best_score = 0; @@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); + what_if(e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); @@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl } // second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(goal_ref const & g, double old_score) +bool sls_engine::handle_plateau(double old_score) { - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); #if _BFS_ unsigned new_const = m_stats.m_moves % sz; #else unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); + expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const); if (!e) return 0; @@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) { - new_score = find_best_move_local(g, q, fd, new_value, i); + new_score = find_best_move_local(q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(g, fd, new_value); + global_score = incremental_score(fd, new_value); local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score) } // main search loop -lbool sls_engine::search(goal_ref const & g) { +lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) { move_type move; unsigned plateau_cnt = 0; - score = rescore(g); - unsigned sz = g->size(); + score = rescore(); + unsigned sz = m_assertions.size(); #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) { if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); + expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves); #endif if (!e) { @@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { @@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) { else #endif #if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #else m_evaluator.randomize_local(to_evaluate); #endif #endif #if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); + score = m_tracker.get_top_sum() / m_assertions.size(); #else score = top_score(g); #endif @@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) { #if _REAL_RS_ || _REAL_PBFS_ score = serious_score(g, fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif } } @@ -840,18 +869,18 @@ bailout: } // main search loop -lbool sls_engine::search_old(goal_ref const & g) { +lbool sls_engine::search_old() { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - score = rescore(g); + score = rescore(); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); unsigned plateau_cnt = 0; @@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) { old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves); if (!to_evaluate.size()) { res = l_true; @@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) { tout << to_evaluate[i]->get_name() << std::endl;); #if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; + for (unsigned i = 0; i < m_assertions.size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl; }); TRACE("sls_max", m_tracker.show_model(tout); tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl;); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " << + m_tracker.get_score(m_assertions[i]) << std::endl;); // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } @@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) { } #if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); + score = serious_score(fd, new_value); #else - score = incremental_score(g, fd, new_value); + score = incremental_score(fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + for (unsigned i = 0; i < m_assertions.size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); tout << " TOP: " << score << std::endl;); } @@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) { // score could theoretically be imprecise. // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); #if _INTENSIFICATION_ handle_plateau(g, score); - //handle_plateau(g); + //handle_plateau(); #else - m_evaluator.randomize_local(g, m_stats.m_moves); + m_evaluator.randomize_local(m_assertions, m_stats.m_moves); #endif - //mk_random_move(g); - score = top_score(g); + //mk_random_move(); + score = top_score(); if (score >= 1.0) { bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + for (unsigned i = 0; i < m_assertions.size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) all_true = false; if (all_true) { res = l_true; // sat @@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + + verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; @@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { #if _WEIGHT_TOGGLE_ m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); #endif - m_tracker.initialize(g); + m_tracker.initialize(m_assertions); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; @@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { checkpoint(); report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); + res = search(); if (res == l_undef) { #if _RESTART_INIT_ - m_tracker.randomize(g); + m_tracker.randomize(); #else - m_tracker.reset(g); + m_tracker.reset(m_assertions); #endif } } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 878354c6d..8458817b6 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -71,6 +71,7 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; + ptr_vector m_assertions; unsigned m_restart_limit; unsigned m_max_restarts; @@ -92,11 +93,12 @@ public: void updt_params(params_ref const & _p); + void assert_expr(expr * e) { m_assertions.push_back(e); } + stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(goal_ref const & g, model & mdl); - + bool full_eval(model & mdl); void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); @@ -104,54 +106,44 @@ public: void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - - - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); - - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); - - - lbool search(goal_ref const & g); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); - lbool search_old(goal_ref const & g); + lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - + bool what_if(expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(goal_ref const & g); - double rescore(goal_ref const & g); - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); #if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score_prune(func_decl * fd, const mpz & new_value); #endif - - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i); + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_vns(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(goal_ref const & g); + void mk_random_move(); - bool handle_plateau(goal_ref const & g); - bool handle_plateau(goal_ref const & g, double old_score); + bool handle_plateau(void); + bool handle_plateau(double old_score); inline unsigned check_restart(unsigned curr_value); }; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 9daf93c32..7638ba5f4 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -922,8 +922,8 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(g, flip)); + void randomize_local(ptr_vector const & as, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(as, flip)); } }; diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 1c33d42a7..c49257692 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,7 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"goal.h" +#include"bv_decl_plugin.h" #include"model.h" #include"sls_compilation_settings.h" @@ -365,12 +365,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -418,12 +418,12 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(goal_ref const & g) { + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); else @@ -438,7 +438,7 @@ public: visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); @@ -450,7 +450,7 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); @@ -465,11 +465,11 @@ public: #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(as[i]); #endif #if _UCT_ - m_touched = _UCT_INIT_ ? g->size() : 1; + m_touched = _UCT_INIT_ ? as.size() : 1; #endif } @@ -606,7 +606,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(goal_ref const & g) { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -620,13 +620,13 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } - void reset(goal_ref const & g) { + void reset(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -636,9 +636,9 @@ public: } #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; + m_touched = _UCT_INIT_ ? as.size() : 1; + for (unsigned i = 0; i < as.size(); i++) + m_scores.find(as[i]).touched = 1; #endif } @@ -1029,13 +1029,13 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { if (sz == 1) return get_constants(); m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1049,22 +1049,22 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * get_unsat_assertion(ptr_vector const & as, unsigned sz, unsigned int pos) { for (unsigned i = pos; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.neq(get_value(q), m_one)) return q; } return 0; } - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_walksat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; @@ -1141,19 +1141,19 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); + ptr_vector & get_unsat_constants_crsat(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(as, sz, pos); if (!q) return m_temp_constants; return go_deeper(q); } - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + ptr_vector & get_unsat_constants(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + if (m_mpz_manager.eq(get_value(as[0]), m_one)) return m_temp_constants; else return get_constants(); @@ -1201,7 +1201,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1219,12 +1219,12 @@ public: return m_temp_constants; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; + m_scores.find(as[pos]).touched = flip; #endif - expr * e = g->form(pos); + expr * e = as[pos]; // expr * e = m_list_false[pos]; #elif _BFS_ == 3 @@ -1303,11 +1303,11 @@ public: } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); + expr * get_unsat_assertion(ptr_vector const & as, unsigned int flip) { + unsigned sz = as.size(); if (sz == 1) - return g->form(0); + return as[0]; m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1351,7 +1351,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1369,13 +1369,13 @@ public: return 0; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; + m_scores.find(as[pos]).touched++; m_touched++; #elif _UCT_ == 2 m_scores.find(g->form(pos)).touched = flip; #endif // return m_list_false[pos]; - return g->form(pos); + return as[pos]; #elif _BFS_ == 3 unsigned int pos = -1; @@ -1429,7 +1429,7 @@ public: unsigned int pos = get_random_uint(16) % sz; return get_unsat_assertion(g, sz, pos); #endif - return g->form(pos); + return as[pos]; #elif _FOCUS_ == 2 #if _BFS_ unsigned int pos = flip % sz; From 1834bb59504733a159ae6f1832eae01d5ec0fc02 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:34:21 +0000 Subject: [PATCH 213/646] disabled old code --- src/tactic/sls/sls_engine.cpp | 4 +++- src/tactic/sls/sls_engine.h | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 9fa2cc263..cc06e4f78 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -868,6 +868,7 @@ bailout: return res; } +#if 0 // Old code. // main search loop lbool sls_engine::search_old() { lbool res = l_undef; @@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() { } } } +#endif bailout: m_mpz_manager.del(new_value); @@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value) return 0; } return 1; -} \ No newline at end of file +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8458817b6..5d4c9a0fc 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -114,7 +114,6 @@ public: protected: void checkpoint(); - lbool search_old(void); double get_restart_armin(unsigned cnt_restarts); bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, @@ -148,4 +147,4 @@ protected: inline unsigned check_restart(unsigned curr_value); }; -#endif \ No newline at end of file +#endif From e9797c392272e90dd7b9ffb43e537098c9f354dd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Mar 2014 13:37:04 +0000 Subject: [PATCH 214/646] bugfix --- src/tactic/sls/sls_engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index cc06e4f78..10aaf6601 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() { } } } -#endif bailout: m_mpz_manager.del(new_value); return res; } +#endif void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { From 71fdb597475d5178ac3a6ec8309cf2cc6b659bce Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:27:06 +0000 Subject: [PATCH 215/646] removed dependency of bvsls on goal_refs Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index c49257692..cf1ad9ea3 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -276,13 +276,13 @@ public: } #endif - void uct_forget(goal_ref const & g) { + void uct_forget(ptr_vector & as) { expr * e; unsigned touched_old, touched_new; - for (unsigned i = 0; i < g->size(); i++) + for (unsigned i = 0; i < as.size(); i++) { - e = g->form(i); + e = as[i]; touched_old = m_scores.find(e).touched; touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); m_scores.find(e).touched = touched_new; From b76ffddf49c0d42472573c41d20c072b503d3e78 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:28:40 +0000 Subject: [PATCH 216/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index cf1ad9ea3..fac080ee7 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include"for_each_expr.h" #include"bv_decl_plugin.h" #include"model.h" From 1b98e6002b7a70ee51f00227ecdecb663a2fe113 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 12:30:15 +0000 Subject: [PATCH 217/646] compilation fixes Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_tracker.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 5d4c9a0fc..96041d09e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,6 +22,7 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" +#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index fac080ee7..537492213 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -21,6 +21,7 @@ Notes: #define _SLS_TRACKER_H_ #include"for_each_expr.h" +#include"ast_smt2_pp.h" #include"bv_decl_plugin.h" #include"model.h" From ad412d4f08f63e61778f940fef7afdb0f54c7f51 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 14:58:59 +0000 Subject: [PATCH 218/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 21 ++++++++++++--------- src/tactic/sls/sls_engine.h | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 10aaf6601..e7ee2abbd 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1069,6 +1069,16 @@ bailout: } #endif +void sls_engine::init_tracker() { +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(m_assertions); +} + void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { mc = 0; @@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); - + assert_expr(g->form(i)); verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; @@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(m_assertions); + init_tracker(); lbool res = l_undef; m_restart_limit = _RESTART_LIMIT_; diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 96041d09e..c56d6ec40 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -109,6 +109,8 @@ public: void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void init_tracker(void); + lbool search(void); void operator()(goal_ref const & g, model_converter_ref & mc); From e382742a29f06e818bf361e2829abe18d118d710 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:26:52 +0000 Subject: [PATCH 219/646] bvsls refactoring Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++---------------- src/tactic/sls/sls_engine.h | 1 + 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index e7ee2abbd..2b359608a 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + lbool res = operator()(); + + if (res == l_true) { + report_tactic_progress("Number of flips:", m_stats.m_moves); + for (unsigned i = 0; i < g->size(); i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + { + verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; + NOT_IMPLEMENTED_YET(); + } + + if (m_produce_models) { + model_ref mdl = m_tracker.get_model(); + mc = model2model_converter(mdl.get()); + TRACE("sls_model", mc->display(tout);); + } + g->reset(); + } + else + mc = 0; +} + +lbool sls_engine::operator()() { init_tracker(); lbool res = l_undef; @@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout);); - } - g->reset(); - } - else - mc = 0; } unsigned sls_engine::check_restart(unsigned curr_value) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index c56d6ec40..c6e3af155 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -113,6 +113,7 @@ public: lbool search(void); + lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: From a48bb976e9ae28e0eb60600ef8d9e43cb1c906e7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 28 Mar 2014 15:28:02 +0000 Subject: [PATCH 220/646] bvsls bugfix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 2b359608a..dc4451bb5 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() { } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; } unsigned sls_engine::check_restart(unsigned curr_value) From c56e55b2305d0c26023a588b5c6d5dba1e79da87 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Sun, 20 Apr 2014 16:38:49 +0100 Subject: [PATCH 221/646] Current version before integration ... --- src/tactic/sls/sls_compilation_settings.h | 40 +- src/tactic/sls/sls_engine.cpp | 586 +++++++++++++++------- src/tactic/sls/sls_engine.h | 73 +-- src/tactic/sls/sls_evaluator.h | 152 +++++- src/tactic/sls/sls_tactic.cpp | 4 +- src/tactic/sls/sls_tracker.h | 472 ++++++++++++++--- 6 files changed, 1040 insertions(+), 287 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 8e52596e0..d2b899dd8 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -36,17 +36,21 @@ Notes: // do we use dirty unit propagation to get rid of nested top level assertions? #define _DIRTY_UP_ 0 +// shall we use additive weighting scheme? +#define _PAWS_ 5 +#define _PAWS_INIT_ 40 + // do we use restarts? // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 +#define _RESTARTS_ 1 // limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 +#define _RESTART_LIMIT_ 100 // 0 = initialize with all zero, 1 initialize with random value #define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid +// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat #define _RESTART_SCHEME_ 1 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 3.0 +#define _RESTART_CONST_ARMIN_ 2.0 // timelimit #define _TIMELIMIT_ 3600 @@ -61,6 +65,21 @@ Notes: // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained #define _VNS_ 0 +// shall we check 2-bit flips in plateaus using Monte Carlo? +#define _VNS_MC_ 0 + +// how many 2-bit flips shall we try per bit? +#define _VNS_MC_TRIES_ 1 + +// shall we check another assertion if no improving step was found in the first one? +#define _VNS_REPICK_ 0 + +// what is the probability of doing so (percentage)? +#define _VNS_PERC_ 100 + +// do a decreasing move with percentage ... +#define _INSIST_PERC_ 0 + // do we reduce the score of unsatisfied literals? // 0 = no // 1 = yes, by multiplying it with some factor @@ -70,7 +89,7 @@ Notes: #define _WEIGHT_DIST_ 1 // the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.25 +#define _WEIGHT_DIST_FACTOR_ 0.5 // shall we toggle the weight after each restart? #define _WEIGHT_TOGGLE_ 0 @@ -82,14 +101,15 @@ Notes: // what is the percentage of random moves in plateaus (instead of full randomization)? #define _PERC_PLATEAU_MOVES_ 0 -// shall we repick clause when randomizing in a plateau or use the current one? +// shall we repick assertion when randomizing in a plateau or use the current one? +// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one #define _REPICK_ 1 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_ #define _UCT_ 1 // how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 10.0 +#define _UCT_CONSTANT_ 20.0 // is uct clause selection probabilistic similar to variable selection in sparrow? // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score @@ -103,7 +123,11 @@ Notes: // how shall we initialize the _UCT_ total touched counter? // 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 1 +#define _UCT_INIT_ 0 + +// do we gradually reduce the touched values of _UCT_? +#define _UCT_FORGET_ 0 +#define _UCT_FORGET_FACTOR_ 0.9 // shall we use addition/subtraction? #define _USE_ADDSUB_ 1 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index dc4451bb5..342e649af 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -74,15 +74,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(model & mdl) { +bool sls_engine::full_eval(goal_ref const & g, model & mdl) { bool res = true; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(m_assertions[i], o, true)) + if (!mdl.eval(g->form(i), o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,7 +93,7 @@ bool sls_engine::full_eval(model & mdl) { return res; } -double sls_engine::top_score() { +double sls_engine::top_score(goal_ref const & g) { #if 0 double min = m_tracker.get_score(g->form(0)); unsigned sz = g->size(); @@ -108,15 +108,15 @@ double sls_engine::top_score() { return min; #else double top_sum = 0.0; - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = m_assertions[i]; + expr * e = g->form(i); top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(m_assertions[i]); + tout << " " << m_tracker.get_score(g->form(i)); tout << " AVG: " << top_sum / (double)sz << std::endl;); #if _CACHE_TOP_SCORE_ @@ -127,40 +127,40 @@ double sls_engine::top_score() { #endif } -double sls_engine::rescore() { +double sls_engine::rescore(goal_ref const & g) { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(); + return top_score(g); } -double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif } -double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif } -double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { #if _EARLY_PRUNE_ m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) #if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / m_assertions.size()); + return (m_tracker.get_top_sum() / g->size()); #else - return top_score(); + return top_score(g); #endif else return 0.0; @@ -169,14 +169,17 @@ double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value #endif } +double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) { + m_stats.m_incr_evals++; + if (m_evaluator.update_prune_new(fd, new_value)) + return (m_tracker.get_top_sum() / g->size()); + else + return 0.0; +} + // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if( - func_decl * fd, - const unsigned & fd_inx, - const mpz & temp, - double & best_score, - unsigned & best_const, - mpz & best_value) { +bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -184,9 +187,9 @@ bool sls_engine::what_if( #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(fd, temp); + double r = incremental_score_prune(g, fd, temp); #else - double r = incremental_score(fd, temp); + double r = incremental_score(g, fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -195,8 +198,33 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif - // if (r >= best_score) { + //if (r >= best_score) { if (r > best_score) { + m_tracker.reset_equal_scores(); + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + /*else if (r == best_score) { + if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0) + { + best_score = r; + best_const = fd_inx; + m_mpz_manager.set(best_value, temp); + return true; + } + }*/ + + return false; +} + +bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { + + double r = incremental_score_prune_new(g, fd, temp); + + if (r >= best_score) { best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -207,15 +235,8 @@ bool sls_engine::what_if( } // same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local( - expr * e, - func_decl * fd, - const unsigned & fd_inx, - const mpz & temp, - double & best_score, - unsigned & best_const, - mpz & best_value) -{ +bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value) { m_evaluator.update(fd, temp); double r = m_tracker.get_score(e); if (r >= best_score) { @@ -356,19 +377,13 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move() { - mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves)); +void sls_engine::mk_random_move(goal_ref const & g) { + mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); } // will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns( - ptr_vector & to_evaluate, - double score, - unsigned & best_const, - mpz & best_value, - unsigned & new_bit, - move_type & move) -{ +double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; unsigned bv_sz, max_bv_sz = 0; double new_score = score; @@ -384,31 +399,31 @@ double sls_engine::find_best_move_vns( if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; // try to flip lsb mk_flip(srt, old_value, 0, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = 0; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); SASSERT(check == score); } @@ -430,13 +445,13 @@ double sls_engine::find_best_move_vns( { mk_flip(srt, old_value, j, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); SASSERT(check == score); } m_mpz_manager.del(old_value); @@ -444,23 +459,99 @@ double sls_engine::find_best_move_vns( return new_score; } +double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { + mpz old_value, temp; + unsigned bv_sz, max_bv_sz = 0; + double new_score = score; + + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { + // try inverting + mk_inv(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INV; + + if (!m_mpz_manager.is_even(old_value)) { + // for odd values, try +1 + mk_inc(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_INC; + } + else { + // for even values, try -1 + mk_dec(bv_sz, old_value, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + move = MV_DEC; + } + + // try to flip lsb + mk_flip(srt, old_value, 0, temp); + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = 0; + move = MV_FLIP; + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + + for (unsigned j = 1; j < max_bv_sz; j++) + { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + // What would happen if we flipped bit #j ? + if (j < bv_sz) + { + mk_flip(srt, old_value, j, temp); + + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + new_bit = j; + move = MV_FLIP; + } + } + // reset to what it was before + double check = incremental_score(g, fd, old_value); + SASSERT(check == score); + } + } + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + return new_score; +} + // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move( - ptr_vector & to_evaluate, - double score, - unsigned & best_const, - mpz & best_value, - unsigned & new_bit, - move_type & move) -{ +double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { mpz old_value, temp; #if _USE_MUL3_ || _USE_UNARY_MINUS_ mpz temp2; #endif unsigned bv_sz; +#if _INSIST_PERC_ + double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score; +#else double new_score = score; +#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + m_tracker.reset_equal_scores(); + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { +// for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) { +// for (unsigned i = to_evaluate.size(); i-- > 0; ) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -470,15 +561,28 @@ double sls_engine::find_best_move( #if _SKIP_BITS_ for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { #else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { +// for (unsigned j = bv_sz; j-- > 0; ) { #endif // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) { + //if (m_tracker.get_random_uint(1)) + //if ((move != MV_FLIP) || (new_bit > j)) + //{ + //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) { + // new_bit = j; + // move = MV_FLIP; + //} + //} + //else + //{ + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } + //} } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -486,19 +590,22 @@ double sls_engine::find_best_move( if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - if (what_if(fd, i, temp, new_score, best_const, best_value)) + //if (m_tracker.get_random_uint(1)) + if (what_if(g, fd, i, temp, new_score, best_const, best_value)) move = MV_INV; #if _USE_UNARY_MINUS_ @@ -528,7 +635,7 @@ double sls_engine::find_best_move( } // reset to what it was before - double check = incremental_score(fd, old_value); + double check = incremental_score(g, fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } @@ -538,6 +645,50 @@ double sls_engine::find_best_move( #if _USE_MUL3_ m_mpz_manager.del(temp2); #endif + + if ((new_score == score) && 1)// (m_tracker.get_random_uint(1))) + best_const = -1; + + return new_score; +} + +// finds the move that increased score the most. returns best_const = -1, if no increasing move exists. +double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value) { + mpz old_value, temp, temp2; + unsigned bv_sz; + double new_score = score; + +// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { + for (unsigned i = 0; i < to_evaluate.size(); i++) { + func_decl * fd = to_evaluate[i]; + sort * srt = fd->get_range(); + bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + m_mpz_manager.set(old_value, m_tracker.get_value(fd)); + + if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { +// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { + for (unsigned j = 0; j < bv_sz; j++) { + mk_flip(srt, old_value, j, temp); + for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + { + unsigned k = m_tracker.get_random_uint(16) % bv_sz; + while (k == j) + k = m_tracker.get_random_uint(16) % bv_sz; + mk_flip(srt, temp, k, temp2); + what_if(g, fd, i, temp2, new_score, best_const, best_value); + } + } + } + + // reset to what it was before + double check = incremental_score(g, fd, old_value); + } + + m_mpz_manager.del(old_value); + m_mpz_manager.del(temp); + m_mpz_manager.del(temp2); + return new_score; } @@ -596,15 +747,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector & to_eva } // first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau() +bool sls_engine::handle_plateau(goal_ref const & g) { - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); #if _BFS_ unsigned pos = m_stats.m_moves % sz; #else unsigned pos = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(sz, pos); + expr * e = m_tracker.get_unsat_assertion(g, sz, pos); if (!e) return 0; @@ -658,15 +809,10 @@ bool sls_engine::handle_plateau() } // what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if( - expr * e, - func_decl * fd, - const mpz & temp, - double & best_score, - mpz & best_value, - unsigned i) -{ - double global_score = incremental_score(fd, temp); +bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i) { + + double global_score = incremental_score(g, fd, temp); double local_score = m_tracker.get_score(e); double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; @@ -680,7 +826,7 @@ bool sls_engine::what_if( } // find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i) +double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) { mpz old_value, temp; double best_score = 0; @@ -691,7 +837,7 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { mk_flip(srt, old_value, j, temp); - what_if(e, fd, temp, best_score, best_value, i); + what_if(g, e, fd, temp, best_score, best_value, i); } m_mpz_manager.del(old_value); @@ -701,15 +847,15 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val } // second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(double old_score) +bool sls_engine::handle_plateau(goal_ref const & g, double old_score) { - unsigned sz = m_assertions.size(); + unsigned sz = g->size(); #if _BFS_ unsigned new_const = m_stats.m_moves % sz; #else unsigned new_const = m_tracker.get_random_uint(16) % sz; #endif - expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const); + expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); if (!e) return 0; @@ -726,12 +872,12 @@ bool sls_engine::handle_plateau(double old_score) for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) { - new_score = find_best_move_local(q, fd, new_value, i); + new_score = find_best_move_local(g, q, fd, new_value, i); m_stats.m_moves++; m_stats.m_flips++; - global_score = incremental_score(fd, new_value); + global_score = incremental_score(g, fd, new_value); local_score = m_tracker.get_score(q); SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); @@ -744,7 +890,7 @@ bool sls_engine::handle_plateau(double old_score) } // main search loop -lbool sls_engine::search() { +lbool sls_engine::search(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; @@ -752,8 +898,15 @@ lbool sls_engine::search() { move_type move; unsigned plateau_cnt = 0; - score = rescore(); - unsigned sz = m_assertions.size(); + score = rescore(g); + unsigned sz = g->size(); + + TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; + tout << "Score distribution:"; + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); + tout << " TOP: " << score << std::endl;); + #if _PERC_STICKY_ expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif @@ -767,9 +920,18 @@ lbool sls_engine::search() { #else while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { #endif + //if (m_stats.m_stopwatch.get_current_seconds() > 10.0) + //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);} + checkpoint(); m_stats.m_moves++; +#if _UCT_FORGET_ + //if (m_stats.m_moves % sz == 0) + if (m_stats.m_moves % _UCT_FORGET_ == 0) + m_tracker.uct_forget(g); +#endif + #if _REAL_RS_ || _REAL_PBFS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif @@ -779,13 +941,14 @@ lbool sls_engine::search() { if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #else - expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves); + expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); #endif if (!e) { res = l_true; goto bailout; } + //ptr_vector & to_evaluate = m_tracker.get_unsat_constants_only(e); ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); #else ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); @@ -818,13 +981,69 @@ lbool sls_engine::search() { #endif old_score = score; new_const = (unsigned)-1; + move = MV_FLIP; + new_bit = 0; #if _VNS_ score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); #endif +#if _VNS_MC_ > _VNS_REPICK_ +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#endif + +#if _VNS_MC_ < _VNS_REPICK_ +#if _VNS_REPICK_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } +#endif +#if _VNS_MC_ + if (new_const == static_cast(-1)) + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); +#endif +#endif + +#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_ + if (new_const == static_cast(-1)) { + if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) + score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); + else { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); + } + } + } +#endif + + if (new_const == static_cast(-1)) { score = old_score; plateau_cnt++; @@ -839,25 +1058,52 @@ lbool sls_engine::search() { mk_random_move(to_evaluate); else #endif -#if _REPICK_ - m_evaluator.randomize_local(m_assertions, m_stats.m_moves); +#if _REPICK_ == 1 + m_evaluator.randomize_local(g, m_stats.m_moves); +#elif _REPICK_ == 2 + { + expr * q = m_tracker.get_new_unsat_assertion(g, e); + if (q) + m_evaluator.randomize_local(q); + else + m_evaluator.randomize_local(e); + } #else - m_evaluator.randomize_local(to_evaluate); + m_evaluator.randomize_local_n(g, to_evaluate); + //m_evaluator.randomize_local(to_evaluate); #endif #endif #if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / m_assertions.size(); + score = m_tracker.get_top_sum() / g->size(); #else score = top_score(g); #endif + +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * q = g->form(i); + if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } + } +#endif + } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ score = serious_score(g, fd, new_value); #else - score = incremental_score(fd, new_value); + score = incremental_score(g, fd, new_value); #endif } } @@ -868,20 +1114,19 @@ bailout: return res; } -#if 0 // Old code. // main search loop -lbool sls_engine::search_old() { +lbool sls_engine::search_old(goal_ref const & g) { lbool res = l_undef; double score = 0.0, old_score = 0.0; unsigned new_const = (unsigned)-1, new_bit = 0; mpz new_value; move_type move; - score = rescore(); + score = rescore(g); TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; tout << "Score distribution:"; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); tout << " TOP: " << score << std::endl;); unsigned plateau_cnt = 0; @@ -927,7 +1172,7 @@ lbool sls_engine::search_old() { old_score = score; new_const = (unsigned)-1; - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves); + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); if (!to_evaluate.size()) { res = l_true; @@ -938,22 +1183,22 @@ lbool sls_engine::search_old() { tout << to_evaluate[i]->get_name() << std::endl;); #if _VNS_ - score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); #else - score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); #endif if (new_const == static_cast(-1)) { TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < m_assertions.size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) - tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl; + for (unsigned i = 0; i < g->size(); i++) { + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) + tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; }); TRACE("sls_max", m_tracker.show_model(tout); tout << "Scores: " << std::endl; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " << - m_tracker.get_score(m_assertions[i]) << std::endl;); + for (unsigned i = 0; i < g->size(); i++) + tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << + m_tracker.get_score(g->form(i)) << std::endl;); // Andreas: If new_const == -1, shouldn't score = old_score anyway? score = old_score; } @@ -991,15 +1236,15 @@ lbool sls_engine::search_old() { case MV_DIV2: m_stats.m_div2s++; break; } -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(fd, new_value); +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ + score = serious_score(g, fd, new_value); #else - score = incremental_score(fd, new_value); + score = incremental_score(g, fd, new_value); #endif TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < m_assertions.size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]); + for (unsigned i = 0; i < g->size(); i++) + tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); tout << " TOP: " << score << std::endl;); } @@ -1008,8 +1253,8 @@ lbool sls_engine::search_old() { // score could theoretically be imprecise. // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! bool all_true = true; - for (unsigned i = 0; i < m_assertions.size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) all_true = false; if (all_true) { res = l_true; // sat @@ -1040,17 +1285,17 @@ lbool sls_engine::search_old() { TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); #if _INTENSIFICATION_ handle_plateau(g, score); - //handle_plateau(); + //handle_plateau(g); #else - m_evaluator.randomize_local(m_assertions, m_stats.m_moves); + m_evaluator.randomize_local(g, m_stats.m_moves); #endif - //mk_random_move(); - score = top_score(); + //mk_random_move(g); + score = top_score(g); if (score >= 1.0) { bool all_true = true; - for (unsigned i = 0; i < m_assertions.size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i]))) + for (unsigned i = 0; i < g->size() && all_true; i++) + if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) all_true = false; if (all_true) { res = l_true; // sat @@ -1067,17 +1312,6 @@ bailout: return res; } -#endif - -void sls_engine::init_tracker() { -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(m_assertions); -} void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { if (g->inconsistent()) { @@ -1087,9 +1321,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); - for (unsigned i = 0; i < g->size(); i++) - assert_expr(g->form(i)); - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; @@ -1100,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; + verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; + verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; verbose_stream() << "_VNS_ " << _VNS_ << std::endl; + verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; + verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; + verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; + verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl; + verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl; verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; @@ -1111,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; + verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; + verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; @@ -1125,9 +1365,36 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; + verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - lbool res = operator()(); +#if _WEIGHT_DIST_ == 4 + m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); +#endif +#if _WEIGHT_TOGGLE_ + m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); +#endif + m_tracker.initialize(g); + lbool res = l_undef; + + m_restart_limit = _RESTART_LIMIT_; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(g); + + if (res == l_undef) + { +#if _RESTART_INIT_ + m_tracker.randomize(g); +#else + m_tracker.reset(g); +#endif + } + } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); @@ -1149,38 +1416,13 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -lbool sls_engine::operator()() { - init_tracker(); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(); -#else - m_tracker.reset(m_assertions); -#endif - } - } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - return res; -} - unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_limit) { -#if _RESTART_SCHEME_ == 4 +#if _RESTART_SCHEME_ == 5 + m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); +#elif _RESTART_SCHEME_ == 4 m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; @@ -1188,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value) m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) + //if (m_stats.m_restarts % 3 == 2) m_restart_limit += _RESTART_LIMIT_; else m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; + //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_; #else m_restart_limit += _RESTART_LIMIT_; #endif @@ -1201,4 +1445,4 @@ unsigned sls_engine::check_restart(unsigned curr_value) return 0; } return 1; -} +} \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index c6e3af155..902c6b7a0 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,7 +22,6 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" -#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" @@ -72,7 +71,6 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; - ptr_vector m_assertions; unsigned m_restart_limit; unsigned m_max_restarts; @@ -94,12 +92,11 @@ public: void updt_params(params_ref const & _p); - void assert_expr(expr * e) { m_assertions.push_back(e); } - stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(model & mdl); + bool full_eval(goal_ref const & g, model & mdl); + void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); @@ -107,48 +104,66 @@ public: void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - void init_tracker(void); + double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - lbool search(void); + double find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + double find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); + + double find_best_move_local(expr * e, ptr_vector & to_evaluate, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + + + bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, + double & best_score, mpz & best_value, unsigned i); + + double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); + + + lbool search(goal_ref const & g); - lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); + lbool search_old(goal_ref const & g); double get_restart_armin(unsigned cnt_restarts); - bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - bool what_if(expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); + + bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + double & best_score, unsigned & best_const, mpz & best_value); + double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value); + bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - double top_score(); - double rescore(); - double serious_score(func_decl * fd, const mpz & new_value); - double incremental_score(func_decl * fd, const mpz & new_value); + double top_score(goal_ref const & g); + double rescore(goal_ref const & g); + double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); + double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); #if _EARLY_PRUNE_ - double incremental_score_prune(func_decl * fd, const mpz & new_value); + double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); #endif - double find_best_move(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i); - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double find_best_move_vns(ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(); - bool handle_plateau(void); - bool handle_plateau(double old_score); + double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + + void mk_random_move(ptr_vector & unsat_constants); + void mk_random_move(goal_ref const & g); + + bool handle_plateau(goal_ref const & g); + bool handle_plateau(goal_ref const & g, double old_score); inline unsigned check_restart(unsigned curr_value); }; -#endif +#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 7638ba5f4..78f2cb79a 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -575,7 +575,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -584,12 +584,13 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -634,7 +635,7 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); @@ -643,12 +644,12 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); #endif -#endif +#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -683,7 +684,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ run_serious_update(max_depth); #else run_update(max_depth); @@ -729,14 +730,16 @@ public: #if _CACHE_TOP_SCORE_ //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); #endif prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) + //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) pot_benefits = 1; if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) + //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { @@ -771,7 +774,7 @@ public: new_score = m_tracker.score(cur); //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur)); + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); #else m_tracker.set_score(cur, m_tracker.score(cur)); @@ -858,6 +861,104 @@ public: } #endif + unsigned run_update_bool_prune_new(unsigned cur_depth) { + expr_fast_mark1 visited; + + double prune_score, new_score; + unsigned pot_benefits = 0; + SASSERT(cur_depth < m_traversal_stack_bool.size()); + + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + + for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + prune_score = m_tracker.get_score_prune(cur); + m_tracker.set_score(cur, new_score); + + if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) + pot_benefits = 1; + if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) + pot_benefits = 1; + + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + else + { + } + } + + cur_depth_exprs.reset(); + cur_depth--; + + while (cur_depth != static_cast(-1)) { + ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; + if (pot_benefits) + { + unsigned cur_size = cur_depth_exprs.size(); + for (unsigned i = 0; i < cur_size; i++) { + expr * cur = cur_depth_exprs[i]; + + new_score = m_tracker.score(cur); + //if (!m_tracker.has_uplinks(cur)) + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); + if (m_tracker.has_uplinks(cur)) { + ptr_vector & ups = m_tracker.get_uplinks(cur); + for (unsigned j = 0; j < ups.size(); j++) { + expr * next = ups[j]; + unsigned next_d = m_tracker.get_distance(next); + SASSERT(next_d < cur_depth); + if (!visited.is_marked(next)) { + m_traversal_stack_bool[next_d].push_back(next); + visited.mark(next); + } + } + } + } + } + cur_depth_exprs.reset(); + cur_depth--; + } + + return pot_benefits; + } + + unsigned update_prune_new(func_decl * fd, const mpz & new_value) { + m_tracker.set_value(fd, new_value); + expr * ep = m_tracker.get_entry_point(fd); + unsigned cur_depth = m_tracker.get_distance(ep); + + if (m_traversal_stack_bool.size() <= cur_depth) + m_traversal_stack_bool.resize(cur_depth+1); + if (m_traversal_stack.size() <= cur_depth) + m_traversal_stack.resize(cur_depth+1); + + if (m_manager.is_bool(ep)) + m_traversal_stack_bool[cur_depth].push_back(ep); + else + { + m_traversal_stack[cur_depth].push_back(ep); + run_update_prune(cur_depth); + } + return run_update_bool_prune_new(cur_depth); + } + void randomize_local(ptr_vector & unsat_constants) { // Randomize _all_ candidates: @@ -901,7 +1002,7 @@ public: mpz temp = m_tracker.get_random(fd->get_range()); #endif -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ serious_update(fd, temp); #else update(fd, temp); @@ -922,9 +1023,36 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(ptr_vector const & as, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(as, flip)); + void randomize_local(goal_ref const & g, unsigned int flip) { + randomize_local(m_tracker.get_unsat_constants(g, flip)); } + + void randomize_local_n(goal_ref const & g, ptr_vector & unsat_constants) { + unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); + func_decl * fd = unsat_constants[r]; + sort * srt = fd->get_range(); + unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); + mpz max_val = m_tracker.get_random(srt); + update(fd, max_val); + double max_score = m_tracker.get_top_sum() / g->size(); + mpz temp_val; + double temp_score; + for (unsigned i = 1; i < 2; i++) + //for (unsigned i = 1; i < bv_sz; i++) + { + m_mpz_manager.set(temp_val, m_tracker.get_random(srt)); + update(fd, temp_val); + temp_score = m_tracker.get_top_sum() / g->size(); + if (temp_score > max_score) + { + m_mpz_manager.set(max_val, temp_val); + max_score = temp_score; + } + } + update(fd, max_val); + m_mpz_manager.del(temp_val); + m_mpz_manager.del(max_val); + } }; #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index b2b7035e0..0b6b01e7c 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -1509,14 +1509,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { mk_max_bv_sharing_tactic(m), // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... + // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! //mk_simplify_tactic(m), - // Andreas: How does a NNF actually look like? Can it contain ITE operators? mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); +// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 537492213..87c90f1f8 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,9 +20,7 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"for_each_expr.h" -#include"ast_smt2_pp.h" -#include"bv_decl_plugin.h" +#include"goal.h" #include"model.h" #include"sls_compilation_settings.h" @@ -88,12 +86,17 @@ private: obj_map m_where_false; expr** m_list_false; #endif +#if _PAWS_ + obj_map m_weights; + //obj_map m_weights; +#endif #if _CACHE_TOP_SCORE_ double m_top_sum; #endif #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ double m_weight_dist_factor; #endif + unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -113,15 +116,52 @@ public: m_mpz_manager.del(m_two); } + unsigned get_formula_size() { + return m_scores.size(); + } + + double get_avg_bw(goal_ref const & g) { + double sum = 0.0; + unsigned count = 0; + + for (unsigned i = 0; i < g->size(); i++) + { + m_temp_constants.reset(); + ptr_vector const & this_decls = m_constants_occ.find(g->form(i)); + unsigned sz = this_decls.size(); + for (unsigned i = 0; i < sz; i++) { + func_decl * fd = this_decls[i]; + m_temp_constants.push_back(fd); + sort * srt = fd->get_range(); + sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); + count++; + } + } + + return sum / count; + } + #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ inline void set_weight_dist_factor(double val) { m_weight_dist_factor = val; } #endif + void reset_equal_scores() { + m_equal_scores = 1; + } + + unsigned inc_equal_scores() { + return ++m_equal_scores; + } + #if _CACHE_TOP_SCORE_ - inline void adapt_top_sum(double add, double sub) { + inline void adapt_top_sum(expr * e, double add, double sub) { +#if _PAWS_ + m_top_sum += m_weights.find(e) * (add - sub); +#else m_top_sum += add - sub; +#endif } inline void set_top_sum(double new_score) { @@ -278,19 +318,21 @@ public: } #endif - void uct_forget(ptr_vector & as) { +#if _UCT_ + void uct_forget(goal_ref const & g) { expr * e; unsigned touched_old, touched_new; - for (unsigned i = 0; i < as.size(); i++) + for (unsigned i = 0; i < g->size(); i++) { - e = as[i]; + e = g->form(i); touched_old = m_scores.find(e).touched; touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); m_scores.find(e).touched = touched_new; m_touched += touched_new - touched_old; } } +#endif void initialize(app * n) { // Build score table @@ -367,12 +409,12 @@ public: } }; - void calculate_expr_distances(ptr_vector const & as) { + void calculate_expr_distances(goal_ref const & g) { // precondition: m_scores is set up. - unsigned sz = as.size(); + unsigned sz = g->size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(as[i])); + stack.push_back(to_app(g->form(i))); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -420,12 +462,12 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(ptr_vector const & as) { + void initialize(goal_ref const & g) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = as.size(); + unsigned sz = g->size(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); if (!m_top_expr.contains(e)) m_top_expr.insert(e); else @@ -440,7 +482,7 @@ public: visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // Andreas: Maybe not fully correct. #if _FOCUS_ == 2 || _INTENSIFICATION_ initialize_recursive(e); @@ -452,7 +494,7 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(as); + calculate_expr_distances(g); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); @@ -465,16 +507,49 @@ public: //} #endif +#if _PAWS_ + for (unsigned i = 0; i < sz; i++) + { + expr * e = g->form(i); + if (!m_weights.contains(e)) + m_weights.insert(e, _PAWS_INIT_); + } +#endif + #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(as[i]); + setup_occs(g->form(i)); #endif #if _UCT_ - m_touched = _UCT_INIT_ ? as.size() : 1; + m_touched = _UCT_INIT_ ? g->size() : 1; #endif } +#if _PAWS_ + void increase_weight(expr * e) + { + //printf("Increasing %d to", m_weights.find(e)); + m_weights.find(e)++; + //m_weights.find(e) *= 1.1; + //printf(" %d\n", m_weights.find(e)); + } + + void decrease_weight(expr * e) + { + unsigned old_weight = m_weights.find(e); + m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; + //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1; + //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e)); + } + + unsigned get_weight(expr * e) + //double get_weight(expr * e) + { + return m_weights.find(e); + } +#endif + #if _REAL_RS_ || _REAL_PBFS_ void make_assertion(expr * e) { @@ -608,7 +683,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(ptr_vector const & as) { + void randomize(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -622,13 +697,13 @@ public: TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? as.size() : 1; - for (unsigned i = 0; i < as.size(); i++) - m_scores.find(as[i]).touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; #endif } - void reset(ptr_vector const & as) { + void reset(goal_ref const & g) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -638,9 +713,9 @@ public: } #if _UCT_RESET_ - m_touched = _UCT_INIT_ ? as.size() : 1; - for (unsigned i = 0; i < as.size(); i++) - m_scores.find(as[i]).touched = 1; + m_touched = _UCT_INIT_ ? g->size() : 1; + for (unsigned i = 0; i < g->size(); i++) + m_scores.find(g->form(i)).touched = 1; #endif } @@ -765,6 +840,7 @@ public: const mpz & v1 = get_value(arg1); if (negated) { + //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -811,40 +887,209 @@ public: SASSERT(a->get_num_args() == 2); const mpz & x = get_value(a->get_arg(0)); const mpz & y = get_value(a->get_arg(1)); - unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); if (negated) { if (m_mpz_manager.gt(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy);*/ +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= rational(m_powers(bv_sz)); + double dbl = 1.0 - n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + m_mpz_manager.del(diff); +#endif + } + } + else { + if (m_mpz_manager.le(x, y)) + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); - } - } - else { - if (m_mpz_manager.le(x, y)) + res = 1.0 + 0.5 * dbl;*/ res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +/* mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/ +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } - else if (m_bv_util.is_bv_sle(n)) { // x <= y +/* else if (m_bv_util.is_bv_sle(n)) { // x <= y + app * a = to_app(n); + SASSERT(a->get_num_args() == 2); + const mpz & x = get_value(a->get_arg(0)); + const mpz & y = get_value(a->get_arg(1)); + int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); + + mpz x_unsigned; + mpz y_unsigned; + const mpz & p = m_powers(bv_sz); + const mpz & p_half = m_powers(bv_sz-1); + if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } + if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); } + + if (negated) { + if (x_unsigned > y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_gt = 0; + unsigned curr_gt = 0; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 1; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_gt = curr_gt; + curr_gt = 0; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); + m_mpz_manager.del(x_copy); + m_mpz_manager.del(y_copy); + } + } + else { + if (x_unsigned <= y_unsigned) + res = 1.0; + else { + mpz x_copy, y_copy; + m_mpz_manager.set(x_copy, x); + m_mpz_manager.set(y_copy, y); + unsigned lower_le = 1; + unsigned curr_le = 1; + int last_pos = -1; + for (int i = 0; i < bv_sz; i++) + { + if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) + { + lower_le = curr_le; + curr_le = 0; + last_pos = i; + } + else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) + { + lower_le = curr_le; + curr_le = 1; + last_pos = i; + } + + m_mpz_manager.machine_div(x_copy, m_two, x_copy); + m_mpz_manager.machine_div(y_copy, m_two, y_copy); + } + + res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2); + } + } + TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << + m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); + + m_mpz_manager.del(x_unsigned); + m_mpz_manager.del(y_unsigned); + }*/ + else if (m_bv_util.is_bv_sle(n)) { // x <= y app * a = to_app(n); SASSERT(a->get_num_args() == 2); mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0))); @@ -857,31 +1102,61 @@ public: if (negated) { if (x > y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(x, y, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= p; - double dbl = n.get_double(); - res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + double dbl = 1.0 - n.get_double(); + //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } else { if (x <= y) - res = 1.0; + { + /*mpz diff; + m_mpz_manager.sub(y, x, diff); + m_mpz_manager.inc(diff); + rational n(diff); + n /= rational(m_powers(bv_sz)); + double dbl = n.get_double(); + // In extreme cases, n is 0.9999 but to_double returns something > 1.0 + m_mpz_manager.del(diff); + res = 1.0 + 0.5 * dbl;*/ + res = 1.0; + } else { + //res = (bv_sz - 1.0) / bv_sz; +#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); + SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; - double dbl = n.get_double(); + double dbl = 1.0 - n.get_double(); res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; m_mpz_manager.del(diff); +#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); @@ -1031,13 +1306,13 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(ptr_vector const & as, unsigned sz) { + ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { if (sz == 1) return get_constants(); m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1051,22 +1326,22 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(ptr_vector const & as, unsigned sz, unsigned int pos) { + expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { for (unsigned i = pos; i < sz; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) return q; } for (unsigned i = 0; i < pos; i++) { - expr * q = as[i]; + expr * q = g->form(i); if (m_mpz_manager.neq(get_value(q), m_one)) return q; } return 0; } - ptr_vector & get_unsat_constants_walksat(ptr_vector const & as, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(as, sz, pos); + ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. if (!q) return m_temp_constants; @@ -1143,20 +1418,66 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_crsat(ptr_vector const & as, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(as, sz, pos); + ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { + expr * q = get_unsat_assertion(g, sz, pos); if (!q) return m_temp_constants; return go_deeper(q); } - ptr_vector & get_unsat_constants(ptr_vector const & as, unsigned int flip) { - unsigned sz = as.size(); + void go_deeper_only(expr * e) { + //if (m_manager.is_bool(e)) { + if (m_manager.is_and(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + unsigned cnt_unsat = 0, pos = -1; + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q); + } + go_deeper(args[pos]); + } + else if (m_manager.is_or(e)) { + app * a = to_app(e); + expr * const * args = a->get_args(); + unsigned int sz = a->get_num_args(); + for (unsigned int i = 0; i < sz; i++) { + expr * q = args[i]; + go_deeper(q); + } + } + //} + else + { + ptr_vector const & this_decls = m_constants_occ.find(e); + unsigned sz2 = this_decls.size(); + for (unsigned j = 0; j < sz2; j++) { + func_decl * fd = this_decls[j]; + if (!m_temp_constants.contains(fd)) + m_temp_constants.push_back(fd); + } + } + } + + ptr_vector & get_unsat_constants_only(expr * e) { + if (e && !m_temp_constants.size()) + go_deeper_only(e); + + return m_temp_constants; + } + + ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(as[0]), m_one)) + if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + { + m_temp_constants.reset(); return m_temp_constants; + } else return get_constants(); } @@ -1169,11 +1490,12 @@ public: #if _PROBABILISTIC_UCT_ double sum_score = 0.0; unsigned start_index = get_random_uint(16) % sz; - + for (unsigned i = start_index; i < sz; i++) { expr * e = g->form(i); vscore = m_scores.find(e); + #if _PROBABILISTIC_UCT_ == 2 double q = vscore.score * vscore.score; #else @@ -1203,7 +1525,7 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); @@ -1221,12 +1543,12 @@ public: return m_temp_constants; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(as[pos]).touched++; + m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 - m_scores.find(as[pos]).touched = flip; + m_scores.find(g->form(pos)).touched = flip; #endif - expr * e = as[pos]; + expr * e = g->form(pos); // expr * e = m_list_false[pos]; #elif _BFS_ == 3 @@ -1304,12 +1626,15 @@ public: } } + expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { + unsigned sz = g->size(); - expr * get_unsat_assertion(ptr_vector const & as, unsigned int flip) { - unsigned sz = as.size(); - - if (sz == 1) - return as[0]; + if (sz == 1) { + if (m_mpz_manager.eq(get_value(g->form(0)), m_zero)) + return g->form(0); + else + return 0; + } m_temp_constants.reset(); #if _FOCUS_ == 1 @@ -1353,12 +1678,12 @@ public: #else double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = as[i]; + expr * e = g->form(i); // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); #if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); #elif _UCT_ == 2 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; #elif _UCT_ == 3 @@ -1371,13 +1696,13 @@ public: return 0; #if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(as[pos]).touched++; + m_scores.find(g->form(pos)).touched++; m_touched++; #elif _UCT_ == 2 m_scores.find(g->form(pos)).touched = flip; #endif // return m_list_false[pos]; - return as[pos]; + return g->form(pos); #elif _BFS_ == 3 unsigned int pos = -1; @@ -1431,7 +1756,7 @@ public: unsigned int pos = get_random_uint(16) % sz; return get_unsat_assertion(g, sz, pos); #endif - return as[pos]; + return g->form(pos); #elif _FOCUS_ == 2 #if _BFS_ unsigned int pos = flip % sz; @@ -1441,6 +1766,23 @@ public: return get_unsat_constants_crsat(g, sz, pos); #endif } + + expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { + unsigned sz = g->size(); + + if (sz == 1) + return 0; + + m_temp_constants.reset(); + + unsigned cnt_unsat = 0, pos = -1; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + + if (pos == static_cast(-1)) + return 0; + return g->form(pos); + } }; #endif \ No newline at end of file From de028e7a30df593547b47262e98d9673f00adfa9 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 00:32:45 +0100 Subject: [PATCH 222/646] Almost cleaned up version. --- src/tactic/sls/sls_compilation_settings.h | 156 +-- src/tactic/sls/sls_engine.cpp | 1168 +++------------------ src/tactic/sls/sls_engine.h | 89 +- src/tactic/sls/sls_evaluator.h | 262 +---- src/tactic/sls/sls_tactic.cpp | 6 +- src/tactic/sls/sls_tracker.h | 904 ++-------------- 6 files changed, 315 insertions(+), 2270 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index d2b899dd8..9add78daa 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,167 +22,13 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 0 - -// shall we use additive weighting scheme? -#define _PAWS_ 5 -#define _PAWS_INIT_ 40 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 1 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 100 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 2.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// shall we check 2-bit flips in plateaus using Monte Carlo? -#define _VNS_MC_ 0 - -// how many 2-bit flips shall we try per bit? -#define _VNS_MC_TRIES_ 1 - -// shall we check another assertion if no improving step was found in the first one? -#define _VNS_REPICK_ 0 - -// what is the probability of doing so (percentage)? -#define _VNS_PERC_ 100 - -// do a decreasing move with percentage ... -#define _INSIST_PERC_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.5 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick assertion when randomizing in a plateau or use the current one? -// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 20.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 0 - -// do we gradually reduce the touched values of _UCT_? -#define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.9 - // shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 +#define _USE_ADDSUB_ 0 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 // shall we use early pruning for incremental update? #define _EARLY_PRUNE_ 1 -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) -InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) -InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) -InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) -InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) -InvalidConfiguration; -#endif - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 342e649af..c240a0c51 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) : m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) { updt_params(p); + m_tracker.updt_params(p); } sls_engine::~sls_engine() { @@ -52,20 +53,21 @@ sls_engine::~sls_engine() { m_mpz_manager.del(m_two); } -double sls_engine::get_restart_armin(unsigned cnt_restarts) -{ - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); -} - void sls_engine::updt_params(params_ref const & _p) { sls_params p(_p); m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); + m_max_restarts = p.max_restarts(); m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); + m_walksat = p.walksat(); + m_walksat_repick = p.walksat_repick(); + m_paws_sp = p.paws_sp(); + m_wp = p.wp(); + m_vns_mc = p.vns_mc(); + m_vns_repick = p.vns_repick(); + + m_restart_base = p.restart_base(); + m_restart_next = m_restart_base; + m_restart_init = p.restart_init(); } void sls_engine::checkpoint() { @@ -74,15 +76,15 @@ void sls_engine::checkpoint() { cooperate("sls"); } -bool sls_engine::full_eval(goal_ref const & g, model & mdl) { +bool sls_engine::full_eval(model & mdl) { bool res = true; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz && res; i++) { checkpoint(); expr_ref o(m_manager); - if (!mdl.eval(g->form(i), o, true)) + if (!mdl.eval(m_assertions[i], o, true)) exit(ERR_INTERNAL_FATAL); res = m_manager.is_true(o.get()); @@ -93,93 +95,58 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) { return res; } -double sls_engine::top_score(goal_ref const & g) { -#if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl;); - return min; -#else +double sls_engine::top_score() { double top_sum = 0.0; - unsigned sz = g->size(); + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = m_assertions[i]; top_sum += m_tracker.get_score(e); } TRACE("sls_top", tout << "Score distribution:"; for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); + tout << " " << m_tracker.get_score(m_assertions[i]); tout << " AVG: " << top_sum / (double)sz << std::endl;); -#if _CACHE_TOP_SCORE_ m_tracker.set_top_sum(top_sum); -#endif return top_sum / (double)sz; -#endif } -double sls_engine::rescore(goal_ref const & g) { +double sls_engine::rescore() { m_evaluator.update_all(); m_stats.m_full_evals++; - return top_score(g); + return top_score(); } -double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif + return (m_tracker.get_top_sum() / m_assertions.size()); } -double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { +double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif + return (m_tracker.get_top_sum() / m_assertions.size()); } -double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { -#if _EARLY_PRUNE_ +double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; -#else - NOT_IMPLEMENTED_YET(); -#endif -} - -double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune_new(fd, new_value)) - return (m_tracker.get_top_sum() / g->size()); + return (m_tracker.get_top_sum() / m_assertions.size()); else return 0.0; } // checks whether the score outcome of a given move is better than the previous score -bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { +bool sls_engine::what_if( + func_decl * fd, + const unsigned & fd_inx, + const mpz & temp, + double & best_score, + unsigned & best_const, + mpz & best_value) { #ifdef Z3DEBUG mpz old_value; @@ -187,9 +154,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd #endif #if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); + double r = incremental_score_prune(fd, temp); #else - double r = incremental_score(g, fd, temp); + double r = incremental_score(fd, temp); #endif #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << @@ -198,7 +165,7 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd m_mpz_manager.del(old_value); #endif - //if (r >= best_score) { + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { m_tracker.reset_equal_scores(); best_score = r; @@ -206,45 +173,6 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd m_mpz_manager.set(best_value, temp); return true; } - /*else if (r == best_score) { - if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0) - { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - }*/ - - return false; -} - -bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - double r = incremental_score_prune_new(g, fd, temp); - - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; -} - -// same as what_if, but only applied to the score of a specific atom, not the total score -bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } return false; } @@ -261,22 +189,6 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, } -// Andreas: do we really need all those temporary mpzs? -void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); -} - -void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); -} - void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { unsigned shift; m_mpz_manager.add(old_value, m_one, incremented); @@ -334,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; #else - mt = MV_FLIP; + move_type mt = MV_FLIP; #endif unsigned bit = 0; @@ -373,216 +285,40 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout);); } - m_evaluator.update(fd, new_value); + m_evaluator.serious_update(fd, new_value); m_mpz_manager.del(new_value); } -void sls_engine::mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); -} - -// will use VNS to ignore some possible moves and increase the flips per second -double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - -double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - for (unsigned j = 1; j < max_bv_sz; j++) - { - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { +double sls_engine::find_best_move( + ptr_vector & to_evaluate, + double score, + unsigned & best_const, + mpz & best_value, + unsigned & new_bit, + move_type & move) +{ mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif unsigned bv_sz; -#if _INSIST_PERC_ - double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score; -#else double new_score = score; -#endif m_tracker.reset_equal_scores(); -// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { for (unsigned i = 0; i < to_evaluate.size(); i++) { -// for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) { -// for (unsigned i = to_evaluate.size(); i-- > 0; ) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); m_mpz_manager.set(old_value, m_tracker.get_value(fd)); // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) { -#else -// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { for (unsigned j = 0; j < bv_sz; j++) { -// for (unsigned j = bv_sz; j-- > 0; ) { -#endif // What would happen if we flipped bit #i ? mk_flip(srt, old_value, j, temp); - //if (m_tracker.get_random_uint(1)) - //if ((move != MV_FLIP) || (new_bit > j)) - //{ - //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) { - // new_bit = j; - // move = MV_FLIP; - //} - //} - //else - //{ - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { + if (what_if(fd, i, temp, new_score, best_const, best_value)) { new_bit = j; move = MV_FLIP; } - //} } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { @@ -590,76 +326,41 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector & to if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INC; } else { // for even values, try -1 mk_dec(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } #endif // try inverting mk_inv(bv_sz, old_value, temp); - //if (m_tracker.get_random_uint(1)) - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) + if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); // Andreas: does not hold anymore now that we use top level score caching //SASSERT(check == score); } m_mpz_manager.del(old_value); m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - - if ((new_score == score) && 1)// (m_tracker.get_random_uint(1))) - best_const = -1; return new_score; } // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. -double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, +double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double score, unsigned & best_const, mpz & best_value) { mpz old_value, temp, temp2; unsigned bv_sz; double new_score = score; -// for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) { for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -667,22 +368,21 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & m_mpz_manager.set(old_value, m_tracker.get_value(fd)); if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) { -// for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { for (unsigned j = 0; j < bv_sz; j++) { mk_flip(srt, old_value, j, temp); - for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++) + for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++) { unsigned k = m_tracker.get_random_uint(16) % bv_sz; while (k == j) k = m_tracker.get_random_uint(16) % bv_sz; mk_flip(srt, temp, k, temp2); - what_if(g, fd, i, temp2, new_score, best_const, best_value); + what_if(fd, i, temp2, new_score, best_const, best_value); } } } // reset to what it was before - double check = incremental_score(g, fd, old_value); + double check = incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -692,618 +392,89 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector & return new_score; } -// same as find_best_move but only considers the score of the current expression instead of the overall score -double sls_engine::find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; -} - -// first try of intensification ... does not seem to be efficient -bool sls_engine::handle_plateau(goal_ref const & g) -{ - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back(&m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } - else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], *m_old_values[i]); - - m_old_values.reset(); - - return 0; -} - -// what_if version needed in the context of 2nd intensification try, combining local and global score -bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; -} - -// find_best_move version needed in the context of 2nd intensification try -double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) -{ - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; -} - -// second try to use intensification ... also not very effective -bool sls_engine::handle_plateau(goal_ref const & g, double old_score) -{ - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; -} - // main search loop -lbool sls_engine::search(goal_ref const & g) { +lbool sls_engine::search() { lbool res = l_undef; double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; + unsigned new_const = (unsigned)-1, new_bit; mpz new_value; move_type move; - unsigned plateau_cnt = 0; - score = rescore(g); - unsigned sz = g->size(); - - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - //if (m_stats.m_stopwatch.get_current_seconds() > 10.0) - //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);} + score = rescore(); + unsigned sz = m_assertions.size(); + while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; + if (m_stats.m_moves % m_restart_base == 0) + m_tracker.ucb_forget(m_assertions); -#if _UCT_FORGET_ - //if (m_stats.m_moves % sz == 0) - if (m_stats.m_moves % _UCT_FORGET_ == 0) - m_tracker.uct_forget(g); -#endif - -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - //ptr_vector & to_evaluate = m_tracker.get_unsat_constants_only(e); - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); + + ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { res = l_true; goto bailout; } -#endif -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) + if (m_wp && m_tracker.get_random_uint(10) < m_wp) { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif + score = m_tracker.get_top_sum() / sz; + continue; } - continue; -#endif -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif old_score = score; new_const = (unsigned)-1; - move = MV_FLIP; - new_bit = 0; -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif + score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); -#if _VNS_MC_ > _VNS_REPICK_ -#if _VNS_MC_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } + if (m_vns_mc && (new_const == static_cast(-1))) + score = find_best_move_mc(to_evaluate, score, new_const, new_value); + + /*if (m_vns_repick && (new_const == static_cast(-1))) + { + expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); + if (q) + { + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); } -#endif -#endif - -#if _VNS_MC_ < _VNS_REPICK_ -#if _VNS_REPICK_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } - } -#endif -#if _VNS_MC_ - if (new_const == static_cast(-1)) - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); -#endif -#endif - -#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_ - if (new_const == static_cast(-1)) { - if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) - score = find_best_move_mc(g, to_evaluate, score, new_const, new_value); - else { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); - score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move); - } - } - } -#endif - + }*/ if (new_const == static_cast(-1)) { score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); + if (m_walksat && m_walksat_repick) + m_evaluator.randomize_local(m_assertions); else -#endif -#if _REPICK_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _REPICK_ == 2 - { - expr * q = m_tracker.get_new_unsat_assertion(g, e); - if (q) - m_evaluator.randomize_local(q); - else - m_evaluator.randomize_local(e); - } -#else - m_evaluator.randomize_local_n(g, to_evaluate); - //m_evaluator.randomize_local(to_evaluate); -#endif -#endif + m_evaluator.randomize_local(to_evaluate); -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif + score = m_tracker.get_top_sum() / m_assertions.size(); -#if _PAWS_ - for (unsigned i = 0; i < sz; i++) + if (m_paws_sp < 1024) { - expr * q = g->form(i); - if (m_tracker.get_random_uint(16) % 100 < _PAWS_) + for (unsigned i = 0; i < sz; i++) { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) - m_tracker.decrease_weight(q); - } - else - { - if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) - m_tracker.increase_weight(q); + expr * q = m_assertions[i]; + if (m_tracker.get_random_uint(10) < m_paws_sp) + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) + m_tracker.decrease_weight(q); + } + else + { + if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) + m_tracker.increase_weight(q); + } } } -#endif - } else { func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - -bailout: - m_mpz_manager.del(new_value); - - return res; -} - -// main search loop -lbool sls_engine::search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl;); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl;); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl;); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl;); - } - - if (score >= 0.99999) { - // if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } - else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true = false; - if (all_true) { - res = l_true; // sat - goto bailout; - } - else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } + score = serious_score(fd, new_value); } } @@ -1321,80 +492,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { m_produce_models = g->models_enabled(); - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl; - verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl; - verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl; - verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl; - verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl; - verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; - verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; + for (unsigned i = 0; i < g->size(); i++) + assert_expr(g->form(i)); + verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + lbool res = operator()(); if (res == l_true) { report_tactic_progress("Number of flips:", m_stats.m_moves); @@ -1416,33 +521,66 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -unsigned sls_engine::check_restart(unsigned curr_value) +lbool sls_engine::operator()() { + m_tracker.initialize(m_assertions); + lbool res = l_undef; + + do { + checkpoint(); + + report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); + res = search(); + + if (res == l_undef) + { + if (m_restart_init) + m_tracker.randomize(m_assertions); + else + m_tracker.reset(m_assertions); + } + } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); + + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + + return res; +} + +/* Andreas: Needed for Armin's restart scheme if we don't want to use loops. +inline double sls_engine::get_restart_armin(unsigned cnt_restarts) { - if (curr_value > m_restart_limit) + unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); + unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; + return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1); +} +*/ + +inline unsigned sls_engine::check_restart(unsigned curr_value) +{ + if (curr_value > m_restart_next) { + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 - m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); + m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); #elif _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); + m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1); #elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; + m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base; #elif _RESTART_SCHEME_ == 1 if (m_stats.m_restarts & 1) - //if (m_stats.m_restarts % 3 == 2) - m_restart_limit += _RESTART_LIMIT_; + m_restart_next += m_restart_base; else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; - //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_; + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; #else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif + m_restart_limit += m_restart_base; +#endif */ + if (m_stats.m_restarts & 1) + m_restart_next += m_restart_base; + else + m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base; return 0; } return 1; -} \ No newline at end of file +} diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 902c6b7a0..ff0e55f24 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -22,6 +22,7 @@ Notes: #include"stopwatch.h" #include"lbool.h" #include"model_converter.h" +#include"goal.h" #include"sls_compilation_settings.h" #include"sls_tracker.h" @@ -35,17 +36,13 @@ public: stopwatch m_stopwatch; unsigned m_full_evals; unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; + unsigned m_moves, m_flips, m_incs, m_decs, m_invs; stats() : m_restarts(0), m_full_evals(0), m_incr_evals(0), m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), m_flips(0), m_incs(0), m_decs(0), @@ -71,14 +68,22 @@ protected: bv_util m_bv_util; sls_tracker m_tracker; sls_evaluator m_evaluator; + ptr_vector m_assertions; - unsigned m_restart_limit; unsigned m_max_restarts; - unsigned m_plateau_limit; + unsigned m_walksat; + unsigned m_walksat_repick; + unsigned m_wp; + unsigned m_vns_mc; + unsigned m_vns_repick; + unsigned m_paws_sp; + unsigned m_restart_base; + unsigned m_restart_next; + unsigned m_restart_init; ptr_vector m_old_values; - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; + typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; public: sls_engine(ast_manager & m, params_ref const & p); @@ -92,78 +97,46 @@ public: void updt_params(params_ref const & _p); + void assert_expr(expr * e) { m_assertions.push_back(e); } + stats const & get_stats(void) { return m_stats; } void reset_statistics(void) { m_stats.reset(); } - bool full_eval(goal_ref const & g, model & mdl); - + bool full_eval(model & mdl); void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result); - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result); - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result); void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented); void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented); void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted); - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); + void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped); - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_lsb(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - double find_best_move_mc(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value); - - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - - - - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i); - - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i); - - - lbool search(goal_ref const & g); + lbool search(void); + lbool operator()(); void operator()(goal_ref const & g, model_converter_ref & mc); protected: void checkpoint(); - lbool search_old(goal_ref const & g); - double get_restart_armin(unsigned cnt_restarts); - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, + bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp, double & best_score, unsigned & best_const, mpz & best_value); - bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value); - double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value); + double top_score(); + double rescore(); + double serious_score(func_decl * fd, const mpz & new_value); + double incremental_score(func_decl * fd, const mpz & new_value); - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value); + double incremental_score_prune(func_decl * fd, const mpz & new_value); + double find_best_move(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); - double top_score(goal_ref const & g); - double rescore(goal_ref const & g); - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value); - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value); -#endif - - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move); + double find_best_move_mc(ptr_vector & to_evaluate, double score, + unsigned & best_const, mpz & best_value); void mk_random_move(ptr_vector & unsat_constants); - void mk_random_move(goal_ref const & g); - - bool handle_plateau(goal_ref const & g); - bool handle_plateau(goal_ref const & g, double old_score); + //inline double get_restart_armin(unsigned cnt_restarts); inline unsigned check_restart(unsigned curr_value); }; -#endif \ No newline at end of file +#endif diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 78f2cb79a..37bfa5a2d 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -81,11 +81,7 @@ public: case OP_AND: { m_mpz_manager.set(result, m_one); for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_zero); break; } @@ -93,11 +89,7 @@ public: } case OP_OR: { for (unsigned i = 0; i < n_args; i++) -#if _DIRTY_UP_ - if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i])) { -#else if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) { -#endif m_mpz_manager.set(result, m_one); break; } @@ -105,16 +97,9 @@ public: } case OP_NOT: { SASSERT(n_args == 1); -#if _DIRTY_UP_ - if (m_tracker.is_top_expr(args[0])) - m_mpz_manager.set(result, m_zero); - else - m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero); -#else const mpz & child = m_tracker.get_value(args[0]); SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child)); m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero); -#endif break; } case OP_EQ: { @@ -545,9 +530,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -559,8 +542,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); -#if _REAL_RS_ || _REAL_PBFS_ - //if (!m_tracker.has_uplinks(cur)) +#if _REAL_RS_ if (m_tracker.is_top_expr(cur)) { if (m_mpz_manager.eq(new_value,m_one)) @@ -570,25 +552,12 @@ public: } #endif + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { @@ -617,9 +586,7 @@ public: expr_fast_mark1 visited; mpz new_value; -#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_ double new_score; -#endif SASSERT(cur_depth < m_traversal_stack.size()); while (cur_depth != static_cast(-1)) { @@ -630,25 +597,12 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); + new_score = m_tracker.score(cur); + if (m_tracker.is_top_expr(cur)) + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); + m_tracker.set_score(cur, new_score); #if _EARLY_PRUNE_ - new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif - m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); -#else -#if _CACHE_TOP_SCORE_ - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif #endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -684,11 +638,7 @@ public: m_traversal_stack[cur_depth].push_back(ep); if (cur_depth > max_depth) max_depth = cur_depth; } -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ run_serious_update(max_depth); -#else - run_update(max_depth); -#endif } void update(func_decl * fd, const mpz & new_value) { @@ -713,7 +663,6 @@ public: run_serious_update(cur_depth); } -#if _EARLY_PRUNE_ unsigned run_update_bool_prune(unsigned cur_depth) { expr_fast_mark1 visited; @@ -727,19 +676,15 @@ public: expr * cur = cur_depth_exprs[i]; new_score = m_tracker.score(cur); -#if _CACHE_TOP_SCORE_ - //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); -#endif + prune_score = m_tracker.get_score_prune(cur); m_tracker.set_score(cur, new_score); if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur))) - //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) pot_benefits = 1; if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur))) - //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) pot_benefits = 1; if (m_tracker.has_uplinks(cur)) { @@ -754,9 +699,6 @@ public: } } } - else - { - } } cur_depth_exprs.reset(); @@ -770,15 +712,11 @@ public: for (unsigned i = 0; i < cur_size; i++) { expr * cur = cur_depth_exprs[i]; -#if _CACHE_TOP_SCORE_ new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#else - m_tracker.set_score(cur, m_tracker.score(cur)); -#endif + if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { @@ -859,161 +797,18 @@ public: } return run_update_bool_prune(cur_depth); } -#endif - - unsigned run_update_bool_prune_new(unsigned cur_depth) { - expr_fast_mark1 visited; - - double prune_score, new_score; - unsigned pot_benefits = 0; - SASSERT(cur_depth < m_traversal_stack_bool.size()); - - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - - for (unsigned i = 0; i < cur_depth_exprs.size(); i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - prune_score = m_tracker.get_score_prune(cur); - m_tracker.set_score(cur, new_score); - - if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur))) - pot_benefits = 1; - if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur))) - pot_benefits = 1; - - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - else - { - } - } - - cur_depth_exprs.reset(); - cur_depth--; - - while (cur_depth != static_cast(-1)) { - ptr_vector & cur_depth_exprs = m_traversal_stack_bool[cur_depth]; - if (pot_benefits) - { - unsigned cur_size = cur_depth_exprs.size(); - for (unsigned i = 0; i < cur_size; i++) { - expr * cur = cur_depth_exprs[i]; - - new_score = m_tracker.score(cur); - //if (!m_tracker.has_uplinks(cur)) - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); - m_tracker.set_score(cur, new_score); - if (m_tracker.has_uplinks(cur)) { - ptr_vector & ups = m_tracker.get_uplinks(cur); - for (unsigned j = 0; j < ups.size(); j++) { - expr * next = ups[j]; - unsigned next_d = m_tracker.get_distance(next); - SASSERT(next_d < cur_depth); - if (!visited.is_marked(next)) { - m_traversal_stack_bool[next_d].push_back(next); - visited.mark(next); - } - } - } - } - } - cur_depth_exprs.reset(); - cur_depth--; - } - - return pot_benefits; - } - - unsigned update_prune_new(func_decl * fd, const mpz & new_value) { - m_tracker.set_value(fd, new_value); - expr * ep = m_tracker.get_entry_point(fd); - unsigned cur_depth = m_tracker.get_distance(ep); - - if (m_traversal_stack_bool.size() <= cur_depth) - m_traversal_stack_bool.resize(cur_depth+1); - if (m_traversal_stack.size() <= cur_depth) - m_traversal_stack.resize(cur_depth+1); - - if (m_manager.is_bool(ep)) - m_traversal_stack_bool[cur_depth].push_back(ep); - else - { - m_traversal_stack[cur_depth].push_back(ep); - run_update_prune(cur_depth); - } - return run_update_bool_prune_new(cur_depth); - } void randomize_local(ptr_vector & unsat_constants) { - // Randomize _all_ candidates: - - //// bool did_something = false; - //for (unsigned i = 0; i < unsat_constants.size(); i++) { - // func_decl * fd = unsat_constants[i]; - // mpz temp = m_tracker.get_random(fd->get_range()); - // // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) { - // // did_something = true; - // // } - // update(fd, temp); - // m_mpz_manager.del(temp); - //} - // Randomize _one_ candidate: unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); func_decl * fd = unsat_constants[r]; -#if _PERC_CHANGE_ - sort * srt = fd->get_range(); - mpz temp; - - if (m_manager.is_bool(srt)) - m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { - mpz temp2, mask; - unsigned bv_sz = m_bv_util.get_bv_size(srt); - m_mpz_manager.set(temp, m_tracker.get_value(fd)); - - for (unsigned bit = 0; bit < bv_sz; bit++) - if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_) - { - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(temp, mask, temp2); - m_mpz_manager.set(temp, temp2); - } - m_mpz_manager.del(mask); - m_mpz_manager.del(temp2); - } -#else mpz temp = m_tracker.get_random(fd->get_range()); -#endif -#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_ serious_update(fd, temp); -#else - update(fd, temp); -#endif + m_mpz_manager.del(temp); - TRACE("sls", /*tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl;*/ - tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; + TRACE("sls", tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl; tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); @@ -1023,36 +818,9 @@ public: randomize_local(m_tracker.get_constants(e)); } - void randomize_local(goal_ref const & g, unsigned int flip) { - randomize_local(m_tracker.get_unsat_constants(g, flip)); + void randomize_local(ptr_vector const & as) { + randomize_local(m_tracker.get_unsat_constants(as)); } - - void randomize_local_n(goal_ref const & g, ptr_vector & unsat_constants) { - unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size(); - func_decl * fd = unsat_constants[r]; - sort * srt = fd->get_range(); - unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); - mpz max_val = m_tracker.get_random(srt); - update(fd, max_val); - double max_score = m_tracker.get_top_sum() / g->size(); - mpz temp_val; - double temp_score; - for (unsigned i = 1; i < 2; i++) - //for (unsigned i = 1; i < bv_sz; i++) - { - m_mpz_manager.set(temp_val, m_tracker.get_random(srt)); - update(fd, temp_val); - temp_score = m_tracker.get_top_sum() / g->size(); - if (temp_score > max_score) - { - m_mpz_manager.set(max_val, temp_val); - max_score = temp_score; - } - } - update(fd, max_val); - m_mpz_manager.del(temp_val); - m_mpz_manager.del(max_val); - } }; #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 0b6b01e7c..6e1102dd2 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -1507,16 +1507,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { using_params(mk_simplify_tactic(m), simp2_p)), using_params(mk_simplify_tactic(m), hoist_p), mk_max_bv_sharing_tactic(m), - // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this? - //mk_ctx_simplify_tactic(m, ctx_p), - // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance! - //mk_simplify_tactic(m), mk_nnf_tactic(m, p)); } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); -// tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); + //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 87c90f1f8..65011dc8d 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,7 +20,9 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ -#include"goal.h" +#include"for_each_expr.h" +#include"ast_smt2_pp.h" +#include"bv_decl_plugin.h" #include"model.h" #include"sls_compilation_settings.h" @@ -37,11 +39,7 @@ class sls_tracker { mpz m_zero, m_one, m_two; struct value_score { -#if _EARLY_PRUNE_ value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; -#else - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { }; -#endif ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; @@ -78,24 +76,22 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; -#if _UCT_ + + unsigned m_walksat; + unsigned m_ucb; + double m_ucb_constant; + unsigned m_ucb_init; + double m_ucb_forget; unsigned m_touched; -#endif -#if _REAL_RS_ || _REAL_PBFS_ + double m_scale_unsat; + unsigned m_paws_init; +#if _REAL_RS_ ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; #endif -#if _PAWS_ obj_map m_weights; - //obj_map m_weights; -#endif -#if _CACHE_TOP_SCORE_ double m_top_sum; -#endif -#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ - double m_weight_dist_factor; -#endif unsigned m_equal_scores; public: @@ -116,6 +112,17 @@ public: m_mpz_manager.del(m_two); } + void updt_params(params_ref const & _p) { + sls_params p(_p); + m_walksat = p.walksat(); + m_ucb = p.walksat_ucb(); + m_ucb_constant = p.walksat_ucb_constant(); + m_ucb_init = p.walksat_ucb_init(); + m_ucb_forget = p.walksat_ucb_forget(); + m_scale_unsat = p.scale_unsat(); + m_paws_init = p.paws_init(); + } + unsigned get_formula_size() { return m_scores.size(); } @@ -141,12 +148,6 @@ public: return sum / count; } -#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_ - inline void set_weight_dist_factor(double val) { - m_weight_dist_factor = val; - } -#endif - void reset_equal_scores() { m_equal_scores = 1; } @@ -155,13 +156,8 @@ public: return ++m_equal_scores; } -#if _CACHE_TOP_SCORE_ inline void adapt_top_sum(expr * e, double add, double sub) { -#if _PAWS_ m_top_sum += m_weights.find(e) * (add - sub); -#else - m_top_sum += add - sub; -#endif } inline void set_top_sum(double new_score) { @@ -171,7 +167,6 @@ public: inline double get_top_sum() { return m_top_sum; } -#endif inline void set_value(expr * n, const mpz & r) { SASSERT(m_scores.contains(n)); @@ -217,7 +212,6 @@ public: return get_score(ep); } -#if _EARLY_PRUNE_ inline void set_score_prune(expr * n, double score) { SASSERT(m_scores.contains(n)); m_scores.find(n).score_prune = score; @@ -237,7 +231,6 @@ public: SASSERT(m_scores.contains(n)); return m_scores.find(n).has_neg_occ; } -#endif inline unsigned get_distance(expr * n) { SASSERT(m_scores.contains(n)); @@ -271,7 +264,7 @@ public: return m_uplinks.find(n); } -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ void debug_real(goal_ref const & g, unsigned flip) { unsigned count = 0; @@ -318,21 +311,22 @@ public: } #endif -#if _UCT_ - void uct_forget(goal_ref const & g) { - expr * e; - unsigned touched_old, touched_new; - - for (unsigned i = 0; i < g->size(); i++) + inline void ucb_forget(ptr_vector & as) { + if (m_ucb_forget < 1.0) { - e = g->form(i); - touched_old = m_scores.find(e).touched; - touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1); - m_scores.find(e).touched = touched_new; - m_touched += touched_new - touched_old; + expr * e; + unsigned touched_old, touched_new; + + for (unsigned i = 0; i < as.size(); i++) + { + e = as[i]; + touched_old = m_scores.find(e).touched; + touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1); + m_scores.find(e).touched = touched_new; + m_touched += touched_new - touched_old; + } } } -#endif void initialize(app * n) { // Build score table @@ -409,12 +403,12 @@ public: } }; - void calculate_expr_distances(goal_ref const & g) { + void calculate_expr_distances(ptr_vector const & as) { // precondition: m_scores is set up. - unsigned sz = g->size(); + unsigned sz = as.size(); ptr_vector stack; for (unsigned i = 0; i < sz; i++) - stack.push_back(to_app(g->form(i))); + stack.push_back(to_app(as[i])); while (!stack.empty()) { app * cur = stack.back(); stack.pop_back(); @@ -462,31 +456,24 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - void initialize(goal_ref const & g) { + void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); expr_mark visited; - unsigned sz = g->size(); + unsigned sz = as.size(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); else printf("this is already in ...\n"); - // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 - initialize_recursive(proc, visited, e); -#endif for_each_expr(proc, visited, e); } visited.reset(); for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // Andreas: Maybe not fully correct. -#if _FOCUS_ == 2 || _INTENSIFICATION_ - initialize_recursive(e); -#endif ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -494,11 +481,11 @@ public: quick_for_each_expr(ffd_proc, visited, e); } - calculate_expr_distances(g); + calculate_expr_distances(as); TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ m_list_false = new expr*[sz]; //for (unsigned i = 0; i < sz; i++) //{ @@ -507,50 +494,38 @@ public: //} #endif -#if _PAWS_ for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; if (!m_weights.contains(e)) - m_weights.insert(e, _PAWS_INIT_); + m_weights.insert(e, m_paws_init); } -#endif #if _EARLY_PRUNE_ for (unsigned i = 0; i < sz; i++) - setup_occs(g->form(i)); + setup_occs(as[i]); #endif -#if _UCT_ - m_touched = _UCT_INIT_ ? g->size() : 1; -#endif + m_touched = m_ucb_init ? as.size() : 1; } -#if _PAWS_ void increase_weight(expr * e) { - //printf("Increasing %d to", m_weights.find(e)); m_weights.find(e)++; - //m_weights.find(e) *= 1.1; - //printf(" %d\n", m_weights.find(e)); } void decrease_weight(expr * e) { unsigned old_weight = m_weights.find(e); - m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_; - //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1; - //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e)); + m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init; } unsigned get_weight(expr * e) - //double get_weight(expr * e) { return m_weights.find(e); } -#endif -#if _REAL_RS_ || _REAL_PBFS_ +#if _REAL_RS_ void make_assertion(expr * e) { if (m_where_false.contains(e)) @@ -683,7 +658,7 @@ public: NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now. } - void randomize(goal_ref const & g) { + void randomize(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -695,15 +670,9 @@ public: } TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); ); - -#if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; -#endif } - void reset(goal_ref const & g) { + void reset(ptr_vector const & as) { TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); ); for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) { @@ -711,15 +680,8 @@ public: set_value(it->m_value, temp); m_mpz_manager.del(temp); } - -#if _UCT_RESET_ - m_touched = _UCT_INIT_ ? g->size() : 1; - for (unsigned i = 0; i < g->size(); i++) - m_scores.find(g->form(i)).touched = 1; -#endif } -#if _EARLY_PRUNE_ void setup_occs(expr * n, bool negated = false) { if (m_manager.is_bool(n)) { @@ -752,7 +714,6 @@ public: else NOT_IMPLEMENTED_YET(); } -#endif double score_bool(expr * n, bool negated = false) { TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; ); @@ -770,57 +731,29 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it does not even occur. -#if _SCORE_AND_AVG_ + /* Andreas: Seems to have no effect. But maybe you want to try it again at some point. double sum = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) -#if _DIRTY_UP_ - sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else sum += get_score(args[i]); -#endif - res = sum / (double) a->get_num_args(); -#else + res = sum / (double) a->get_num_args(); */ double min = 1.0; for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else double cur = get_score(args[i]); -#endif if (cur < min) min = cur; } res = min; -#endif } else if (m_manager.is_or(n)) { SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); // Andreas: Seems to have no effect. Probably it is still too similar to the original version. -#if _SCORE_OR_MUL_ - double inv = 1.0; - for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else - double cur = get_score(args[i]); -#endif - inv *= (1.0 - get_score(args[i])); - } - res = 1.0 - inv; -#else double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { -#if _DIRTY_UP_ - double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]); -#else double cur = get_score(args[i]); -#endif if (cur > max) max = cur; } res = max; -#endif } else if (m_manager.is_ite(n)) { SASSERT(!negated); @@ -855,24 +788,14 @@ public: m_mpz_manager.bitwise_xor(v0, v1, diff); unsigned hamming_distance = 0; unsigned bv_sz = m_bv_util.get_bv_size(arg0); - #if 1 // unweighted hamming distance + // unweighted hamming distance while (!m_mpz_manager.is_zero(diff)) { - //m_mpz_manager.set(diff_m1, diff); - //m_mpz_manager.dec(diff_m1); - //m_mpz_manager.bitwise_and(diff, diff_m1, diff); - //hamming_distance++; if (!m_mpz_manager.is_even(diff)) { hamming_distance++; } m_mpz_manager.machine_div(diff, m_two, diff); } res = 1.0 - (hamming_distance / (double) bv_sz); - #else - rational r(diff); - r /= m_powers(bv_sz); - double dbl = r.get_double(); - res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl; - #endif TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << " ; SZ = " << bv_sz << std::endl; ); @@ -891,205 +814,36 @@ public: if (negated) { if (m_mpz_manager.gt(x, y)) - { - /*mpz diff; - m_mpz_manager.sub(x, y, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -/* mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_gt = 0; - unsigned curr_gt = 0; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 1; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 0; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); - m_mpz_manager.del(x_copy); - m_mpz_manager.del(y_copy);*/ -#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = 1.0 - n.get_double(); + double dbl = n.get_double(); // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; - //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } } else { if (m_mpz_manager.le(x, y)) - { - /*mpz diff; - m_mpz_manager.sub(y, x, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -/* mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_le = 1; - unsigned curr_le = 1; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_le = curr_le; - curr_le = 0; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_le = curr_le; - curr_le = 1; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/ -#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); rational n(diff); n /= rational(m_powers(bv_sz)); - double dbl = 1.0 - n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } -/* else if (m_bv_util.is_bv_sle(n)) { // x <= y - app * a = to_app(n); - SASSERT(a->get_num_args() == 2); - const mpz & x = get_value(a->get_arg(0)); - const mpz & y = get_value(a->get_arg(1)); - int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]); - - mpz x_unsigned; - mpz y_unsigned; - const mpz & p = m_powers(bv_sz); - const mpz & p_half = m_powers(bv_sz-1); - if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } - if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); } - - if (negated) { - if (x_unsigned > y_unsigned) - res = 1.0; - else { - mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_gt = 0; - unsigned curr_gt = 0; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 1; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_gt = curr_gt; - curr_gt = 0; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2); - m_mpz_manager.del(x_copy); - m_mpz_manager.del(y_copy); - } - } - else { - if (x_unsigned <= y_unsigned) - res = 1.0; - else { - mpz x_copy, y_copy; - m_mpz_manager.set(x_copy, x); - m_mpz_manager.set(y_copy, y); - unsigned lower_le = 1; - unsigned curr_le = 1; - int last_pos = -1; - for (int i = 0; i < bv_sz; i++) - { - if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy)) - { - lower_le = curr_le; - curr_le = 0; - last_pos = i; - } - else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy)) - { - lower_le = curr_le; - curr_le = 1; - last_pos = i; - } - - m_mpz_manager.machine_div(x_copy, m_two, x_copy); - m_mpz_manager.machine_div(y_copy, m_two, y_copy); - } - - res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2); - } - } - TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << - m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); - - m_mpz_manager.del(x_unsigned); - m_mpz_manager.del(y_unsigned); - }*/ - else if (m_bv_util.is_bv_sle(n)) { // x <= y + else if (m_bv_util.is_bv_sle(n)) { // x <= y app * a = to_app(n); SASSERT(a->get_num_args() == 2); mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0))); @@ -1102,61 +856,32 @@ public: if (negated) { if (x > y) - { - /*mpz diff; - m_mpz_manager.sub(x, y, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -#if 1 mpz diff; m_mpz_manager.sub(y, x, diff); m_mpz_manager.inc(diff); rational n(diff); n /= p; - double dbl = 1.0 - n.get_double(); - //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); } else { if (x <= y) - { - /*mpz diff; - m_mpz_manager.sub(y, x, diff); - m_mpz_manager.inc(diff); - rational n(diff); - n /= rational(m_powers(bv_sz)); - double dbl = n.get_double(); - // In extreme cases, n is 0.9999 but to_double returns something > 1.0 - m_mpz_manager.del(diff); - res = 1.0 + 0.5 * dbl;*/ res = 1.0; - } else { - //res = (bv_sz - 1.0) / bv_sz; -#if 1 mpz diff; m_mpz_manager.sub(x, y, diff); SASSERT(!m_mpz_manager.is_neg(diff)); rational n(diff); n /= p; - double dbl = 1.0 - n.get_double(); - res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl; + double dbl = n.get_double(); + res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl; m_mpz_manager.del(diff); -#endif } TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; ); @@ -1171,11 +896,7 @@ public: expr * child = a->get_arg(0); if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. NOT_IMPLEMENTED_YET(); -#if _DIRTY_UP_ - res = is_top_expr(child) ? 0.0 : score_bool(child, true); -#else res = score_bool(child, true); -#endif } else if (m_manager.is_distinct(n)) { app * a = to_app(n); @@ -1199,25 +920,11 @@ public: SASSERT(res >= 0.0 && res <= 1.0); -#if _WEIGHT_DIST_ app * a = to_app(n); family_id afid = a->get_family_id(); if (afid == m_bv_util.get_family_id()) -#endif -#if _WEIGHT_DIST_ == 1 -#if _WEIGHT_TOGGLE_ - if (res < 1.0) res *= m_weight_dist_factor; -#else - if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_; -#endif -#elif _WEIGHT_DIST_ == 2 - res *= res; -#elif _WEIGHT_DIST_ == 3 - if (res < 1.0) res = 0.0; -#elif _WEIGHT_DIST_ == 4 - if (res < 1.0) res *= m_weight_dist_factor; -#endif + if (res < 1.0) res *= m_scale_unsat; TRACE("sls_score", tout << "SCORE = " << res << std::endl; ); return res; @@ -1268,33 +975,6 @@ public: NOT_IMPLEMENTED_YET(); } - expr * get_unsat_expression(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e) || m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return get_unsat_expression(q); - } - } - } - return e; - } - ptr_vector & get_constants(expr * e) { ptr_vector const & this_decls = m_constants_occ.find(e); unsigned sz = this_decls.size(); @@ -1306,13 +986,17 @@ public: return m_temp_constants; } - ptr_vector & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) { - if (sz == 1) - return get_constants(); + ptr_vector & get_unsat_constants_gsat(ptr_vector const & as) { + unsigned sz = as.size(); + if (sz == 1) { + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return get_constants(); + } + m_temp_constants.reset(); for (unsigned i = 0; i < sz; i++) { - expr * q = g->form(i); + expr * q = as[i]; if (m_mpz_manager.eq(get_value(q), m_one)) continue; ptr_vector const & this_decls = m_constants_occ.find(q); @@ -1326,35 +1010,6 @@ public: return m_temp_constants; } - expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) { - for (unsigned i = pos; i < sz; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - for (unsigned i = 0; i < pos; i++) { - expr * q = g->form(i); - if (m_mpz_manager.neq(get_value(q), m_one)) - return q; - } - return 0; - } - - ptr_vector & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); - // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration. - if (!q) - return m_temp_constants; - ptr_vector const & this_decls = m_constants_occ.find(q); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - return m_temp_constants; - } - ptr_vector & get_unsat_constants_walksat(expr * e) { if (!e || m_temp_constants.size()) return m_temp_constants; @@ -1368,420 +1023,89 @@ public: return m_temp_constants; } - ptr_vector & go_deeper(expr * e) { - if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - // Andreas: might be used for guided branching - //for (unsigned i = 0; i < a->get_num_args(); i++) { - //double cur = get_score(args[i]); - //} - // Andreas: A random number is better here since reusing flip will cause patterns. - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned int pos = get_random_uint(16) % sz; - for (unsigned int i = pos; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - for (unsigned int i = 0; i < pos; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one)) - return go_deeper(q); - } - } - } - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - return m_temp_constants; - } + ptr_vector & get_unsat_constants(ptr_vector const & as) { + if (m_walksat) + { + expr * e = get_unsat_assertion(as); - ptr_vector & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) { - expr * q = get_unsat_assertion(g, sz, pos); - if (!q) - return m_temp_constants; - - return go_deeper(q); - } - - void go_deeper_only(expr * e) { - //if (m_manager.is_bool(e)) { - if (m_manager.is_and(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - unsigned cnt_unsat = 0, pos = -1; - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q); - } - go_deeper(args[pos]); - } - else if (m_manager.is_or(e)) { - app * a = to_app(e); - expr * const * args = a->get_args(); - unsigned int sz = a->get_num_args(); - for (unsigned int i = 0; i < sz; i++) { - expr * q = args[i]; - go_deeper(q); - } - } - //} - else - { - ptr_vector const & this_decls = m_constants_occ.find(e); - unsigned sz2 = this_decls.size(); - for (unsigned j = 0; j < sz2; j++) { - func_decl * fd = this_decls[j]; - if (!m_temp_constants.contains(fd)) - m_temp_constants.push_back(fd); - } - } - } - - ptr_vector & get_unsat_constants_only(expr * e) { - if (e && !m_temp_constants.size()) - go_deeper_only(e); - - return m_temp_constants; - } - - ptr_vector & get_unsat_constants(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); - - if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_one)) + if (!e) { m_temp_constants.reset(); return m_temp_constants; } - else - return get_constants(); - } - else { - m_temp_constants.reset(); -#if _FOCUS_ == 1 -#if _UCT_ - unsigned pos = -1; - value_score vscore; -#if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - for (unsigned i = start_index; i < sz; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); - -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } -#else - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); -// for (unsigned i = 0; i < m_where_false.size(); i++) { -// expr * e = m_list_false[i]; - vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); -#elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; -#elif _UCT_ == 3 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); -#endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - } -#endif - if (pos == static_cast(-1)) - return m_temp_constants; - -#if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; - m_touched++; -#elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; -#endif - expr * e = g->form(pos); -// expr * e = m_list_false[pos]; - -#elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } - } - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _BFS_ == 1 - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; - expr * e = get_unsat_assertion(g, sz, pos); -#elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return m_temp_constants; - expr * e = g->form(pos); -#elif _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - expr * e = m_list_false[get_random_uint(16) % sz]; -#elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return m_temp_constants; - else - expr * e = m_list_false[flip % sz]; -#else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; - expr * e = get_unsat_assertion(g, sz, pos); -#endif return get_unsat_constants_walksat(e); -#elif _FOCUS_ == 2 -#if _BFS_ - // I guess it was buggy ... - // unsigned int pos = flip % m_constants.size(); - unsigned int pos = flip % sz; -#else - // I guess it was buggy ... - // unsigned int pos = get_random_uint(16) % m_constants.size(); - unsigned int pos = get_random_uint(16) % sz; -#endif - return get_unsat_constants_crsat(g, sz, pos); -#else - return get_unsat_constants_gsat(g, sz); -#endif } + else + return get_unsat_constants_gsat(as); } - expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) { - unsigned sz = g->size(); - + expr * get_unsat_assertion(ptr_vector const & as) { + unsigned sz = as.size(); if (sz == 1) { - if (m_mpz_manager.eq(get_value(g->form(0)), m_zero)) - return g->form(0); + if (m_mpz_manager.neq(get_value(as[0]), m_one)) + return as[0]; else return 0; } - m_temp_constants.reset(); -#if _FOCUS_ == 1 -#if _UCT_ + unsigned pos = -1; - value_score vscore; -#if _PROBABILISTIC_UCT_ - double sum_score = 0.0; - unsigned start_index = get_random_uint(16) % sz; - - for (unsigned i = start_index; i < sz; i++) + if (m_ucb) { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score + _UCT_EPS_; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } - for (unsigned i = 0; i < start_index; i++) - { - expr * e = g->form(i); - vscore = m_scores.find(e); -#if _PROBABILISTIC_UCT_ == 2 - double q = vscore.score * vscore.score + _UCT_EPS_; -#else - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; -#endif - if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) { - sum_score += q; - if (rand() <= (q * RAND_MAX / sum_score) + 1) - pos = i; - } - } -#else - double max = -1.0; + value_score vscore; + double max = -1.0; for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); + expr * e = as[i]; // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); -#if _UCT_ == 1 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched); -#elif _UCT_ == 2 - double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; -#elif _UCT_ == 3 + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); +#if _UCT_ == 3 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); #endif - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } -#endif - if (pos == static_cast(-1)) - return 0; + if (pos == static_cast(-1)) + return 0; -#if _UCT_ == 1 || _UCT_ == 3 - m_scores.find(g->form(pos)).touched++; - m_touched++; -#elif _UCT_ == 2 - m_scores.find(g->form(pos)).touched = flip; -#endif + m_scores.find(as[pos]).touched++; + m_touched++; // return m_list_false[pos]; - return g->form(pos); - -#elif _BFS_ == 3 - unsigned int pos = -1; - double max = -1.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _BFS_ == 2 - unsigned int pos = -1; - double min = 2.0; - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - double q = get_score(e); - if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; } } - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _BFS_ == 1 - unsigned int pos = flip % sz; - return get_unsat_assertion(g, sz, pos); -#elif _UNIFORM_RANDOM_ - unsigned cnt_unsat = 0, pos = -1; - for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; - if (pos == static_cast(-1)) - return 0; - return g->form(pos); -#elif _REAL_RS_ + else + { + unsigned cnt_unsat = 0; + for (unsigned i = 0; i < sz; i++) + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; + if (pos == static_cast(-1)) + return 0; + } + + return as[pos]; +#if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; sz = m_where_false.size(); if (sz == 0) return 0; return m_list_false[get_random_uint(16) % sz]; -#elif _REAL_PBFS_ - //unsigned pos = m_false_list[flip % m_cnt_false]; - //expr * e = get_unsat_assertion(g, sz, pos); - //expr * e = m_unsat_expr[flip % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return0; - else - return m_list_false[flip % sz]; -#else - unsigned int pos = get_random_uint(16) % sz; - return get_unsat_assertion(g, sz, pos); -#endif - return g->form(pos); -#elif _FOCUS_ == 2 -#if _BFS_ - unsigned int pos = flip % sz; -#else - unsigned int pos = get_random_uint(16) % sz; -#endif - return get_unsat_constants_crsat(g, sz, pos); #endif } - expr * get_new_unsat_assertion(goal_ref const & g, expr * e) { - unsigned sz = g->size(); - + expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + unsigned sz = as.size(); if (sz == 1) return 0; - m_temp_constants.reset(); - + unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i; + if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; if (pos == static_cast(-1)) return 0; - return g->form(pos); + return as[pos]; } }; From fb18547a5f12be7db71b04aea7198df2c5dcfad7 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 01:07:30 +0100 Subject: [PATCH 223/646] Fixed bug with VNS repick. --- src/tactic/sls/sls_compilation_settings.h | 2 +- src/tactic/sls/sls_engine.cpp | 22 +++++++++++++++++----- src/tactic/sls/sls_tracker.h | 7 ++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 9add78daa..a649bc9ed 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -23,7 +23,7 @@ Notes: #define _SLS_COMPILATION_SETTINGS_H_ // shall we use addition/subtraction? -#define _USE_ADDSUB_ 0 +#define _USE_ADDSUB_ 1 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index c240a0c51..af8ae1df2 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_base = p.restart_base(); m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. + if (m_walksat_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); + if (m_vns_repick && !m_walksat) + NOT_IMPLEMENTED_YET(); } void sls_engine::checkpoint() { @@ -435,19 +441,25 @@ lbool sls_engine::search() { if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); - /*if (m_vns_repick && (new_const == static_cast(-1))) + if (m_vns_repick && (new_const == static_cast(-1))) { - expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e); + expr * q = m_tracker.get_new_unsat_assertion(m_assertions); if (q) { - ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e); + ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move); + + if (new_const != static_cast(-1)) { + func_decl * fd = to_evaluate2[new_const]; + score = serious_score(fd, new_value); + continue; + } } - }*/ + } if (new_const == static_cast(-1)) { score = old_score; - if (m_walksat && m_walksat_repick) + if (m_walksat_repick) m_evaluator.randomize_local(m_assertions); else m_evaluator.randomize_local(to_evaluate); diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 65011dc8d..7b48057d4 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -76,7 +76,7 @@ private: ptr_vector m_constants; ptr_vector m_temp_constants; occ_type m_constants_occ; - + unsigned m_last_pos; unsigned m_walksat; unsigned m_ucb; double m_ucb_constant; @@ -1082,6 +1082,7 @@ public: return 0; } + m_last_pos = pos; return as[pos]; #if _REAL_RS_ //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; @@ -1093,7 +1094,7 @@ public: #endif } - expr * get_new_unsat_assertion(ptr_vector const & as, expr * e) { + expr * get_new_unsat_assertion(ptr_vector const & as) { unsigned sz = as.size(); if (sz == 1) return 0; @@ -1101,7 +1102,7 @@ public: unsigned cnt_unsat = 0, pos = -1; for (unsigned i = 0; i < sz; i++) - if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i; + if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; if (pos == static_cast(-1)) return 0; From ca1e3c3d9fe5974fbd2f358a40b6319250131ef2 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Tue, 22 Apr 2014 16:10:44 +0100 Subject: [PATCH 224/646] Backup before I touch early pruning ... --- src/tactic/sls/sls_compilation_settings.h | 3 --- src/tactic/sls/sls_engine.cpp | 30 +++++++++++++---------- src/tactic/sls/sls_engine.h | 1 + src/tactic/sls/sls_evaluator.h | 4 +-- src/tactic/sls/sls_tracker.h | 9 ------- 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index a649bc9ed..5c837b4b2 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,9 +22,6 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? #define _REAL_RS_ 0 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index af8ae1df2..5d4df237e 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) { m_walksat = p.walksat(); m_walksat_repick = p.walksat_repick(); m_paws_sp = p.paws_sp(); + m_paws = m_paws_sp < 1024; m_wp = p.wp(); m_vns_mc = p.vns_mc(); m_vns_repick = p.vns_repick(); @@ -173,7 +174,6 @@ bool sls_engine::what_if( // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { - m_tracker.reset_equal_scores(); best_score = r; best_const = fd_inx; m_mpz_manager.set(best_value, temp); @@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); else { -#if _USE_ADDSUB_ if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; move_type mt = (move_type)rnd_mv; // inversion doesn't make sense, let's do a flip instead. if (mt == MV_INV) mt = MV_FLIP; -#else - move_type mt = MV_FLIP; -#endif unsigned bit = 0; switch (mt) @@ -308,8 +304,9 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - m_tracker.reset_equal_scores(); - + //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); + //for (unsigned j = 0; j < to_evaluate.size(); j++) { + //unsigned i = (j + offset) % to_evaluate.size(); for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); @@ -328,7 +325,6 @@ double sls_engine::find_best_move( } if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ if (!m_mpz_manager.is_even(old_value)) { // for odd values, try +1 mk_inc(bv_sz, old_value, temp); @@ -341,7 +337,6 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_DEC; } -#endif // try inverting mk_inv(bv_sz, old_value, temp); if (what_if(fd, i, temp, new_score, best_const, best_value)) @@ -418,7 +413,7 @@ lbool sls_engine::search() { #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); #endif - + // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) { @@ -426,6 +421,7 @@ lbool sls_engine::search() { goto bailout; } + // random walk with probability wp / 1024 if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); @@ -436,14 +432,18 @@ lbool sls_engine::search() { old_score = score; new_const = (unsigned)-1; + // find best increasing move score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move); + // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously if (m_vns_mc && (new_const == static_cast(-1))) score = find_best_move_mc(to_evaluate, score, new_const, new_value); + // repick assertion if no increasing move was found previously if (m_vns_repick && (new_const == static_cast(-1))) { expr * q = m_tracker.get_new_unsat_assertion(m_assertions); + // only apply if another unsatisfied assertion actually exists if (q) { ptr_vector & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q); @@ -457,6 +457,7 @@ lbool sls_engine::search() { } } + // randomize if no increasing move was found if (new_const == static_cast(-1)) { score = old_score; if (m_walksat_repick) @@ -466,16 +467,19 @@ lbool sls_engine::search() { score = m_tracker.get_top_sum() / m_assertions.size(); - if (m_paws_sp < 1024) + // update assertion weights if a weigthing is enabled (sp < 1024) + if (m_paws) { for (unsigned i = 0; i < sz; i++) { expr * q = m_assertions[i]; + // smooth weights with probability sp / 1024 if (m_tracker.get_random_uint(10) < m_paws_sp) { if (m_mpz_manager.eq(m_tracker.get_value(q),m_one)) m_tracker.decrease_weight(q); } + // increase weights otherwise else { if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero)) @@ -484,6 +488,7 @@ lbool sls_engine::search() { } } } + // otherwise, apply most increasing move else { func_decl * fd = to_evaluate[new_const]; score = serious_score(fd, new_value); @@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; @@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { - /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter. + /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter. I leave the other versions as comments in case you want to try it again somewhen. #if _RESTART_SCHEME_ == 5 m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ff0e55f24..94f3fa626 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -76,6 +76,7 @@ protected: unsigned m_wp; unsigned m_vns_mc; unsigned m_vns_repick; + unsigned m_paws; unsigned m_paws_sp; unsigned m_restart_base; unsigned m_restart_next; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 37bfa5a2d..200a0e380 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -37,9 +37,7 @@ class sls_evaluator { powers & m_powers; expr_ref_buffer m_temp_exprs; vector > m_traversal_stack; -#if _EARLY_PRUNE_ vector > m_traversal_stack_bool; -#endif public: sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : @@ -753,7 +751,7 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); - // should always have uplinks ... + // Andreas: Should actually always have uplinks ... if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 7b48057d4..a815c9ad3 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -92,7 +92,6 @@ private: #endif obj_map m_weights; double m_top_sum; - unsigned m_equal_scores; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -148,14 +147,6 @@ public: return sum / count; } - void reset_equal_scores() { - m_equal_scores = 1; - } - - unsigned inc_equal_scores() { - return ++m_equal_scores; - } - inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); } From 80c94ef0b63efe68d125fb7f6548da4630313db8 Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Wed, 23 Apr 2014 14:52:18 +0100 Subject: [PATCH 225/646] Moved parameters to the right file. Almost clean. --- src/tactic/sls/sls_compilation_settings.h | 5 +-- src/tactic/sls/sls_engine.cpp | 38 +++++++++++------------ src/tactic/sls/sls_engine.h | 3 +- src/tactic/sls/sls_evaluator.h | 5 --- src/tactic/sls/sls_params.pyg | 6 +--- src/tactic/sls/sls_tracker.h | 33 +++++++++----------- 6 files changed, 36 insertions(+), 54 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 5c837b4b2..707802cf4 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -22,10 +22,7 @@ Notes: #ifndef _SLS_COMPILATION_SETTINGS_H_ #define _SLS_COMPILATION_SETTINGS_H_ -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? +// should we use unsat-structures as done in SLS 4 SAT? #define _REAL_RS_ 0 -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - #endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5d4df237e..a1c72609c 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_next = m_restart_base; m_restart_init = p.restart_init(); + m_early_prune = p.early_prune(); + // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) NOT_IMPLEMENTED_YET(); @@ -117,7 +119,7 @@ double sls_engine::top_score() { m_tracker.set_top_sum(top_sum); - return top_sum / (double)sz; + return top_sum; } double sls_engine::rescore() { @@ -129,21 +131,21 @@ double sls_engine::rescore() { double sls_engine::serious_score(func_decl * fd, const mpz & new_value) { m_evaluator.serious_update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) { m_evaluator.update(fd, new_value); m_stats.m_incr_evals++; - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); } double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) { m_stats.m_incr_evals++; if (m_evaluator.update_prune(fd, new_value)) - return (m_tracker.get_top_sum() / m_assertions.size()); + return m_tracker.get_top_sum(); else - return 0.0; + return -DBL_MAX; } // checks whether the score outcome of a given move is better than the previous score @@ -160,11 +162,11 @@ bool sls_engine::what_if( m_mpz_manager.set(old_value, m_tracker.get_value(fd)); #endif -#if _EARLY_PRUNE_ - double r = incremental_score_prune(fd, temp); -#else - double r = incremental_score(fd, temp); -#endif + double r; + if (m_early_prune) + r = incremental_score_prune(fd, temp); + else + r = incremental_score(fd, temp); #ifdef Z3DEBUG TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << " --> " << r << std::endl;); @@ -342,11 +344,8 @@ double sls_engine::find_best_move( if (what_if(fd, i, temp, new_score, best_const, best_value)) move = MV_INV; } - // reset to what it was before - double check = incremental_score(fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double } } } - // reset to what it was before - double check = incremental_score(fd, old_value); + incremental_score(fd, old_value); } m_mpz_manager.del(old_value); @@ -408,7 +406,10 @@ lbool sls_engine::search() { checkpoint(); m_stats.m_moves++; if (m_stats.m_moves % m_restart_base == 0) + { m_tracker.ucb_forget(m_assertions); + //score = rescore(); + } #if _REAL_RS_ //m_tracker.debug_real(g, m_stats.m_moves); @@ -425,7 +426,7 @@ lbool sls_engine::search() { if (m_wp && m_tracker.get_random_uint(10) < m_wp) { mk_random_move(to_evaluate); - score = m_tracker.get_top_sum() / sz; + score = m_tracker.get_top_sum(); continue; } @@ -465,7 +466,7 @@ lbool sls_engine::search() { else m_evaluator.randomize_local(to_evaluate); - score = m_tracker.get_top_sum() / m_assertions.size(); + score = m_tracker.get_top_sum(); // update assertion weights if a weigthing is enabled (sp < 1024) if (m_paws) @@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { assert_expr(g->form(i)); verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; lbool res = operator()(); diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 94f3fa626..ac8610871 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -81,8 +81,7 @@ protected: unsigned m_restart_base; unsigned m_restart_next; unsigned m_restart_init; - - ptr_vector m_old_values; + unsigned m_early_prune; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index 200a0e380..e4cf3c466 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -554,9 +554,7 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); @@ -599,9 +597,6 @@ public: if (m_tracker.is_top_expr(cur)) m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); -#if _EARLY_PRUNE_ - m_tracker.set_score_prune(cur, new_score); -#endif if (m_tracker.has_uplinks(cur)) { ptr_vector & ups = m_tracker.get_uplinks(cur); for (unsigned j = 0; j < ups.size(); j++) { diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index bf5bd181a..98875b20d 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -8,19 +8,15 @@ def_module_params('sls', ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), - ('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'), ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), ('paws_init', UINT, 40, 'initial/minimum assertion weights'), ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), - ('wp', UINT, 100, 'random walk with probability wp / 1024'), + ('wp', UINT, 0, 'random walk with probability wp / 1024'), ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), - ('random_offset', BOOL, 1, 'use random offset for candidate evaluation'), - ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), - ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index a815c9ad3..507596273 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -44,11 +44,9 @@ class sls_tracker { unsynch_mpz_manager * m; mpz value; double score; -#if _EARLY_PRUNE_ double score_prune; unsigned has_pos_occ; unsigned has_neg_occ; -#endif unsigned distance; // max distance from any root unsigned touched; value_score & operator=(const value_score & other) { @@ -122,6 +120,7 @@ public: m_paws_init = p.paws_init(); } + /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. unsigned get_formula_size() { return m_scores.size(); } @@ -145,7 +144,7 @@ public: } return sum / count; - } + }*/ inline void adapt_top_sum(expr * e, double add, double sub) { m_top_sum += m_weights.find(e) * (add - sub); @@ -417,6 +416,8 @@ public: } } + /* Andreas: Used this at some point to have values for the non-top-level expressions. + However, it did not give better performance but even cause some additional m/o - is not used currently. void initialize_recursive(init_proc proc, expr_mark visited, expr * e) { if (m_manager.is_and(e) || m_manager.is_or(e)) { app * a = to_app(e); @@ -445,7 +446,7 @@ public: find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); expr_fast_mark1 visited; quick_for_each_expr(ffd_proc, visited, e); - } + }*/ void initialize(ptr_vector const & as) { init_proc proc(m_manager, *this); @@ -455,8 +456,6 @@ public: expr * e = as[i]; if (!m_top_expr.contains(e)) m_top_expr.insert(e); - else - printf("this is already in ...\n"); for_each_expr(proc, visited, e); } @@ -464,7 +463,6 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - // Andreas: Maybe not fully correct. ptr_vector t; m_constants_occ.insert_if_not_there(e, t); find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e)); @@ -488,15 +486,16 @@ public: for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; - if (!m_weights.contains(e)) + + // initialize weights + if (!m_weights.contains(e)) m_weights.insert(e, m_paws_init); + + // positive/negative occurences used for early pruning + setup_occs(as[i]); } -#if _EARLY_PRUNE_ - for (unsigned i = 0; i < sz; i++) - setup_occs(as[i]); -#endif - + // initialize ucb total touched value (individual ones are always initialized to 1) m_touched = m_ucb_init ? as.size() : 1; } @@ -738,7 +737,6 @@ public: SASSERT(!negated); app * a = to_app(n); expr * const * args = a->get_args(); - // Andreas: Seems to have no effect. Probably it is still too similar to the original version. double max = 0.0; for (unsigned i = 0; i < a->get_num_args(); i++) { double cur = get_score(args[i]); @@ -764,7 +762,6 @@ public: const mpz & v1 = get_value(arg1); if (negated) { - //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0; res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0; TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << m_mpz_manager.to_string(v1) << std::endl; ); @@ -1051,10 +1048,8 @@ public: // for (unsigned i = 0; i < m_where_false.size(); i++) { // expr * e = m_list_false[i]; vscore = m_scores.find(e); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); -#if _UCT_ == 3 - double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); -#endif + //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } } if (pos == static_cast(-1)) From 7d18a17bb38ca701a49a17595e926dd5edf7933a Mon Sep 17 00:00:00 2001 From: Andreas Froehlich Date: Fri, 25 Apr 2014 13:56:15 +0100 Subject: [PATCH 226/646] Cleaned up final SLS version. Enjoy! --- src/tactic/sls/sls_compilation_settings.h | 28 ---- src/tactic/sls/sls_engine.cpp | 43 ++++-- src/tactic/sls/sls_engine.h | 2 + src/tactic/sls/sls_evaluator.h | 8 +- src/tactic/sls/sls_params.pyg | 6 +- src/tactic/sls/sls_tracker.h | 153 ++++++++-------------- 6 files changed, 94 insertions(+), 146 deletions(-) diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h index 707802cf4..e69de29bb 100644 --- a/src/tactic/sls/sls_compilation_settings.h +++ b/src/tactic/sls/sls_compilation_settings.h @@ -1,28 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sls_compilation_constants.h - -Abstract: - - Stochastic Local Search (SLS) compilation constants - -Author: - - Christoph (cwinter) 2014-03-19 - -Notes: - - This file should go away completely once we have evaluated all options. - ---*/ - -#ifndef _SLS_COMPILATION_SETTINGS_H_ -#define _SLS_COMPILATION_SETTINGS_H_ - -// should we use unsat-structures as done in SLS 4 SAT? -#define _REAL_RS_ 0 - -#endif \ No newline at end of file diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index a1c72609c..269790902 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) { m_restart_init = p.restart_init(); m_early_prune = p.early_prune(); + m_random_offset = p.random_offset(); + m_rescore = p.rescore(); // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT. if (m_walksat_repick && !m_walksat) @@ -174,6 +176,9 @@ bool sls_engine::what_if( m_mpz_manager.del(old_value); #endif + // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection. + // r += 0.0001 * m_tracker.get_random_uint(8); + // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB. if (r > best_score) { best_score = r; @@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector & unsat_constants) { if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2; if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; + + // Andreas: The other option would be to scale the probability for flips according to the bit-width. + /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt); + rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3); + if (rnd_mv > 3) rnd_mv = 0; */ + move_type mt = (move_type)rnd_mv; - // inversion doesn't make sense, let's do a flip instead. + // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true? if (mt == MV_INV) mt = MV_FLIP; unsigned bit = 0; @@ -306,10 +317,13 @@ double sls_engine::find_best_move( unsigned bv_sz; double new_score = score; - //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size(); - //for (unsigned j = 0; j < to_evaluate.size(); j++) { - //unsigned i = (j + offset) % to_evaluate.size(); - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector & to_evaluate, double unsigned bv_sz; double new_score = score; - for (unsigned i = 0; i < to_evaluate.size(); i++) { + // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list. + unsigned sz = to_evaluate.size(); + unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0; + for (unsigned j = 0; j < sz; j++) { + unsigned i = j + offset; + if (i >= sz) i -= sz; + //for (unsigned i = 0; i < to_evaluate.size(); i++) { func_decl * fd = to_evaluate[i]; sort * srt = fd->get_range(); bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); @@ -405,15 +425,16 @@ lbool sls_engine::search() { while (check_restart(m_stats.m_moves)) { checkpoint(); m_stats.m_moves++; + + // Andreas: Every base restart interval ... if (m_stats.m_moves % m_restart_base == 0) { + // ... potentially smooth the touched counters ... m_tracker.ucb_forget(m_assertions); - //score = rescore(); + // ... or normalize the top-level score. + if (m_rescore) score = rescore(); } -#if _REAL_RS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif // get candidate variables ptr_vector & to_evaluate = m_tracker.get_unsat_constants(m_assertions); if (!to_evaluate.size()) @@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { for (unsigned i = 0; i < g->size(); i++) assert_expr(g->form(i)); - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - lbool res = operator()(); if (res == l_true) { diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index ac8610871..8158808fa 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -82,6 +82,8 @@ protected: unsigned m_restart_next; unsigned m_restart_init; unsigned m_early_prune; + unsigned m_random_offset; + unsigned m_rescore; typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type; diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h index e4cf3c466..61afb7457 100644 --- a/src/tactic/sls/sls_evaluator.h +++ b/src/tactic/sls/sls_evaluator.h @@ -22,7 +22,6 @@ Notes: #include"model_evaluator.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" #include"sls_tracker.h" @@ -540,19 +539,16 @@ public: (*this)(to_app(cur), new_value); m_tracker.set_value(cur, new_value); -#if _REAL_RS_ + new_score = m_tracker.score(cur); if (m_tracker.is_top_expr(cur)) { + m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); if (m_mpz_manager.eq(new_value,m_one)) m_tracker.make_assertion(cur); else m_tracker.break_assertion(cur); } -#endif - new_score = m_tracker.score(cur); - if (m_tracker.is_top_expr(cur)) - m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur)); m_tracker.set_score(cur, new_score); m_tracker.set_score_prune(cur, new_score); diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index 98875b20d..ad7a22675 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -8,15 +8,19 @@ def_module_params('sls', ('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'), ('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'), ('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'), + ('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'), ('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'), ('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'), ('paws_init', UINT, 40, 'initial/minimum assertion weights'), ('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'), - ('wp', UINT, 0, 'random walk with probability wp / 1024'), + ('wp', UINT, 100, 'random walk with probability wp / 1024'), ('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'), ('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'), ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), + ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), + ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') )) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 507596273..4356bcc9b 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -80,14 +80,13 @@ private: double m_ucb_constant; unsigned m_ucb_init; double m_ucb_forget; + double m_ucb_noise; unsigned m_touched; double m_scale_unsat; unsigned m_paws_init; -#if _REAL_RS_ - ptr_vector m_unsat_expr; obj_map m_where_false; expr** m_list_false; -#endif + unsigned m_track_unsat; obj_map m_weights; double m_top_sum; @@ -116,8 +115,12 @@ public: m_ucb_constant = p.walksat_ucb_constant(); m_ucb_init = p.walksat_ucb_init(); m_ucb_forget = p.walksat_ucb_forget(); + m_ucb_noise = p.walksat_ucb_noise(); m_scale_unsat = p.scale_unsat(); m_paws_init = p.paws_init(); + // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy. + // If you want to use it, you will also need to change comments in the assertion selection. + m_track_unsat = 0;//p.track_unsat(); } /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently. @@ -254,53 +257,6 @@ public: return m_uplinks.find(n); } -#if _REAL_RS_ - void debug_real(goal_ref const & g, unsigned flip) - { - unsigned count = 0; - for (unsigned i = 0; i < g->size(); i++) - { - expr * e = g->form(i); - if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size()); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e)) - { - printf("iteration %d: ", flip); - printf("form %d is unsat but not in unsat list\n", i); - exit(4); - } - - if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e)) - { - unsigned pos = m_where_false.find(e); - expr * q = m_list_false[pos]; - if (q != e) - { - printf("iteration %d: ", flip); - printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos); - exit(4); - } - } - - if (m_mpz_manager.eq(get_value(e),m_zero)) - count++; - } - - // should be true now that duplicate assertions are removed - if (count != m_where_false.size()) - { - printf("iteration %d: ", flip); - printf("%d are unsat but list is of size %d\n", count, m_where_false.size()); - exit(4); - } - } -#endif - inline void ucb_forget(ptr_vector & as) { if (m_ucb_forget < 1.0) { @@ -474,14 +430,15 @@ public: TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); ); -#if _REAL_RS_ - m_list_false = new expr*[sz]; - //for (unsigned i = 0; i < sz; i++) - //{ - // if (m_mpz_manager.eq(get_value(g->form(i)),m_zero)) - // break_assertion(g->form(i)); - //} -#endif + if (m_track_unsat) + { + m_list_false = new expr*[sz]; + for (unsigned i = 0; i < sz; i++) + { + if (m_mpz_manager.eq(get_value(as[i]), m_zero)) + break_assertion(as[i]); + } + } for (unsigned i = 0; i < sz; i++) { @@ -515,44 +472,36 @@ public: return m_weights.find(e); } -#if _REAL_RS_ void make_assertion(expr * e) { - if (m_where_false.contains(e)) + if (m_track_unsat) { - unsigned pos = m_where_false.find(e); - m_where_false.erase(e); - if (pos != m_where_false.size()) + if (m_where_false.contains(e)) { - expr * q = m_list_false[m_where_false.size()]; - m_list_false[pos] = q; - m_where_false.find(q) = pos; - //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos); + unsigned pos = m_where_false.find(e); + m_where_false.erase(e); + if (pos != m_where_false.size()) + { + expr * q = m_list_false[m_where_false.size()]; + m_list_false[pos] = q; + m_where_false.find(q) = pos; + } } - //else - //printf("Erasing %d from %d to %d\n", e, pos); -// m_list_false[m_where_false.size()] = 0; -// printf("Going in %d\n", m_where_false.size()); } - //if (m_unsat_expr.contains(e)) - //m_unsat_expr.erase(e); } void break_assertion(expr * e) { - //printf("I'm broken... that's still fine.\n"); - if (!m_where_false.contains(e)) + if (m_track_unsat) { - //printf("This however is not so cool...\n"); - unsigned pos = m_where_false.size(); - m_list_false[pos] = e; - m_where_false.insert(e, pos); - // printf("Going in %d\n", m_where_false.size()); + if (!m_where_false.contains(e)) + { + unsigned pos = m_where_false.size(); + m_list_false[pos] = e; + m_where_false.insert(e, pos); + } } - //if (!m_unsat_expr.contains(e)) - //m_unsat_expr.push_back(e); } -#endif void show_model(std::ostream & out) { unsigned sz = get_num_constants(); @@ -1043,24 +992,38 @@ public: { value_score vscore; double max = -1.0; + // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit. + /* for (unsigned i = 0; i < m_where_false.size(); i++) { + expr * e = m_list_false[i]; */ for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; -// for (unsigned i = 0; i < m_where_false.size(); i++) { -// expr * e = m_list_false[i]; - vscore = m_scores.find(e); - //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); - double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); - if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; } + if (m_mpz_manager.neq(get_value(e), m_one)) + { + vscore = m_scores.find(e); + // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise. + // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched); + double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); + if (q > max) { max = q; pos = i; } + } } if (pos == static_cast(-1)) return 0; - m_scores.find(as[pos]).touched++; m_touched++; -// return m_list_false[pos]; + m_scores.find(as[pos]).touched++; + // Andreas: Also part of track_unsat data structures. Additionally disable the previous line! + /* m_last_pos = pos; + m_scores.find(m_list_false[pos]).touched++; + return m_list_false[pos]; */ } else { + // Andreas: The track_unsat data structures for random assertion selection. + /* sz = m_where_false.size(); + if (sz == 0) + return 0; + return m_list_false[get_random_uint(16) % sz]; */ + unsigned cnt_unsat = 0; for (unsigned i = 0; i < sz; i++) if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i; @@ -1070,14 +1033,6 @@ public: m_last_pos = pos; return as[pos]; -#if _REAL_RS_ - //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false]; - //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()]; - sz = m_where_false.size(); - if (sz == 0) - return 0; - return m_list_false[get_random_uint(16) % sz]; -#endif } expr * get_new_unsat_assertion(ptr_vector const & as) { From 992d150b8180c8d0e5b059e3c4c186f35dae7d7c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 17:17:47 +0100 Subject: [PATCH 227/646] BVSLS comments Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_params.pyg | 2 +- src/tactic/sls/sls_tracker.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg index ad7a22675..bf5bd181a 100644 --- a/src/tactic/sls/sls_params.pyg +++ b/src/tactic/sls/sls_params.pyg @@ -19,7 +19,7 @@ def_module_params('sls', ('restart_base', UINT, 100, 'base restart interval given by moves per run'), ('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'), ('early_prune', BOOL, 1, 'use early pruning for score prediction'), - ('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'), + ('random_offset', BOOL, 1, 'use random offset for candidate evaluation'), ('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'), ('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'), ('random_seed', UINT, 0, 'random seed') diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 4356bcc9b..d58f94af2 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -831,7 +831,9 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF. + // Precondition: Assertion set is in NNF. + // Also: careful about the unsat assertion scaling further down. + if (m_manager.is_and(child) || m_manager.is_or(child)) NOT_IMPLEMENTED_YET(); res = score_bool(child, true); } From bec5938d9c06be6512ab2df49134ce33d09c0eb2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:03:35 +0100 Subject: [PATCH 228/646] removed unused file Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_compilation_settings.h | 0 src/tactic/sls/sls_engine.cpp | 1 - src/tactic/sls/sls_engine.h | 1 - src/tactic/sls/sls_tracker.h | 1 - 4 files changed, 3 deletions(-) delete mode 100644 src/tactic/sls/sls_compilation_settings.h diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 269790902..67dba0237 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -27,7 +27,6 @@ Notes: #include"cooperate.h" #include"luby.h" -#include"sls_compilation_settings.h" #include"sls_params.hpp" #include"sls_engine.h" diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8158808fa..8a8a57e0e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -24,7 +24,6 @@ Notes: #include"model_converter.h" #include"goal.h" -#include"sls_compilation_settings.h" #include"sls_tracker.h" #include"sls_evaluator.h" diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index d58f94af2..186fae250 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,7 +25,6 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" -#include"sls_compilation_settings.h" #include"sls_powers.h" class sls_tracker { From 7a7566f39e183f8cc5cbe9f1ae251f96aafc1e6f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 18:11:30 +0100 Subject: [PATCH 229/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 186fae250..73355197a 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -25,6 +25,7 @@ Notes: #include"bv_decl_plugin.h" #include"model.h" +#include"sls_params.hpp" #include"sls_powers.h" class sls_tracker { @@ -1052,4 +1053,4 @@ public: } }; -#endif \ No newline at end of file +#endif From 7105e4d213ded77b3be3e8d9ea13b0a40076f0fa Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:49:35 +0100 Subject: [PATCH 230/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h index 8a8a57e0e..b056c438e 100644 --- a/src/tactic/sls/sls_engine.h +++ b/src/tactic/sls/sls_engine.h @@ -136,8 +136,8 @@ protected: void mk_random_move(ptr_vector & unsat_constants); - //inline double get_restart_armin(unsigned cnt_restarts); - inline unsigned check_restart(unsigned curr_value); + //double get_restart_armin(unsigned cnt_restarts); + unsigned check_restart(unsigned curr_value); }; #endif From 0016ba5f3e768d2669dc41a3b951b5d34269d329 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 21:54:08 +0100 Subject: [PATCH 231/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 67dba0237..5b32e5790 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,6 +16,7 @@ Author: Notes: --*/ +#include #include #include"map.h" From 8745872d28db43740c5e3fe029375f1a3cf1ba36 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 25 Apr 2014 22:03:26 +0100 Subject: [PATCH 232/646] compilation fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 5b32e5790..c0c319ab4 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -581,7 +581,7 @@ lbool sls_engine::operator()() { } /* Andreas: Needed for Armin's restart scheme if we don't want to use loops. -inline double sls_engine::get_restart_armin(unsigned cnt_restarts) +double sls_engine::get_restart_armin(unsigned cnt_restarts) { unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; @@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts) } */ -inline unsigned sls_engine::check_restart(unsigned curr_value) +unsigned sls_engine::check_restart(unsigned curr_value) { if (curr_value > m_restart_next) { From 85ff954bc6d4f87ecb5adbf2063980fbe0eb879f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 11 Sep 2014 00:27:37 +0100 Subject: [PATCH 233/646] merge fix Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tactic.cpp | 1413 +-------------------------------- 1 file changed, 30 insertions(+), 1383 deletions(-) diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 6e1102dd2..9bbed20bb 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -16,1378 +16,30 @@ Author: Notes: --*/ -#include -#include"map.h" #include"nnf.h" -#include"cooperate.h" -#include"ast_smt2_pp.h" -#include"ast_pp.h" -#include"var_subst.h" -#include"model_pp.h" -#include"model_evaluator.h" #include"solve_eqs_tactic.h" -#include"elim_uncnstr_tactic.h" #include"bv_size_reduction_tactic.h" #include"max_bv_sharing_tactic.h" #include"simplify_tactic.h" -#include"stopwatch.h" #include"propagate_values_tactic.h" -#include"sls_tactic.h" +#include"ctx_simplify_tactic.h" +#include"elim_uncnstr_tactic.h" #include"nnf_tactic.h" -#include"luby.h" -#include "ctx_simplify_tactic.h" - -// which unsatisfied assertion is selected? only works with _FOCUS_ > 0 -// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score -#define _BFS_ 0 - -// how many terms are considered for variable selection? -// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom -#define _FOCUS_ 1 - -// probability of choosing the same assertion again in the next step -#define _PERC_STICKY_ 0 - -// do we use dirty unit propagation to get rid of nested top level assertions? -#define _DIRTY_UP_ 1 - -// do we use restarts? -// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time -#define _RESTARTS_ 3 -// limit of moves/plateaus/seconds until first restart occurs -#define _RESTART_LIMIT_ 10 -// 0 = initialize with all zero, 1 initialize with random value -#define _RESTART_INIT_ 0 -// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat -#define _RESTART_SCHEME_ 1 -// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3 -#define _RESTART_CONST_ARMIN_ 4.0 - -// timelimit -#define _TIMELIMIT_ 3600 - -// should score of conjunctions be calculated by average rather than max? -#define _SCORE_AND_AVG_ 0 - -// should score of discunctions be calculated by multiplication of the inverse score rather than min? -#define _SCORE_OR_MUL_ 0 - -// do we use some kind of variable neighbourhood-search? -// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained -#define _VNS_ 0 - -// do we reduce the score of unsatisfied literals? -// 0 = no -// 1 = yes, by multiplying it with some factor -// 2 = yes, by squaring it -// 3 = yes, by setting it to zero -// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!) -#define _WEIGHT_DIST_ 1 - -// the factor used for _WEIGHT_DIST_ = 1 -#define _WEIGHT_DIST_FACTOR_ 0.5 - -// shall we toggle the weight after each restart? -#define _WEIGHT_TOGGLE_ 0 - -// do we use intensification steps in local minima? if so, how many? -#define _INTENSIFICATION_ 0 -#define _INTENSIFICATION_TRIES_ 0 - -// what is the percentage of random moves in plateaus (instead of full randomization)? -#define _PERC_PLATEAU_MOVES_ 0 - -// shall we repick clause when randomizing in a plateau or use the current one? -#define _REPICK_ 1 - -// do we use some UCT-like scheme for assertion-selection? overrides _BFS_ -#define _UCT_ 1 - -// how much diversification is used in the UCT-scheme? -#define _UCT_CONSTANT_ 20.0 - -// is uct clause selection probabilistic similar to variable selection in sparrow? -// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score -#define _PROBABILISTIC_UCT_ 0 - -// additive constants for probabilistic uct > 0 -#define _UCT_EPS_ 0.0001 - -// shall we reset _UCT_ touched values after restart? -#define _UCT_RESET_ 0 - -// do we gradually reduce the touched values of _UCT_? -#define _UCT_FORGET_ 0 -#define _UCT_FORGET_FACTOR_ 0.5 - -// how shall we initialize the _UCT_ total touched counter? -// 0 = initialize with one, 1 = initialize with number of assertions -#define _UCT_INIT_ 0 - -// shall we use addition/subtraction? -#define _USE_ADDSUB_ 1 - -// shall we try multilication and division by 2? -#define _USE_MUL2DIV2_ 0 - -// shall we try multiplication by 3? -#define _USE_MUL3_ 0 - -// shall we try unary minus (= inverting and incrementing) -#define _USE_UNARY_MINUS_ 0 - -// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0 -#define _UNIFORM_RANDOM_ 0 - -// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection? -#define _REAL_RS_ 0 -#define _REAL_PBFS_ 0 - -// how many bits do we neglect in each iteration? -#define _SKIP_BITS_ 0 - -// when randomizing local, what is the probability for changing a single bit? -// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage -#define _PERC_CHANGE_ 0 - -// do we use random steps for noise? -// 0 = no, 1 = randomize local, 2 = make random move -#define _TYPE_RSTEP_ 0 - -// with what probability _PERM_STEP_/1000 will the random step happen? -#define _PERM_RSTEP_ 0 - -// shall we use early pruning for incremental update? -#define _EARLY_PRUNE_ 1 - -// shall we use caching for top_score? -#define _CACHE_TOP_SCORE_ 1 - - -#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) - InvalidConfiguration; -#endif -#if (_PROBABILISTIC_UCT_ && !_UCT_) - InvalidConfiguration; -#endif -#if (_PERM_RSTEP_ && !_TYPE_RSTEP_) - InvalidConfiguration; -#endif -#if (_PERC_CHANGE_ == 50) - InvalidConfiguration; -#endif -#if (_PERC_STICKY_ && !_FOCUS_) - InvalidConfiguration; -#endif - +#include"stopwatch.h" +#include"sls_tactic.h" #include"sls_params.hpp" -#include"sls_evaluator.h" -#include"sls_tracker.h" +#include"sls_engine.h" -class sls_tactic : public tactic { - class stats { - public: - unsigned m_restarts; - stopwatch m_stopwatch; - unsigned m_full_evals; - unsigned m_incr_evals; - unsigned m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s; - - stats() : - m_restarts(0), - m_full_evals(0), - m_incr_evals(0), - m_moves(0), - m_umins(0), - m_mul2s(0), - m_mul3s(0), - m_div2s(0), - m_flips(0), - m_incs(0), - m_decs(0), - m_invs(0) { - m_stopwatch.reset(); - m_stopwatch.start(); - } - void reset() { - m_full_evals = m_flips = m_incr_evals = 0; - m_stopwatch.reset(); - m_stopwatch.start(); - } - }; - - struct imp { - ast_manager & m_manager; - stats & m_stats; - unsynch_mpz_manager m_mpz_manager; - powers m_powers; - mpz m_zero, m_one, m_two; - bool m_produce_models; - volatile bool m_cancel; - bv_util m_bv_util; - sls_tracker m_tracker; - sls_evaluator m_evaluator; - - unsigned m_restart_limit; - unsigned m_max_restarts; - unsigned m_plateau_limit; - - ptr_vector m_old_values; - - typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type; - - imp(ast_manager & m, params_ref const & p, stats & s) : - m_manager(m), - m_stats(s), - m_powers(m_mpz_manager), - m_zero(m_mpz_manager.mk_z(0)), - m_one(m_mpz_manager.mk_z(1)), - m_two(m_mpz_manager.mk_z(2)), - m_cancel(false), - m_bv_util(m), - m_tracker(m, m_bv_util, m_mpz_manager, m_powers), - m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) - { - updt_params(p); - } - - ~imp() { - m_mpz_manager.del(m_zero); - m_mpz_manager.del(m_one); - m_mpz_manager.del(m_two); - } - - double get_restart_armin(unsigned cnt_restarts) - { - unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts)); - unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2; - //printf("armin: %f\n", pow(1.1, inner_id + 1)); - return pow(_RESTART_CONST_ARMIN_, inner_id + 1); - } - - inline unsigned check_restart(unsigned curr_value) - { - if (curr_value > m_restart_limit) - { -#if _RESTART_SCHEME_ == 5 - m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts)); -#elif _RESTART_SCHEME_ == 4 - m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1); -#elif _RESTART_SCHEME_ == 3 - m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 2 - m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_; -#elif _RESTART_SCHEME_ == 1 - if (m_stats.m_restarts & 1) - m_restart_limit += _RESTART_LIMIT_; - else - m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_; -#else - m_restart_limit += _RESTART_LIMIT_; -#endif -#if _WEIGHT_TOGGLE_ - printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1)); -#endif - return 0; - } - return 1; - } - - ast_manager & m() const { return m_manager; } - - void set_cancel(bool f) { m_cancel = f; } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - - static void collect_param_descrs(param_descrs & r) { - sls_params::collect_param_descrs(r); - } - - void updt_params(params_ref const & _p) { - sls_params p(_p); - m_produce_models = _p.get_bool("model", false); - m_max_restarts = p.restarts(); - m_tracker.set_random_seed(p.random_seed()); - m_plateau_limit = p.plateau_limit(); - } - - void checkpoint() { - if (m_cancel) - throw tactic_exception(TACTIC_CANCELED_MSG); - cooperate("sls"); - } - - bool full_eval(goal_ref const & g, model & mdl) { - bool res = true; - - unsigned sz = g->size(); - for (unsigned i = 0; i < sz && res; i++) { - checkpoint(); - expr_ref o(m_manager); - - if (!mdl.eval(g->form(i), o, true)) - exit(ERR_INTERNAL_FATAL); - - res = m_manager.is_true(o.get()); - } - - TRACE("sls", tout << "Evaluation: " << res << std::endl;); - - return res; - } - - double top_score(goal_ref const & g) { - #if 0 - double min = m_tracker.get_score(g->form(0)); - unsigned sz = g->size(); - for (unsigned i = 1; i < sz; i++) { - double q = m_tracker.get_score(g->form(i)); - if (q < min) min = q; - } - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " MIN: " << min << std::endl; ); - return min; - #else - double top_sum = 0.0; - unsigned sz = g->size(); - for (unsigned i = 0; i < sz; i++) { - expr * e = g->form(i); - top_sum += m_tracker.get_score(e); - } - - TRACE("sls_top", tout << "Score distribution:"; - for (unsigned i = 0; i < sz; i++) - tout << " " << m_tracker.get_score(g->form(i)); - tout << " AVG: " << top_sum / (double) sz << std::endl; ); - -#if _CACHE_TOP_SCORE_ - m_tracker.set_top_sum(top_sum); -#endif - - return top_sum / (double) sz; - #endif - } - - double rescore(goal_ref const & g) { - m_evaluator.update_all(); - m_stats.m_full_evals++; - return top_score(g); - } - - double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.serious_update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - - double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_evaluator.update(fd, new_value); - m_stats.m_incr_evals++; -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - } - -#if _EARLY_PRUNE_ - double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) { - m_stats.m_incr_evals++; - if (m_evaluator.update_prune(fd, new_value)) -#if _CACHE_TOP_SCORE_ - return (m_tracker.get_top_sum() / g->size()); -#else - return top_score(g); -#endif - else - return 0.0; - } -#endif - - // checks whether the score outcome of a given move is better than the previous score - bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - - #ifdef Z3DEBUG - mpz old_value; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - #endif - -#if _EARLY_PRUNE_ - double r = incremental_score_prune(g, fd, temp); -#else - double r = incremental_score(g, fd, temp); -#endif - #ifdef Z3DEBUG - TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << - " --> " << r << std::endl; ); - - m_mpz_manager.del(old_value); - #endif - -// if (r >= best_score) { - if (r > best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // same as what_if, but only applied to the score of a specific atom, not the total score - bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, - double & best_score, unsigned & best_const, mpz & best_value) { - m_evaluator.update(fd, temp); - double r = m_tracker.get_score(e); - if (r >= best_score) { - best_score = r; - best_const = fd_inx; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.add(old_value, add_value, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - - } - - // Andreas: do we really need all those temporary mpzs? - void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) { - mpz temp, mask, mask2; - m_mpz_manager.mul(old_value, m_two, temp); - m_mpz_manager.set(mask, m_powers(bv_sz)); - m_mpz_manager.bitwise_not(bv_sz, mask, mask2); - m_mpz_manager.bitwise_and(temp, mask2, result); - m_mpz_manager.del(temp); - m_mpz_manager.del(mask); - m_mpz_manager.del(mask2); - } - - void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) { - m_mpz_manager.div(old_value, m_two, result); - } - - void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) { - unsigned shift; - m_mpz_manager.add(old_value, m_one, incremented); - if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz) - m_mpz_manager.set(incremented, m_zero); - } - - void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) { - if (m_mpz_manager.is_zero(old_value)) { - m_mpz_manager.set(decremented, m_powers(bv_sz)); - m_mpz_manager.dec(decremented); - } - else - m_mpz_manager.sub(old_value, m_one, decremented); - } - - void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) { - m_mpz_manager.bitwise_not(bv_sz, old_value, inverted); - } - - void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) { - m_mpz_manager.set(flipped, m_zero); - - if (m_bv_util.is_bv_sort(s)) { - mpz mask; - m_mpz_manager.set(mask, m_powers(bit)); - m_mpz_manager.bitwise_xor(old_value, mask, flipped); - m_mpz_manager.del(mask); - } - else if (m_manager.is_bool(s)) - m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero); - else - NOT_IMPLEMENTED_YET(); - } - - void mk_random_move(ptr_vector & unsat_constants) - { - unsigned rnd_mv = 0; - unsigned ucc = unsat_constants.size(); - unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc; - func_decl * fd = unsat_constants[rc]; - - mpz new_value; - - sort * srt = fd->get_range(); - if (m_manager.is_bool(srt)) - m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero); - else - { -#if _USE_ADDSUB_ - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2; - if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++; - move_type mt = (move_type) rnd_mv; - - // inversion doesn't make sense, let's do a flip instead. - if (mt == MV_INV) mt = MV_FLIP; -#else - mt = MV_FLIP; -#endif - unsigned bit = 0; - - switch (mt) - { - case MV_FLIP: { - unsigned bv_sz = m_bv_util.get_bv_size(srt); - bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz; - mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value); - break; - } - case MV_INC: - mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_DEC: - mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - case MV_INV: - mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value); - break; - default: - NOT_IMPLEMENTED_YET(); - } - - TRACE("sls", tout << "Randomization candidates: "; - for (unsigned i = 0; i < unsat_constants.size(); i++) - tout << unsat_constants[i]->get_name() << ", "; - tout << std::endl; - tout << "Random move: "; - switch (mt) { - case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break; - case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break; - case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break; - case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break; - } - tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); ); - } - - m_evaluator.update(fd, new_value); - m_mpz_manager.del(new_value); - } - - void mk_random_move(goal_ref const & g) { - mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves)); - } - - // will use VNS to ignore some possible moves and increase the flips per second - double find_best_move_vns(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz, max_bv_sz = 0; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - if (max_bv_sz < bv_sz) max_bv_sz = bv_sz; - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - - // try to flip lsb - mk_flip(srt, old_value, 0, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = 0; - move = MV_FLIP; - } - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - - // we can either check the condition once in the beginning or check it repeatedly after every bit -#if _VNS_ == 1 - for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++) -#else - if (new_score <= score) - for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++) -#endif - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // What would happen if we flipped bit #j ? - if (j < bv_sz) - { - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - // reset to what it was before - double check = incremental_score(g, fd, old_value); - SASSERT(check == score); - } - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // finds the move that increased score the most. returns best_const = -1, if no increasing move exists. - double find_best_move(goal_ref const & g, ptr_vector & to_evaluate, double score, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; -#if _USE_MUL3_ || _USE_UNARY_MINUS_ - mpz temp2; -#endif - unsigned bv_sz; - double new_score = score; - - for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit -#if _SKIP_BITS_ - for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) { -#else - for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) { -#endif - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { -#if _USE_ADDSUB_ - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } -#endif - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - -#if _USE_UNARY_MINUS_ - mk_inc(bv_sz, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_UMIN; -#endif - -#if _USE_MUL2DIV2_ - // try multiplication by 2 - mk_mul2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_MUL2; - -#if _USE_MUL3_ - // try multiplication by 3 - mk_add(bv_sz, old_value, temp, temp2); - if (what_if(g, fd, i, temp2, new_score, best_const, best_value)) - move = MV_MUL3; -#endif - - // try division by 2 - mk_div2(bv_sz, old_value, temp); - if (what_if(g, fd, i, temp, new_score, best_const, best_value)) - move = MV_DIV2; -#endif - } - - // reset to what it was before - double check = incremental_score(g, fd, old_value); - // Andreas: does not hold anymore now that we use top level score caching - //SASSERT(check == score); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); -#if _USE_MUL3_ - m_mpz_manager.del(temp2); -#endif - return new_score; - } - - // same as find_best_move but only considers the score of the current expression instead of the overall score - double find_best_move_local(expr * e, ptr_vector & to_evaluate, - unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) { - mpz old_value, temp; - unsigned bv_sz; - double new_score = m_tracker.get_score(e); - // Andreas: tie breaking not implemented yet - // double tie_score = top_score(g); - for (unsigned i = 0; i < to_evaluate.size(); i++) { - func_decl * fd = to_evaluate[i]; - sort * srt = fd->get_range(); - bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - // first try to flip every bit - for (unsigned j = 0; j < bv_sz; j++) { - // What would happen if we flipped bit #i ? - mk_flip(srt, old_value, j, temp); - - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) { - new_bit = j; - move = MV_FLIP; - } - } - - if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) { - if (!m_mpz_manager.is_even(old_value)) { - // for odd values, try +1 - mk_inc(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INC; - } - else { - // for even values, try -1 - mk_dec(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_DEC; - } - - // try inverting - mk_inv(bv_sz, old_value, temp); - if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) - move = MV_INV; - } - - // reset to what it was before - m_evaluator.update(fd, old_value); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - return new_score; - } - - // first try of intensification ... does not seem to be efficient - bool handle_plateau(goal_ref const & g) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned pos = m_stats.m_moves % sz; -#else - unsigned pos = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, pos); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - for (unsigned i = 0; i < to_evaluate.size(); i++) - { - m_tracker.get_value(to_evaluate[i]); - m_old_values.push_back( & m_tracker.get_value(to_evaluate[i])); - } - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++) - { - // Andreas: Could be extended to use (best) score but this is computationally more expensive. - find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move); - - if (new_const == static_cast(-1)) { - // Andreas: Actually this should never happen. - NOT_IMPLEMENTED_YET(); - } else { - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - - m_evaluator.update(fd, new_value); - } - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - for (unsigned i = 0; i < to_evaluate.size(); i++) - m_tracker.set_value(to_evaluate[i], * m_old_values[i]); - - m_old_values.reset(); - - return 0; - } - - // what_if version needed in the context of 2nd intensification try, combining local and global score - bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, - double & best_score, mpz & best_value, unsigned i) { - - double global_score = incremental_score(g, fd, temp); - double local_score = m_tracker.get_score(e); - double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_; - - if (new_score >= best_score) { - best_score = new_score; - m_mpz_manager.set(best_value, temp); - return true; - } - - return false; - } - - // find_best_move version needed in the context of 2nd intensification try - double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i) - { - mpz old_value, temp; - double best_score = 0; - - sort * srt = fd->get_range(); - unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt); - m_mpz_manager.set(old_value, m_tracker.get_value(fd)); - - for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) { - mk_flip(srt, old_value, j, temp); - what_if(g, e, fd, temp, best_score, best_value, i); - } - - m_mpz_manager.del(old_value); - m_mpz_manager.del(temp); - - return best_score; - } - - // second try to use intensification ... also not very effective - bool handle_plateau(goal_ref const & g, double old_score) - { - unsigned sz = g->size(); -#if _BFS_ - unsigned new_const = m_stats.m_moves % sz; -#else - unsigned new_const = m_tracker.get_random_uint(16) % sz; -#endif - expr * e = m_tracker.get_unsat_assertion(g, sz, new_const); - if (!e) - return 0; - - expr * q = m_tracker.get_unsat_expression(e); - ptr_vector & to_evaluate = m_tracker.get_constants(q); - - new_const = m_tracker.get_random_uint(16) % to_evaluate.size(); - func_decl * fd = to_evaluate[new_const]; - - mpz new_value; - //m_mpz_manager.set(new_value, m_tracker.get_value(fd)); - unsigned new_bit = 0; - double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score; - - for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++) - { - new_score = find_best_move_local(g, q, fd, new_value, i); - - m_stats.m_moves++; - m_stats.m_flips++; - - global_score = incremental_score(g, fd, new_value); - local_score = m_tracker.get_score(q); - - SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_); - - if (m_mpz_manager.is_one(m_tracker.get_value(q))) - return 1; - } - - return 0; - } - - // main search loop - lbool search(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - unsigned plateau_cnt = 0; - - score = rescore(g); - unsigned sz = g->size(); -#if _PERC_STICKY_ - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - -#if _RESTARTS_ == 1 - while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 2 - while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#elif _RESTARTS_ == 3 - while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#endif - checkpoint(); - m_stats.m_moves++; - -#if _UCT_FORGET_ - if (m_stats.m_moves % _UCT_FORGET_ == 0) - m_tracker.uct_forget(g); -#endif - -#if _REAL_RS_ || _REAL_PBFS_ - //m_tracker.debug_real(g, m_stats.m_moves); -#endif - -#if _FOCUS_ -#if _PERC_STICKY_ - if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one)) - e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#else - expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); -#endif - if (!e) - { - res = l_true; - goto bailout; - } - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else - ptr_vector & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(to_evaluate); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(to_evaluate); -#endif -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } - continue; -#endif - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - old_score = score; - new_const = (unsigned)-1; - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - - if (new_const == static_cast(-1)) { - score = old_score; - plateau_cnt++; -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); - //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves); - //to_evaluate = m_tracker.get_unsat_constants_walksat(e); -#else -#if _PERC_PLATEAU_MOVES_ - if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_) - mk_random_move(to_evaluate); - else -#endif -#if _REPICK_ - m_evaluator.randomize_local(g, m_stats.m_moves); -#else - m_evaluator.randomize_local(to_evaluate); -#endif -#endif - -#if _CACHE_TOP_SCORE_ - score = m_tracker.get_top_sum() / g->size(); -#else - score = top_score(g); -#endif - } else { - func_decl * fd = to_evaluate[new_const]; -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - // main search loop - lbool search_old(goal_ref const & g) { - lbool res = l_undef; - double score = 0.0, old_score = 0.0; - unsigned new_const = (unsigned)-1, new_bit = 0; - mpz new_value; - move_type move; - - score = rescore(g); - TRACE("sls", tout << "Starting search, initial score = " << std::setprecision(32) << score << std::endl; - tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - - unsigned plateau_cnt = 0; - - // Andreas: Why do we only allow so few plateaus? -#if _RESTARTS_ - while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) { - //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) { -#else - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) { -#endif - do { - checkpoint(); - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif - -#if _TYPE_RSTEP_ - if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_) - { -#if _TYPE_RSTEP_ == 1 - m_evaluator.randomize_local(g, m_stats.m_moves); -#elif _TYPE_RSTEP_ == 2 - mk_random_move(g); -#endif - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } -#endif - old_score = score; - new_const = (unsigned)-1; - - ptr_vector & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves); - if (!to_evaluate.size()) - { - res = l_true; - goto bailout; - } - TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl; - for (unsigned i = 0 ; i < to_evaluate.size(); i++) - tout << to_evaluate[i]->get_name() << std::endl; ); - -#if _VNS_ - score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move); -#else - score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move); -#endif - if (new_const == static_cast(-1)) { - TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) { - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl; - }); - - TRACE("sls_max", m_tracker.show_model(tout); - tout << "Scores: " << std::endl; - for (unsigned i = 0; i < g->size(); i++) - tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << - m_tracker.get_score(g->form(i)) << std::endl; ); - // Andreas: If new_const == -1, shouldn't score = old_score anyway? - score = old_score; - } - else { - // Andreas: Why does randomizing not count as a move? (Now it does.) - m_stats.m_moves++; - func_decl * fd = to_evaluate[new_const]; - - TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: "; - switch (move) { - case MV_FLIP: - tout << "Flip"; - if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit; - break; - case MV_INC: - tout << "+1"; - break; - case MV_DEC: - tout << "-1"; - break; - case MV_INV: - tout << "NEG"; - break; - }; - tout << ") ; new score = " << std::setprecision(32) << score << std::endl; ); - - switch (move) { - case MV_FLIP: m_stats.m_flips++; break; - case MV_INC: m_stats.m_incs++; break; - case MV_DEC: m_stats.m_decs++; break; - case MV_INV: m_stats.m_invs++; break; - case MV_UMIN: m_stats.m_umins++; break; - case MV_MUL2: m_stats.m_mul2s++; break; - case MV_MUL3: m_stats.m_mul3s++; break; - case MV_DIV2: m_stats.m_div2s++; break; - } - -#if _REAL_RS_ || _REAL_PBFS_ - score = serious_score(g, fd, new_value); -#else - score = incremental_score(g, fd, new_value); -#endif - - TRACE("sls", tout << "Score distribution:"; - for (unsigned i = 0; i < g->size(); i++) - tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i)); - tout << " TOP: " << score << std::endl; ); - } - - if (score >= 0.99999) { -// if (score >= 1.0) { - // score could theoretically be imprecise. - // Andreas: it seems using top level score caching can make the score unprecise also in the other direction! - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - /* - if (m_stats.m_moves % 100 == 0) - { - verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl; - verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - }*/ - } - while (score > old_score && res == l_undef); - - // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant. - if (score != old_score) { - report_tactic_progress("This should not happen I guess.", plateau_cnt); - plateau_cnt = 0; - } else { - m_stats.m_moves++; - plateau_cnt++; - //report_tactic_progress("Plateau.", plateau_cnt); - // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway. - //if (plateau_cnt < m_plateau_limit) { - TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; ); -#if _INTENSIFICATION_ - handle_plateau(g, score); - //handle_plateau(g); -#else - m_evaluator.randomize_local(g, m_stats.m_moves); -#endif - //mk_random_move(g); - score = top_score(g); - - if (score >= 1.0) { - bool all_true = true; - for (unsigned i = 0; i < g->size() && all_true; i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - all_true=false; - if (all_true) { - res = l_true; // sat - goto bailout; - } else - TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;); - } - } - } - - bailout: - m_mpz_manager.del(new_value); - - return res; - } - - void operator()(goal_ref const & g, model_converter_ref & mc) { - if (g->inconsistent()) { - mc = 0; - return; - } - - verbose_stream() << "_BFS_ " << _BFS_ << std::endl; - verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl; - verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl; - verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl; - verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl; - verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl; - verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl; - verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl; - verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl; - verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl; - verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl; - verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl; - verbose_stream() << "_VNS_ " << _VNS_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl; - verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl; - verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl; - verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl; - verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl; - verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl; - verbose_stream() << "_UCT_ " << _UCT_ << std::endl; - verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl; - verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl; - verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl; - verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl; - verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl; - verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl; - verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl; - verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl; - verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl; - verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl; - verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl; - verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl; - verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl; - verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl; - verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl; - verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl; - verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl; - verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl; - verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl; - verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl; - -#if _WEIGHT_DIST_ == 4 - m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_); -#endif -#if _WEIGHT_TOGGLE_ - m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_); -#endif - m_tracker.initialize(g); - lbool res = l_undef; - - m_restart_limit = _RESTART_LIMIT_; - - do { - checkpoint(); - - report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts); - res = search(g); - - if (res == l_undef) - { -#if _RESTART_INIT_ - m_tracker.randomize(g); -#else - m_tracker.reset(g); -#endif - } - } - while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts); - - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; - - if (res == l_true) { - report_tactic_progress("Number of flips:", m_stats.m_moves); - for (unsigned i = 0; i < g->size(); i++) - if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i)))) - { - verbose_stream() << "Terminated before all assertions were SAT!" << std::endl; - NOT_IMPLEMENTED_YET(); - } - - if (m_produce_models) { - model_ref mdl = m_tracker.get_model(); - mc = model2model_converter(mdl.get()); - TRACE("sls_model", mc->display(tout); ); - } - g->reset(); - } - else - mc = 0; - } - }; - +class sls_tactic : public tactic { ast_manager & m; params_ref m_params; - imp * m_imp; - stats m_stats; + sls_engine * m_engine; public: sls_tactic(ast_manager & _m, params_ref const & p): m(_m), m_params(p) { - m_imp = alloc(imp, m, p, m_stats); + m_engine = alloc(sls_engine, m, p); } virtual tactic * translate(ast_manager & m) { @@ -1395,16 +47,16 @@ public: } virtual ~sls_tactic() { - dealloc(m_imp); + dealloc(m_engine); } virtual void updt_params(params_ref const & p) { m_params = p; - m_imp->updt_params(p); + m_engine->updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - imp::collect_param_descrs(r); + sls_params::collect_param_descrs(r); } virtual void operator()(goal_ref const & g, @@ -1412,14 +64,13 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - SASSERT(g->is_well_sorted()); - m_imp->m_produce_models = g->models_enabled(); + SASSERT(g->is_well_sorted()); mc = 0; pc = 0; core = 0; result.reset(); TRACE("sls", g->display(tout);); tactic_report report("sls", *g); - m_imp->operator()(g, mc); + m_engine->operator()(g, mc); g->inc_depth(); result.push_back(g.get()); @@ -1428,40 +79,36 @@ public: } virtual void cleanup() { - imp * d = m_imp; + sls_engine * d = alloc(sls_engine, m, m_params); #pragma omp critical (tactic_cancel) { - d = m_imp; + std::swap(d, m_engine); } dealloc(d); - d = alloc(imp, m, m_params, m_stats); - #pragma omp critical (tactic_cancel) - { - m_imp = d; - } } virtual void collect_statistics(statistics & st) const { - double seconds = m_stats.m_stopwatch.get_current_seconds(); - st.update("sls restarts", m_stats.m_restarts); - st.update("sls full evals", m_stats.m_full_evals); - st.update("sls incr evals", m_stats.m_incr_evals); - st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds); - st.update("sls FLIP moves", m_stats.m_flips); - st.update("sls INC moves", m_stats.m_incs); - st.update("sls DEC moves", m_stats.m_decs); - st.update("sls INV moves", m_stats.m_invs); - st.update("sls moves", m_stats.m_moves); - st.update("sls moves/sec", m_stats.m_moves / seconds); + sls_engine::stats const & stats = m_engine->get_stats(); + double seconds = stats.m_stopwatch.get_current_seconds(); + st.update("sls restarts", stats.m_restarts); + st.update("sls full evals", stats.m_full_evals); + st.update("sls incr evals", stats.m_incr_evals); + st.update("sls incr evals/sec", stats.m_incr_evals / seconds); + st.update("sls FLIP moves", stats.m_flips); + st.update("sls INC moves", stats.m_incs); + st.update("sls DEC moves", stats.m_decs); + st.update("sls INV moves", stats.m_invs); + st.update("sls moves", stats.m_moves); + st.update("sls moves/sec", stats.m_moves / seconds); } virtual void reset_statistics() { - m_stats.reset(); + m_engine->reset_statistics(); } virtual void set_cancel(bool f) { - if (m_imp) - m_imp->set_cancel(f); + if (m_engine) + m_engine->set_cancel(f); } }; From 168c3eb363e89b245cd4d36b3a7e744b3e979748 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 19 Dec 2014 12:32:57 +0000 Subject: [PATCH 234/646] BV-SLS optimization Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 73355197a..89ef57871 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -89,6 +89,7 @@ private: unsigned m_track_unsat; obj_map m_weights; double m_top_sum; + obj_hashtable m_temp_seen; public: sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) : @@ -440,6 +441,7 @@ public: } } + m_temp_seen.reset(); for (unsigned i = 0; i < sz; i++) { expr * e = as[i]; @@ -630,7 +632,14 @@ public: app * a = to_app(n); expr * const * args = a->get_args(); for (unsigned i = 0; i < a->get_num_args(); i++) - setup_occs(args[i]); + { + expr * child = args[i]; + if (!m_temp_seen.contains(child)) + { + setup_occs(child, false); + m_temp_seen.insert(child); + } + } } else if (m_manager.is_not(n)) { @@ -638,8 +647,7 @@ public: app * a = to_app(n); SASSERT(a->get_num_args() == 1); expr * child = a->get_arg(0); - if (m_manager.is_and(child) || m_manager.is_or(child)) - NOT_IMPLEMENTED_YET(); + SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child)); setup_occs(child, true); } else From 916ef815fabe999205a858cf27063a859b1b3dd9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 15:59:20 +0000 Subject: [PATCH 235/646] Disabled BV-SLS as default tactic in anticipation for integration with the unstable branch. Signed-off-by: Christoph M. Wintersteiger --- src/tactic/portfolio/default_tactic.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 53da9a159..5a5cbcf94 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -32,8 +32,7 @@ Notes: tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), mk_qfbv_sls_tactic(m), - // cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), From 58bf80f1138ffe356e603a76ebff8f8c8de6686b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 17:03:56 +0000 Subject: [PATCH 236/646] Cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/tactic/smtlogics/qfbv_tactic.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index a7870176d..3b4da2f2d 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -28,8 +28,6 @@ Notes: #include"bv_size_reduction_tactic.h" #include"aig_tactic.h" #include"sat_tactic.h" -//#include"nnf_tactic.h" -//#include"sls_tactic.h" #define MEMLIMIT 300 From f1a00da401ccd42155e3753bc83320e81b89b1bb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 12 Jan 2015 17:43:56 +0000 Subject: [PATCH 237/646] BV-SLS Cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/sat/tactic/sat_tactic.cpp | 2 -- src/tactic/portfolio/default_tactic.cpp | 1 - src/tactic/portfolio/smt_strategic_solver.cpp | 5 +--- src/tactic/smtlogics/qfbv_tactic.cpp | 26 ------------------- 4 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp index 717bf7007..677540991 100644 --- a/src/sat/tactic/sat_tactic.cpp +++ b/src/sat/tactic/sat_tactic.cpp @@ -66,8 +66,6 @@ class sat_tactic : public tactic { CASSERT("sat_solver", m_solver.check_invariant()); IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream());); TRACE("sat_dimacs", m_solver.display_dimacs(tout);); - //m_solver.display_dimacs(std::cerr); - //exit(0); lbool r = m_solver.check(); if (r == l_false) { diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 5a5cbcf94..9ecc16ecf 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -28,7 +28,6 @@ Notes: #include"probe_arith.h" #include"quant_tactics.h" #include"qffpa_tactic.h" -#include"sls_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index f63b4fd8c..ae79446e3 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,14 +37,11 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -#include"sls_tactic.h" - tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - // return mk_qfbv_tactic(m, p); - return mk_qfbv_sls_tactic(m, p); + return mk_qfbv_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index 3b4da2f2d..ac53ca0c8 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -93,32 +93,6 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { mk_sat_tactic(m)); #endif - /* use full sls - tactic * st = using_params(and_then(preamble_st, - cond(mk_is_qfbv_probe(), - cond(mk_is_qfbv_eq_probe(), - and_then(mk_bv1_blaster_tactic(m), - using_params(mk_smt_tactic(), solver_p)), - and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))), - mk_smt_tactic())), - main_p);*/ - - /* use pure dpll - tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), - and_then(mk_bit_blaster_tactic(m), - when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), - and_then(using_params(and_then(mk_simplify_tactic(m), - mk_solve_eqs_tactic(m)), - local_ctx_p), - if_no_proofs(cond(mk_produce_unsat_cores_probe(), - mk_aig_tactic(), - using_params(mk_aig_tactic(), - big_aig_p))))), - new_sat), - mk_smt_tactic())), - main_p);*/ - tactic * st = using_params(and_then(preamble_st, // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function // symbols. In this case, we should not use From dbc9bebd189bc168218b3cef30e203bb888c50d3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 15 Jan 2015 16:47:10 +0530 Subject: [PATCH 238/646] fix instance test Signed-off-by: Nikolaj Bjorner --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index db629cd2d..1414201b2 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -6183,7 +6183,7 @@ class Fixedpoint(Z3PPObject): """ query = _get_args(query) sz = len(query) - if sz >= 1 and isinstance(query[0], FuncDecl): + if sz >= 1 and isinstance(query[0], FuncDeclRef): _decls = (FuncDecl * sz)() i = 0 for q in query: From caafee0033bf3df860dff3c53694f42075c9978a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 15 Jan 2015 19:18:18 +0000 Subject: [PATCH 239/646] Added simplifier plugin for FP --- src/ast/simplifier/fpa_simplifier_plugin.cpp | 43 ++++++++++++++++++++ src/ast/simplifier/fpa_simplifier_plugin.h | 40 ++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 src/ast/simplifier/fpa_simplifier_plugin.cpp create mode 100644 src/ast/simplifier/fpa_simplifier_plugin.h diff --git a/src/ast/simplifier/fpa_simplifier_plugin.cpp b/src/ast/simplifier/fpa_simplifier_plugin.cpp new file mode 100644 index 000000000..d2f7a3e58 --- /dev/null +++ b/src/ast/simplifier/fpa_simplifier_plugin.cpp @@ -0,0 +1,43 @@ +/*++ +Copyright (c) 2015 Microsoft Corporation + +Module Name: + + fpa_simplifier_plugin.cpp + +Abstract: + + Simplifier for the floating-point theory + +Author: + + Christoph (cwinter) 2015-01-14 + +--*/ +#include"fpa_simplifier_plugin.h" + +fpa_simplifier_plugin::fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b) : +simplifier_plugin(symbol("fpa"), m), +m_util(m), +m_bsimp(b), +m_rw(m) {} + +fpa_simplifier_plugin::~fpa_simplifier_plugin() {} + +bool fpa_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { + set_reduce_invoked(); + + SASSERT(f->get_family_id() == get_family_id()); + /*switch (f->get_decl_kind()) { + case OP_FPA_FP: break; + }*/ + + return m_rw.mk_app_core(f, num_args, args, result) == BR_DONE; +} + +bool fpa_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & result) { + set_reduce_invoked(); + + return m_rw.mk_eq_core(lhs, rhs, result) == BR_DONE; +} + diff --git a/src/ast/simplifier/fpa_simplifier_plugin.h b/src/ast/simplifier/fpa_simplifier_plugin.h new file mode 100644 index 000000000..36e315737 --- /dev/null +++ b/src/ast/simplifier/fpa_simplifier_plugin.h @@ -0,0 +1,40 @@ +/*++ +Copyright (c) 2015 Microsoft Corporation + +Module Name: + + fpa_simplifier_plugin.h + +Abstract: + + Simplifier for the floating-point theory + +Author: + + Christoph (cwinter) 2015-01-14 + +--*/ +#ifndef _FPA_SIMPLIFIER_PLUGIN_H_ +#define _FPA_SIMPLIFIER_PLUGIN_H_ + +#include"basic_simplifier_plugin.h" +#include"fpa_decl_plugin.h" +#include"fpa_rewriter.h" + +class fpa_simplifier_plugin : public simplifier_plugin { + fpa_util m_util; + basic_simplifier_plugin & m_bsimp; + fpa_rewriter m_rw; + +public: + fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b); + ~fpa_simplifier_plugin(); + + + virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); + + virtual bool reduce_eq(expr * lhs, expr * rhs, expr_ref & result); + +}; + +#endif /* _FPA_SIMPLIFIER_PLUGIN_H_ */ From 5344d6f3c02f02aa980f916eb8ae09acba7ae81b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 15 Jan 2015 19:25:49 +0000 Subject: [PATCH 240/646] various bugfixes and extensions for FPA Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 237 ++++++------- src/ast/fpa/fpa2bv_converter.h | 16 +- src/ast/fpa/fpa2bv_rewriter.h | 10 +- src/ast/fpa_decl_plugin.cpp | 12 +- src/ast/fpa_decl_plugin.h | 7 +- src/ast/rewriter/fpa_rewriter.cpp | 10 +- src/smt/asserted_formulas.cpp | 4 +- src/smt/theory_fpa.cpp | 412 +++++++++++++--------- src/tactic/fpa/fpa2bv_model_converter.cpp | 2 +- src/tactic/fpa/qffp_tactic.cpp | 27 +- 10 files changed, 396 insertions(+), 341 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index f6ce259f2..4cdb64d8d 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -44,8 +44,8 @@ fpa2bv_converter::~fpa2bv_converter() { } void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { - SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_FPA_TO_FP)); - SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(a, m_plugin->get_family_id(), OP_FPA_FP)); + SASSERT(is_app_of(b, m_plugin->get_family_id(), OP_FPA_FP)); expr_ref sgn(m), s(m), e(m); m_simp.mk_eq(to_app(a)->get_arg(0), to_app(b)->get_arg(0), sgn); @@ -64,20 +64,20 @@ void fpa2bv_converter::mk_eq(expr * a, expr * b, expr_ref & result) { } void fpa2bv_converter::mk_ite(expr * c, expr * t, expr * f, expr_ref & result) { - SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FPA_TO_FP)); - SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(t, m_plugin->get_family_id(), OP_FPA_FP)); + SASSERT(is_app_of(f, m_plugin->get_family_id(), OP_FPA_FP)); expr *t_sgn, *t_sig, *t_exp; expr *f_sgn, *f_sig, *f_exp; - split_triple(t, t_sgn, t_sig, t_exp); - split_triple(f, f_sgn, f_sig, f_exp); + split_fp(t, t_sgn, t_exp, t_sig); + split_fp(f, f_sgn, f_exp, f_sig); expr_ref sgn(m), s(m), e(m); m_simp.mk_ite(c, t_sgn, f_sgn, sgn); m_simp.mk_ite(c, t_sig, f_sig, s); m_simp.mk_ite(c, t_exp, f_exp, e); - mk_triple(sgn, s, e, result); + mk_fp(sgn, e, s, result); } void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -111,7 +111,7 @@ void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * ar mk_bias(e, biased_exp); - mk_triple(bv_sgn, bv_sig, biased_exp, result); + mk_fp(bv_sgn, biased_exp, bv_sig, result); TRACE("fpa2bv_dbg", tout << "value of [" << sign << " " << m_mpz_manager.to_string(sig) << " " << exp << "] is " << mk_ismt2_pp(result, m) << std::endl;); @@ -158,7 +158,7 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { SASSERT(m_bv_util.get_bv_size(e) == ebits); #endif - mk_triple(sgn, s, e, result); + mk_fp(sgn, e, s, result); m_const2bv.insert(f, result); m.inc_ref(f); @@ -177,7 +177,7 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result) s = m.mk_var(base_inx + 1, m_bv_util.mk_sort(sbits-1)); e = m.mk_var(base_inx + 2, m_bv_util.mk_sort(ebits)); - mk_triple(sgn, s, e, result); + mk_fp(sgn, e, s, result); } void fpa2bv_converter::mk_uninterpreted_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result) @@ -191,7 +191,7 @@ void fpa2bv_converter::mk_uninterpreted_function(func_decl * f, unsigned num, ex if (is_float(args[i])) { expr * sgn, * sig, * exp; - split_triple(args[i], sgn, sig, exp); + split_fp(args[i], sgn, exp, sig); new_args.push_back(sgn); new_args.push_back(sig); new_args.push_back(exp); @@ -210,7 +210,7 @@ void fpa2bv_converter::mk_uninterpreted_function(func_decl * f, unsigned num, ex a_sgn = m.mk_app(fd3.f_sgn, new_args.size(), new_args.c_ptr()); a_sig = m.mk_app(fd3.f_sig, new_args.size(), new_args.c_ptr()); a_exp = m.mk_app(fd3.f_exp, new_args.size(), new_args.c_ptr()); - mk_triple(a_sgn, a_sig, a_exp, result); + mk_fp(a_sgn, a_exp, a_sig, result); } else { sort_ref_buffer new_domain(m); @@ -256,7 +256,7 @@ void fpa2bv_converter::mk_uninterpreted_function(func_decl * f, unsigned num, ex m.inc_ref(f_sgn); m.inc_ref(f_sig); m.inc_ref(f_exp); - mk_triple(a_sgn, a_sig, a_exp, result); + mk_fp(a_sgn, a_exp, a_sig, result); } } @@ -300,10 +300,10 @@ void fpa2bv_converter::mk_pinf(func_decl * f, expr_ref & result) { unsigned ebits = m_util.get_ebits(srt); expr_ref top_exp(m); mk_top_exp(ebits, top_exp); - mk_triple(m_bv_util.mk_numeral(0, 1), - m_bv_util.mk_numeral(0, sbits-1), - top_exp, - result); + mk_fp(m_bv_util.mk_numeral(0, 1), + top_exp, + m_bv_util.mk_numeral(0, sbits-1), + result); } void fpa2bv_converter::mk_ninf(func_decl * f, expr_ref & result) { @@ -313,10 +313,10 @@ void fpa2bv_converter::mk_ninf(func_decl * f, expr_ref & result) { unsigned ebits = m_util.get_ebits(srt); expr_ref top_exp(m); mk_top_exp(ebits, top_exp); - mk_triple(m_bv_util.mk_numeral(1, 1), - m_bv_util.mk_numeral(0, sbits-1), - top_exp, - result); + mk_fp(m_bv_util.mk_numeral(1, 1), + top_exp, + m_bv_util.mk_numeral(0, sbits-1), + result); } void fpa2bv_converter::mk_nan(func_decl * f, expr_ref & result) { @@ -326,10 +326,10 @@ void fpa2bv_converter::mk_nan(func_decl * f, expr_ref & result) { unsigned ebits = m_util.get_ebits(srt); expr_ref top_exp(m); mk_top_exp(ebits, top_exp); - mk_triple(m_bv_util.mk_numeral(0, 1), - m_bv_util.mk_numeral(1, sbits-1), - top_exp, - result); + mk_fp(m_bv_util.mk_numeral(0, 1), + top_exp, + m_bv_util.mk_numeral(1, sbits-1), + result); } void fpa2bv_converter::mk_nzero(func_decl *f, expr_ref & result) { @@ -339,10 +339,10 @@ void fpa2bv_converter::mk_nzero(func_decl *f, expr_ref & result) { unsigned ebits = m_util.get_ebits(srt); expr_ref bot_exp(m); mk_bot_exp(ebits, bot_exp); - mk_triple(m_bv_util.mk_numeral(1, 1), - m_bv_util.mk_numeral(0, sbits-1), - bot_exp, - result); + mk_fp(m_bv_util.mk_numeral(1, 1), + bot_exp, + m_bv_util.mk_numeral(0, sbits - 1), + result); } void fpa2bv_converter::mk_pzero(func_decl *f, expr_ref & result) { @@ -352,10 +352,10 @@ void fpa2bv_converter::mk_pzero(func_decl *f, expr_ref & result) { unsigned ebits = m_util.get_ebits(srt); expr_ref bot_exp(m); mk_bot_exp(ebits, bot_exp); - mk_triple(m_bv_util.mk_numeral(0, 1), - m_bv_util.mk_numeral(0, sbits-1), - bot_exp, - result); + mk_fp(m_bv_util.mk_numeral(0, 1), + bot_exp, + m_bv_util.mk_numeral(0, sbits-1), + result); } void fpa2bv_converter::add_core(unsigned sbits, unsigned ebits, expr_ref & rm, @@ -607,13 +607,13 @@ void fpa2bv_converter::mk_sub(func_decl * f, unsigned num, expr * const * args, void fpa2bv_converter::mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split_triple(args[0], sgn, s, e); + split_fp(args[0], sgn, e, s); expr_ref c(m), nsgn(m); mk_is_nan(args[0], c); nsgn = m_bv_util.mk_bv_not(sgn); expr_ref r_sgn(m); m_simp.mk_ite(c, sgn, nsgn, r_sgn); - mk_triple(r_sgn, s, e, result); + mk_fp(r_sgn, e, s, result); } void fpa2bv_converter::mk_mul(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -1027,8 +1027,8 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args, void fpa2bv_converter::mk_abs(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split_triple(args[0], sgn, s, e); - mk_triple(m_bv_util.mk_numeral(0, 1), s, e, result); + split_fp(args[0], sgn, e, s); + mk_fp(m_bv_util.mk_numeral(0, 1), e, s, result); } void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -1038,8 +1038,8 @@ void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split_triple(x, x_sgn, x_sig, x_exp); - split_triple(y, y_sgn, y_sig, y_exp); + split_fp(x, x_sgn, x_exp, x_sig); + split_fp(y, y_sgn, y_exp, y_sig); expr_ref c1(m), c2(m), x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), c1_and(m); mk_is_zero(x, x_is_zero); @@ -1071,7 +1071,7 @@ void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, m_simp.mk_ite(c2, x_exp, c3xy_exp, c2c3_exp); m_simp.mk_ite(c1, y_exp, c2c3_exp, r_exp); - mk_triple(r_sgn, r_sig, r_exp, result); + mk_fp(r_sgn, r_exp, r_sig, result); } void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -1081,8 +1081,8 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split_triple(x, x_sgn, x_sig, x_exp); - split_triple(y, y_sgn, y_sig, y_exp); + split_fp(x, x_sgn, x_exp, x_sig); + split_fp(y, y_sgn, y_exp, y_sig); expr_ref c1(m), c2(m), x_is_nan(m), y_is_nan(m), y_is_zero(m), x_is_zero(m), c1_and(m); mk_is_zero(y, y_is_zero); @@ -1114,7 +1114,7 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, m_simp.mk_ite(c2, x_exp, c3xy_exp, c2c3_exp); m_simp.mk_ite(c1, y_exp, c2c3_exp, r_exp); - mk_triple(r_sgn, r_sig, r_exp, result); + mk_fp(r_sgn, r_exp, r_sig, result); } void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -1689,8 +1689,8 @@ void fpa2bv_converter::mk_float_eq(func_decl * f, unsigned num, expr * const * a expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split_triple(x, x_sgn, x_sig, x_exp); - split_triple(y, y_sgn, y_sig, y_exp); + split_fp(x, x_sgn, x_exp, x_sig); + split_fp(y, y_sgn, y_exp, y_sig); expr_ref x_eq_y_sgn(m), x_eq_y_exp(m), x_eq_y_sig(m); m_simp.mk_eq(x_sgn, y_sgn, x_eq_y_sgn); @@ -1725,8 +1725,8 @@ void fpa2bv_converter::mk_float_lt(func_decl * f, unsigned num, expr * const * a expr * x_sgn, * x_sig, * x_exp; expr * y_sgn, * y_sig, * y_exp; - split_triple(x, x_sgn, x_sig, x_exp); - split_triple(y, y_sgn, y_sig, y_exp); + split_fp(x, x_sgn, x_exp, x_sig); + split_fp(y, y_sgn, y_exp, y_sig); expr_ref c3(m), t3(m), t4(m), one_1(m), nil_1(m); one_1 = m_bv_util.mk_numeral(1, 1); @@ -1863,10 +1863,10 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args int sz = m_bv_util.get_bv_size(bv); SASSERT((unsigned)sz == to_sbits + to_ebits); - mk_triple(m_bv_util.mk_extract(sz - 1, sz - 1, bv), - m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), - m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), - result); + mk_fp(m_bv_util.mk_extract(sz - 1, sz - 1, bv), + m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv), + m_bv_util.mk_extract(sz - to_ebits - 2, 0, bv), + result); } else if (num == 2 && m_bv_util.is_bv(args[0]) && @@ -1895,7 +1895,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args SASSERT(m_bv_util.get_bv_size(args[0]) == 1); SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); - mk_triple(args[0], args[2], args[1], result); + mk_fp(args[0], args[1], args[2], result); } else if (num == 3 && m_bv_util.is_bv(args[0]) && @@ -2061,6 +2061,8 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * TRACE("fpa2bv_to_fp_real", tout << "rm: " << mk_ismt2_pp(rm, m) << std::endl << "x: " << mk_ismt2_pp(x, m) << std::endl;); SASSERT(m_util.is_float(s)); + SASSERT(au().is_real(x)); + unsigned ebits = m_util.get_ebits(s); unsigned sbits = m_util.get_sbits(s); @@ -2093,11 +2095,9 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits); mk_bias(unbiased_exp, e); - mk_triple(sgn, s, e, result); + mk_fp(sgn, e, s, result); } - else { - NOT_IMPLEMENTED_YET(); - + else { mpf_manager & fm = fu().fm(); bv_util & bu = m_bv_util; arith_util & au = m_arith_util; @@ -2109,44 +2109,15 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * two = au.mk_numeral(rational(2), false); expr_ref sgn(m), sig(m), exp(m); - sgn = m.mk_ite(au.mk_lt(x, zero), bv1, bv0); - sig = bu.mk_numeral(0, sbits + 4); - mpz const & max_normal_exponent = fm.m_powers2.m1(ebits-1); - exp = bu.mk_numeral(max_normal_exponent, ebits); - - //expr_ref cur_s(m), cur_d(m), cur_r(m), cur_s2(m), bv1_s4(m); - //bv1_s4 = bu.mk_numeral(1, sbits + 4); - //cur_s = x; - //std::string trace_name; - //for (unsigned i = 0; i < sbits + 3; i++) { - // std::stringstream dbg_name; - // dbg_name << "fpa2bv_to_float_real_sig_" << i; - // dbg_decouple(dbg_name.str().c_str(), sig); + sgn = mk_fresh_const("fpa2bv_to_fp_real_sgn", 1); + sig = mk_fresh_const("fpa2bv_to_fp_real_sig", sbits + 4); + exp = mk_fresh_const("fpa2bv_to_fp_real_exp", ebits + 2); - // cur_s = au.mk_div(cur_s, two); - // // cur_r = au.mk_rem(cur_s, two); - // cur_r = au.mk_mod(cur_s, two); - // cur_s2 = bu.mk_bv_shl(sig, bv1_s4); - // sig = m.mk_ite(au.mk_eq(cur_r, zero), - // cur_s2, - // bu.mk_bv_add(cur_s2, bv1_s4)); - //} - //dbg_decouple("fpa2bv_to_float_real_last_cur_s", cur_s); - //expr_ref inc(m); - //inc = m.mk_not(m.mk_eq(cur_s, zero)); - //dbg_decouple("fpa2bv_to_float_real_inc", inc); - //sig = m.mk_ite(inc, bu.mk_bv_add(sig, bv1_s4), sig); - - //SASSERT(bu.get_bv_size(sgn) == 1); - //SASSERT(bu.get_bv_size(sig) == sbits + 4); - //SASSERT(bu.get_bv_size(exp) == ebits + 2); + expr_ref rme(rm, m); + round(s, rme, sgn, sig, exp, result); - //dbg_decouple("fpa2bv_to_float_real_sgn", sgn); - //dbg_decouple("fpa2bv_to_float_real_sig", sig); - //dbg_decouple("fpa2bv_to_float_real_exp", exp); - - //expr_ref rmr(rm, m); - //round(s, rmr, sgn, sig, exp, result); + expr * e = m.mk_eq(m_util.mk_to_real(result), x); + m_extra_assertions.push_back(e); } SASSERT(is_well_sorted(m, result)); @@ -2208,7 +2179,7 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); SASSERT(num == 1); SASSERT(f->get_num_parameters() == 0); - SASSERT(is_app_of(args[0], m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(args[0], m_plugin->get_family_id(), OP_FPA_FP)); expr * x = args[0]; sort * s = m.get_sort(x); @@ -2565,19 +2536,10 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split_triple(args[0], sgn, s, e); + split_fp(args[0], sgn, e, s); result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s); } -void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - SASSERT(num == 3); - SASSERT(m_bv_util.get_bv_size(args[0]) == 1); - SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); - SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); - mk_triple(args[0], args[2], args[1], result); - TRACE("fpa2bv_mk_fp", tout << "mk_fp result = " << mk_ismt2_pp(result, m) << std::endl;); -} - void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_ubv", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); @@ -2753,6 +2715,10 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg expr_ref sgn(m), sig(m), exp(m), lz(m); unpack(x, sgn, sig, exp, lz, true); + dbg_decouple("fpa2bv_to_sbv_sgn", sgn); + dbg_decouple("fpa2bv_to_sbv_sig", sig); + dbg_decouple("fpa2bv_to_sbv_exp", exp); + // x is of the form +- [1].[sig] * 2^(exp-lz) SASSERT(m_bv_util.get_bv_size(sgn) == 1); SASSERT(m_bv_util.get_bv_size(sig) == sbits); @@ -2777,8 +2743,8 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg SASSERT(m_bv_util.get_bv_size(shift) == ebits + 2); SASSERT(m_bv_util.get_bv_size(shift_neg) == ebits + 2); SASSERT(m_bv_util.get_bv_size(shift_abs) == ebits + 2); - dbg_decouple("fpa2bv_to_ubv_shift", shift); - dbg_decouple("fpa2bv_to_ubv_shift_abs", shift_abs); + dbg_decouple("fpa2bv_to_sbv_shift", shift); + dbg_decouple("fpa2bv_to_sbv_shift_abs", shift_abs); // sig is of the form +- [1].[sig][r][g][s] ... and at least bv_sz + 3 long // [1][ ... sig ... ][r][g][ ... s ...] @@ -2861,28 +2827,43 @@ expr_ref fpa2bv_converter::mk_to_real_unspecified() { return expr_ref(m_util.mk_internal_to_real_unspecified(), m); } -void fpa2bv_converter::split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); - SASSERT(to_app(e)->get_num_args() == 3); - +void fpa2bv_converter::mk_fp(expr * sign, expr * exponent, expr * significand, expr_ref & result) { + SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); + SASSERT(m_bv_util.is_bv(significand)); + SASSERT(m_bv_util.is_bv(exponent)); + result = m.mk_app(m_util.get_family_id(), OP_FPA_FP, sign, exponent, significand); +} + +void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 3); + SASSERT(m_bv_util.get_bv_size(args[0]) == 1); + SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2]) + 1); + SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); + mk_fp(args[0], args[1], args[2], result); + TRACE("fpa2bv_mk_fp", tout << "mk_fp result = " << mk_ismt2_pp(result, m) << std::endl;); +} + +void fpa2bv_converter::split_fp(expr * e, expr * & sgn, expr * & exp, expr * & sig) const { + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_FP)); + SASSERT(to_app(e)->get_num_args() == 3); sgn = to_app(e)->get_arg(0); exp = to_app(e)->get_arg(1); sig = to_app(e)->get_arg(2); } -void fpa2bv_converter::split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); +void fpa2bv_converter::split_fp(expr * e, expr_ref & sgn, expr_ref & exp, expr_ref & sig) const { + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr *e_sgn, *e_sig, *e_exp; - split_triple(e, e_sgn, e_sig, e_exp); + split_fp(e, e_sgn, e_exp, e_sig); sgn = e_sgn; - sig = e_sig; exp = e_exp; + sig = e_sig; } void fpa2bv_converter::mk_is_nan(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); // exp == 1^n , sig != 0 expr_ref sig_is_zero(m), sig_is_not_zero(m), exp_is_top(m), top_exp(m), zero(m); @@ -2897,7 +2878,7 @@ void fpa2bv_converter::mk_is_nan(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_inf(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref eq1(m), eq2(m), top_exp(m), zero(m); mk_top_exp(m_bv_util.get_bv_size(exp), top_exp); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(sig)); @@ -2921,7 +2902,7 @@ void fpa2bv_converter::mk_is_ninf(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref zero(m); @@ -2930,7 +2911,7 @@ void fpa2bv_converter::mk_is_pos(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_neg(expr * e, expr_ref & result) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_FP)); SASSERT(to_app(e)->get_num_args() == 3); expr * a0 = to_app(e)->get_arg(0); expr_ref one(m); @@ -2940,7 +2921,7 @@ void fpa2bv_converter::mk_is_neg(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_zero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref eq1(m), eq2(m), bot_exp(m), zero(m); mk_bot_exp(m_bv_util.get_bv_size(exp), bot_exp); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(sig)); @@ -2951,7 +2932,7 @@ void fpa2bv_converter::mk_is_zero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_nzero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref e_is_zero(m), eq(m), one_1(m); mk_is_zero(e, e_is_zero); one_1 = m_bv_util.mk_numeral(1, 1); @@ -2961,7 +2942,7 @@ void fpa2bv_converter::mk_is_nzero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_pzero(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref e_is_zero(m), eq(m), nil_1(m); mk_is_zero(e, e_is_zero); nil_1 = m_bv_util.mk_numeral(0, 1); @@ -2971,7 +2952,7 @@ void fpa2bv_converter::mk_is_pzero(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_denormal(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref zero(m); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(exp)); m_simp.mk_eq(exp, zero, result); @@ -2979,7 +2960,7 @@ void fpa2bv_converter::mk_is_denormal(expr * e, expr_ref & result) { void fpa2bv_converter::mk_is_normal(expr * e, expr_ref & result) { expr * sgn, * sig, * exp; - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); expr_ref is_special(m), is_denormal(m), p(m); mk_is_denormal(e, is_denormal); @@ -3093,7 +3074,7 @@ void fpa2bv_converter::mk_unbias(expr * e, expr_ref & result) { } void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp, expr_ref & lz, bool normalize) { - SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_TO_FP)); + SASSERT(is_app_of(e, m_plugin->get_family_id(), OP_FPA_FP)); SASSERT(to_app(e)->get_num_args() == 3); sort * srt = to_app(e)->get_decl()->get_range(); @@ -3101,7 +3082,11 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref unsigned sbits = m_util.get_sbits(srt); unsigned ebits = m_util.get_ebits(srt); - split_triple(e, sgn, sig, exp); + split_fp(e, sgn, exp, sig); + + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(exp) == ebits); + SASSERT(m_bv_util.get_bv_size(sig) == sbits-1); expr_ref is_normal(m); mk_is_normal(e, is_normal); @@ -3134,7 +3119,7 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref expr_ref shift(m); m_simp.mk_ite(is_sig_zero, zero_e, lz, shift); dbg_decouple("fpa2bv_unpack_shift", shift); - SASSERT(is_well_sorted(m, is_sig_zero)); + SASSERT(is_well_sorted(m, is_sig_zero)); SASSERT(is_well_sorted(m, shift)); SASSERT(m_bv_util.get_bv_size(shift) == ebits); if (ebits <= sbits) { @@ -3545,7 +3530,7 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & SASSERT(m_bv_util.get_bv_size(res_exp) == ebits); SASSERT(is_well_sorted(m, res_exp)); - mk_triple(res_sgn, res_sig, res_exp, result); + mk_fp(res_sgn, res_exp, res_sig, result); TRACE("fpa2bv_round", tout << "ROUND = " << mk_ismt2_pp(result, m) << std::endl; ); } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 062c56ef2..82fad6ff9 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -72,15 +72,11 @@ public: bool is_rm(sort * s) { return m_util.is_rm(s); } bool is_float_family(func_decl * f) { return f->get_family_id() == m_util.get_family_id(); } - void mk_triple(expr * sign, expr * significand, expr * exponent, expr_ref & result) { - SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1); - SASSERT(m_bv_util.is_bv(significand)); - SASSERT(m_bv_util.is_bv(exponent)); - result = m.mk_app(m_util.get_family_id(), OP_FPA_TO_FP, sign, exponent, significand); - } + void mk_fp(expr * sign, expr * exponent, expr * significand, expr_ref & result); + void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void split_triple(expr * e, expr * & sgn, expr * & sig, expr * & exp) const; - void split_triple(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref & exp) const; + void split_fp(expr * e, expr * & sgn, expr * & exp, expr * & sig) const; + void split_fp(expr * e, expr_ref & sgn, expr_ref & exp, expr_ref & sig) const; void mk_eq(expr * a, expr * b, expr_ref & result); void mk_ite(expr * c, expr * t, expr * f, expr_ref & result); @@ -125,9 +121,7 @@ public: void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - - void mk_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_is_subnormal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 75176c9c4..ed885a4cc 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -259,13 +259,13 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { unsigned ebits = m_conv.fu().get_ebits(s); unsigned sbits = m_conv.fu().get_sbits(s); new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits)); - m_conv.mk_triple(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var), - m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var), - m_conv.bu().mk_extract(ebits-1, 0, new_var), - new_exp); + m_conv.mk_fp(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var), + m_conv.bu().mk_extract(ebits - 1, 0, new_var), + m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var), + new_exp); } else - new_exp = m().mk_var(t->get_idx(), s); + new_exp = m().mk_var(t->get_idx(), s); result = new_exp; result_pr = 0; diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 9900812dd..8cf158604 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -72,7 +72,7 @@ func_decl * fpa_decl_plugin::mk_numeral_decl(mpf const & v) { parameter p(mk_id(v), true); SASSERT(p.is_external()); sort * s = mk_float_sort(v.get_ebits(), v.get_sbits()); - return m_manager->mk_const_decl(symbol("fpa"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p)); + return m_manager->mk_const_decl(symbol("fp.numeral"), s, func_decl_info(m_family_id, OP_FPA_NUM, 1, &p)); } app * fpa_decl_plugin::mk_numeral(mpf const & v) { @@ -131,6 +131,11 @@ bool fpa_decl_plugin::is_numeral(expr * n, mpf & val) { return false; } +bool fpa_decl_plugin::is_numeral(expr * n) { + scoped_mpf v(m_fm); + return is_numeral(n, v); +} + bool fpa_decl_plugin::is_rm_numeral(expr * n, mpf_rounding_mode & val) { if (is_app_of(n, m_family_id, OP_FPA_RM_NEAREST_TIES_TO_AWAY)) { val = MPF_ROUND_NEAREST_TAWAY; @@ -156,6 +161,11 @@ bool fpa_decl_plugin::is_rm_numeral(expr * n, mpf_rounding_mode & val) { return 0; } +bool fpa_decl_plugin::is_rm_numeral(expr * n) { + mpf_rounding_mode t; + return is_rm_numeral(n, t); +} + void fpa_decl_plugin::del(parameter const & p) { SASSERT(p.is_external()); recycled_id(p.get_ext_id()); diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index 24481d348..fc1521456 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -191,10 +191,10 @@ public: mpf_manager & fm() { return m_fm; } func_decl * mk_numeral_decl(mpf const & v); app * mk_numeral(mpf const & v); - bool is_numeral(expr * n) { return is_app_of(n, m_family_id, OP_FPA_NUM); } + bool is_numeral(expr * n); bool is_numeral(expr * n, mpf & val); bool is_rm_numeral(expr * n, mpf_rounding_mode & val); - bool is_rm_numeral(expr * n) { mpf_rounding_mode t; return is_rm_numeral(n, t); } + bool is_rm_numeral(expr * n); mpf const & get_value(unsigned id) const { SASSERT(m_value_table.contains(id)); @@ -322,8 +322,7 @@ public: app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_INF, arg1); } app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_ZERO, arg1); } app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NORMAL, arg1); } - app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_SUBNORMAL, arg1); } - app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } + app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_SUBNORMAL, arg1); } app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_POSITIVE, arg1); } app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FPA_IS_NEGATIVE, arg1); } diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index 915d25e50..ce7fe5ed6 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -131,7 +131,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const scoped_mpf v(m_util.fm()); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator()); result = m_util.mk_value(v); - m_util.fm().del(v); + m_util.fm().del(v); return BR_DONE; } else if (bu.is_numeral(args[0], r1, bvs1) && @@ -268,10 +268,8 @@ br_status fpa_rewriter::mk_abs(expr * arg1, expr_ref & result) { result = arg1; return BR_DONE; } - result = m().mk_ite(m_util.mk_is_sign_minus(arg1), - m_util.mk_neg(arg1), - arg1); - return BR_REWRITE2; + + return BR_FAILED; } br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) { @@ -565,7 +563,7 @@ br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & r1.is_one(), r3.to_mpq().numerator(), m_util.fm().unbias_exp(bvs2, biased_exp)); - TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;); + TRACE("fp_rewriter", tout << "simplified (fp ...) to " << m_util.fm().to_string(v) << std::endl;); result = m_util.mk_value(v); return BR_DONE; } diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 4775e44a4..1acfcdf57 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -22,6 +22,7 @@ Revision History: #include"arith_simplifier_plugin.h" #include"array_simplifier_plugin.h" #include"datatype_simplifier_plugin.h" +#include"fpa_simplifier_plugin.h" #include"bv_simplifier_plugin.h" #include"for_each_expr.h" #include"well_sorted.h" @@ -96,7 +97,8 @@ void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifie s.register_plugin(alloc(array_simplifier_plugin, m_manager, *bsimp, s, m_params)); bvsimp = alloc(bv_simplifier_plugin, m_manager, *bsimp, m_params); s.register_plugin(bvsimp); - s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp)); + s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp)); + s.register_plugin(alloc(fpa_simplifier_plugin, m_manager, *bsimp)); } void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, proof * const * prs) { diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 158622428..ac9bd5141 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -54,11 +54,11 @@ namespace smt { unsigned ebits = m_th.m_fpa_util.get_ebits(s); unsigned sbits = m_th.m_fpa_util.get_sbits(s); SASSERT(bv_sz == ebits + sbits); - m_th.m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), - m_bv_util.mk_extract(sbits - 2, 0, bv), - m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), - result); - + m_th.m_converter.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), + m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), + m_bv_util.mk_extract(sbits - 2, 0, bv), + result); + SASSERT(m_th.m_fpa_util.is_float(result)); m_const2bv.insert(f, result); m.inc_ref(f); m.inc_ref(result); @@ -97,62 +97,86 @@ namespace smt { } theory_fpa::~theory_fpa() - { + { ast_manager & m = get_manager(); dec_ref_map_values(m, m_conversions); dec_ref_map_values(m, m_wraps); - dec_ref_map_values(m, m_unwraps); + dec_ref_map_values(m, m_unwraps); } app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector & values) { - SASSERT(values.size() == 1); ast_manager & m = m_th.get_manager(); + TRACE("t_fpa_detail", for (unsigned i = 0; i < values.size(); i++) + tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;); + mpf_manager & mpfm = m_fu.fm(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); - unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); - - SASSERT(m_bu.get_bv_size(values[0]) == (m_ebits + m_sbits)); - + unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); app * result; - + scoped_mpz bias(mpzm); mpzm.power(mpz(2), m_ebits - 1, bias); mpzm.dec(bias); - rational all_rat(0); - scoped_mpz all_bits(mpzm); + scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); unsigned bv_sz; - bool r = m_bu.is_numeral(values[0], all_rat, bv_sz); - SASSERT(r); - SASSERT(bv_sz == (m_ebits+m_sbits)); - SASSERT(all_rat.is_int()); - mpzm.set(all_bits, all_rat.to_mpq().numerator()); - - scoped_mpz sgn_z(mpzm), sig_z(mpzm), exp_z(mpzm); - mpzm.machine_div2k(all_bits, m_ebits + m_sbits - 1, sgn_z); - mpzm.mod(all_bits, mpfm.m_powers2(m_ebits + m_sbits - 1), all_bits); + if (values.size() == 1) { + SASSERT(m_bu.is_bv(values[0])); + SASSERT(m_bu.get_bv_size(values[0]) == (m_ebits + m_sbits)); - mpzm.machine_div2k(all_bits, m_sbits - 1, exp_z); - mpzm.mod(all_bits, mpfm.m_powers2(m_sbits - 1), all_bits); - - mpzm.set(sig_z, all_bits); + rational all_r(0); + scoped_mpz all_z(mpzm); - TRACE("t_fpa_detail", tout << "sgn=" << mpzm.to_string(sgn_z) << " ; " << - "sig=" << mpzm.to_string(sig_z) << " ; " << - "exp=" << mpzm.to_string(exp_z) << std::endl;); + bool r = m_bu.is_numeral(values[0], all_r, bv_sz); + SASSERT(r); + SASSERT(bv_sz == (m_ebits + m_sbits)); + SASSERT(all_r.is_int()); + mpzm.set(all_z, all_r.to_mpq().numerator()); + + mpzm.machine_div2k(all_z, m_ebits + m_sbits - 1, sgn_z); + mpzm.mod(all_z, mpfm.m_powers2(m_ebits + m_sbits - 1), all_z); + + mpzm.machine_div2k(all_z, m_sbits - 1, exp_z); + mpzm.mod(all_z, mpfm.m_powers2(m_sbits - 1), all_z); + + mpzm.set(sig_z, all_z); + } + else if (values.size() == 3) { + rational sgn_r(0), exp_r(0), sig_r(0); + + bool r = m_bu.is_numeral(values[0], sgn_r, bv_sz); + SASSERT(r && bv_sz == 1); + r = m_bu.is_numeral(values[1], exp_r, bv_sz); + SASSERT(r && bv_sz == m_ebits); + r = m_bu.is_numeral(values[2], sig_r, bv_sz); + SASSERT(r && bv_sz == m_sbits - 1); + + SASSERT(sgn_r.to_mpq().denominator() == mpz(1)); + SASSERT(exp_r.to_mpq().denominator() == mpz(1)); + SASSERT(sig_r.to_mpq().denominator() == mpz(1)); + + mpzm.set(sgn_z, sgn_r.to_mpq().numerator()); + mpzm.set(exp_z, exp_r.to_mpq().numerator()); + mpzm.set(sig_z, sig_r.to_mpq().numerator()); + } + else + UNREACHABLE(); scoped_mpz exp_u = exp_z - bias; SASSERT(mpzm.is_int64(exp_u)); - scoped_mpf f(mpfm); + scoped_mpf f(mpfm); mpfm.set(f, m_ebits, m_sbits, mpzm.is_one(sgn_z), sig_z, mpzm.get_int64(exp_u)); result = m_fu.mk_value(f); TRACE("t_fpa", tout << "fpa_value_proc::mk_value [" << - mk_ismt2_pp(values[0], m) << "] --> " << - mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + mpzm.to_string(sgn_z) << "," << + mpzm.to_string(exp_z) << "," << + mpzm.to_string(sig_z) << "] --> " << + mk_ismt2_pp(result, m_th.get_manager()) << "\n";); + return result; } @@ -160,8 +184,8 @@ namespace smt { SASSERT(values.size() == 1); ast_manager & m = m_th.get_manager(); - TRACE("t_fpa", tout << "fpa_rm_value_proc::mk_value for: [" << - mk_ismt2_pp(values[0], m) << "]" << std::endl;); + TRACE("t_fpa_detail", for (unsigned i = 0; i < values.size(); i++) + tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;); app * result = 0; sort * s = m.get_sort(values[0]); @@ -199,42 +223,44 @@ namespace smt { if (!m_wraps.find(e_srt, w)) { SASSERT(!m_wraps.contains(e_srt)); - sort * bv_srt = 0; - + sort * bv_srt; if (m_converter.is_rm(e_srt)) bv_srt = m_bv_util.mk_sort(3); else { SASSERT(m_converter.is_float(e_srt)); unsigned ebits = m_fpa_util.get_ebits(e_srt); unsigned sbits = m_fpa_util.get_sbits(e_srt); - bv_srt = m_bv_util.mk_sort(ebits + sbits); + bv_srt = m_bv_util.mk_sort(ebits + sbits); } - w = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt); + w = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVWRAP, 0, 0, 1, &e_srt, bv_srt); m_wraps.insert(e_srt, w); - m.inc_ref(w); + m.inc_ref(w); } - return app_ref(m.mk_app(w, e), m); + app_ref res(m); + res = m.mk_app(w, e); + return res; } app_ref theory_fpa::unwrap(expr * e, sort * s) { SASSERT(!m_fpa_util.is_unwrap(e)); ast_manager & m = get_manager(); context & ctx = get_context(); - sort * e_srt = m.get_sort(e); + sort * bv_srt = m.get_sort(e); func_decl *u; - if (!m_unwraps.find(e_srt, u)) { - SASSERT(!m_unwraps.contains(e_srt)); - sort * bv_srt = m.get_sort(e); + if (!m_unwraps.find(bv_srt, u)) { + SASSERT(!m_unwraps.contains(bv_srt)); u = m.mk_func_decl(get_family_id(), OP_FPA_INTERNAL_BVUNWRAP, 0, 0, 1, &bv_srt, s); - m_unwraps.insert(s, u); + m_unwraps.insert(bv_srt, u); m.inc_ref(u); } - return app_ref(m.mk_app(u, e), m); + app_ref res(m); + res = m.mk_app(u, e); + return res; } expr_ref theory_fpa::convert_atom(expr * e) { @@ -244,55 +270,30 @@ namespace smt { m_rw(e, res); m_th_rw(res, res); SASSERT(is_app(res)); - SASSERT(m.is_bool(res)); + SASSERT(m.is_bool(res)); return res; } expr_ref theory_fpa::convert_term(expr * e) { - ast_manager & m = get_manager(); - TRACE("t_fpa_detail", tout << "converting: " << mk_ismt2_pp(e, m) << " sort is: " << mk_ismt2_pp(m.get_sort(e), m) << std::endl;); + ast_manager & m = get_manager(); context & ctx = get_context(); - expr_ref ec(m), res(m); + expr_ref e_conv(m), res(m); proof_ref pr(m); - m_rw(e, ec); + m_rw(e, e_conv); - SASSERT(is_app(ec)); - app_ref eca(to_app(ec), m); - TRACE("t_fpa_detail", tout << "eca = " << mk_ismt2_pp(eca, m) << " sort is: " << mk_ismt2_pp(m.get_sort(eca), m) << std::endl;); - - if (m_fpa_util.is_rm(e)) { - expr_ref bv_rm(m); - bv_rm = eca; - TRACE("t_fpa_detail", tout << "bvrm = " << mk_ismt2_pp(bv_rm, m) << " sort is: " << mk_ismt2_pp(m.get_sort(bv_rm), m) << std::endl;); - SASSERT(is_sort_of(m.get_sort(bv_rm), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(m_bv_util.get_bv_size(bv_rm) == 3); - m_th_rw(bv_rm, res); + if (m_fpa_util.is_rm(e)) { + SASSERT(is_sort_of(m.get_sort(e_conv), m_bv_util.get_family_id(), BV_SORT)); + SASSERT(m_bv_util.get_bv_size(e_conv) == 3); + m_th_rw(e_conv, res); } else if (m_fpa_util.is_float(e)) { - SASSERT(eca->get_family_id() == get_family_id()); - fpa_op_kind k = (fpa_op_kind)(eca->get_decl_kind()); - SASSERT(k == OP_FPA_TO_FP || k == OP_FPA_INTERNAL_BVUNWRAP); - switch (k) { - case OP_FPA_TO_FP: { - SASSERT(eca->get_num_args() == 3); - SASSERT(is_sort_of(m.get_sort(eca->get_arg(0)), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(eca->get_arg(1)), m_bv_util.get_family_id(), BV_SORT)); - SASSERT(is_sort_of(m.get_sort(eca->get_arg(2)), m_bv_util.get_family_id(), BV_SORT)); - - expr *sgn, *sig, *exp; - expr_ref s_sgn(m), s_sig(m), s_exp(m); - m_converter.split_triple(eca, sgn, sig, exp); - m_th_rw(sgn, s_sgn); - m_th_rw(sig, s_sig); - m_th_rw(exp, s_exp); - - m_converter.mk_triple(s_sgn, s_sig, s_exp, res); - break; - } - default: - res = eca; - } + expr_ref sgn(m), sig(m), exp(m); + m_converter.split_fp(e_conv, sgn, exp, sig); + m_th_rw(sgn); + m_th_rw(exp); + m_th_rw(sig); + m_converter.mk_fp(sgn, exp, sig, res); } else UNREACHABLE(); @@ -310,7 +311,7 @@ namespace smt { SASSERT(m_arith_util.is_real(e) || m_bv_util.is_bv(e)); - m_rw(e, res); + m_rw(e, res); m_th_rw(res, res); return res; } @@ -327,12 +328,13 @@ namespace smt { SASSERT(m_fpa_util.is_float(srt)); unsigned ebits = m_fpa_util.get_ebits(srt); unsigned sbits = m_fpa_util.get_sbits(srt); - expr * bv = to_app(e)->get_arg(0); - unsigned bv_sz = m_bv_util.get_bv_size(bv); - m_converter.mk_triple(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), - m_bv_util.mk_extract(sbits - 2, 0, bv), - m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), - res); + expr_ref bv(m); + bv = to_app(e)->get_arg(0); + unsigned bv_sz = m_bv_util.get_bv_size(bv); + m_converter.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv), + m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv), + m_bv_util.mk_extract(sbits - 2, 0, bv), + res); } return res; } @@ -342,7 +344,7 @@ namespace smt { ast_manager & m = get_manager(); context & ctx = get_context(); expr_ref res(m); - + if (m_conversions.contains(e)) { res = m_conversions.find(e); TRACE("t_fpa_detail", tout << "cached:" << std::endl; @@ -401,11 +403,12 @@ namespace smt { void theory_fpa::assert_cnstr(expr * e) { if (get_manager().is_true(e)) return; TRACE("t_fpa_detail", tout << "asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); - context& ctx = get_context(); + context & ctx = get_context(); ctx.internalize(e, false); literal lit(ctx.get_literal(e)); ctx.mark_as_relevant(lit); - ctx.mk_th_axiom(get_id(), 1, &lit); + ctx.mk_th_axiom(get_id(), 1, &lit); + TRACE("t_fpa_detail", tout << "done asserting " << mk_ismt2_pp(e, get_manager()) << "\n";); } void theory_fpa::attach_new_th_var(enode * n) { @@ -433,11 +436,10 @@ namespace smt { ctx.set_var_theory(l.var(), get_id()); expr_ref bv_atom(m); - bv_atom = convert(atom); + bv_atom = convert_atom(atom); SASSERT(is_app(bv_atom) && m.is_bool(bv_atom)); bv_atom = m.mk_and(bv_atom, mk_side_conditions()); - expr_ref atom_iff(m); assert_cnstr(m.mk_iff(atom, bv_atom)); return true; } @@ -447,7 +449,7 @@ namespace smt { context & ctx = get_context(); TRACE("t_fpa", tout << "internalizing term: " << mk_ismt2_pp(term, get_manager()) << "\n";); SASSERT(term->get_family_id() == get_family_id()); - SASSERT(!ctx.e_internalized(term)); + SASSERT(!ctx.e_internalized(term)); unsigned num_args = term->get_num_args(); for (unsigned i = 0; i < num_args; i++) @@ -455,7 +457,7 @@ namespace smt { enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true); - + if (is_attached_to_var(e)) return false; @@ -476,9 +478,9 @@ namespace smt { assert_cnstr(mk_side_conditions()); break; } - default: /* ignore */; + default: /* ignore */; } - + return true; } @@ -486,33 +488,33 @@ namespace smt { TRACE("t_fpa", tout << "apply sort cnstr for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); SASSERT(n->get_owner()->get_family_id() == get_family_id() || n->get_owner()->get_family_id() == null_theory_id); - SASSERT(s->get_family_id() == get_family_id()); + SASSERT(s->get_family_id() == get_family_id()); - if (!is_attached_to_var(n)) + if (!is_attached_to_var(n)) { attach_new_th_var(n); - ast_manager & m = get_manager(); - context & ctx = get_context(); + ast_manager & m = get_manager(); + context & ctx = get_context(); - app_ref owner(m); - sort_ref owner_sort(m); - owner = n->get_owner(); - owner_sort = m.get_sort(owner); + app_ref owner(m); + sort_ref owner_sort(m); + owner = n->get_owner(); + owner_sort = m.get_sort(owner); - if (m_fpa_util.is_rm(owner_sort)) { - // For every RM term, we need to make sure that it's - // associated bit-vector is within the valid range. - if (!m_fpa_util.is_unwrap(owner)) - { - expr_ref valid(m), limit(m); - limit = m_bv_util.mk_numeral(4, 3); - valid = m_bv_util.mk_ule(wrap(owner), limit); - assert_cnstr(valid); + if (m_fpa_util.is_rm(owner_sort)) { + // For every RM term, we need to make sure that it's + // associated bit-vector is within the valid range. + if (!m_fpa_util.is_unwrap(owner)) { + expr_ref valid(m), limit(m); + limit = m_bv_util.mk_numeral(4, 3); + valid = m_bv_util.mk_ule(wrap(owner), limit); + assert_cnstr(valid); + } } + + if (!ctx.relevancy() && !m_fpa_util.is_unwrap(owner)) + assert_cnstr(m.mk_eq(unwrap(wrap(owner), owner_sort), owner)); } - - if (!ctx.relevancy() && !m_fpa_util.is_unwrap(owner)) - assert_cnstr(m.mk_eq(unwrap(wrap(owner), owner_sort), owner)); } void theory_fpa::new_eq_eh(theory_var x, theory_var y) { @@ -527,36 +529,40 @@ namespace smt { bv_util & bu = m_bv_util; mpf_manager & mpfm = fu.fm(); - app * xe = get_enode(x)->get_owner(); - app * ye = get_enode(y)->get_owner(); + expr_ref xe(m), ye(m); + xe = get_enode(x)->get_owner(); + ye = get_enode(y)->get_owner(); if ((m.is_bool(xe) && m.is_bool(ye)) || (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) { - SASSERT(xe->get_decl()->get_family_id() == get_family_id()); + SASSERT(to_app(xe)->get_decl()->get_family_id() == get_family_id()); return; } - + expr_ref xc(m), yc(m); xc = convert(xe); yc = convert(ye); - + + TRACE("t_fpa_detail", tout << "xc=" << mk_ismt2_pp(xc, m) << std::endl; + tout << "yc=" << mk_ismt2_pp(yc, m) << std::endl;); + expr_ref c(m); - + if (fu.is_float(xe) && fu.is_float(ye)) { expr *x_sgn, *x_sig, *x_exp; - m_converter.split_triple(xc, x_sgn, x_sig, x_exp); + m_converter.split_fp(xc, x_sgn, x_exp, x_sig); expr *y_sgn, *y_sig, *y_exp; - m_converter.split_triple(yc, y_sgn, y_sig, y_exp); + m_converter.split_fp(yc, y_sgn, y_exp, y_sig); - c = m.mk_and(m.mk_eq(x_sgn, y_sgn), - m.mk_eq(x_sig, y_sig), - m.mk_eq(x_exp, y_exp)); + c = m.mk_eq(m_bv_util.mk_concat(m_bv_util.mk_concat(x_sgn, x_exp), x_sig), + m_bv_util.mk_concat(m_bv_util.mk_concat(y_sgn, y_exp), y_sig)); } else c = m.mk_eq(xc, yc); - - assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); + + m_th_rw(c); + assert_cnstr(m.mk_iff(m.mk_eq(xe, ye), c)); assert_cnstr(mk_side_conditions()); return; @@ -572,12 +578,13 @@ namespace smt { context & ctx = get_context(); mpf_manager & mpfm = m_fpa_util.fm(); - app * xe = get_enode(x)->get_owner(); - app * ye = get_enode(y)->get_owner(); + expr_ref xe(m), ye(m); + xe = get_enode(x)->get_owner(); + ye = get_enode(y)->get_owner(); if ((m.is_bool(xe) && m.is_bool(ye)) || (m_bv_util.is_bv(xe) && m_bv_util.is_bv(ye))) { - SASSERT(xe->get_decl()->get_family_id() == get_family_id()); + SASSERT(to_app(xe)->get_decl()->get_family_id() == get_family_id()); return; } @@ -590,18 +597,18 @@ namespace smt { if (m_fpa_util.is_float(xe) && m_fpa_util.is_float(ye)) { expr *x_sgn, *x_sig, *x_exp; - m_converter.split_triple(xc, x_sgn, x_sig, x_exp); + m_converter.split_fp(xc, x_sgn, x_exp, x_sig); expr *y_sgn, *y_sig, *y_exp; - m_converter.split_triple(yc, y_sgn, y_sig, y_exp); - - c = m.mk_or(m.mk_not(m.mk_eq(x_sgn, y_sgn)), - m.mk_not(m.mk_eq(x_sig, y_sig)), - m.mk_not(m.mk_eq(x_exp, y_exp))); + m_converter.split_fp(yc, y_sgn, y_exp, y_sig); + + c = m.mk_not(m.mk_eq(m_bv_util.mk_concat(m_bv_util.mk_concat(x_sgn, x_exp), x_sig), + m_bv_util.mk_concat(m_bv_util.mk_concat(y_sgn, y_exp), y_sig))); } else c = m.mk_not(m.mk_eq(xc, yc)); - assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); + m_th_rw(c); + assert_cnstr(m.mk_iff(m.mk_not(m.mk_eq(xe, ye)), c)); assert_cnstr(mk_side_conditions()); return; @@ -609,7 +616,7 @@ namespace smt { void theory_fpa::push_scope_eh() { theory::push_scope_eh(); - m_trail_stack.push_scope(); + m_trail_stack.push_scope(); } void theory_fpa::pop_scope_eh(unsigned num_scopes) { @@ -628,8 +635,10 @@ namespace smt { expr_ref converted(m); converted = m.mk_and(convert(e), mk_side_conditions()); - if (!is_true) converted = m.mk_not(converted); - assert_cnstr(converted); + if (is_true) + assert_cnstr(m.mk_implies(e, converted)); + else + assert_cnstr(m.mk_implies(m.mk_not(e), m.mk_not(converted))); } void theory_fpa::relevant_eh(app * n) { @@ -664,18 +673,17 @@ namespace smt { assert_cnstr(c); } else { - c = m.mk_eq(unwrap(wrapped, m.get_sort(n)), n); + c = m.mk_eq(unwrap(wrapped, m.get_sort(n)), n); assert_cnstr(c); } } } else if (n->get_family_id() == get_family_id()) { - SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n)); // These are the conversion functions fp.to_* */ + SASSERT(!m_fpa_util.is_float(n) && !m_fpa_util.is_rm(n)); } else UNREACHABLE(); - } void theory_fpa::reset_eh() { @@ -695,6 +703,7 @@ namespace smt { final_check_status theory_fpa::final_check_eh() { TRACE("t_fpa", tout << "final_check_eh\n";); + SASSERT(m_converter.m_extra_assertions.empty()); return FC_DONE; } @@ -705,45 +714,75 @@ namespace smt { } model_value_proc * theory_fpa::mk_value(enode * n, model_generator & mg) { - TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << "\n";); + TRACE("t_fpa", tout << "mk_value for: " << mk_ismt2_pp(n->get_owner(), get_manager()) << + " (sort " << mk_ismt2_pp(get_manager().get_sort(n->get_owner()), get_manager()) << ")\n";); ast_manager & m = get_manager(); context & ctx = get_context(); - app * owner = n->get_owner(); + app_ref owner(m); + owner = n->get_owner(); // If the owner is not internalized, it doesn't have an enode associated. SASSERT(ctx.e_internalized(owner)); if (m_fpa_util.is_rm_numeral(owner) || - m_fpa_util.is_numeral(owner)) + m_fpa_util.is_numeral(owner)) { return alloc(expr_wrapper_proc, owner); + } model_value_proc * res = 0; app_ref wrapped(m); wrapped = wrap(owner); - - CTRACE("t_fpa", !ctx.e_internalized(wrapped), - tout << "Model dependency not internalized: " << - mk_ismt2_pp(wrapped, m) << - " (owner " << (!ctx.e_internalized(owner) ? "not" : "is") << - " internalized)" << std::endl;); - - if (m_fpa_util.is_rm(owner)) { - fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); - vp->add_dependency(ctx.get_enode(wrapped)); - res = vp; - } - else if (m_fpa_util.is_float(owner)) { + SASSERT(m_bv_util.is_bv(wrapped)); + + CTRACE("t_fpa_detail", !ctx.e_internalized(wrapped), + tout << "Model dependency not internalized: " << + mk_ismt2_pp(wrapped, m) << + " (owner " << (!ctx.e_internalized(owner) ? "not" : "is") << + " internalized)" << std::endl;); + + if (is_app_of(owner, get_family_id(), OP_FPA_FP)) { + SASSERT(to_app(owner)->get_num_args() == 3); + app_ref a0(m), a1(m), a2(m); + a0 = to_app(owner->get_arg(0)); + a1 = to_app(owner->get_arg(1)); + a2 = to_app(owner->get_arg(2)); unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner)); unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner)); - fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits); - vp->add_dependency(ctx.get_enode(wrapped)); + fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits); + vp->add_dependency(ctx.get_enode(a0)); + vp->add_dependency(ctx.get_enode(a1)); + vp->add_dependency(ctx.get_enode(a2)); + TRACE("t_fpa_detail", tout << "Depends on: " << + mk_ismt2_pp(a0, m) << " eq. cls. #" << get_enode(a0)->get_root()->get_owner()->get_id() << std::endl << + mk_ismt2_pp(a1, m) << " eq. cls. #" << get_enode(a1)->get_root()->get_owner()->get_id() << std::endl << + mk_ismt2_pp(a2, m) << " eq. cls. #" << get_enode(a2)->get_root()->get_owner()->get_id() << std::endl;); res = vp; } - else - UNREACHABLE(); + else if (ctx.e_internalized(wrapped)) { + if (m_fpa_util.is_rm(owner)) { + fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this); + vp->add_dependency(ctx.get_enode(wrapped)); + res = vp; + } + else if (m_fpa_util.is_float(owner)) { + unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner)); + unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner)); + fpa_value_proc * vp = alloc(fpa_value_proc, this, ebits, sbits); + enode * en = ctx.get_enode(wrapped); + vp->add_dependency(en); + TRACE("t_fpa_detail", tout << "Depends on: " << mk_ismt2_pp(wrapped, m) << " eq. cls. #" << en->get_root()->get_owner()->get_id() << std::endl;); + res = vp; + } + } + else { + unsigned ebits = m_fpa_util.get_ebits(m.get_sort(owner)); + unsigned sbits = m_fpa_util.get_sbits(m.get_sort(owner)); + return alloc(expr_wrapper_proc, m_fpa_util.mk_pzero(ebits, sbits)); + } + SASSERT(res != 0); return res; } @@ -754,7 +793,7 @@ namespace smt { ast_manager & m = get_manager(); context & ctx = get_context(); - out << "theory variables:" << std::endl; + out << "fpa theory variables:" << std::endl; ptr_vector::const_iterator it = ctx.begin_enodes(); ptr_vector::const_iterator end = ctx.end_enodes(); for (; it != end; it++) { @@ -762,5 +801,32 @@ namespace smt { if (v != -1) out << v << " -> " << mk_ismt2_pp((*it)->get_owner(), m) << std::endl; } + + out << "bv theory variables:" << std::endl; + it = ctx.begin_enodes(); + end = ctx.end_enodes(); + for (; it != end; it++) { + theory_var v = (*it)->get_th_var(m_bv_util.get_family_id()); + if (v != -1) out << v << " -> " << + mk_ismt2_pp((*it)->get_owner(), m) << std::endl; + } + + out << "arith theory variables:" << std::endl; + it = ctx.begin_enodes(); + end = ctx.end_enodes(); + for (; it != end; it++) { + theory_var v = (*it)->get_th_var(m_arith_util.get_family_id()); + if (v != -1) out << v << " -> " << + mk_ismt2_pp((*it)->get_owner(), m) << std::endl; + } + + out << "equivalence classes:\n"; + it = ctx.begin_enodes(); + end = ctx.end_enodes(); + for (; it != end; ++it) { + expr * n = (*it)->get_owner(); + expr * r = (*it)->get_root()->get_owner(); + out << r->get_id() << " --> " << mk_ismt2_pp(n, m) << std::endl; + } } }; diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index dfddfd12f..5c12cbd8f 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -116,7 +116,7 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { bv_mdl->eval(a->get_arg(1), exp, true); bv_mdl->eval(a->get_arg(2), sig, true); - SASSERT(a->is_app_of(fu.get_family_id(), OP_FPA_TO_FP)); + SASSERT(a->is_app_of(fu.get_family_id(), OP_FPA_FP)); #ifdef Z3DEBUG SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); diff --git a/src/tactic/fpa/qffp_tactic.cpp b/src/tactic/fpa/qffp_tactic.cpp index 5bc006f00..6b081f0a5 100644 --- a/src/tactic/fpa/qffp_tactic.cpp +++ b/src/tactic/fpa/qffp_tactic.cpp @@ -22,6 +22,7 @@ Notes: #include"sat_tactic.h" #include"fpa2bv_tactic.h" #include"smt_tactic.h" +#include"propagate_values_tactic.h" #include"qffp_tactic.h" @@ -30,19 +31,19 @@ tactic * mk_qffp_tactic(ast_manager & m, params_ref const & p) { simp_p.set_bool("arith_lhs", true); simp_p.set_bool("elim_and", true); - tactic * st = cond( mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), - and_then(mk_simplify_tactic(m, simp_p), - mk_smt_tactic()), - and_then( - mk_simplify_tactic(m, p), - mk_fpa2bv_tactic(m, p), - using_params(mk_simplify_tactic(m, p), simp_p), - mk_bit_blaster_tactic(m, p), - using_params(mk_simplify_tactic(m, p), simp_p), - cond(mk_is_propositional_probe(), - mk_sat_tactic(m, p), - mk_smt_tactic(p)), - mk_fail_if_undecided_tactic())); + tactic * st = and_then(mk_simplify_tactic(m, simp_p), + mk_propagate_values_tactic(m, p), + cond(mk_or(mk_produce_proofs_probe(), mk_produce_unsat_cores_probe()), + mk_smt_tactic(), + and_then( + mk_fpa2bv_tactic(m, p), + using_params(mk_simplify_tactic(m, p), simp_p), + mk_bit_blaster_tactic(m, p), + using_params(mk_simplify_tactic(m, p), simp_p), + cond(mk_is_propositional_probe(), + mk_sat_tactic(m, p), + mk_smt_tactic(p)), + mk_fail_if_undecided_tactic()))); st->updt_params(p); return st; From b9bbfbdbb7bcf67a9489eab3c8ef535b6d324825 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 16 Jan 2015 12:05:12 +0530 Subject: [PATCH 241/646] fix interval dependencies bug. Codeplex issue 163 Signed-off-by: Nikolaj Bjorner --- src/duality/duality_rpfp.cpp | 2 +- src/smt/old_interval.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index cdc8fb3b2..304e41168 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -3147,7 +3147,7 @@ namespace Duality { } if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ - looks_bad: + //looks_bad: if(!axioms_added){ // add the axioms in the off chance they are useful const std::vector &theory = ls->get_axioms(); diff --git a/src/smt/old_interval.cpp b/src/smt/old_interval.cpp index ffc3331be..9dd8e0955 100644 --- a/src/smt/old_interval.cpp +++ b/src/smt/old_interval.cpp @@ -295,6 +295,8 @@ interval & interval::operator*=(interval const & other) { } if (other.is_zero()) { *this = other; + m_lower_dep = m_manager.mk_join(m_lower_dep, m_upper_dep); + m_upper_dep = m_lower_dep; return *this; } From bb722b24c12354640718e444ced8468b8f4dc43a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 16 Jan 2015 17:34:01 +0000 Subject: [PATCH 242/646] Added call to memory::finalize() to ease memory leak debugging Signed-off-by: Christoph M. Wintersteiger --- src/shell/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shell/main.cpp b/src/shell/main.cpp index 0eb612f35..8239871a3 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -337,6 +337,7 @@ int main(int argc, char ** argv) { default: UNREACHABLE(); } + memory::finalize(); #ifdef _WINDOWS _CrtDumpMemoryLeaks(); #endif From 67e04c5dfba23718167b68dd8cd417d6480bc3f7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 16 Jan 2015 17:40:28 +0000 Subject: [PATCH 243/646] Python example: removed function that has no body. Signed-off-by: Christoph M. Wintersteiger --- examples/python/complex/complex.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/python/complex/complex.py b/examples/python/complex/complex.py index d90c01e93..a2de4a6cc 100644 --- a/examples/python/complex/complex.py +++ b/examples/python/complex/complex.py @@ -65,9 +65,6 @@ class ComplexExpr: def __neq__(self, other): return Not(self.__eq__(other)) - def __pow__(self, k): - - def simplify(self): return ComplexExpr(simplify(self.r), simplify(self.i)) From c3247d75988d0a3f0c7f4808acb881c1d60621ed Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 17 Jan 2015 16:36:33 +0000 Subject: [PATCH 244/646] FPA: bugfix for rounding mode bv translation Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 6 +++--- src/ast/fpa/fpa2bv_converter.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 4cdb64d8d..1f7ea1186 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -3170,11 +3170,11 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) { switch(f->get_decl_kind()) - { - case OP_FPA_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; + { case OP_FPA_RM_NEAREST_TIES_TO_EVEN: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3); break; - case OP_FPA_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: result = m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3); break; case OP_FPA_RM_TOWARD_POSITIVE: result = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); break; + case OP_FPA_RM_TOWARD_NEGATIVE: result = m_bv_util.mk_numeral(BV_RM_TO_NEGATIVE, 3); break; case OP_FPA_RM_TOWARD_ZERO: result = m_bv_util.mk_numeral(BV_RM_TO_ZERO, 3); break; default: UNREACHABLE(); } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index 82fad6ff9..fa797b610 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -26,7 +26,7 @@ Notes: #include"bv_decl_plugin.h" #include"basic_simplifier_plugin.h" -typedef enum { BV_RM_TIES_TO_AWAY=0, BV_RM_TIES_TO_EVEN=1, BV_RM_TO_NEGATIVE=2, BV_RM_TO_POSITIVE=3, BV_RM_TO_ZERO=4 } BV_RM_VAL; +typedef enum { BV_RM_TIES_TO_EVEN, BV_RM_TIES_TO_AWAY, BV_RM_TO_POSITIVE, BV_RM_TO_NEGATIVE, BV_RM_TO_ZERO = 4 } BV_RM_VAL; struct func_decl_triple { func_decl_triple () { f_sgn = 0; f_sig = 0; f_exp = 0; } From 6af978292703e4f7ceefa0399e07d002de34a7c5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 18 Jan 2015 04:50:00 +0530 Subject: [PATCH 245/646] set default file format to smt2 Signed-off-by: Nikolaj Bjorner --- src/shell/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shell/main.cpp b/src/shell/main.cpp index 0eb612f35..d84c88366 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -297,7 +297,7 @@ int main(int argc, char ** argv) { } if (g_input_kind == IN_UNSPECIFIED) { - g_input_kind = IN_SMTLIB; + g_input_kind = IN_SMTLIB_2; char const * ext = get_extension(g_input_file); if (ext) { if (strcmp(ext, "datalog") == 0 || strcmp(ext, "dl") == 0) { From 5619f6b583147b5bdb0218001a05c0f3a47ecf1a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 15:18:12 +0000 Subject: [PATCH 246/646] FPA Python API bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 19 ++++++-------- src/api/python/z3printer.py | 52 ++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index ee33fbe51..82002c4f7 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -904,12 +904,8 @@ def _to_expr_ref(a, ctx): if sk == Z3_DATATYPE_SORT: return DatatypeRef(a, ctx) if sk == Z3_FLOATING_POINT_SORT: - if k == Z3_APP_AST: - e = ExprRef(a, ctx) - if e.decl().kind() == Z3_OP_FPA_NUM: - return FPNumRef(a, ctx) - else: - return FPRef(a, ctx) + if k == Z3_APP_AST and _is_numeral(ctx, a): + return FPNumRef(a, ctx) else: return FPRef(a, ctx) if sk == Z3_ROUNDING_MODE_SORT: @@ -7817,7 +7813,8 @@ class FPNumRef(FPRef): return self.decl().kind() == Z3_OP_FPA_PLUS_ZERO or self.decl().kind() == Z3_OP_FPA_MINUS_ZERO def isNegative(self): - return (self.num_args() == 0 and (Z3_OP_FPA_MINUS_INF or Z3_OP_FPA_MINUS_ZERO)) or (self.num_args() == 3 and self.arg(0) == BitVecVal(1)) + k = self.decl().kind() + return (self.num_args() == 0 and (k == Z3_OP_FPA_MINUS_INF or k == Z3_OP_FPA_MINUS_ZERO)) or (self.num_args() == 3 and self.arg(0) == BitVecVal(1)) def _to_fpnum(num, ctx=None): if isinstance(num, FPNum): @@ -7851,7 +7848,7 @@ def is_fp_value(a): True """ return is_fp(a) and _is_numeral(a.ctx, a.ast) - + def FPSort(ebits, sbits, ctx=None): """Return a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used. @@ -7989,7 +7986,7 @@ def fpAbs(a): FloatingPoint(8, 24) """ if __debug__: - _z3_assert(is_fp(a), "First argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression") return FPRef(Z3_mk_fpa_abs(a.ctx_ref(), a.as_ast()), a.ctx) def fpNeg(a): @@ -8004,7 +8001,7 @@ def fpNeg(a): FloatingPoint(8, 24) """ if __debug__: - _z3_assert(is_fp(a), "First argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression") return FPRef(Z3_mk_fpa_neg(a.ctx_ref(), a.as_ast()), a.ctx) def fpAdd(rm, a, b): @@ -8069,7 +8066,7 @@ def fpDiv(rm, a, b): if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") - return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) + return FPRef(Z3_mk_fpa_div(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) def fpRem(a, b): """Create a Z3 floating-point remainder expression. diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index a74a67fa8..da49f1719 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -71,7 +71,7 @@ _z3_op_to_fpa_normal_str = { Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : 'PZero', Z3_OP_FPA_MINUS_ZERO : 'NZero', Z3_OP_FPA_ADD : 'fpAdd', Z3_OP_FPA_SUB : 'fpSub', Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MUL : 'fpMul', Z3_OP_FPA_DIV : 'fpDiv', Z3_OP_FPA_REM : 'fpRem', Z3_OP_FPA_ABS : 'fpAbs', - Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MIN : 'fpMin', Z3_OP_FPA_MAX : 'fpMax', + Z3_OP_FPA_MIN : 'fpMin', Z3_OP_FPA_MAX : 'fpMax', Z3_OP_FPA_FMA : 'fpFMA', Z3_OP_FPA_SQRT : 'fpSqrt', Z3_OP_FPA_ROUND_TO_INTEGRAL : 'fpRoundToIntegral', Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : 'fpLT', Z3_OP_FPA_GT : 'fpGT', Z3_OP_FPA_LE : 'fpLEQ', @@ -93,9 +93,8 @@ _z3_op_to_fpa_pretty_str = { Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo', Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : '+0.0', Z3_OP_FPA_MINUS_ZERO : '-0.0', - Z3_OP_FPA_ADD : '+', Z3_OP_FPA_SUB : '-', Z3_OP_FPA_NEG : '-', Z3_OP_FPA_MUL : '*', - Z3_OP_FPA_DIV : '/', Z3_OP_FPA_REM : '%', - Z3_OP_FPA_NEG: '-', + Z3_OP_FPA_ADD : '+', Z3_OP_FPA_SUB : '-', Z3_OP_FPA_MUL : '*', Z3_OP_FPA_DIV : '/', + Z3_OP_FPA_REM : '%', Z3_OP_FPA_NEG : '-', Z3_OP_FPA_EQ : 'fpEQ', Z3_OP_FPA_LT : '<', Z3_OP_FPA_GT : '>', Z3_OP_FPA_LE : '<=', Z3_OP_FPA_GE : '>=' } @@ -578,7 +577,7 @@ class Formatter: def pp_fprm_value(self, a): z3._z3_assert(z3.is_fprm_value(a), 'expected FPRMNumRef') - if self.fpa_pretty and _z3_op_to_fpa_pretty_str.has_key(a.decl().kind()): + if self.fpa_pretty and a.decl().kind() in _z3_op_to_fpa_pretty_str: return to_format(_z3_op_to_fpa_pretty_str.get(a.decl().kind())) else: return to_format(a.as_string()) @@ -617,7 +616,7 @@ class Formatter: return compose(r) else: if (a.isNaN()): - return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_NAN]) + return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_NAN]) elif (a.isInf()): if (a.isNegative()): return to_format(_z3_op_to_fpa_pretty_str[Z3_OP_FPA_MINUS_INF]) @@ -649,28 +648,33 @@ class Formatter: z3._z3_assert(isinstance(a, z3.FPRef), "type mismatch") k = a.decl().kind() op = '?' - if self.fpa_pretty: - op = _z3_op_to_fpa_pretty_str.get(k, None) - if (op == None): - op = _z3_op_to_str.get(k, None) + if (self.fpa_pretty and k in _z3_op_to_fpa_pretty_str): + op = _z3_op_to_fpa_pretty_str[k] + elif k in _z3_op_to_fpa_normal_str: + op = _z3_op_to_fpa_normal_str[k] + elif k in _z3_op_to_str: + op = _z3_op_to_str[k] n = a.num_args() - if self.fpa_pretty and self.is_infix(k) and n >= 3: - rm = a.arg(0) - if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm): - arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs)) - arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs)) - r = [] - r.append(arg1) - r.append(to_format(' ')) - r.append(to_format(op)) - r.append(to_format(' ')) - r.append(arg2) - return compose(r) + if self.fpa_pretty: + if self.is_infix(k) and n >= 3: + rm = a.arg(0) + if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm): + arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs)) + arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs)) + r = [] + r.append(arg1) + r.append(to_format(' ')) + r.append(to_format(op)) + r.append(to_format(' ')) + r.append(arg2) + return compose(r) + elif k == Z3_OP_FPA_NEG: + return compose([to_format('-') , to_format(self.pp_expr(a.arg(0), d+1, xs))]) - if _z3_op_to_fpa_normal_str.has_key(k): - op = _z3_op_to_fpa_normal_str.get(k, None) + if k in _z3_op_to_fpa_normal_str: + op = _z3_op_to_fpa_normal_str[k] r = [] r.append(to_format(op)) From 70f0d2f423f32d6a7ef23e6d9b202d3355d2ddd4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 13:37:02 +0000 Subject: [PATCH 247/646] Beginnings of a new ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 1 + scripts/mk_util.py | 36 +- scripts/update_api.py | 207 ++++++++++ src/api/ml/README | 3 + .../ml/{ => old}/add_error_checking.V3.sed | 0 src/api/ml/{ => old}/add_error_checking.sed | 0 src/api/ml/{ => old}/build-lib.cmd | 0 src/api/ml/{ => old}/build-lib.sh | 0 src/api/ml/{ => old}/build-test.cmd | 0 src/api/ml/{ => old}/build-test.sh | 0 src/api/ml/{ => old}/build.cmd | 0 src/api/ml/{ => old}/clean.cmd | 0 src/api/ml/{ => old}/cleantmp.cmd | 0 src/api/ml/{ => old}/compile_mlapi.cmd | 0 src/api/ml/{ => old}/error_handling.idl | 0 src/api/ml/{ => old}/exec.cmd | 0 src/api/ml/{ => old}/exec.sh | 0 src/api/ml/{ => old}/generate_mlapi.cmd | 0 src/api/ml/{ => old}/generate_mlapi.sh | 0 src/api/ml/{ => old}/import.cmd | 0 src/api/ml/{ => old}/mlx_get_app_args.idl | 0 src/api/ml/{ => old}/mlx_get_array_sort.idl | 0 .../ml/{ => old}/mlx_get_datatype_sort.idl | 0 src/api/ml/{ => old}/mlx_get_domains.idl | 0 src/api/ml/{ => old}/mlx_get_error_msg.idl | 0 .../ml/{ => old}/mlx_get_pattern_terms.idl | 0 src/api/ml/{ => old}/mlx_get_tuple_sort.idl | 0 src/api/ml/{ => old}/mlx_mk_context_x.idl | 0 src/api/ml/{ => old}/mlx_mk_datatypes.idl | 0 src/api/ml/{ => old}/mlx_mk_numeral.idl | 0 src/api/ml/{ => old}/mlx_mk_sort.idl | 0 src/api/ml/{ => old}/mlx_mk_symbol.idl | 0 src/api/ml/{ => old}/mlx_model.idl | 0 src/api/ml/{ => old}/mlx_numeral_refine.idl | 0 src/api/ml/{ => old}/mlx_parse_smtlib.idl | 0 src/api/ml/{ => old}/mlx_sort_refine.idl | 0 src/api/ml/{ => old}/mlx_statistics.idl | 0 src/api/ml/{ => old}/mlx_symbol_refine.idl | 0 src/api/ml/{ => old}/mlx_term_refine.idl | 0 src/api/ml/{ => old}/postprocess.sed | 0 src/api/ml/{ => old}/preprocess.sed | 0 src/api/ml/{ => old}/queen.ml | 0 src/api/ml/{ => old}/queen.regress.err | 0 src/api/ml/{ => old}/queen.regress.out | 0 src/api/ml/{ => old}/reverse.sed | 0 src/api/ml/{ => old}/test_mlapi.cmd | 0 src/api/ml/{ => old}/test_theory.ml | 0 src/api/ml/{ => old}/update-ml-doc.cmd | 0 src/api/ml/{ => old}/x3V3.ml | 0 src/api/ml/{ => old}/x3V3.mli | 0 src/api/ml/{ => old}/z3.0.idl | 0 src/api/ml/test_capi.regress.err | 5 - src/api/ml/test_capi.regress.out | 386 ------------------ src/api/ml/test_mlapi.regress.err | 0 src/api/ml/test_mlapi.regress.out | 32 -- src/api/ml/test_mlapiV3.regress.err | 5 - src/api/ml/test_mlapiV3.regress.out | 315 -------------- 57 files changed, 245 insertions(+), 745 deletions(-) create mode 100644 src/api/ml/README rename src/api/ml/{ => old}/add_error_checking.V3.sed (100%) rename src/api/ml/{ => old}/add_error_checking.sed (100%) rename src/api/ml/{ => old}/build-lib.cmd (100%) rename src/api/ml/{ => old}/build-lib.sh (100%) rename src/api/ml/{ => old}/build-test.cmd (100%) rename src/api/ml/{ => old}/build-test.sh (100%) rename src/api/ml/{ => old}/build.cmd (100%) rename src/api/ml/{ => old}/clean.cmd (100%) rename src/api/ml/{ => old}/cleantmp.cmd (100%) rename src/api/ml/{ => old}/compile_mlapi.cmd (100%) rename src/api/ml/{ => old}/error_handling.idl (100%) rename src/api/ml/{ => old}/exec.cmd (100%) rename src/api/ml/{ => old}/exec.sh (100%) rename src/api/ml/{ => old}/generate_mlapi.cmd (100%) rename src/api/ml/{ => old}/generate_mlapi.sh (100%) rename src/api/ml/{ => old}/import.cmd (100%) rename src/api/ml/{ => old}/mlx_get_app_args.idl (100%) rename src/api/ml/{ => old}/mlx_get_array_sort.idl (100%) rename src/api/ml/{ => old}/mlx_get_datatype_sort.idl (100%) rename src/api/ml/{ => old}/mlx_get_domains.idl (100%) rename src/api/ml/{ => old}/mlx_get_error_msg.idl (100%) rename src/api/ml/{ => old}/mlx_get_pattern_terms.idl (100%) rename src/api/ml/{ => old}/mlx_get_tuple_sort.idl (100%) rename src/api/ml/{ => old}/mlx_mk_context_x.idl (100%) rename src/api/ml/{ => old}/mlx_mk_datatypes.idl (100%) rename src/api/ml/{ => old}/mlx_mk_numeral.idl (100%) rename src/api/ml/{ => old}/mlx_mk_sort.idl (100%) rename src/api/ml/{ => old}/mlx_mk_symbol.idl (100%) rename src/api/ml/{ => old}/mlx_model.idl (100%) rename src/api/ml/{ => old}/mlx_numeral_refine.idl (100%) rename src/api/ml/{ => old}/mlx_parse_smtlib.idl (100%) rename src/api/ml/{ => old}/mlx_sort_refine.idl (100%) rename src/api/ml/{ => old}/mlx_statistics.idl (100%) rename src/api/ml/{ => old}/mlx_symbol_refine.idl (100%) rename src/api/ml/{ => old}/mlx_term_refine.idl (100%) rename src/api/ml/{ => old}/postprocess.sed (100%) rename src/api/ml/{ => old}/preprocess.sed (100%) rename src/api/ml/{ => old}/queen.ml (100%) rename src/api/ml/{ => old}/queen.regress.err (100%) rename src/api/ml/{ => old}/queen.regress.out (100%) rename src/api/ml/{ => old}/reverse.sed (100%) rename src/api/ml/{ => old}/test_mlapi.cmd (100%) rename src/api/ml/{ => old}/test_theory.ml (100%) rename src/api/ml/{ => old}/update-ml-doc.cmd (100%) rename src/api/ml/{ => old}/x3V3.ml (100%) rename src/api/ml/{ => old}/x3V3.mli (100%) rename src/api/ml/{ => old}/z3.0.idl (100%) delete mode 100644 src/api/ml/test_capi.regress.err delete mode 100644 src/api/ml/test_capi.regress.out delete mode 100644 src/api/ml/test_mlapi.regress.err delete mode 100644 src/api/ml/test_mlapi.regress.out delete mode 100644 src/api/ml/test_mlapiV3.regress.err delete mode 100644 src/api/ml/test_mlapiV3.regress.out diff --git a/scripts/mk_project.py b/scripts/mk_project.py index b30bba609..e2b003d21 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -87,6 +87,7 @@ def init_project_def(): export_files=API_files) add_dot_net_dll('dotnet', ['api_dll'], 'api/dotnet', dll_name='Microsoft.Z3', assembly_info_dir='Properties') add_java_dll('java', ['api_dll'], 'api/java', dll_name='libz3java', package_name="com.microsoft.z3", manifest_file='manifest') + add_ml_lib('ml', ['api_dll'], 'api/ml', lib_name='libz3ml') add_hlib('cpp', 'api/c++', includes2install=['z3++.h']) set_z3py_dir('api/python') # Examples diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4641a7b1b..cb6b17cce 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -65,6 +65,7 @@ VS_PROJ = False TRACE = False DOTNET_ENABLED=False JAVA_ENABLED=False +ML_ENABLED=False STATIC_LIB=False VER_MAJOR=None VER_MINOR=None @@ -476,13 +477,13 @@ def display_help(exit_code): # Parse configuration option for mk_make script def parse_options(): global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM - global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH + global DOTNET_ENABLED, JAVA_ENABLED, ML_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:df:sxhmcvtnp:gj', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof', - 'githash=']) + 'githash=', 'ml']) except: print("ERROR: Invalid command line option") display_help(1) @@ -535,6 +536,8 @@ def parse_options(): GPROF = True elif opt == '--githash': GIT_HASH=arg + elif opt in ('', '--ml'): + ML_ENABLED = True else: print("ERROR: Invalid command line option '%s'" % opt) display_help(1) @@ -621,6 +624,9 @@ def is_verbose(): def is_java_enabled(): return JAVA_ENABLED +def is_ml_enabled(): + return ML_ENABLED + def is_compiler(given, expected): """ Return True if the 'given' compiler is the expected one. @@ -1268,6 +1274,26 @@ class JavaDLLComponent(Component): shutil.copy(os.path.join(build_path, 'libz3java.%s' % so), os.path.join(dist_path, 'bin', 'libz3java.%s' % so)) +class MLComponent(Component): + def __init__(self, name, lib_name, path, deps): + Component.__init__(self, name, path, deps) + if lib_name == None: + lib_name = name + self.lib_name = lib_name + + def mk_makefile(self, out): + if is_ml_enabled(): + mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) + libfile = '%s$(LIB_EXT)' % self.lib_name + out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'z3_native.c'))) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) %s/z3_native.c\n' % self.to_src_dir) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'z3_native')) + out.write('ml: %s\n' % libfile) + out.write('\n') + + def main_component(self): + return is_ml_enabled() + class ExampleComponent(Component): def __init__(self, name, path): Component.__init__(self, name, path, []) @@ -1430,6 +1456,10 @@ def add_java_dll(name, deps=[], path=None, dll_name=None, package_name=None, man c = JavaDLLComponent(name, dll_name, package_name, manifest_file, path, deps) reg_component(name, c) +def add_ml_lib(name, deps=[], path=None, lib_name=None): + c = MLComponent(name, lib_name, path, deps) + reg_component(name, c) + def add_cpp_example(name, path=None): c = CppExampleComponent(name, path) reg_component(name, c) @@ -1513,6 +1543,7 @@ def mk_config(): # End of Windows VS config.mk if is_verbose(): print('64-bit: %s' % is64()) + print('ML API: %s' % is_ml_enabled()) if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) @@ -1631,6 +1662,7 @@ def mk_config(): if GPROF: print('gprof: enabled') print('Python version: %s' % distutils.sysconfig.get_python_version()) + print('ML API: %s' % is_ml_enabled()) if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) diff --git a/scripts/update_api.py b/scripts/update_api.py index 2fbf42cca..9ef0ce9a2 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -155,6 +155,10 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I STRING : 'jstring', STRING_PTR : 'jobject', BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} +# Mapping to ML types +Type2ML = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', + STRING : 'char*', STRING_PTR : 'char**', + BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -205,6 +209,13 @@ def type2javaw(ty): else: return Type2JavaW[ty] +def type2ml(ty): + global Type2ML + if (ty >= FIRST_OBJ_ID): + return 'long' + else: + return Type2ML[ty] + def _in(ty): return (IN, ty); @@ -313,6 +324,24 @@ def param2pystr(p): else: return type2pystr(param_type(p)) +def param2ml(p): + k = param_kind(p) + if k == OUT: + if param_type(p) == INT or param_type(p) == UINT: + return "int*" + elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: + return "long*" + elif param_type(p) == STRING: + return "char*" + else: + print "ERROR: unreachable code" + assert(False) + exit(1) + if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: + return "%s[]" % type2ml(param_type(p)) + else: + return type2ml(param_type(p)) + # Save name, result, params to generate wrapper _API2PY = [] @@ -1039,6 +1068,183 @@ def mk_bindings(): exe_c.write(" in.register_cmd(%s, exec_%s);\n" % (key, val)) exe_c.write("}\n") +def ml_method_name(name): + result = '' + name = name[3:] # Remove Z3_ + return result + +def mk_ml(): + if not is_ml_enabled(): + return + ml_dir = get_component('ml').src_dir + ml_nativef = os.path.join(ml_dir, 'z3_native.ml') + ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') + ml_native = open(ml_nativef, 'w') + ml_native.write('// Automatically generated file\n') + ml_native.write('\n') + for name, result, params in _dotnet_decls: + ml_native.write(' external %s : (' % ml_method_name(name)) + first = True + i = 0; + for param in params: + if first: + first = False + else: + ml_native.write(', ') + ml_native.write('%s a%d' % (param2ml(param), i)) + i = i + 1 + ml_native.write('%s)\n' % (type2ml(result))) + # ml_native.write(' = "NATIVE_%s"' % ml_method_name(name)) + # ml_native.write('\n\n') + # # Exception wrappers + # for name, result, params in _dotnet_decls: + # java_native.write(' public static %s %s(' % (type2java(result), java_method_name(name))) + # first = True + # i = 0; + # for param in params: + # if first: + # first = False + # else: + # java_native.write(', ') + # java_native.write('%s a%d' % (param2java(param), i)) + # i = i + 1 + # java_native.write(')') + # if len(params) > 0 and param_type(params[0]) == CONTEXT: + # java_native.write(' throws Z3Exception') + # java_native.write('\n') + # java_native.write(' {\n') + # java_native.write(' ') + # if result != VOID: + # java_native.write('%s res = ' % type2java(result)) + # java_native.write('INTERNAL%s(' % (java_method_name(name))) + # first = True + # i = 0; + # for param in params: + # if first: + # first = False + # else: + # java_native.write(', ') + # java_native.write('a%d' % i) + # i = i + 1 + # java_native.write(');\n') + # if len(params) > 0 and param_type(params[0]) == CONTEXT: + # java_native.write(' Z3_error_code err = Z3_error_code.fromInt(INTERNALgetErrorCode(a0));\n') + # java_native.write(' if (err != Z3_error_code.Z3_OK)\n') + # java_native.write(' throw new Z3Exception(INTERNALgetErrorMsgEx(a0, err.toInt()));\n') + # if result != VOID: + # java_native.write(' return res;\n') + # java_native.write(' }\n\n') + # java_native.write('}\n') + ml_wrapper = open(ml_wrapperf, 'w') + ml_wrapper.write('// Automatically generated file\n\n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#ifdef Custom_tag\n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n') + ml_wrapper.write('#endif\n') + # for name, result, params in _dotnet_decls: + # java_wrapper.write('JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) + # i = 0; + # for param in params: + # java_wrapper.write(', ') + # java_wrapper.write('%s a%d' % (param2javaw(param), i)) + # i = i + 1 + # java_wrapper.write(') {\n') + # # preprocess arrays, strings, in/out arguments + # i = 0 + # for param in params: + # k = param_kind(param) + # if k == OUT or k == INOUT: + # java_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + # elif k == IN_ARRAY or k == INOUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) + # else: + # java_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) + # elif k == OUT_ARRAY: + # java_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), + # i, + # type2str(param_type(param)), + # param_array_capacity_pos(param), + # type2str(param_type(param)))) + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + # else: + # java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) + # elif k == IN and param_type(param) == STRING: + # java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i)) + # i = i + 1 + # # invoke procedure + # java_wrapper.write(' ') + # if result != VOID: + # java_wrapper.write('%s result = ' % type2str(result)) + # java_wrapper.write('%s(' % name) + # i = 0 + # first = True + # for param in params: + # if first: + # first = False + # else: + # java_wrapper.write(', ') + # k = param_kind(param) + # if k == OUT or k == INOUT: + # java_wrapper.write('&_a%s' % i) + # elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + # java_wrapper.write('_a%s' % i) + # elif k == IN and param_type(param) == STRING: + # java_wrapper.write('_a%s' % i) + # else: + # java_wrapper.write('(%s)a%i' % (param2str(param), i)) + # i = i + 1 + # java_wrapper.write(');\n') + # # cleanup + # i = 0 + # for param in params: + # k = param_kind(param) + # if k == OUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + # else: + # java_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) + # java_wrapper.write(' free(_a%s);\n' % i) + # elif k == IN_ARRAY or k == OUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) + # else: + # java_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) + + # elif k == OUT or k == INOUT: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' {\n') + # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') + # java_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) + # java_wrapper.write(' }\n') + # else: + # java_wrapper.write(' {\n') + # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') + # java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) + # java_wrapper.write(' }\n') + # i = i + 1 + # # return + # if result == STRING: + # java_wrapper.write(' return jenv->NewStringUTF(result);\n') + # elif result != VOID: + # java_wrapper.write(' return (%s) result;\n' % type2javaw(result)) + # java_wrapper.write('}\n') + # java_wrapper.write('#ifdef __cplusplus\n') + # java_wrapper.write('}\n') + # java_wrapper.write('#endif\n') + if is_verbose(): + print "Generated '%s'" % ml_nativef + # Collect API(...) commands from def def_APIs(): pat1 = re.compile(" *def_API.*") @@ -1063,6 +1269,7 @@ mk_py_wrappers() mk_dotnet() mk_dotnet_wrappers() mk_java() +mk_ml() log_h.close() log_c.close() diff --git a/src/api/ml/README b/src/api/ml/README new file mode 100644 index 000000000..925fced59 --- /dev/null +++ b/src/api/ml/README @@ -0,0 +1,3 @@ +This directory is work in progress. + +We are currently working on a brand new ML API. diff --git a/src/api/ml/add_error_checking.V3.sed b/src/api/ml/old/add_error_checking.V3.sed similarity index 100% rename from src/api/ml/add_error_checking.V3.sed rename to src/api/ml/old/add_error_checking.V3.sed diff --git a/src/api/ml/add_error_checking.sed b/src/api/ml/old/add_error_checking.sed similarity index 100% rename from src/api/ml/add_error_checking.sed rename to src/api/ml/old/add_error_checking.sed diff --git a/src/api/ml/build-lib.cmd b/src/api/ml/old/build-lib.cmd similarity index 100% rename from src/api/ml/build-lib.cmd rename to src/api/ml/old/build-lib.cmd diff --git a/src/api/ml/build-lib.sh b/src/api/ml/old/build-lib.sh similarity index 100% rename from src/api/ml/build-lib.sh rename to src/api/ml/old/build-lib.sh diff --git a/src/api/ml/build-test.cmd b/src/api/ml/old/build-test.cmd similarity index 100% rename from src/api/ml/build-test.cmd rename to src/api/ml/old/build-test.cmd diff --git a/src/api/ml/build-test.sh b/src/api/ml/old/build-test.sh similarity index 100% rename from src/api/ml/build-test.sh rename to src/api/ml/old/build-test.sh diff --git a/src/api/ml/build.cmd b/src/api/ml/old/build.cmd similarity index 100% rename from src/api/ml/build.cmd rename to src/api/ml/old/build.cmd diff --git a/src/api/ml/clean.cmd b/src/api/ml/old/clean.cmd similarity index 100% rename from src/api/ml/clean.cmd rename to src/api/ml/old/clean.cmd diff --git a/src/api/ml/cleantmp.cmd b/src/api/ml/old/cleantmp.cmd similarity index 100% rename from src/api/ml/cleantmp.cmd rename to src/api/ml/old/cleantmp.cmd diff --git a/src/api/ml/compile_mlapi.cmd b/src/api/ml/old/compile_mlapi.cmd similarity index 100% rename from src/api/ml/compile_mlapi.cmd rename to src/api/ml/old/compile_mlapi.cmd diff --git a/src/api/ml/error_handling.idl b/src/api/ml/old/error_handling.idl similarity index 100% rename from src/api/ml/error_handling.idl rename to src/api/ml/old/error_handling.idl diff --git a/src/api/ml/exec.cmd b/src/api/ml/old/exec.cmd similarity index 100% rename from src/api/ml/exec.cmd rename to src/api/ml/old/exec.cmd diff --git a/src/api/ml/exec.sh b/src/api/ml/old/exec.sh similarity index 100% rename from src/api/ml/exec.sh rename to src/api/ml/old/exec.sh diff --git a/src/api/ml/generate_mlapi.cmd b/src/api/ml/old/generate_mlapi.cmd similarity index 100% rename from src/api/ml/generate_mlapi.cmd rename to src/api/ml/old/generate_mlapi.cmd diff --git a/src/api/ml/generate_mlapi.sh b/src/api/ml/old/generate_mlapi.sh similarity index 100% rename from src/api/ml/generate_mlapi.sh rename to src/api/ml/old/generate_mlapi.sh diff --git a/src/api/ml/import.cmd b/src/api/ml/old/import.cmd similarity index 100% rename from src/api/ml/import.cmd rename to src/api/ml/old/import.cmd diff --git a/src/api/ml/mlx_get_app_args.idl b/src/api/ml/old/mlx_get_app_args.idl similarity index 100% rename from src/api/ml/mlx_get_app_args.idl rename to src/api/ml/old/mlx_get_app_args.idl diff --git a/src/api/ml/mlx_get_array_sort.idl b/src/api/ml/old/mlx_get_array_sort.idl similarity index 100% rename from src/api/ml/mlx_get_array_sort.idl rename to src/api/ml/old/mlx_get_array_sort.idl diff --git a/src/api/ml/mlx_get_datatype_sort.idl b/src/api/ml/old/mlx_get_datatype_sort.idl similarity index 100% rename from src/api/ml/mlx_get_datatype_sort.idl rename to src/api/ml/old/mlx_get_datatype_sort.idl diff --git a/src/api/ml/mlx_get_domains.idl b/src/api/ml/old/mlx_get_domains.idl similarity index 100% rename from src/api/ml/mlx_get_domains.idl rename to src/api/ml/old/mlx_get_domains.idl diff --git a/src/api/ml/mlx_get_error_msg.idl b/src/api/ml/old/mlx_get_error_msg.idl similarity index 100% rename from src/api/ml/mlx_get_error_msg.idl rename to src/api/ml/old/mlx_get_error_msg.idl diff --git a/src/api/ml/mlx_get_pattern_terms.idl b/src/api/ml/old/mlx_get_pattern_terms.idl similarity index 100% rename from src/api/ml/mlx_get_pattern_terms.idl rename to src/api/ml/old/mlx_get_pattern_terms.idl diff --git a/src/api/ml/mlx_get_tuple_sort.idl b/src/api/ml/old/mlx_get_tuple_sort.idl similarity index 100% rename from src/api/ml/mlx_get_tuple_sort.idl rename to src/api/ml/old/mlx_get_tuple_sort.idl diff --git a/src/api/ml/mlx_mk_context_x.idl b/src/api/ml/old/mlx_mk_context_x.idl similarity index 100% rename from src/api/ml/mlx_mk_context_x.idl rename to src/api/ml/old/mlx_mk_context_x.idl diff --git a/src/api/ml/mlx_mk_datatypes.idl b/src/api/ml/old/mlx_mk_datatypes.idl similarity index 100% rename from src/api/ml/mlx_mk_datatypes.idl rename to src/api/ml/old/mlx_mk_datatypes.idl diff --git a/src/api/ml/mlx_mk_numeral.idl b/src/api/ml/old/mlx_mk_numeral.idl similarity index 100% rename from src/api/ml/mlx_mk_numeral.idl rename to src/api/ml/old/mlx_mk_numeral.idl diff --git a/src/api/ml/mlx_mk_sort.idl b/src/api/ml/old/mlx_mk_sort.idl similarity index 100% rename from src/api/ml/mlx_mk_sort.idl rename to src/api/ml/old/mlx_mk_sort.idl diff --git a/src/api/ml/mlx_mk_symbol.idl b/src/api/ml/old/mlx_mk_symbol.idl similarity index 100% rename from src/api/ml/mlx_mk_symbol.idl rename to src/api/ml/old/mlx_mk_symbol.idl diff --git a/src/api/ml/mlx_model.idl b/src/api/ml/old/mlx_model.idl similarity index 100% rename from src/api/ml/mlx_model.idl rename to src/api/ml/old/mlx_model.idl diff --git a/src/api/ml/mlx_numeral_refine.idl b/src/api/ml/old/mlx_numeral_refine.idl similarity index 100% rename from src/api/ml/mlx_numeral_refine.idl rename to src/api/ml/old/mlx_numeral_refine.idl diff --git a/src/api/ml/mlx_parse_smtlib.idl b/src/api/ml/old/mlx_parse_smtlib.idl similarity index 100% rename from src/api/ml/mlx_parse_smtlib.idl rename to src/api/ml/old/mlx_parse_smtlib.idl diff --git a/src/api/ml/mlx_sort_refine.idl b/src/api/ml/old/mlx_sort_refine.idl similarity index 100% rename from src/api/ml/mlx_sort_refine.idl rename to src/api/ml/old/mlx_sort_refine.idl diff --git a/src/api/ml/mlx_statistics.idl b/src/api/ml/old/mlx_statistics.idl similarity index 100% rename from src/api/ml/mlx_statistics.idl rename to src/api/ml/old/mlx_statistics.idl diff --git a/src/api/ml/mlx_symbol_refine.idl b/src/api/ml/old/mlx_symbol_refine.idl similarity index 100% rename from src/api/ml/mlx_symbol_refine.idl rename to src/api/ml/old/mlx_symbol_refine.idl diff --git a/src/api/ml/mlx_term_refine.idl b/src/api/ml/old/mlx_term_refine.idl similarity index 100% rename from src/api/ml/mlx_term_refine.idl rename to src/api/ml/old/mlx_term_refine.idl diff --git a/src/api/ml/postprocess.sed b/src/api/ml/old/postprocess.sed similarity index 100% rename from src/api/ml/postprocess.sed rename to src/api/ml/old/postprocess.sed diff --git a/src/api/ml/preprocess.sed b/src/api/ml/old/preprocess.sed similarity index 100% rename from src/api/ml/preprocess.sed rename to src/api/ml/old/preprocess.sed diff --git a/src/api/ml/queen.ml b/src/api/ml/old/queen.ml similarity index 100% rename from src/api/ml/queen.ml rename to src/api/ml/old/queen.ml diff --git a/src/api/ml/queen.regress.err b/src/api/ml/old/queen.regress.err similarity index 100% rename from src/api/ml/queen.regress.err rename to src/api/ml/old/queen.regress.err diff --git a/src/api/ml/queen.regress.out b/src/api/ml/old/queen.regress.out similarity index 100% rename from src/api/ml/queen.regress.out rename to src/api/ml/old/queen.regress.out diff --git a/src/api/ml/reverse.sed b/src/api/ml/old/reverse.sed similarity index 100% rename from src/api/ml/reverse.sed rename to src/api/ml/old/reverse.sed diff --git a/src/api/ml/test_mlapi.cmd b/src/api/ml/old/test_mlapi.cmd similarity index 100% rename from src/api/ml/test_mlapi.cmd rename to src/api/ml/old/test_mlapi.cmd diff --git a/src/api/ml/test_theory.ml b/src/api/ml/old/test_theory.ml similarity index 100% rename from src/api/ml/test_theory.ml rename to src/api/ml/old/test_theory.ml diff --git a/src/api/ml/update-ml-doc.cmd b/src/api/ml/old/update-ml-doc.cmd similarity index 100% rename from src/api/ml/update-ml-doc.cmd rename to src/api/ml/old/update-ml-doc.cmd diff --git a/src/api/ml/x3V3.ml b/src/api/ml/old/x3V3.ml similarity index 100% rename from src/api/ml/x3V3.ml rename to src/api/ml/old/x3V3.ml diff --git a/src/api/ml/x3V3.mli b/src/api/ml/old/x3V3.mli similarity index 100% rename from src/api/ml/x3V3.mli rename to src/api/ml/old/x3V3.mli diff --git a/src/api/ml/z3.0.idl b/src/api/ml/old/z3.0.idl similarity index 100% rename from src/api/ml/z3.0.idl rename to src/api/ml/old/z3.0.idl diff --git a/src/api/ml/test_capi.regress.err b/src/api/ml/test_capi.regress.err deleted file mode 100644 index 0c383b409..000000000 --- a/src/api/ml/test_capi.regress.err +++ /dev/null @@ -1,5 +0,0 @@ -WARNING: invalid function application, sort mismatch on argument at position 1 -WARNING: (define iff Bool Bool Bool) applied to: -x of sort Int -y of sort Bool - diff --git a/src/api/ml/test_capi.regress.out b/src/api/ml/test_capi.regress.out deleted file mode 100644 index 48870057c..000000000 --- a/src/api/ml/test_capi.regress.out +++ /dev/null @@ -1,386 +0,0 @@ -Z3 4.2.0.0 - -simple_example -CONTEXT: -(solver)END OF CONTEXT - -DeMorgan -DeMorgan is valid - -find_model_example1 -model for: x xor y -sat -y -> false -x -> true - - -find_model_example2 -model for: x < y + 1, x > 2 -sat -y -> 3 -x -> 3 - -model for: x < y + 1, x > 2, not(x = y) -sat -y -> 4 -x -> 3 - - -prove_example1 -prove: x = y implies g(x) = g(y) -valid -disprove: x = y implies g(g(x)) = g(y) -invalid -counterexample: -y -> U!val!0 -x -> U!val!0 -g -> { - U!val!0 -> U!val!1 - U!val!1 -> U!val!2 - else -> U!val!1 -} - - -prove_example2 -prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 -valid -disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1 -invalid -counterexample: -z -> (- 1) -y -> (- 7719) -x -> (- 7719) -g -> { - (- 7719) -> 0 - 0 -> 2 - (- 1) -> 3 - else -> 0 -} - - -push_pop_example1 -assert: x >= 'big number' -push -number of scopes: 1 -assert: x <= 3 -unsat -pop -number of scopes: 0 -sat -x = 1000000000000000000000000000000000000000000000000000000:int -function interpretations: -assert: y > x -sat -y = 1000000000000000000000000000000000000000000000000000001:int -x = 1000000000000000000000000000000000000000000000000000000:int -function interpretations: - -quantifier_example1 -pattern: {(f #0 #1)} - -assert axiom: -(forall (k!0 Int) (k!1 Int) (= (inv!0 (f k!1 k!0)) k!0) :pat {(f k!1 k!0)}) -prove: f(x, y) = f(w, v) implies y = v -valid -disprove: f(x, y) = f(w, v) implies x = w -that is: not(f(x, y) = f(w, v) implies x = w) is satisfiable -unknown -potential model: -w = 2:int -v = 1:int -y = 1:int -x = 0:int -function interpretations: -f = {(else|->(define f!52 Int Int Int)[(define k!50 Int Int)[#unknown], (define k!51 Int Int)[#unknown]])} -#51 = {(2:int|->2:int), (1:int|->1:int), (15:int|->15:int), (11:int|->11:int), (0:int|->0:int), (19:int|->19:int), (else|->2:int)} -f!52 = {(0:int, 1:int|->3:int), (2:int, 1:int|->3:int), (0:int, 0:int|->4:int), (2:int, 0:int|->5:int), (6:int, 2:int|->7:int), (2:int, 2:int|->8:int), (0:int, 2:int|->9:int), (6:int, 0:int|->10:int), (0:int, 11:int|->12:int), (2:int, 11:int|->13:int), (6:int, 11:int|->14:int), (0:int, 15:int|->16:int), (2:int, 15:int|->17:int), (6:int, 15:int|->18:int), (0:int, 19:int|->20:int), (6:int, 19:int|->21:int), (2:int, 19:int|->22:int), (else|->3:int)} -inv!0 = {(3:int|->1:int), (4:int|->0:int), (5:int|->0:int), (7:int|->2:int), (8:int|->2:int), (9:int|->2:int), (10:int|->0:int), (12:int|->11:int), (13:int|->11:int), (14:int|->11:int), (16:int|->15:int), (17:int|->15:int), (18:int|->15:int), (20:int|->19:int), (21:int|->19:int), (22:int|->19:int), (else|->2:int)} -#50 = {(2:int|->2:int), (6:int|->6:int), (0:int|->0:int), (else|->2:int)} -reason for last failure: 7 (7 = quantifiers) - -array_example1 -prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)) -(=> (= (store a1 i1 v1) (store a2 i2 v2)) - (or (= i1 i3) (= i2 i3) (= (select a1 i3) (select a2 i3)))) -valid - -array_example2 -n = 2 -(distinct k!0 k!1) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -function interpretations: -#0 = {((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#1 = {((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 3 -(distinct k!0 k!1 k!2) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -#2 = (define as-array[k!2] (Array Bool Bool)) -function interpretations: -#0 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define false Bool)), (else|->(define true Bool))} -#1 = {((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#2 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 4 -(distinct k!0 k!1 k!2 k!3) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -#2 = (define as-array[k!2] (Array Bool Bool)) -#3 = (define as-array[k!3] (Array Bool Bool)) -function interpretations: -#0 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define true Bool)), (else|->(define false Bool))} -#1 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define false Bool)), (else|->(define true Bool))} -#2 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#3 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 5 -(distinct k!0 k!1 k!2 k!3 k!4) -unsat - -array_example3 -domain: int -range: bool - -tuple_example1 -tuple_sort: (real, real) -prove: get_x(mk_pair(x, y)) = 1 implies x = 1 -valid -disprove: get_x(mk_pair(x, y)) = 1 implies y = 1 -invalid -counterexample: -y -> 0 -x -> 1 - -prove: get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2 -valid -disprove: get_x(p1) = get_x(p2) implies p1 = p2 -invalid -counterexample: -p1 -> (mk_pair 1 0) -p2 -> (mk_pair 1 2) - -prove: p2 = update(p1, 0, 10) implies get_x(p2) = 10 -valid -disprove: p2 = update(p1, 0, 10) implies get_y(p2) = 10 -invalid -counterexample: -p2 -> (mk_pair 10 1) -p1 -> (mk_pair 0 1) - - -bitvector_example1 -disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers -invalid -counterexample: -x -> bv2147483656[32] - - -bitvector_example2 -find values of x and y, such that x ^ y - 103 == x * y -sat -y -> bv3905735879[32] -x -> bv3787456528[32] - - -eval_example1 -MODEL: -y -> 4 -x -> 3 - -evaluating x+y -result = 7:int - -two_contexts_example1 -k!0 - -error_code_example1 -last call succeeded. -last call failed. - -error_code_example2 -before Z3_mk_iff -Z3 error: type error. - -parser_example1 -formula 0: (> x y) -formula 1: (> x 0) -sat -y -> 0 -x -> 1 - - -parser_example2 -formula: (> x y) -sat -y -> (- 1) -x -> 0 - - -parser_example3 -assert axiom: -(forall (x Int) (y Int) (= (g x y) (g y x)) :qid {k!1}) -formula: (forall (x Int) (y Int) (=> (= x y) (= (g x 0) (g 0 y))) :qid {k!1}) -valid - -parser_example4 -declaration 0: (define y Int) -declaration 1: (define sk_hack Bool Bool) -declaration 2: (define x Int) -assumption 0: (= x 20) -formula 0: (> x y) -formula 1: (> x 0) - -parser_example5 -Z3 error: parser error. -Error message: 'ERROR: line 1 column 41: could not find sort symbol 'y'. -'. - -numeral_example -Numerals n1:1/2 n2:1/2 -valid -Numerals n1:(- 1/3) n2:(- 33333333333333333333333333333333333333333333333333/100000000000000000000000000000000000000000000000000) -valid - -ite_example -term: (if false 1 0) - -list_example -valid -valid -valid -valid -valid -valid -valid -Formula (=> (is_cons u) (= u (cons (head u) (tail u)))) -valid -invalid -counterexample: -u -> nil - - -tree_example -valid -valid -valid -valid -valid -Formula (=> (is_cons u) (= u (cons (car u) (cdr u)))) -valid -invalid -counterexample: -u -> nil - - -forest_example -valid -valid -valid -valid -valid -valid - -binary_tree_example -valid -valid -valid -valid -valid - -enum_example -(define apple[fruit:0] fruit) -(define banana[fruit:1] fruit) -(define orange[fruit:2] fruit) -(define is_apple[fruit:0] fruit Bool) -(define is_banana[fruit:1] fruit Bool) -(define is_orange[fruit:2] fruit Bool) -valid -valid -invalid -counterexample: - -valid -valid - -unsat_core_and_proof_example -unsat -proof: [unit-resolution - [def-axiom (or (or (not PredA) PredB (not PredC)) (not PredB))] - [unit-resolution - [def-axiom (or (or (not PredA) (not PredB) (not PredC)) PredB)] - [unit-resolution - [mp - [asserted (or (and PredA PredB PredC) P1)] - [monotonicity - [rewrite - (iff (and PredA PredB PredC) - (not (or (not PredA) (not PredB) (not PredC))))] - (iff (or (and PredA PredB PredC) P1) - (or (not (or (not PredA) (not PredB) (not PredC))) P1))] - (or (not (or (not PredA) (not PredB) (not PredC))) P1)] - [asserted (not P1)] - (not (or (not PredA) (not PredB) (not PredC)))] - PredB] - [unit-resolution - [mp - [asserted (or (and PredA (not PredB) PredC) P2)] - [monotonicity - [rewrite - (iff (and PredA (not PredB) PredC) - (not (or (not PredA) PredB (not PredC))))] - (iff (or (and PredA (not PredB) PredC) P2) - (or (not (or (not PredA) PredB (not PredC))) P2))] - (or (not (or (not PredA) PredB (not PredC))) P2)] - [asserted (not P2)] - (not (or (not PredA) PredB (not PredC)))] - false] - -core: -(not P1) -(not P2) - - -get_implied_equalities example -Class a |-> 0 -Class b |-> 0 -Class c |-> 0 -Class d |-> 3 -Class (f a) |-> 0 -Class (f b) |-> 0 -Class (f c) |-> 0 -asserting f(a) <= b -Class a |-> 0 -Class b |-> 0 -Class c |-> 0 -Class d |-> 3 -Class (f a) |-> 0 -Class (f b) |-> 0 -Class (f c) |-> 0 - -incremental_example1 -unsat core: 0 2 3 -unsat -sat -unsat core: 0 2 3 -unsat -unsat core: 0 2 3 -unsat -sat - -reference_counter_example -model for: x xor y -sat -y -> false -x -> true - - -smt2parser_example -formulas: (and (bvuge a bv16[8]) (bvule a bv240[8])) - -substitute_example -substitution result: (f (f a 0) 1) - -substitute_vars_example -substitution result: (f (f a (g b)) a) diff --git a/src/api/ml/test_mlapi.regress.err b/src/api/ml/test_mlapi.regress.err deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/api/ml/test_mlapi.regress.out b/src/api/ml/test_mlapi.regress.out deleted file mode 100644 index 1fb6289c7..000000000 --- a/src/api/ml/test_mlapi.regress.out +++ /dev/null @@ -1,32 +0,0 @@ -datatype created: -sort: tree -constructor: (define leaf[tree:0] Int tree) recognizer: (define is_leaf[tree:0] tree Bool) accessors: (define data[tree:0:0] tree Int) -constructor: (define node[tree:1] forest tree) recognizer: (define is_node[tree:1] tree Bool) accessors: (define children[tree:1:0] tree forest) -sort: forest -constructor: (define nil[forest:0] forest) recognizer: (define is_nil[forest:0] forest Bool) accessors: -constructor: (define cons[forest:1] tree forest forest) recognizer: (define is_cons[forest:1] forest Bool) accessors: (define hd[forest:1:0] forest tree) (define tl[forest:1:1] forest forest) - -t1: (node (cons (leaf 1) (cons (leaf 2) nil))) -t2: (node (cons (node (cons (leaf 1) (cons (leaf 2) nil))) (cons (leaf 3) nil))) -t3: (node (cons (node (cons (leaf 1) (cons (leaf 2) nil))) - (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil))) -t4: (node (cons (leaf 4) (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil))) -f1: (cons (leaf 0) nil) -f2: (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil) -f3: (cons (node (cons (leaf 1) (cons (leaf 2) nil))) (cons (leaf 0) nil)) -t1: (node (cons (leaf 1) (cons (leaf 2) nil))) -t2: (node (cons (node (cons (leaf 1) (cons (leaf 2) nil))) (cons (leaf 3) nil))) -t3: (node (cons (node (cons (leaf 1) (cons (leaf 2) nil))) - (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil))) -t4: (node (cons (leaf 4) (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil))) -f1: (cons (leaf 0) nil) -f2: (cons (node (cons (leaf 1) (cons (leaf 2) nil))) nil) -f3: (cons (node (cons (leaf 1) (cons (leaf 2) nil))) (cons (leaf 0) nil)) -valid -valid -l1: (cons x u) -l2: (cons y v) -valid -valid -valid -valid diff --git a/src/api/ml/test_mlapiV3.regress.err b/src/api/ml/test_mlapiV3.regress.err deleted file mode 100644 index 0c383b409..000000000 --- a/src/api/ml/test_mlapiV3.regress.err +++ /dev/null @@ -1,5 +0,0 @@ -WARNING: invalid function application, sort mismatch on argument at position 1 -WARNING: (define iff Bool Bool Bool) applied to: -x of sort Int -y of sort Bool - diff --git a/src/api/ml/test_mlapiV3.regress.out b/src/api/ml/test_mlapiV3.regress.out deleted file mode 100644 index efcc4388d..000000000 --- a/src/api/ml/test_mlapiV3.regress.out +++ /dev/null @@ -1,315 +0,0 @@ -Z3 4.2.0.0 - -simple_example -CONTEXT: -(solver)END OF CONTEXT - -DeMorgan -DeMorgan is valid - -find_model_example1 -model for: x xor y -sat -y -> false -x -> true - - -find_model_example2 -model for: x < y + 1, x > 2 -sat -y -> 3 -x -> 3 - -model for: x < y + 1, x > 2, not(x = y) -sat -y -> 4 -x -> 3 - - -prove_example1 -prove: x = y implies g(x) = g(y) -valid -disprove: x = y implies g(g(x)) = g(y) -invalid -counterexample: -y -> U!val!0 -x -> U!val!0 -g -> { - U!val!0 -> U!val!1 - U!val!1 -> U!val!2 - else -> U!val!1 -} - - -prove_example2 -prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 -valid -disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1 -invalid -counterexample: -z -> (- 1) -y -> (- 7719) -x -> (- 7719) -g -> { - (- 7719) -> 0 - 0 -> 2 - (- 1) -> 3 - else -> 0 -} - - -push_pop_example1 -assert: x >= 'big number' -push -number of scopes: 1 -assert: x <= 3 -unsat -pop -number of scopes: 0 -sat -x = 1000000000000000000000000000000000000000000000000000000:int -function interpretations: -assert: y > x -sat -y = 1000000000000000000000000000000000000000000000000000001:int -x = 1000000000000000000000000000000000000000000000000000000:int -function interpretations: - -quantifier_example1 -pattern: {(f #0 #1)} - -assert axiom: -(forall (k!0 Int) (k!1 Int) (= (inv!0 (f k!1 k!0)) k!0) :pat {(f k!1 k!0)}) -prove: f(x, y) = f(w, v) implies y = v -valid -disprove: f(x, y) = f(w, v) implies x = w -that is: not(f(x, y) = f(w, v) implies x = w) is satisfiable -unknown -potential model: -w = 2:int -v = 1:int -y = 1:int -x = 0:int -function interpretations: -f = {(else|->(define f!52 Int Int Int)[(define k!50 Int Int)[#unknown], (define k!51 Int Int)[#unknown]])} -#51 = {(2:int|->2:int), (1:int|->1:int), (15:int|->15:int), (11:int|->11:int), (0:int|->0:int), (19:int|->19:int), (else|->2:int)} -f!52 = {(0:int, 1:int|->3:int), (2:int, 1:int|->3:int), (0:int, 0:int|->4:int), (2:int, 0:int|->5:int), (6:int, 2:int|->7:int), (2:int, 2:int|->8:int), (0:int, 2:int|->9:int), (6:int, 0:int|->10:int), (0:int, 11:int|->12:int), (2:int, 11:int|->13:int), (6:int, 11:int|->14:int), (0:int, 15:int|->16:int), (2:int, 15:int|->17:int), (6:int, 15:int|->18:int), (0:int, 19:int|->20:int), (6:int, 19:int|->21:int), (2:int, 19:int|->22:int), (else|->3:int)} -inv!0 = {(3:int|->1:int), (4:int|->0:int), (5:int|->0:int), (7:int|->2:int), (8:int|->2:int), (9:int|->2:int), (10:int|->0:int), (12:int|->11:int), (13:int|->11:int), (14:int|->11:int), (16:int|->15:int), (17:int|->15:int), (18:int|->15:int), (20:int|->19:int), (21:int|->19:int), (22:int|->19:int), (else|->2:int)} -#50 = {(2:int|->2:int), (6:int|->6:int), (0:int|->0:int), (else|->2:int)} -reason for last failure: 7 (7 = quantifiers) - -array_example1 -prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)) -(=> (= (store a1 i1 v1) (store a2 i2 v2)) - (or (= i1 i3) (= i2 i3) (= (select a1 i3) (select a2 i3)))) -valid - -array_example2 -n = 2 -(distinct k!0 k!1) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -function interpretations: -#0 = {((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#1 = {((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 3 -(distinct k!0 k!1 k!2) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -#2 = (define as-array[k!2] (Array Bool Bool)) -function interpretations: -#0 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define false Bool)), (else|->(define true Bool))} -#1 = {((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#2 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 4 -(distinct k!0 k!1 k!2 k!3) -sat -#0 = (define as-array[k!0] (Array Bool Bool)) -#1 = (define as-array[k!1] (Array Bool Bool)) -#2 = (define as-array[k!2] (Array Bool Bool)) -#3 = (define as-array[k!3] (Array Bool Bool)) -function interpretations: -#0 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define true Bool)), (else|->(define false Bool))} -#1 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define false Bool)), (else|->(define true Bool))} -#2 = {((define true Bool)|->(define true Bool)), ((define false Bool)|->(define true Bool)), (else|->(define true Bool))} -#3 = {((define true Bool)|->(define false Bool)), ((define false Bool)|->(define false Bool)), (else|->(define false Bool))} -n = 5 -(distinct k!0 k!1 k!2 k!3 k!4) -unsat - -array_example3 -domain: int -range: bool - -tuple_example1 -tuple_sort: (real, real) -prove: get_x(mk_pair(x, y)) = 1 implies x = 1 -valid -disprove: get_x(mk_pair(x, y)) = 1 implies y = 1 -invalid -counterexample: -y -> 0 -x -> 1 - -prove: get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2 -valid -disprove: get_x(p1) = get_x(p2) implies p1 = p2 -invalid -counterexample: -p1 -> (mk_pair 1 0) -p2 -> (mk_pair 1 2) - -prove: p2 = update(p1, 0, 10) implies get_x(p2) = 10 -valid -disprove: p2 = update(p1, 0, 10) implies get_y(p2) = 10 -invalid -counterexample: -p2 -> (mk_pair 10 1) -p1 -> (mk_pair 0 1) - - -bitvector_example1 -disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers -invalid -counterexample: -x -> bv2147483656[32] - - -bitvector_example2 -find values of x and y, such that x ^ y - 103 == x * y -sat -y -> bv3905735879[32] -x -> bv3787456528[32] - - -eval_example1 -MODEL: -y -> 4 -x -> 3 - -evaluating x+y -result = 7:int - -two_contexts_example1 -k!0 - -error_code_example1 -last call succeeded. -last call failed. - -error_code_example2 -before Z3_mk_iff -Z3 error: type error. - -parser_example1 -formula 0: (> x y) -formula 1: (> x 0) -sat -y -> 0 -x -> 1 - - -parser_example2 -formula: (> x y) -sat -y -> (- 1) -x -> 0 - - -parser_example3 -assert axiom: -(forall (x Int) (y Int) (= (g x y) (g y x)) :qid {k!1}) -formula: (forall (x Int) (y Int) (=> (= x y) (= (g x 0) (g 0 y))) :qid {k!1}) -valid - -parser_example4 -declaration 0: (define y Int) -declaration 1: (define sk_hack Bool Bool) -declaration 2: (define x Int) -assumption 0: (= x 20) -formula 0: (> x y) -formula 1: (> x 0) - -parser_example5 -Z3 error: parser error. -Error message: 'ERROR: line 1 column 41: could not find sort symbol 'y'. -'. - -ite_example -term: (if false 1 0) - -enum_example -(define apple[fruit:0] fruit) -(define banana[fruit:1] fruit) -(define orange[fruit:2] fruit) -(define is_apple[fruit:0] fruit Bool) -(define is_banana[fruit:1] fruit Bool) -(define is_orange[fruit:2] fruit Bool) -valid -valid -invalid -counterexample: - -valid -valid - -unsat_core_and_proof_example -unsat -proof: [unit-resolution - [def-axiom (or (or (not PredA) PredC (not PredB)) (not PredC))] - [unit-resolution - [def-axiom (or (or (not PredA) (not PredB) (not PredC)) PredC)] - [unit-resolution - [mp - [asserted (or (and PredA PredB PredC) P1)] - [monotonicity - [rewrite - (iff (and PredA PredB PredC) - (not (or (not PredA) (not PredB) (not PredC))))] - (iff (or (and PredA PredB PredC) P1) - (or (not (or (not PredA) (not PredB) (not PredC))) P1))] - (or (not (or (not PredA) (not PredB) (not PredC))) P1)] - [asserted (not P1)] - (not (or (not PredA) (not PredB) (not PredC)))] - PredC] - [unit-resolution - [mp - [asserted (or (and PredA (not PredC) PredB) P2)] - [monotonicity - [rewrite - (iff (and PredA (not PredC) PredB) - (not (or (not PredA) PredC (not PredB))))] - (iff (or (and PredA (not PredC) PredB) P2) - (or (not (or (not PredA) PredC (not PredB))) P2))] - (or (not (or (not PredA) PredC (not PredB))) P2)] - [asserted (not P2)] - (not (or (not PredA) PredC (not PredB)))] - false] - -core: -(not P2) -(not P1) - - -abstract_example -formula: (> x y) -abstracted formula: (> #0 y) - -get_implied_equalities example -Class a |-> 0 -Class b |-> 0 -Class c |-> 0 -Class d |-> 3 -Class (f a) |-> 0 -Class (f b) |-> 0 -Class (f c) |-> 0 -asserting f(a) <= b -Class a |-> 0 -Class b |-> 0 -Class c |-> 0 -Class d |-> 3 -Class (f a) |-> 0 -Class (f b) |-> 0 -Class (f c) |-> 0 From 03a5c88dedfc148308c04be596adc56ed251d674 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 15:07:33 +0000 Subject: [PATCH 248/646] More new ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 3 + scripts/mk_util.py | 89 ++++++++++++++++++++++++++++++ scripts/update_api.py | 125 ++++++++++++++++++++++++------------------ 3 files changed, 164 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 65a69bf51..3c4fb1218 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ src/api/java/enumerations/*.java *.bak doc/api doc/code +src/api/ml/z3_native.c +src/api/ml/z3_native.ml +src/api/ml/z3_enums.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index cb6b17cce..8543f1ffa 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -49,6 +49,7 @@ UTIL_COMPONENT='util' API_COMPONENT='api' DOTNET_COMPONENT='dotnet' JAVA_COMPONENT='java' +ML_COMPONENT='ml' CPP_COMPONENT='cpp' ##################### IS_WINDOWS=False @@ -2230,6 +2231,8 @@ def mk_bindings(api_files): if is_java_enabled(): check_java() mk_z3consts_java(api_files) + if is_ml_enabled(): + mk_z3consts_ml(api_files) _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3py_to_build() @@ -2503,6 +2506,92 @@ def mk_z3consts_java(api_files): if VERBOSE: print("Generated '%s'" % ('%s' % gendir)) +# Extract enumeration types from z3_api.h, and add ML definitions +def mk_z3consts_ml(api_files): + blank_pat = re.compile("^ *$") + comment_pat = re.compile("^ *//.*$") + typedef_pat = re.compile("typedef enum *") + typedef2_pat = re.compile("typedef enum { *") + openbrace_pat = re.compile("{ *") + closebrace_pat = re.compile("}.*;") + + ml = get_component(ML_COMPONENT) + + DeprecatedEnums = [ 'Z3_search_failure' ] + gendir = ml.src_dir + if not os.path.exists(gendir): + os.mkdir(gendir) + + efile = open('%s.ml' % os.path.join(gendir, "z3_enums"), 'w') + efile.write('(* Automatically generated file *)\n\n') + # efile.write('module z3_enums = struct\n\n'); + + + for api_file in api_files: + api_file_c = ml.find_file(api_file, ml.name) + api_file = os.path.join(api_file_c.src_dir, api_file) + + api = open(api_file, 'r') + + SEARCHING = 0 + FOUND_ENUM = 1 + IN_ENUM = 2 + + mode = SEARCHING + decls = {} + idx = 0 + + linenum = 1 + for line in api: + m1 = blank_pat.match(line) + m2 = comment_pat.match(line) + if m1 or m2: + # skip blank lines and comments + linenum = linenum + 1 + elif mode == SEARCHING: + m = typedef_pat.match(line) + if m: + mode = FOUND_ENUM + m = typedef2_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + elif mode == FOUND_ENUM: + m = openbrace_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + else: + assert False, "Invalid %s, line: %s" % (api_file, linenum) + else: + assert mode == IN_ENUM + words = re.split('[^\-a-zA-Z0-9_]+', line) + m = closebrace_pat.match(line) + if m: + name = words[1] + if name not in DeprecatedEnums: + efile.write('\n(* %s *)\n' % name) + efile.write('type %s =\n' % name[3:]) # strip Z3_ + efile.write + for k, i in decls.iteritems(): + efile.write(' | %s \n' % k[3:]) # strip Z3_ + mode = SEARCHING + else: + if words[2] != '': + if len(words[2]) > 1 and words[2][1] == 'x': + idx = int(words[2], 16) + else: + idx = int(words[2]) + decls[words[1]] = idx + idx = idx + 1 + linenum = linenum + 1 + efile.write('\n') + # efile.write'end\n'); + if VERBOSE: + print "Generated '%s/z3_enums.ml'" % ('%s' % gendir) + def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 9ef0ce9a2..1e86dc0ef 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -156,9 +156,9 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} # Mapping to ML types -Type2ML = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', - STRING : 'char*', STRING_PTR : 'char**', - BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int' } +Type2ML = { VOID : 'unit', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', + STRING : 'string', STRING_PTR : 'char**', + BOOL : 'lbool', SYMBOL : 'symbol', PRINT_MODE : 'ast_print_mode', ERROR_CODE : 'error_code' } next_type_id = FIRST_OBJ_ID @@ -332,13 +332,13 @@ def param2ml(p): elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: return "long*" elif param_type(p) == STRING: - return "char*" + return "string" else: print "ERROR: unreachable code" assert(False) exit(1) if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: - return "%s[]" % type2ml(param_type(p)) + return "%s array" % type2ml(param_type(p)) else: return type2ml(param_type(p)) @@ -1069,9 +1069,7 @@ def mk_bindings(): exe_c.write("}\n") def ml_method_name(name): - result = '' - name = name[3:] # Remove Z3_ - return result + return name[3:] # Remove Z3_ def mk_ml(): if not is_ml_enabled(): @@ -1080,10 +1078,57 @@ def mk_ml(): ml_nativef = os.path.join(ml_dir, 'z3_native.ml') ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') ml_native = open(ml_nativef, 'w') - ml_native.write('// Automatically generated file\n') + ml_native.write('(* Automatically generated file *)\n') ml_native.write('\n') + ml_native.write('module Z3 = struct\n\n') + ml_native.write('type context\n') + ml_native.write('and symbol\n') + ml_native.write('and ast\n') + ml_native.write('and sort = private ast\n') + ml_native.write('and func_decl = private ast\n') + ml_native.write('and app = private ast\n') + ml_native.write('and pattern = private ast\n') + ml_native.write('and params\n') + ml_native.write('and param_descrs\n') + ml_native.write('and model\n') + ml_native.write('and func_interp\n') + ml_native.write('and func_entry\n') + ml_native.write('and fixedpoint\n') + ml_native.write('and ast_vector\n') + ml_native.write('and ast_map\n') + ml_native.write('and goal\n') + ml_native.write('and tactic\n') + ml_native.write('and probe\n') + ml_native.write('and apply_result\n') + ml_native.write('and solver\n') + ml_native.write('and stats\n') + ml_native.write('\n') + ml_native.write(' exception Z3Exception of string\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external %s : (' % ml_method_name(name)) + ml_native.write(' external native_%s : ' % ml_method_name(name)) + i = 0; + for param in params: + ml_native.write('%s -> ' % param2ml(param)) + i = i + 1 + ml_native.write('%s\n' % (type2ml(result))) + ml_native.write(' = "Native_Z3_%s"\n\n' % ml_method_name(name)) + # Exception wrappers + for name, result, params in _dotnet_decls: + ml_native.write(' let %s ' % ml_method_name(name)) + first = True + i = 0; + for param in params: + if first: + first = False; + else: + ml_native.write(' ') + ml_native.write('a%d' % i) + i = i + 1 + ml_native.write(' = \n') + ml_native.write(' ') + if result != VOID: + ml_native.write('let res = ') + ml_native.write('n_%s(' % (ml_method_name(name))) first = True i = 0; for param in params: @@ -1091,50 +1136,24 @@ def mk_ml(): first = False else: ml_native.write(', ') - ml_native.write('%s a%d' % (param2ml(param), i)) + ml_native.write('a%d' % i) i = i + 1 - ml_native.write('%s)\n' % (type2ml(result))) - # ml_native.write(' = "NATIVE_%s"' % ml_method_name(name)) - # ml_native.write('\n\n') - # # Exception wrappers - # for name, result, params in _dotnet_decls: - # java_native.write(' public static %s %s(' % (type2java(result), java_method_name(name))) - # first = True - # i = 0; - # for param in params: - # if first: - # first = False - # else: - # java_native.write(', ') - # java_native.write('%s a%d' % (param2java(param), i)) - # i = i + 1 - # java_native.write(')') - # if len(params) > 0 and param_type(params[0]) == CONTEXT: - # java_native.write(' throws Z3Exception') - # java_native.write('\n') - # java_native.write(' {\n') - # java_native.write(' ') - # if result != VOID: - # java_native.write('%s res = ' % type2java(result)) - # java_native.write('INTERNAL%s(' % (java_method_name(name))) - # first = True - # i = 0; - # for param in params: - # if first: - # first = False - # else: - # java_native.write(', ') - # java_native.write('a%d' % i) - # i = i + 1 - # java_native.write(');\n') - # if len(params) > 0 and param_type(params[0]) == CONTEXT: - # java_native.write(' Z3_error_code err = Z3_error_code.fromInt(INTERNALgetErrorCode(a0));\n') - # java_native.write(' if (err != Z3_error_code.Z3_OK)\n') - # java_native.write(' throw new Z3Exception(INTERNALgetErrorMsgEx(a0, err.toInt()));\n') - # if result != VOID: - # java_native.write(' return res;\n') - # java_native.write(' }\n\n') - # java_native.write('}\n') + ml_native.write(')') + if result != VOID: + ml_native.write(' in\n') + else: + ml_native.write(';\n') + if len(params) > 0 and param_type(params[0]) == CONTEXT: + ml_native.write(' let err = error_code.fromInt(n_get_error_code(a0)) in \n') + ml_native.write(' if err <> Z3_enums.OK then\n') + ml_native.write(' raise (z3_exception n_get_error_msg_ex(a0, err.toInt()))\n') + ml_native.write(' else\n') + if result == VOID: + ml_native.write(' ()\n') + else: + ml_native.write(' res\n') + ml_native.write('\n') + ml_native.write('\nend\n') ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') ml_wrapper.write('#include \n') From f5a0520b838fa04ba5336daf35ffa268b670c6db Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 16:35:39 +0000 Subject: [PATCH 249/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 3 + scripts/mk_util.py | 6 +- scripts/update_api.py | 211 +++++++++++++------------ src/api/ml/{ => old}/Makefile | 0 src/api/ml/{ => old}/Makefile.build | 0 src/api/ml/{ => old}/test_mlapi.ml | 0 src/api/ml/{ => old}/test_mlapiV3.ml | 0 src/api/ml/{ => old}/x3.ml | 0 src/api/ml/{ => old}/z3_stubs.c | 0 src/api/ml/{ => old}/z3_theory_stubs.c | 0 10 files changed, 120 insertions(+), 100 deletions(-) rename src/api/ml/{ => old}/Makefile (100%) rename src/api/ml/{ => old}/Makefile.build (100%) rename src/api/ml/{ => old}/test_mlapi.ml (100%) rename src/api/ml/{ => old}/test_mlapiV3.ml (100%) rename src/api/ml/{ => old}/x3.ml (100%) rename src/api/ml/{ => old}/z3_stubs.c (100%) rename src/api/ml/{ => old}/z3_theory_stubs.c (100%) diff --git a/.gitignore b/.gitignore index 3c4fb1218..f2a31c21e 100644 --- a/.gitignore +++ b/.gitignore @@ -64,9 +64,12 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java + *.bak doc/api doc/code src/api/ml/z3_native.c src/api/ml/z3_native.ml +src/api/ml/native.c +src/api/ml/Z3.ml src/api/ml/z3_enums.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8543f1ffa..4249a04b0 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1286,9 +1286,9 @@ class MLComponent(Component): if is_ml_enabled(): mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) libfile = '%s$(LIB_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'z3_native.c'))) - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) %s/z3_native.c\n' % self.to_src_dir) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'z3_native')) + out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) out.write('ml: %s\n' % libfile) out.write('\n') diff --git a/scripts/update_api.py b/scripts/update_api.py index 1e86dc0ef..9acdf1040 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1075,12 +1075,12 @@ def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'z3_native.ml') - ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') + ml_nativef = os.path.join(ml_dir, 'Z3.ml') + ml_wrapperf = os.path.join(ml_dir, 'native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n') ml_native.write('\n') - ml_native.write('module Z3 = struct\n\n') + ml_native.write('module Z3Native = struct\n\n') ml_native.write('type context\n') ml_native.write('and symbol\n') ml_native.write('and ast\n') @@ -1166,101 +1166,118 @@ def mk_ml(): ml_wrapper.write('#ifdef Custom_tag\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') - ml_wrapper.write('#endif\n') - # for name, result, params in _dotnet_decls: - # java_wrapper.write('JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) - # i = 0; - # for param in params: - # java_wrapper.write(', ') - # java_wrapper.write('%s a%d' % (param2javaw(param), i)) - # i = i + 1 - # java_wrapper.write(') {\n') - # # preprocess arrays, strings, in/out arguments - # i = 0 - # for param in params: - # k = param_kind(param) - # if k == OUT or k == INOUT: - # java_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) - # elif k == IN_ARRAY or k == INOUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) - # else: - # java_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) - # elif k == OUT_ARRAY: - # java_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), - # i, - # type2str(param_type(param)), - # param_array_capacity_pos(param), - # type2str(param_type(param)))) - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - # else: - # java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) - # elif k == IN and param_type(param) == STRING: - # java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i)) - # i = i + 1 - # # invoke procedure - # java_wrapper.write(' ') - # if result != VOID: - # java_wrapper.write('%s result = ' % type2str(result)) - # java_wrapper.write('%s(' % name) - # i = 0 - # first = True - # for param in params: - # if first: - # first = False - # else: - # java_wrapper.write(', ') - # k = param_kind(param) - # if k == OUT or k == INOUT: - # java_wrapper.write('&_a%s' % i) - # elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: - # java_wrapper.write('_a%s' % i) - # elif k == IN and param_type(param) == STRING: - # java_wrapper.write('_a%s' % i) - # else: - # java_wrapper.write('(%s)a%i' % (param2str(param), i)) - # i = i + 1 - # java_wrapper.write(');\n') - # # cleanup - # i = 0 - # for param in params: - # k = param_kind(param) - # if k == OUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - # else: - # java_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) - # java_wrapper.write(' free(_a%s);\n' % i) - # elif k == IN_ARRAY or k == OUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) - # else: - # java_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) + ml_wrapper.write('#endif\n\n') + ml_wrapper.write('#include \n\n') + for name, result, params in _dotnet_decls: + #return type = type2ml(result) + ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) + first = True + i = 0 + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('value a%d' % i) + # param type = param2ml(param) + i = i + 1 + ml_wrapper.write(') {\n') + ml_wrapper.write(' CAMLparam%d(' % len(params)) + i = 0 + first = True + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('a%d' % i) + i = i + 1 + ml_wrapper.write(');\n') + # preprocess arrays, strings, in/out arguments + i = 0 + for param in params: + k = param_kind(param) + if k == OUT or k == INOUT: + ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + elif k == IN_ARRAY or k == INOUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) + else: + ml_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) + elif k == OUT_ARRAY: + ml_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), + i, + type2str(param_type(param)), + param_array_capacity_pos(param), + type2str(param_type(param)))) + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + else: + ml_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) + elif k == IN and param_type(param) == STRING: + ml_wrapper.write(' Z3_string _a%s = (Z3_string) String_val(a%s);\n' % (i, i)) + i = i + 1 + # invoke procedure + ml_wrapper.write(' ') + if result != VOID: + ml_wrapper.write('%s result = ' % type2str(result)) + ml_wrapper.write('%s(' % name) + i = 0 + first = True + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + k = param_kind(param) + if k == OUT or k == INOUT: + ml_wrapper.write('&_a%s' % i) + elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + ml_wrapper.write('_a%s' % i) + elif k == IN and param_type(param) == STRING: + ml_wrapper.write('_a%s' % i) + else: + ml_wrapper.write('(%s)a%i' % (param2str(param), i)) + i = i + 1 + ml_wrapper.write(');\n') + # cleanup + i = 0 + for param in params: + k = param_kind(param) + if k == OUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + else: + ml_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) + ml_wrapper.write(' free(_a%s);\n' % i) + elif k == IN_ARRAY or k == OUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) + else: + ml_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) - # elif k == OUT or k == INOUT: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' {\n') - # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') - # java_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) - # java_wrapper.write(' }\n') - # else: - # java_wrapper.write(' {\n') - # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') - # java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) - # java_wrapper.write(' }\n') - # i = i + 1 - # # return - # if result == STRING: - # java_wrapper.write(' return jenv->NewStringUTF(result);\n') - # elif result != VOID: - # java_wrapper.write(' return (%s) result;\n' % type2javaw(result)) - # java_wrapper.write('}\n') - # java_wrapper.write('#ifdef __cplusplus\n') - # java_wrapper.write('}\n') - # java_wrapper.write('#endif\n') + elif k == OUT or k == INOUT: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' {\n') + ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') + ml_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) + ml_wrapper.write(' }\n') + else: + ml_wrapper.write(' {\n') + ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') + ml_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) + ml_wrapper.write(' }\n') + i = i + 1 + # return + if result == STRING: + ml_wrapper.write(' return caml_copy_string(result);\n') + elif result == VOID: + ml_wrapper.write(' CAMLreturn(Val_unit);\n') + elif result != VOID: + ml_wrapper.write(' return (value) result;\n') + ml_wrapper.write('}\n\n') if is_verbose(): print "Generated '%s'" % ml_nativef diff --git a/src/api/ml/Makefile b/src/api/ml/old/Makefile similarity index 100% rename from src/api/ml/Makefile rename to src/api/ml/old/Makefile diff --git a/src/api/ml/Makefile.build b/src/api/ml/old/Makefile.build similarity index 100% rename from src/api/ml/Makefile.build rename to src/api/ml/old/Makefile.build diff --git a/src/api/ml/test_mlapi.ml b/src/api/ml/old/test_mlapi.ml similarity index 100% rename from src/api/ml/test_mlapi.ml rename to src/api/ml/old/test_mlapi.ml diff --git a/src/api/ml/test_mlapiV3.ml b/src/api/ml/old/test_mlapiV3.ml similarity index 100% rename from src/api/ml/test_mlapiV3.ml rename to src/api/ml/old/test_mlapiV3.ml diff --git a/src/api/ml/x3.ml b/src/api/ml/old/x3.ml similarity index 100% rename from src/api/ml/x3.ml rename to src/api/ml/old/x3.ml diff --git a/src/api/ml/z3_stubs.c b/src/api/ml/old/z3_stubs.c similarity index 100% rename from src/api/ml/z3_stubs.c rename to src/api/ml/old/z3_stubs.c diff --git a/src/api/ml/z3_theory_stubs.c b/src/api/ml/old/z3_theory_stubs.c similarity index 100% rename from src/api/ml/z3_theory_stubs.c rename to src/api/ml/old/z3_theory_stubs.c From 65ddf2be491719af481c93c6140a17271fa201e4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 21:39:52 +0000 Subject: [PATCH 250/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 5 ++-- scripts/mk_util.py | 42 +++++++++++++++++++++--------- scripts/update_api.py | 59 +++++++++++++++++++++++-------------------- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/.gitignore b/.gitignore index f2a31c21e..95c44e557 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ callgrind.out.* # OCaml generated files *.a *.cma +*.cmo *.cmi *.cmxa ocamlz3 @@ -71,5 +72,5 @@ doc/code src/api/ml/z3_native.c src/api/ml/z3_native.ml src/api/ml/native.c -src/api/ml/Z3.ml -src/api/ml/z3_enums.ml +src/api/ml/z3.ml +src/api/ml/enumerations.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4249a04b0..31e64b10e 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -672,6 +672,9 @@ def get_cs_files(path): def get_java_files(path): return filter(lambda f: f.endswith('.java'), os.listdir(path)) +def get_ml_files(path): + return filter(lambda f: f.endswith('.ml'), os.listdir(path)) + def find_all_deps(name, deps): new_deps = [] for dep in deps: @@ -1284,9 +1287,17 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): - mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) + bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') + mk_dir(bld_dir) libfile = '%s$(LIB_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + for mlfile in get_ml_files(self.src_dir): + out.write('%si: %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) + out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) + out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) + out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + for mlfile in get_ml_files(self.src_dir): + out.write(' %si' % os.path.join('api','ml', mlfile)) + out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) out.write('ml: %s\n' % libfile) @@ -2522,11 +2533,9 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) - efile = open('%s.ml' % os.path.join(gendir, "z3_enums"), 'w') + efile = open('%s.ml' % os.path.join(gendir, "enumerations"), 'w') efile.write('(* Automatically generated file *)\n\n') - # efile.write('module z3_enums = struct\n\n'); - - + efile.write('module Enumerations = struct\n') for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2572,11 +2581,21 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: - efile.write('\n(* %s *)\n' % name) efile.write('type %s =\n' % name[3:]) # strip Z3_ - efile.write for k, i in decls.iteritems(): - efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write('\n') + efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in decls.iteritems(): + efile.write(' | %s -> %d\n' % (k[3:], i)) + efile.write('\n') + efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in decls.iteritems(): + efile.write(' | %d -> %s\n' % (i, k[3:])) + # use Z3.Exception? + efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') mode = SEARCHING else: if words[2] != '': @@ -2587,10 +2606,9 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 - efile.write('\n') - # efile.write'end\n'); + efile.write('end\n') if VERBOSE: - print "Generated '%s/z3_enums.ml'" % ('%s' % gendir) + print "Generated '%s/enumerations.ml'" % ('%s' % gendir) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 9acdf1040..b8295405e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -156,9 +156,9 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} # Mapping to ML types -Type2ML = { VOID : 'unit', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', - STRING : 'string', STRING_PTR : 'char**', - BOOL : 'lbool', SYMBOL : 'symbol', PRINT_MODE : 'ast_print_mode', ERROR_CODE : 'error_code' } +Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', + STRING : 'string', STRING_PTR : 'char**', + BOOL : 'int', SYMBOL : 'symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -212,7 +212,7 @@ def type2javaw(ty): def type2ml(ty): global Type2ML if (ty >= FIRST_OBJ_ID): - return 'long' + return 'int' else: return Type2ML[ty] @@ -328,9 +328,9 @@ def param2ml(p): k = param_kind(p) if k == OUT: if param_type(p) == INT or param_type(p) == UINT: - return "int*" + return "int" elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: - return "long*" + return "int" elif param_type(p) == STRING: return "string" else: @@ -1075,12 +1075,12 @@ def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'Z3.ml') + ml_nativef = os.path.join(ml_dir, 'z3.ml') ml_wrapperf = os.path.join(ml_dir, 'native.c') ml_native = open(ml_nativef, 'w') - ml_native.write('(* Automatically generated file *)\n') - ml_native.write('\n') - ml_native.write('module Z3Native = struct\n\n') + ml_native.write('(* Automatically generated file *)\n\n') + ml_native.write('open Enumerations\n\n') + ml_native.write('module Z3 = struct\n\n') ml_native.write('type context\n') ml_native.write('and symbol\n') ml_native.write('and ast\n') @@ -1103,15 +1103,17 @@ def mk_ml(): ml_native.write('and solver\n') ml_native.write('and stats\n') ml_native.write('\n') - ml_native.write(' exception Z3Exception of string\n\n') + ml_native.write(' exception Exception of string\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external native_%s : ' % ml_method_name(name)) + ml_native.write(' external n_%s : ' % ml_method_name(name)) i = 0; for param in params: ml_native.write('%s -> ' % param2ml(param)) i = i + 1 + if len(params) == 0: + ml_native.write(' unit -> ') ml_native.write('%s\n' % (type2ml(result))) - ml_native.write(' = "Native_Z3_%s"\n\n' % ml_method_name(name)) + ml_native.write(' = "n_%s"\n\n' % ml_method_name(name)) # Exception wrappers for name, result, params in _dotnet_decls: ml_native.write(' let %s ' % ml_method_name(name)) @@ -1128,25 +1130,28 @@ def mk_ml(): ml_native.write(' ') if result != VOID: ml_native.write('let res = ') - ml_native.write('n_%s(' % (ml_method_name(name))) - first = True - i = 0; - for param in params: - if first: - first = False - else: - ml_native.write(', ') - ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(')') + if len(params) == 0: + ml_native.write('n_%s()' % (ml_method_name(name))) + else: + ml_native.write('(n_%s ' % (ml_method_name(name))) + first = True + i = 0; + for param in params: + if first: + first = False + else: + ml_native.write(' ') + ml_native.write('a%d' % i) + i = i + 1 + ml_native.write(')') if result != VOID: ml_native.write(' in\n') else: ml_native.write(';\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = error_code.fromInt(n_get_error_code(a0)) in \n') - ml_native.write(' if err <> Z3_enums.OK then\n') - ml_native.write(' raise (z3_exception n_get_error_msg_ex(a0, err.toInt()))\n') + ml_native.write(' let err = (Enumerations.int2error_code (n_get_error_code a0)) in \n') + ml_native.write(' if err <> Enumerations.OK then\n') + ml_native.write(' raise (Exception (n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') From 8d30fabc0a556ba3ef239958fcf37feb096a257e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:34:36 +0000 Subject: [PATCH 251/646] New native ML API layer. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 35 ++-- scripts/update_api.py | 400 +++++++++++++++++++++++++++--------------- 2 files changed, 286 insertions(+), 149 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 31e64b10e..962f15670 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1287,20 +1287,31 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): + deffile = open('%s.mllib' % os.path.join(self.src_dir, "z3"), 'w') + for mlfile in get_ml_files(self.src_dir): + deffile.write('%s\n' % (string.upper(mlfile[0]) + mlfile[1:-3])) + deffile.close() + bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') mk_dir(bld_dir) - libfile = '%s$(LIB_EXT)' % self.lib_name + libfile = '%s$(SO_EXT)' % self.lib_name + # for mlfile in get_ml_files(self.src_dir): + # out.write('%si: libz3$(SO_EXT) %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) + # out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) + # out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) + out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) for mlfile in get_ml_files(self.src_dir): - out.write('%si: %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) - out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) - out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) - out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) - for mlfile in get_ml_files(self.src_dir): - out.write(' %si' % os.path.join('api','ml', mlfile)) + out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) - out.write('ml: %s\n' % libfile) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + out.write('z3.cmxa: %s\n' % libfile) + out.write('\tcd %s && ocamlbuild -lflags -cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cmxa && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) + out.write('\tcp api/ml/z3.cmxa .\n') + out.write('z3.cma: %s\n' % libfile) + out.write('\tcd %s && ocamlbuild -lflags -custom,-cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) + out.write('\tcp api/ml/z3.cma .\n') + out.write('ml: z3.cmxa z3.cma\n') out.write('\n') def main_component(self): @@ -2533,9 +2544,9 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) - efile = open('%s.ml' % os.path.join(gendir, "enumerations"), 'w') + efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') - efile.write('module Enumerations = struct\n') + efile.write('module Z3enums = struct\n') for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) diff --git a/scripts/update_api.py b/scripts/update_api.py index b8295405e..b613ce79d 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1071,98 +1071,145 @@ def mk_bindings(): def ml_method_name(name): return name[3:] # Remove Z3_ +def is_out_param(p): + if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + return True + else: + return False + +def outparams(params): + op = [] + for param in params: + if is_out_param(param): + op.append(param) + return op + +def is_in_param(p): + if param_kind(p) == IN or param_kind(p) == INOUT or param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY: + return True + else: + return False + +def inparams(params): + ip = [] + for param in params: + if is_in_param(param): + ip.append(param) + return ip + +def is_array_param(p): + if param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_ARRAY: + return True + else: + return False + def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'z3.ml') - ml_wrapperf = os.path.join(ml_dir, 'native.c') + ml_nativef = os.path.join(ml_dir, 'z3native.ml') + ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') - ml_native.write('open Enumerations\n\n') - ml_native.write('module Z3 = struct\n\n') - ml_native.write('type context\n') - ml_native.write('and symbol\n') - ml_native.write('and ast\n') - ml_native.write('and sort = private ast\n') - ml_native.write('and func_decl = private ast\n') - ml_native.write('and app = private ast\n') - ml_native.write('and pattern = private ast\n') - ml_native.write('and params\n') - ml_native.write('and param_descrs\n') - ml_native.write('and model\n') - ml_native.write('and func_interp\n') - ml_native.write('and func_entry\n') - ml_native.write('and fixedpoint\n') - ml_native.write('and ast_vector\n') - ml_native.write('and ast_map\n') - ml_native.write('and goal\n') - ml_native.write('and tactic\n') - ml_native.write('and probe\n') - ml_native.write('and apply_result\n') - ml_native.write('and solver\n') - ml_native.write('and stats\n') - ml_native.write('\n') + ml_native.write('open Z3enums\n\n') + ml_native.write('module Z3native = struct\n\n') + ml_native.write(' type context\n') + ml_native.write(' and symbol\n') + ml_native.write(' and ast\n') + ml_native.write(' and sort = private ast\n') + ml_native.write(' and func_decl = private ast\n') + ml_native.write(' and app = private ast\n') + ml_native.write(' and pattern = private ast\n') + ml_native.write(' and params\n') + ml_native.write(' and param_descrs\n') + ml_native.write(' and model\n') + ml_native.write(' and func_interp\n') + ml_native.write(' and func_entry\n') + ml_native.write(' and fixedpoint\n') + ml_native.write(' and ast_vector\n') + ml_native.write(' and ast_map\n') + ml_native.write(' and goal\n') + ml_native.write(' and tactic\n') + ml_native.write(' and probe\n') + ml_native.write(' and apply_result\n') + ml_native.write(' and solver\n') + ml_native.write(' and stats\n\n') ml_native.write(' exception Exception of string\n\n') + + # ML declarations + ml_native.write(' module ML2C = struct\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external n_%s : ' % ml_method_name(name)) - i = 0; - for param in params: - ml_native.write('%s -> ' % param2ml(param)) - i = i + 1 - if len(params) == 0: + ml_native.write(' external n_%s : ' % ml_method_name(name)) + ip = inparams(params) + op = outparams(params) + if len(ip) == 0: ml_native.write(' unit -> ') - ml_native.write('%s\n' % (type2ml(result))) - ml_native.write(' = "n_%s"\n\n' % ml_method_name(name)) + for p in ip: + ml_native.write('%s -> ' % param2ml(p)) + if len(op) > 0: + ml_native.write('(') + ml_native.write('%s' % type2ml(result)) + for p in op: + ml_native.write(' * %s' % param2ml(p)) + if len(op) > 0: + ml_native.write(')') + ml_native.write('\n') + ml_native.write(' = "n_%s"\n' % ml_method_name(name)) + if len(ip) > 5: + ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write('\n') + ml_native.write(' end\n\n') + # Exception wrappers for name, result, params in _dotnet_decls: - ml_native.write(' let %s ' % ml_method_name(name)) + ip = inparams(params) + op = outparams(params) + ml_native.write(' let %s ' % ml_method_name(name)) first = True i = 0; - for param in params: - if first: - first = False; - else: - ml_native.write(' ') - ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(' = \n') - ml_native.write(' ') - if result != VOID: - ml_native.write('let res = ') - if len(params) == 0: - ml_native.write('n_%s()' % (ml_method_name(name))) - else: - ml_native.write('(n_%s ' % (ml_method_name(name))) - first = True - i = 0; - for param in params: + for p in params: + if is_in_param(p): if first: - first = False + first = False; else: ml_native.write(' ') ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(')') - if result != VOID: - ml_native.write(' in\n') + i = i + 1 + ml_native.write(' = \n') + ml_native.write(' ') + if result == VOID: + ml_native.write('let _ = ') else: - ml_native.write(';\n') + ml_native.write('let res = ') + ml_native.write('(ML2C.n_%s' % (ml_method_name(name))) + first = True + i = 0; + for p in params: + if is_in_param(p): + ml_native.write(' a%d' % i) + i = i + 1 + ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (Enumerations.int2error_code (n_get_error_code a0)) in \n') - ml_native.write(' if err <> Enumerations.OK then\n') - ml_native.write(' raise (Exception (n_get_error_msg_ex a0 (error_code2int err)))\n') + ml_native.write(' let err = (Z3enums.int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' if err <> Z3enums.OK then\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (Z3enums.error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') else: ml_native.write(' res\n') ml_native.write('\n') - ml_native.write('\nend\n') + + ml_native.write('end\n') + + # C interface ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') ml_wrapper.write('#include \n') - ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('extern "C" {\n') + ml_wrapper.write('#endif\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') @@ -1171,61 +1218,119 @@ def mk_ml(): ml_wrapper.write('#ifdef Custom_tag\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') + ml_wrapper.write('#endif\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('}\n') ml_wrapper.write('#endif\n\n') ml_wrapper.write('#include \n\n') + ml_wrapper.write('#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal1(X6); \n') + ml_wrapper.write('#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal2(X6,X7); \n') + ml_wrapper.write('#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal3(X6,X7,X8); \n') + ml_wrapper.write('\n') + ml_wrapper.write('#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam2(X6,X7); \n') + ml_wrapper.write('#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam3(X6,X7,X8); \n') + ml_wrapper.write('#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9); \n') + ml_wrapper.write('#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') + ml_wrapper.write(' CAMLxparam2(X11,X12); \n') + ml_wrapper.write('#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') + ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') + ml_wrapper.write('\n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('extern "C" {\n') + ml_wrapper.write('#endif\n\n') for name, result, params in _dotnet_decls: - #return type = type2ml(result) + ip = inparams(params) + op = outparams(params) + ret_size = len(op) + if result != VOID: + ret_size = ret_size + 1 + + # Setup frame + n_locals = 0 + for p in params: + if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): + n_locals = n_locals + 1 ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) first = True i = 0 - for param in params: - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('value a%d' % i) - # param type = param2ml(param) + for p in params: + if is_in_param(p): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('value a%d' % i) i = i + 1 ml_wrapper.write(') {\n') - ml_wrapper.write(' CAMLparam%d(' % len(params)) + ml_wrapper.write(' CAMLparam%d(' % len(ip)) i = 0 first = True - for param in params: - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('a%d' % i) + for p in params: + if is_in_param(p): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('a%d' % i) i = i + 1 ml_wrapper.write(');\n') + i = 0 + first = True + if result != VOID: + n_locals = n_locals + 1 + if ret_size > 1: + n_locals = n_locals + 1 + if n_locals > 0: + ml_wrapper.write(' CAMLlocal%s(' % (n_locals)) + if ret_size > 1: + if result != VOID: + ml_wrapper.write('result, ') + ml_wrapper.write('result_tuple') + first = False + elif result != VOID: + ml_wrapper.write('result') + first = False + for p in params: + if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('_a%s' % i) + i = i + 1 + ml_wrapper.write(');\n') + # preprocess arrays, strings, in/out arguments i = 0 for param in params: - k = param_kind(param) - if k == OUT or k == INOUT: - ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) - elif k == IN_ARRAY or k == INOUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) - else: - ml_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) - elif k == OUT_ARRAY: - ml_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), - i, - type2str(param_type(param)), - param_array_capacity_pos(param), - type2str(param_type(param)))) - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - else: - ml_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) - elif k == IN and param_type(param) == STRING: - ml_wrapper.write(' Z3_string _a%s = (Z3_string) String_val(a%s);\n' % (i, i)) + if param_kind(param) == OUT_ARRAY: + ml_wrapper.write(' _a%s = (long) malloc(sizeof(%s) * ((long)a%s));\n' % (i, + type2str(param_type(param)), + param_array_capacity_pos(param))) + elif param_kind(param) == IN and param_type(param) == STRING: + ml_wrapper.write(' _a%s = (value) String_val(a%s);\n' % (i, i)) i = i + 1 + # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('%s result = ' % type2str(result)) + ml_wrapper.write('result = (value) ') ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1236,53 +1341,74 @@ def mk_ml(): ml_wrapper.write(', ') k = param_kind(param) if k == OUT or k == INOUT: - ml_wrapper.write('&_a%s' % i) - elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: - ml_wrapper.write('_a%s' % i) + ml_wrapper.write('(%s)&_a%s' % (param2str(param), i)) + elif k == INOUT_ARRAY or k == IN_ARRAY: + ml_wrapper.write('(%s*)a%s' % (type2str(param_type(param)), i)) + elif k == OUT_ARRAY: + ml_wrapper.write('(%s*)_a%s' % (type2str(param_type(param)), i)) elif k == IN and param_type(param) == STRING: - ml_wrapper.write('_a%s' % i) + ml_wrapper.write('(Z3_string) _a%s' % i) else: ml_wrapper.write('(%s)a%i' % (param2str(param), i)) i = i + 1 ml_wrapper.write(');\n') - # cleanup - i = 0 - for param in params: - k = param_kind(param) - if k == OUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - else: - ml_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) - ml_wrapper.write(' free(_a%s);\n' % i) - elif k == IN_ARRAY or k == OUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) - else: - ml_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) - elif k == OUT or k == INOUT: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' {\n') - ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') - ml_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) - ml_wrapper.write(' }\n') + # return tuples + if len(op) > 0: + ml_wrapper.write(' result_tuple = caml_alloc(%s, 0);\n' % ret_size) + i = j = 0 + if result != VOID: + if result == STRING: + ml_wrapper.write(' Store_field(result_tuple, 0, caml_copy_string(result));\n') else: - ml_wrapper.write(' {\n') - ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') - ml_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) - ml_wrapper.write(' }\n') + ml_wrapper.write(' Store_field(result_tuple, 0, result);\n') + j = j + 1 + for p in params: + if param_kind(p) == OUT_ARRAY or param_kind(p) == OUT: + ml_wrapper.write(' Store_field(result_tuple, %s, _a%s);\n' % (j, i)) + j = j + 1; + elif is_out_param(p): + if param_type(p) == STRING: + ml_wrapper.write(' Store_field(result_tuple, %s, caml_copy_string((const char *)_a%s));\n' % (j, i)) + else: + ml_wrapper.write(' Store_field(result_tuple, %s, a%s);\n' % (j, i)) + j = j + 1; + i = i + 1 + + # local array cleanup + i = 0 + for p in params: + if param_kind(p) == OUT_ARRAY: + ml_wrapper.write(' free((long*)_a%s);\n' % i) i = i + 1 + # return - if result == STRING: - ml_wrapper.write(' return caml_copy_string(result);\n') - elif result == VOID: - ml_wrapper.write(' CAMLreturn(Val_unit);\n') - elif result != VOID: - ml_wrapper.write(' return (value) result;\n') + if len(op) > 0: + ml_wrapper.write(' CAMLreturn(result_tuple);\n') + else: + if result == STRING: + ml_wrapper.write(' CAMLreturn(caml_copy_string((const char*) result));\n') + elif result == VOID: + ml_wrapper.write(' CAMLreturn(Val_unit);\n') + elif result != VOID: + ml_wrapper.write(' CAMLreturn(result);\n') + ml_wrapper.write('}\n\n') + if len(ip) > 5: + ml_wrapper.write('CAMLprim value n_%s_bytecode(value * argv, int argn) {\n' % ml_method_name(name)) + ml_wrapper.write(' return n_%s(' % ml_method_name(name)) + i = 0 + while i < len(ip): + if i == 0: + ml_wrapper.write('argv[0]') + else: + ml_wrapper.write(', argv[%s]' % i) + i = i + 1 + ml_wrapper.write(');\n}\n') + ml_wrapper.write('\n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('}\n') + ml_wrapper.write('#endif\n') if is_verbose(): print "Generated '%s'" % ml_nativef From d5f135c4325772297fd49e24b22a0984044c6eb4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:37:32 +0000 Subject: [PATCH 252/646] More new ML API. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 705f9a3e7..61ac503a0 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,3 +1,4 @@ +<<<<<<< HEAD (* File generated from z3.idl *) type context @@ -3383,3 +3384,16 @@ let set_new_relevant_callback th cb = end +======= +(* + Author: CM Wintersteiger + (C) Microsoft Research, 2012 +*) + +open Z3enums +open Z3native + +module Z3 = struct + +end +>>>>>>> More new ML API. From a965d65901ba6698f3ac13a8dbcb69d23f8b2610 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:37:46 +0000 Subject: [PATCH 253/646] ML API temp files added to .gitignore Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 95c44e557..fccf9424d 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,6 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java - *.bak doc/api doc/code @@ -74,3 +73,7 @@ src/api/ml/z3_native.ml src/api/ml/native.c src/api/ml/z3.ml src/api/ml/enumerations.ml +src/api/ml/z3native.c +src/api/ml/z3native.ml +src/api/ml/z3enums.ml +src/api/ml/z3.mllib From 2dde851ed7ec60719efb3290999d0fb41a45e3c8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 08:06:10 +0000 Subject: [PATCH 254/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 ++- scripts/update_api.py | 58 +++++++++---------------------- src/api/ml/z3.ml | 80 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 962f15670..c17df82e6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -458,7 +458,8 @@ def display_help(exit_code): if IS_WINDOWS: print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.") print(" -j, --java generate Java bindings.") - print(" --staticlib build Z3 static library.") + print(" --ml generate Ocaml bindinds.") + print(" --staticlib build Z3 static library.") if not IS_WINDOWS: print(" -g, --gmp use GMP.") print(" --gprof enable gprof") @@ -2546,7 +2547,6 @@ def mk_z3consts_ml(api_files): efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') - efile.write('module Z3enums = struct\n') for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2617,7 +2617,6 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 - efile.write('end\n') if VERBOSE: print "Generated '%s/enumerations.ml'" % ('%s' % gendir) diff --git a/scripts/update_api.py b/scripts/update_api.py index b613ce79d..9eb7d1405 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -158,7 +158,7 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I # Mapping to ML types Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', STRING : 'string', STRING_PTR : 'char**', - BOOL : 'int', SYMBOL : 'symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } + BOOL : 'int', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -182,6 +182,7 @@ def def_Types(): v = Type2Str[k] if is_obj(k): Type2Dotnet[k] = v + Type2ML[k] = v.lower() def type2str(ty): global Type2Str @@ -211,10 +212,7 @@ def type2javaw(ty): def type2ml(ty): global Type2ML - if (ty >= FIRST_OBJ_ID): - return 'int' - else: - return Type2ML[ty] + return Type2ML[ty] def _in(ty): return (IN, ty); @@ -327,17 +325,11 @@ def param2pystr(p): def param2ml(p): k = param_kind(p) if k == OUT: - if param_type(p) == INT or param_type(p) == UINT: - return "int" - elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: - return "int" - elif param_type(p) == STRING: + if param_type(p) == STRING: return "string" else: - print "ERROR: unreachable code" - assert(False) - exit(1) - if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: + return "ptr" + elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: return "%s array" % type2ml(param_type(p)) else: return type2ml(param_type(p)) @@ -1104,6 +1096,7 @@ def is_array_param(p): return False def mk_ml(): + global Type2Str if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir @@ -1112,29 +1105,12 @@ def mk_ml(): ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') ml_native.write('open Z3enums\n\n') - ml_native.write('module Z3native = struct\n\n') - ml_native.write(' type context\n') - ml_native.write(' and symbol\n') - ml_native.write(' and ast\n') - ml_native.write(' and sort = private ast\n') - ml_native.write(' and func_decl = private ast\n') - ml_native.write(' and app = private ast\n') - ml_native.write(' and pattern = private ast\n') - ml_native.write(' and params\n') - ml_native.write(' and param_descrs\n') - ml_native.write(' and model\n') - ml_native.write(' and func_interp\n') - ml_native.write(' and func_entry\n') - ml_native.write(' and fixedpoint\n') - ml_native.write(' and ast_vector\n') - ml_native.write(' and ast_map\n') - ml_native.write(' and goal\n') - ml_native.write(' and tactic\n') - ml_native.write(' and probe\n') - ml_native.write(' and apply_result\n') - ml_native.write(' and solver\n') - ml_native.write(' and stats\n\n') - ml_native.write(' exception Exception of string\n\n') + ml_native.write('type ptr\n') + ml_native.write('and z3_symbol = ptr\n') + for k, v in Type2Str.iteritems(): + if is_obj(k): + ml_native.write('and %s = ptr\n' % v.lower()) + ml_native.write('\nexception Exception of string\n\n') # ML declarations ml_native.write(' module ML2C = struct\n\n') @@ -1190,9 +1166,9 @@ def mk_ml(): i = i + 1 ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (Z3enums.int2error_code (ML2C.n_get_error_code a0)) in \n') - ml_native.write(' if err <> Z3enums.OK then\n') - ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (Z3enums.error_code2int err)))\n') + ml_native.write(' let err = (int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' if err <> OK then\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') @@ -1200,8 +1176,6 @@ def mk_ml(): ml_native.write(' res\n') ml_native.write('\n') - ml_native.write('end\n') - # C interface ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 61ac503a0..b00569da1 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -3388,12 +3388,88 @@ end (* Author: CM Wintersteiger (C) Microsoft Research, 2012 -*) + *) open Z3enums open Z3native -module Z3 = struct +class context = + object (self) + val m_n_ctx : Z3native.z3_context option = None + val mutable m_refCount : int = 0 + initializer Gc.finalise (fun self -> self#dispose ()) self + method dispose () = + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with + | Some(x) -> (del_context x) + | None -> () + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 + method add_one_ctx_obj = m_refCount <- m_refCount + 1 + end +class virtual z3object ctx_init obj_init = + object (self) + val mutable m_ctx : context option = ctx_init + val mutable m_n_obj : Z3native.ptr option = obj_init + + initializer + (match m_n_obj with + | Some (x) -> self#incref x; + (match m_ctx with + | Some(x) -> x#add_one_ctx_obj + | None -> () + ) + | None -> () + ); + Gc.finalise (fun self -> self#dispose ()) self + + method virtual incref : Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> unit + + (* + Disposes of the underlying native Z3 object. + *) + method dispose () = + Printf.printf "Disposing %d \n" (Oo.id self) ; + (match m_n_obj with + | Some (x) -> self#decref x; m_n_obj <- None + | None -> () + ); + (match m_ctx with + | Some (x) -> x#sub_one_ctx_obj + | None -> () + ); + m_ctx <- None + + + method get_native_object = m_n_obj + + method set_native_object x = + (match x with + | Some(x) -> self#incref x + | None -> () + ); + (match m_n_obj with + | Some(x) -> self#decref x + | None -> () + ); + m_n_obj <- x + + method get_context = m_ctx + + method array_to_native a = + let f e = e#get_native_object in + (Array.map f a) + + method array_length a = + match a with + | Some(x) -> (Array.length x) + | None -> 0 + + end + +<<<<<<< HEAD end >>>>>>> More new ML API. +======= +>>>>>>> More ML API From bea09539cfe19f58bf4c09dc33747fad3d5f2d23 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 16:33:51 +0000 Subject: [PATCH 255/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- examples/ml/MLExample.ml | 12 ++++++++ examples/ml/README | 14 ++++++++++ scripts/mk_project.py | 1 + scripts/mk_util.py | 22 +++++++++++++++ src/api/ml/z3.ml | 59 ++++++++++++++++++++++++++++++++-------- 5 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 examples/ml/MLExample.ml create mode 100644 examples/ml/README diff --git a/examples/ml/MLExample.ml b/examples/ml/MLExample.ml new file mode 100644 index 000000000..8cc248206 --- /dev/null +++ b/examples/ml/MLExample.ml @@ -0,0 +1,12 @@ +(* + Copyright (C) 2012 Microsoft Corporation + Author: CM Wintersteiger (cwinter) 2012-12-17 + *) + + open Z3 + + let _ = ignore(Log.open_ "z3.log") ; +let cfg = Some [("model", "true"); ("proof", "false")] in +let ctx = (new context cfg) in +ctx#dispose +;; diff --git a/examples/ml/README b/examples/ml/README new file mode 100644 index 000000000..a83400e99 --- /dev/null +++ b/examples/ml/README @@ -0,0 +1,14 @@ +### This is work-in-progress and does not work yet. + +Small example using the Z3 ML bindings. +To build the example execute + make examples +in the build directory. + +It will create MLExample in the build directory, +which can be run on Windows via +ocaml -I . MLExample + +On Linux and FreeBSD, we must use +?? + diff --git a/scripts/mk_project.py b/scripts/mk_project.py index e2b003d21..5bbc42da8 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -98,6 +98,7 @@ def init_project_def(): add_c_example('maxsat') add_dotnet_example('dotnet_example', 'dotnet') add_java_example('java_example', 'java') + add_ml_example('ml_example', 'ml') add_z3py_example('py_example', 'python') return API_files diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c17df82e6..27913ab62 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1427,6 +1427,24 @@ class JavaExampleComponent(ExampleComponent): out.write(' -d .\n') out.write('_ex_%s: JavaExample.class\n\n' % (self.name)) +class MLExampleComponent(ExampleComponent): + def __init__(self, name, path): + ExampleComponent.__init__(self, name, path) + + def is_example(self): + return ML_ENABLED + + def mk_makefile(self, out): + if ML_ENABLED: + out.write('_ex_%s: z3.cmxa' % self.name) + deps = '' + for mlfile in get_ml_files(self.ex_dir): + out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) + if IS_WINDOWS: + deps = deps.replace('/', '\\') + out.write('%s\n' % deps) + out.write('\tcd %s && ocamlbuild -build-dir ../../%s -lib z3 MLExample.native && cd -\n\n' % (self.to_src_dir, BUILD_DIR)) + class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): ExampleComponent.__init__(self, name, path) @@ -1500,6 +1518,10 @@ def add_java_example(name, path=None): c = JavaExampleComponent(name, path) reg_component(name, c) +def add_ml_example(name, path=None): + c = MLExampleComponent(name, path) + reg_component(name, c) + def add_z3py_example(name, path=None): c = PythonExampleComponent(name, path) reg_component(name, c) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b00569da1..31c5aa342 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -3386,29 +3386,62 @@ end ======= (* - Author: CM Wintersteiger - (C) Microsoft Research, 2012 + Copyright (C) 2012 Microsoft Corporation + Author: CM Wintersteiger (cwinter) 2012-12-17 *) open Z3enums open Z3native -class context = +module Log = + struct + let m_is_open = false +(* CMW: "open" seems to be an invalid function name*) + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) + end + +class virtual idisposable = + object + method virtual dispose : unit + end + +class context settings = object (self) - val m_n_ctx : Z3native.z3_context option = None + inherit idisposable + val mutable m_n_ctx : Z3native.z3_context option = None val mutable m_refCount : int = 0 - initializer Gc.finalise (fun self -> self#dispose ()) self - method dispose () = - Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with - | Some(x) -> (del_context x) - | None -> () + + initializer + let cfg = mk_config() in + (match settings with + | Some(x) -> + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f x) + | _ -> () + ) ; + m_n_ctx <- Some (mk_context_rc cfg) ; + del_config(cfg) ; + Gc.finalise (fun self -> self#dispose) self + + method dispose : unit = + if m_refCount == 0 then ( + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with + | Some(x) -> (del_context x) + | None -> () + ) else ( + (* re-queue for finalization? *) + ) + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 end class virtual z3object ctx_init obj_init = object (self) + inherit idisposable val mutable m_ctx : context option = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init @@ -3421,7 +3454,7 @@ class virtual z3object ctx_init obj_init = ) | None -> () ); - Gc.finalise (fun self -> self#dispose ()) self + Gc.finalise (fun self -> self#dispose) self method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit @@ -3429,7 +3462,7 @@ class virtual z3object ctx_init obj_init = (* Disposes of the underlying native Z3 object. *) - method dispose () = + method dispose = Printf.printf "Disposing %d \n" (Oo.id self) ; (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None @@ -3457,6 +3490,7 @@ class virtual z3object ctx_init obj_init = method get_context = m_ctx +(* method array_to_native a = let f e = e#get_native_object in (Array.map f a) @@ -3465,6 +3499,7 @@ class virtual z3object ctx_init obj_init = match a with | Some(x) -> (Array.length x) | None -> 0 +*) end From 01dc79fcd44a03710c5b6e43284cdebd23b0aaa7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 17:26:28 +0000 Subject: [PATCH 256/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 158 +++++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 31c5aa342..fb8121c79 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -3388,120 +3388,120 @@ end (* Copyright (C) 2012 Microsoft Corporation Author: CM Wintersteiger (cwinter) 2012-12-17 - *) +*) open Z3enums open Z3native module Log = - struct - let m_is_open = false -(* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) - end - +struct + let m_is_open = false + (* CMW: "open" seems to be an invalid function name*) + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) +end + class virtual idisposable = - object - method virtual dispose : unit - end +object + method virtual dispose : unit +end class context settings = - object (self) - inherit idisposable - val mutable m_n_ctx : Z3native.z3_context option = None - val mutable m_refCount : int = 0 - - initializer - let cfg = mk_config() in - (match settings with - | Some(x) -> - let f e = (set_param_value cfg (fst e) (snd e)) in - (List.iter f x) - | _ -> () - ) ; - m_n_ctx <- Some (mk_context_rc cfg) ; - del_config(cfg) ; - Gc.finalise (fun self -> self#dispose) self - - method dispose : unit = - if m_refCount == 0 then ( - Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with +object (self) + inherit idisposable + val mutable m_n_ctx : Z3native.z3_context option = None + val mutable m_refCount : int = 0 + + initializer + let cfg = mk_config() in + (match settings with + | Some(x) -> + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f x) + | _ -> () + ) ; + m_n_ctx <- Some (mk_context_rc cfg) ; + del_config(cfg) ; + Gc.finalise (fun self -> self#dispose) self + + method dispose : unit = + if m_refCount == 0 then ( + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with | Some(x) -> (del_context x) | None -> () - ) else ( - (* re-queue for finalization? *) - ) + ) else ( + (* re-queue for finalization? *) + ) - method sub_one_ctx_obj = m_refCount <- m_refCount - 1 - method add_one_ctx_obj = m_refCount <- m_refCount + 1 - end + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 + method add_one_ctx_obj = m_refCount <- m_refCount + 1 +end class virtual z3object ctx_init obj_init = - object (self) - inherit idisposable - val mutable m_ctx : context option = ctx_init - val mutable m_n_obj : Z3native.ptr option = obj_init - - initializer - (match m_n_obj with +object (self) + inherit idisposable + val mutable m_ctx : context option = ctx_init + val mutable m_n_obj : Z3native.ptr option = obj_init + + initializer + (match m_n_obj with | Some (x) -> self#incref x; - (match m_ctx with + (match m_ctx with | Some(x) -> x#add_one_ctx_obj | None -> () - ) + ) | None -> () - ); - Gc.finalise (fun self -> self#dispose) self + ); + Gc.finalise (fun self -> self#dispose) self - method virtual incref : Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> unit - - (* - Disposes of the underlying native Z3 object. - *) - method dispose = - Printf.printf "Disposing %d \n" (Oo.id self) ; - (match m_n_obj with + method virtual incref : Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> unit + + (* + Disposes of the underlying native Z3 object. + *) + method dispose = + Printf.printf "Disposing %d \n" (Oo.id self) ; + (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None | None -> () - ); - (match m_ctx with + ); + (match m_ctx with | Some (x) -> x#sub_one_ctx_obj | None -> () - ); - m_ctx <- None + ); + m_ctx <- None - method get_native_object = m_n_obj + method get_native_object = m_n_obj - method set_native_object x = - (match x with + method set_native_object x = + (match x with | Some(x) -> self#incref x | None -> () - ); - (match m_n_obj with + ); + (match m_n_obj with | Some(x) -> self#decref x | None -> () - ); - m_n_obj <- x + ); + m_n_obj <- x - method get_context = m_ctx + method get_context = m_ctx -(* + (* method array_to_native a = - let f e = e#get_native_object in - (Array.map f a) + let f e = e#get_native_object in + (Array.map f a) method array_length a = - match a with - | Some(x) -> (Array.length x) - | None -> 0 -*) + match a with + | Some(x) -> (Array.length x) + | None -> 0 + *) - end +end <<<<<<< HEAD end From e7e85dc7b4892f6a08c9f4ad56f55f342b0913f7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 20:18:53 +0000 Subject: [PATCH 257/646] File renamed Signed-off-by: Christoph M. Wintersteiger --- examples/ml/{MLExample.ml => mlexample.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/ml/{MLExample.ml => mlexample.ml} (100%) diff --git a/examples/ml/MLExample.ml b/examples/ml/mlexample.ml similarity index 100% rename from examples/ml/MLExample.ml rename to examples/ml/mlexample.ml From c001da618826339103136692b90996f3b047dd4f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 22:25:16 +0000 Subject: [PATCH 258/646] ML API and example compilation. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 12 ++++++------ examples/ml/ml_example.ml | 14 ++++++++++++++ examples/ml/mlexample.ml | 12 ------------ scripts/mk_util.py | 33 ++++++++++++++++++--------------- src/api/ml/z3.ml | 2 +- 5 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 examples/ml/ml_example.ml delete mode 100644 examples/ml/mlexample.ml diff --git a/examples/ml/README b/examples/ml/README index a83400e99..3e1eb0d1c 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -5,10 +5,10 @@ To build the example execute make examples in the build directory. -It will create MLExample in the build directory, -which can be run on Windows via -ocaml -I . MLExample +It will create ml_example in the build directory, +which can be run in the build directory via +LD_LIBRARY_PATH=. ./ml_example +or +LD_LIBRARY_PATH=. ./ml_example.byte +for the byte-code version. -On Linux and FreeBSD, we must use -?? - diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml new file mode 100644 index 000000000..9c704e4d0 --- /dev/null +++ b/examples/ml/ml_example.ml @@ -0,0 +1,14 @@ +(* + Copyright (C) 2012 Microsoft Corporation + Author: CM Wintersteiger (cwinter) 2012-12-17 +*) + +open Z3 + +let _ = ignore(Log.open_ "z3.log") ; + let cfg = Some [("model", "true"); ("proof", "false")] in + let ctx = (new context cfg) in + Printf.printf "Disposing...\n"; + ctx#dispose ; + Printf.printf "Exiting.\n"; +;; diff --git a/examples/ml/mlexample.ml b/examples/ml/mlexample.ml deleted file mode 100644 index 8cc248206..000000000 --- a/examples/ml/mlexample.ml +++ /dev/null @@ -1,12 +0,0 @@ -(* - Copyright (C) 2012 Microsoft Corporation - Author: CM Wintersteiger (cwinter) 2012-12-17 - *) - - open Z3 - - let _ = ignore(Log.open_ "z3.log") ; -let cfg = Some [("model", "true"); ("proof", "false")] in -let ctx = (new context cfg) in -ctx#dispose -;; diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 27913ab62..da7d22d54 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1296,10 +1296,6 @@ class MLComponent(Component): bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') mk_dir(bld_dir) libfile = '%s$(SO_EXT)' % self.lib_name - # for mlfile in get_ml_files(self.src_dir): - # out.write('%si: libz3$(SO_EXT) %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) - # out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) - # out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) @@ -1307,11 +1303,9 @@ class MLComponent(Component): out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -lflags -cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cmxa && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) - out.write('\tcp api/ml/z3.cmxa .\n') + out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -lflags -custom,-cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) - out.write('\tcp api/ml/z3.cma .\n') + out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -custom,-cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3native$(OBJ_EXT) z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('ml: z3.cmxa z3.cma\n') out.write('\n') @@ -1436,14 +1430,23 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('_ex_%s: z3.cmxa' % self.name) - deps = '' + out.write('ml_example.byte: z3.cma ') for mlfile in get_ml_files(self.ex_dir): - out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) - if IS_WINDOWS: - deps = deps.replace('/', '\\') - out.write('%s\n' % deps) - out.write('\tcd %s && ocamlbuild -build-dir ../../%s -lib z3 MLExample.native && cd -\n\n' % (self.to_src_dir, BUILD_DIR)) + out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) + out.write('\n') + out.write('\tocamlc -g -o ml_example.byte -I . z3.cma -I api/ml') + for mlfile in get_ml_files(self.ex_dir): + out.write(' %s/%s' % (self.to_ex_dir, mlfile)) + out.write('\n') + out.write('ml_example($EXE_EXT): z3.cmxa ') + for mlfile in get_ml_files(self.ex_dir): + out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) + out.write('\n') + out.write('\tocamlopt -g -o ml_example -I . z3.cmxa -I api/ml') + for mlfile in get_ml_files(self.ex_dir): + out.write(' %s/%s' % (self.to_ex_dir, mlfile)) + out.write('\n') + out.write('_ex_%s: ml_example.byte ml_example($EXE_EXT)\n\n' % self.name) class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index fb8121c79..71e16898e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -3463,7 +3463,7 @@ object (self) Disposes of the underlying native Z3 object. *) method dispose = - Printf.printf "Disposing %d \n" (Oo.id self) ; + Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None | None -> () From 0fad5abd199091ebbb7eb719d291aa359d547f32 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 23:31:42 +0000 Subject: [PATCH 259/646] more ML API Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 3486 +--------------------------------------------- 1 file changed, 68 insertions(+), 3418 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 71e16898e..55ffd91e8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,3390 +1,3 @@ -<<<<<<< HEAD -(* File generated from z3.idl *) - -type context -and symbol -and ast -and sort = private ast -and func_decl = private ast -and app = private ast -and pattern = private ast -and params -and param_descrs -and model -and func_interp -and func_entry -and fixedpoint -and ast_vector -and ast_map -and goal -and tactic -and probe -and apply_result -and solver -and stats - - - -and constructor -and constructor_list - -and lbool = - | L_FALSE - | L_UNDEF - | L_TRUE - -and symbol_kind = - | INT_SYMBOL - | STRING_SYMBOL - -and parameter_kind = - | PARAMETER_INT - | PARAMETER_DOUBLE - | PARAMETER_RATIONAL - | PARAMETER_SYMBOL - | PARAMETER_SORT - | PARAMETER_AST - | PARAMETER_FUNC_DECL - -and sort_kind = - | UNINTERPRETED_SORT - | BOOL_SORT - | INT_SORT - | REAL_SORT - | BV_SORT - | ARRAY_SORT - | DATATYPE_SORT - | RELATION_SORT - | FINITE_DOMAIN_SORT - | UNKNOWN_SORT - -and ast_kind = - | NUMERAL_AST - | APP_AST - | VAR_AST - | QUANTIFIER_AST - | SORT_AST - | FUNC_DECL_AST - | UNKNOWN_AST - -and decl_kind = - | OP_TRUE - | OP_FALSE - | OP_EQ - | OP_DISTINCT - | OP_ITE - | OP_AND - | OP_OR - | OP_IFF - | OP_XOR - | OP_NOT - | OP_IMPLIES - | OP_OEQ - | OP_ANUM - | OP_AGNUM - | OP_LE - | OP_GE - | OP_LT - | OP_GT - | OP_ADD - | OP_SUB - | OP_UMINUS - | OP_MUL - | OP_DIV - | OP_IDIV - | OP_REM - | OP_MOD - | OP_TO_REAL - | OP_TO_INT - | OP_IS_INT - | OP_POWER - | OP_STORE - | OP_SELECT - | OP_CONST_ARRAY - | OP_ARRAY_MAP - | OP_ARRAY_DEFAULT - | OP_SET_UNION - | OP_SET_INTERSECT - | OP_SET_DIFFERENCE - | OP_SET_COMPLEMENT - | OP_SET_SUBSET - | OP_AS_ARRAY - | OP_BNUM - | OP_BIT1 - | OP_BIT0 - | OP_BNEG - | OP_BADD - | OP_BSUB - | OP_BMUL - | OP_BSDIV - | OP_BUDIV - | OP_BSREM - | OP_BUREM - | OP_BSMOD - | OP_BSDIV0 - | OP_BUDIV0 - | OP_BSREM0 - | OP_BUREM0 - | OP_BSMOD0 - | OP_ULEQ - | OP_SLEQ - | OP_UGEQ - | OP_SGEQ - | OP_ULT - | OP_SLT - | OP_UGT - | OP_SGT - | OP_BAND - | OP_BOR - | OP_BNOT - | OP_BXOR - | OP_BNAND - | OP_BNOR - | OP_BXNOR - | OP_CONCAT - | OP_SIGN_EXT - | OP_ZERO_EXT - | OP_EXTRACT - | OP_REPEAT - | OP_BREDOR - | OP_BREDAND - | OP_BCOMP - | OP_BSHL - | OP_BLSHR - | OP_BASHR - | OP_ROTATE_LEFT - | OP_ROTATE_RIGHT - | OP_EXT_ROTATE_LEFT - | OP_EXT_ROTATE_RIGHT - | OP_INT2BV - | OP_BV2INT - | OP_CARRY - | OP_XOR3 - | OP_PR_UNDEF - | OP_PR_TRUE - | OP_PR_ASSERTED - | OP_PR_GOAL - | OP_PR_MODUS_PONENS - | OP_PR_REFLEXIVITY - | OP_PR_SYMMETRY - | OP_PR_TRANSITIVITY - | OP_PR_TRANSITIVITY_STAR - | OP_PR_MONOTONICITY - | OP_PR_QUANT_INTRO - | OP_PR_DISTRIBUTIVITY - | OP_PR_AND_ELIM - | OP_PR_NOT_OR_ELIM - | OP_PR_REWRITE - | OP_PR_REWRITE_STAR - | OP_PR_PULL_QUANT - | OP_PR_PULL_QUANT_STAR - | OP_PR_PUSH_QUANT - | OP_PR_ELIM_UNUSED_VARS - | OP_PR_DER - | OP_PR_QUANT_INST - | OP_PR_HYPOTHESIS - | OP_PR_LEMMA - | OP_PR_UNIT_RESOLUTION - | OP_PR_IFF_TRUE - | OP_PR_IFF_FALSE - | OP_PR_COMMUTATIVITY - | OP_PR_DEF_AXIOM - | OP_PR_DEF_INTRO - | OP_PR_APPLY_DEF - | OP_PR_IFF_OEQ - | OP_PR_NNF_POS - | OP_PR_NNF_NEG - | OP_PR_NNF_STAR - | OP_PR_CNF_STAR - | OP_PR_SKOLEMIZE - | OP_PR_MODUS_PONENS_OEQ - | OP_PR_TH_LEMMA - | OP_PR_HYPER_RESOLVE - | OP_RA_STORE - | OP_RA_EMPTY - | OP_RA_IS_EMPTY - | OP_RA_JOIN - | OP_RA_UNION - | OP_RA_WIDEN - | OP_RA_PROJECT - | OP_RA_FILTER - | OP_RA_NEGATION_FILTER - | OP_RA_RENAME - | OP_RA_COMPLEMENT - | OP_RA_SELECT - | OP_RA_CLONE - | OP_FD_LT - | OP_LABEL - | OP_LABEL_LIT - | OP_DT_CONSTRUCTOR - | OP_DT_RECOGNISER - | OP_DT_ACCESSOR - | OP_UNINTERPRETED - -and param_kind = - | PK_UINT - | PK_BOOL - | PK_DOUBLE - | PK_SYMBOL - | PK_STRING - | PK_OTHER - | PK_INVALID - -and ast_print_mode = - | PRINT_SMTLIB_FULL - | PRINT_LOW_LEVEL - | PRINT_SMTLIB_COMPLIANT - | PRINT_SMTLIB2_COMPLIANT - -and error_code = - | OK - | SORT_ERROR - | IOB - | INVALID_ARG - | PARSER_ERROR - | NO_PARSER - | INVALID_PATTERN - | MEMOUT_FAIL - | FILE_ACCESS_ERROR - | INTERNAL_FATAL - | INVALID_USAGE - | DEC_REF_ERROR - | EXCEPTION - -and goal_prec = - | GOAL_PRECISE - | GOAL_UNDER - | GOAL_OVER - | GOAL_UNDER_OVER - - -external finalize_Z3_context : context -> unit = "finalize_Z3_context";; let _ = Callback.register "finalize_Z3_context" finalize_Z3_context -external finalize_Z3_ast : ast -> unit = "finalize_Z3_ast";; let _ = Callback.register "finalize_Z3_ast" finalize_Z3_ast -external finalize_Z3_params : params -> unit = "finalize_Z3_params";; let _ = Callback.register "finalize_Z3_params" finalize_Z3_params -external finalize_Z3_param_descrs : param_descrs -> unit = "finalize_Z3_param_descrs";; let _ = Callback.register "finalize_Z3_param_descrs" finalize_Z3_param_descrs -external finalize_Z3_model : model -> unit = "finalize_Z3_model";; let _ = Callback.register "finalize_Z3_model" finalize_Z3_model -external finalize_Z3_func_interp : func_interp -> unit = "finalize_Z3_func_interp";; let _ = Callback.register "finalize_Z3_func_interp" finalize_Z3_func_interp -external finalize_Z3_func_entry : func_entry -> unit = "finalize_Z3_func_entry";; let _ = Callback.register "finalize_Z3_func_entry" finalize_Z3_func_entry -external finalize_Z3_fixedpoint : fixedpoint -> unit = "finalize_Z3_fixedpoint";; let _ = Callback.register "finalize_Z3_fixedpoint" finalize_Z3_fixedpoint -external finalize_Z3_ast_vector : ast_vector -> unit = "finalize_Z3_ast_vector";; let _ = Callback.register "finalize_Z3_ast_vector" finalize_Z3_ast_vector -external finalize_Z3_ast_map : ast_map -> unit = "finalize_Z3_ast_map";; let _ = Callback.register "finalize_Z3_ast_map" finalize_Z3_ast_map -external finalize_Z3_goal : goal -> unit = "finalize_Z3_goal";; let _ = Callback.register "finalize_Z3_goal" finalize_Z3_goal -external finalize_Z3_tactic : tactic -> unit = "finalize_Z3_tactic";; let _ = Callback.register "finalize_Z3_tactic" finalize_Z3_tactic -external finalize_Z3_probe : probe -> unit = "finalize_Z3_probe";; let _ = Callback.register "finalize_Z3_probe" finalize_Z3_probe -external finalize_Z3_apply_result : apply_result -> unit = "finalize_Z3_apply_result";; let _ = Callback.register "finalize_Z3_apply_result" finalize_Z3_apply_result -external finalize_Z3_solver : solver -> unit = "finalize_Z3_solver";; let _ = Callback.register "finalize_Z3_solver" finalize_Z3_solver -external finalize_Z3_stats : stats -> unit = "finalize_Z3_stats";; let _ = Callback.register "finalize_Z3_stats" finalize_Z3_stats - -let del_constructor _ _ = () -let del_constructor_list _ _ = () -let del_model _ _ = () -let del_context _ = () -let reset_memory () = () - - -(** Exceptions raised by Z3. It is safe to continue interacting with Z3 after - catching [Error] exceptions. - - {b See also}: {!get_error_msg} -*) -exception Error of context * error_code - - -(* Register dynamically-generated exception tag for use from C *) -let _ = Callback.register_exception "Z3.Error" (Error (Obj.magic None, OK)) - -external mk_context: (string * string) list -> context = "caml_z3_mk_context" - -external update_param_value : context -> string -> string -> unit - = "camlidl_z3_Z3_update_param_value" - -external get_param_value : context -> string -> string option - = "camlidl_z3_Z3_get_param_value" - -external interrupt : context -> unit - = "camlidl_z3_Z3_interrupt" - -external mk_params : context -> params - = "camlidl_z3_Z3_mk_params" - -external params_set_bool : context -> params -> symbol -> bool -> unit - = "camlidl_z3_Z3_params_set_bool" - -external params_set_uint : context -> params -> symbol -> int -> unit - = "camlidl_z3_Z3_params_set_uint" - -external params_set_double : context -> params -> symbol -> float -> unit - = "camlidl_z3_Z3_params_set_double" - -external params_set_symbol : context -> params -> symbol -> symbol -> unit - = "camlidl_z3_Z3_params_set_symbol" - -external params_to_string : context -> params -> string - = "camlidl_z3_Z3_params_to_string" - -external params_validate : context -> params -> param_descrs -> unit - = "camlidl_z3_Z3_params_validate" - -external param_descrs_get_kind : context -> param_descrs -> symbol -> param_kind - = "camlidl_z3_Z3_param_descrs_get_kind" - -external param_descrs_size : context -> param_descrs -> int - = "camlidl_z3_Z3_param_descrs_size" - -external param_descrs_get_name : context -> param_descrs -> int -> symbol - = "camlidl_z3_Z3_param_descrs_get_name" - -external param_descrs_to_string : context -> param_descrs -> string - = "camlidl_z3_Z3_param_descrs_to_string" - - -(** - Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - - {b See also}: {!symbol_refine} -*) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string - -external mk_int_symbol : context -> int -> symbol - = "camlidl_z3_Z3_mk_int_symbol" - -external mk_string_symbol : context -> string -> symbol - = "camlidl_z3_Z3_mk_string_symbol" - - -(** - A datatype constructor descriptor. -*) -type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) -} -(** - A datatype is described by a name and constructor descriptors. -*) -type datatype_desc = symbol * datatype_constructor_desc array -(** - A datatype constructor representation. -*) -type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) -} -(** - A datatype is represented by a sort and constructors. -*) -type datatype = sort * datatype_constructor array -(** - Refined view of a {!sort}. - - {b See also}: {!mk_sort} - - {b See also}: {!sort_refine} -*) -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_bv of int - | Sort_finite_domain of symbol * int64 - | Sort_real - | Sort_array of sort * sort - | Sort_datatype of datatype_constructor array - | Sort_relation of sort array - | Sort_unknown - -external mk_uninterpreted_sort : context -> symbol -> sort - = "camlidl_z3_Z3_mk_uninterpreted_sort" - -external mk_bool_sort : context -> sort - = "camlidl_z3_Z3_mk_bool_sort" - -external mk_int_sort : context -> sort - = "camlidl_z3_Z3_mk_int_sort" - -external mk_real_sort : context -> sort - = "camlidl_z3_Z3_mk_real_sort" - -external mk_bv_sort : context -> int -> sort - = "camlidl_z3_Z3_mk_bv_sort" - -external mk_finite_domain_sort : context -> symbol -> int64 -> sort - = "camlidl_z3_Z3_mk_finite_domain_sort" - -external mk_array_sort : context -> sort -> sort -> sort - = "camlidl_z3_Z3_mk_array_sort" - -external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array - = "camlidl_z3_Z3_mk_tuple_sort" - -external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array - = "camlidl_z3_Z3_mk_enumeration_sort" - -external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl - = "camlidl_z3_Z3_mk_list_sort" - -external mk_constructor : context -> symbol -> symbol -> symbol array -> sort option array -> int array -> constructor - = "camlidl_z3_Z3_mk_constructor_bytecode" "camlidl_z3_Z3_mk_constructor" - -external del_constructor : context -> constructor -> unit - = "camlidl_z3_Z3_del_constructor" - -external mk_datatype : context -> symbol -> constructor array -> sort * constructor array - = "camlidl_z3_Z3_mk_datatype" - -external mk_constructor_list : context -> constructor array -> constructor_list - = "camlidl_z3_Z3_mk_constructor_list" - -external del_constructor_list : context -> constructor_list -> unit - = "camlidl_z3_Z3_del_constructor_list" - -external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array - = "camlidl_z3_Z3_mk_datatypes" - -external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array - = "camlidl_z3_Z3_query_constructor" - -external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3_Z3_mk_func_decl" - -external mk_app : context -> func_decl -> ast array -> ast - = "camlidl_z3_Z3_mk_app" - -external mk_const : context -> symbol -> sort -> ast - = "camlidl_z3_Z3_mk_const" - -external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl - = "camlidl_z3_Z3_mk_fresh_func_decl" - -external mk_fresh_const : context -> string -> sort -> ast - = "camlidl_z3_Z3_mk_fresh_const" - -external mk_true : context -> ast - = "camlidl_z3_Z3_mk_true" - -external mk_false : context -> ast - = "camlidl_z3_Z3_mk_false" - -external mk_eq : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_eq" - -external mk_distinct : context -> ast array -> ast - = "camlidl_z3_Z3_mk_distinct" - -external mk_not : context -> ast -> ast - = "camlidl_z3_Z3_mk_not" - -external mk_ite : context -> ast -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ite" - -external mk_iff : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_iff" - -external mk_implies : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_implies" - -external mk_xor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_xor" - -external mk_and : context -> ast array -> ast - = "camlidl_z3_Z3_mk_and" - -external mk_or : context -> ast array -> ast - = "camlidl_z3_Z3_mk_or" - -external mk_add : context -> ast array -> ast - = "camlidl_z3_Z3_mk_add" - -external mk_mul : context -> ast array -> ast - = "camlidl_z3_Z3_mk_mul" - -external mk_sub : context -> ast array -> ast - = "camlidl_z3_Z3_mk_sub" - -external mk_unary_minus : context -> ast -> ast - = "camlidl_z3_Z3_mk_unary_minus" - -external mk_div : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_div" - -external mk_mod : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_mod" - -external mk_rem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_rem" - -external mk_power : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_power" - -external mk_lt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_lt" - -external mk_le : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_le" - -external mk_gt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_gt" - -external mk_ge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ge" - -external mk_int2real : context -> ast -> ast - = "camlidl_z3_Z3_mk_int2real" - -external mk_real2int : context -> ast -> ast - = "camlidl_z3_Z3_mk_real2int" - -external mk_is_int : context -> ast -> ast - = "camlidl_z3_Z3_mk_is_int" - -external mk_bvnot : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvnot" - -external mk_bvredand : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvredand" - -external mk_bvredor : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvredor" - -external mk_bvand : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvand" - -external mk_bvor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvor" - -external mk_bvxor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvxor" - -external mk_bvnand : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvnand" - -external mk_bvnor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvnor" - -external mk_bvxnor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvxnor" - -external mk_bvneg : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvneg" - -external mk_bvadd : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvadd" - -external mk_bvsub : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsub" - -external mk_bvmul : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvmul" - -external mk_bvudiv : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvudiv" - -external mk_bvsdiv : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsdiv" - -external mk_bvurem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvurem" - -external mk_bvsrem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsrem" - -external mk_bvsmod : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsmod" - -external mk_bvult : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvult" - -external mk_bvslt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvslt" - -external mk_bvule : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvule" - -external mk_bvsle : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsle" - -external mk_bvuge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvuge" - -external mk_bvsge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsge" - -external mk_bvugt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvugt" - -external mk_bvsgt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsgt" - -external mk_concat : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_concat" - -external mk_extract : context -> int -> int -> ast -> ast - = "camlidl_z3_Z3_mk_extract" - -external mk_sign_ext : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_sign_ext" - -external mk_zero_ext : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_zero_ext" - -external mk_repeat : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_repeat" - -external mk_bvshl : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvshl" - -external mk_bvlshr : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvlshr" - -external mk_bvashr : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvashr" - -external mk_rotate_left : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_rotate_left" - -external mk_rotate_right : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_rotate_right" - -external mk_ext_rotate_left : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ext_rotate_left" - -external mk_ext_rotate_right : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ext_rotate_right" - -external mk_int2bv : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_int2bv" - -external mk_bv2int : context -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bv2int" - -external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvadd_no_overflow" - -external mk_bvadd_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvadd_no_underflow" - -external mk_bvsub_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsub_no_overflow" - -external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvsub_no_underflow" - -external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsdiv_no_overflow" - -external mk_bvneg_no_overflow : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvneg_no_overflow" - -external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvmul_no_overflow" - -external mk_bvmul_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvmul_no_underflow" - -external mk_select : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_select" - -external mk_store : context -> ast -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_store" - -external mk_const_array : context -> sort -> ast -> ast - = "camlidl_z3_Z3_mk_const_array" - -external mk_map : context -> func_decl -> int -> ast -> ast - = "camlidl_z3_Z3_mk_map" - -external mk_array_default : context -> ast -> ast - = "camlidl_z3_Z3_mk_array_default" - -external mk_set_sort : context -> sort -> sort - = "camlidl_z3_Z3_mk_set_sort" - -external mk_empty_set : context -> sort -> ast - = "camlidl_z3_Z3_mk_empty_set" - -external mk_full_set : context -> sort -> ast - = "camlidl_z3_Z3_mk_full_set" - -external mk_set_add : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_add" - -external mk_set_del : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_del" - -external mk_set_union : context -> ast array -> ast - = "camlidl_z3_Z3_mk_set_union" - -external mk_set_intersect : context -> ast array -> ast - = "camlidl_z3_Z3_mk_set_intersect" - -external mk_set_difference : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_difference" - -external mk_set_complement : context -> ast -> ast - = "camlidl_z3_Z3_mk_set_complement" - -external mk_set_member : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_member" - -external mk_set_subset : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_subset" - - -(** - Summary: \[ [ numeral_refined ] \] is the refined view of a numeral . -*) -type numeral_refined = - | Numeral_int of int * sort - | Numeral_int64 of int64 * sort - | Numeral_large of string * sort - | Numeral_rational of numeral_refined * numeral_refined - -external mk_numeral : context -> string -> sort -> ast - = "camlidl_z3_Z3_mk_numeral" - -external mk_real : context -> int -> int -> ast - = "camlidl_z3_Z3_mk_real" - -external mk_int : context -> int -> sort -> ast - = "camlidl_z3_Z3_mk_int" - -external mk_int64 : context -> int64 -> sort -> ast - = "camlidl_z3_Z3_mk_int64" - -external mk_pattern : context -> ast array -> pattern - = "camlidl_z3_Z3_mk_pattern" - -external mk_bound : context -> int -> sort -> ast - = "camlidl_z3_Z3_mk_bound" - -external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_bytecode" "camlidl_z3_Z3_mk_forall" - -external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_bytecode" "camlidl_z3_Z3_mk_exists" - -external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_bytecode" "camlidl_z3_Z3_mk_quantifier" - -external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3_Z3_mk_quantifier_ex" - -external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_const" - -external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_const" - -external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_bytecode" "camlidl_z3_Z3_mk_quantifier_const" - -external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3_Z3_mk_quantifier_const_ex" - -external get_symbol_kind : context -> symbol -> symbol_kind - = "camlidl_z3_Z3_get_symbol_kind" - -external get_symbol_int : context -> symbol -> int - = "camlidl_z3_Z3_get_symbol_int" - -external get_symbol_string : context -> symbol -> string - = "camlidl_z3_Z3_get_symbol_string" - -external get_sort_name : context -> sort -> symbol - = "camlidl_z3_Z3_get_sort_name" - -external get_sort_id : context -> sort -> int - = "camlidl_z3_Z3_get_sort_id" - -external sort_to_ast : context -> sort -> ast - = "camlidl_z3_Z3_sort_to_ast" - -external is_eq_sort : context -> sort -> sort -> bool - = "camlidl_z3_Z3_is_eq_sort" - -external get_sort_kind : context -> sort -> sort_kind - = "camlidl_z3_Z3_get_sort_kind" - -external get_bv_sort_size : context -> sort -> int - = "camlidl_z3_Z3_get_bv_sort_size" - -external get_finite_domain_sort_size : context -> sort -> int64 option - = "camlidl_z3_Z3_get_finite_domain_sort_size" - -external get_array_sort_domain : context -> sort -> sort - = "camlidl_z3_Z3_get_array_sort_domain" - -external get_array_sort_range : context -> sort -> sort - = "camlidl_z3_Z3_get_array_sort_range" - -external get_tuple_sort_mk_decl : context -> sort -> func_decl - = "camlidl_z3_Z3_get_tuple_sort_mk_decl" - -external get_tuple_sort_num_fields : context -> sort -> int - = "camlidl_z3_Z3_get_tuple_sort_num_fields" - -external get_tuple_sort_field_decl : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_tuple_sort_field_decl" - -external get_datatype_sort_num_constructors : context -> sort -> int - = "camlidl_z3_Z3_get_datatype_sort_num_constructors" - -external get_datatype_sort_constructor : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_constructor" - -external get_datatype_sort_recognizer : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_recognizer" - -external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_constructor_accessor" - -external get_relation_arity : context -> sort -> int - = "camlidl_z3_Z3_get_relation_arity" - -external get_relation_column : context -> sort -> int -> sort - = "camlidl_z3_Z3_get_relation_column" - -external func_decl_to_ast : context -> func_decl -> ast - = "camlidl_z3_Z3_func_decl_to_ast" - -external is_eq_func_decl : context -> func_decl -> func_decl -> bool - = "camlidl_z3_Z3_is_eq_func_decl" - -external get_func_decl_id : context -> func_decl -> int - = "camlidl_z3_Z3_get_func_decl_id" - -external get_decl_name : context -> func_decl -> symbol - = "camlidl_z3_Z3_get_decl_name" - -external get_decl_kind : context -> func_decl -> decl_kind - = "camlidl_z3_Z3_get_decl_kind" - -external get_domain_size : context -> func_decl -> int - = "camlidl_z3_Z3_get_domain_size" - -external get_arity : context -> func_decl -> int - = "camlidl_z3_Z3_get_arity" - -external get_domain : context -> func_decl -> int -> sort - = "camlidl_z3_Z3_get_domain" - -external get_range : context -> func_decl -> sort - = "camlidl_z3_Z3_get_range" - -external get_decl_num_parameters : context -> func_decl -> int - = "camlidl_z3_Z3_get_decl_num_parameters" - -external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind - = "camlidl_z3_Z3_get_decl_parameter_kind" - -external get_decl_int_parameter : context -> func_decl -> int -> int - = "camlidl_z3_Z3_get_decl_int_parameter" - -external get_decl_double_parameter : context -> func_decl -> int -> float - = "camlidl_z3_Z3_get_decl_double_parameter" - -external get_decl_symbol_parameter : context -> func_decl -> int -> symbol - = "camlidl_z3_Z3_get_decl_symbol_parameter" - -external get_decl_sort_parameter : context -> func_decl -> int -> sort - = "camlidl_z3_Z3_get_decl_sort_parameter" - -external get_decl_ast_parameter : context -> func_decl -> int -> ast - = "camlidl_z3_Z3_get_decl_ast_parameter" - -external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl - = "camlidl_z3_Z3_get_decl_func_decl_parameter" - -external get_decl_rational_parameter : context -> func_decl -> int -> string - = "camlidl_z3_Z3_get_decl_rational_parameter" - -external app_to_ast : context -> app -> ast - = "camlidl_z3_Z3_app_to_ast" - -external get_app_decl : context -> app -> func_decl - = "camlidl_z3_Z3_get_app_decl" - -external get_app_num_args : context -> app -> int - = "camlidl_z3_Z3_get_app_num_args" - -external get_app_arg : context -> app -> int -> ast - = "camlidl_z3_Z3_get_app_arg" - - -(** - Summary: \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} -*) -type binder_type = Forall | Exists -(** - Summary: \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} -*) -type term_refined = - | Term_numeral of numeral_refined - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_var of int * sort - -external is_eq_ast : context -> ast -> ast -> bool - = "camlidl_z3_Z3_is_eq_ast" - -external get_ast_id : context -> ast -> int - = "camlidl_z3_Z3_get_ast_id" - -external get_ast_hash : context -> ast -> int - = "camlidl_z3_Z3_get_ast_hash" - -external get_sort : context -> ast -> sort - = "camlidl_z3_Z3_get_sort" - -external is_well_sorted : context -> ast -> bool - = "camlidl_z3_Z3_is_well_sorted" - -external get_bool_value : context -> ast -> lbool - = "camlidl_z3_Z3_get_bool_value" - -external get_ast_kind : context -> ast -> ast_kind - = "camlidl_z3_Z3_get_ast_kind" - -external is_app : context -> ast -> bool - = "camlidl_z3_Z3_is_app" - -external is_numeral_ast : context -> ast -> bool - = "camlidl_z3_Z3_is_numeral_ast" - -external is_algebraic_number : context -> ast -> bool - = "camlidl_z3_Z3_is_algebraic_number" - -external to_app : context -> ast -> app - = "camlidl_z3_Z3_to_app" - -external to_func_decl : context -> ast -> func_decl - = "camlidl_z3_Z3_to_func_decl" - -external get_numeral_string : context -> ast -> string - = "camlidl_z3_Z3_get_numeral_string" - -external get_numeral_decimal_string : context -> ast -> int -> string - = "camlidl_z3_Z3_get_numeral_decimal_string" - -external get_numerator : context -> ast -> ast - = "camlidl_z3_Z3_get_numerator" - -external get_denominator : context -> ast -> ast - = "camlidl_z3_Z3_get_denominator" - -external get_numeral_small : context -> ast -> bool * int64 * int64 - = "camlidl_z3_Z3_get_numeral_small" - -external get_numeral_int : context -> ast -> bool * int - = "camlidl_z3_Z3_get_numeral_int" - -external get_numeral_int64 : context -> ast -> bool * int64 - = "camlidl_z3_Z3_get_numeral_int64" - -external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 - = "camlidl_z3_Z3_get_numeral_rational_int64" - -external get_algebraic_number_lower : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_algebraic_number_lower" - -external get_algebraic_number_upper : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_algebraic_number_upper" - -external pattern_to_ast : context -> pattern -> ast - = "camlidl_z3_Z3_pattern_to_ast" - -external get_pattern_num_terms : context -> pattern -> int - = "camlidl_z3_Z3_get_pattern_num_terms" - -external get_pattern : context -> pattern -> int -> ast - = "camlidl_z3_Z3_get_pattern" - -external get_index_value : context -> ast -> int - = "camlidl_z3_Z3_get_index_value" - -external is_quantifier_forall : context -> ast -> bool - = "camlidl_z3_Z3_is_quantifier_forall" - -external get_quantifier_weight : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_weight" - -external get_quantifier_num_patterns : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_patterns" - -external get_quantifier_pattern_ast : context -> ast -> int -> pattern - = "camlidl_z3_Z3_get_quantifier_pattern_ast" - -external get_quantifier_num_no_patterns : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_no_patterns" - -external get_quantifier_no_pattern_ast : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_quantifier_no_pattern_ast" - -external get_quantifier_num_bound : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_bound" - -external get_quantifier_bound_name : context -> ast -> int -> symbol - = "camlidl_z3_Z3_get_quantifier_bound_name" - -external get_quantifier_bound_sort : context -> ast -> int -> sort - = "camlidl_z3_Z3_get_quantifier_bound_sort" - -external get_quantifier_body : context -> ast -> ast - = "camlidl_z3_Z3_get_quantifier_body" - -external simplify : context -> ast -> ast - = "camlidl_z3_Z3_simplify" - -external simplify_ex : context -> ast -> params -> ast - = "camlidl_z3_Z3_simplify_ex" - -external simplify_get_help : context -> string - = "camlidl_z3_Z3_simplify_get_help" - -external simplify_get_param_descrs : context -> param_descrs - = "camlidl_z3_Z3_simplify_get_param_descrs" - -external update_term : context -> ast -> ast array -> ast - = "camlidl_z3_Z3_update_term" - -external substitute : context -> ast -> ast array -> ast array -> ast - = "camlidl_z3_Z3_substitute" - -external substitute_vars : context -> ast -> ast array -> ast - = "camlidl_z3_Z3_substitute_vars" - -external translate : context -> ast -> context -> ast - = "camlidl_z3_Z3_translate" - - -(** - A model assigns uninterpreted sorts to finite universes of distinct values, constants to values, - and arrays and functions to finite maps from argument values to result values plus a default - value for all other arguments. -*) -type model_refined = { - sorts : (sort, ast_vector) Hashtbl.t; - consts : (func_decl, ast) Hashtbl.t; - arrays : (func_decl, (ast, ast) Hashtbl.t * ast) Hashtbl.t; - funcs : (func_decl, (ast array, ast) Hashtbl.t * ast) Hashtbl.t; -} - -external model_eval : context -> model -> ast -> bool -> ast option - = "camlidl_z3_Z3_model_eval" - -external model_get_const_interp : context -> model -> func_decl -> ast option - = "camlidl_z3_Z3_model_get_const_interp" - -external model_get_func_interp : context -> model -> func_decl -> func_interp option - = "camlidl_z3_Z3_model_get_func_interp" - -external model_get_num_consts : context -> model -> int - = "camlidl_z3_Z3_model_get_num_consts" - -external model_get_const_decl : context -> model -> int -> func_decl - = "camlidl_z3_Z3_model_get_const_decl" - -external model_get_num_funcs : context -> model -> int - = "camlidl_z3_Z3_model_get_num_funcs" - -external model_get_func_decl : context -> model -> int -> func_decl - = "camlidl_z3_Z3_model_get_func_decl" - -external model_get_num_sorts : context -> model -> int - = "camlidl_z3_Z3_model_get_num_sorts" - -external model_get_sort : context -> model -> int -> sort - = "camlidl_z3_Z3_model_get_sort" - -external model_get_sort_universe : context -> model -> sort -> ast_vector - = "camlidl_z3_Z3_model_get_sort_universe" - -external is_as_array : context -> ast -> bool - = "camlidl_z3_Z3_is_as_array" - -external get_as_array_func_decl : context -> ast -> func_decl - = "camlidl_z3_Z3_get_as_array_func_decl" - -external func_interp_get_num_entries : context -> func_interp -> int - = "camlidl_z3_Z3_func_interp_get_num_entries" - -external func_interp_get_entry : context -> func_interp -> int -> func_entry - = "camlidl_z3_Z3_func_interp_get_entry" - -external func_interp_get_else : context -> func_interp -> ast - = "camlidl_z3_Z3_func_interp_get_else" - -external func_interp_get_arity : context -> func_interp -> int - = "camlidl_z3_Z3_func_interp_get_arity" - -external func_entry_get_value : context -> func_entry -> ast - = "camlidl_z3_Z3_func_entry_get_value" - -external func_entry_get_num_args : context -> func_entry -> int - = "camlidl_z3_Z3_func_entry_get_num_args" - -external func_entry_get_arg : context -> func_entry -> int -> ast - = "camlidl_z3_Z3_func_entry_get_arg" - -external open_log : string -> bool - = "camlidl_z3_Z3_open_log" - -external append_log : string -> unit - = "camlidl_z3_Z3_append_log" - -external close_log : unit -> unit - = "camlidl_z3_Z3_close_log" - -external toggle_warning_messages : bool -> unit - = "camlidl_z3_Z3_toggle_warning_messages" - -external set_ast_print_mode : context -> ast_print_mode -> unit - = "camlidl_z3_Z3_set_ast_print_mode" - -external ast_to_string : context -> ast -> string - = "camlidl_z3_Z3_ast_to_string" - -external pattern_to_string : context -> pattern -> string - = "camlidl_z3_Z3_pattern_to_string" - -external sort_to_string : context -> sort -> string - = "camlidl_z3_Z3_sort_to_string" - -external func_decl_to_string : context -> func_decl -> string - = "camlidl_z3_Z3_func_decl_to_string" - -external model_to_string : context -> model -> string - = "camlidl_z3_Z3_model_to_string" - -external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3_Z3_benchmark_to_smtlib_string" - -external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3_Z3_parse_smtlib2_string" - -external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3_Z3_parse_smtlib2_file" - -external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_string_bytecode" "camlidl_z3_Z3_parse_smtlib_string" - -external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_file_bytecode" "camlidl_z3_Z3_parse_smtlib_file" - -external get_smtlib_num_formulas : context -> int - = "camlidl_z3_Z3_get_smtlib_num_formulas" - -external get_smtlib_formula : context -> int -> ast - = "camlidl_z3_Z3_get_smtlib_formula" - -external get_smtlib_num_assumptions : context -> int - = "camlidl_z3_Z3_get_smtlib_num_assumptions" - -external get_smtlib_assumption : context -> int -> ast - = "camlidl_z3_Z3_get_smtlib_assumption" - -external get_smtlib_num_decls : context -> int - = "camlidl_z3_Z3_get_smtlib_num_decls" - -external get_smtlib_decl : context -> int -> func_decl - = "camlidl_z3_Z3_get_smtlib_decl" - -external get_smtlib_num_sorts : context -> int - = "camlidl_z3_Z3_get_smtlib_num_sorts" - -external get_smtlib_sort : context -> int -> sort - = "camlidl_z3_Z3_get_smtlib_sort" - -external get_smtlib_error : context -> string - = "camlidl_z3_Z3_get_smtlib_error" - -external set_error : context -> error_code -> unit - = "camlidl_z3_Z3_set_error" - -external get_error_msg_ex : context -> error_code -> string - = "camlidl_z3_Z3_get_error_msg_ex" - -external get_version : unit -> int * int * int * int - = "camlidl_z3_Z3_get_version" - -external enable_trace : string -> unit - = "camlidl_z3_Z3_enable_trace" - -external disable_trace : string -> unit - = "camlidl_z3_Z3_disable_trace" - -external mk_fixedpoint : context -> fixedpoint - = "camlidl_z3_Z3_mk_fixedpoint" - -external fixedpoint_add_rule : context -> fixedpoint -> ast -> symbol -> unit - = "camlidl_z3_Z3_fixedpoint_add_rule" - -external fixedpoint_add_fact : context -> fixedpoint -> func_decl -> int array -> unit - = "camlidl_z3_Z3_fixedpoint_add_fact" - -external fixedpoint_assert : context -> fixedpoint -> ast -> unit - = "camlidl_z3_Z3_fixedpoint_assert" - -external fixedpoint_query : context -> fixedpoint -> ast -> lbool - = "camlidl_z3_Z3_fixedpoint_query" - -external fixedpoint_query_relations : context -> fixedpoint -> func_decl array -> lbool - = "camlidl_z3_Z3_fixedpoint_query_relations" - -external fixedpoint_get_answer : context -> fixedpoint -> ast - = "camlidl_z3_Z3_fixedpoint_get_answer" - -external fixedpoint_get_reason_unknown : context -> fixedpoint -> string - = "camlidl_z3_Z3_fixedpoint_get_reason_unknown" - -external fixedpoint_update_rule : context -> fixedpoint -> ast -> symbol -> unit - = "camlidl_z3_Z3_fixedpoint_update_rule" - -external fixedpoint_get_num_levels : context -> fixedpoint -> func_decl -> int - = "camlidl_z3_Z3_fixedpoint_get_num_levels" - -external fixedpoint_get_cover_delta : context -> fixedpoint -> int -> func_decl -> ast - = "camlidl_z3_Z3_fixedpoint_get_cover_delta" - -external fixedpoint_add_cover : context -> fixedpoint -> int -> func_decl -> ast -> unit - = "camlidl_z3_Z3_fixedpoint_add_cover" - -external fixedpoint_get_statistics : context -> fixedpoint -> stats - = "camlidl_z3_Z3_fixedpoint_get_statistics" - -external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> unit - = "camlidl_z3_Z3_fixedpoint_register_relation" - -external fixedpoint_set_predicate_representation : context -> fixedpoint -> func_decl -> symbol array -> unit - = "camlidl_z3_Z3_fixedpoint_set_predicate_representation" - -external fixedpoint_get_rules : context -> fixedpoint -> ast_vector - = "camlidl_z3_Z3_fixedpoint_get_rules" - -external fixedpoint_get_assertions : context -> fixedpoint -> ast_vector - = "camlidl_z3_Z3_fixedpoint_get_assertions" - -external fixedpoint_set_params : context -> fixedpoint -> params -> unit - = "camlidl_z3_Z3_fixedpoint_set_params" - -external fixedpoint_get_help : context -> fixedpoint -> string - = "camlidl_z3_Z3_fixedpoint_get_help" - -external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs - = "camlidl_z3_Z3_fixedpoint_get_param_descrs" - -external fixedpoint_to_string : context -> fixedpoint -> ast array -> string - = "camlidl_z3_Z3_fixedpoint_to_string" - -external fixedpoint_from_string : context -> fixedpoint -> string -> ast_vector - = "camlidl_z3_Z3_fixedpoint_from_string" - -external fixedpoint_from_file : context -> fixedpoint -> string -> ast_vector - = "camlidl_z3_Z3_fixedpoint_from_file" - -external fixedpoint_push : context -> fixedpoint -> unit - = "camlidl_z3_Z3_fixedpoint_push" - -external fixedpoint_pop : context -> fixedpoint -> unit - = "camlidl_z3_Z3_fixedpoint_pop" - -external mk_ast_vector : context -> ast_vector - = "camlidl_z3_Z3_mk_ast_vector" - -external ast_vector_size : context -> ast_vector -> int - = "camlidl_z3_Z3_ast_vector_size" - -external ast_vector_get : context -> ast_vector -> int -> ast - = "camlidl_z3_Z3_ast_vector_get" - -external ast_vector_set : context -> ast_vector -> int -> ast -> unit - = "camlidl_z3_Z3_ast_vector_set" - -external ast_vector_resize : context -> ast_vector -> int -> unit - = "camlidl_z3_Z3_ast_vector_resize" - -external ast_vector_push : context -> ast_vector -> ast -> unit - = "camlidl_z3_Z3_ast_vector_push" - -external ast_vector_translate : context -> ast_vector -> context -> ast_vector - = "camlidl_z3_Z3_ast_vector_translate" - -external ast_vector_to_string : context -> ast_vector -> string - = "camlidl_z3_Z3_ast_vector_to_string" - -external mk_ast_map : context -> ast_map - = "camlidl_z3_Z3_mk_ast_map" - -external ast_map_contains : context -> ast_map -> ast -> bool - = "camlidl_z3_Z3_ast_map_contains" - -external ast_map_find : context -> ast_map -> ast -> ast - = "camlidl_z3_Z3_ast_map_find" - -external ast_map_insert : context -> ast_map -> ast -> ast -> unit - = "camlidl_z3_Z3_ast_map_insert" - -external ast_map_erase : context -> ast_map -> ast -> unit - = "camlidl_z3_Z3_ast_map_erase" - -external ast_map_reset : context -> ast_map -> unit - = "camlidl_z3_Z3_ast_map_reset" - -external ast_map_size : context -> ast_map -> int - = "camlidl_z3_Z3_ast_map_size" - -external ast_map_keys : context -> ast_map -> ast_vector - = "camlidl_z3_Z3_ast_map_keys" - -external ast_map_to_string : context -> ast_map -> string - = "camlidl_z3_Z3_ast_map_to_string" - -external mk_goal : context -> bool -> bool -> bool -> goal - = "camlidl_z3_Z3_mk_goal" - -external goal_precision : context -> goal -> goal_prec - = "camlidl_z3_Z3_goal_precision" - -external goal_assert : context -> goal -> ast -> unit - = "camlidl_z3_Z3_goal_assert" - -external goal_inconsistent : context -> goal -> bool - = "camlidl_z3_Z3_goal_inconsistent" - -external goal_depth : context -> goal -> int - = "camlidl_z3_Z3_goal_depth" - -external goal_reset : context -> goal -> unit - = "camlidl_z3_Z3_goal_reset" - -external goal_size : context -> goal -> int - = "camlidl_z3_Z3_goal_size" - -external goal_formula : context -> goal -> int -> ast - = "camlidl_z3_Z3_goal_formula" - -external goal_num_exprs : context -> goal -> int - = "camlidl_z3_Z3_goal_num_exprs" - -external goal_is_decided_sat : context -> goal -> bool - = "camlidl_z3_Z3_goal_is_decided_sat" - -external goal_is_decided_unsat : context -> goal -> bool - = "camlidl_z3_Z3_goal_is_decided_unsat" - -external goal_translate : context -> goal -> context -> goal - = "camlidl_z3_Z3_goal_translate" - -external goal_to_string : context -> goal -> string - = "camlidl_z3_Z3_goal_to_string" - -external mk_tactic : context -> string -> tactic - = "camlidl_z3_Z3_mk_tactic" - -external mk_probe : context -> string -> probe - = "camlidl_z3_Z3_mk_probe" - -external tactic_and_then : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_and_then" - -external tactic_or_else : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_or_else" - -external tactic_par_or : context -> tactic array -> tactic - = "camlidl_z3_Z3_tactic_par_or" - -external tactic_par_and_then : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_par_and_then" - -external tactic_try_for : context -> tactic -> int -> tactic - = "camlidl_z3_Z3_tactic_try_for" - -external tactic_when : context -> probe -> tactic -> tactic - = "camlidl_z3_Z3_tactic_when" - -external tactic_cond : context -> probe -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_cond" - -external tactic_repeat : context -> tactic -> int -> tactic - = "camlidl_z3_Z3_tactic_repeat" - -external tactic_skip : context -> tactic - = "camlidl_z3_Z3_tactic_skip" - -external tactic_fail : context -> tactic - = "camlidl_z3_Z3_tactic_fail" - -external tactic_fail_if : context -> probe -> tactic - = "camlidl_z3_Z3_tactic_fail_if" - -external tactic_fail_if_not_decided : context -> tactic - = "camlidl_z3_Z3_tactic_fail_if_not_decided" - -external tactic_using_params : context -> tactic -> params -> tactic - = "camlidl_z3_Z3_tactic_using_params" - -external probe_const : context -> float -> probe - = "camlidl_z3_Z3_probe_const" - -external probe_lt : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_lt" - -external probe_gt : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_gt" - -external probe_le : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_le" - -external probe_ge : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_ge" - -external probe_eq : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_eq" - -external probe_and : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_and" - -external probe_or : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_or" - -external probe_not : context -> probe -> probe - = "camlidl_z3_Z3_probe_not" - -external get_num_tactics : context -> int - = "camlidl_z3_Z3_get_num_tactics" - -external get_tactic_name : context -> int -> string - = "camlidl_z3_Z3_get_tactic_name" - -external get_num_probes : context -> int - = "camlidl_z3_Z3_get_num_probes" - -external get_probe_name : context -> int -> string - = "camlidl_z3_Z3_get_probe_name" - -external tactic_get_help : context -> tactic -> string - = "camlidl_z3_Z3_tactic_get_help" - -external tactic_get_param_descrs : context -> tactic -> param_descrs - = "camlidl_z3_Z3_tactic_get_param_descrs" - -external tactic_get_descr : context -> string -> string - = "camlidl_z3_Z3_tactic_get_descr" - -external probe_get_descr : context -> string -> string - = "camlidl_z3_Z3_probe_get_descr" - -external probe_apply : context -> probe -> goal -> float - = "camlidl_z3_Z3_probe_apply" - -external tactic_apply : context -> tactic -> goal -> apply_result - = "camlidl_z3_Z3_tactic_apply" - -external tactic_apply_ex : context -> tactic -> goal -> params -> apply_result - = "camlidl_z3_Z3_tactic_apply_ex" - -external apply_result_to_string : context -> apply_result -> string - = "camlidl_z3_Z3_apply_result_to_string" - -external apply_result_get_num_subgoals : context -> apply_result -> int - = "camlidl_z3_Z3_apply_result_get_num_subgoals" - -external apply_result_get_subgoal : context -> apply_result -> int -> goal - = "camlidl_z3_Z3_apply_result_get_subgoal" - -external apply_result_convert_model : context -> apply_result -> int -> model -> model - = "camlidl_z3_Z3_apply_result_convert_model" - -external mk_solver : context -> solver - = "camlidl_z3_Z3_mk_solver" - -external mk_simple_solver : context -> solver - = "camlidl_z3_Z3_mk_simple_solver" - -external mk_solver_for_logic : context -> symbol -> solver - = "camlidl_z3_Z3_mk_solver_for_logic" - -external mk_solver_from_tactic : context -> tactic -> solver - = "camlidl_z3_Z3_mk_solver_from_tactic" - -external solver_get_help : context -> solver -> string - = "camlidl_z3_Z3_solver_get_help" - -external solver_get_param_descrs : context -> solver -> param_descrs - = "camlidl_z3_Z3_solver_get_param_descrs" - -external solver_set_params : context -> solver -> params -> unit - = "camlidl_z3_Z3_solver_set_params" - -external solver_push : context -> solver -> unit - = "camlidl_z3_Z3_solver_push" - -external solver_pop : context -> solver -> int -> unit - = "camlidl_z3_Z3_solver_pop" - -external solver_reset : context -> solver -> unit - = "camlidl_z3_Z3_solver_reset" - -external solver_get_num_scopes : context -> solver -> int - = "camlidl_z3_Z3_solver_get_num_scopes" - -external solver_assert : context -> solver -> ast -> unit - = "camlidl_z3_Z3_solver_assert" - -external solver_assert_and_track : context -> solver -> ast -> ast -> unit - = "camlidl_z3_Z3_solver_assert_and_track" - -external solver_get_assertions : context -> solver -> ast_vector - = "camlidl_z3_Z3_solver_get_assertions" - -external solver_check : context -> solver -> lbool - = "camlidl_z3_Z3_solver_check" - -external solver_check_assumptions : context -> solver -> ast array -> lbool - = "camlidl_z3_Z3_solver_check_assumptions" - -external solver_get_model : context -> solver -> model - = "camlidl_z3_Z3_solver_get_model" - -external solver_get_proof : context -> solver -> ast - = "camlidl_z3_Z3_solver_get_proof" - -external solver_get_unsat_core : context -> solver -> ast_vector - = "camlidl_z3_Z3_solver_get_unsat_core" - -external solver_get_reason_unknown : context -> solver -> string - = "camlidl_z3_Z3_solver_get_reason_unknown" - -external solver_get_statistics : context -> solver -> stats - = "camlidl_z3_Z3_solver_get_statistics" - -external solver_to_string : context -> solver -> string - = "camlidl_z3_Z3_solver_to_string" - - -type stat_datum = Stat_int of int | Stat_float of float -type stats_refined = (string, stat_datum) Hashtbl.t - -external stats_to_string : context -> stats -> string - = "camlidl_z3_Z3_stats_to_string" - -external stats_size : context -> stats -> int - = "camlidl_z3_Z3_stats_size" - -external stats_get_key : context -> stats -> int -> string - = "camlidl_z3_Z3_stats_get_key" - -external stats_is_uint : context -> stats -> int -> bool - = "camlidl_z3_Z3_stats_is_uint" - -external stats_is_double : context -> stats -> int -> bool - = "camlidl_z3_Z3_stats_is_double" - -external stats_get_uint_value : context -> stats -> int -> int - = "camlidl_z3_Z3_stats_get_uint_value" - -external stats_get_double_value : context -> stats -> int -> float - = "camlidl_z3_Z3_stats_get_double_value" - -external get_implied_equalities : context -> solver -> ast array -> lbool * int array - = "camlidl_z3_Z3_get_implied_equalities" - - -(* Internal auxiliary functions: *) -(* -(* Transform a pair of arrays into an array of pairs *) -let array_combine a b = - if Array.length a <> Array.length b then raise (Invalid_argument "array_combine"); - Array.init (Array.length a) (fun i -> (a.(i), b.(i))) -(* [a |> b] is the pipeline operator for [b(a)] *) -let ( |> ) x f = f x -*) -(* Find the index of an element in an array, raises Not_found is missing *) -let find equal x a = - let len = Array.length a in - let rec find_ i = - if i >= len then - raise Not_found - else - if equal x a.(i) then - i - else - find_ (i+1) - in - find_ 0 -(* Symbols *) -let symbol_refine c s = - match get_symbol_kind c s with - | INT_SYMBOL -> Symbol_int (get_symbol_int c s) - | STRING_SYMBOL -> Symbol_string (get_symbol_string c s) -let mk_symbol c = function - | Symbol_int(i) -> mk_int_symbol c i - | Symbol_string(s) -> mk_string_symbol c s -(* Sorts *) -let get_datatype_sort c s = - Array.init (get_datatype_sort_num_constructors c s) (fun i -> - let constructor = get_datatype_sort_constructor c s i in - let recognizer = get_datatype_sort_recognizer c s i in - let accessors = - Array.init (get_domain_size c constructor) (fun j -> - get_datatype_sort_constructor_accessor c s i j - ) in - {constructor; recognizer; accessors} - ) -let sort_refine c s = - match get_sort_kind c s with - | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c s) - | BOOL_SORT -> Sort_bool - | INT_SORT -> Sort_int - | BV_SORT -> Sort_bv (get_bv_sort_size c s) - | FINITE_DOMAIN_SORT -> - (match get_finite_domain_sort_size c s with - | Some(sz) -> Sort_finite_domain (get_sort_name c s, sz) - | None -> failwith "Z3.sort_refine: failed to get size of finite-domain sort" - ) - | REAL_SORT -> Sort_real - | ARRAY_SORT -> Sort_array (get_array_sort_domain c s, get_array_sort_range c s) - | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c s) - | RELATION_SORT -> Sort_relation (Array.init (get_relation_arity c s) (fun i -> get_relation_column c s i)) - | UNKNOWN_SORT -> Sort_unknown -let mk_sort c = function - | Sort_uninterpreted(s) -> mk_uninterpreted_sort c s - | Sort_bool -> mk_bool_sort c - | Sort_int -> mk_int_sort c - | Sort_bv(size) -> mk_bv_sort c size - | Sort_finite_domain(name,size) -> mk_finite_domain_sort c name size - | Sort_real -> mk_real_sort c - | Sort_array(domain,range) -> mk_array_sort c domain range - | Sort_datatype(constructors) -> get_range c constructors.(0).constructor - | Sort_relation(_) -> invalid_arg "Z3.mk_sort: cannot construct relation sorts" - | Sort_unknown(_) -> invalid_arg "Z3.mk_sort: cannot construct unknown sorts" -(* Replacement datatypes creation API *) -let mk_datatypes ctx generator = - let usort0 = mk_uninterpreted_sort ctx (mk_int_symbol ctx 0) - in - let rec find_num_sorts i = - if i = max_int then invalid_arg "mk_datatypes: too many sorts" - else - match generator (Array.make i usort0) with - | None -> find_num_sorts (i+1) - | Some(a) when Array.length a = i -> i - | Some _ -> invalid_arg "mk_datatypes: number of sorts and datatype descriptors must be equal" - in - let num_sorts = find_num_sorts 0 - in - let sorts0 = Array.init num_sorts (fun i -> mk_uninterpreted_sort ctx (mk_int_symbol ctx i)) - in - let ctorss_descriptors = - match generator sorts0 with - | Some(ctorss_descriptors) -> ctorss_descriptors - | None -> invalid_arg "mk_datatypes: generator failed" - in - let names = Array.map fst ctorss_descriptors - in - let ctorss = - Array.map (fun (_, ctors_descriptor) -> - Array.map (fun {constructor_desc; recognizer_desc; accessor_descs} -> - let field_names = Array.map fst accessor_descs - in - let sort_refs = Array.make (Array.length accessor_descs) 0 - in - let field_sorts = - Array.mapi (fun i (_, sort) -> - try - let j = find (fun s t -> is_eq_sort ctx s t) sort sorts0 in - sort_refs.(i) <- j ; - None - with Not_found -> - Some(sort) - ) accessor_descs - in - mk_constructor ctx constructor_desc recognizer_desc field_names field_sorts sort_refs - ) ctors_descriptor - ) ctorss_descriptors - in - let constructor_lists = Array.map (mk_constructor_list ctx) ctorss - in - let sorts,_ = mk_datatypes ctx names constructor_lists - in - let datatypes = - Array.mapi (fun i sort -> - (sort, - Array.mapi (fun j ctor -> - let num_fields = Array.length (snd ctorss_descriptors.(i)).(j).accessor_descs in - let constructor, recognizer, accessors = query_constructor ctx ctor num_fields in - {constructor; recognizer; accessors} - ) ctorss.(i)) - ) sorts - in - Array.iter (fun ctor_list -> - del_constructor_list ctx ctor_list - ) constructor_lists - ; - Array.iter (fun ctors -> - Array.iter (fun ctor -> - del_constructor ctx ctor - ) ctors - ) ctorss - ; - datatypes -(* Numerals *) -let rec numeral_refine c t = - assert( get_ast_kind c t = NUMERAL_AST ); - let sort = get_sort c t in - let is_int, i = get_numeral_int c t in - if is_int then - Numeral_int (i, sort) - else - let is_int64, i = get_numeral_int64 c t in - if is_int64 then - Numeral_int64 (i, sort) - else - if get_sort_kind c sort <> REAL_SORT then - Numeral_large (get_numeral_string c t, sort) - else - let n = numeral_refine c (get_numerator c t) in - let d = numeral_refine c (get_denominator c t) in - Numeral_rational (n, d) -let to_real c x = - if get_sort_kind c (get_sort c x) = REAL_SORT then - x - else - mk_int2real c x -let rec embed_numeral c = function - | Numeral_int (i, s) -> mk_int c i s - | Numeral_int64 (i, s) -> mk_int64 c i s - | Numeral_large (l, s) -> mk_numeral c l s - | Numeral_rational (Numeral_int(n,_), Numeral_int(d,_)) -> mk_real c n d - | Numeral_rational (n, d) -> - mk_div c (to_real c (embed_numeral c n)) (to_real c (embed_numeral c d)) - (* Or should the following be used instead? - let n_str = get_numeral_string c (embed_numeral c n) in - let d_str = get_numeral_string c (embed_numeral c d) in - mk_numeral c (n_str ^ " / " ^ d_str) (mk_real_sort c) - *) -(* Terms *) -let get_app_args c a = - Array.init (get_app_num_args c a) (get_app_arg c a);; -let get_domains c d = - Array.init (get_domain_size c d) (get_domain c d);; -let get_pattern_terms c p = - Array.init (get_pattern_num_terms c p) (get_pattern c p) -let term_refine c t = - match get_ast_kind c t with - | NUMERAL_AST -> - Term_numeral (numeral_refine c t) - | APP_AST -> - let t' = to_app c t in - let f = get_app_decl c t' in - let num_args = get_app_num_args c t' in - let args = Array.init num_args (get_app_arg c t') in - let k = get_decl_kind c f in - Term_app (k, f, args) - | QUANTIFIER_AST -> - let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in - let bound = - Array.init nb (fun i -> - (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i) - ) in - let body = get_quantifier_body c t in - Term_quantifier (bt, w, pats, bound, body) - | VAR_AST -> - Term_var (get_index_value c t, get_sort c t) - | _ -> - assert false -(* let mk_term c = function *) -(* | Term_numeral (numeral, sort) -> mk_numeral c numeral sort *) -(* | Term_app (kind, decl, args) -> *) -(* | Term_quantifier (strength, weight, pats, bound, body) -> *) -(* | Term_var (index, sort) -> *) -(* Refined model API *) -let model_refine c m = - let num_sorts = model_get_num_sorts c m in - let sorts = Hashtbl.create num_sorts in - for i = 0 to num_sorts - 1 do - let sort = model_get_sort c m i in - let universe = model_get_sort_universe c m sort in - Hashtbl.add sorts sort universe - done; - let num_consts = model_get_num_consts c m in - let consts = Hashtbl.create num_consts in - let arrays = Hashtbl.create 0 in - for i = 0 to num_consts - 1 do - let const_decl = model_get_const_decl c m i in - match model_get_const_interp c m const_decl with - | Some(const_interp) -> - if is_as_array c const_interp then - let array_decl = get_as_array_func_decl c const_interp in - match model_get_func_interp c m array_decl with - | Some(array_interp) -> - let num_entries = func_interp_get_num_entries c array_interp in - let tbl = Hashtbl.create num_entries in - for i = 0 to num_entries - 1 do - let entry = func_interp_get_entry c array_interp i in - assert( func_entry_get_num_args c entry = 1 ); - let arg = func_entry_get_arg c entry 0 in - let value = func_entry_get_value c entry in - Hashtbl.add tbl arg value - done; - let default = func_interp_get_else c array_interp in - Hashtbl.add arrays const_decl (tbl, default) - | None -> - () - else - Hashtbl.add consts const_decl const_interp - | None -> - () - done; - let num_funcs = model_get_num_funcs c m in - let funcs = Hashtbl.create num_funcs in - for i = 0 to num_funcs - 1 do - let func_decl = model_get_func_decl c m i in - if not (Hashtbl.mem arrays func_decl) then - match model_get_func_interp c m func_decl with - | Some(func_interp) -> - let num_entries = func_interp_get_num_entries c func_interp in - let tbl = Hashtbl.create num_entries in - for i = 0 to num_entries - 1 do - let entry = func_interp_get_entry c func_interp i in - let num_args = func_entry_get_num_args c entry in - let args = Array.init num_args (fun i -> func_entry_get_arg c entry i) in - let value = func_entry_get_value c entry in - Hashtbl.add tbl args value - done; - let default = func_interp_get_else c func_interp in - Hashtbl.add funcs func_decl (tbl, default) - | None -> - () - done; - {sorts; consts; arrays; funcs} -(* Extended parser API *) -let get_smtlib_formulas c = - Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c) -let get_smtlib_assumptions c = - Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c) -let get_smtlib_decls c = - Array.init (get_smtlib_num_decls c) (get_smtlib_decl c) -let get_smtlib_parse_results c = - (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c) -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = - parse_smtlib_string c a1 a2 a3 a4 a5 ; - get_smtlib_parse_results c -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = - parse_smtlib_file c a1 a2 a3 a4 a5 ; - get_smtlib_parse_results c -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = - parse_smtlib_string c a1 a2 a3 a4 a5 ; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_string_formula" -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = - parse_smtlib_file c a1 a2 a3 a4 a5 ; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_file_formula" -(* Error handling *) -let get_error_msg c e = - match e with - | PARSER_ERROR -> (get_error_msg_ex c e) ^ ": " ^ (get_smtlib_error c) - | _ -> get_error_msg_ex c e -(* Refined stats API *) -let stats_refine c s = - let num_stats = stats_size c s in - let tbl = Hashtbl.create num_stats in - for i = 0 to num_stats - 1 do - let key = stats_get_key c s i in - let datum = - if stats_is_uint c s i then - Stat_int(stats_get_uint_value c s i) - else - Stat_float(stats_get_double_value c s i) in - Hashtbl.add tbl key datum - done; - tbl - - -let _ = - Printexc.register_printer (function - | Error(c,e) -> Some ("Z3 "^(get_error_msg c e)) - | _ -> None - ) - - -module V3 = struct - -(* File generated from z3V3.idl *) - -type symbol -and literals -and theory -and config -and context -and sort -and func_decl -and ast -and app -and pattern -and model -and constructor -and constructor_list - -and lbool = - | L_FALSE - | L_UNDEF - | L_TRUE - -and symbol_kind = - | INT_SYMBOL - | STRING_SYMBOL - -and parameter_kind = - | PARAMETER_INT - | PARAMETER_DOUBLE - | PARAMETER_RATIONAL - | PARAMETER_SYMBOL - | PARAMETER_SORT - | PARAMETER_AST - | PARAMETER_FUNC_DECL - -and sort_kind = - | UNINTERPRETED_SORT - | BOOL_SORT - | INT_SORT - | REAL_SORT - | BV_SORT - | ARRAY_SORT - | DATATYPE_SORT - | RELATION_SORT - | FINITE_DOMAIN_SORT - | UNKNOWN_SORT - -and ast_kind = - | NUMERAL_AST - | APP_AST - | VAR_AST - | QUANTIFIER_AST - | SORT_AST - | FUNC_DECL_AST - | UNKNOWN_AST - -and decl_kind = - | OP_TRUE - | OP_FALSE - | OP_EQ - | OP_DISTINCT - | OP_ITE - | OP_AND - | OP_OR - | OP_IFF - | OP_XOR - | OP_NOT - | OP_IMPLIES - | OP_OEQ - | OP_ANUM - | OP_AGNUM - | OP_LE - | OP_GE - | OP_LT - | OP_GT - | OP_ADD - | OP_SUB - | OP_UMINUS - | OP_MUL - | OP_DIV - | OP_IDIV - | OP_REM - | OP_MOD - | OP_TO_REAL - | OP_TO_INT - | OP_IS_INT - | OP_POWER - | OP_STORE - | OP_SELECT - | OP_CONST_ARRAY - | OP_ARRAY_MAP - | OP_ARRAY_DEFAULT - | OP_SET_UNION - | OP_SET_INTERSECT - | OP_SET_DIFFERENCE - | OP_SET_COMPLEMENT - | OP_SET_SUBSET - | OP_AS_ARRAY - | OP_BNUM - | OP_BIT1 - | OP_BIT0 - | OP_BNEG - | OP_BADD - | OP_BSUB - | OP_BMUL - | OP_BSDIV - | OP_BUDIV - | OP_BSREM - | OP_BUREM - | OP_BSMOD - | OP_BSDIV0 - | OP_BUDIV0 - | OP_BSREM0 - | OP_BUREM0 - | OP_BSMOD0 - | OP_ULEQ - | OP_SLEQ - | OP_UGEQ - | OP_SGEQ - | OP_ULT - | OP_SLT - | OP_UGT - | OP_SGT - | OP_BAND - | OP_BOR - | OP_BNOT - | OP_BXOR - | OP_BNAND - | OP_BNOR - | OP_BXNOR - | OP_CONCAT - | OP_SIGN_EXT - | OP_ZERO_EXT - | OP_EXTRACT - | OP_REPEAT - | OP_BREDOR - | OP_BREDAND - | OP_BCOMP - | OP_BSHL - | OP_BLSHR - | OP_BASHR - | OP_ROTATE_LEFT - | OP_ROTATE_RIGHT - | OP_EXT_ROTATE_LEFT - | OP_EXT_ROTATE_RIGHT - | OP_INT2BV - | OP_BV2INT - | OP_CARRY - | OP_XOR3 - | OP_PR_UNDEF - | OP_PR_TRUE - | OP_PR_ASSERTED - | OP_PR_GOAL - | OP_PR_MODUS_PONENS - | OP_PR_REFLEXIVITY - | OP_PR_SYMMETRY - | OP_PR_TRANSITIVITY - | OP_PR_TRANSITIVITY_STAR - | OP_PR_MONOTONICITY - | OP_PR_QUANT_INTRO - | OP_PR_DISTRIBUTIVITY - | OP_PR_AND_ELIM - | OP_PR_NOT_OR_ELIM - | OP_PR_REWRITE - | OP_PR_REWRITE_STAR - | OP_PR_PULL_QUANT - | OP_PR_PULL_QUANT_STAR - | OP_PR_PUSH_QUANT - | OP_PR_ELIM_UNUSED_VARS - | OP_PR_DER - | OP_PR_QUANT_INST - | OP_PR_HYPOTHESIS - | OP_PR_LEMMA - | OP_PR_UNIT_RESOLUTION - | OP_PR_IFF_TRUE - | OP_PR_IFF_FALSE - | OP_PR_COMMUTATIVITY - | OP_PR_DEF_AXIOM - | OP_PR_DEF_INTRO - | OP_PR_APPLY_DEF - | OP_PR_IFF_OEQ - | OP_PR_NNF_POS - | OP_PR_NNF_NEG - | OP_PR_NNF_STAR - | OP_PR_CNF_STAR - | OP_PR_SKOLEMIZE - | OP_PR_MODUS_PONENS_OEQ - | OP_PR_TH_LEMMA - | OP_PR_HYPER_RESOLVE - | OP_RA_STORE - | OP_RA_EMPTY - | OP_RA_IS_EMPTY - | OP_RA_JOIN - | OP_RA_UNION - | OP_RA_WIDEN - | OP_RA_PROJECT - | OP_RA_FILTER - | OP_RA_NEGATION_FILTER - | OP_RA_RENAME - | OP_RA_COMPLEMENT - | OP_RA_SELECT - | OP_RA_CLONE - | OP_FD_LT - | OP_LABEL - | OP_LABEL_LIT - | OP_DT_CONSTRUCTOR - | OP_DT_RECOGNISER - | OP_DT_ACCESSOR - | OP_UNINTERPRETED - -and param_kind = - | PK_UINT - | PK_BOOL - | PK_DOUBLE - | PK_SYMBOL - | PK_STRING - | PK_OTHER - | PK_INVALID - -and search_failure = - | NO_FAILURE - | UNKNOWN - | TIMEOUT - | MEMOUT_WATERMARK - | CANCELED - | NUM_CONFLICTS - | THEORY - | QUANTIFIERS - -and ast_print_mode = - | PRINT_SMTLIB_FULL - | PRINT_LOW_LEVEL - | PRINT_SMTLIB_COMPLIANT - | PRINT_SMTLIB2_COMPLIANT - - -external global_param_set : string -> string -> unit - = "camlidl_z3V3_Z3_global_param_set" - -external global_param_reset_all : unit -> unit - = "camlidl_z3V3_Z3_global_param_reset_all" - -external global_param_get : string -> string option - = "camlidl_z3V3_Z3_global_param_get" - -external mk_config : unit -> config - = "camlidl_z3V3_Z3_mk_config" - -external del_config : config -> unit - = "camlidl_z3V3_Z3_del_config" - -external set_param_value : config -> string -> string -> unit - = "camlidl_z3V3_Z3_set_param_value" - -external mk_context : config -> context - = "camlidl_z3V3_Z3_mk_context" - -external del_context : context -> unit - = "camlidl_z3V3_Z3_del_context" - -external update_param_value : context -> string -> string -> unit - = "camlidl_z3V3_Z3_update_param_value" - -external get_param_value : context -> string -> string option - = "camlidl_z3V3_Z3_get_param_value" - -external mk_int_symbol : context -> int -> symbol - = "camlidl_z3V3_Z3_mk_int_symbol" - -external mk_string_symbol : context -> string -> symbol - = "camlidl_z3V3_Z3_mk_string_symbol" - -external mk_uninterpreted_sort : context -> symbol -> sort - = "camlidl_z3V3_Z3_mk_uninterpreted_sort" - -external mk_bool_sort : context -> sort - = "camlidl_z3V3_Z3_mk_bool_sort" - -external mk_int_sort : context -> sort - = "camlidl_z3V3_Z3_mk_int_sort" - -external mk_real_sort : context -> sort - = "camlidl_z3V3_Z3_mk_real_sort" - -external mk_bv_sort : context -> int -> sort - = "camlidl_z3V3_Z3_mk_bv_sort" - -external mk_finite_domain_sort : context -> symbol -> int64 -> sort - = "camlidl_z3V3_Z3_mk_finite_domain_sort" - -external mk_array_sort : context -> sort -> sort -> sort - = "camlidl_z3V3_Z3_mk_array_sort" - -external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array - = "camlidl_z3V3_Z3_mk_tuple_sort" - -external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array - = "camlidl_z3V3_Z3_mk_enumeration_sort" - -external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl - = "camlidl_z3V3_Z3_mk_list_sort" - -external mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - = "camlidl_z3V3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" - -external del_constructor : context -> constructor -> unit - = "camlidl_z3V3_Z3_del_constructor" - -external mk_datatype : context -> symbol -> constructor array -> sort * constructor array - = "camlidl_z3V3_Z3_mk_datatype" - -external mk_constructor_list : context -> constructor array -> constructor_list - = "camlidl_z3V3_Z3_mk_constructor_list" - -external del_constructor_list : context -> constructor_list -> unit - = "camlidl_z3V3_Z3_del_constructor_list" - -external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array - = "camlidl_z3V3_Z3_mk_datatypes" - -external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array - = "camlidl_z3V3_Z3_query_constructor" - -external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_func_decl" - -external mk_app : context -> func_decl -> ast array -> ast - = "camlidl_z3V3_Z3_mk_app" - -external mk_const : context -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_mk_const" - -external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_fresh_func_decl" - -external mk_fresh_const : context -> string -> sort -> ast - = "camlidl_z3V3_Z3_mk_fresh_const" - -external mk_true : context -> ast - = "camlidl_z3V3_Z3_mk_true" - -external mk_false : context -> ast - = "camlidl_z3V3_Z3_mk_false" - -external mk_eq : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_eq" - -external mk_distinct : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_distinct" - -external mk_not : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_not" - -external mk_ite : context -> ast -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ite" - -external mk_iff : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_iff" - -external mk_implies : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_implies" - -external mk_xor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_xor" - -external mk_and : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_and" - -external mk_or : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_or" - -external mk_add : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_add" - -external mk_mul : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_mul" - -external mk_sub : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_sub" - -external mk_unary_minus : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_unary_minus" - -external mk_div : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_div" - -external mk_mod : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_mod" - -external mk_rem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_rem" - -external mk_power : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_power" - -external mk_lt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_lt" - -external mk_le : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_le" - -external mk_gt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_gt" - -external mk_ge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ge" - -external mk_int2real : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_int2real" - -external mk_real2int : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_real2int" - -external mk_is_int : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_is_int" - -external mk_bvnot : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnot" - -external mk_bvredand : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvredand" - -external mk_bvredor : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvredor" - -external mk_bvand : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvand" - -external mk_bvor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvor" - -external mk_bvxor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvxor" - -external mk_bvnand : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnand" - -external mk_bvnor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnor" - -external mk_bvxnor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvxnor" - -external mk_bvneg : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvneg" - -external mk_bvadd : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvadd" - -external mk_bvsub : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsub" - -external mk_bvmul : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvmul" - -external mk_bvudiv : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvudiv" - -external mk_bvsdiv : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsdiv" - -external mk_bvurem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvurem" - -external mk_bvsrem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsrem" - -external mk_bvsmod : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsmod" - -external mk_bvult : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvult" - -external mk_bvslt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvslt" - -external mk_bvule : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvule" - -external mk_bvsle : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsle" - -external mk_bvuge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvuge" - -external mk_bvsge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsge" - -external mk_bvugt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvugt" - -external mk_bvsgt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsgt" - -external mk_concat : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_concat" - -external mk_extract : context -> int -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_extract" - -external mk_sign_ext : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_sign_ext" - -external mk_zero_ext : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_zero_ext" - -external mk_repeat : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_repeat" - -external mk_bvshl : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvshl" - -external mk_bvlshr : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvlshr" - -external mk_bvashr : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvashr" - -external mk_rotate_left : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_rotate_left" - -external mk_rotate_right : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_rotate_right" - -external mk_ext_rotate_left : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ext_rotate_left" - -external mk_ext_rotate_right : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ext_rotate_right" - -external mk_int2bv : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_int2bv" - -external mk_bv2int : context -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bv2int" - -external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvadd_no_overflow" - -external mk_bvadd_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvadd_no_underflow" - -external mk_bvsub_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsub_no_overflow" - -external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvsub_no_underflow" - -external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsdiv_no_overflow" - -external mk_bvneg_no_overflow : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvneg_no_overflow" - -external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvmul_no_overflow" - -external mk_bvmul_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvmul_no_underflow" - -external mk_select : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_select" - -external mk_store : context -> ast -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_store" - -external mk_const_array : context -> sort -> ast -> ast - = "camlidl_z3V3_Z3_mk_const_array" - -external mk_map : context -> func_decl -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_map" - -external mk_array_default : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_array_default" - -external mk_set_sort : context -> sort -> sort - = "camlidl_z3V3_Z3_mk_set_sort" - -external mk_empty_set : context -> sort -> ast - = "camlidl_z3V3_Z3_mk_empty_set" - -external mk_full_set : context -> sort -> ast - = "camlidl_z3V3_Z3_mk_full_set" - -external mk_set_add : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_add" - -external mk_set_del : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_del" - -external mk_set_union : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_set_union" - -external mk_set_intersect : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_set_intersect" - -external mk_set_difference : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_difference" - -external mk_set_complement : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_complement" - -external mk_set_member : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_member" - -external mk_set_subset : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_subset" - -external mk_numeral : context -> string -> sort -> ast - = "camlidl_z3V3_Z3_mk_numeral" - -external mk_real : context -> int -> int -> ast - = "camlidl_z3V3_Z3_mk_real" - -external mk_int : context -> int -> sort -> ast - = "camlidl_z3V3_Z3_mk_int" - -external mk_int64 : context -> int64 -> sort -> ast - = "camlidl_z3V3_Z3_mk_int64" - -external mk_pattern : context -> ast array -> pattern - = "camlidl_z3V3_Z3_mk_pattern" - -external mk_bound : context -> int -> sort -> ast - = "camlidl_z3V3_Z3_mk_bound" - -external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" - -external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" - -external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" - -external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" - -external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_forall_const" - -external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_exists_const" - -external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" - -external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" - -external get_symbol_kind : context -> symbol -> symbol_kind - = "camlidl_z3V3_Z3_get_symbol_kind" - -external get_symbol_int : context -> symbol -> int - = "camlidl_z3V3_Z3_get_symbol_int" - -external get_symbol_string : context -> symbol -> string - = "camlidl_z3V3_Z3_get_symbol_string" - -external get_sort_name : context -> sort -> symbol - = "camlidl_z3V3_Z3_get_sort_name" - -external get_sort_id : context -> sort -> int - = "camlidl_z3V3_Z3_get_sort_id" - -external sort_to_ast : context -> sort -> ast - = "camlidl_z3V3_Z3_sort_to_ast" - -external is_eq_sort : context -> sort -> sort -> bool - = "camlidl_z3V3_Z3_is_eq_sort" - -external get_sort_kind : context -> sort -> sort_kind - = "camlidl_z3V3_Z3_get_sort_kind" - -external get_bv_sort_size : context -> sort -> int - = "camlidl_z3V3_Z3_get_bv_sort_size" - -external get_finite_domain_sort_size : context -> sort -> int64 option - = "camlidl_z3V3_Z3_get_finite_domain_sort_size" - -external get_array_sort_domain : context -> sort -> sort - = "camlidl_z3V3_Z3_get_array_sort_domain" - -external get_array_sort_range : context -> sort -> sort - = "camlidl_z3V3_Z3_get_array_sort_range" - -external get_tuple_sort_mk_decl : context -> sort -> func_decl - = "camlidl_z3V3_Z3_get_tuple_sort_mk_decl" - -external get_tuple_sort_num_fields : context -> sort -> int - = "camlidl_z3V3_Z3_get_tuple_sort_num_fields" - -external get_tuple_sort_field_decl : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_tuple_sort_field_decl" - -external get_datatype_sort_num_constructors : context -> sort -> int - = "camlidl_z3V3_Z3_get_datatype_sort_num_constructors" - -external get_datatype_sort_constructor : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_constructor" - -external get_datatype_sort_recognizer : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_recognizer" - -external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_constructor_accessor" - -external get_relation_arity : context -> sort -> int - = "camlidl_z3V3_Z3_get_relation_arity" - -external get_relation_column : context -> sort -> int -> sort - = "camlidl_z3V3_Z3_get_relation_column" - -external func_decl_to_ast : context -> func_decl -> ast - = "camlidl_z3V3_Z3_func_decl_to_ast" - -external is_eq_func_decl : context -> func_decl -> func_decl -> bool - = "camlidl_z3V3_Z3_is_eq_func_decl" - -external get_func_decl_id : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_func_decl_id" - -external get_decl_name : context -> func_decl -> symbol - = "camlidl_z3V3_Z3_get_decl_name" - -external get_decl_kind : context -> func_decl -> decl_kind - = "camlidl_z3V3_Z3_get_decl_kind" - -external get_domain_size : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_domain_size" - -external get_arity : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_arity" - -external get_domain : context -> func_decl -> int -> sort - = "camlidl_z3V3_Z3_get_domain" - -external get_range : context -> func_decl -> sort - = "camlidl_z3V3_Z3_get_range" - -external get_decl_num_parameters : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_decl_num_parameters" - -external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind - = "camlidl_z3V3_Z3_get_decl_parameter_kind" - -external get_decl_int_parameter : context -> func_decl -> int -> int - = "camlidl_z3V3_Z3_get_decl_int_parameter" - -external get_decl_double_parameter : context -> func_decl -> int -> float - = "camlidl_z3V3_Z3_get_decl_double_parameter" - -external get_decl_symbol_parameter : context -> func_decl -> int -> symbol - = "camlidl_z3V3_Z3_get_decl_symbol_parameter" - -external get_decl_sort_parameter : context -> func_decl -> int -> sort - = "camlidl_z3V3_Z3_get_decl_sort_parameter" - -external get_decl_ast_parameter : context -> func_decl -> int -> ast - = "camlidl_z3V3_Z3_get_decl_ast_parameter" - -external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl - = "camlidl_z3V3_Z3_get_decl_func_decl_parameter" - -external get_decl_rational_parameter : context -> func_decl -> int -> string - = "camlidl_z3V3_Z3_get_decl_rational_parameter" - -external app_to_ast : context -> app -> ast - = "camlidl_z3V3_Z3_app_to_ast" - -external get_app_decl : context -> app -> func_decl - = "camlidl_z3V3_Z3_get_app_decl" - -external get_app_num_args : context -> app -> int - = "camlidl_z3V3_Z3_get_app_num_args" - -external get_app_arg : context -> app -> int -> ast - = "camlidl_z3V3_Z3_get_app_arg" - -external is_eq_ast : context -> ast -> ast -> bool - = "camlidl_z3V3_Z3_is_eq_ast" - -external get_ast_id : context -> ast -> int - = "camlidl_z3V3_Z3_get_ast_id" - -external get_ast_hash : context -> ast -> int - = "camlidl_z3V3_Z3_get_ast_hash" - -external get_sort : context -> ast -> sort - = "camlidl_z3V3_Z3_get_sort" - -external is_well_sorted : context -> ast -> bool - = "camlidl_z3V3_Z3_is_well_sorted" - -external get_bool_value : context -> ast -> lbool - = "camlidl_z3V3_Z3_get_bool_value" - -external get_ast_kind : context -> ast -> ast_kind - = "camlidl_z3V3_Z3_get_ast_kind" - -external is_app : context -> ast -> bool - = "camlidl_z3V3_Z3_is_app" - -external is_numeral_ast : context -> ast -> bool - = "camlidl_z3V3_Z3_is_numeral_ast" - -external is_algebraic_number : context -> ast -> bool - = "camlidl_z3V3_Z3_is_algebraic_number" - -external to_app : context -> ast -> app - = "camlidl_z3V3_Z3_to_app" - -external to_func_decl : context -> ast -> func_decl - = "camlidl_z3V3_Z3_to_func_decl" - -external get_numeral_string : context -> ast -> string - = "camlidl_z3V3_Z3_get_numeral_string" - -external get_numeral_decimal_string : context -> ast -> int -> string - = "camlidl_z3V3_Z3_get_numeral_decimal_string" - -external get_numerator : context -> ast -> ast - = "camlidl_z3V3_Z3_get_numerator" - -external get_denominator : context -> ast -> ast - = "camlidl_z3V3_Z3_get_denominator" - -external get_numeral_small : context -> ast -> bool * int64 * int64 - = "camlidl_z3V3_Z3_get_numeral_small" - -external get_numeral_int : context -> ast -> bool * int - = "camlidl_z3V3_Z3_get_numeral_int" - -external get_numeral_int64 : context -> ast -> bool * int64 - = "camlidl_z3V3_Z3_get_numeral_int64" - -external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 - = "camlidl_z3V3_Z3_get_numeral_rational_int64" - -external get_algebraic_number_lower : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_algebraic_number_lower" - -external get_algebraic_number_upper : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_algebraic_number_upper" - -external pattern_to_ast : context -> pattern -> ast - = "camlidl_z3V3_Z3_pattern_to_ast" - -external get_pattern_num_terms : context -> pattern -> int - = "camlidl_z3V3_Z3_get_pattern_num_terms" - -external get_pattern : context -> pattern -> int -> ast - = "camlidl_z3V3_Z3_get_pattern" - -external get_index_value : context -> ast -> int - = "camlidl_z3V3_Z3_get_index_value" - -external is_quantifier_forall : context -> ast -> bool - = "camlidl_z3V3_Z3_is_quantifier_forall" - -external get_quantifier_weight : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_weight" - -external get_quantifier_num_patterns : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_patterns" - -external get_quantifier_pattern_ast : context -> ast -> int -> pattern - = "camlidl_z3V3_Z3_get_quantifier_pattern_ast" - -external get_quantifier_num_no_patterns : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_no_patterns" - -external get_quantifier_no_pattern_ast : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_quantifier_no_pattern_ast" - -external get_quantifier_num_bound : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_bound" - -external get_quantifier_bound_name : context -> ast -> int -> symbol - = "camlidl_z3V3_Z3_get_quantifier_bound_name" - -external get_quantifier_bound_sort : context -> ast -> int -> sort - = "camlidl_z3V3_Z3_get_quantifier_bound_sort" - -external get_quantifier_body : context -> ast -> ast - = "camlidl_z3V3_Z3_get_quantifier_body" - -external simplify : context -> ast -> ast - = "camlidl_z3V3_Z3_simplify" - -external update_term : context -> ast -> ast array -> ast - = "camlidl_z3V3_Z3_update_term" - -external substitute : context -> ast -> ast array -> ast array -> ast - = "camlidl_z3V3_Z3_substitute" - -external substitute_vars : context -> ast -> ast array -> ast - = "camlidl_z3V3_Z3_substitute_vars" - -external open_log : string -> bool - = "camlidl_z3V3_Z3_open_log" - -external append_log : string -> unit - = "camlidl_z3V3_Z3_append_log" - -external close_log : unit -> unit - = "camlidl_z3V3_Z3_close_log" - -external toggle_warning_messages : bool -> unit - = "camlidl_z3V3_Z3_toggle_warning_messages" - -external set_ast_print_mode : context -> ast_print_mode -> unit - = "camlidl_z3V3_Z3_set_ast_print_mode" - -external ast_to_string : context -> ast -> string - = "camlidl_z3V3_Z3_ast_to_string" - -external pattern_to_string : context -> pattern -> string - = "camlidl_z3V3_Z3_pattern_to_string" - -external sort_to_string : context -> sort -> string - = "camlidl_z3V3_Z3_sort_to_string" - -external func_decl_to_string : context -> func_decl -> string - = "camlidl_z3V3_Z3_func_decl_to_string" - -external model_to_string : context -> model -> string - = "camlidl_z3V3_Z3_model_to_string" - -external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" - -external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3V3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" - -external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3V3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" - -external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3V3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" - -external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3V3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" - -external get_smtlib_num_formulas : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_formulas" - -external get_smtlib_formula : context -> int -> ast - = "camlidl_z3V3_Z3_get_smtlib_formula" - -external get_smtlib_num_assumptions : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_assumptions" - -external get_smtlib_assumption : context -> int -> ast - = "camlidl_z3V3_Z3_get_smtlib_assumption" - -external get_smtlib_num_decls : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_decls" - -external get_smtlib_decl : context -> int -> func_decl - = "camlidl_z3V3_Z3_get_smtlib_decl" - -external get_smtlib_num_sorts : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_sorts" - -external get_smtlib_sort : context -> int -> sort - = "camlidl_z3V3_Z3_get_smtlib_sort" - -external get_smtlib_error : context -> string - = "camlidl_z3V3_Z3_get_smtlib_error" - -external get_version : unit -> int * int * int * int - = "camlidl_z3V3_Z3_get_version" - -external enable_trace : string -> unit - = "camlidl_z3V3_Z3_enable_trace" - -external disable_trace : string -> unit - = "camlidl_z3V3_Z3_disable_trace" - -external reset_memory : unit -> unit - = "camlidl_z3V3_Z3_reset_memory" - -external theory_mk_sort : context -> theory -> symbol -> sort - = "camlidl_z3V3_Z3_theory_mk_sort" - -external theory_mk_value : context -> theory -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_theory_mk_value" - -external theory_mk_constant : context -> theory -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_theory_mk_constant" - -external theory_mk_func_decl : context -> theory -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_theory_mk_func_decl" - -external theory_get_context : theory -> context - = "camlidl_z3V3_Z3_theory_get_context" - -external theory_assert_axiom : theory -> ast -> unit - = "camlidl_z3V3_Z3_theory_assert_axiom" - -external theory_assume_eq : theory -> ast -> ast -> unit - = "camlidl_z3V3_Z3_theory_assume_eq" - -external theory_enable_axiom_simplification : theory -> bool -> unit - = "camlidl_z3V3_Z3_theory_enable_axiom_simplification" - -external theory_get_eqc_root : theory -> ast -> ast - = "camlidl_z3V3_Z3_theory_get_eqc_root" - -external theory_get_eqc_next : theory -> ast -> ast - = "camlidl_z3V3_Z3_theory_get_eqc_next" - -external theory_get_num_parents : theory -> ast -> int - = "camlidl_z3V3_Z3_theory_get_num_parents" - -external theory_get_parent : theory -> ast -> int -> ast - = "camlidl_z3V3_Z3_theory_get_parent" - -external theory_is_value : theory -> ast -> bool - = "camlidl_z3V3_Z3_theory_is_value" - -external theory_is_decl : theory -> func_decl -> bool - = "camlidl_z3V3_Z3_theory_is_decl" - -external theory_get_num_elems : theory -> int - = "camlidl_z3V3_Z3_theory_get_num_elems" - -external theory_get_elem : theory -> int -> ast - = "camlidl_z3V3_Z3_theory_get_elem" - -external theory_get_num_apps : theory -> int - = "camlidl_z3V3_Z3_theory_get_num_apps" - -external theory_get_app : theory -> int -> ast - = "camlidl_z3V3_Z3_theory_get_app" - -external mk_injective_function : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_injective_function" - -external set_logic : context -> string -> bool - = "camlidl_z3V3_Z3_set_logic" - -external push : context -> unit - = "camlidl_z3V3_Z3_push" - -external pop : context -> int -> unit - = "camlidl_z3V3_Z3_pop" - -external get_num_scopes : context -> int - = "camlidl_z3V3_Z3_get_num_scopes" - -external persist_ast : context -> ast -> int -> unit - = "camlidl_z3V3_Z3_persist_ast" - -external assert_cnstr : context -> ast -> unit - = "camlidl_z3V3_Z3_assert_cnstr" - -external check_and_get_model : context -> lbool * model - = "camlidl_z3V3_Z3_check_and_get_model" - -external check : context -> lbool - = "camlidl_z3V3_Z3_check" - -external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array - = "camlidl_z3V3_Z3_check_assumptions" - -external del_model : context -> model -> unit - = "camlidl_z3V3_Z3_del_model" - -external soft_check_cancel : context -> unit - = "camlidl_z3V3_Z3_soft_check_cancel" - -external get_search_failure : context -> search_failure - = "camlidl_z3V3_Z3_get_search_failure" - -external mk_label : context -> symbol -> bool -> ast -> ast - = "camlidl_z3V3_Z3_mk_label" - -external get_relevant_labels : context -> literals - = "camlidl_z3V3_Z3_get_relevant_labels" - -external get_relevant_literals : context -> literals - = "camlidl_z3V3_Z3_get_relevant_literals" - -external get_guessed_literals : context -> literals - = "camlidl_z3V3_Z3_get_guessed_literals" - -external del_literals : context -> literals -> unit - = "camlidl_z3V3_Z3_del_literals" - -external get_num_literals : context -> literals -> int - = "camlidl_z3V3_Z3_get_num_literals" - -external get_label_symbol : context -> literals -> int -> symbol - = "camlidl_z3V3_Z3_get_label_symbol" - -external get_literal : context -> literals -> int -> ast - = "camlidl_z3V3_Z3_get_literal" - -external disable_literal : context -> literals -> int -> unit - = "camlidl_z3V3_Z3_disable_literal" - -external block_literals : context -> literals -> unit - = "camlidl_z3V3_Z3_block_literals" - -external get_model_num_constants : context -> model -> int - = "camlidl_z3V3_Z3_get_model_num_constants" - -external get_model_constant : context -> model -> int -> func_decl - = "camlidl_z3V3_Z3_get_model_constant" - -external get_model_num_funcs : context -> model -> int - = "camlidl_z3V3_Z3_get_model_num_funcs" - -external get_model_func_decl : context -> model -> int -> func_decl - = "camlidl_z3V3_Z3_get_model_func_decl" - -external eval_func_decl : context -> model -> func_decl -> bool * ast - = "camlidl_z3V3_Z3_eval_func_decl" - -external is_array_value : context -> model -> ast -> bool * int - = "camlidl_z3V3_Z3_is_array_value" - -external get_array_value : context -> model -> ast -> ast array -> ast array -> ast array * ast array * ast - = "camlidl_z3V3_Z3_get_array_value" - -external get_model_func_else : context -> model -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_else" - -external get_model_func_num_entries : context -> model -> int -> int - = "camlidl_z3V3_Z3_get_model_func_num_entries" - -external get_model_func_entry_num_args : context -> model -> int -> int -> int - = "camlidl_z3V3_Z3_get_model_func_entry_num_args" - -external get_model_func_entry_arg : context -> model -> int -> int -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_entry_arg" - -external get_model_func_entry_value : context -> model -> int -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_entry_value" - -external eval : context -> model -> ast -> bool * ast - = "camlidl_z3V3_Z3_eval" - -external eval_decl : context -> model -> func_decl -> ast array -> bool * ast - = "camlidl_z3V3_Z3_eval_decl" - -external context_to_string : context -> string - = "camlidl_z3V3_Z3_context_to_string" - -external statistics_to_string : context -> string - = "camlidl_z3V3_Z3_statistics_to_string" - -external get_context_assignment : context -> ast - = "camlidl_z3V3_Z3_get_context_assignment" - - -(* Internal auxillary functions: *) -(* Transform a pair of arrays into an array of pairs *) -let array_combine a b = - if Array.length a <> Array.length b then raise (Invalid_argument "array_combine"); - Array.init (Array.length a) (fun i->(a.(i),b.(i)));; -(* [a |> b] is the pipeline operator for [b(a)] *) -let ( |> ) x f = f x;; -(* Extensions, except for refinement: *) -let mk_context_x configs = - let config = mk_config() in - let f(param_id,param_value) = set_param_value config param_id param_value in - Array.iter f configs; - let context = mk_context config in - del_config config; - context;; -let get_app_args c a = - Array.init (get_app_num_args c a) (get_app_arg c a);; -let get_domains c d = - Array.init (get_domain_size c d) (get_domain c d);; -let get_array_sort c t = (get_array_sort_domain c t, get_array_sort_range c t);; -let get_tuple_sort c ty = - (get_tuple_sort_mk_decl c ty, - Array.init (get_tuple_sort_num_fields c ty) (get_tuple_sort_field_decl c ty));; -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array -} -let get_datatype_sort c ty = - Array.init (get_datatype_sort_num_constructors c ty) - (fun idx_c -> - let constr = get_datatype_sort_constructor c ty idx_c in - let recog = get_datatype_sort_recognizer c ty idx_c in - let num_acc = get_domain_size c constr in - { constructor = constr; - recognizer = recog; - accessors = Array.init num_acc (get_datatype_sort_constructor_accessor c ty idx_c); - }) -let get_model_constants c m = - Array.init (get_model_num_constants c m) (get_model_constant c m);; -let get_model_func_entry c m i j = - (Array.init - (get_model_func_entry_num_args c m i j) - (get_model_func_entry_arg c m i j), - get_model_func_entry_value c m i j);; -let get_model_func_entries c m i = - Array.init (get_model_func_num_entries c m i) (get_model_func_entry c m i);; -let get_model_funcs c m = - Array.init (get_model_num_funcs c m) - (fun i->(get_model_func_decl c m i |> get_decl_name c, - get_model_func_entries c m i, - get_model_func_else c m i));; -let get_smtlib_formulas c = - Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c);; -let get_smtlib_assumptions c = - Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c);; -let get_smtlib_decls c = - Array.init (get_smtlib_num_decls c) (get_smtlib_decl c);; -let get_smtlib_parse_results c = - (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c);; -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = - (parse_smtlib_string c a1 a2 a3 a4 a5; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_string_formula");; -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = - (parse_smtlib_file c a1 a2 a3 a4 a5; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_file_formula");; -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = - (parse_smtlib_string c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = - (parse_smtlib_file c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; -(* Refinement: *) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string - | Symbol_unknown;; -let symbol_refine c s = - match get_symbol_kind c s with - | INT_SYMBOL -> Symbol_int (get_symbol_int c s) - | STRING_SYMBOL -> Symbol_string (get_symbol_string c s);; -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_real - | Sort_bv of int - | Sort_array of (sort * sort) - | Sort_datatype of datatype_constructor_refined array - | Sort_relation - | Sort_finite_domain - | Sort_unknown of symbol;; -let sort_refine c ty = - match get_sort_kind c ty with - | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c ty) - | BOOL_SORT -> Sort_bool - | INT_SORT -> Sort_int - | REAL_SORT -> Sort_real - | BV_SORT -> Sort_bv (get_bv_sort_size c ty) - | ARRAY_SORT -> Sort_array (get_array_sort_domain c ty, get_array_sort_range c ty) - | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c ty) - | RELATION_SORT -> Sort_relation - | FINITE_DOMAIN_SORT -> Sort_finite_domain - | UNKNOWN_SORT -> Sort_unknown (get_sort_name c ty);; -let get_pattern_terms c p = - Array.init (get_pattern_num_terms c p) (get_pattern c p) -type binder_type = | Forall | Exists -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string -type term_refined = - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol *sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort -let term_refine c t = - match get_ast_kind c t with - | NUMERAL_AST -> - let (is_small, n, d) = get_numeral_small c t in - if is_small then - Term_numeral(Numeral_small(n,d), get_sort c t) - else - Term_numeral(Numeral_large(get_numeral_string c t), get_sort c t) - | APP_AST -> - let t' = to_app c t in - let f = get_app_decl c t' in - let num_args = get_app_num_args c t' in - let args = Array.init num_args (get_app_arg c t') in - let k = get_decl_kind c f in - Term_app (k, f, args) - | QUANTIFIER_AST -> - let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in - let bound = Array.init nb - (fun i -> (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i)) in - let body = get_quantifier_body c t in - Term_quantifier(bt, w, pats, bound, body) - | VAR_AST -> - Term_var(get_index_value c t, get_sort c t) - | _ -> assert false -type theory_callbacks = - { - mutable delete_theory : unit -> unit; - mutable reduce_eq : ast -> ast -> ast option; - mutable reduce_app : func_decl -> ast array -> ast option; - mutable reduce_distinct : ast array -> ast option; - mutable final_check : unit -> bool; - mutable new_app : ast -> unit; - mutable new_elem : ast -> unit; - mutable init_search: unit -> unit; - mutable push: unit -> unit; - mutable pop: unit -> unit; - mutable restart : unit -> unit; - mutable reset: unit -> unit; - mutable new_eq : ast -> ast -> unit; - mutable new_diseq : ast -> ast -> unit; - mutable new_assignment: ast -> bool -> unit; - mutable new_relevant : ast -> unit; - } -let mk_theory_callbacks() = - { - delete_theory = (fun () -> ()); - reduce_eq = (fun _ _ -> None); - reduce_app = (fun _ _ -> None); - reduce_distinct = (fun _ -> None); - final_check = (fun _ -> true); - new_app = (fun _ -> ()); - new_elem = (fun _ -> ()); - init_search= (fun () -> ()); - push= (fun () -> ()); - pop= (fun () -> ()); - restart = (fun () -> ()); - reset= (fun () -> ()); - new_eq = (fun _ _ -> ()); - new_diseq = (fun _ _ -> ()); - new_assignment = (fun _ _ -> ()); - new_relevant = (fun _ -> ()); - } -external get_theory_callbacks : theory -> theory_callbacks = "get_theory_callbacks" -external mk_theory_register : context -> string -> theory_callbacks -> theory = "mk_theory_register" -external set_delete_callback_register : theory -> unit = "set_delete_callback_register" -external set_reduce_app_callback_register : theory -> unit = "set_reduce_app_callback_register" -external set_reduce_eq_callback_register : theory -> unit = "set_reduce_eq_callback_register" -external set_reduce_distinct_callback_register : theory -> unit = "set_reduce_distinct_callback_register" -external set_new_app_callback_register : theory -> unit = "set_new_app_callback_register" -external set_new_elem_callback_register : theory -> unit = "set_new_elem_callback_register" -external set_init_search_callback_register : theory -> unit = "set_init_search_callback_register" -external set_push_callback_register : theory -> unit = "set_push_callback_register" -external set_pop_callback_register : theory -> unit = "set_pop_callback_register" -external set_restart_callback_register : theory -> unit = "set_restart_callback_register" -external set_reset_callback_register : theory -> unit = "set_reset_callback_register" -external set_final_check_callback_register : theory -> unit = "set_final_check_callback_register" -external set_new_eq_callback_register : theory -> unit = "set_new_eq_callback_register" -external set_new_diseq_callback_register : theory -> unit = "set_new_diseq_callback_register" -external set_new_assignment_callback_register : theory -> unit = "set_new_assignment_callback_register" -external set_new_relevant_callback_register : theory -> unit = "set_new_relevant_callback_register" -let is_some opt = - match opt with - | Some v -> true - | None -> false -let get_some opt = - match opt with - | Some v -> v - | None -> failwith "None unexpected" -let apply_delete (th:theory_callbacks) = th.delete_theory () -let set_delete_callback th cb = - let cbs = get_theory_callbacks th in - cbs.delete_theory <- cb; - set_delete_callback_register th -let mk_theory context name = - Callback.register "is_some" is_some; - Callback.register "get_some" get_some; - Callback.register "apply_delete" apply_delete; - let cbs = mk_theory_callbacks() in - mk_theory_register context name cbs -let apply_reduce_app (th:theory_callbacks) f args = th.reduce_app f args -let set_reduce_app_callback th cb = - Callback.register "apply_reduce_app" apply_reduce_app; - let cbs = get_theory_callbacks th in - cbs.reduce_app <- cb; - set_reduce_app_callback_register th -let apply_reduce_eq (th:theory_callbacks) a b = th.reduce_eq a b -let set_reduce_eq_callback th cb = - Callback.register "apply_reduce_eq" apply_reduce_eq; - let cbs = get_theory_callbacks th in - cbs.reduce_eq <- cb; - set_reduce_eq_callback_register th -let apply_reduce_distinct (th:theory_callbacks) args = th.reduce_distinct args -let set_reduce_distinct_callback th cb = - Callback.register "apply_reduce_distinct" apply_reduce_distinct; - let cbs = get_theory_callbacks th in - cbs.reduce_distinct <- cb; - set_reduce_distinct_callback_register th -let apply_new_app (th:theory_callbacks) a = th.new_app a -let set_new_app_callback th cb = - Callback.register "apply_new_app" apply_new_app; - let cbs = get_theory_callbacks th in - cbs.new_app <- cb; - set_new_app_callback_register th -let apply_new_elem (th:theory_callbacks) a = th.new_elem a -let set_new_elem_callback th cb = - Callback.register "apply_new_elem" apply_new_elem; - let cbs = get_theory_callbacks th in - cbs.new_elem <- cb; - set_new_elem_callback_register th -let apply_init_search (th:theory_callbacks) = th.init_search() -let set_init_search_callback th cb = - Callback.register "apply_init_search" apply_init_search; - let cbs = get_theory_callbacks th in - cbs.init_search <- cb; - set_init_search_callback_register th -let apply_push (th:theory_callbacks) = th.push() -let set_push_callback th cb = - Callback.register "apply_push" apply_push; - let cbs = get_theory_callbacks th in - cbs.push <- cb; - set_push_callback_register th -let apply_pop (th:theory_callbacks) = th.pop() -let set_pop_callback th cb = - Callback.register "apply_pop" apply_pop; - let cbs = get_theory_callbacks th in - cbs.pop <- cb; - set_pop_callback_register th -let apply_restart (th:theory_callbacks) = th.restart() -let set_restart_callback th cb = - Callback.register "apply_restart" apply_restart; - let cbs = get_theory_callbacks th in - cbs.restart <- cb; - set_restart_callback_register th -let apply_reset (th:theory_callbacks) = th.reset() -let set_reset_callback th cb = - Callback.register "apply_reset" apply_reset; - let cbs = get_theory_callbacks th in - cbs.reset <- cb; - set_reset_callback_register th -let apply_final_check (th:theory_callbacks) = th.final_check() -let set_final_check_callback th cb = - Callback.register "apply_final_check" apply_final_check; - let cbs = get_theory_callbacks th in - cbs.final_check <- cb; - set_final_check_callback_register th -let apply_new_eq (th:theory_callbacks) a b = th.new_eq a b -let set_new_eq_callback th cb = - Callback.register "apply_new_eq" apply_new_eq; - let cbs = get_theory_callbacks th in - cbs.new_eq <- cb; - set_new_eq_callback_register th -let apply_new_diseq (th:theory_callbacks) a b = th.new_diseq a b -let set_new_diseq_callback th cb = - Callback.register "apply_new_diseq" apply_new_diseq; - let cbs = get_theory_callbacks th in - cbs.new_diseq <- cb; - set_new_diseq_callback_register th -let apply_new_assignment (th:theory_callbacks) a b = th.new_assignment a b -let set_new_assignment_callback th cb = - Callback.register "apply_new_assignment" apply_new_assignment; - let cbs = get_theory_callbacks th in - cbs.new_assignment <- cb; - set_new_assignment_callback_register th -let apply_new_relevant (th:theory_callbacks) a = th.new_relevant a -let set_new_relevant_callback th cb = - Callback.register "apply_new_relevant" apply_new_relevant; - let cbs = get_theory_callbacks th in - cbs.new_relevant <- cb; - set_new_relevant_callback_register th - - -end - -======= (* Copyright (C) 2012 Microsoft Corporation Author: CM Wintersteiger (cwinter) 2012-12-17 @@ -3410,48 +23,42 @@ end class context settings = object (self) inherit idisposable - val mutable m_n_ctx : Z3native.z3_context option = None + + val mutable m_n_ctx : Z3native.z3_context = + let cfg = mk_config() in + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = mk_context_rc cfg in + del_config(cfg) ; + v + val mutable m_refCount : int = 0 - initializer - let cfg = mk_config() in - (match settings with - | Some(x) -> - let f e = (set_param_value cfg (fst e) (snd e)) in - (List.iter f x) - | _ -> () - ) ; - m_n_ctx <- Some (mk_context_rc cfg) ; - del_config(cfg) ; - Gc.finalise (fun self -> self#dispose) self + initializer Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with - | Some(x) -> (del_context x) - | None -> () + (del_context m_n_ctx) ) else ( (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 + method get_native = m_n_ctx end class virtual z3object ctx_init obj_init = object (self) inherit idisposable - val mutable m_ctx : context option = ctx_init + val mutable m_ctx : context = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init initializer (match m_n_obj with | Some (x) -> self#incref x; - (match m_ctx with - | Some(x) -> x#add_one_ctx_obj - | None -> () - ) + m_ctx#add_one_ctx_obj | None -> () ); Gc.finalise (fun self -> self#dispose) self @@ -3465,15 +72,9 @@ object (self) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with - | Some (x) -> self#decref x; m_n_obj <- None + | Some (x) -> self#decref x; m_n_obj <- None; m_ctx#sub_one_ctx_obj | None -> () ); - (match m_ctx with - | Some (x) -> x#sub_one_ctx_obj - | None -> () - ); - m_ctx <- None - method get_native_object = m_n_obj @@ -3489,6 +90,7 @@ object (self) m_n_obj <- x method get_context = m_ctx + method get_native_context = m_ctx#get_native (* method array_to_native a = @@ -3500,11 +102,59 @@ object (self) | Some(x) -> (Array.length x) | None -> 0 *) +end + +class symbol ctx_init obj_init = +object (self) + inherit z3object ctx_init obj_init + + method incref o = () + method decref o = () + + method kind = match m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") + + method is_int_symbol = match m_n_obj with + | Some(x) -> self#kind == INT_SYMBOL + | _ -> false + + method is_string_symbol = match m_n_obj with + | Some(x) -> self#kind == STRING_SYMBOL + | _ -> false + + method to_string = match m_n_obj with + | Some(x) -> + ( + match self#kind with + | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) + ) + | None -> "" + + method create ctx obj = + match obj with + | Some(x) -> ( + match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with + | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) + | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) + ) + | None -> raise (Exception "Can't create null objects") end -<<<<<<< HEAD end ->>>>>>> More new ML API. -======= ->>>>>>> More ML API + +and intsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init + + method get_int = match m_n_obj with + | Some(x) -> (get_symbol_int m_ctx#get_native x) + | None -> 0 +end + +and stringsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end From b193b827ed05770ee5171093a75a1a1cde8b05bc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 04:10:38 +0000 Subject: [PATCH 260/646] ML API bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 20 +++++-- scripts/update_api.py | 21 +++++-- src/api/ml/z3.ml | 121 ++++++++++++++++++++++---------------- 3 files changed, 101 insertions(+), 61 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 9c704e4d0..c79b3cdaa 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,11 +4,19 @@ *) open Z3 - -let _ = ignore(Log.open_ "z3.log") ; - let cfg = Some [("model", "true"); ("proof", "false")] in - let ctx = (new context cfg) in - Printf.printf "Disposing...\n"; - ctx#dispose ; + +exception ExampleException of string + +let _ = + if not (Log.open_ "z3.log") then + raise (ExampleException "Log couldn't be opened.") + else + ( + Printf.printf "Running Z3 version %s\n" Version.to_string ; + let cfg = [("model", "true"); ("proof", "false")] in + let ctx = (new context cfg) in + Printf.printf "Disposing...\n"; + ctx#dispose (* can do, but we'd rather let it go out of scope *) ; + ); Printf.printf "Exiting.\n"; ;; diff --git a/scripts/update_api.py b/scripts/update_api.py index 9eb7d1405..25adce2af 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -325,7 +325,9 @@ def param2pystr(p): def param2ml(p): k = param_kind(p) if k == OUT: - if param_type(p) == STRING: + if param_type(p) == INT or param_type(p) == UINT or param_type(p) == INT64 or param_type(p) == UINT64: + return "int" + elif param_type(p) == STRING: return "string" else: return "ptr" @@ -1124,9 +1126,16 @@ def mk_ml(): ml_native.write('%s -> ' % param2ml(p)) if len(op) > 0: ml_native.write('(') - ml_native.write('%s' % type2ml(result)) + first = True + if result != VOID or len(op) == 0: + ml_native.write('%s' % type2ml(result)) + first = False for p in op: - ml_native.write(' * %s' % param2ml(p)) + if first: + first = False + else: + ml_native.write(' * ') + ml_native.write('%s' % param2ml(p)) if len(op) > 0: ml_native.write(')') ml_native.write('\n') @@ -1153,11 +1162,13 @@ def mk_ml(): i = i + 1 ml_native.write(' = \n') ml_native.write(' ') - if result == VOID: + if result == VOID and len(op) == 0: ml_native.write('let _ = ') else: ml_native.write('let res = ') ml_native.write('(ML2C.n_%s' % (ml_method_name(name))) + if len(ip) == 0: + ml_native.write(' ()') first = True i = 0; for p in params: @@ -1170,7 +1181,7 @@ def mk_ml(): ml_native.write(' if err <> OK then\n') ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') - if result == VOID: + if result == VOID and len(op) == 0: ml_native.write(' ()\n') else: ml_native.write(' res\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 55ffd91e8..31bb7e5fc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -9,12 +9,27 @@ open Z3native module Log = struct let m_is_open = false - (* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) + (* CMW: "open" seems to be an invalid function name*) + let open_ fn = let rv = (open_log fn) in + Printf.printf "ol returned %d\n" rv ; + ((int2lbool rv) == L_TRUE) + let close = close_log + let append s = append_log s end - + +module Version = +struct + let major = let (x, _, _, _) = get_version in x + let minor = let (_, x, _, _) = get_version in x + let build = let (_, _, x, _) = get_version in x + let revision = let (_, _, _, x) = get_version in x + let to_string = + string_of_int major ^ "." ^ + string_of_int minor ^ "." ^ + string_of_int build ^ "." ^ + string_of_int revision ^ "." +end + class virtual idisposable = object method virtual dispose : unit @@ -25,7 +40,7 @@ object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config() in + let cfg = mk_config in let f e = (set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = mk_context_rc cfg in @@ -34,14 +49,15 @@ object (self) val mutable m_refCount : int = 0 - initializer Gc.finalise (fun self -> self#dispose) self + initializer + Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing %d \n" (Oo.id self) ; (del_context m_n_ctx) ) else ( - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 @@ -66,9 +82,9 @@ object (self) method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) + (* + Disposes of the underlying native Z3 object. + *) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with @@ -92,16 +108,17 @@ object (self) method get_context = m_ctx method get_native_context = m_ctx#get_native - (* - method array_to_native a = +(* + method array_to_native a = let f e = e#get_native_object in (Array.map f a) - method array_length a = + method array_length a = match a with - | Some(x) -> (Array.length x) - | None -> 0 - *) + | Some(x) -> (Array.length x) + | None -> 0 +*) + end class symbol ctx_init obj_init = @@ -110,51 +127,55 @@ object (self) method incref o = () method decref o = () +end - method kind = match m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) - | _ -> raise (Exception "Underlying object lost") +class int_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_int_symbol = match m_n_obj with - | Some(x) -> self#kind == INT_SYMBOL - | _ -> false +class string_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_string_symbol = match m_n_obj with - | Some(x) -> self#kind == STRING_SYMBOL - | _ -> false - - method to_string = match m_n_obj with - | Some(x) -> - ( - match self#kind with - | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) - ) - | None -> "" - - method create ctx obj = +module Symbol = +struct + let create ctx obj = match obj with | Some(x) -> ( match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) - | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) + | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) + | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) ) | None -> raise (Exception "Can't create null objects") -end + let kind o = match o#m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") -end + let is_int_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == INT_SYMBOL + | _ -> false -and intsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let is_string_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == STRING_SYMBOL + | _ -> false - method get_int = match m_n_obj with - | Some(x) -> (get_symbol_int m_ctx#get_native x) + let get_int o = match o#m_n_obj with + | Some(x) -> (get_symbol_int o#get_native_context x) | None -> 0 -end -and stringsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let get_string o = match o#m_n_obj with + | Some(x) -> (get_symbol_string o#get_native_context x) + | None -> "" + + let to_string o = match o#m_n_obj with + | Some(x) -> + ( + match (kind o) with + | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) + ) + | None -> "" end From e87feb8e456e91d05a14dee17d62f9cf1c531e27 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 04:12:41 +0000 Subject: [PATCH 261/646] added temporary Makefile for ML annotations. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/api/ml/Makefile diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile new file mode 100644 index 000000000..f97a2dc30 --- /dev/null +++ b/src/api/ml/Makefile @@ -0,0 +1,6 @@ +# This is a temporary support file for emacs annotations. +# It does not compile the Z3 ML API; this will be built +# in the top-level build directory. + +all: + ocamlbuild -cflag -annot z3.cmxa \ No newline at end of file From 518da6b6e2b70ec17bda199f589d316605857fc1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 19:08:23 +0000 Subject: [PATCH 262/646] move old files Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/{ => old}/README-linux | 0 src/api/ml/{ => old}/README-osx | 0 src/api/ml/{ => old}/README-test-linux | 0 src/api/ml/{ => old}/README-test-osx | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/api/ml/{ => old}/README-linux (100%) rename src/api/ml/{ => old}/README-osx (100%) rename src/api/ml/{ => old}/README-test-linux (100%) rename src/api/ml/{ => old}/README-test-osx (100%) diff --git a/src/api/ml/README-linux b/src/api/ml/old/README-linux similarity index 100% rename from src/api/ml/README-linux rename to src/api/ml/old/README-linux diff --git a/src/api/ml/README-osx b/src/api/ml/old/README-osx similarity index 100% rename from src/api/ml/README-osx rename to src/api/ml/old/README-osx diff --git a/src/api/ml/README-test-linux b/src/api/ml/old/README-test-linux similarity index 100% rename from src/api/ml/README-test-linux rename to src/api/ml/old/README-test-linux diff --git a/src/api/ml/README-test-osx b/src/api/ml/old/README-test-osx similarity index 100% rename from src/api/ml/README-test-osx rename to src/api/ml/old/README-test-osx From 8e83f8d034949f3f4918267b014b647a3458d9c8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 20:51:18 +0000 Subject: [PATCH 263/646] ML build system checks Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 62 +++++++++++++++++++++++++++++++++++++++++++--- src/api/ml/z3.ml | 8 +++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index da7d22d54..8848d4ce4 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -32,6 +32,10 @@ CXXFLAGS=getenv("CXXFLAGS", "") EXAMP_DEBUG_FLAG='' LDFLAGS=getenv("LDFLAGS", "") JNI_HOME=getenv("JNI_HOME", None) +OCAMLC=getenv("OCAMLC", "ocamlc") +OCAMLOPT=getenv("OCAMLC", "ocamlopt") +OCAMLBUILD=getenv("OCAMLBUILD", "ocamlbuild") +OCAML_LIB=getenv("OCAML_LIB", None) CXX_COMPILERS=['g++', 'clang++'] C_COMPILERS=['gcc', 'clang'] @@ -335,6 +339,43 @@ def check_java(): if JNI_HOME == None: raise MKException("Failed to detect jni.h. Possible solution: set JNI_HOME with the path to JDK.") +def check_ml(): + t = TempFile('hello.ml') + t.add('print_string "Hello world!\n";;') + t.commit() + if is_verbose(): + print "Testing %s..." % OCAMLC + r = exec_cmd([OCAMLC, 'hello.ml']) + if r != 0: + raise MKException('Failed testing ocamlc compiler. Set environment variable OCAMLC with the path to the Ocaml compiler') + if is_verbose(): + print "Testing %s..." % OCAMLOPT + r = exec_cmd([OCAMLC, 'hello.ml']) + if r != 0: + raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') + r = exec_cmd([OCAMLBUILD]) + if r != 0: + raise MKException('Failed testing ocamlbuild. Set environment variable OCAMLBUILD with the path to ocamlbuild') + find_ml_lib() + +def find_ml_lib(): + global OCAML_LIB + if is_verbose(): + print "Finding OCAML_LIB..." + t = TempFile('output') + null = open(os.devnull, 'wb') + try: + subprocess.call([OCAMLC, '-where'], stdout=t.fname, stderr=null) + t.commit() + except: + raise MKException('Failed to find Ocaml library; please set OCAML_LIB') + t = open('output', 'r') + for line in t: + OCAML_LIB = line[:-1] + if is_verbose(): + print 'OCAML_LIB=%s' % OCAML_LIB + return + def is64(): return sys.maxsize >= 2**32 @@ -474,6 +515,10 @@ def display_help(exit_code): print(" CXXFLAGS C++ compiler flags") print(" JDK_HOME JDK installation directory (only relevant if -j or --java option is provided)") print(" JNI_HOME JNI bindings directory (only relevant if -j or --java option is provided)") + print(" OCAMLC Ocaml byte-code compiler (only relevant with --ml)") + print(" OCAMLOPT Ocaml native compiler (only relevant with --ml)") + print(" OCAMLBUILD Ocaml build system (only relevant with --ml)") + print(" OCAML_LIB Ocaml library directory (only relevant with --ml)") exit(exit_code) # Parse configuration option for mk_make script @@ -1300,7 +1345,7 @@ class MLComponent(Component): for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) @@ -1438,7 +1483,7 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example($EXE_EXT): z3.cmxa ') + out.write('ml_example($EXE_EXT): z3.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') @@ -1596,6 +1641,11 @@ def mk_config(): if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) + if is_ml_enabled(): + print('Ocaml Compiler: %s' % OCAMLC) + print('Ocaml Native: %s' % OCAMLOPT) + print('Ocamlbuild: %s' % OCAMLBUILD) + print('Ocaml Library: %s' % OCAML_LIB) else: global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG OS_DEFINES = "" @@ -1715,7 +1765,12 @@ def mk_config(): if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) - + if is_ml_enabled(): + print('Ocaml Compiler: %s' % OCAMLC) + print('Ocaml Native: %s' % OCAMLOPT) + print('Ocamlbuild: %s' % OCAMLBUILD) + print('Ocaml Library: %s' % OCAML_LIB) + def mk_install(out): out.write('install: ') for c in get_components(): @@ -2280,6 +2335,7 @@ def mk_bindings(api_files): check_java() mk_z3consts_java(api_files) if is_ml_enabled(): + check_ml() mk_z3consts_ml(api_files) _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3py_to_build() diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 31bb7e5fc..d901d09ef 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -10,11 +10,9 @@ module Log = struct let m_is_open = false (* CMW: "open" seems to be an invalid function name*) - let open_ fn = let rv = (open_log fn) in - Printf.printf "ol returned %d\n" rv ; - ((int2lbool rv) == L_TRUE) - let close = close_log - let append s = append_log s + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) end module Version = From 7efe7a2c16ad26a7021e7b0619a4450be2f8e6c7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Dec 2012 03:02:12 +0000 Subject: [PATCH 264/646] ML native layer bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/Makefile | 7 ++ scripts/mk_util.py | 2 +- scripts/update_api.py | 165 +++++++++++++++++++++++++----------------- src/api/ml/z3.ml | 11 +-- 4 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 examples/ml/Makefile diff --git a/examples/ml/Makefile b/examples/ml/Makefile new file mode 100644 index 000000000..4b3e7c4d2 --- /dev/null +++ b/examples/ml/Makefile @@ -0,0 +1,7 @@ +# This is a temporary support file for emacs annotations. +# It does not compile the Z3 ML example; this will be built +# in the top-level build directory. + +all: + OCAML_COMPAT=c ocamlc -g -annot -o ml_example.byte -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cma ml_example.ml + ocamlopt -g -annot -o ml_example -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8848d4ce4..b6cf4dedc 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2699,7 +2699,7 @@ def mk_z3consts_ml(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s/enumerations.ml'" % ('%s' % gendir) + print "Generated '%s/z3enums.ml'" % ('%s' % gendir) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 25adce2af..d0ef2ec86 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1,3 +1,4 @@ + ############################################ # Copyright (c) 2012 Microsoft Corporation # @@ -1097,6 +1098,45 @@ def is_array_param(p): else: return False +def arrayparams(params): + op = [] + for param in params: + if is_array_param(param): + op.append(param) + return op + + +def ml_unwrap(t): + if t == STRING: + return 'String_val' + elif t == BOOL or t == INT or PRINT_MODE or ERROR_CODE: + return 'Int_val' + elif t == UINT: + return 'Unsigned_int_val' + elif t == INT64: + return 'Long_val' + elif t == UINT64: + return 'Unsigned_long_val' + elif t == DOUBLE: + return 'Double_val' + else: + return 'Data_custom_val' + +def ml_set_wrap(t, d, n): + if t == VOID: + return d + ' = Val_unit;' + elif t == BOOL or t == INT or t == UINT or PRINT_MODE or ERROR_CODE: + return d + ' = Val_int(' + n + ');' + elif t == INT64 or t == UINT64: + return d + ' = Val_long(' + n + ');' + elif t == DOUBLE: + return 'Store_double_val(' + d + ', ' + n + ');' + elif t == STRING: + return d + ' = caml_copy_string((const char*) ' + n + ');' + else: + ts = type2str(t) + return d + ' = caml_alloc_custom(0, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' + def mk_ml(): global Type2Str if not is_ml_enabled(): @@ -1242,15 +1282,12 @@ def mk_ml(): for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) + ap = arrayparams(params) ret_size = len(op) if result != VOID: ret_size = ret_size + 1 # Setup frame - n_locals = 0 - for p in params: - if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): - n_locals = n_locals + 1 ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) first = True i = 0 @@ -1276,46 +1313,50 @@ def mk_ml(): i = i + 1 ml_wrapper.write(');\n') i = 0 - first = True - if result != VOID: - n_locals = n_locals + 1 - if ret_size > 1: - n_locals = n_locals + 1 - if n_locals > 0: - ml_wrapper.write(' CAMLlocal%s(' % (n_locals)) - if ret_size > 1: - if result != VOID: - ml_wrapper.write('result, ') - ml_wrapper.write('result_tuple') - first = False - elif result != VOID: - ml_wrapper.write('result') - first = False + if len(op) + len(ap) == 0: + ml_wrapper.write(' CAMLlocal1(result);\n') + else: + c = 0 for p in params: - if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('_a%s' % i) + if is_out_param(p) or is_array_param(p): + c = c + 1 + ml_wrapper.write(' CAMLlocal%s(result, res_val' % (c+2)) + for p in params: + if is_out_param(p) or is_array_param(p): + ml_wrapper.write(', _a%s_val' % i) i = i + 1 ml_wrapper.write(');\n') # preprocess arrays, strings, in/out arguments i = 0 for param in params: - if param_kind(param) == OUT_ARRAY: - ml_wrapper.write(' _a%s = (long) malloc(sizeof(%s) * ((long)a%s));\n' % (i, - type2str(param_type(param)), - param_array_capacity_pos(param))) - elif param_kind(param) == IN and param_type(param) == STRING: - ml_wrapper.write(' _a%s = (value) String_val(a%s);\n' % (i, i)) + k = param_kind(param) + if k == OUT_ARRAY: + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * (_a%s));\n' % ( + type2str(param_type(param)), + i, + type2str(param_type(param)), + type2str(param_type(param)), + param_array_capacity_pos(param))) + elif k == IN_ARRAY or k == INOUT_ARRAY: + t = param_type(param) + ts = type2str(t) + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) + ml_wrapper.write(' for (unsigned i = 0; i < a%s; i++) _a%s[i] = (%s) %s(Field(a%s, i));\n' % (param_array_capacity_pos(param), i, ts, ml_unwrap(t), i)) + elif k == IN: + t = param_type(param) + ml_wrapper.write(' %s _a%s = (%s) %s(a%s);\n' % (type2str(t), i, type2str(t), ml_unwrap(t), i)) + elif k == OUT: + ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + elif k == INOUT: + ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) + i = i + 1 # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('result = (value) ') + ml_wrapper.write('%s z3_result = ' % type2str(result)) ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1326,58 +1367,50 @@ def mk_ml(): ml_wrapper.write(', ') k = param_kind(param) if k == OUT or k == INOUT: - ml_wrapper.write('(%s)&_a%s' % (param2str(param), i)) - elif k == INOUT_ARRAY or k == IN_ARRAY: - ml_wrapper.write('(%s*)a%s' % (type2str(param_type(param)), i)) - elif k == OUT_ARRAY: - ml_wrapper.write('(%s*)_a%s' % (type2str(param_type(param)), i)) - elif k == IN and param_type(param) == STRING: - ml_wrapper.write('(Z3_string) _a%s' % i) + ml_wrapper.write('&_a%s' % i) else: - ml_wrapper.write('(%s)a%i' % (param2str(param), i)) + ml_wrapper.write('_a%i' % i) i = i + 1 ml_wrapper.write(');\n') - # return tuples + # convert output params if len(op) > 0: - ml_wrapper.write(' result_tuple = caml_alloc(%s, 0);\n' % ret_size) + if result != VOID: + ml_wrapper.write(' %s\n' % ml_set_wrap(result, "res_val", "z3_result")) + i = 0; + for p in params: + if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) + ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) { value t; %s Store_field(_a%s, i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[i]'), i)) + elif is_out_param(p): + ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) + i = i + 1 + + # return tuples + if len(op) == 0: + ml_wrapper.write(' %s\n' % ml_set_wrap(result, "result", "z3_result")) + else: + ml_wrapper.write(' result = caml_alloc(%s, 0);\n' % ret_size) i = j = 0 if result != VOID: - if result == STRING: - ml_wrapper.write(' Store_field(result_tuple, 0, caml_copy_string(result));\n') - else: - ml_wrapper.write(' Store_field(result_tuple, 0, result);\n') + ml_wrapper.write(' Store_field(result, 0, res_val);\n') j = j + 1 for p in params: - if param_kind(p) == OUT_ARRAY or param_kind(p) == OUT: - ml_wrapper.write(' Store_field(result_tuple, %s, _a%s);\n' % (j, i)) - j = j + 1; - elif is_out_param(p): - if param_type(p) == STRING: - ml_wrapper.write(' Store_field(result_tuple, %s, caml_copy_string((const char *)_a%s));\n' % (j, i)) - else: - ml_wrapper.write(' Store_field(result_tuple, %s, a%s);\n' % (j, i)) + if is_out_param(p): + ml_wrapper.write(' Store_field(result, %s, _a%s_val);\n' % (j, i)) j = j + 1; i = i + 1 # local array cleanup i = 0 for p in params: - if param_kind(p) == OUT_ARRAY: - ml_wrapper.write(' free((long*)_a%s);\n' % i) + k = param_kind(p) + if k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + ml_wrapper.write(' free(_a%s);\n' % i) i = i + 1 # return - if len(op) > 0: - ml_wrapper.write(' CAMLreturn(result_tuple);\n') - else: - if result == STRING: - ml_wrapper.write(' CAMLreturn(caml_copy_string((const char*) result));\n') - elif result == VOID: - ml_wrapper.write(' CAMLreturn(Val_unit);\n') - elif result != VOID: - ml_wrapper.write(' CAMLreturn(result);\n') - + ml_wrapper.write(' CAMLreturn(result);\n') ml_wrapper.write('}\n\n') if len(ip) > 5: ml_wrapper.write('CAMLprim value n_%s_bytecode(value * argv, int argn) {\n' % ml_method_name(name)) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index d901d09ef..cc1429f14 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -22,10 +22,11 @@ struct let build = let (_, _, x, _) = get_version in x let revision = let (_, _, _, x) = get_version in x let to_string = - string_of_int major ^ "." ^ - string_of_int minor ^ "." ^ - string_of_int build ^ "." ^ - string_of_int revision ^ "." + let (mj, mn, bld, rev) = get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." end class virtual idisposable = @@ -52,7 +53,7 @@ object (self) method dispose : unit = if m_refCount == 0 then ( - Printf.printf "Disposing %d \n" (Oo.id self) ; + Printf.printf "Disposing context %d \n" (Oo.id self) ; (del_context m_n_ctx) ) else ( (* re-queue for finalization? *) From 794823ba6d149561eec5c168cc8e7cd9d9a1387c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Dec 2012 07:18:46 +0000 Subject: [PATCH 265/646] More ML API: Fixes in native layer. Added symbols. Prepared code for automatic documentation. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 5 ++ scripts/mk_util.py | 4 + scripts/update_api.py | 37 ++++++--- src/api/ml/z3.ml | 168 ++++++++++++++++++++++++++------------ 4 files changed, 151 insertions(+), 63 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index c79b3cdaa..7046a92b0 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,6 +4,7 @@ *) open Z3 +open Z3.Context exception ExampleException of string @@ -15,6 +16,10 @@ let _ = Printf.printf "Running Z3 version %s\n" Version.to_string ; let cfg = [("model", "true"); ("proof", "false")] in let ctx = (new context cfg) in + let is = (mk_symbol_int ctx 42) in + let ss = (mk_symbol_string ctx "mySymbol") in + Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); + Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); Printf.printf "Disposing...\n"; ctx#dispose (* can do, but we'd rather let it go out of scope *) ; ); diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b6cf4dedc..68493b7b6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2628,6 +2628,7 @@ def mk_z3consts_ml(api_files): efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') + efile.write('(** The enumeration types of Z3. *)\n\n') for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2673,15 +2674,18 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: + efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ for k, i in decls.iteritems(): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') + efile.write('(** Convert %s to int*)\n' % name[3:]) efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') + efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): diff --git a/scripts/update_api.py b/scripts/update_api.py index d0ef2ec86..c8cd05c7e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1106,26 +1106,26 @@ def arrayparams(params): return op -def ml_unwrap(t): +def ml_unwrap(t, ts, s): if t == STRING: - return 'String_val' - elif t == BOOL or t == INT or PRINT_MODE or ERROR_CODE: - return 'Int_val' + return '(' + ts + ') String_val(' + s + ')' + elif t == BOOL or t == INT or t == PRINT_MODE or t == ERROR_CODE: + return '(' + ts + ') Int_val(' + s + ')' elif t == UINT: - return 'Unsigned_int_val' + return '(' + ts + ') Unsigned_int_val(' + s + ')' elif t == INT64: - return 'Long_val' + return '(' + ts + ') Long_val(' + s + ')' elif t == UINT64: - return 'Unsigned_long_val' + return '(' + ts + ') Unsigned_long_val(' + s + ')' elif t == DOUBLE: - return 'Double_val' + return '(' + ts + ') Double_val(' + s + ')' else: - return 'Data_custom_val' + return '* (' + ts + '*) Data_custom_val(' + s + ')' def ml_set_wrap(t, d, n): if t == VOID: return d + ' = Val_unit;' - elif t == BOOL or t == INT or t == UINT or PRINT_MODE or ERROR_CODE: + elif t == BOOL or t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: return d + ' = Val_int(' + n + ');' elif t == INT64 or t == UINT64: return d + ' = Val_long(' + n + ');' @@ -1135,7 +1135,7 @@ def ml_set_wrap(t, d, n): return d + ' = caml_copy_string((const char*) ' + n + ');' else: ts = type2str(t) - return d + ' = caml_alloc_custom(0, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' + return d + ' = caml_alloc_custom(&default_custom_ops, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' def mk_ml(): global Type2Str @@ -1146,7 +1146,9 @@ def mk_ml(): ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') + ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_native.write('open Z3enums\n\n') + ml_native.write('(**/**)\n') ml_native.write('type ptr\n') ml_native.write('and z3_symbol = ptr\n') for k, v in Type2Str.iteritems(): @@ -1226,6 +1228,7 @@ def mk_ml(): else: ml_native.write(' res\n') ml_native.write('\n') + ml_native.write('(**/**)\n') # C interface ml_wrapper = open(ml_wrapperf, 'w') @@ -1276,6 +1279,14 @@ def mk_ml(): ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') ml_wrapper.write('\n\n') + ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') + ml_wrapper.write(' identifier: "default handling",\n') + ml_wrapper.write(' finalize: custom_finalize_default,\n') + ml_wrapper.write(' compare: custom_compare_default,\n') + ml_wrapper.write(' hash: custom_hash_default,\n') + ml_wrapper.write(' serialize: custom_serialize_default,\n') + ml_wrapper.write(' deserialize: custom_deserialize_default\n') + ml_wrapper.write('};\n\n') ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') @@ -1342,10 +1353,10 @@ def mk_ml(): t = param_type(param) ts = type2str(t) ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) - ml_wrapper.write(' for (unsigned i = 0; i < a%s; i++) _a%s[i] = (%s) %s(Field(a%s, i));\n' % (param_array_capacity_pos(param), i, ts, ml_unwrap(t), i)) + ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) _a%s[i] = %s;\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', i)'))) elif k == IN: t = param_type(param) - ml_wrapper.write(' %s _a%s = (%s) %s(a%s);\n' % (type2str(t), i, type2str(t), ml_unwrap(t), i)) + ml_wrapper.write(' %s _a%s = %s;\n' % (type2str(t), i, ml_unwrap(t, type2str(t), 'a' + str(i)))) elif k == OUT: ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) elif k == INOUT: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index cc1429f14..321b17c82 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,33 +1,17 @@ -(* +(** + The Z3 ML/Ocaml Interface. + Copyright (C) 2012 Microsoft Corporation - Author: CM Wintersteiger (cwinter) 2012-12-17 + @author CM Wintersteiger (cwinter) 2012-12-17 *) open Z3enums open Z3native -module Log = -struct - let m_is_open = false - (* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) -end +(**/**) -module Version = -struct - let major = let (x, _, _, _) = get_version in x - let minor = let (_, x, _, _) = get_version in x - let build = let (_, _, x, _) = get_version in x - let revision = let (_, _, _, x) = get_version in x - let to_string = - let (mj, mn, bld, rev) = get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end +(* Object definitions. These are internal and should be interacted + with only via the corresponding functions from modules. *) class virtual idisposable = object @@ -61,7 +45,7 @@ object (self) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 - method get_native = m_n_ctx + method gno = m_n_ctx end class virtual z3object ctx_init obj_init = @@ -91,9 +75,9 @@ object (self) | None -> () ); - method get_native_object = m_n_obj + method gno = m_n_obj - method set_native_object x = + method sno x = (match x with | Some(x) -> self#incref x | None -> () @@ -105,11 +89,11 @@ object (self) m_n_obj <- x method get_context = m_ctx - method get_native_context = m_ctx#get_native + method gnc = m_ctx#gno (* method array_to_native a = - let f e = e#get_native_object in + let f e = e#gno in (Array.map f a) method array_length a = @@ -120,61 +104,145 @@ object (self) end -class symbol ctx_init obj_init = +class symbol ctx obj = object (self) - inherit z3object ctx_init obj_init + inherit z3object ctx obj method incref o = () method decref o = () end -class int_symbol ctx_init obj_init = +class int_symbol ctx = object(self) - inherit symbol ctx_init obj_init + inherit symbol ctx None + method cnstr_obj obj = (self#sno obj) ; self + method cnstr_int i = (self#sno (Some (mk_int_symbol ctx#gno i))) ; self end -class string_symbol ctx_init obj_init = +class string_symbol ctx = object(self) - inherit symbol ctx_init obj_init + inherit symbol ctx None + method cnstr_obj obj = (self#sno obj) ; self + method cnstr_string name = (self#sno (Some (mk_string_symbol ctx#gno name))) ; self end +(**/**) + +(** Interaction logging for Z3. + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log = +struct + (** Open an interaction log file. + @param filename the name of the file to open. + @return True if opening the log file succeeds, false otherwise. + *) + (* CMW: "open" seems to be a reserved keyword? *) + let open_ filename = ((int2lbool (open_log filename)) == L_TRUE) + + (** Closes the interaction log. *) + let close = close_log + + (** Appends a user-provided string to the interaction log. + @param s the string to append*) + let append s = append_log s +end + +(** Version information. *) +module Version = +struct + (** The major version. *) + let major = let (x, _, _, _) = get_version in x + + (** The minor version. *) + let minor = let (_, x, _, _) = get_version in x + + (** The build version. *) + let build = let (_, _, x, _) = get_version in x + + (** The revision. *) + let revision = let (_, _, _, x) = get_version in x + + (** A string representation of the version information. *) + let to_string = + let (mj, mn, bld, rev) = get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + +(** Symbols are used to name several term and type constructors. *) module Symbol = struct +(**/**) let create ctx obj = match obj with | Some(x) -> ( - match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) - | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) + match (int2symbol_kind (get_symbol_kind ctx#gno x)) with + | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj obj) :> symbol) + | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj obj) :> symbol) ) | None -> raise (Exception "Can't create null objects") +(**/**) - let kind o = match o#m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) + (** The kind of the symbol (int or string) *) + let kind (o : symbol) = match o#gno with + | Some(x) -> (int2symbol_kind (get_symbol_kind o#gnc x)) | _ -> raise (Exception "Underlying object lost") - let is_int_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == INT_SYMBOL + (** Indicates whether the symbol is of Int kind *) + let is_int_symbol (o : symbol) = match o#gno with + | Some(x) -> (kind o) == INT_SYMBOL | _ -> false - let is_string_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == STRING_SYMBOL + (** Indicates whether the symbol is of string kind. *) + let is_string_symbol (o : symbol) = match o#gno with + | Some(x) -> (kind o) == STRING_SYMBOL | _ -> false - let get_int o = match o#m_n_obj with - | Some(x) -> (get_symbol_int o#get_native_context x) + (** The int value of the symbol. *) + let get_int (o : int_symbol) = match o#gno with + | Some(x) -> (get_symbol_int o#gnc x) | None -> 0 - let get_string o = match o#m_n_obj with - | Some(x) -> (get_symbol_string o#get_native_context x) + (** The string value of the symbol. *) + let get_string (o : string_symbol) = match o#gno with + | Some(x) -> (get_symbol_string o#gnc x) | None -> "" - let to_string o = match o#m_n_obj with + (** A string representation of the symbol. *) + let to_string (o : symbol) = match o#gno with | Some(x) -> ( match (kind o) with - | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) + | INT_SYMBOL -> (string_of_int (get_symbol_int o#gnc x)) + | STRING_SYMBOL -> (get_symbol_string o#gnc x) ) | None -> "" end + +(** The main interaction with Z3 happens via the Context. *) +module Context = +struct + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_symbol_int ctx i = + (new int_symbol ctx)#cnstr_int i + + (** Creates a new symbol using a string. *) + let mk_symbol_string ctx s = + (new string_symbol ctx)#cnstr_string s + + (** + Create an array of symbols. + *) + let mk_symbols ctx names = + let f elem = mk_symbol_string ctx elem in + (Array.map f names) + +end From fc227e3c9613cb573a8048c68df0d70742c25dea Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 00:50:32 +0000 Subject: [PATCH 266/646] .NET API documentation bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Expr.cs | 2 +- src/api/dotnet/Params.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index f4a63a61b..53bf4d4f0 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -1311,7 +1311,7 @@ namespace Microsoft.Z3 #region Relational Terms /// - /// Indicates whether the term is of an array sort. + /// Indicates whether the term is of relation sort. /// public bool IsRelation { diff --git a/src/api/dotnet/Params.cs b/src/api/dotnet/Params.cs index c33728491..9a814b2ec 100644 --- a/src/api/dotnet/Params.cs +++ b/src/api/dotnet/Params.cs @@ -23,7 +23,7 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { /// - /// A ParameterSet represents a configuration in the form of Symbol/value pairs. + /// A Params objects represents a configuration in the form of Symbol/value pairs. /// [ContractVerification(true)] public class Params : Z3Object From dab162886e8036d59b5a853f99c8adc5d7ea0074 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 00:51:07 +0000 Subject: [PATCH 267/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 6 +- src/api/ml/z3.ml | 5746 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 5659 insertions(+), 93 deletions(-) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index f97a2dc30..4d4a6c08f 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -3,4 +3,8 @@ # in the top-level build directory. all: - ocamlbuild -cflag -annot z3.cmxa \ No newline at end of file + ocamlbuild -cflag -annot z3.cmxa + +doc: *.ml + mkdir -p doc + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml *.ml -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 321b17c82..2100f371e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -6,7 +6,6 @@ *) open Z3enums -open Z3native (**/**) @@ -18,27 +17,28 @@ object method virtual dispose : unit end +(** Context objects *) class context settings = object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config in - let f e = (set_param_value cfg (fst e) (snd e)) in + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; - let v = mk_context_rc cfg in - del_config(cfg) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; v val mutable m_refCount : int = 0 initializer Gc.finalise (fun self -> self#dispose) self - + method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing context %d \n" (Oo.id self) ; - (del_context m_n_ctx) + (Z3native.del_context m_n_ctx) ) else ( (* re-queue for finalization? *) ) @@ -48,6 +48,8 @@ object (self) method gno = m_n_ctx end + +(** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) inherit idisposable @@ -56,14 +58,14 @@ object (self) initializer (match m_n_obj with - | Some (x) -> self#incref x; + | Some (x) -> self#incref m_ctx#gno x; m_ctx#add_one_ctx_obj | None -> () ); Gc.finalise (fun self -> self#dispose) self - method virtual incref : Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> unit + method virtual incref : Z3native.ptr -> Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> Z3native.ptr -> unit (* Disposes of the underlying native Z3 object. @@ -71,61 +73,415 @@ object (self) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with - | Some (x) -> self#decref x; m_n_obj <- None; m_ctx#sub_one_ctx_obj + | Some (x) -> self#decref m_ctx#gno x; m_n_obj <- None; m_ctx#sub_one_ctx_obj | None -> () ); - method gno = m_n_obj + method gno = match m_n_obj with + | Some(x) -> x + | None -> raise (Z3native.Exception "Z3 object lost") - method sno x = - (match x with - | Some(x) -> self#incref x - | None -> () - ); + method sno nc o = + self#incref nc o ; (match m_n_obj with - | Some(x) -> self#decref x + | Some(x) -> self#decref nc x | None -> () ); - m_n_obj <- x + m_n_obj <- Some o - method get_context = m_ctx + method gc = m_ctx method gnc = m_ctx#gno - -(* - method array_to_native a = - let f e = e#gno in - (Array.map f a) - - method array_length a = - match a with - | Some(x) -> (Array.length x) - | None -> 0 -*) - end -class symbol ctx obj = + +(** Parameter set objects *) +class params ctx obj = object (self) - inherit z3object ctx obj - - method incref o = () - method decref o = () + inherit z3object ctx obj as super + method incref ctx o = Z3native.params_inc_ref ctx o + method decref ctx o = Z3native.params_dec_ref ctx o end + +(** Symbol objects *) +class symbol ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method incref ctx o = () + method decref ctx o = () +end + +let symbolaton (a : symbol array) = + let f (e : symbol) = e#gno in + Array.map f a + +(** Int symbol objects *) class int_symbol ctx = object(self) - inherit symbol ctx None - method cnstr_obj obj = (self#sno obj) ; self - method cnstr_int i = (self#sno (Some (mk_int_symbol ctx#gno i))) ; self + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_int i = (self#sno ctx#gno (Z3native.mk_int_symbol ctx#gno i)) ; self end +(** String symbol objects *) class string_symbol ctx = object(self) - inherit symbol ctx None - method cnstr_obj obj = (self#sno obj) ; self - method cnstr_string name = (self#sno (Some (mk_string_symbol ctx#gno name))) ; self + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_string name = (self#sno ctx#gno (Z3native.mk_string_symbol ctx#gno name)) ; self end +let create_symbol ctx no = + match (int2symbol_kind (Z3native.get_symbol_kind ctx#gno no)) with + | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) + | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) + +(** AST objects *) +class ast ctx = +object (self) + inherit z3object ctx None as super (* CMW: derive from icomparable? *) + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + + method incref nc o = Z3native.inc_ref nc o + method decref nc o = Z3native.dec_ref nc o +end + +let astaton (a : ast array) = + let f (e : ast) = e#gno in + Array.map f a + +(** Sort objects *) +class sort ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Arithmetic sort objects, i.e., Int or Real. *) +class arith_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Array sorts objects *) +class array_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx#gno (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self +end + +(** Bit-vector sort objects *) +class bitvec_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Boolean sort objects *) +class bool_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Datatype sort objects *) +class datatype_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_sc (name : symbol) constructors = (self#sno ctx#gno (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self +end + +(** Enum sort objects *) +class enum_sort ctx = +object (self) + inherit sort ctx as super + val mutable _constdecls = None + val mutable _testerdecls = None + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ss (name : symbol) (enum_names : symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + _constdecls <- Some a ; + _testerdecls <- Some b ; + (self#sno ctx#gno r) ; + self + + method const_decls = match _constdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing const decls") + + method tester_decls = match _testerdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tester decls") +end + +(** Int sort objects *) +class int_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Real sort objects *) +class real_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Uninterpreted sort objects *) +class uninterpreted_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_s (s : symbol) = (self #sno ctx#gno (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self +end + +(** Finite domain sort objects *) +class finite_domain_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx#gno (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self +end + +(** Relation sort objects *) +class relation_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** List sort objects *) +class list_sort ctx = +object (self) + inherit sort ctx as super + val mutable _nildecl = None + val mutable _is_nildecl = None + val mutable _consdecl = None + val mutable _is_consdecl = None + val mutable _headdecl = None + val mutable _taildecl = None + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ss (name : symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + _nildecl <- Some a ; + _is_nildecl <- Some b ; + _consdecl <- Some c ; + _is_consdecl <- Some d ; + _headdecl <- Some e ; + _taildecl <- Some f ; + (self#sno ctx#gno r) ; + self + + method nil_decl = match _nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing nil decl") + + method is_nil_decl = match _is_nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_nil decls") + + method cons_decl = match _consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing cons decls") + + method is_cons_decl = match _is_consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_cons decls") + + method head_decl = match _headdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing head decls") + + method tail_decl = match _taildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tail decls") + +end + +(** Set sort objects *) +class set_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_s (s : sort) = (self#sno ctx#gno s#gno) ; self +end + +(** Tuple sort objects *) +class tuple_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = + let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + (self#sno ctx#gno x) ; + self +end + +let create_sort ctx obj = + match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) + | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) + | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) + | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) + | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) + | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) + | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) + | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) + | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + +(** Function declaration objects *) +class func_decl ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + + method incref nc o = super#incref nc o + method decref nc o = super#decref nc o +end + +class parameter = +object (self) + val mutable m_kind : parameter_kind = PARAMETER_INT; + val mutable m_i : int = 0 + val mutable m_d : float = 0.0 + val mutable m_sym : symbol option = None + val mutable m_srt : sort option = None + val mutable m_ast : ast option = None + val mutable m_fd : func_decl option = None + val mutable m_r : string = "" + + method cnstr_int i = m_kind <- PARAMETER_INT; m_i <- i + method cnstr_double d = m_kind <- PARAMETER_DOUBLE; m_d <- d + method cnstr_symbol sym = m_kind <- PARAMETER_SYMBOL; m_sym <- sym + method cnstr_sort srt = m_kind <- PARAMETER_SORT; m_srt <- srt + method cnstr_ast ast = m_kind <- PARAMETER_AST; m_ast <- ast + method cnstr_func_decl fd = m_kind <- PARAMETER_FUNC_DECL; m_fd <- fd + method cnstr_rational r = m_kind <- PARAMETER_RATIONAL; m_r <- r + + method kind = m_kind + method int = m_i + method double = m_d + method symbol = match m_sym with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter symbol") + method sort = match m_srt with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter sort") + method ast = match m_ast with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter ast") + method func_decl = match m_fd with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter func_decl") + method rational = m_r +end + +(** Expression objects *) +class expr ctx = +object(self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +let expraton (a : expr array) = + let f (e : expr) = e#gno in + Array.map f a + +(** Boolean expression objects *) +class bool_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Arithmetic expression objects (int/real) *) +class arith_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Int expression objects *) +class int_expr ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Real expression objects *) +class real_expr ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Bit-vector expression objects *) +class bitvec_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Array expression objects *) +class array_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Datatype expression objects *) +class datatype_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Integer numeral expression objects *) +class int_num ctx = +object (self) + inherit int_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Rational numeral expression objects *) +class rat_num ctx = +object (self) + inherit real_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Bit-vector numeral expression objects *) +class bitvec_num ctx = +object (self) + inherit bitvec_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Algebraic numeral expression objects *) +class algebraic_num ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + + +(** Quantifier objects *) +class quantifier ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + + + (**/**) (** Interaction logging for Z3. @@ -138,34 +494,34 @@ struct @return True if opening the log file succeeds, false otherwise. *) (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((int2lbool (open_log filename)) == L_TRUE) + let open_ filename = ((int2lbool (Z3native.open_log filename)) == L_TRUE) (** Closes the interaction log. *) - let close = close_log + let close = Z3native.close_log (** Appends a user-provided string to the interaction log. @param s the string to append*) - let append s = append_log s + let append s = Z3native.append_log s end (** Version information. *) module Version = struct (** The major version. *) - let major = let (x, _, _, _) = get_version in x + let major = let (x, _, _, _) = Z3native.get_version in x (** The minor version. *) - let minor = let (_, x, _, _) = get_version in x + let minor = let (_, x, _, _) = Z3native.get_version in x (** The build version. *) - let build = let (_, _, x, _) = get_version in x + let build = let (_, _, x, _) = Z3native.get_version in x (** The revision. *) - let revision = let (_, _, _, x) = get_version in x + let revision = let (_, _, _, x) = Z3native.get_version in x (** A string representation of the version information. *) let to_string = - let (mj, mn, bld, rev) = get_version in + let (mj, mn, bld, rev) = Z3native.get_version in string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ @@ -174,75 +530,5281 @@ end (** Symbols are used to name several term and type constructors. *) module Symbol = -struct -(**/**) - let create ctx obj = - match obj with - | Some(x) -> ( - match (int2symbol_kind (get_symbol_kind ctx#gno x)) with - | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj obj) :> symbol) - | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj obj) :> symbol) - ) - | None -> raise (Exception "Can't create null objects") -(**/**) - +struct (** The kind of the symbol (int or string) *) - let kind (o : symbol) = match o#gno with - | Some(x) -> (int2symbol_kind (get_symbol_kind o#gnc x)) - | _ -> raise (Exception "Underlying object lost") + let kind (o : symbol) = (int2symbol_kind (Z3native.get_symbol_kind o#gnc o#gno)) (** Indicates whether the symbol is of Int kind *) - let is_int_symbol (o : symbol) = match o#gno with - | Some(x) -> (kind o) == INT_SYMBOL - | _ -> false + let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL (** Indicates whether the symbol is of string kind. *) - let is_string_symbol (o : symbol) = match o#gno with - | Some(x) -> (kind o) == STRING_SYMBOL - | _ -> false + let is_string_symbol (o : symbol) = (kind o) == STRING_SYMBOL (** The int value of the symbol. *) - let get_int (o : int_symbol) = match o#gno with - | Some(x) -> (get_symbol_int o#gnc x) - | None -> 0 + let get_int (o : int_symbol) = Z3native.get_symbol_int o#gnc o#gno (** The string value of the symbol. *) - let get_string (o : string_symbol) = match o#gno with - | Some(x) -> (get_symbol_string o#gnc x) - | None -> "" + let get_string (o : string_symbol) = Z3native.get_symbol_string o#gnc o#gno (** A string representation of the symbol. *) - let to_string (o : symbol) = match o#gno with - | Some(x) -> - ( - match (kind o) with - | INT_SYMBOL -> (string_of_int (get_symbol_int o#gnc x)) - | STRING_SYMBOL -> (get_symbol_string o#gnc x) - ) - | None -> "" + let to_string (o : symbol) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) + | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) end -(** The main interaction with Z3 happens via the Context. *) + +(** + The Sort module implements type information for ASTs. +*) +module Sort = +struct + (** + Comparison operator. + @param a A sort + @param b A sort + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) (a : sort) (b : sort) = (a == b) || + if a#gnc != b#gnc then + false + else + ((int2lbool (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + + (** + Returns a unique identifier for the sort. + *) + let get_id (x : sort) = Z3native.get_sort_id x#gnc x#gno + + (** + The kind of the sort. + *) + let get_sort_kind (x : sort) = (int2sort_kind (Z3native.get_sort_kind x#gnc x#gno)) + + (** + The name of the sort + *) + let get_name (x : sort) = (create_symbol x#gc (Z3native.get_sort_name x#gnc x#gno)) + + (** + A string representation of the sort. + *) + let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno +end + +(** Array sorts *) +module ArraySort = +struct + (** The domain of the array sort. *) + let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + + (** The range of the array sort. *) + let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) +end + +(** Bit-vector sorts *) +module BitVectorSort = +struct + (** The size of the bit-vector sort. *) + let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno +end + +(** Finite domain sorts. *) +module FiniteDomainSort = +struct + (** The size of the finite domain sort. *) + let get_size (x : finite_domain_sort) = + let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") +end + +(** Relation sorts. *) +module RelationSort = +struct + (** The arity of the relation sort. *) + let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + + (** The sorts of the columns of the relation sort. *) + let get_column_sorts (x : relation_sort) = + let n = get_arity x in + let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + Array.init n f + +end + +(**/**) +let create_expr ctx obj = + if int2ast_kind (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + (((new quantifier ctx)#cnstr_obj obj) :> expr) + else + let s = Z3native.get_sort ctx#gno obj in + let sk = (int2sort_kind (Z3native.get_sort_kind ctx#gno s)) in + if (int2lbool (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + (((new algebraic_num ctx)#cnstr_obj obj) :> expr) + else + if ((int2lbool (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + match sk with + | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) + | REAL_SORT -> (((new rat_num ctx)#cnstr_obj obj) :> expr) + | BV_SORT -> (((new bitvec_num ctx)#cnstr_obj obj) :> expr) + | _ -> raise (Z3native.Exception "Unsupported numeral object") + else + match sk with + | BOOL_SORT -> (((new bool_expr ctx)#cnstr_obj obj) :> expr) + | INT_SORT -> (((new int_expr ctx)#cnstr_obj obj) :> expr) + | REAL_SORT -> (((new real_expr ctx)#cnstr_obj obj) :> expr) + | BV_SORT -> (((new bitvec_expr ctx)#cnstr_obj obj) :> expr) + | ARRAY_SORT -> (((new array_expr ctx)#cnstr_obj obj) :> expr) + | DATATYPE_SORT -> (((new datatype_expr ctx)#cnstr_obj obj) :> expr) + | _ -> (new expr ctx)#cnstr_obj obj + +let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = + let o = Z3native.mk_app ctx#gno f#gno (Array.length args) (astaton args) in + create_expr ctx o + +let create_ast ctx no = + match (int2ast_kind (Z3native.get_ast_kind ctx#gno no)) with + | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) + | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) + | SORT_AST -> ((create_sort ctx no) :> ast) + | APP_AST + | NUMERAL_AST + | VAR_AST -> ((create_expr ctx no) :> ast) + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") +(**/**) + +(** Function declarations. *) +module FuncDecl = +struct +(** Parameters of Func_Decls *) + module Parameter = + struct + (** + The kind of the parameter. + *) + let get_kind (x : parameter) = x#kind + + (**The int value of the parameter.*) + let get_int (x : parameter) = + if (x#kind != PARAMETER_INT) then + raise (Z3native.Exception "parameter is not an int") + else + x#int + + (**The double value of the parameter.*) + let get_double (x : parameter) = + if (x#kind != PARAMETER_DOUBLE) then + raise (Z3native.Exception "parameter is not a double") + else + x#double + + (**The Symbol value of the parameter.*) + let get_symbol (x : parameter) = + if (x#kind != PARAMETER_SYMBOL) then + raise (Z3native.Exception "parameter is not a symbol") + else + x#symbol + + (**The Sort value of the parameter.*) + let get_sort (x : parameter) = + if (x#kind != PARAMETER_SORT) then + raise (Z3native.Exception "parameter is not a sort") + else + x#sort + + (**The AST value of the parameter.*) + let get_ast (x : parameter) = + if (x#kind != PARAMETER_AST) then + raise (Z3native.Exception "parameter is not an ast") + else + x#ast + + (**The FunctionDeclaration value of the parameter.*) + let get_ast (x : parameter) = + if (x#kind != PARAMETER_FUNC_DECL) then + raise (Z3native.Exception "parameter is not an function declaration") + else + x#func_decl + + (**The rational string value of the parameter.*) + let get_rational (x : parameter) = + if (x#kind != PARAMETER_RATIONAL) then + raise (Z3native.Exception "parameter is not a ratinoal string") + else + x#rational + end + + (** + Comparison operator. + @param a A func_decl + @param b A func_decl + @return True if and are from the same context + and represent the same func_decl; false otherwise. + *) + let ( = ) (a : func_decl) (b : func_decl) = (a == b) || + if a#gnc == a#gnc then + false + else + ((int2lbool (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + (** + A string representations of the function declaration. + *) + let to_string (x : func_decl) = Z3native.func_decl_to_string x#gnc x#gno + + (** + Returns a unique identifier for the function declaration. + *) + let get_id (x : func_decl) = Z3native.get_func_decl_id x#gnc x#gno + + (** + The arity of the function declaration + *) + let get_arity (x : func_decl) = Z3native.get_arity x#gnc x#gno + + (** + The size of the domain of the function declaration + + *) + let get_domain_size (x : func_decl) = Z3native.get_domain_size x#gnc x#gno + + (** + The domain of the function declaration + *) + let get_domain (x : func_decl) = + let n = (get_domain_size x) in + let f i = create_sort x#gc (Z3native.get_domain x#gnc x#gno i) in + Array.init n f + + (** + The range of the function declaration + *) + let get_range (x : func_decl) = + create_sort x#gc (Z3native.get_range x#gnc x#gno) + + (** + The kind of the function declaration. + *) + let get_decl_kind (x : func_decl) = (int2decl_kind (Z3native.get_decl_kind x#gnc x#gno)) + + (** + The name of the function declaration + *) + let get_name (x : func_decl) = (create_symbol x#gc (Z3native.get_decl_name x#gnc x#gno)) + + (** + The number of parameters of the function declaration + *) + let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) + + (** + The parameters of the function declaration + *) + let get_parameters (x : func_decl) = + let n = (get_num_parameters x) in + let f i = ( + match (int2parameter_kind (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with + | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) + | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) + | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SORT -> (new parameter)#cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) + | PARAMETER_AST -> (new parameter)#cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) + | PARAMETER_FUNC_DECL -> (new parameter)#cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) + | PARAMETER_RATIONAL -> (new parameter)#cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) + ) in + Array.init n f + + (** + Create expression that applies function to arguments. + + *) + let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args + +end + +(** Datatype sorts *) +module DatatypeSort = +struct + (** The number of constructors of the datatype sort. *) + let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + + (** The range of the array sort. *) + let get_constructors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + Array.init n f + + (** The recognizers. *) + let get_recognizers (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + Array.init n f + + (** The constructor accessors. *) + let get_accessors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = ( + let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in + let ds = (Z3native.get_domain_size fd#gnc fd#gno) in + let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + Array.init ds g + ) in + Array.init n f +end + +(** Enumeration sorts. *) +module EnumSort = +struct + (** The function declarations of the constants in the enumeration. *) + let get_const_decls (x : enum_sort) = + let f e = ((new func_decl x#gc)#cnstr_obj e) in + Array.map f x#const_decls + + (** The test predicates for the constants in the enumeration. *) + let get_tester_decls (x : enum_sort) = + let f e = ((new func_decl x#gc)#cnstr_obj e) in + Array.map f x#tester_decls +end + +(** List sorts. *) +module ListSort = +struct + (** The declaration of the nil function of this list sort. *) + let get_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#nil_decl + + (** The declaration of the isNil function of this list sort. *) + let get_is_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_nil_decl + + (** The declaration of the cons function of this list sort. *) + let get_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#cons_decl + + (** The declaration of the isCons function of this list sort. *) + let get_is_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_cons_decl + + (** The declaration of the head function of this list sort.*) + let get_head_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#head_decl + + (** The declaration of the tail function of this list sort. *) + let get_tail_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#tail_decl + + (** The empty list. *) + let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] +end + +module TupleSort = +struct + (** The constructor function of the tuple.*) + let get_mk_decl (x : tuple_sort) = + (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + + (** The number of fields in the tuple. *) + let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + + (** The field declarations. *) + let get_field_decls (x : tuple_sort) = + let n = get_num_fields x in + let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + Array.init n f +end + +(** The abstract syntax tree (AST) module. *) +module AST = +struct + (** + The AST's hash code. + @return A hash code + *) + let get_hash_code ( x : ast) = Z3native.get_ast_hash x#gnc x#gno + + (** + A unique identifier for the AST (unique among all ASTs). + *) + let get_id ( x : ast) = Z3native.get_ast_id x#gnc x#gno + + (** + The kind of the AST. + *) + let get_ast_kind ( x : ast) = (int2ast_kind (Z3native.get_ast_kind x#gnc x#gno)) + + (** + Indicates whether the AST is an Expr + *) + let is_expr ( x : ast) = + match get_ast_kind ( x : ast) with + | APP_AST + | NUMERAL_AST + | QUANTIFIER_AST + | VAR_AST -> true + | _ -> false + + (** + Indicates whether the AST is a BoundVariable + *) + let is_var ( x : ast) = (get_ast_kind x) == VAR_AST + + (** + Indicates whether the AST is a Quantifier + *) + let is_quantifier ( x : ast) = (get_ast_kind x) == QUANTIFIER_AST + + + (** + Indicates whether the AST is a Sort + *) + let is_sort ( x : ast) = (get_ast_kind x) == SORT_AST + + (** + Indicates whether the AST is a FunctionDeclaration + *) + let is_func_decl ( x : ast) = (get_ast_kind x) == FUNC_DECL_AST + + (** + A string representation of the AST. + *) + let to_string ( x : ast) = Z3native.ast_to_string x#gnc x#gno + + (** + A string representation of the AST in s-expression notation. + *) + let to_sexpr ( x : ast) = Z3native.ast_to_string x#gnc x#gno + + (** + Comparison operator. + @param a An AST + @param b An AST + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) (a : expr) (b : expr) = (a == b) || + if a#gnc == b#gnc then + false + else + ((int2lbool (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + + (** + Object Comparison. + @param other Another ast + @return Negative if the object should be sorted before , positive if after else zero. + *) + let compare a b = + if (get_id a) < (get_id b) then -1 else + if (get_id a) > (get_id b) then 1 else + 0 + + (** Operator < *) + let ( < ) (a : ast) (b : ast) = (compare a b) + + (** + Translates (copies) the AST to the Context . + @param ctx A context + @return A copy of the AST which is associated with + *) + let translate ( x : ast) to_ctx = + if x#gc == to_ctx then + x + else + (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) +end + +(** + Parameter sets + + A Params objects represents a configuration in the form of Symbol/value pairs. +*) +module Params = +struct + (** + Adds a parameter setting. + *) + let add_bool (p : params) (name : symbol) (value : bool) = + Z3native.params_set_bool p#gnc p#gno name#gno (lbool2int (if value then L_TRUE else L_FALSE)) + + (** + Adds a parameter setting. + *) + let add_int (p : params) (name : symbol) (value : int) = + Z3native.params_set_uint p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_double (p : params) (name : symbol) (value : float) = + Z3native.params_set_double p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol (p : params) (name : symbol) (value : symbol) = + Z3native.params_set_symbol p#gnc p#gno name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool (p : params) (name : string) (value : bool) = + add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_int (p : params) (name : string) (value : int) = + add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_double (p : params) (name : string) (value : float) = + add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol (p : params) (name : string) (value : symbol) = + add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + A string representation of the parameter set. + *) + let to_string (p : params) = Z3native.params_to_string p#gnc p#gno +end + +(** Expressions (terms) *) +module Expr = +struct + (** + Returns a simplified version of the expression. + A set of parameters to configure the simplifier + + *) + let simplify ( x : expr ) ( p : params option ) = match p with + | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) + | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) + + (** + The function declaration of the function that is applied in this expression. + *) + let get_func_decl ( x : expr ) = (new func_decl x#gc)#cnstr_obj (Z3native.get_app_decl x#gnc x#gno) + + (** + Indicates whether the expression is the true or false expression + or something else (Z3_L_UNDEF). + *) + let get_bool_value ( x : expr ) = int2lbool (Z3native.get_bool_value x#gnc x#gno) + + (** + The number of arguments of the expression. + *) + let get_num_args ( x : expr ) = Z3native.get_app_num_args x#gnc x#gno + + (** + The arguments of the expression. + *) + let get_args ( x : expr ) = let n = (get_num_args x) in + let f i = create_expr x#gc (Z3native.get_app_arg x#gnc x#gno i) in + Array.init n f + + (** + Update the arguments of the expression using the arguments + The number of new arguments should coincide with the current number of arguments. + *) + let update ( x : expr ) args = + if (Array.length args <> (get_num_args x)) then + raise (Z3native.Exception "Number of arguments does not match") + else + x#sno x#gnc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + + (** + Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. + + *) + let substitute ( x : expr ) from to_ = + if (Array.length from) <> (Array.length to_) then + raise (Z3native.Exception "Argument sizes do not match") + else + create_expr x#gc (Z3native.substitute x#gnc x#gno (Array.length from) (expraton from) (expraton to_)) + + (** + Substitute every occurrence of from in the expression with to. + + *) + let substitute_one ( x : expr ) from to_ = + substitute ( x : expr ) [| from |] [| to_ |] + + (** + Substitute the free variables in the expression with the expressions in + + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. + + *) + let substitute_vars ( x : expr ) to_ = + create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) + + + (** + Translates (copies) the term to the Context . + A context + A copy of the term which is associated with + *) + let translate ( x : expr ) to_ctx = + if x#gc == to_ctx then + x + else + create_expr to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno) + + (** + Returns a string representation of the expression. + *) + let to_string ( x : expr ) = Z3native.ast_to_string x#gnc x#gno + + (** + Indicates whether the term is a numeral + *) + let is_numeral ( x : expr ) = int2lbool (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + + (** + Indicates whether the term is well-sorted. + True if the term is well-sorted, false otherwise. + *) + let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + + (** + The Sort of the term. + *) + let get_sort ( x : expr ) = create_sort x#gc (Z3native.get_sort x#gnc x#gno) + + (** + Indicates whether the term has Boolean sort. + *) + let is_bool ( x : expr ) = (AST.is_expr x) && + (int2lbool (Z3native.is_eq_sort x#gnc + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno))) == L_TRUE + + (** + Indicates whether the term is of integer sort. + *) + let is_int ( x : expr ) = + ((int2lbool (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + + (** + Indicates whether the term is of sort real. + *) + let is_real ( x : expr ) = + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + + (** + Indicates whether the term is of an array sort. + *) + let is_array ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + + (** + Indicates whether the term represents a constant. + *) + let is_const ( x : expr ) = (AST.is_expr x) && + (get_num_args x) == 0 && + FuncDecl.get_domain_size(get_func_decl x) == 0 + + (** + Indicates whether the term is an integer numeral. + *) + let is_int_numeral ( x : expr ) = (is_numeral x) && (is_int x) + + (** + Indicates whether the term is a real numeral. + *) + let is_rat_num ( x : expr ) = (is_numeral x) && (is_real x) + + (** + Indicates whether the term is an algebraic number + *) + let is_algebraic_number ( x : expr ) = int2lbool(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + + (** + Indicates whether the term is the constant true. + *) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + + (** + Indicates whether the term is the constant false. + *) + let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + + (** + Indicates whether the term is an equality predicate. + *) + let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + + (** + Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). + *) + let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + + (** + Indicates whether the term is a ternary if-then-else term + *) + let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + + (** + Indicates whether the term is an n-ary conjunction + *) + let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + + (** + Indicates whether the term is an n-ary disjunction + *) + let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + + (** + Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) + *) + let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + + (** + Indicates whether the term is an exclusive or + *) + let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + + (** + Indicates whether the term is a negation + *) + let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + + (** + Indicates whether the term is an implication + *) + let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + + (** + Indicates whether the term is an arithmetic numeral. + *) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ANUM) + + (** + Indicates whether the term is a less-than-or-equal + *) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LE) + + (** + Indicates whether the term is a greater-than-or-equal + *) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GE) + + (** + Indicates whether the term is a less-than + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LT) + + (** + Indicates whether the term is a greater-than + *) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GT) + + (** + Indicates whether the term is addition (binary) + *) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ADD) + + (** + Indicates whether the term is subtraction (binary) + *) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SUB) + + (** + Indicates whether the term is a unary minus + *) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UMINUS) + + (** + Indicates whether the term is multiplication (binary) + *) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MUL) + + (** + Indicates whether the term is division (binary) + *) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DIV) + + (** + Indicates whether the term is integer division (binary) + *) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IDIV) + + (** + Indicates whether the term is remainder (binary) + *) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REM) + + (** + Indicates whether the term is modulus (binary) + *) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MOD) + + (** + Indicates whether the term is a coercion of integer to real (unary) + *) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_REAL) + + (** + Indicates whether the term is a coercion of real to integer (unary) + *) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_INT) + + (** + Indicates whether the term is a check that tests whether a real is integral (unary) + *) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IS_INT) + + (** + Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. + *) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_STORE) + + (** + Indicates whether the term is an array select. + *) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SELECT) + + (** + Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. + *) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONST_ARRAY) + + (** + Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. + *) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_DEFAULT) + + (** + Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + *) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_MAP) + + (** + Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. + *) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AS_ARRAY) + + (** + Indicates whether the term is set union + *) + let is_set_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_UNION) + + (** + Indicates whether the term is set intersection + *) + let is_set_intersect ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_INTERSECT) + + (** + Indicates whether the term is set difference + *) + let is_set_difference ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_DIFFERENCE) + + (** + Indicates whether the term is set complement + *) + let is_set_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_COMPLEMENT) + + (** + Indicates whether the term is set subset + *) + let is_set_subset ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_SUBSET) + + (** + Indicates whether the terms is of bit-vector sort. + *) + let is_bv ( x : expr ) = + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + + (** + Indicates whether the term is a bit-vector numeral + *) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNUM) + + (** + Indicates whether the term is a one-bit bit-vector with value one + *) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT1) + + (** + Indicates whether the term is a one-bit bit-vector with value zero + *) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT0) + + (** + Indicates whether the term is a bit-vector unary minus + *) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNEG) + + (** + Indicates whether the term is a bit-vector addition (binary) + *) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BADD) + + (** + Indicates whether the term is a bit-vector subtraction (binary) + *) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSUB) + + (** + Indicates whether the term is a bit-vector multiplication (binary) + *) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BMUL) + + (** + Indicates whether the term is a bit-vector signed division (binary) + *) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV) + + (** + Indicates whether the term is a bit-vector unsigned division (binary) + *) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV) + + (** + Indicates whether the term is a bit-vector signed remainder (binary) + *) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM) + + (** + Indicates whether the term is a bit-vector unsigned remainder (binary) + *) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM) + + (** + Indicates whether the term is a bit-vector signed modulus + *) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD) + + (** + Indicates whether the term is a bit-vector signed division by zero + *) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV0) + + (** + Indicates whether the term is a bit-vector unsigned division by zero + *) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV0) + + (** + Indicates whether the term is a bit-vector signed remainder by zero + *) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM0) + + (** + Indicates whether the term is a bit-vector unsigned remainder by zero + *) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM0) + + (** + Indicates whether the term is a bit-vector signed modulus by zero + *) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD0) + + (** + Indicates whether the term is an unsigned bit-vector less-than-or-equal + *) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULEQ) + + (** + Indicates whether the term is a signed bit-vector less-than-or-equal + *) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLEQ) + + (** + Indicates whether the term is an unsigned bit-vector greater-than-or-equal + *) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGEQ) + + (** + Indicates whether the term is a signed bit-vector greater-than-or-equal + *) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGEQ) + + (** + Indicates whether the term is an unsigned bit-vector less-than + *) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULT) + + (** + Indicates whether the term is a signed bit-vector less-than + *) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLT) + + (** + Indicates whether the term is an unsigned bit-vector greater-than + *) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGT) + + (** + Indicates whether the term is a signed bit-vector greater-than + *) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGT) + + (** + Indicates whether the term is a bit-wise AND + *) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BAND) + + (** + Indicates whether the term is a bit-wise OR + *) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BOR) + + (** + Indicates whether the term is a bit-wise NOT + *) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOT) + + (** + Indicates whether the term is a bit-wise XOR + *) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXOR) + + (** + Indicates whether the term is a bit-wise NAND + *) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNAND) + + (** + Indicates whether the term is a bit-wise NOR + *) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOR) + + (** + Indicates whether the term is a bit-wise XNOR + *) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXNOR) + + (** + Indicates whether the term is a bit-vector concatenation (binary) + *) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONCAT) + + (** + Indicates whether the term is a bit-vector sign extension + *) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SIGN_EXT) + + (** + Indicates whether the term is a bit-vector zero extension + *) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ZERO_EXT) + + (** + Indicates whether the term is a bit-vector extraction + *) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXTRACT) + + (** + Indicates whether the term is a bit-vector repetition + *) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REPEAT) + + (** + Indicates whether the term is a bit-vector reduce OR + *) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDOR) + + (** + Indicates whether the term is a bit-vector reduce AND + *) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDAND) + + (** + Indicates whether the term is a bit-vector comparison + *) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BCOMP) + + (** + Indicates whether the term is a bit-vector shift left + *) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSHL) + + (** + Indicates whether the term is a bit-vector logical shift right + *) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BLSHR) + + (** + Indicates whether the term is a bit-vector arithmetic shift left + *) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BASHR) + + (** + Indicates whether the term is a bit-vector rotate left + *) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_LEFT) + + (** + Indicates whether the term is a bit-vector rotate right + *) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_RIGHT) + + (** + Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. + *) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_LEFT) + + (** + Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. + *) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_RIGHT) + + (** + Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. + *) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_INT2BV) + + (** + Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. + *) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BV2INT) + + (** + Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + *) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CARRY) + + (** + Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + *) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR3) + + (** + Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. + *) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + + (** + Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + *) + + (** + Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. + *) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + + (** + Indicates whether the term is a Proof for the expression 'true'. + *) + let is_proof_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRUE) + + (** + Indicates whether the term is a proof for a fact asserted by the user. + *) + let is_proof_asserted ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ASSERTED) + + (** + Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. + *) + let is_proof_goal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_GOAL) + + (** + Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). + *) + let is_proof_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS) + + (** + Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. + *) + let is_proof_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REFLEXIVITY) + + (** + Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. + + *) + let is_proof_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SYMMETRY) + + (** + Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) + + *) + let is_proof_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY) + + (** + Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. + + *) + let is_proof_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + + + (** + Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. + + *) + let is_proof_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MONOTONICITY) + + (** + Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) + + *) + let is_proof_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INTRO) + + (** + Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. + + *) + let is_proof_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DISTRIBUTIVITY) + + (** + Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i + + *) + let is_proof_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_AND_ELIM) + + (** + Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) + + *) + let is_proof_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NOT_OR_ELIM) + + (** + Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) + + *) + let is_proof_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE) + + (** + Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) + + *) + let is_proof_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE_STAR) + + (** + Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. + + *) + let is_proof_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT) + + (** + Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents + + *) + let is_proof_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT_STAR) + + (** + Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents + + *) + let is_proof_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PUSH_QUANT) + + (** + Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. + + *) + let is_proof_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + + (** + Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. + + *) + let is_proof_der ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DER) + + (** + Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) + + *) + let is_proof_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INST) + + (** + Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. + *) + let is_proof_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_HYPOTHESIS) + + (** + Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. + + *) + let is_proof_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_LEMMA) + + (** + Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') + + *) + let is_proof_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_UNIT_RESOLUTION) + + (** + Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) + + *) + let is_proof_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_TRUE) + + (** + Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) + + *) + let is_proof_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_FALSE) + + (** + Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. + + *) + let is_proof_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + + (** + Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). + + *) + let is_proof_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_AXIOM) + + (** + Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) + + *) + let is_proof_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_INTRO) + + (** + Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. + + *) + let is_proof_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_APPLY_DEF) + + (** + Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) + + *) + let is_proof_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_OEQ) + + (** + Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. + + *) + let is_proof_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_POS) + + (** + Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) + + *) + let is_proof_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_NEG) + + (** + Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. + + *) + let is_proof_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_STAR) + + (** + Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. + + *) + let is_proof_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_CNF_STAR) + + (** + Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. + + *) + let is_proof_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SKOLEMIZE) + + (** + Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q + + *) + let is_proof_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + + (** + Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. + + *) + let is_proof_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TH_LEMMA) + + (** + Indicates whether the term is of a relation sort. + *) + let is_Relation ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + + (** + Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. + + *) + let is_relation_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_STORE) + + (** + Indicates whether the term is an empty relation + *) + let is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_EMPTY) + + (** + Indicates whether the term is a test for the emptiness of a relation + *) + let is_is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_IS_EMPTY) + + (** + Indicates whether the term is a relational join + *) + let is_relational_join ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_JOIN) + + (** + Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. + *) + let is_relation_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_UNION) + + (** + Indicates whether the term is the widening of two relations + The function takes two arguments. + *) + let is_relation_widen ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_WIDEN) + + (** + Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. + *) + let is_relation_project ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_PROJECT) + + (** + Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. + + *) + let is_relation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_FILTER) + + (** + Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. + + *) + let is_relation_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_NEGATION_FILTER) + + (** + Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. + + *) + let is_relation_rename ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_RENAME) + + (** + Indicates whether the term is the complement of a relation + *) + let is_relation_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_COMPLEMENT) + + (** + Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. + + *) + let is_relation_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_SELECT) + + (** + Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind + to perform destructive updates to the first argument. + + *) + let is_relation_clone ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_CLONE) + + (** + Indicates whether the term is of an array sort. + *) + let is_finite_domain ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + + (** + Indicates whether the term is a less than predicate over a finite domain. + *) + let is_finite_domain_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FD_LT) + + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno +end + +(* Integer Numerals *) +module IntNum = +struct + (** Retrieve the int value. *) + let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Rational Numerals *) +module RatNum = +struct + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) (precision : int) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Bit-vector numerals *) +module BitVecNum = +struct + (** Retrieve the int value. *) + let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Algebraic numbers *) +module AlgebraicNum = +struct + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + + the precision of the result + A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + + + A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** The main interaction with Z3 happens via the Context module. *) module Context = struct + + (* SYMBOLS *) + (** Creates a new symbol using an integer. Not all integers can be passed to this function. The legal range of unsigned integers is 0 to 2^30-1. *) - let mk_symbol_int ctx i = + let mk_symbol_int ( ctx : context ) i = (new int_symbol ctx)#cnstr_int i - + (** Creates a new symbol using a string. *) - let mk_symbol_string ctx s = + let mk_symbol_string ( ctx : context ) s = (new string_symbol ctx)#cnstr_string s (** Create an array of symbols. *) - let mk_symbols ctx names = - let f elem = mk_symbol_string ctx elem in + let mk_symbols_int ( ctx : context ) names = + let f elem = mk_symbol_int ( ctx : context ) elem in + (Array.map f names) + + (** + Create an array of symbols. + *) + let mk_symbols_string ( ctx : context ) names = + let f elem = mk_symbol_string ( ctx : context ) elem in (Array.map f names) + + (* SORTS *) + + (** + Create a new Boolean sort. + *) + let mk_bool_sort ( ctx : context ) = + (new bool_sort ctx) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_sort ( ctx : context ) (s : symbol) = + (new uninterpreted_sort ctx)#cnstr_s s + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_sort_s ( ctx : context ) (s : string) = + mk_uninterpreted_sort ctx ((mk_symbol_string ( ctx : context ) s) :> symbol) + + (** + Create a new integer sort. + *) + let mk_int_sort ( ctx : context ) = + (new int_sort ctx) + + (** + Create a real sort. + *) + let mk_real_sort ( ctx : context ) = + (new real_sort ctx) + + (** + Create a new bit-vector sort. + *) + let mk_bitvec_sort ( ctx : context ) size = + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) + + (** + Create a new array sort. + *) + let mk_array_sort ( ctx : context ) domain range = + (new array_sort ctx)#cnstr_dr domain range + + (** + Create a new tuple sort. + *) + let mk_tuple_sort ( ctx : context ) name field_names field_sorts = + (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts + + (** + Create a new enumeration sort. + *) + let mk_enum_sort ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss name enum_names + + (** + Create a new enumeration sort. + *) + let mk_enum_sort_s ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss + ((mk_symbol_string ( ctx : context ) name) :> symbol) + (let f e = (e :> symbol) in + (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) + ) + + (** + Create a new list sort. + *) + let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = + (new list_sort ctx)#cnstr_ss name elem_sort + + (** + Create a new list sort. + *) + let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = + mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort + + + (** + Create a new finite domain sort. + *) + let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = + (new finite_domain_sort ctx)#cnstr_si name size + + (** + Create a new finite domain sort. + *) + let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = + (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size + +(** + +(* DATATYPES *) +(** + Create a datatype constructor. +*) + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + public Constructor MkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) + { + + + + + return new Constructor(this, name, recognizer, fieldNames, sorts, sortRefs); + } + +(** + Create a datatype constructor. +*) + @param name + @param recognizer + @param fieldNames + @param sorts + @param sortRefs + @return + public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) + { + + + return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs); + } + +(** + Create a new datatype sort. +*) + let mk_Datatype_Sort(Symbol name, Constructor[] constructors) + { + + + + + + + CheckContextMatch(name); + CheckContextMatch(constructors); + return new DatatypeSort(this, name, constructors); + } + +(** + Create a new datatype sort. +*) + let mk_Datatype_Sort(string name, Constructor[] constructors) + { + + + + + CheckContextMatch(constructors); + return new DatatypeSort(this, MkSymbol(name), constructors); + } + +(** + Create mutually recursive datatypes. +*) + @param names names of datatype sorts + @param c list of constructors, one list per sort. + let mk_Datatype_Sorts(Symbol[] names, Constructor[][] c) + { + + + + + + + + CheckContextMatch(names); + uint n = (uint)names.Length; + ConstructorList[] cla = new ConstructorList[n]; + IntPtr[] n_constr = new IntPtr[n]; + for (uint i = 0; i < n; i++) + { + Constructor[] constructor = c[i]; + + CheckContextMatch(constructor); + cla[i] = new ConstructorList(this, constructor); + n_constr[i] = cla[i].x#gno; + } + IntPtr[] n_res = new IntPtr[n]; + Z3native.mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); + DatatypeSort[] res = new DatatypeSort[n]; + for (uint i = 0; i < n; i++) + res[i] = new DatatypeSort(this, n_res[i]); + return res; + } + +(** + Create mutually recursive data-types. +*) + @param names + @param c + @return + let mk_Datatype_Sorts(string[] names, Constructor[][] c) + { + + + + + + + + return MkDatatypeSorts(MkSymbols(names), c); + } + + + + +(* FUNCTION DECLARATIONS *) +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(Symbol name, Sort[] domain, Sort range) + { + + + + + + CheckContextMatch(name); + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, name, domain, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(Symbol name, Sort domain, Sort range) + { + + + + + + CheckContextMatch(name); + CheckContextMatch(domain); + CheckContextMatch(range); + Sort[] q = new Sort[] { domain }; + return new Func_Decl(this, name, q, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(string name, Sort[] domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, MkSymbol(name), domain, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(string name, Sort domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + Sort[] q = new Sort[] { domain }; + return new Func_Decl(this, MkSymbol(name), q, range); + } + +(** + Creates a fresh function declaration with a name prefixed with . +*) + + + let mk_Fresh_Func_Decl(string prefix, Sort[] domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, prefix, domain, range); + } + +(** + Creates a new constant function declaration. +*) + let mk_Const_Decl(Symbol name, Sort range) + { + + + + + CheckContextMatch(name); + CheckContextMatch(range); + return new Func_Decl(this, name, null, range); + } + +(** + Creates a new constant function declaration. +*) + let mk_Const_Decl(string name, Sort range) + { + + + + CheckContextMatch(range); + return new Func_Decl(this, MkSymbol(name), null, range); + } + +(** + Creates a fresh constant function declaration with a name prefixed with . +*) + + + let mk_Fresh_ConstDecl(string prefix, Sort range) + { + + + + CheckContextMatch(range); + return new Func_Decl(this, prefix, null, range); + } + + +(* BOUND VARIABLES *) +(** + Creates a new bound variable. +*) + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + public Expr MkBound(uint index, Sort ty) + { + + + + return Expr.Create(this, Z3native.mk_bound(nCtx, index, ty.x#gno)); + } + + +(* QUANTIFIER PATTERNS *) +(** + Create a quantifier pattern. +*) + public Pattern MkPattern(params Expr[] terms) + { + + if (terms.Length == 0) + throw new Z3Exception("Cannot create a pattern from zero terms"); + + + + + + IntPtr[] termsNative = AST.ArrayToNative(terms); + return new Pattern(this, Z3native.mk_pattern(nCtx, (uint)terms.Length, termsNative)); + } + + +(* CONSTANTS *) +(** + Creates a new Constant of sort and named . +*) + public Expr MkConst(Symbol name, Sort range) + { + + + + + CheckContextMatch(name); + CheckContextMatch(range); + + return Expr.Create(this, Z3native.mk_const(nCtx, name.x#gno, range.x#gno)); + } + +(** + Creates a new Constant of sort and named . +*) + public Expr MkConst(string name, Sort range) + { + + + + return MkConst(MkSymbol(name), range); + } + +(** + Creates a fresh Constant of sort and a + name prefixed with . +*) + let mk_Fresh_Const(string prefix, Sort range) + { + + + + CheckContextMatch(range); + return Expr.Create(this, Z3native.mk_fresh_const(nCtx, prefix, range.x#gno)); + } + +(** + Creates a fresh constant from the Func_Decl . +*) + @param f A decl of a 0-arity function + public Expr MkConst(Func_Decl f) + { + + + + return MkApp(f); + } + +(** + Create a Boolean constant. +*) + let mk_Bool_Const(Symbol name) + { + + + + return (BoolExpr)MkConst(name, BoolSort); + } + +(** + Create a Boolean constant. +*) + let mk_Bool_Const(string name) + { + + + return (BoolExpr)MkConst(MkSymbol(name), BoolSort); + } + +(** + Creates an integer constant. +*) + let mk_Int_Const(Symbol name) + { + + + + return (IntExpr)MkConst(name, IntSort); + } + +(** + Creates an integer constant. +*) + let mk_Int_Const(string name) + { + + + + return (IntExpr)MkConst(name, IntSort); + } + +(** + Creates a real constant. +*) + let mk_Real_Const(Symbol name) + { + + + + return (RealExpr)MkConst(name, RealSort); + } + +(** + Creates a real constant. +*) + let mk_Real_Const(string name) + { + + + return (RealExpr)MkConst(name, RealSort); + } + +(** + Creates a bit-vector constant. +*) + let mk_B_VConst(Symbol name, uint size) + { + + + + return (BitVecExpr)MkConst(name, MkBitVecSort(size)); + } + +(** + Creates a bit-vector constant. +*) + let mk_B_VConst(string name, uint size) + { + + + return (BitVecExpr)MkConst(name, MkBitVecSort(size)); + } + + +(* TERMS *) +(** + Create a new function application. +*) + public Expr MkApp(Func_Decl f, params Expr[] args) + { + + + + + CheckContextMatch(f); + CheckContextMatch(args); + return Expr.Create(this, f, args); + } + +(* PROPOSITIONAL *) +(** + The true Term. +*) + public BoolExpr MkTrue ( ctx : context ) = + { + + + return new BoolExpr(this, Z3native.mk_true(nCtx)); + } + +(** + The false Term. +*) + public BoolExpr MkFalse ( ctx : context ) = + { + + + return new BoolExpr(this, Z3native.mk_false(nCtx)); + } + +(** + Creates a Boolean value. +*) + public BoolExpr MkBool(bool value) + { + + + return value ? MkTrue ( ctx : context ) = : MkFalse ( ctx : context ) =; + } + +(** + Creates the equality = . +*) + public BoolExpr MkEq(Expr x, Expr y) + { + + + + + CheckContextMatch(x); + CheckContextMatch(y); + return new BoolExpr(this, Z3native.mk_eq(nCtx, x.x#gno, y.x#gno)); + } + +(** + Creates a distinct term. +*) + public BoolExpr MkDistinct(params Expr[] args) + { + + + + + + CheckContextMatch(args); + return new BoolExpr(this, Z3native.mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Mk an expression representing not(a). +*) + public BoolExpr MkNot(BoolExpr a) + { + + + + CheckContextMatch(a); + return new BoolExpr(this, Z3native.mk_not(nCtx, a.x#gno)); + } + +(** + Create an expression representing an if-then-else: ite(t1, t2, t3). +*) + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + let mk_I_TE(BoolExpr t1, Expr t2, Expr t3) + { + + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + CheckContextMatch(t3); + return Expr.Create(this, Z3native.mk_ite(nCtx, t1.x#gno, t2.x#gno, t3.x#gno)); + } + +(** + Create an expression representing t1 iff t2. +*) + public BoolExpr MkIff(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_iff(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 -> t2. +*) + public BoolExpr MkImplies(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_implies(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 xor t2. +*) + public BoolExpr MkXor(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_xor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t[0] and t[1] and .... +*) + public BoolExpr MkAnd(params BoolExpr[] t) + { + + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] or t[1] or .... +*) + public BoolExpr MkOr(params BoolExpr[] t) + { + + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + + +(* ARITHMETIC *) +(** + Create an expression representing t[0] + t[1] + .... +*) + public ArithExpr MkAdd(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] * t[1] * .... +*) + public ArithExpr MkMul(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] - t[1] - .... +*) + public ArithExpr MkSub(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing -t. +*) + let mk_Unary_Minus(ArithExpr t) + { + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_unary_minus(nCtx, t.x#gno)); + } + +(** + Create an expression representing t1 / t2. +*) + public ArithExpr MkDiv(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return (ArithExpr)Expr.Create(this, Z3native.mk_div(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 mod t2. +*) + The arguments must have int type. + public IntExpr MkMod(IntExpr t1, IntExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new IntExpr(this, Z3native.mk_mod(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 rem t2. +*) + The arguments must have int type. + public IntExpr MkRem(IntExpr t1, IntExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new IntExpr(this, Z3native.mk_rem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 ^ t2. +*) + public ArithExpr MkPower(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return (ArithExpr)Expr.Create(this, Z3native.mk_power(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 < t2 +*) + public BoolExpr MkLt(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_lt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 <= t2 +*) + public BoolExpr MkLe(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_le(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 > t2 +*) + public BoolExpr MkGt(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_gt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 >= t2 +*) + public BoolExpr MkGe(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_ge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Coerce an integer to a real. +*) + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + + public RealExpr MkInt2Real(IntExpr t) + { + + + + CheckContextMatch(t); + return new RealExpr(this, Z3native.mk_int2real(nCtx, t.x#gno)); + } + +(** + Coerce a real to an integer. +*) + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + + public IntExpr MkReal2Int(RealExpr t) + { + + + + CheckContextMatch(t); + return new IntExpr(this, Z3native.mk_real2int(nCtx, t.x#gno)); + } + +(** + Creates an expression that checks whether a real number is an integer. +*) + let mk_Is_Integer(RealExpr t) + { + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_is_int(nCtx, t.x#gno)); + } + + +(* BIT-VECTORS *) +(** + Bitwise negation. +*) + The argument must have a bit-vector sort. + let mk_B_VNot(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvnot(nCtx, t.x#gno)); + } + +(** + Take conjunction of bits in a vector, return vector of length 1. +*) + The argument must have a bit-vector sort. + let mk_B_VRedAND(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvredand(nCtx, t.x#gno)); + } + +(** + Take disjunction of bits in a vector, return vector of length 1. +*) + The argument must have a bit-vector sort. + let mk_B_VRedOR(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvredor(nCtx, t.x#gno)); + } + +(** + Bitwise conjunction. +*) + The arguments must have a bit-vector sort. + let mk_B_VAND(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvand(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise disjunction. +*) + The arguments must have a bit-vector sort. + let mk_B_VOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise XOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VXOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvxor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise NAND. +*) + The arguments must have a bit-vector sort. + let mk_B_VNAND(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvnand(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise NOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VNOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvnor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise XNOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VXNOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvxnor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Standard two's complement unary minus. +*) + The arguments must have a bit-vector sort. + let mk_B_VNeg(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvneg(nCtx, t.x#gno)); + } + +(** + Two's complement addition. +*) + The arguments must have the same bit-vector sort. + let mk_B_VAdd(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvadd(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement subtraction. +*) + The arguments must have the same bit-vector sort. + let mk_B_VSub(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsub(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement multiplication. +*) + The arguments must have the same bit-vector sort. + let mk_B_VMul(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvmul(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned division. +*) + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VUDiv(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvudiv(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Signed division. +*) + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSDiv(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsdiv(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned remainder. +*) + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VURem(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvurem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Signed remainder. +*) + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSRem(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsrem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed remainder (sign follows divisor). +*) + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSMod(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsmod(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned less-than +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VULT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvult(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed less-than +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSLT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvslt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned less-than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VULE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvule(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed less-than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSLE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsle(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned greater than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VUGE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvuge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed greater than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSGE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned greater-than. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VUGT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvugt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed greater-than. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSGT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsgt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bit-vector concatenation. +*) + + The arguments must have a bit-vector sort. + + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). + + public BitVecExpr MkConcat(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_concat(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bit-vector extraction. +*) + + Extract the bits down to from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. + The argument must have a bit-vector sort. + + public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_extract(nCtx, high, low, t.x#gno)); + } + +(** + Bit-vector sign extension. +*) + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. + The argument must have a bit-vector sort. + + let mk_Sign_Ext(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_sign_ext(nCtx, i, t.x#gno)); + } + +(** + Bit-vector zero extension. +*) + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. + The argument must have a bit-vector sort. + + let mk_Zero_Ext(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_zero_ext(nCtx, i, t.x#gno)); + } + +(** + Bit-vector repetition. +*) + + The argument must have a bit-vector sort. + + public BitVecExpr MkRepeat(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_repeat(nCtx, i, t.x#gno)); + } + +(** + Shift left. +*) + + It is equivalent to multiplication by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VSHL(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvshl(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Logical shift right +*) + + It is equivalent to unsigned division by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VLSHR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvlshr(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Arithmetic shift right +*) + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VASHR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvashr(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Rotate Left. +*) + + Rotate bits of \c t to the left \c i times. + The argument must have a bit-vector sort. + + let mk_B_VRotateLeft(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_rotate_left(nCtx, i, t.x#gno)); + } + +(** + Rotate Right. +*) + + Rotate bits of \c t to the right \c i times. + The argument must have a bit-vector sort. + + let mk_B_VRotateRight(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_rotate_right(nCtx, i, t.x#gno)); + } + +(** + Rotate Left. +*) + + Rotate bits of to the left times. + The arguments must have the same bit-vector sort. + + let mk_B_VRotateLeft(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_ext_rotate_left(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Rotate Right. +*) + + Rotate bits of to the right times. + The arguments must have the same bit-vector sort. + + let mk_B_VRotateRight(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_ext_rotate_right(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an bit bit-vector from the integer argument . +*) + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + + public BitVecExpr MkInt2BV(uint n, IntExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_int2bv(nCtx, n, t.x#gno)); + } + +(** + Create an integer from the bit-vector argument . +*) + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in . + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of bit-vector sort. + + let mk_B_V2Int(BitVecExpr t, bool signed) + { + + + + CheckContextMatch(t); + return new IntExpr(this, Z3native.mk_bv2int(nCtx, t.x#gno, (signed) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise addition does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VAddNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvadd_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise addition does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvadd_no_underflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise subtraction does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSubNoOverflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsub_no_overflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise subtraction does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsub_no_underflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise signed division does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsdiv_no_overflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise negation does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VNegNoOverflow(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_bvneg_no_overflow(nCtx, t.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise multiplication does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VMulNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvmul_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise multiplication does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvmul_no_underflow(nCtx, t1.x#gno, t2.x#gno)); + } + + +(* ARRAYS *) +(** + Create an array constant. +*) + let mk_Array_Const(Symbol name, Sort domain, Sort range) + { + + + + + + return (ArrayExpr)MkConst(name, MkArraySort(domain, range)); + } + +(** + Create an array constant. +*) + let mk_Array_Const(string name, Sort domain, Sort range) + { + + + + + return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range)); + } + +(** + Array read. +*) + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + + + + public Expr MkSelect(ArrayExpr a, Expr i) + { + + + + + CheckContextMatch(a); + CheckContextMatch(i); + return Expr.Create(this, Z3native.mk_select(nCtx, a.x#gno, i.x#gno)); + } + +(** + Array update. +*) + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + + + + public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v) + { + + + + + + CheckContextMatch(a); + CheckContextMatch(i); + CheckContextMatch(v); + return new ArrayExpr(this, Z3native.mk_store(nCtx, a.x#gno, i.x#gno, v.x#gno)); + } + +(** + Create a constant array. +*) + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + + + + let mk_Const_Array(Sort domain, Expr v) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(v); + return new ArrayExpr(this, Z3native.mk_const_array(nCtx, domain.x#gno, v.x#gno)); + } + +(** + Maps f on the argument arrays. +*) + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + + + + + public ArrayExpr MkMap(Func_Decl f, params ArrayExpr[] args) + { + + + + + CheckContextMatch(f); + CheckContextMatch(args); + return (ArrayExpr)Expr.Create(this, Z3native.mk_map(nCtx, f.x#gno, AST.ArrayLength(args), AST.ArrayToNative(args))); + } + +(** + Access the array default value. +*) + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. + + let mk_Term_Array(ArrayExpr array) + { + + + + CheckContextMatch(array); + return Expr.Create(this, Z3native.mk_array_default(nCtx, array.x#gno)); + } + + +(* SETS *) +(** + Create a set type. +*) + let mk_Set_Sort(Sort ty) + { + + + + CheckContextMatch(ty); + return new SetSort(this, ty); + } + +(** + Create an empty set. +*) + let mk_Empty_Set(Sort domain) + { + + + + CheckContextMatch(domain); + return Expr.Create(this, Z3native.mk_empty_set(nCtx, domain.x#gno)); + } + +(** + Create the full set. +*) + let mk_Full_Set(Sort domain) + { + + + + CheckContextMatch(domain); + return Expr.Create(this, Z3native.mk_full_set(nCtx, domain.x#gno)); + } + +(** + Add an element to the set. +*) + let mk_Set_Add(Expr set, Expr element) + { + + + + + CheckContextMatch(set); + CheckContextMatch(element); + return Expr.Create(this, Z3native.mk_set_add(nCtx, set.x#gno, element.x#gno)); + } + + +(** + Remove an element from a set. +*) + let mk_Set_Del(Expr set, Expr element) + { + + + + + CheckContextMatch(set); + CheckContextMatch(element); + return Expr.Create(this, Z3native.mk_set_del(nCtx, set.x#gno, element.x#gno)); + } + +(** + Take the union of a list of sets. +*) + let mk_Set_Union(params Expr[] args) + { + + + + CheckContextMatch(args); + return Expr.Create(this, Z3native.mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Take the intersection of a list of sets. +*) + let mk_Set_Intersection(params Expr[] args) + { + + + + + CheckContextMatch(args); + return Expr.Create(this, Z3native.mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Take the difference between two sets. +*) + let mk_Set_Difference(Expr arg1, Expr arg2) + { + + + + + CheckContextMatch(arg1); + CheckContextMatch(arg2); + return Expr.Create(this, Z3native.mk_set_difference(nCtx, arg1.x#gno, arg2.x#gno)); + } + +(** + Take the complement of a set. +*) + let mk_Set_Complement(Expr arg) + { + + + + CheckContextMatch(arg); + return Expr.Create(this, Z3native.mk_set_complement(nCtx, arg.x#gno)); + } + +(** + Check for set membership. +*) + let mk_Set_Membership(Expr elem, Expr set) + { + + + + + CheckContextMatch(elem); + CheckContextMatch(set); + return Expr.Create(this, Z3native.mk_set_member(nCtx, elem.x#gno, set.x#gno)); + } + +(** + Check for subsetness of sets. +*) + let mk_Set_Subset(Expr arg1, Expr arg2) + { + + + + + CheckContextMatch(arg1); + CheckContextMatch(arg2); + return Expr.Create(this, Z3native.mk_set_subset(nCtx, arg1.x#gno, arg2.x#gno)); + } + + +(* NUMERALS *) + +(* GENERAL NUMERALS *) +(** + Create a Term of a given sort. +*) + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + public Expr MkNumeral(string v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_numeral(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(int v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_int(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(uint v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_unsigned_int(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(long v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_int64(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(ulong v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_unsigned_int64(nCtx, v, ty.x#gno)); + } + + +(* REALS *) +(** + Create a real from a fraction. +*) + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + public RatNum MkReal(int num, int den) + { + if (den == 0) + throw new Z3Exception("Denominator is zero"); + + + + + return new RatNum(this, Z3native.mk_real(nCtx, num, den)); + } + +(** + Create a real numeral. +*) + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + public RatNum MkReal(string v) + { + + + return new RatNum(this, Z3native.mk_numeral(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(int v) + { + + + return new RatNum(this, Z3native.mk_int(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(uint v) + { + + + return new RatNum(this, Z3native.mk_unsigned_int(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(long v) + { + + + return new RatNum(this, Z3native.mk_int64(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(ulong v) + { + + + return new RatNum(this, Z3native.mk_unsigned_int64(nCtx, v, RealSort.x#gno)); + } + + +(* INTEGERS *) +(** + Create an integer numeral. +*) + @param v A string representing the Term value in decimal notation. + public IntNum MkInt(string v) + { + + + return new IntNum(this, Z3native.mk_numeral(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(int v) + { + + + return new IntNum(this, Z3native.mk_int(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(uint v) + { + + + return new IntNum(this, Z3native.mk_unsigned_int(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(long v) + { + + + return new IntNum(this, Z3native.mk_int64(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(ulong v) + { + + + return new IntNum(this, Z3native.mk_unsigned_int64(nCtx, v, IntSort.x#gno)); + } + + +(* BIT-VECTORS *) +(** + Create a bit-vector numeral. +*) + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + let mk_B_V(string v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(int v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(uint v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(long v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(ulong v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + + + // Numerals + +(* QUANTIFIERS *) +(** + Create a universal Quantifier. +*) + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. + + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + + return new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a universal Quantifier. +*) + public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + return new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + +(** + Create an existential Quantifier. +*) + + public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + return new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + +(** + Create an existential Quantifier. +*) + public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + return new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a Quantifier. +*) + public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + + if (universal) + return MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + return MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a Quantifier. +*) + public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + if (universal) + return MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + + + // Expr + +(* OPTIONS *) + +(** + Selects the format used for pretty-printing expressions. +*) + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + + + + + + public Z3_ast_print_mode PrintMode + { + set { Z3native.set_ast_print_mode(nCtx, (uint)value); } + } + + +(* SMT Files & Strings *) +(** + Convert a benchmark into an SMT-LIB formatted string. +*) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) + { + + + + + return Z3native.benchmark_to_smtlib_string(nCtx, name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula.x#gno); + } + +(** + Parse the given string using the SMT-LIB parser. +*) + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. + + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string(nCtx, str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); + } + +(** + Parse the given file using the SMT-LIB parser. +*) + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file(nCtx, fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); + } + +(** + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBFormulas { get { return Z3native.get_smtlib_num_formulas(nCtx)) + +(** + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public BoolExpr[] SMTLIBFormulas + { + get + { + + + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_formula(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBAssumptions { get { return Z3native.get_smtlib_num_assumptions(nCtx)) + +(** + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public BoolExpr[] SMTLIBAssumptions + { + get + { + + + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_assumption(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBDecls { get { return Z3native.get_smtlib_num_decls(nCtx)) + +(** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public Func_Decl[] SMTLIBDecls + { + get + { + + + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBSorts { get { return Z3native.get_smtlib_num_sorts(nCtx)) + +(** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public Sort[] SMTLIBSorts + { + get + { + + + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort(nCtx, i)); + return res; + } + } + +(** + Parse the given string using the SMT-LIB2 parser. +*) + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + public BoolExpr ParseSMTLIB2String(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_string(nCtx, str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); + } + +(** + Parse the given file using the SMT-LIB2 parser. +*) + + public BoolExpr ParseSMTLIB2File(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_file(nCtx, fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); + } + + +(* GOALS *) +(** + Creates a new Goal. +*) + + Note that the Context must have been created with proof generation support if + is set to true here. + + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) + { + + + return new Goal(this, models, unsatCores, proofs); + } + + +(* PARAMETERSETS *) +(** + Creates a new ParameterSet. +*) + public Params MkParams ( ctx : context ) = + { + + + return new Params(this); + } + + +(* TACTICS *) +(** + The number of supported tactics. +*) + public uint NumTactics + { + get { return Z3native.get_num_tactics(nCtx); } + } + +(** + The names of all supported tactics. +*) + public string[] TacticNames + { + get + { + + + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name(nCtx, i); + return res; + } + } + +(** + Returns a string containing a description of the tactic with the given name. +*) + public string TacticDescription(string name) + { + + + return Z3native.tactic_get_descr(nCtx, name); + } + +(** + Creates a new Tactic. +*) + public Tactic MkTactic(string name) + { + + + return new Tactic(this, name); + } + +(** + Create a tactic that applies to a Goal and + then to every subgoal produced by . +*) + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + { + + + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + CheckContextMatch(ts); + + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) + { + last = ts[ts.Length - 1].x#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then(nCtx, ts[i].x#gno, last); + } + if (last != IntPtr.Zero) + { + last = Z3native.tactic_and_then(nCtx, t2.x#gno, last); + return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, last)); + } + else + return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that applies to a Goal and + then to every subgoal produced by . +*) + + Shorthand for AndThen. + + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) + { + + + + + + return AndThen(t1, t2, ts); + } + +(** + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. +*) + public Tactic OrElse(Tactic t1, Tactic t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_or_else(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that applies to a goal for milliseconds. +*) + + If does not terminate within milliseconds, then it fails. + + public Tactic TryFor(Tactic t, uint ms) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_try_for(nCtx, t.x#gno, ms)); + } + +(** + Create a tactic that applies to a given goal if the probe + evaluates to true. +*) + + If evaluates to false, then the new tactic behaves like the skip tactic. + + public Tactic When(Probe p, Tactic t) + { + + + + + CheckContextMatch(t); + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_when(nCtx, p.x#gno, t.x#gno)); + } + +(** + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. +*) + public Tactic Cond(Probe p, Tactic t1, Tactic t2) + { + + + + + + CheckContextMatch(p); + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_cond(nCtx, p.x#gno, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. +*) + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_repeat(nCtx, t.x#gno, max)); + } + +(** + Create a tactic that just returns the given goal. +*) + public Tactic Skip ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_skip(nCtx)); + } + +(** + Create a tactic always fails. +*) + public Tactic Fail ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_fail(nCtx)); + } + +(** + Create a tactic that fails if the probe evaluates to false. +*) + public Tactic FailIf(Probe p) + { + + + + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_fail_if(nCtx, p.x#gno)); + } + +(** + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). +*) + public Tactic FailIfNotDecided ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_fail_if_not_decided(nCtx)); + } + +(** + Create a tactic that applies using the given set of parameters . +*) + public Tactic UsingParams(Tactic t, Params p) + { + + + + + CheckContextMatch(t); + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_using_params(nCtx, t.x#gno, p.x#gno)); + } + +(** + Create a tactic that applies using the given set of parameters . +*) + Alias for UsingParams + public Tactic With(Tactic t, Params p) + { + + + + + return UsingParams(t, p); + } + +(** + Create a tactic that applies the given tactics in parallel. +*) + public Tactic ParOr(params Tactic[] t) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); + } + +(** + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. +*) + public Tactic ParAndThen(Tactic t1, Tactic t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_par_and_then(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Interrupt the execution of a Z3 procedure. +*) + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = + { + Z3native.interrupt(nCtx); + } + + +(* PROBES *) +(** + The number of supported Probes. +*) + public uint NumProbes + { + get { return Z3native.get_num_probes(nCtx); } + } + +(** + The names of all supported Probes. +*) + public string[] ProbeNames + { + get + { + + + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name(nCtx, i); + return res; + } + } + +(** + Returns a string containing a description of the probe with the given name. +*) + public string ProbeDescription(string name) + { + + + return Z3native.probe_get_descr(nCtx, name); + } + +(** + Creates a new Probe. +*) + public Probe MkProbe(string name) + { + + + return new Probe(this, name); + } + +(** + Create a probe that always evaluates to . +*) + public Probe Const(double val) + { + + + return new Probe(this, Z3native.probe_const(nCtx, val)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by +*) + public Probe Lt(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_lt(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by +*) + public Probe Gt(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_gt(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by +*) + public Probe Le(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_le(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by +*) + public Probe Ge(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_ge(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by +*) + public Probe Eq(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_eq(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + and evaluate to "true". +*) + public Probe And(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_and(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + or evaluate to "true". +*) + public Probe Or(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_or(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". +*) + public Probe Not(Probe p) + { + + + + CheckContextMatch(p); + return new Probe(this, Z3native.probe_not(nCtx, p.x#gno)); + } + + +(* SOLVERS *) +(** + Creates a new (incremental) solver. +*) + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. + + public Solver MkSolver(Symbol logic = null) + { + + + if (logic == null) + return new Solver(this, Z3native.mk_solver(nCtx)); + else + return new Solver(this, Z3native.mk_solver_for_logic(nCtx, logic.x#gno)); + } + +(** + Creates a new (incremental) solver. +*) + + public Solver MkSolver(string logic) + { + + + return MkSolver(MkSymbol(logic)); + } + +(** + Creates a new (incremental) solver. +*) + let mk_Simple_Solver ( ctx : context ) = + { + + + return new Solver(this, Z3native.mk_simple_solver(nCtx)); + } + +(** + Creates a solver that is implemented using the given tactic. +*) + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. + + public Solver MkSolver(Tactic t) + { + + + + return new Solver(this, Z3native.mk_solver_from_tactic(nCtx, t.x#gno)); + } + + +(* FIXEDPOINTS *) +(** + Create a Fixedpoint context. +*) + public Fixedpoint MkFixedpoint ( ctx : context ) = + { + + + return new Fixedpoint(this); + } + + + +(* MISCELLANEOUS *) +(** + Wraps an AST. +*) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) + { + + return AST.Create(this, nativeObject); + } + +(** + Unwraps an AST. +*) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) + { + return a.x#gno; + } + +(** + Return a string describing all available parameters to Expr.Simplify. +*) + public string SimplifyHelp ( ctx : context ) = + { + + + return Z3native.simplify_get_help(nCtx); + } + +(** + Retrieves parameter descriptions for simplifier. +*) + public ParamDescrs SimplifyParameterDescriptions + { + get { return new ParamDescrs(this, Z3native.simplify_get_param_descrs(nCtx)); } + } + +(** + Enable/disable printing of warning messages to the console. +*) + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) + { + Z3native.toggle_warning_messages((enabled) ? 1 : 0); + } + + +(* ERROR HANDLING *) + //(** + //A delegate which is executed when an error is raised. + //*) + // + //Note that it is possible for memory leaks to occur if error handlers + //throw exceptions. + // + //public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); + + //(** + //The OnError event. + //*) + //public event ErrorHandler OnError = null; + + +(* PARAMETERS *) +(** + Update a mutable configuration parameter. +*) + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + + + public void UpdateParamValue(string id, string value) + { + Z3native.update_param_value(nCtx, id, value); + } + +(** + Get a configuration parameter. +*) + + Returns null if the parameter value does not exist. + + + public string GetParamValue(string id) + { + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value(nCtx, id, out res); + if (r == (int)Z3_lbool.Z3_L_FALSE) + return null; + else + return Marshal.PtrToStringAnsi(res); + } + + + +(* INTERNAL *) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get { return m_ctx) + + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + { + // Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + } + + internal void InitContext ( ctx : context ) = + { + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); // keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); + } +*) end From 2277ad3654e4778d6ca9b0a904c4ac8e637cce4f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 01:45:10 +0000 Subject: [PATCH 268/646] ML API bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 ++- scripts/update_api.py | 2 +- src/api/ml/z3.ml | 136 ++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 66 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 7046a92b0..f414e9d1a 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -18,10 +18,16 @@ let _ = let ctx = (new context cfg) in let is = (mk_symbol_int ctx 42) in let ss = (mk_symbol_string ctx "mySymbol") in + let bs = (mk_bool_sort ctx) in + let ints = (mk_int_sort ctx) in + let rs = (mk_real_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); Printf.printf "Disposing...\n"; - ctx#dispose (* can do, but we'd rather let it go out of scope *) ; + Gc.full_major () ); Printf.printf "Exiting.\n"; ;; diff --git a/scripts/update_api.py b/scripts/update_api.py index c8cd05c7e..c3f2abce6 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1280,7 +1280,7 @@ def mk_ml(): ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') ml_wrapper.write('\n\n') ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') - ml_wrapper.write(' identifier: "default handling",\n') + ml_wrapper.write(' identifier: (char*) "default handling",\n') ml_wrapper.write(' finalize: custom_finalize_default,\n') ml_wrapper.write(' compare: custom_compare_default,\n') ml_wrapper.write(' hash: custom_hash_default,\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 2100f371e..3a0e9208e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -30,21 +30,25 @@ object (self) Z3native.del_config(cfg) ; v - val mutable m_refCount : int = 0 + val mutable m_obj_cnt : int = 0 initializer - Gc.finalise (fun self -> self#dispose) self + (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v method dispose : unit = - if m_refCount == 0 then ( - Printf.printf "Disposing context %d \n" (Oo.id self) ; + if m_obj_cnt == 0 then ( + (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) (Z3native.del_context m_n_ctx) ) else ( + Printf.printf "NOT DISPOSING context %d because it still has %d objects alive\n" (Oo.id self) m_obj_cnt; (* re-queue for finalization? *) ) - method sub_one_ctx_obj = m_refCount <- m_refCount - 1 - method add_one_ctx_obj = m_refCount <- m_refCount + 1 + method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 + method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx end @@ -62,18 +66,21 @@ object (self) m_ctx#add_one_ctx_obj | None -> () ); - Gc.finalise (fun self -> self#dispose) self + (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v method virtual incref : Z3native.ptr -> Z3native.ptr -> unit method virtual decref : Z3native.ptr -> Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) method dispose = - Printf.printf "Disposing z3object %d \n" (Oo.id self) ; + (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) (match m_n_obj with - | Some (x) -> self#decref m_ctx#gno x; m_n_obj <- None; m_ctx#sub_one_ctx_obj + | Some (x) -> + self#decref m_ctx#gno x; + m_ctx#sub_one_ctx_obj ; + m_n_obj <- None; | None -> () ); @@ -81,10 +88,11 @@ object (self) | Some(x) -> x | None -> raise (Z3native.Exception "Z3 object lost") - method sno nc o = - self#incref nc o ; + method sno (ctx : context) o = + m_ctx#add_one_ctx_obj ; + self#incref ctx#gno o ; (match m_n_obj with - | Some(x) -> self#decref nc x + | Some(x) -> self#decref ctx#gno x ; m_ctx#sub_one_ctx_obj | None -> () ); m_n_obj <- Some o @@ -107,7 +115,7 @@ end class symbol ctx = object (self) inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method incref ctx o = () method decref ctx o = () end @@ -120,16 +128,16 @@ let symbolaton (a : symbol array) = class int_symbol ctx = object(self) inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_int i = (self#sno ctx#gno (Z3native.mk_int_symbol ctx#gno i)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol ctx#gno i)) ; self end (** String symbol objects *) class string_symbol ctx = object(self) inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_string name = (self#sno ctx#gno (Z3native.mk_string_symbol ctx#gno name)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol ctx#gno name)) ; self end let create_symbol ctx no = @@ -141,7 +149,7 @@ let create_symbol ctx no = class ast ctx = object (self) inherit z3object ctx None as super (* CMW: derive from icomparable? *) - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = Z3native.inc_ref nc o method decref nc o = Z3native.dec_ref nc o @@ -155,44 +163,44 @@ let astaton (a : ast array) = class sort ctx = object (self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Arithmetic sort objects, i.e., Int or Real. *) class arith_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Array sorts objects *) class array_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx#gno (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self end (** Bit-vector sort objects *) class bitvec_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Boolean sort objects *) class bool_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Datatype sort objects *) class datatype_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_sc (name : symbol) constructors = (self#sno ctx#gno (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_sc (name : symbol) constructors = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self end (** Enum sort objects *) @@ -201,12 +209,12 @@ object (self) inherit sort ctx as super val mutable _constdecls = None val mutable _testerdecls = None - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in _constdecls <- Some a ; _testerdecls <- Some b ; - (self#sno ctx#gno r) ; + (self#sno ctx r) ; self method const_decls = match _constdecls with @@ -222,37 +230,37 @@ end class int_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Real sort objects *) class real_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Uninterpreted sort objects *) class uninterpreted_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx#gno (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self end (** Finite domain sort objects *) class finite_domain_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx#gno (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self end (** Relation sort objects *) class relation_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** List sort objects *) @@ -265,7 +273,7 @@ object (self) val mutable _is_consdecl = None val mutable _headdecl = None val mutable _taildecl = None - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in _nildecl <- Some a ; @@ -274,7 +282,7 @@ object (self) _is_consdecl <- Some d ; _headdecl <- Some e ; _taildecl <- Some f ; - (self#sno ctx#gno r) ; + (self#sno ctx r) ; self method nil_decl = match _nildecl with @@ -307,18 +315,18 @@ end class set_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_s (s : sort) = (self#sno ctx#gno s#gno) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_s (s : sort) = (self#sno ctx s#gno) ; self end (** Tuple sort objects *) class tuple_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in - (self#sno ctx#gno x) ; + (self#sno ctx x) ; self end @@ -339,9 +347,9 @@ let create_sort ctx obj = class func_decl ctx = object (self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o method decref nc o = super#decref nc o @@ -388,7 +396,7 @@ end class expr ctx = object(self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end let expraton (a : expr array) = @@ -399,77 +407,77 @@ let expraton (a : expr array) = class bool_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Arithmetic expression objects (int/real) *) class arith_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Int expression objects *) class int_expr ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Real expression objects *) class real_expr ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Bit-vector expression objects *) class bitvec_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Array expression objects *) class array_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Datatype expression objects *) class datatype_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Integer numeral expression objects *) class int_num ctx = object (self) inherit int_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Rational numeral expression objects *) class rat_num ctx = object (self) inherit real_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Bit-vector numeral expression objects *) class bitvec_num ctx = object (self) inherit bitvec_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Algebraic numeral expression objects *) class algebraic_num ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end @@ -477,7 +485,7 @@ end class quantifier ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end @@ -1112,7 +1120,7 @@ struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - x#sno x#gnc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + x#sno x#gc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -2483,7 +2491,7 @@ struct Create a new Boolean sort. *) let mk_bool_sort ( ctx : context ) = - (new bool_sort ctx) + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) (** Create a new uninterpreted sort. @@ -2501,13 +2509,13 @@ struct Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx) + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx) + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) (** Create a new bit-vector sort. From 524336ea3e21093639c54158f6c7b21b14811e02 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 03:57:18 +0000 Subject: [PATCH 269/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 572 ++++++++++++++++++++++++++++++----------------- 1 file changed, 364 insertions(+), 208 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 3a0e9208e..116d7a230 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -33,11 +33,11 @@ object (self) val mutable m_obj_cnt : int = 0 initializer - (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v - + (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v + method dispose : unit = if m_obj_cnt == 0 then ( (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) @@ -110,7 +110,6 @@ object (self) method decref ctx o = Z3native.params_dec_ref ctx o end - (** Symbol objects *) class symbol ctx = object (self) @@ -166,6 +165,10 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +let sortaton (a : sort array) = + let f (e : sort) = e#gno in + Array.map f a + (** Arithmetic sort objects, i.e., Int or Real. *) class arith_sort ctx = object (self) @@ -195,20 +198,12 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** Datatype sort objects *) -class datatype_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) constructors = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self -end - (** Enum sort objects *) class enum_sort ctx = object (self) inherit sort ctx as super - val mutable _constdecls = None - val mutable _testerdecls = None + val mutable _constdecls : Z3native.ptr array option = None + val mutable _testerdecls : Z3native.ptr array option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in @@ -267,12 +262,12 @@ end class list_sort ctx = object (self) inherit sort ctx as super - val mutable _nildecl = None - val mutable _is_nildecl = None - val mutable _consdecl = None - val mutable _is_consdecl = None - val mutable _headdecl = None - val mutable _taildecl = None + val mutable _nildecl : Z3native.ptr option = None + val mutable _is_nildecl : Z3native.ptr option = None + val mutable _consdecl : Z3native.ptr option = None + val mutable _is_consdecl : Z3native.ptr option = None + val mutable _headdecl : Z3native.ptr option = None + val mutable _taildecl : Z3native.ptr option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in @@ -291,23 +286,23 @@ object (self) method is_nil_decl = match _is_nildecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decls") + | None -> raise (Z3native.Exception "Missing is_nil decl") method cons_decl = match _consdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decls") + | None -> raise (Z3native.Exception "Missing cons decl") method is_cons_decl = match _is_consdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decls") + | None -> raise (Z3native.Exception "Missing is_cons decl") method head_decl = match _headdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decls") + | None -> raise (Z3native.Exception "Missing head decl") method tail_decl = match _taildecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decls") + | None -> raise (Z3native.Exception "Missing tail decl") end @@ -330,18 +325,6 @@ object (self) self end -let create_sort ctx obj = - match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with - | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) - | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) - | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) - | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) - | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) - | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) - | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) - | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) - | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") (** Function declaration objects *) class func_decl ctx = @@ -392,6 +375,126 @@ object (self) method rational = m_r end + +(** Constructor objects *) +class constructor ctx = +object (self) + inherit z3object ctx None as super + val mutable m_n : int = 0 + val mutable m_tester_decl : func_decl option = None + val mutable m_constructor_decl : func_decl option = None + val mutable m_accessor_decls : func_decl array option = None + method incref ctx o = () + method decref ctx o = () + initializer + let f = fun o -> Z3native.del_constructor o#gnc o#gno in + let v = self in + Gc.finalise f v + + method cnstr_ssssi (name : symbol) (recognizer : symbol) (field_names : symbol array) (sorts : sort array) (sort_refs : int array) = + m_n <- (Array.length field_names) ; + if m_n != (Array.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if m_n != (Array.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let o = (Z3native.mk_constructor ctx#gno name#gno recognizer#gno m_n (symbolaton field_names) + (sortaton sorts) + sort_refs) in + self#sno ctx o ; + self + + method private init = + match m_tester_decl with + | None -> + let (a, b, c) = (Z3native.query_constructor self#gnc self#gno m_n) in + m_constructor_decl <- Some ((new func_decl ctx)#cnstr_obj a) ; + m_tester_decl <- Some ((new func_decl ctx)#cnstr_obj b) ; + m_accessor_decls <- Some (let f e = ((new func_decl ctx)#cnstr_obj e) in Array.map f c) ; + () + | _ -> () + + method get_n = m_n + + method tester_decl = match m_tester_decl with + | Some(x) -> x + | None -> self#init ; self#tester_decl + + method constructor_decl = match m_constructor_decl with + | Some(x) -> x + | None -> self#init ; self#constructor_decl + + method accessor_decls = match m_accessor_decls with + | Some(x) -> x + | None -> self#init ; self#accessor_decls +end + +let constructoraton (a : constructor array) = + let f (e : constructor) = e#gno in + Array.map f a + +(** Constructor list objects *) +class constructor_list ctx = +object (self) + inherit z3object ctx None + method incref ctx o = () + method decref ctx o = () + initializer + let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in + let v = self in + Gc.finalise f v + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ca ( c : constructor array ) = + self#sno ctx (Z3native.mk_constructor_list ctx#gno (Array.length c) (constructoraton c)) ; + self +end + +let constructor_listaton (a : constructor_list array) = + let f (e : constructor_list) = e#gno in + Array.map f a + +(** Datatype sort objects *) +class datatype_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (constructoraton constructors)))) ; self +end + +let create_sort ctx obj = + match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) + | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) + | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) + | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) + | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) + | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) + | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) + | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) + | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + +(** AST vector objects *) +class ast_vector ctx = +object (self) + inherit z3object ctx None + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref ctx o = Z3native.ast_vector_inc_ref ctx o + method decref ctx o = Z3native.ast_vector_dec_ref ctx o +end + + +(** AST map objects *) +class ast_map ctx = +object (self) + inherit z3object ctx None + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref ctx o = Z3native.ast_map_inc_ref ctx o + method decref ctx o = Z3native.ast_map_dec_ref ctx o +end + + (** Expression objects *) class expr ctx = object(self) @@ -492,7 +595,8 @@ end (**/**) -(** Interaction logging for Z3. +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) module Log = @@ -512,7 +616,7 @@ struct let append s = Z3native.append_log s end -(** Version information. *) +(** Version information *) module Version = struct (** The major version. *) @@ -536,7 +640,7 @@ struct string_of_int rev ^ "." end -(** Symbols are used to name several term and type constructors. *) +(** Symbols are used to name several term and type constructors *) module Symbol = struct (** The kind of the symbol (int or string) *) @@ -562,9 +666,7 @@ struct end -(** - The Sort module implements type information for ASTs. -*) +(** The Sort module implements type information for ASTs *) module Sort = struct (** @@ -612,13 +714,13 @@ struct end (** Bit-vector sorts *) -module BitVectorSort = +module BitVecSort = struct (** The size of the bit-vector sort. *) let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno end -(** Finite domain sorts. *) +(** Finite domain sorts *) module FiniteDomainSort = struct (** The size of the finite domain sort. *) @@ -628,7 +730,7 @@ struct else raise (Z3native.Exception "Conversion failed.") end -(** Relation sorts. *) +(** Relation sorts *) module RelationSort = struct (** The arity of the relation sort. *) @@ -684,60 +786,60 @@ let create_ast ctx no = | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") (**/**) -(** Function declarations. *) +(** Function declarations *) module FuncDecl = struct -(** Parameters of Func_Decls *) + (** Parameters of Func_Decls *) module Parameter = struct - (** - The kind of the parameter. - *) + (** + The kind of the parameter. + *) let get_kind (x : parameter) = x#kind - (**The int value of the parameter.*) + (**The int value of the parameter.*) let get_int (x : parameter) = if (x#kind != PARAMETER_INT) then raise (Z3native.Exception "parameter is not an int") else x#int - (**The double value of the parameter.*) + (**The double value of the parameter.*) let get_double (x : parameter) = if (x#kind != PARAMETER_DOUBLE) then raise (Z3native.Exception "parameter is not a double") else x#double - (**The Symbol value of the parameter.*) + (**The Symbol value of the parameter.*) let get_symbol (x : parameter) = if (x#kind != PARAMETER_SYMBOL) then raise (Z3native.Exception "parameter is not a symbol") else x#symbol - (**The Sort value of the parameter.*) + (**The Sort value of the parameter.*) let get_sort (x : parameter) = if (x#kind != PARAMETER_SORT) then raise (Z3native.Exception "parameter is not a sort") else x#sort - (**The AST value of the parameter.*) + (**The AST value of the parameter.*) let get_ast (x : parameter) = if (x#kind != PARAMETER_AST) then raise (Z3native.Exception "parameter is not an ast") else x#ast - (**The FunctionDeclaration value of the parameter.*) + (**The FunctionDeclaration value of the parameter.*) let get_ast (x : parameter) = if (x#kind != PARAMETER_FUNC_DECL) then raise (Z3native.Exception "parameter is not an function declaration") else x#func_decl - (**The rational string value of the parameter.*) + (**The rational string value of the parameter.*) let get_rational (x : parameter) = if (x#kind != PARAMETER_RATIONAL) then raise (Z3native.Exception "parameter is not a ratinoal string") @@ -826,7 +928,7 @@ struct (** Create expression that applies function to arguments. - + @param args The arguments *) let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args @@ -862,7 +964,7 @@ struct Array.init n f end -(** Enumeration sorts. *) +(** Enumeration sorts *) module EnumSort = struct (** The function declarations of the constants in the enumeration. *) @@ -876,7 +978,7 @@ struct Array.map f x#tester_decls end -(** List sorts. *) +(** List sorts *) module ListSort = struct (** The declaration of the nil function of this list sort. *) @@ -901,6 +1003,7 @@ struct let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] end +(** Tuple sorts *) module TupleSort = struct (** The constructor function of the tuple.*) @@ -917,7 +1020,7 @@ struct Array.init n f end -(** The abstract syntax tree (AST) module. *) +(** The abstract syntax tree (AST) module *) module AST = struct (** @@ -1077,12 +1180,107 @@ struct let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end +(** Vectors of ASTs *) +module ASTVector = +struct + (** The size of the vector *) + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size x#gnc x#gno + + (** + Retrieves the i-th object in the vector. + @param i Index + @return An AST + *) + let get ( x : ast_vector ) ( i : int ) = + create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + + (** Sets the i-th object in the vector. *) + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set x#gnc x#gno i value#gno + + (** Resize the vector to . + @param newSize The new size of the vector. *) + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize x#gnc x#gno new_size + + (** + Add the AST to the back of the vector. The size + is increased by 1. + @param a An AST + *) + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push x#gnc x#gno a#gno + + (** + Translates all ASTs in the vector to . + @param to_ctx A context + @return A new ASTVector + *) + let translate ( x : ast_vector ) ( to_ctx : context ) = + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + + (** Retrieves a string representation of the vector. *) + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string x#gnc x#gno +end + +(** Map from AST to AST *) +module ASTMap = +struct + (** Checks whether the map contains the key . + @param k An AST + @return True if is a key in the map, false otherwise. *) + let contains ( m : ast_map ) ( key : ast ) = + (int2lbool (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + + (** Finds the value associated with the key . + + This function signs an error when is not a key in the map. + + @param k An AST + *) + let find ( m : ast_map ) ( key : ast ) = + create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + + (** + Stores or replaces a new key/value pair in the map. + @param k The key AST + @param v The value AST + *) + let insert ( m : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + + (** + Erases the key from the map. + @param k An AST + *) + let erase ( m : ast_map ) ( key : ast ) = + Z3native.ast_map_erase m#gnc m#gno key#gno + + (** Removes all keys from the map. *) + let reset ( m : ast_map ) = + Z3native.ast_map_reset m#gnc m#gno + + (** The size of the map *) + let get_size ( m : ast_map ) = + Z3native.ast_map_size m#gnc m#gno + + (** The keys stored in the map. *) + let get_keys ( m : ast_map ) = + (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + + (** Retrieves a string representation of the map.*) + let to_strnig ( m : ast_map ) = + Z3native.ast_map_to_string m#gnc m#gno +end + (** Expressions (terms) *) module Expr = struct (** Returns a simplified version of the expression. - A set of parameters to configure the simplifier + @param p A set of parameters to configure the simplifier *) let simplify ( x : expr ) ( p : params option ) = match p with @@ -1155,8 +1353,8 @@ struct (** Translates (copies) the term to the Context . - A context - A copy of the term which is associated with + @param ctx A context + @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = if x#gc == to_ctx then @@ -1176,7 +1374,7 @@ struct (** Indicates whether the term is well-sorted. - True if the term is well-sorted, false otherwise. + @return True if the term is well-sorted, false otherwise. *) let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE @@ -2372,13 +2570,13 @@ struct Z3native.get_index_value x#gnc x#gno end -(* Integer Numerals *) +(** Integer Numerals *) module IntNum = struct (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -2410,9 +2608,9 @@ module BitVecNum = struct (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") - + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno end @@ -2424,9 +2622,8 @@ struct Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^. - - the precision of the result - A numeral Expr of sort Real + @param precision the precision of the result + @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) @@ -2435,9 +2632,8 @@ struct Return a lower bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^. - - - A numeral Expr of sort Real + @param precision the precision of the result + @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) @@ -2450,8 +2646,24 @@ struct (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno end + +(** Constructors are used for datatype sorts *) +module Constructor = +struct + (** The number of fields of the constructor. *) + let get_num_fields ( x : constructor ) = x#get_n + + (** The function declaration of the constructor. *) + let get_constructor_decl ( x : constructor ) = x#constructor_decl + + (** The function declaration of the tester. *) + let get_tester_decl ( x : constructor ) = x#tester_decl + + (** The function declarations of the accessors *) + let get_accessor_decls ( x : constructor ) = x#accessor_decls +end -(** The main interaction with Z3 happens via the Context module. *) +(** The main interaction with Z3 happens via the Context module *) module Context = struct @@ -2551,151 +2763,95 @@ struct (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) ) - (** - Create a new list sort. - *) + (** + Create a new list sort. + *) let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort + (new list_sort ctx)#cnstr_ss name elem_sort - (** - Create a new list sort. - *) + (** + Create a new list sort. + *) let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort - (** - Create a new finite domain sort. - *) + (** + Create a new finite domain sort. + *) let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = (new finite_domain_sort ctx)#cnstr_si name size - (** - Create a new finite domain sort. - *) + (** + Create a new finite domain sort. + *) let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size -(** - -(* DATATYPES *) -(** - Create a datatype constructor. -*) - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - public Constructor MkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) - { + (* DATATYPES *) + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + mk_constructor ctx ((mk_symbol_string ctx name) :> symbol) recognizer field_names sorts sort_refs - return new Constructor(this, name, recognizer, fieldNames, sorts, sortRefs); - } + (** + Create a new datatype sort. + *) + let mk_datatype_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + (new datatype_sort ctx)#cnstr_sc name constructors + + (** + Create a new datatype sort. + *) + let mk_datatype_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + mk_datatype_sort ctx ((mk_symbol_string ctx name) :> symbol) constructors + + (** + Create mutually recursive datatypes. + @param names names of datatype sorts + @param c list of constructors, one list per sort. + *) + let mk_datatype_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let n = (Array.length names) in + let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let cla = (Array.map f c) in + let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + (Array.map g r) + + (** Create mutually recursive data-types. *) + let mk_datatype_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + mk_datatype_sorts ctx + ( + let f e = ((mk_symbol_string ctx e) :> symbol) in + Array.map f names + ) + c (** - Create a datatype constructor. -*) - @param name - @param recognizer - @param fieldNames - @param sorts - @param sortRefs - @return - public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) - { - - - return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs); - } - -(** - Create a new datatype sort. -*) - let mk_Datatype_Sort(Symbol name, Constructor[] constructors) - { - - - - - - - CheckContextMatch(name); - CheckContextMatch(constructors); - return new DatatypeSort(this, name, constructors); - } - -(** - Create a new datatype sort. -*) - let mk_Datatype_Sort(string name, Constructor[] constructors) - { - - - - - CheckContextMatch(constructors); - return new DatatypeSort(this, MkSymbol(name), constructors); - } - -(** - Create mutually recursive datatypes. -*) - @param names names of datatype sorts - @param c list of constructors, one list per sort. - let mk_Datatype_Sorts(Symbol[] names, Constructor[][] c) - { - - - - - - - - CheckContextMatch(names); - uint n = (uint)names.Length; - ConstructorList[] cla = new ConstructorList[n]; - IntPtr[] n_constr = new IntPtr[n]; - for (uint i = 0; i < n; i++) - { - Constructor[] constructor = c[i]; - - CheckContextMatch(constructor); - cla[i] = new ConstructorList(this, constructor); - n_constr[i] = cla[i].x#gno; - } - IntPtr[] n_res = new IntPtr[n]; - Z3native.mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); - DatatypeSort[] res = new DatatypeSort[n]; - for (uint i = 0; i < n; i++) - res[i] = new DatatypeSort(this, n_res[i]); - return res; - } - -(** - Create mutually recursive data-types. -*) - @param names - @param c - @return - let mk_Datatype_Sorts(string[] names, Constructor[][] c) - { - - - - - - - - return MkDatatypeSorts(MkSymbols(names), c); - } - - (* FUNCTION DECLARATIONS *) From d6a2048785d3ad803c6af74fd632fab736fb53ef Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 21:06:13 +0000 Subject: [PATCH 270/646] More new ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 +- scripts/update_api.py | 11 +- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 1025 +++++++++++++++++++++++++++++++++++------ 4 files changed, 901 insertions(+), 141 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 68493b7b6..9b5ab1a7a 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2680,13 +2680,13 @@ def mk_z3consts_ml(api_files): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) - efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ + efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') efile.write('(** Convert int to %s*)\n' % name[3:]) - efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ + efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %d -> %s\n' % (i, k[3:])) diff --git a/scripts/update_api.py b/scripts/update_api.py index c3f2abce6..27f7dd507 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1154,7 +1154,9 @@ def mk_ml(): for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) - ml_native.write('\nexception Exception of string\n\n') + ml_native.write('\nexternal is_null : ptr -> bool\n') + ml_native.write(' = "n_is_null"\n\n') + ml_native.write('exception Exception of string\n\n') # ML declarations ml_native.write(' module ML2C = struct\n\n') @@ -1219,9 +1221,9 @@ def mk_ml(): i = i + 1 ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' let err = (error_code_of_int (ML2C.n_get_error_code a0)) in \n') ml_native.write(' if err <> OK then\n') - ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (int_of_error_code err)))\n') ml_native.write(' else\n') if result == VOID and len(op) == 0: ml_native.write(' ()\n') @@ -1290,6 +1292,9 @@ def mk_ml(): ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') + ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') + ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index 4d4a6c08f..ad5442327 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml *.ml -hide Z3 + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.ml -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 116d7a230..c22ef869b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -9,9 +9,6 @@ open Z3enums (**/**) -(* Object definitions. These are internal and should be interacted - with only via the corresponding functions from modules. *) - class virtual idisposable = object method virtual dispose : unit @@ -106,8 +103,8 @@ end class params ctx obj = object (self) inherit z3object ctx obj as super - method incref ctx o = Z3native.params_inc_ref ctx o - method decref ctx o = Z3native.params_dec_ref ctx o + method incref nc o = Z3native.params_inc_ref nc o + method decref nc o = Z3native.params_dec_ref nc o end (** Symbol objects *) @@ -115,8 +112,8 @@ class symbol ctx = object (self) inherit z3object ctx None as super method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () end let symbolaton (a : symbol array) = @@ -140,7 +137,7 @@ object(self) end let create_symbol ctx no = - match (int2symbol_kind (Z3native.get_symbol_kind ctx#gno no)) with + match (symbol_kind_of_int (Z3native.get_symbol_kind ctx#gno no)) with | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) @@ -198,29 +195,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** Enum sort objects *) -class enum_sort ctx = -object (self) - inherit sort ctx as super - val mutable _constdecls : Z3native.ptr array option = None - val mutable _testerdecls : Z3native.ptr array option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in - _constdecls <- Some a ; - _testerdecls <- Some b ; - (self#sno ctx r) ; - self - - method const_decls = match _constdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing const decls") - - method tester_decls = match _testerdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tester decls") -end - (** Int sort objects *) class int_sort ctx = object (self) @@ -258,54 +232,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** List sort objects *) -class list_sort ctx = -object (self) - inherit sort ctx as super - val mutable _nildecl : Z3native.ptr option = None - val mutable _is_nildecl : Z3native.ptr option = None - val mutable _consdecl : Z3native.ptr option = None - val mutable _is_consdecl : Z3native.ptr option = None - val mutable _headdecl : Z3native.ptr option = None - val mutable _taildecl : Z3native.ptr option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in - _nildecl <- Some a ; - _is_nildecl <- Some b ; - _consdecl <- Some c ; - _is_consdecl <- Some d ; - _headdecl <- Some e ; - _taildecl <- Some f ; - (self#sno ctx r) ; - self - - method nil_decl = match _nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing nil decl") - - method is_nil_decl = match _is_nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decl") - - method cons_decl = match _consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decl") - - method is_cons_decl = match _is_consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decl") - - method head_decl = match _headdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decl") - - method tail_decl = match _taildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decl") - -end - (** Set sort objects *) class set_sort ctx = object (self) @@ -376,6 +302,76 @@ object (self) end +(** Enum sort objects *) +class enum_sort ctx = +object (self) + inherit sort ctx as super + val mutable _constdecls : func_decl array option = None + val mutable _testerdecls : func_decl array option = None + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ss (name : symbol) (enum_names : symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; + _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; + (self#sno ctx r) ; + self + + method const_decls = match _constdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing const decls") + + method tester_decls = match _testerdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tester decls") +end + +(** List sort objects *) +class list_sort ctx = +object (self) + inherit sort ctx as super + val mutable _nildecl : func_decl option = None + val mutable _is_nildecl : func_decl option = None + val mutable _consdecl : func_decl option = None + val mutable _is_consdecl : func_decl option = None + val mutable _headdecl : func_decl option = None + val mutable _taildecl : func_decl option = None + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ss (name : symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; + _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; + _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; + _is_consdecl <- Some ((new func_decl ctx)#cnstr_obj d) ; + _headdecl <- Some ((new func_decl ctx)#cnstr_obj e) ; + _taildecl <- Some ((new func_decl ctx)#cnstr_obj f) ; + (self#sno ctx r) ; + self + + method nil_decl = match _nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing nil decl") + + method is_nil_decl = match _is_nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_nil decl") + + method cons_decl = match _consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing cons decl") + + method is_cons_decl = match _is_consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_cons decl") + + method head_decl = match _headdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing head decl") + + method tail_decl = match _taildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tail decl") +end + (** Constructor objects *) class constructor ctx = object (self) @@ -384,8 +380,8 @@ object (self) val mutable m_tester_decl : func_decl option = None val mutable m_constructor_decl : func_decl option = None val mutable m_accessor_decls : func_decl array option = None - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () initializer let f = fun o -> Z3native.del_constructor o#gnc o#gno in let v = self in @@ -438,8 +434,8 @@ let constructoraton (a : constructor array) = class constructor_list ctx = object (self) inherit z3object ctx None - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () initializer let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in let v = self in @@ -463,7 +459,7 @@ object (self) end let create_sort ctx obj = - match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + match (sort_kind_of_int (Z3native.get_sort_kind ctx#gno obj)) with | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) @@ -480,8 +476,8 @@ class ast_vector ctx = object (self) inherit z3object ctx None method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = Z3native.ast_vector_inc_ref ctx o - method decref ctx o = Z3native.ast_vector_dec_ref ctx o + method incref nc o = Z3native.ast_vector_inc_ref nc o + method decref nc o = Z3native.ast_vector_dec_ref nc o end @@ -490,8 +486,8 @@ class ast_map ctx = object (self) inherit z3object ctx None method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = Z3native.ast_map_inc_ref ctx o - method decref ctx o = Z3native.ast_map_dec_ref ctx o + method incref nc o = Z3native.ast_map_inc_ref nc o + method decref nc o = Z3native.ast_map_dec_ref nc o end @@ -583,7 +579,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end - (** Quantifier objects *) class quantifier ctx = object (self) @@ -591,10 +586,127 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +(** Parameter description objects *) +class param_descrs ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.param_descrs_inc_ref nc o + method decref nc o = Z3native.param_descrs_dec_ref nc o +end +(** Goal objects *) +class goal ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.goal_inc_ref nc o + method decref nc o = Z3native.goal_dec_ref nc o +end + +(** Tactic objects *) +class tactic ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.tactic_inc_ref nc o + method decref nc o = Z3native.tactic_dec_ref nc o +end + +(** Function interpretation entry objects *) +class func_entry ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.func_entry_inc_ref nc o + method decref nc o = Z3native.func_entry_dec_ref nc o +end + +(** Function interpretation objects *) +class func_interp ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.func_interp_inc_ref nc o + method decref nc o = Z3native.func_interp_dec_ref nc o +end + +(** Model objects *) +class model ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.model_inc_ref nc o + method decref nc o = Z3native.model_dec_ref nc o +end + +(** Tactic application result objects *) +class apply_result ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.apply_result_inc_ref nc o + method decref nc o = Z3native.apply_result_dec_ref nc o +end + +(** Probe objects *) +class probe ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.probe_inc_ref nc o + method decref nc o = Z3native.probe_dec_ref nc o +end + +(** Statistical value objects *) +class statistics_entry = +object (self) + val mutable m_key : string = "" + val mutable m_is_int = false + val mutable m_is_float = false + val mutable m_int = 0 + val mutable m_float = 0.0 + + method cnstr_si k v = + m_key <- k; + m_is_int <- true; + m_int <- v; + self + + method cnstr_sd k v = + m_key <- k; + m_is_float <- true; + m_float <- v; + self + + method key = m_key + method int = m_int + method float = m_float + method is_int = m_is_int + method is_float = m_is_float +end + +(** Statistics objects *) +class statistics ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.stats_inc_ref nc o + method decref nc o = Z3native.stats_dec_ref nc o +end + +(** Solver objects *) +class solver ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.solver_inc_ref nc o + method decref nc o = Z3native.solver_dec_ref nc o +end (**/**) + (** Interaction logging for Z3 Note that this is a global, static log and if multiple Context @@ -606,7 +718,7 @@ struct @return True if opening the log file succeeds, false otherwise. *) (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((int2lbool (Z3native.open_log filename)) == L_TRUE) + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) (** Closes the interaction log. *) let close = Z3native.close_log @@ -644,7 +756,7 @@ end module Symbol = struct (** The kind of the symbol (int or string) *) - let kind (o : symbol) = (int2symbol_kind (Z3native.get_symbol_kind o#gnc o#gno)) + let kind (o : symbol) = (symbol_kind_of_int (Z3native.get_symbol_kind o#gnc o#gno)) (** Indicates whether the symbol is of Int kind *) let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL @@ -680,7 +792,7 @@ struct if a#gnc != b#gnc then false else - ((int2lbool (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) (** Returns a unique identifier for the sort. @@ -690,7 +802,7 @@ struct (** The kind of the sort. *) - let get_sort_kind (x : sort) = (int2sort_kind (Z3native.get_sort_kind x#gnc x#gno)) + let get_sort_kind (x : sort) = (sort_kind_of_int (Z3native.get_sort_kind x#gnc x#gno)) (** The name of the sort @@ -726,7 +838,7 @@ struct (** The size of the finite domain sort. *) let get_size (x : finite_domain_sort) = let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") end @@ -746,15 +858,15 @@ end (**/**) let create_expr ctx obj = - if int2ast_kind (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then (((new quantifier ctx)#cnstr_obj obj) :> expr) else let s = Z3native.get_sort ctx#gno obj in - let sk = (int2sort_kind (Z3native.get_sort_kind ctx#gno s)) in - if (int2lbool (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in + if (lbool_of_int (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if ((int2lbool (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + if ((lbool_of_int (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -776,7 +888,7 @@ let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = create_expr ctx o let create_ast ctx no = - match (int2ast_kind (Z3native.get_ast_kind ctx#gno no)) with + match (ast_kind_of_int (Z3native.get_ast_kind ctx#gno no)) with | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) | SORT_AST -> ((create_sort ctx no) :> ast) @@ -858,7 +970,7 @@ struct if a#gnc == a#gnc then false else - ((int2lbool (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) (** A string representations of the function declaration. *) @@ -897,7 +1009,7 @@ struct (** The kind of the function declaration. *) - let get_decl_kind (x : func_decl) = (int2decl_kind (Z3native.get_decl_kind x#gnc x#gno)) + let get_decl_kind (x : func_decl) = (decl_kind_of_int (Z3native.get_decl_kind x#gnc x#gno)) (** The name of the function declaration @@ -915,7 +1027,7 @@ struct let get_parameters (x : func_decl) = let n = (get_num_parameters x) in let f i = ( - match (int2parameter_kind (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with + match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) @@ -968,36 +1080,32 @@ end module EnumSort = struct (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = - let f e = ((new func_decl x#gc)#cnstr_obj e) in - Array.map f x#const_decls + let get_const_decls (x : enum_sort) = x#const_decls (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = - let f e = ((new func_decl x#gc)#cnstr_obj e) in - Array.map f x#tester_decls + let get_tester_decls (x : enum_sort) = x#tester_decls end (** List sorts *) module ListSort = struct (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#nil_decl + let get_nil_decl (x : list_sort) = x#nil_decl (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_nil_decl + let get_is_nil_decl (x : list_sort) = x#is_nil_decl (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#cons_decl + let get_cons_decl (x : list_sort) = x#cons_decl (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_cons_decl + let get_is_cons_decl (x : list_sort) = x#is_cons_decl (** The declaration of the head function of this list sort.*) - let get_head_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#head_decl + let get_head_decl (x : list_sort) = x#head_decl (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#tail_decl + let get_tail_decl (x : list_sort) = x#tail_decl (** The empty list. *) let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] @@ -1037,7 +1145,7 @@ struct (** The kind of the AST. *) - let get_ast_kind ( x : ast) = (int2ast_kind (Z3native.get_ast_kind x#gnc x#gno)) + let get_ast_kind ( x : ast) = (ast_kind_of_int (Z3native.get_ast_kind x#gnc x#gno)) (** Indicates whether the AST is an Expr @@ -1092,7 +1200,7 @@ struct if a#gnc == b#gnc then false else - ((int2lbool (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) (** Object Comparison. @@ -1130,7 +1238,7 @@ struct Adds a parameter setting. *) let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (lbool2int (if value then L_TRUE else L_FALSE)) + Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) (** Adds a parameter setting. @@ -1232,7 +1340,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( m : ast_map ) ( key : ast ) = - (int2lbool (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE (** Finds the value associated with the key . @@ -1296,7 +1404,7 @@ struct Indicates whether the expression is the true or false expression or something else (Z3_L_UNDEF). *) - let get_bool_value ( x : expr ) = int2lbool (Z3native.get_bool_value x#gnc x#gno) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) (** The number of arguments of the expression. @@ -1370,13 +1478,13 @@ struct (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = int2lbool (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + let is_numeral ( x : expr ) = lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + let is_well_sorted ( x : expr ) = lbool_of_int (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE (** The Sort of the term. @@ -1387,7 +1495,7 @@ struct Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (AST.is_expr x) && - (int2lbool (Z3native.is_eq_sort x#gnc + (lbool_of_int (Z3native.is_eq_sort x#gnc (Z3native.mk_bool_sort x#gnc) (Z3native.get_sort x#gnc x#gno))) == L_TRUE @@ -1395,21 +1503,21 @@ struct Indicates whether the term is of integer sort. *) let is_int ( x : expr ) = - ((int2lbool (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) (** Indicates whether the term is of sort real. *) let is_real ( x : expr ) = - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) (** Indicates whether the term is of an array sort. *) let is_array ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) (** Indicates whether the term represents a constant. @@ -1431,7 +1539,7 @@ struct (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = int2lbool(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE (** Indicates whether the term is the constant true. @@ -1634,7 +1742,7 @@ struct Indicates whether the terms is of bit-vector sort. *) let is_bv ( x : expr ) = - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral @@ -2422,8 +2530,8 @@ struct Indicates whether the term is of a relation sort. *) let is_Relation ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) (** Indicates whether the term is an relation store @@ -2536,8 +2644,8 @@ struct Indicates whether the term is of an array sort. *) let is_finite_domain ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. @@ -2575,7 +2683,7 @@ module IntNum = struct (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) @@ -2608,7 +2716,7 @@ module BitVecNum = struct (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) @@ -2662,7 +2770,654 @@ struct (** The function declarations of the accessors *) let get_accessor_decls ( x : constructor ) = x#accessor_decls end + + +(** ParamDescrs describe sets of parameters.*) +module ParamDescrs = +struct + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno + +end + +(** Goals + + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) +module Goal = +struct + + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. + *) + let get_precision ( x : goal ) = + goal_prec_of_int (Z3native.goal_precision x#gnc x#gno) + + (** Indicates whether the goal is precise. *) + let is_precise ( x : goal ) = + (get_precision x) == GOAL_PRECISE + + (** Indicates whether the goal is an under-approximation. *) + let is_underapproximation ( x : goal ) = + (get_precision x) == GOAL_UNDER + + (** Indicates whether the goal is an over-approximation. *) + let is_overapproximation ( x : goal ) = + (get_precision x) == GOAL_OVER + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) + let is_garbage ( x : goal ) = + (get_precision x) == GOAL_UNDER_OVER + + (** Adds the constraints to the given goal. *) + (* CMW: assert seems to be a keyword. *) + let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let f e = Z3native.goal_assert x#gnc x#gno e#gno in + Array.map f constraints + + (** Indicates whether the goal contains `false'. *) + let is_inconsistent ( x : goal ) = + (lbool_of_int (Z3native.goal_inconsistent x#gnc x#gno)) == L_TRUE + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) + let get_depth ( x : goal ) = Z3native.goal_depth x#gnc x#gno + + (** Erases all formulas from the given goal. *) + let reset ( x : goal ) = Z3native.goal_reset x#gnc x#gno + + (** The number of formulas in the goal. *) + let get_size ( x : goal ) = Z3native.goal_size x#gnc x#gno + + (** The formulas in the goal. *) + let get_formulas ( x : goal ) = + let n = get_size x in + let f i = (new bool_expr x#gc)#cnstr_obj (Z3native.goal_formula x#gnc x#gno i) in + Array.init n f + + (** The number of formulas, subformulas and terms in the goal. *) + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs x#gnc x#gno + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) + let is_decided_sat ( x : goal ) = + (lbool_of_int (Z3native.goal_is_decided_sat x#gnc x#gno)) == L_TRUE + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) + let is_decided_unsat ( x : goal ) = + (lbool_of_int (Z3native.goal_is_decided_unsat x#gnc x#gno)) == L_TRUE + + (** Translates (copies) the Goal to the target Context . *) + let translate ( x : goal ) ( to_ctx : context ) = + (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno to_ctx#gno) + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) + let simplify ( x : goal ) ( p : params option ) = + let tn = Z3native.mk_tactic x#gnc "simplify" in + Z3native.tactic_inc_ref x#gnc tn ; + let arn = match p with + | None -> Z3native.tactic_apply x#gnc tn x#gno + | Some(pn) -> Z3native.tactic_apply_ex x#gnc tn x#gno pn#gno + in + Z3native.apply_result_inc_ref x#gnc arn ; + let sg = Z3native.apply_result_get_num_subgoals x#gnc arn in + let res = if sg == 0 then + raise (Z3native.Exception "No subgoals") + else + Z3native.apply_result_get_subgoal x#gnc arn 0 in + Z3native.apply_result_dec_ref x#gnc arn ; + Z3native.tactic_dec_ref x#gnc tn ; + (new goal x#gc)#cnstr_obj res + + (** A string representation of the Goal. *) + let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno +end + + +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Tactic = +struct + (** A string containing a description of parameters accepted by the tactic. *) + let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno + + + (** Retrieves parameter descriptions for Tactics. *) + let get_param_descrs ( x : tactic ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.tactic_get_param_descrs x#gnc x#gno) + + (** Apply the tactic to the goal. *) + let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + match p with + | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) + | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) + + (** Creates a solver that is implemented using the given tactic. + *) + let get_solver ( x : tactic ) = + (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) + +end + + +(** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. +*) +module FuncInterp = +struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") +end + +(** Models. + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr x#gc np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl x#gnc n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in + if (lbool_of_int r) == L_FALSE then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr x#gc v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in + let n = (ASTVector.get_size n_univ) in + let f i = (ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno +end + +(** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) +module ApplyResult = +struct + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals x#gnc x#gno + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in + Array.init n f + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno +end + +(** Objects that track statistical information about solvers. *) +module Statistics = +struct + + (** + Statistical data is organized into pairs of [Key, Entry], where every + Entry is either a DoubleEntry or a UIntEntry + *) + module Entry = + struct + (** The key of the entry. *) + let get_key (x : statistics_entry) = x#key + + (** The int-value of the entry. *) + let get_int (x : statistics_entry) = x#int + + (** The float-value of the entry. *) + let get_float (x : statistics_entry) = x#float + + (** True if the entry is uint-valued. *) + let is_int (x : statistics_entry) = x#is_int + + (** True if the entry is double-valued. *) + let is_float (x : statistics_entry) = x#is_float + + (** The string representation of the the entry's value. *) + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + + (** The string representation of the entry (key and value) *) + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + (** A string representation of the statistical data. *) + let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + + (** The number of statistical data. *) + let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + + (** The data entries. *) + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key x#gnc x#gno i in + if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + else + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ) in + Array.init n f + + (** + The statistical counters. + *) + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key x#gnc x#gno i) in + Array.init n f + + (** + The value of a particular statistical counter. + *) + let get ( x : statistics ) ( key : string ) = + let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + Array.fold_left f None (get_entries x) + +end + +(** Solvers *) +module Solver = +struct + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + (** + A string that describes all available solver parameters. + *) + let get_help ( x : solver ) = Z3native.solver_get_help x#gnc x#gno + + (** + Sets the solver parameters. + *) + let set_parameters ( x : solver ) ( value : params )= + Z3native.solver_set_params x#gnc x#gno value#gno + + (** + Retrieves parameter descriptions for solver. + *) + let get_param_descrs ( x : solver ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.solver_get_param_descrs x#gnc x#gno) + + (** + The current number of backtracking points (scopes). + + + *) + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes x#gnc x#gno + + (** + Creates a backtracking point. + + *) + let push ( x : solver ) = Z3native.solver_push x#gnc x#gno + + (** + Backtracks backtracking points. + Note that an exception is thrown if is not smaller than NumScopes + + *) + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n + + (** + Resets the Solver. + This removes all assertions from the solver. + *) + let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno + + (** + Assert a constraint (or multiple) into the solver. + *) + let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in + Array.map f constraints + + (** + The number of assertions in the solver. + *) + let get_num_assertions ( x : solver ) = + let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + (ASTVector.get_size a) + + + (** + The set of asserted formulas. + *) + let get_assertions ( x : solver ) = + let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let n = (ASTVector.get_size a) in + let f i = ((new bool_expr x#gc)#cnstr_obj (ASTVector.get a i)#gno) in + Array.init n f + + (** + Checks whether the assertions in the solver are consistent or not. + + + + + + *) + let check ( x : solver ) ( assumptions : bool_expr array option) = + let r = + match assumptions with + | None -> lbool_of_int (Z3native.solver_check x#gnc x#gno) + | Some (ass) -> lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length ass) (astaton ass)) + in + match r with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN + + (** + The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. + + *) + let get_model ( x : solver ) = + let q = Z3native.solver_get_model x#gnc x#gno in + if (Z3native.is_null q) then + None + else + Some ((new model x#gc)#cnstr_obj q) + + (** + The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. + + *) + let get_proof ( x : solver ) = + let q = Z3native.solver_get_proof x#gnc x#gno in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. + + *) + let get_unsat_core ( x : solver ) = + let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in + let n = (ASTVector.get_size cn) in + let f i = (ASTVector.get cn i) in + Array.init n f + + (** + A brief justification of why the last call to Check returned UNKNOWN. + *) + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown x#gnc x#gno + + + (** + Solver statistics. + *) + let get_statistics ( x : solver ) = + (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + + (** + A string representation of the solver. + *) + let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno +end + +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = +struct + (** + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. + *) + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply x#gnc x#gno g#gno +end + + (** The main interaction with Z3 happens via the Context module *) module Context = struct From 3684b3a87d438d0bd989752ad69268bbf9f37c51 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 23 Dec 2012 02:20:24 +0000 Subject: [PATCH 271/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 6488 +++++++++++++++++++--------------------------- 1 file changed, 2629 insertions(+), 3859 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c22ef869b..5f67e11e2 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -586,6 +586,13 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +(** Quantifier pattern objects *) +class pattern ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self +end + (** Parameter description objects *) class param_descrs ctx = object (self) @@ -775,6 +782,33 @@ struct match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) + + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_int ( ctx : context ) i = + (new int_symbol ctx)#cnstr_int i + + (** Creates a new symbol using a string. *) + let mk_string ( ctx : context ) s = + (new string_symbol ctx)#cnstr_string s + + (** + Create an array of symbols. + *) + let mk_ints ( ctx : context ) ( names : int array ) = + let f elem = mk_int ( ctx : context ) elem in + (Array.map f names) + + (** + Create an array of symbols. + *) + let mk_strings ( ctx : context ) ( names : string array ) = + let f elem = mk_string ( ctx : context ) elem in + (Array.map f names) end @@ -813,49 +847,26 @@ struct A string representation of the sort. *) let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno + + (** + Create a new Boolean sort. + *) + let mk_bool ( ctx : context ) = + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted ( ctx : context ) (s : symbol) = + (new uninterpreted_sort ctx)#cnstr_s s + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_s ( ctx : context ) (s : string) = + mk_uninterpreted ctx ((Symbol.mk_string ( ctx : context ) s) :> symbol) end -(** Array sorts *) -module ArraySort = -struct - (** The domain of the array sort. *) - let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) - - (** The range of the array sort. *) - let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) -end - -(** Bit-vector sorts *) -module BitVecSort = -struct - (** The size of the bit-vector sort. *) - let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno -end - -(** Finite domain sorts *) -module FiniteDomainSort = -struct - (** The size of the finite domain sort. *) - let get_size (x : finite_domain_sort) = - let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") -end - -(** Relation sorts *) -module RelationSort = -struct - (** The arity of the relation sort. *) - let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno - - (** The sorts of the columns of the relation sort. *) - let get_column_sorts (x : relation_sort) = - let n = get_arity x in - let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in - Array.init n f - -end - (**/**) let create_expr ctx obj = if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then @@ -957,6 +968,48 @@ struct raise (Z3native.Exception "parameter is not a ratinoal string") else x#rational + + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name domain range + + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = + mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix domain range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name [||] range + + + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix [||] range + end (** @@ -1046,91 +1099,103 @@ struct end -(** Datatype sorts *) -module DatatypeSort = -struct - (** The number of constructors of the datatype sort. *) - let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno - - (** The range of the array sort. *) - let get_constructors (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in - Array.init n f - - (** The recognizers. *) - let get_recognizers (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in - Array.init n f - - (** The constructor accessors. *) - let get_accessors (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = ( - let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in - let ds = (Z3native.get_domain_size fd#gnc fd#gno) in - let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in - Array.init ds g - ) in - Array.init n f -end - -(** Enumeration sorts *) -module EnumSort = -struct - (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = x#const_decls - - (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = x#tester_decls -end - -(** List sorts *) -module ListSort = -struct - (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = x#nil_decl - - (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = x#is_nil_decl - - (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = x#cons_decl - - (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = x#is_cons_decl - - (** The declaration of the head function of this list sort.*) - let get_head_decl (x : list_sort) = x#head_decl - - (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = x#tail_decl - - (** The empty list. *) - let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] -end - -(** Tuple sorts *) -module TupleSort = -struct - (** The constructor function of the tuple.*) - let get_mk_decl (x : tuple_sort) = - (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) - - (** The number of fields in the tuple. *) - let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno - - (** The field declarations. *) - let get_field_decls (x : tuple_sort) = - let n = get_num_fields x in - let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in - Array.init n f -end - (** The abstract syntax tree (AST) module *) module AST = struct + (** Vectors of ASTs *) + module ASTVector = + struct + (** The size of the vector *) + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size x#gnc x#gno + + (** + Retrieves the i-th object in the vector. + @param i Index + @return An AST + *) + let get ( x : ast_vector ) ( i : int ) = + create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + + (** Sets the i-th object in the vector. *) + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set x#gnc x#gno i value#gno + + (** Resize the vector to . + @param newSize The new size of the vector. *) + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize x#gnc x#gno new_size + + (** + Add the AST to the back of the vector. The size + is increased by 1. + @param a An AST + *) + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push x#gnc x#gno a#gno + + (** + Translates all ASTs in the vector to . + @param to_ctx A context + @return A new ASTVector + *) + let translate ( x : ast_vector ) ( to_ctx : context ) = + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + + (** Retrieves a string representation of the vector. *) + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string x#gnc x#gno + end + + (** Map from AST to AST *) + module ASTMap = + struct + (** Checks whether the map contains the key . + @param k An AST + @return True if is a key in the map, false otherwise. *) + let contains ( m : ast_map ) ( key : ast ) = + (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + + (** Finds the value associated with the key . + + This function signs an error when is not a key in the map. + @param k An AST + *) + let find ( m : ast_map ) ( key : ast ) = + create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + + (** + Stores or replaces a new key/value pair in the map. + @param k The key AST + @param v The value AST + *) + let insert ( m : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + + (** + Erases the key from the map. + @param k An AST + *) + let erase ( m : ast_map ) ( key : ast ) = + Z3native.ast_map_erase m#gnc m#gno key#gno + + (** Removes all keys from the map. *) + let reset ( m : ast_map ) = + Z3native.ast_map_reset m#gnc m#gno + + (** The size of the map *) + let get_size ( m : ast_map ) = + Z3native.ast_map_size m#gnc m#gno + + (** The keys stored in the map. *) + let get_keys ( m : ast_map ) = + (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + + (** Retrieves a string representation of the map.*) + let to_strnig ( m : ast_map ) = + Z3native.ast_map_to_string m#gnc m#gno + end + (** The AST's hash code. @return A hash code @@ -1159,7 +1224,7 @@ struct | _ -> false (** - Indicates whether the AST is a BoundVariable + Indicates whether the AST is a bound variable *) let is_var ( x : ast) = (get_ast_kind x) == VAR_AST @@ -1227,163 +1292,7 @@ struct (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) end -(** - Parameter sets - - A Params objects represents a configuration in the form of Symbol/value pairs. -*) -module Params = -struct - (** - Adds a parameter setting. - *) - let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) - - (** - Adds a parameter setting. - *) - let add_int (p : params) (name : symbol) (value : int) = - Z3native.params_set_uint p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_double (p : params) (name : symbol) (value : float) = - Z3native.params_set_double p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_symbol (p : params) (name : symbol) (value : symbol) = - Z3native.params_set_symbol p#gnc p#gno name#gno value#gno - - (** - Adds a parameter setting. - *) - let add_s_bool (p : params) (name : string) (value : bool) = - add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_int (p : params) (name : string) (value : int) = - add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_double (p : params) (name : string) (value : float) = - add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_symbol (p : params) (name : string) (value : symbol) = - add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - A string representation of the parameter set. - *) - let to_string (p : params) = Z3native.params_to_string p#gnc p#gno -end - -(** Vectors of ASTs *) -module ASTVector = -struct - (** The size of the vector *) - let get_size ( x : ast_vector ) = - Z3native.ast_vector_size x#gnc x#gno - - (** - Retrieves the i-th object in the vector. - @param i Index - @return An AST - *) - let get ( x : ast_vector ) ( i : int ) = - create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) - - (** Sets the i-th object in the vector. *) - let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set x#gnc x#gno i value#gno - - (** Resize the vector to . - @param newSize The new size of the vector. *) - let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize x#gnc x#gno new_size - - (** - Add the AST to the back of the vector. The size - is increased by 1. - @param a An AST - *) - let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push x#gnc x#gno a#gno - - (** - Translates all ASTs in the vector to . - @param to_ctx A context - @return A new ASTVector - *) - let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) - - (** Retrieves a string representation of the vector. *) - let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string x#gnc x#gno -end - -(** Map from AST to AST *) -module ASTMap = -struct - (** Checks whether the map contains the key . - @param k An AST - @return True if is a key in the map, false otherwise. *) - let contains ( m : ast_map ) ( key : ast ) = - (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE - - (** Finds the value associated with the key . - - This function signs an error when is not a key in the map. - - @param k An AST - *) - let find ( m : ast_map ) ( key : ast ) = - create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) - - (** - Stores or replaces a new key/value pair in the map. - @param k The key AST - @param v The value AST - *) - let insert ( m : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert m#gnc m#gno key#gno value#gno - - (** - Erases the key from the map. - @param k An AST - *) - let erase ( m : ast_map ) ( key : ast ) = - Z3native.ast_map_erase m#gnc m#gno key#gno - - (** Removes all keys from the map. *) - let reset ( m : ast_map ) = - Z3native.ast_map_reset m#gnc m#gno - - (** The size of the map *) - let get_size ( m : ast_map ) = - Z3native.ast_map_size m#gnc m#gno - - (** The keys stored in the map. *) - let get_keys ( m : ast_map ) = - (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) - - (** Retrieves a string representation of the map.*) - let to_strnig ( m : ast_map ) = - Z3native.ast_map_to_string m#gnc m#gno -end - -(** Expressions (terms) *) +(** General expressions (terms), including Boolean logic *) module Expr = struct (** @@ -1402,7 +1311,7 @@ struct (** Indicates whether the expression is the true or false expression - or something else (Z3_L_UNDEF). + or something else (L_UNDEF). *) let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) @@ -1434,7 +1343,6 @@ struct The result is the new expression. The arrays from and to must have size num_exprs. For every i smaller than num_exprs, we must have that sort of from[i] must be equal to sort of to[i]. - *) let substitute ( x : expr ) from to_ = if (Array.length from) <> (Array.length to_) then @@ -1453,7 +1361,6 @@ struct Substitute the free variables in the expression with the expressions in For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. - *) let substitute_vars ( x : expr ) to_ = create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) @@ -1496,28 +1403,8 @@ struct *) let is_bool ( x : expr ) = (AST.is_expr x) && (lbool_of_int (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno))) == L_TRUE - - (** - Indicates whether the term is of integer sort. - *) - let is_int ( x : expr ) = - ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) - - (** - Indicates whether the term is of sort real. - *) - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) - - (** - Indicates whether the term is of an array sort. - *) - let is_array ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno))) == L_TRUE (** Indicates whether the term represents a constant. @@ -1526,21 +1413,6 @@ struct (get_num_args x) == 0 && FuncDecl.get_domain_size(get_func_decl x) == 0 - (** - Indicates whether the term is an integer numeral. - *) - let is_int_numeral ( x : expr ) = (is_numeral x) && (is_int x) - - (** - Indicates whether the term is a real numeral. - *) - let is_rat_num ( x : expr ) = (is_numeral x) && (is_real x) - - (** - Indicates whether the term is an algebraic number - *) - let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE - (** Indicates whether the term is the constant true. *) @@ -1597,146 +1469,1189 @@ struct let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) (** - Indicates whether the term is an arithmetic numeral. + Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ANUM) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) (** - Indicates whether the term is a less-than-or-equal + Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LE) (** - Indicates whether the term is a greater-than-or-equal + Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GE) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) (** - Indicates whether the term is a less-than + Creates a new Constant of sort and named . *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LT) + let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + create_expr ctx (Z3native.mk_const ctx#gno name#gno range#gno) + (** - Indicates whether the term is a greater-than + Creates a new Constant of sort and named . *) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GT) + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) range + (** - Indicates whether the term is addition (binary) + Creates a constant from the func_decl . + @param f An expression of a 0-arity function *) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ADD) + let mk_const_f ( ctx : context ) ( f : func_decl ) = + create_expr_fa ctx f [||] (** - Indicates whether the term is subtraction (binary) + Creates a fresh constant of sort and a + name prefixed with . *) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SUB) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = + create_expr ctx (Z3native.mk_fresh_const ctx#gno prefix range#gno) (** - Indicates whether the term is a unary minus - *) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UMINUS) + Create a Boolean constant. + *) + let mk_bool_const ( ctx : context ) ( name : symbol ) = + ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) + + (** + Create a Boolean constant. + *) + let mk_bool_const_s ( ctx : context ) ( name : string ) = + mk_bool_const ctx ((Symbol.mk_string ctx name) :> symbol) (** - Indicates whether the term is multiplication (binary) + Create a new function application. *) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MUL) + let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = + create_expr_fa ctx f args (** - Indicates whether the term is division (binary) - *) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DIV) + The true Term. + *) + let mk_true ( ctx : context ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_true ctx#gno) (** - Indicates whether the term is integer division (binary) - *) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IDIV) + The false Term. + *) + let mk_false ( ctx : context ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_false ctx#gno) (** - Indicates whether the term is remainder (binary) - *) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REM) + Creates a Boolean value. + *) + let mk_bool ( ctx : context ) ( value : bool) = + if value then mk_true ctx else mk_false ctx (** - Indicates whether the term is modulus (binary) + Creates the equality = . *) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MOD) + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq ctx#gno x#gno y#gno) (** - Indicates whether the term is a coercion of integer to real (unary) + Creates a distinct term. *) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_REAL) + let mk_distinct ( ctx : context ) ( args : expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct ctx#gno (Array.length args) (astaton args)) + + (** + Mk an expression representing not(a). + *) + let mk_not ( ctx : context ) ( a : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_not ctx#gno a#gno) + + (** + Create an expression representing an if-then-else: ite(t1, t2, t3). + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + *) + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + create_expr ctx (Z3native.mk_ite ctx#gno t1#gno t2#gno t3#gno) + + (** + Create an expression representing t1 iff t2. + *) + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff ctx#gno t1#gno t2#gno) (** - Indicates whether the term is a coercion of real to integer (unary) + Create an expression representing t1 -> t2. *) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_INT) + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies ctx#gno t1#gno t2#gno) (** - Indicates whether the term is a check that tests whether a real is integral (unary) + Create an expression representing t1 xor t2. *) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IS_INT) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor ctx#gno t1#gno t2#gno) + + (** + Create an expression representing the AND of args + *) + let mk_and ( ctx : context ) ( args : bool_expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_and ctx#gno (Array.length args) (astaton args)) + + (** + Create an expression representing the OR of args + *) + let mk_or ( ctx : context ) ( args : bool_expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) +end + +(** Functions to manipulate Array expressions *) +module Arrays = +struct + (** + Create a new array sort. + *) + let mk_sort ( ctx : context ) domain range = + (new array_sort ctx)#cnstr_dr domain range (** Indicates whether the term is an array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. + Array store takes at least 3 arguments. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. + For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the - function passed as parameter. + function passed as parameter. *) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + (** + Indicates whether the term is of an array sort. + *) + let is_array ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + + (** The domain of the array sort. *) + let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + + (** The range of the array sort. *) + let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) + + + (** + Create an array constant. + *) + let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) + + (** + Create an array constant. + *) + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) domain range + + (** + Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + + + *) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + ((create_expr ctx (Z3native.mk_select ctx#gno a#gno i#gno)) :> array_expr) + + (** + Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + + + *) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = + (new array_expr ctx)#cnstr_obj (Z3native.mk_store ctx#gno a#gno i#gno v#gno) + + (** + Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + + + *) + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array ctx#gno domain#gno v#gno) + + (** + Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + + + + *) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + ((create_expr ctx (Z3native.mk_map ctx#gno f#gno (Array.length args) (astaton args))) :> array_expr) + + (** + Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. + *) + let mk_term_array ( ctx : context ) ( arg : array_expr ) = + ((create_expr ctx (Z3native.mk_array_default ctx#gno arg#gno)) :> array_expr) +end + +(** Functions to manipulate Set expressions *) +module Sets = +struct (** Indicates whether the term is set union *) - let is_set_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_set_intersect ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_set_difference ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_set_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_set_subset ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + +(** + Create a set type. +*) +let mk_sort ( ctx : context ) ( ty : sort) = + (new set_sort ctx)#cnstr_s ty + +(** + Create an empty set. +*) +let mk_empty ( ctx : context ) ( domain : sort ) = + (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + + (** + Create the full set. + *) +let mk_full ( ctx : context ) ( domain : sort ) = + create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + +(** + Add an element to the set. +*) +let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + + (** + Remove an element from a set. + *) +let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + + (** + Take the union of a list of sets. + *) +let mk_union ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + +(** + Take the intersection of a list of sets. +*) +let mk_intersection ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + +(** + Take the difference between two sets. +*) +let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + +(** + Take the complement of a set. +*) +let mk_complement ( ctx : context ) ( arg : expr ) = + create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + +(** + Check for set membership. +*) +let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + + (** + Check for subsetness of sets. + *) +let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + +end + +(** Functions to manipulate Finite Domain expressions *) +module FiniteDomains = +struct + (** + Create a new finite domain sort. + *) + let mk_sort ( ctx : context ) ( name : symbol ) size = + (new finite_domain_sort ctx)#cnstr_si name size + + (** + Create a new finite domain sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) size = + (new finite_domain_sort ctx)#cnstr_si ((Symbol.mk_string ctx name) :> symbol) size + + + (** + Indicates whether the term is of an array sort. + *) + let is_finite_domain ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + + (** + Indicates whether the term is a less than predicate over a finite domain. + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + + (** The size of the finite domain sort. *) + let get_size (x : finite_domain_sort) = + let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") +end + +(** Functions to manipulate Relation expressions *) +module Relations = +struct + (** + Indicates whether the term is of a relation sort. + *) + let is_relation ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + + (** + Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. + *) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + + (** + Indicates whether the term is an empty relation + *) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + + (** + Indicates whether the term is a test for the emptiness of a relation + *) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + + (** + Indicates whether the term is a relational join + *) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + + (** + Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. + *) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + + (** + Indicates whether the term is the widening of two relations + The function takes two arguments. + *) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + + (** + Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. + *) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + + (** + Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. + *) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + + (** + Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. + *) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + + (** + Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. + *) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + + (** + Indicates whether the term is the complement of a relation + *) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + + (** + Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. + *) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + + (** + Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind + to perform destructive updates to the first argument. + *) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + + (** The arity of the relation sort. *) + let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + + (** The sorts of the columns of the relation sort. *) + let get_column_sorts (x : relation_sort) = + let n = get_arity x in + let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + Array.init n f + +end + +(** Quantifier expressions *) +module Quantifiers = +struct + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Pattern = + struct + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms x#gnc x#gno + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + end + + (** + Indicates whether the quantifier is universal. + *) + let is_universal ( x : quantifier ) = + lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + + (** + Indicates whether the quantifier is existential. + *) + let is_existential ( x : quantifier ) = not (is_universal x) + + (** + The weight of the quantifier. + *) + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + + (** + The number of patterns. + *) + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + + (** + The patterns. + *) + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of no-patterns. + *) + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + + (** + The no-patterns. + *) + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of bound variables. + *) + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + + (** + The symbols for the bound variables. + *) + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + Array.init n f + + (** + The sorts of the bound variables. + *) + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + Array.init n f + + (** + The body of the quantifier. + *) + let get_body ( x : quantifier ) = + (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + + (** + Creates a new bound variable. + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + *) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + + (** + Create a quantifier pattern. + *) + let mk_pattern ( ctx : context ) ( terms : expr array ) = + if (Array.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) +end + +(** Functions to manipulate Datatype expressions *) +module Datatypes = +struct + (** Constructors *) + module Constructor = + struct + (** The number of fields of the constructor. *) + let get_num_fields ( x : constructor ) = x#get_n + + (** The function declaration of the constructor. *) + let get_constructor_decl ( x : constructor ) = x#constructor_decl + + (** The function declaration of the tester. *) + let get_tester_decl ( x : constructor ) = x#tester_decl + + (** The function declarations of the accessors *) + let get_accessor_decls ( x : constructor ) = x#accessor_decls + end + + (* DATATYPES *) + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + + + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + mk_constructor ctx ((Symbol.mk_string ctx name) :> symbol) recognizer field_names sorts sort_refs + + + (** + Create a new datatype sort. + *) + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + (new datatype_sort ctx)#cnstr_sc name constructors + + (** + Create a new datatype sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) constructors + + (** + Create mutually recursive datatypes. + @param names names of datatype sorts + @param c list of constructors, one list per sort. + *) + let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let n = (Array.length names) in + let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let cla = (Array.map f c) in + let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + (Array.map g r) + + (** Create mutually recursive data-types. *) + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + mk_sorts ctx + ( + let f e = ((Symbol.mk_string ctx e) :> symbol) in + Array.map f names + ) + c + + (** The number of constructors of the datatype sort. *) + let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + + (** The range of the array sort. *) + let get_constructors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + Array.init n f + + (** The recognizers. *) + let get_recognizers (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + Array.init n f + + (** The constructor accessors. *) + let get_accessors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = ( + let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in + let ds = (Z3native.get_domain_size fd#gnc fd#gno) in + let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + Array.init ds g + ) in + Array.init n f +end + +(** Functions to manipulate Enumeration expressions *) +module Enumerations = +struct + (** + Create a new enumeration sort. + *) + let mk_sort ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss name enum_names + + (** + Create a new enumeration sort. + *) + let mk_sort_s ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss + ((Symbol.mk_string ( ctx : context ) name) :> symbol) + (let f e = (e :> symbol) in + (Array.map f (Symbol.mk_strings ( ctx : context ) enum_names)) + ) + + (** The function declarations of the constants in the enumeration. *) + let get_const_decls (x : enum_sort) = x#const_decls + + (** The test predicates for the constants in the enumeration. *) + let get_tester_decls (x : enum_sort) = x#tester_decls +end + +(** Functions to manipulate List expressions *) +module Lists = +struct + (** + Create a new list sort. + *) + let mk_sort ( ctx : context ) (name : symbol) elem_sort = + (new list_sort ctx)#cnstr_ss name elem_sort + + (** + Create a new list sort. + *) + let mk_list_s ( ctx : context ) (name : string) elem_sort = + mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) elem_sort + + + (** The declaration of the nil function of this list sort. *) + let get_nil_decl (x : list_sort) = x#nil_decl + + (** The declaration of the isNil function of this list sort. *) + let get_is_nil_decl (x : list_sort) = x#is_nil_decl + + (** The declaration of the cons function of this list sort. *) + let get_cons_decl (x : list_sort) = x#cons_decl + + (** The declaration of the isCons function of this list sort. *) + let get_is_cons_decl (x : list_sort) = x#is_cons_decl + + (** The declaration of the head function of this list sort. *) + let get_head_decl (x : list_sort) = x#head_decl + + (** The declaration of the tail function of this list sort. *) + let get_tail_decl (x : list_sort) = x#tail_decl + + (** The empty list. *) + let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] +end + +(** Functions to manipulate Tuple expressions *) +module Tuples = +struct + (** + Create a new tuple sort. + *) + let mk_sort ( ctx : context ) name field_names field_sorts = + (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts + + (** The constructor function of the tuple. *) + let get_mk_decl (x : tuple_sort) = + (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + + (** The number of fields in the tuple. *) + let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + + (** The field declarations. *) + let get_field_decls (x : tuple_sort) = + let n = get_num_fields x in + let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + Array.init n f +end + +(** Functions to manipulate arithmetic expressions *) +module Arithmetic = +struct + (** + Create a new integer sort. + *) + let mk_int_sort ( ctx : context ) = + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) + + (** + Create a real sort. + *) + let mk_real_sort ( ctx : context ) = + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) + + (** + Indicates whether the term is of integer sort. + *) + let is_int ( x : expr ) = + ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + + (** + Indicates whether the term is an arithmetic numeral. + *) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + (** + Indicates whether the term is a less-than-or-equal + *) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + (** + Indicates whether the term is a greater-than-or-equal + *) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + (** + Indicates whether the term is a less-than + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + (** + Indicates whether the term is a greater-than + *) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + (** + Indicates whether the term is addition (binary) + *) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + (** + Indicates whether the term is subtraction (binary) + *) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + (** + Indicates whether the term is a unary minus + *) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + (** + Indicates whether the term is multiplication (binary) + *) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + (** + Indicates whether the term is division (binary) + *) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + (** + Indicates whether the term is integer division (binary) + *) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + (** + Indicates whether the term is remainder (binary) + *) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + (** + Indicates whether the term is modulus (binary) + *) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + (** + Indicates whether the term is a coercion of integer to real (unary) + *) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + (** + Indicates whether the term is a coercion of real to integer (unary) + *) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + (** + Indicates whether the term is a check that tests whether a real is integral (unary) + *) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + (** + Indicates whether the term is of sort real. + *) + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + + (** + Indicates whether the term is an integer numeral. + *) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + (** + Indicates whether the term is a real numeral. + *) + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + (** + Indicates whether the term is an algebraic number + *) + let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + + (** Retrieve the int value. *) + let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) (precision : int) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno + + (** + Creates an integer constant. + *) + let mk_int_const ( ctx : context ) ( name : symbol ) = + ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) + + (** + Creates an integer constant. + *) + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx ((Symbol.mk_string ctx name) :> symbol) + + (** + Creates a real constant. + *) + let mk_real_const ( ctx : context ) ( name : symbol ) = + ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) + + (** + Creates a real constant. + *) + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx ((Symbol.mk_string ctx name) :> symbol) + + (** + Create an expression representing t[0] + t[1] + .... + *) + let mk_add ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_add ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing t[0] * t[1] * .... + *) + let mk_mul ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_mul ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing t[0] - t[1] - .... + *) + let mk_sub ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_sub ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing -t. + *) + let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = + (create_expr ctx (Z3native.mk_unary_minus ctx#gno t#gno) :> arith_expr) + + (** + Create an expression representing t1 / t2. + *) + let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + (create_expr ctx (Z3native.mk_div ctx#gno t1#gno t2#gno) :> arith_expr) + + (** + Create an expression representing t1 mod t2. + The arguments must have int type. + *) + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_mod ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 rem t2. + The arguments must have int type. + *) + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_rem ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 ^ t2. + *) + let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (create_expr ctx (Z3native.mk_power ctx#gno t1#gno t2#gno) :> arith_expr) + + (** + Create an expression representing t1 < t2 + *) + let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 <= t2 + *) + let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_le ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 > t2 + *) + let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 >= t2 + *) + let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge ctx#gno t1#gno t2#gno) + + (** + Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + *) + let mk_int2real ( ctx : context ) ( t : int_expr ) = + (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real ctx#gno t#gno) + + (** + Coerce a real to an integer. + + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + *) + let mk_real2int ( ctx : context ) ( t : real_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int ctx#gno t#gno) + + (** + Creates an expression that checks whether a real number is an integer. + *) + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int ctx#gno t#gno) + + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno +end + + +(** Functions to manipulate bit-vector expressions *) +module BitVectors = +struct + (** + Create a new bit-vector sort. + *) + let mk_sort ( ctx : context ) size = + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) (** Indicates whether the terms is of bit-vector sort. @@ -1747,300 +2662,750 @@ struct (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BADD) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULT) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BAND) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BOR) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOT) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. + rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. + rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + + (** The size of a bit-vector sort. *) + let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno + + (** Retrieve the int value. *) + let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno (** - Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. + Creates a bit-vector constant. *) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = + ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) (** - Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + Creates a bit-vector constant. *) + let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) size (** - Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. + Bitwise negation. + The argument must have a bit-vector sort. *) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + let mk_not ( ctx : context ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot ctx#gno t#gno) + (** + Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. + *) + let mk_redand ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand ctx#gno t#gno) + + (** + Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. + *) + let mk_redor ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor ctx#gno t#gno) + + (** + Bitwise conjunction. + The arguments must have a bit-vector sort. + *) + let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand ctx#gno t1#gno t2#gno) + + (** + Bitwise disjunction. + The arguments must have a bit-vector sort. + *) + let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor ctx#gno t1#gno t2#gno) + + (** + Bitwise XOR. + The arguments must have a bit-vector sort. + *) + let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor ctx#gno t1#gno t2#gno) + + (** + Bitwise NAND. + The arguments must have a bit-vector sort. + *) + let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand ctx#gno t1#gno t2#gno) + + (** + Bitwise NOR. + The arguments must have a bit-vector sort. + *) + let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor ctx#gno t1#gno t2#gno) + + (** + Bitwise XNOR. + The arguments must have a bit-vector sort. + *) + let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor ctx#gno t1#gno t2#gno) + + (** + Standard two's complement unary minus. + The arguments must have a bit-vector sort. + *) + let mk_neg ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg ctx#gno t#gno) + + (** + Two's complement addition. + The arguments must have the same bit-vector sort. + *) + let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd ctx#gno t1#gno t2#gno) + + (** + Two's complement subtraction. + The arguments must have the same bit-vector sort. + *) + let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub ctx#gno t1#gno t2#gno) + + (** + Two's complement multiplication. + The arguments must have the same bit-vector sort. + *) + let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul ctx#gno t1#gno t2#gno) + + (** + Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv ctx#gno t1#gno t2#gno) + + (** + Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv ctx#gno t1#gno t2#gno) + + (** + Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem ctx#gno t1#gno t2#gno) + + (** + Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem ctx#gno t1#gno t2#gno) + + (** + Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod ctx#gno t1#gno t2#gno) + + (** + Unsigned less-than + + The arguments must have the same bit-vector sort. + *) + let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult ctx#gno t1#gno t2#gno) + + (** + Two's complement signed less-than + + The arguments must have the same bit-vector sort. + *) + let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt ctx#gno t1#gno t2#gno) + + (** + Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule ctx#gno t1#gno t2#gno) + + (** + Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle ctx#gno t1#gno t2#gno) + + (** + Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge ctx#gno t1#gno t2#gno) + + (** + Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge ctx#gno t1#gno t2#gno) + + (** + Unsigned greater-than. + + The arguments must have the same bit-vector sort. + *) + let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt ctx#gno t1#gno t2#gno) + + (** + Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. + *) + let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt ctx#gno t1#gno t2#gno) + + (** + Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). + *) + let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat ctx#gno t1#gno t2#gno) + + (** + Bit-vector extraction. + + Extract the bits down to from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. + The argument must have a bit-vector sort. + *) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract ctx#gno high low t#gno) + + (** + Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. + The argument must have a bit-vector sort. + *) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext ctx#gno i t#gno) + + (** + Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. + The argument must have a bit-vector sort. + *) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext ctx#gno i t#gno) + + (** + Bit-vector repetition. + + The argument must have a bit-vector sort. + *) + let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat ctx#gno i t#gno) + + (** + Shift left. + + + It is equivalent to multiplication by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl ctx#gno t1#gno t2#gno) + + (** + Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr ctx#gno t1#gno t2#gno) + + (** + Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr ctx#gno t1#gno t2#gno) + + (** + Rotate Left. + + Rotate bits of \c t to the left \c i times. + The argument must have a bit-vector sort. + *) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left ctx#gno i t#gno) + + (** + Rotate Right. + + Rotate bits of \c t to the right \c i times. + The argument must have a bit-vector sort. + *) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right ctx#gno i t#gno) + + (** + Rotate Left. + + Rotate bits of to the left times. + The arguments must have the same bit-vector sort. + *) + let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left ctx#gno t1#gno t2#gno) + + (** + Rotate Right. + + + Rotate bits of to the right times. + The arguments must have the same bit-vector sort. + *) + let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right ctx#gno t1#gno t2#gno) + + (** + Create an bit bit-vector from the integer argument . + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + *) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv ctx#gno n t#gno) + + (** + Create an integer from the bit-vector argument . + + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in . + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of bit-vector sort. + *) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow ctx#gno t#gno) + + (** + Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) + +end + +(** Functions to manipulate Proof objects *) +module Proofs = +struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_proof_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRUE) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_proof_asserted ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_proof_goal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -2049,18 +3414,18 @@ struct T1: p T2: (implies p q) [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). + The second antecedents may also be a proof for (iff p q). *) - let is_proof_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. The only reflexive relations that are used are equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. + That is, R is either '~', '=' or 'iff'. *) - let is_proof_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -2069,9 +3434,8 @@ struct T1: (R t s) [symmetry T1]: (R s t) T1 is the antecedent of this proof object. - *) - let is_proof_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -2081,9 +3445,8 @@ struct T1: (R t s) T2: (R s u) [trans T1 T2]: (R t u) - *) - let is_proof_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -2102,9 +3465,8 @@ struct using the antecedents, symmetry and transitivity. That is, if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. - *) - let is_proof_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -2116,9 +3478,8 @@ struct [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. - *) - let is_proof_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -2126,9 +3487,8 @@ struct Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - *) - let is_proof_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -2144,9 +3504,8 @@ struct This proof object has no antecedents. Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. - *) - let is_proof_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -2154,9 +3513,8 @@ struct Given a proof for (and l_1 ... l_n), produces a proof for l_i T1: (and l_1 ... l_n) [and-elim T1]: l_i - *) - let is_proof_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -2164,9 +3522,8 @@ struct Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) - *) - let is_proof_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -2183,9 +3540,8 @@ struct (= (+ ( x : expr ) 0) x) (= (+ ( x : expr ) 1 2) (+ 3 x)) (iff (or ( x : expr ) false) x) - *) - let is_proof_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -2199,17 +3555,15 @@ struct - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - *) - let is_proof_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - *) - let is_proof_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -2217,9 +3571,8 @@ struct A proof for (iff P Q) where Q is in prenex normal form. This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents - *) - let is_proof_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -2230,9 +3583,9 @@ struct ... (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) This proof object has no antecedents - *) - let is_proof_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PUSH_QUANT) + + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -2242,9 +3595,9 @@ struct It is used to justify the elimination of unused variables. This proof object has no antecedents. - *) - let is_proof_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution @@ -2256,23 +3609,22 @@ struct This proof object has no antecedents. Several variables can be eliminated simultaneously. - *) - let is_proof_der ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DER) + + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) - *) - let is_proof_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. + Mark a hypothesis in a natural deduction style proof. *) - let is_proof_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -2283,9 +3635,8 @@ struct This proof object has one antecedent: a hypothetical proof for false. It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. - *) - let is_proof_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -2295,27 +3646,24 @@ struct ... T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - *) - let is_proof_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true T1: p [iff-true T1]: (iff p true) - *) - let is_proof_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false T1: (not p) [iff-false T1]: (iff p false) - *) - let is_proof_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -2326,9 +3674,8 @@ struct This proof object has no antecedents. Remark: if f is bool, then = is iff. - *) - let is_proof_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -2362,9 +3709,8 @@ struct You can recover the propositional tautologies by unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). - *) - let is_proof_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -2385,9 +3731,8 @@ struct Otherwise: [def-intro]: (= n e) - *) - let is_proof_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -2395,18 +3740,16 @@ struct [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is a proof that n is a name for F. - *) - let is_proof_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq T1: (iff p q) [iff~ T1]: (~ p q) - *) - let is_proof_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -2432,9 +3775,8 @@ struct for NNF_POS are 'implies', 'iff', 'xor', 'ite'. NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. - *) - let is_proof_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -2457,9 +3799,8 @@ struct T4: s_2 ~ r_2' [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) - *) - let is_proof_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -2469,9 +3810,8 @@ struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) - let is_proof_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -2479,9 +3819,8 @@ struct A proof for (~ P Q) where Q is in conjunctive normal form. This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) - let is_proof_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step @@ -2492,9 +3831,8 @@ struct [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) This proof object has no antecedents. - *) - let is_proof_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -2503,9 +3841,8 @@ struct T1: p T2: (~ p q) [mp~ T1 T2]: q - *) - let is_proof_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -2520,259 +3857,74 @@ struct - farkas - followed by rational coefficients. Multiply the coefficients to the inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - *) - let is_proof_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TH_LEMMA) - - (** - Indicates whether the term is of a relation sort. - *) - let is_Relation ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) - - (** - Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. - - *) - let is_relation_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_STORE) - - (** - Indicates whether the term is an empty relation - *) - let is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_EMPTY) - - (** - Indicates whether the term is a test for the emptiness of a relation - *) - let is_is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_IS_EMPTY) - - (** - Indicates whether the term is a relational join - *) - let is_relational_join ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_JOIN) - - (** - Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. - *) - let is_relation_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_UNION) - - (** - Indicates whether the term is the widening of two relations - The function takes two arguments. - *) - let is_relation_widen ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_WIDEN) - - (** - Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. - *) - let is_relation_project ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_PROJECT) - - (** - Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. - - *) - let is_relation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_FILTER) - - (** - Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. - - *) - let is_relation_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_NEGATION_FILTER) - - (** - Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. - - *) - let is_relation_rename ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_RENAME) - - (** - Indicates whether the term is the complement of a relation - *) - let is_relation_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_COMPLEMENT) - - (** - Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. - - *) - let is_relation_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_SELECT) - - (** - Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind - to perform destructive updates to the first argument. - - *) - let is_relation_clone ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_CLONE) - - (** - Indicates whether the term is of an array sort. - *) - let is_finite_domain ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) - - (** - Indicates whether the term is a less than predicate over a finite domain. - *) - let is_finite_domain_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FD_LT) - - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - - *) - let get_index ( x : expr ) = - if not (AST.is_var x) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value x#gnc x#gno + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** Integer Numerals *) -module IntNum = -struct - (** Retrieve the int value. *) - let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") +(** + Parameter sets (of Solvers, Tactics, ...) - (** Returns a string representation of the numeral. *) - let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Rational Numerals *) -module RatNum = -struct - - (** The numerator of a rational numeral. *) - let get_numerator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) - - (** The denominator of a rational numeral. *) - let get_denominator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : rat_num ) (precision : int) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** Returns a string representation of the numeral. *) - let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Bit-vector numerals *) -module BitVecNum = -struct - (** Retrieve the int value. *) - let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Algebraic numbers *) -module AlgebraicNum = + A Params objects represents a configuration in the form of symbol/value pairs. +*) +module Params = struct (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real + Adds a parameter setting. *) - let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) - - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + let add_bool (p : params) (name : symbol) (value : bool) = + Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision + (** + Adds a parameter setting. + *) + let add_int (p : params) (name : symbol) (value : int) = + Z3native.params_set_uint p#gnc p#gno name#gno value - (** Returns a string representation of the numeral. *) - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno + (** + Adds a parameter setting. + *) + let add_double (p : params) (name : symbol) (value : float) = + Z3native.params_set_double p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol (p : params) (name : symbol) (value : symbol) = + Z3native.params_set_symbol p#gnc p#gno name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool (p : params) (name : string) (value : bool) = + add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_int (p : params) (name : string) (value : int) = + add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_double (p : params) (name : string) (value : float) = + add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol (p : params) (name : string) (value : symbol) = + add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + A string representation of the parameter set. + *) + let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end -(** Constructors are used for datatype sorts *) -module Constructor = -struct - (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = x#get_n - - (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = x#constructor_decl - - (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = x#tester_decl - - (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = x#accessor_decls -end - - -(** ParamDescrs describe sets of parameters.*) +(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) module ParamDescrs = struct @@ -2917,102 +4069,100 @@ struct | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) - (** Creates a solver that is implemented using the given tactic. + (** creates a solver that is implemented using the given tactic. *) let get_solver ( x : tactic ) = (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) end - -(** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. -*) -module FuncInterp = -struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") -end - -(** Models. +(** Models A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) @@ -3093,7 +4243,7 @@ struct This function may fail if contains quantifiers, is partial (MODEL_PARTIAL enabled), or if is not well-sorted. In this case a ModelEvaluationFailedException is thrown. - + An expression When this flag is enabled, a model value will be assigned to any constant @@ -3120,7 +4270,6 @@ struct Z3 also provides an intepretation for uninterpreted sorts used in a formula. The interpretation for a sort is a finite set of distinct values. We say this finite set is the "universe" of the sort. - *) @@ -3137,8 +4286,8 @@ struct *) let sort_universe ( x : model ) ( s : sort ) = let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (ASTVector.get_size n_univ) in - let f i = (ASTVector.get n_univ i) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -3174,84 +4323,85 @@ struct let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno end -(** Objects that track statistical information about solvers. *) -module Statistics = -struct - - (** - Statistical data is organized into pairs of [Key, Entry], where every - Entry is either a DoubleEntry or a UIntEntry - *) - module Entry = - struct - (** The key of the entry. *) - let get_key (x : statistics_entry) = x#key - - (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x#int - - (** The float-value of the entry. *) - let get_float (x : statistics_entry) = x#float - - (** True if the entry is uint-valued. *) - let is_int (x : statistics_entry) = x#is_int - - (** True if the entry is double-valued. *) - let is_float (x : statistics_entry) = x#is_float - - (** The string representation of the the entry's value. *) - let to_string_value (x : statistics_entry) = - if (is_int x) then - string_of_int (get_int x) - else if (is_float x) then - string_of_float (get_float x) - else - raise (Z3native.Exception "Unknown statistical entry type") - - (** The string representation of the entry (key and value) *) - let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) - end - - (** A string representation of the statistical data. *) - let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno - - (** The number of statistical data. *) - let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno - - (** The data entries. *) - let get_entries ( x : statistics ) = - let n = (get_size x ) in - let f i = ( - let k = Z3native.stats_get_key x#gnc x#gno i in - if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) - else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) - ) in - Array.init n f - - (** - The statistical counters. - *) - let get_keys ( x : statistics ) = - let n = (get_size x) in - let f i = (Z3native.stats_get_key x#gnc x#gno i) in - Array.init n f - - (** - The value of a particular statistical counter. - *) - let get ( x : statistics ) ( key : string ) = - let f p c = (if (Entry.get_key c) = key then (Some c) else p) in - Array.fold_left f None (get_entries x) - -end - (** Solvers *) module Solver = struct type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + (** Objects that track statistical information about solvers. *) + module Statistics = + struct + + (** + Statistical data is organized into pairs of [Key, Entry], where every + Entry is either a DoubleEntry or a UIntEntry + *) + module Entry = + struct + (** The key of the entry. *) + let get_key (x : statistics_entry) = x#key + + (** The int-value of the entry. *) + let get_int (x : statistics_entry) = x#int + + (** The float-value of the entry. *) + let get_float (x : statistics_entry) = x#float + + (** True if the entry is uint-valued. *) + let is_int (x : statistics_entry) = x#is_int + + (** True if the entry is double-valued. *) + let is_float (x : statistics_entry) = x#is_float + + (** The string representation of the the entry's value. *) + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + + (** The string representation of the entry (key and value) *) + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + (** A string representation of the statistical data. *) + let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + + (** The number of statistical data. *) + let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + + (** The data entries. *) + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key x#gnc x#gno i in + if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + else + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ) in + Array.init n f + + (** + The statistical counters. + *) + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key x#gnc x#gno i) in + Array.init n f + + (** + The value of a particular statistical counter. + *) + let get ( x : statistics ) ( key : string ) = + let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + Array.fold_left f None (get_entries x) + + end + + (** A string that describes all available solver parameters. *) @@ -3284,14 +4434,14 @@ struct (** Backtracks backtracking points. - Note that an exception is thrown if is not smaller than NumScopes + Note that an exception is thrown if is not smaller than NumScopes *) let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n (** Resets the Solver. - This removes all assertions from the solver. + This removes all assertions from the solver. *) let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno @@ -3307,7 +4457,7 @@ struct *) let get_num_assertions ( x : solver ) = let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in - (ASTVector.get_size a) + (AST.ASTVector.get_size a) (** @@ -3315,8 +4465,8 @@ struct *) let get_assertions ( x : solver ) = let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in - let n = (ASTVector.get_size a) in - let f i = ((new bool_expr x#gc)#cnstr_obj (ASTVector.get a i)#gno) in + let n = (AST.ASTVector.get_size a) in + let f i = ((new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -3325,7 +4475,6 @@ struct - *) let check ( x : solver ) ( assumptions : bool_expr array option) = let r = @@ -3343,7 +4492,6 @@ struct The result is None if Check was not invoked before, if its results was not SATISFIABLE, or if model production is not enabled. - *) let get_model ( x : solver ) = let q = Z3native.solver_get_model x#gnc x#gno in @@ -3357,7 +4505,6 @@ struct The result is null if Check was not invoked before, if its results was not UNSATISFIABLE, or if proof production is disabled. - *) let get_proof ( x : solver ) = let q = Z3native.solver_get_proof x#gnc x#gno in @@ -3372,12 +4519,11 @@ struct The unsat core is a subset of Assertions The result is empty if Check was not invoked before, if its results was not UNSATISFIABLE, or if core production is disabled. - *) let get_unsat_core ( x : solver ) = let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in - let n = (ASTVector.get_size cn) in - let f i = (ASTVector.get cn i) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in Array.init n f (** @@ -3418,3312 +4564,936 @@ struct end -(** The main interaction with Z3 happens via the Context module *) -module Context = -struct +(* STUFF FROM THE CONTEXT *) - (* SYMBOLS *) - - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) - let mk_symbol_int ( ctx : context ) i = - (new int_symbol ctx)#cnstr_int i - - (** Creates a new symbol using a string. *) - let mk_symbol_string ( ctx : context ) s = - (new string_symbol ctx)#cnstr_string s - - (** - Create an array of symbols. - *) - let mk_symbols_int ( ctx : context ) names = - let f elem = mk_symbol_int ( ctx : context ) elem in - (Array.map f names) - - (** - Create an array of symbols. - *) - let mk_symbols_string ( ctx : context ) names = - let f elem = mk_symbol_string ( ctx : context ) elem in - (Array.map f names) - - - (* SORTS *) - - (** - Create a new Boolean sort. - *) - let mk_bool_sort ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_sort ( ctx : context ) (s : symbol) = - (new uninterpreted_sort ctx)#cnstr_s s - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_sort_s ( ctx : context ) (s : string) = - mk_uninterpreted_sort ctx ((mk_symbol_string ( ctx : context ) s) :> symbol) - - (** - Create a new integer sort. - *) - let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) - - (** - Create a real sort. - *) - let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) - - (** - Create a new bit-vector sort. - *) - let mk_bitvec_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) - - (** - Create a new array sort. - *) - let mk_array_sort ( ctx : context ) domain range = - (new array_sort ctx)#cnstr_dr domain range - - (** - Create a new tuple sort. - *) - let mk_tuple_sort ( ctx : context ) name field_names field_sorts = - (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts - - (** - Create a new enumeration sort. - *) - let mk_enum_sort ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss name enum_names - - (** - Create a new enumeration sort. - *) - let mk_enum_sort_s ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss - ((mk_symbol_string ( ctx : context ) name) :> symbol) - (let f e = (e :> symbol) in - (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) - ) - - (** - Create a new list sort. - *) - let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort - - (** - Create a new list sort. - *) - let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = - mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort - - - (** - Create a new finite domain sort. - *) - let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = - (new finite_domain_sort ctx)#cnstr_si name size - - (** - Create a new finite domain sort. - *) - let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size - - (* DATATYPES *) - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs - - - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - mk_constructor ctx ((mk_symbol_string ctx name) :> symbol) recognizer field_names sorts sort_refs - - - (** - Create a new datatype sort. - *) - let mk_datatype_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = - (new datatype_sort ctx)#cnstr_sc name constructors - - (** - Create a new datatype sort. - *) - let mk_datatype_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = - mk_datatype_sort ctx ((mk_symbol_string ctx name) :> symbol) constructors - - (** - Create mutually recursive datatypes. - @param names names of datatype sorts - @param c list of constructors, one list per sort. - *) - let mk_datatype_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = - let n = (Array.length names) in - let f e = ( (new constructor_list ctx)#cnstr_ca e ) in - let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in - let g e = ( (new datatype_sort ctx)#cnstr_obj e) in - (Array.map g r) - - (** Create mutually recursive data-types. *) - let mk_datatype_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = - mk_datatype_sorts ctx - ( - let f e = ((mk_symbol_string ctx e) :> symbol) in - Array.map f names - ) - c - -(** - - -(* FUNCTION DECLARATIONS *) -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(Symbol name, Sort[] domain, Sort range) - { - - - - - - CheckContextMatch(name); - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, name, domain, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(Symbol name, Sort domain, Sort range) - { - - - - - - CheckContextMatch(name); - CheckContextMatch(domain); - CheckContextMatch(range); - Sort[] q = new Sort[] { domain }; - return new Func_Decl(this, name, q, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(string name, Sort[] domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, MkSymbol(name), domain, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(string name, Sort domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - Sort[] q = new Sort[] { domain }; - return new Func_Decl(this, MkSymbol(name), q, range); - } - -(** - Creates a fresh function declaration with a name prefixed with . -*) - - - let mk_Fresh_Func_Decl(string prefix, Sort[] domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, prefix, domain, range); - } - -(** - Creates a new constant function declaration. -*) - let mk_Const_Decl(Symbol name, Sort range) - { - - - - - CheckContextMatch(name); - CheckContextMatch(range); - return new Func_Decl(this, name, null, range); - } - -(** - Creates a new constant function declaration. -*) - let mk_Const_Decl(string name, Sort range) - { - - - - CheckContextMatch(range); - return new Func_Decl(this, MkSymbol(name), null, range); - } - -(** - Creates a fresh constant function declaration with a name prefixed with . -*) - - - let mk_Fresh_ConstDecl(string prefix, Sort range) - { - - - - CheckContextMatch(range); - return new Func_Decl(this, prefix, null, range); - } - - -(* BOUND VARIABLES *) -(** - Creates a new bound variable. -*) - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - public Expr MkBound(uint index, Sort ty) - { - - - - return Expr.Create(this, Z3native.mk_bound(nCtx, index, ty.x#gno)); - } - - -(* QUANTIFIER PATTERNS *) -(** - Create a quantifier pattern. -*) - public Pattern MkPattern(params Expr[] terms) - { - - if (terms.Length == 0) - throw new Z3Exception("Cannot create a pattern from zero terms"); - - - - - - IntPtr[] termsNative = AST.ArrayToNative(terms); - return new Pattern(this, Z3native.mk_pattern(nCtx, (uint)terms.Length, termsNative)); - } - - -(* CONSTANTS *) -(** - Creates a new Constant of sort and named . -*) - public Expr MkConst(Symbol name, Sort range) - { - - - - - CheckContextMatch(name); - CheckContextMatch(range); - - return Expr.Create(this, Z3native.mk_const(nCtx, name.x#gno, range.x#gno)); - } - -(** - Creates a new Constant of sort and named . -*) - public Expr MkConst(string name, Sort range) - { - - - - return MkConst(MkSymbol(name), range); - } - -(** - Creates a fresh Constant of sort and a - name prefixed with . -*) - let mk_Fresh_Const(string prefix, Sort range) - { - - - - CheckContextMatch(range); - return Expr.Create(this, Z3native.mk_fresh_const(nCtx, prefix, range.x#gno)); - } - -(** - Creates a fresh constant from the Func_Decl . -*) - @param f A decl of a 0-arity function - public Expr MkConst(Func_Decl f) - { - - - - return MkApp(f); - } - -(** - Create a Boolean constant. -*) - let mk_Bool_Const(Symbol name) - { - - - - return (BoolExpr)MkConst(name, BoolSort); - } - -(** - Create a Boolean constant. -*) - let mk_Bool_Const(string name) - { - - - return (BoolExpr)MkConst(MkSymbol(name), BoolSort); - } - -(** - Creates an integer constant. -*) - let mk_Int_Const(Symbol name) - { - - - - return (IntExpr)MkConst(name, IntSort); - } - -(** - Creates an integer constant. -*) - let mk_Int_Const(string name) - { - - - - return (IntExpr)MkConst(name, IntSort); - } - -(** - Creates a real constant. -*) - let mk_Real_Const(Symbol name) - { - - - - return (RealExpr)MkConst(name, RealSort); - } - -(** - Creates a real constant. -*) - let mk_Real_Const(string name) - { - - - return (RealExpr)MkConst(name, RealSort); - } - -(** - Creates a bit-vector constant. -*) - let mk_B_VConst(Symbol name, uint size) - { - - - - return (BitVecExpr)MkConst(name, MkBitVecSort(size)); - } - -(** - Creates a bit-vector constant. -*) - let mk_B_VConst(string name, uint size) - { - - - return (BitVecExpr)MkConst(name, MkBitVecSort(size)); - } - - -(* TERMS *) -(** - Create a new function application. -*) - public Expr MkApp(Func_Decl f, params Expr[] args) - { - - - - - CheckContextMatch(f); - CheckContextMatch(args); - return Expr.Create(this, f, args); - } - -(* PROPOSITIONAL *) -(** - The true Term. -*) - public BoolExpr MkTrue ( ctx : context ) = - { - - - return new BoolExpr(this, Z3native.mk_true(nCtx)); - } - -(** - The false Term. -*) - public BoolExpr MkFalse ( ctx : context ) = - { - - - return new BoolExpr(this, Z3native.mk_false(nCtx)); - } - -(** - Creates a Boolean value. -*) - public BoolExpr MkBool(bool value) - { - - - return value ? MkTrue ( ctx : context ) = : MkFalse ( ctx : context ) =; - } - -(** - Creates the equality = . -*) - public BoolExpr MkEq(Expr x, Expr y) - { - - - - - CheckContextMatch(x); - CheckContextMatch(y); - return new BoolExpr(this, Z3native.mk_eq(nCtx, x.x#gno, y.x#gno)); - } - -(** - Creates a distinct term. -*) - public BoolExpr MkDistinct(params Expr[] args) - { - - - - - - CheckContextMatch(args); - return new BoolExpr(this, Z3native.mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Mk an expression representing not(a). -*) - public BoolExpr MkNot(BoolExpr a) - { - - - - CheckContextMatch(a); - return new BoolExpr(this, Z3native.mk_not(nCtx, a.x#gno)); - } - -(** - Create an expression representing an if-then-else: ite(t1, t2, t3). -*) - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - let mk_I_TE(BoolExpr t1, Expr t2, Expr t3) - { - - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - CheckContextMatch(t3); - return Expr.Create(this, Z3native.mk_ite(nCtx, t1.x#gno, t2.x#gno, t3.x#gno)); - } - -(** - Create an expression representing t1 iff t2. -*) - public BoolExpr MkIff(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_iff(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 -> t2. -*) - public BoolExpr MkImplies(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_implies(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 xor t2. -*) - public BoolExpr MkXor(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_xor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t[0] and t[1] and .... -*) - public BoolExpr MkAnd(params BoolExpr[] t) - { - - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] or t[1] or .... -*) - public BoolExpr MkOr(params BoolExpr[] t) - { - - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - - -(* ARITHMETIC *) -(** - Create an expression representing t[0] + t[1] + .... -*) - public ArithExpr MkAdd(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] * t[1] * .... -*) - public ArithExpr MkMul(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] - t[1] - .... -*) - public ArithExpr MkSub(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing -t. -*) - let mk_Unary_Minus(ArithExpr t) - { - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_unary_minus(nCtx, t.x#gno)); - } - -(** - Create an expression representing t1 / t2. -*) - public ArithExpr MkDiv(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return (ArithExpr)Expr.Create(this, Z3native.mk_div(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 mod t2. -*) - The arguments must have int type. - public IntExpr MkMod(IntExpr t1, IntExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new IntExpr(this, Z3native.mk_mod(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 rem t2. -*) - The arguments must have int type. - public IntExpr MkRem(IntExpr t1, IntExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new IntExpr(this, Z3native.mk_rem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 ^ t2. -*) - public ArithExpr MkPower(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return (ArithExpr)Expr.Create(this, Z3native.mk_power(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 < t2 -*) - public BoolExpr MkLt(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_lt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 <= t2 -*) - public BoolExpr MkLe(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_le(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 > t2 -*) - public BoolExpr MkGt(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_gt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 >= t2 -*) - public BoolExpr MkGe(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_ge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Coerce an integer to a real. -*) - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - - public RealExpr MkInt2Real(IntExpr t) - { - - - - CheckContextMatch(t); - return new RealExpr(this, Z3native.mk_int2real(nCtx, t.x#gno)); - } - -(** - Coerce a real to an integer. -*) - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - - public IntExpr MkReal2Int(RealExpr t) - { - - - - CheckContextMatch(t); - return new IntExpr(this, Z3native.mk_real2int(nCtx, t.x#gno)); - } - -(** - Creates an expression that checks whether a real number is an integer. -*) - let mk_Is_Integer(RealExpr t) - { - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_is_int(nCtx, t.x#gno)); - } - - -(* BIT-VECTORS *) -(** - Bitwise negation. -*) - The argument must have a bit-vector sort. - let mk_B_VNot(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvnot(nCtx, t.x#gno)); - } - -(** - Take conjunction of bits in a vector, return vector of length 1. -*) - The argument must have a bit-vector sort. - let mk_B_VRedAND(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvredand(nCtx, t.x#gno)); - } - -(** - Take disjunction of bits in a vector, return vector of length 1. -*) - The argument must have a bit-vector sort. - let mk_B_VRedOR(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvredor(nCtx, t.x#gno)); - } - -(** - Bitwise conjunction. -*) - The arguments must have a bit-vector sort. - let mk_B_VAND(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvand(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise disjunction. -*) - The arguments must have a bit-vector sort. - let mk_B_VOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise XOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VXOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvxor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise NAND. -*) - The arguments must have a bit-vector sort. - let mk_B_VNAND(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvnand(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise NOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VNOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvnor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise XNOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VXNOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvxnor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Standard two's complement unary minus. -*) - The arguments must have a bit-vector sort. - let mk_B_VNeg(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvneg(nCtx, t.x#gno)); - } - -(** - Two's complement addition. -*) - The arguments must have the same bit-vector sort. - let mk_B_VAdd(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvadd(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement subtraction. -*) - The arguments must have the same bit-vector sort. - let mk_B_VSub(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsub(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement multiplication. -*) - The arguments must have the same bit-vector sort. - let mk_B_VMul(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvmul(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned division. -*) - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VUDiv(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvudiv(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Signed division. -*) - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSDiv(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsdiv(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned remainder. -*) - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VURem(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvurem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Signed remainder. -*) - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSRem(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsrem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed remainder (sign follows divisor). -*) - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSMod(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsmod(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned less-than -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VULT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvult(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed less-than -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSLT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvslt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned less-than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VULE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvule(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed less-than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSLE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsle(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned greater than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VUGE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvuge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed greater than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSGE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned greater-than. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VUGT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvugt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed greater-than. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSGT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsgt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bit-vector concatenation. -*) - - The arguments must have a bit-vector sort. - - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). - - public BitVecExpr MkConcat(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_concat(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bit-vector extraction. -*) - - Extract the bits down to from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. - The argument must have a bit-vector sort. - - public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_extract(nCtx, high, low, t.x#gno)); - } - -(** - Bit-vector sign extension. -*) - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. - The argument must have a bit-vector sort. - - let mk_Sign_Ext(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_sign_ext(nCtx, i, t.x#gno)); - } - -(** - Bit-vector zero extension. -*) - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. - The argument must have a bit-vector sort. - - let mk_Zero_Ext(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_zero_ext(nCtx, i, t.x#gno)); - } - -(** - Bit-vector repetition. -*) - - The argument must have a bit-vector sort. - - public BitVecExpr MkRepeat(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_repeat(nCtx, i, t.x#gno)); - } - -(** - Shift left. -*) - - It is equivalent to multiplication by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VSHL(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvshl(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Logical shift right -*) - - It is equivalent to unsigned division by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VLSHR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvlshr(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Arithmetic shift right -*) - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VASHR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvashr(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Rotate Left. -*) - - Rotate bits of \c t to the left \c i times. - The argument must have a bit-vector sort. - - let mk_B_VRotateLeft(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_rotate_left(nCtx, i, t.x#gno)); - } - -(** - Rotate Right. -*) - - Rotate bits of \c t to the right \c i times. - The argument must have a bit-vector sort. - - let mk_B_VRotateRight(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_rotate_right(nCtx, i, t.x#gno)); - } - -(** - Rotate Left. -*) - - Rotate bits of to the left times. - The arguments must have the same bit-vector sort. - - let mk_B_VRotateLeft(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_ext_rotate_left(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Rotate Right. -*) - - Rotate bits of to the right times. - The arguments must have the same bit-vector sort. - - let mk_B_VRotateRight(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_ext_rotate_right(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an bit bit-vector from the integer argument . -*) - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - - public BitVecExpr MkInt2BV(uint n, IntExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_int2bv(nCtx, n, t.x#gno)); - } - -(** - Create an integer from the bit-vector argument . -*) - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in . - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of bit-vector sort. - - let mk_B_V2Int(BitVecExpr t, bool signed) - { - - - - CheckContextMatch(t); - return new IntExpr(this, Z3native.mk_bv2int(nCtx, t.x#gno, (signed) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise addition does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VAddNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvadd_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise addition does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvadd_no_underflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise subtraction does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSubNoOverflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsub_no_overflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise subtraction does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsub_no_underflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise signed division does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsdiv_no_overflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise negation does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VNegNoOverflow(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_bvneg_no_overflow(nCtx, t.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise multiplication does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VMulNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvmul_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise multiplication does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvmul_no_underflow(nCtx, t1.x#gno, t2.x#gno)); - } - - -(* ARRAYS *) -(** - Create an array constant. -*) - let mk_Array_Const(Symbol name, Sort domain, Sort range) - { - - - - - - return (ArrayExpr)MkConst(name, MkArraySort(domain, range)); - } - -(** - Create an array constant. -*) - let mk_Array_Const(string name, Sort domain, Sort range) - { - - - - - return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range)); - } - -(** - Array read. -*) - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - - - - public Expr MkSelect(ArrayExpr a, Expr i) - { - - - - - CheckContextMatch(a); - CheckContextMatch(i); - return Expr.Create(this, Z3native.mk_select(nCtx, a.x#gno, i.x#gno)); - } - -(** - Array update. -*) - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - - - - public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v) - { - - - - - - CheckContextMatch(a); - CheckContextMatch(i); - CheckContextMatch(v); - return new ArrayExpr(this, Z3native.mk_store(nCtx, a.x#gno, i.x#gno, v.x#gno)); - } - -(** - Create a constant array. -*) - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - - - - let mk_Const_Array(Sort domain, Expr v) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(v); - return new ArrayExpr(this, Z3native.mk_const_array(nCtx, domain.x#gno, v.x#gno)); - } - -(** - Maps f on the argument arrays. -*) - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - - - - - public ArrayExpr MkMap(Func_Decl f, params ArrayExpr[] args) - { - - - - - CheckContextMatch(f); - CheckContextMatch(args); - return (ArrayExpr)Expr.Create(this, Z3native.mk_map(nCtx, f.x#gno, AST.ArrayLength(args), AST.ArrayToNative(args))); - } - -(** - Access the array default value. -*) - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - - let mk_Term_Array(ArrayExpr array) - { - - - - CheckContextMatch(array); - return Expr.Create(this, Z3native.mk_array_default(nCtx, array.x#gno)); - } - - -(* SETS *) -(** - Create a set type. -*) - let mk_Set_Sort(Sort ty) - { - - - - CheckContextMatch(ty); - return new SetSort(this, ty); - } - -(** - Create an empty set. -*) - let mk_Empty_Set(Sort domain) - { - - - - CheckContextMatch(domain); - return Expr.Create(this, Z3native.mk_empty_set(nCtx, domain.x#gno)); - } - -(** - Create the full set. -*) - let mk_Full_Set(Sort domain) - { - - - - CheckContextMatch(domain); - return Expr.Create(this, Z3native.mk_full_set(nCtx, domain.x#gno)); - } - -(** - Add an element to the set. -*) - let mk_Set_Add(Expr set, Expr element) - { - - - - - CheckContextMatch(set); - CheckContextMatch(element); - return Expr.Create(this, Z3native.mk_set_add(nCtx, set.x#gno, element.x#gno)); - } - - -(** - Remove an element from a set. -*) - let mk_Set_Del(Expr set, Expr element) - { - - - - - CheckContextMatch(set); - CheckContextMatch(element); - return Expr.Create(this, Z3native.mk_set_del(nCtx, set.x#gno, element.x#gno)); - } - -(** - Take the union of a list of sets. -*) - let mk_Set_Union(params Expr[] args) - { - - - - CheckContextMatch(args); - return Expr.Create(this, Z3native.mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Take the intersection of a list of sets. -*) - let mk_Set_Intersection(params Expr[] args) - { - - - - - CheckContextMatch(args); - return Expr.Create(this, Z3native.mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Take the difference between two sets. -*) - let mk_Set_Difference(Expr arg1, Expr arg2) - { - - - - - CheckContextMatch(arg1); - CheckContextMatch(arg2); - return Expr.Create(this, Z3native.mk_set_difference(nCtx, arg1.x#gno, arg2.x#gno)); - } - -(** - Take the complement of a set. -*) - let mk_Set_Complement(Expr arg) - { - - - - CheckContextMatch(arg); - return Expr.Create(this, Z3native.mk_set_complement(nCtx, arg.x#gno)); - } - -(** - Check for set membership. -*) - let mk_Set_Membership(Expr elem, Expr set) - { - - - - - CheckContextMatch(elem); - CheckContextMatch(set); - return Expr.Create(this, Z3native.mk_set_member(nCtx, elem.x#gno, set.x#gno)); - } - -(** - Check for subsetness of sets. -*) - let mk_Set_Subset(Expr arg1, Expr arg2) - { - - - - - CheckContextMatch(arg1); - CheckContextMatch(arg2); - return Expr.Create(this, Z3native.mk_set_subset(nCtx, arg1.x#gno, arg2.x#gno)); - } - +(** (* NUMERALS *) (* GENERAL NUMERALS *) (** - Create a Term of a given sort. + Create a Term of a given sort. *) - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - public Expr MkNumeral(string v, Sort ty) - { + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + public Expr MkNumeral(string v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_numeral(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_numeral ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(int v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(int v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_int(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_int ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(uint v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(uint v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_unsigned_int(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_unsigned_int ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(long v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(long v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_int64(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_int64 ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(ulong v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(ulong v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_unsigned_int64(nCtx, v, ty.x#gno)); - } - + create_expr ctx (Z3native.mk_unsigned_int64 ctx#gno v, ty#gno) (* REALS *) (** - Create a real from a fraction. + Create a real from a fraction. *) - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - public RatNum MkReal(int num, int den) - { - if (den == 0) - throw new Z3Exception("Denominator is zero"); + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + public RatNum MkReal(int num, int den) + if (den == 0) + throw new Z3Exception("Denominator is zero"); - - - return new RatNum(this, Z3native.mk_real(nCtx, num, den)); - } + new RatNum(this, Z3native.mk_real ctx#gno num, den) (** - Create a real numeral. + Create a real numeral. *) - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - public RatNum MkReal(string v) - { + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + public RatNum MkReal(string v) - - return new RatNum(this, Z3native.mk_numeral(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_numeral ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(int v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(int v) - - return new RatNum(this, Z3native.mk_int(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_int ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(uint v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(uint v) - - return new RatNum(this, Z3native.mk_unsigned_int(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_unsigned_int ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(long v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(long v) - - return new RatNum(this, Z3native.mk_int64(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_int64 ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(ulong v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(ulong v) - - return new RatNum(this, Z3native.mk_unsigned_int64(nCtx, v, RealSort.x#gno)); - } - + new RatNum(this, Z3native.mk_unsigned_int64 ctx#gno v, RealSort#gno) (* INTEGERS *) (** - Create an integer numeral. + Create an integer numeral. *) - @param v A string representing the Term value in decimal notation. - public IntNum MkInt(string v) - { + @param v A string representing the Term value in decimal notation. + public IntNum MkInt(string v) - - return new IntNum(this, Z3native.mk_numeral(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_numeral ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(int v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(int v) - - return new IntNum(this, Z3native.mk_int(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_int ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(uint v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(uint v) - - return new IntNum(this, Z3native.mk_unsigned_int(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_unsigned_int ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(long v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(long v) - - return new IntNum(this, Z3native.mk_int64(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_int64 ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(ulong v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(ulong v) - - return new IntNum(this, Z3native.mk_unsigned_int64(nCtx, v, IntSort.x#gno)); - } - + new IntNum(this, Z3native.mk_unsigned_int64 ctx#gno v, IntSort#gno) (* BIT-VECTORS *) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - let mk_B_V(string v, uint size) - { + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) string v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(int v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) int v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(uint v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) uint v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(long v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) long v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(ulong v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) ulong v, uint size) + (BitVecNum)MkNumeral(v, MkBitVecSort(size) - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } - - - // Numerals + // Numerals (* QUANTIFIERS *) (** - Create a universal Quantifier. + Create a universal Quantifier. + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. *) - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. - - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - - - - - - return new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a universal Quantifier. + Create a universal Quantifier. *) - public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - - - - - - return new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create an existential Quantifier. + Create an existential Quantifier. *) - - public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + + public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - - - - - - - - - return new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create an existential Quantifier. + Create an existential Quantifier. *) - public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - return new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a Quantifier. + Create a Quantifier. *) - public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - - - - - - if (universal) - return MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - return MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + if (universal) + MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a Quantifier. + Create a Quantifier. *) - public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + if (universal) + MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - - - - - - if (universal) - return MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } - - - - // Expr + // Expr (* OPTIONS *) (** - Selects the format used for pretty-printing expressions. + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. *) - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. - - - - - - public Z3_ast_print_mode PrintMode - { - set { Z3native.set_ast_print_mode(nCtx, (uint)value); } - } - + + + + + public Z3_ast_print_mode PrintMode + + set { Z3native.set_ast_print_mode ctx#gno (uint)value); } (* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Convert a benchmark into an SMT-LIB formatted string. *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) - { + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) - - - - return Z3native.benchmark_to_smtlib_string(nCtx, name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula.x#gno); - } + Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula#gno); (** - Parse the given string using the SMT-LIB parser. + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. - - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string(nCtx, str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); - } + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - Parse the given file using the SMT-LIB parser. + Parse the given file using the SMT-LIB parser. *) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file(nCtx, fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); - } + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBFormulas { get { return Z3native.get_smtlib_num_formulas(nCtx)) + public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public BoolExpr[] SMTLIBFormulas - { - get - { + let[] SMTLIBFormulas + get + + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) + res; - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_formula(nCtx, i)); - return res; - } - } (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBAssumptions { get { return Z3native.get_smtlib_num_assumptions(nCtx)) + public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public BoolExpr[] SMTLIBAssumptions - { - get - { + let[] SMTLIBAssumptions + get + + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) + res; - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_assumption(nCtx, i)); - return res; - } - } (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBDecls { get { return Z3native.get_smtlib_num_decls(nCtx)) + public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Func_Decl[] SMTLIBDecls - { - get - { + public Func_Decl[] SMTLIBDecls + get + + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) + res; - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl(nCtx, i)); - return res; - } - } (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBSorts { get { return Z3native.get_smtlib_num_sorts(nCtx)) + public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Sort[] SMTLIBSorts - { - get - { + public Sort[] SMTLIBSorts + get + + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) + res; - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort(nCtx, i)); - return res; - } - } (** - Parse the given string using the SMT-LIB2 parser. + Parse the given string using the SMT-LIB2 parser. *) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - public BoolExpr ParseSMTLIB2String(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_string(nCtx, str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); - } + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (** - Parse the given file using the SMT-LIB2 parser. + Parse the given file using the SMT-LIB2 parser. *) - - public BoolExpr ParseSMTLIB2File(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { + + let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_file(nCtx, fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); - } - + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (* GOALS *) (** - Creates a new Goal. + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. *) - - Note that the Context must have been created with proof generation support if - is set to true here. - - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - { + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - - return new Goal(this, models, unsatCores, proofs); - } - + new Goal(this, models, unsatCores, proofs); (* PARAMETERSETS *) (** - Creates a new ParameterSet. + Creates a new ParameterSet. *) - public Params MkParams ( ctx : context ) = - { + public Params MkParams ( ctx : context ) = - - return new Params(this); - } - + new Params(this); (* TACTICS *) (** - The number of supported tactics. + The number of supported tactics. *) - public uint NumTactics - { - get { return Z3native.get_num_tactics(nCtx); } - } + public uint NumTactics + + get {Z3native.get_num_tactics ctx#gno); } (** - The names of all supported tactics. + The names of all supported tactics. *) - public string[] TacticNames - { - get - { + public string[] TacticNames + get + + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name ctx#gno i); + res; - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name(nCtx, i); - return res; - } - } (** - Returns a string containing a description of the tactic with the given name. + Returns a string containing a description of the tactic with the given name. *) - public string TacticDescription(string name) - { + public string TacticDescription(string name) - - return Z3native.tactic_get_descr(nCtx, name); - } + Z3native.tactic_get_descr ctx#gno name); (** - Creates a new Tactic. + Creates a new Tactic. *) - public Tactic MkTactic(string name) - { + public Tactic MkTactic(string name) - - return new Tactic(this, name); - } + new Tactic(this, name); (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . *) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - { + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) + last = ts[ts.Length - 1]#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); + if (last != IntPtr.Zero) + last = Z3native.tactic_and_then ctx#gno t2#gno last); + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) - - CheckContextMatch(t1); - CheckContextMatch(t2); - CheckContextMatch(ts); - - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) - { - last = ts[ts.Length - 1].x#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then(nCtx, ts[i].x#gno, last); - } - if (last != IntPtr.Zero) - { - last = Z3native.tactic_and_then(nCtx, t2.x#gno, last); - return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, last)); - } - else - return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, t2.x#gno)); - } + else + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . + + Shorthand for AndThen. *) - - Shorthand for AndThen. - - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - { + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - - - - - return AndThen(t1, t2, ts); - } + AndThen(t1, t2, ts); (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. *) - public Tactic OrElse(Tactic t1, Tactic t2) - { + public Tactic OrElse(Tactic t1, Tactic t2) - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_or_else(nCtx, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a goal for milliseconds. + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. *) - - If does not terminate within milliseconds, then it fails. - - public Tactic TryFor(Tactic t, uint ms) - { + public Tactic TryFor(Tactic t, uint ms) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_try_for(nCtx, t.x#gno, ms)); - } + new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) (** - Create a tactic that applies to a given goal if the probe - evaluates to true. + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. *) - - If evaluates to false, then the new tactic behaves like the skip tactic. - - public Tactic When(Probe p, Tactic t) - { + public Tactic When(Probe p, Tactic t) - - - - CheckContextMatch(t); - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_when(nCtx, p.x#gno, t.x#gno)); - } + new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. *) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) - { + public Tactic Cond(Probe p, Tactic t1, Tactic t2) - - - - - CheckContextMatch(p); - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_cond(nCtx, p.x#gno, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. *) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - { + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_repeat(nCtx, t.x#gno, max)); - } + new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) (** - Create a tactic that just returns the given goal. + Create a tactic that just returns the given goal. *) - public Tactic Skip ( ctx : context ) = - { + public Tactic Skip ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_skip(nCtx)); - } + new Tactic(this, Z3native.tactic_skip ctx#gno) (** - Create a tactic always fails. + Create a tactic always fails. *) - public Tactic Fail ( ctx : context ) = - { + public Tactic Fail ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_fail(nCtx)); - } + new Tactic(this, Z3native.tactic_fail ctx#gno) (** - Create a tactic that fails if the probe evaluates to false. + Create a tactic that fails if the probe evaluates to false. *) - public Tactic FailIf(Probe p) - { + public Tactic FailIf(Probe p) - - - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_fail_if(nCtx, p.x#gno)); - } + new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) - public Tactic FailIfNotDecided ( ctx : context ) = - { + public Tactic FailIfNotDecided ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_fail_if_not_decided(nCtx)); - } + new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) (** - Create a tactic that applies using the given set of parameters . + Create a tactic that applies using the given set of parameters . *) - public Tactic UsingParams(Tactic t, Params p) - { + public Tactic UsingParams(Tactic t, Params p) - - - - CheckContextMatch(t); - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_using_params(nCtx, t.x#gno, p.x#gno)); - } + new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) (** - Create a tactic that applies using the given set of parameters . -*) - Alias for UsingParams - public Tactic With(Tactic t, Params p) - { + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + public Tactic With(Tactic t, Params p) - - - - return UsingParams(t, p); - } + UsingParams(t, p); (** - Create a tactic that applies the given tactics in parallel. + Create a tactic that applies the given tactics in parallel. *) - public Tactic ParOr(params Tactic[] t) - { + public Tactic ParOr(params Tactic[] t) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); - } + new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. *) - public Tactic ParAndThen(Tactic t1, Tactic t2) - { + public Tactic ParAndThen(Tactic t1, Tactic t2) - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_par_and_then(nCtx, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) (** - Interrupt the execution of a Z3 procedure. + Interrupt the execution of a Z3 procedure. *) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = - { - Z3native.interrupt(nCtx); - } - + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = + + Z3native.interrupt ctx#gno); (* PROBES *) (** - The number of supported Probes. + The number of supported Probes. *) - public uint NumProbes - { - get { return Z3native.get_num_probes(nCtx); } - } + public uint NumProbes + + get {Z3native.get_num_probes ctx#gno); } (** - The names of all supported Probes. + The names of all supported Probes. *) - public string[] ProbeNames - { - get - { + public string[] ProbeNames + get + + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name ctx#gno i); + res; - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name(nCtx, i); - return res; - } - } (** - Returns a string containing a description of the probe with the given name. + Returns a string containing a description of the probe with the given name. *) - public string ProbeDescription(string name) - { + public string ProbeDescription(string name) - - return Z3native.probe_get_descr(nCtx, name); - } + Z3native.probe_get_descr ctx#gno name); (** - Creates a new Probe. + Creates a new Probe. *) - public Probe MkProbe(string name) - { + public Probe MkProbe(string name) - - return new Probe(this, name); - } + new Probe(this, name); (** - Create a probe that always evaluates to . + Create a probe that always evaluates to . *) - public Probe Const(double val) - { + public Probe Const(double val) - - return new Probe(this, Z3native.probe_const(nCtx, val)); - } + new Probe(this, Z3native.probe_const ctx#gno val) (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - public Probe Lt(Probe p1, Probe p2) - { + public Probe Lt(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_lt(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by *) - public Probe Gt(Probe p1, Probe p2) - { + public Probe Gt(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_gt(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by *) - public Probe Le(Probe p1, Probe p2) - { + public Probe Le(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_le(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by *) - public Probe Ge(Probe p1, Probe p2) - { + public Probe Ge(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_ge(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by *) - public Probe Eq(Probe p1, Probe p2) - { + public Probe Eq(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_eq(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". + Create a probe that evaluates to "true" when the value + and evaluate to "true". *) - public Probe And(Probe p1, Probe p2) - { + public Probe And(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_and(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". + Create a probe that evaluates to "true" when the value + or evaluate to "true". *) - public Probe Or(Probe p1, Probe p2) - { + public Probe Or(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_or(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". + Create a probe that evaluates to "true" when the value + does not evaluate to "true". *) - public Probe Not(Probe p) - { + public Probe Not(Probe p) - - - CheckContextMatch(p); - return new Probe(this, Z3native.probe_not(nCtx, p.x#gno)); - } - + new Probe(this, Z3native.probe_not ctx#gno p#gno) (* SOLVERS *) (** - Creates a new (incremental) solver. -*) - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. - - public Solver MkSolver(Symbol logic = null) - { + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. +*) + public Solver MkSolver(Symbol logic = null) - - if (logic == null) - return new Solver(this, Z3native.mk_solver(nCtx)); - else - return new Solver(this, Z3native.mk_solver_for_logic(nCtx, logic.x#gno)); - } + if (logic == null) + new Solver(this, Z3native.mk_solver ctx#gno) + else + new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - - public Solver MkSolver(string logic) - { + + public Solver MkSolver(string logic) - - return MkSolver(MkSymbol(logic)); - } + MkSolver(MkSymbol(logic) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - let mk_Simple_Solver ( ctx : context ) = - { + let mk_Simple_Solver ( ctx : context ) ctx : context ) = - - return new Solver(this, Z3native.mk_simple_solver(nCtx)); - } + new Solver(this, Z3native.mk_simple_solver ctx#gno) (** - Creates a solver that is implemented using the given tactic. + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. - - public Solver MkSolver(Tactic t) - { + public Solver MkSolver(Tactic t) - - - return new Solver(this, Z3native.mk_solver_from_tactic(nCtx, t.x#gno)); - } - + new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) (* FIXEDPOINTS *) (** - Create a Fixedpoint context. + Create a Fixedpoint context. *) - public Fixedpoint MkFixedpoint ( ctx : context ) = - { - - - return new Fixedpoint(this); - } - + public Fixedpoint MkFixedpoint ( ctx : context ) = + new Fixedpoint(this); (* MISCELLANEOUS *) (** - Wraps an AST. + Wraps an AST. *) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) - { + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) - return AST.Create(this, nativeObject); - } + AST.Create(this, nativeObject); (** - Unwraps an AST. + Unwraps an AST. *) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) - { - return a.x#gno; - } + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) + + a#gno; (** - Return a string describing all available parameters to Expr.Simplify. + a string describing all available parameters to Expr.Simplify. *) - public string SimplifyHelp ( ctx : context ) = - { + public string SimplifyHelp ( ctx : context ) = - - return Z3native.simplify_get_help(nCtx); - } + Z3native.simplify_get_help ctx#gno); (** - Retrieves parameter descriptions for simplifier. + Retrieves parameter descriptions for simplifier. *) - public ParamDescrs SimplifyParameterDescriptions - { - get { return new ParamDescrs(this, Z3native.simplify_get_param_descrs(nCtx)); } - } + public ParamDescrs SimplifyParameterDescriptions + + get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } (** - Enable/disable printing of warning messages to the console. + Enable/disable printing of warning messages to the console. *) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) - { - Z3native.toggle_warning_messages((enabled) ? 1 : 0); - } - + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) + + Z3native.toggle_warning_messages((enabled) ? 1 : 0); (* ERROR HANDLING *) - //(** - //A delegate which is executed when an error is raised. - //*) - // - //Note that it is possible for memory leaks to occur if error handlers - //throw exceptions. - // - //public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); +(** + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. +*) + public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); - //(** - //The OnError event. - //*) - //public event ErrorHandler OnError = null; - +(** + The OnError event. +*) + public event ErrorHandler OnError = null; (* PARAMETERS *) (** - Update a mutable configuration parameter. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - - - public void UpdateParamValue(string id, string value) - { - Z3native.update_param_value(nCtx, id, value); - } + + public void UpdateParamValue(string id, string value) + + Z3native.update_param_value ctx#gno id, value); (** - Get a configuration parameter. + Get a configuration parameter. + + Returns null if the parameter value does not exist. + *) - - Returns null if the parameter value does not exist. - - - public string GetParamValue(string id) - { - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value(nCtx, id, out res); - if (r == (int)Z3_lbool.Z3_L_FALSE) - return null; - else - return Marshal.PtrToStringAnsi(res); - } + public string GetParamValue(string id) - + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value ctx#gno id, out res); + if (r == (int)Z3_lbool.L_FALSE) + null; + else + Marshal.PtrToStringAnsi(res); (* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get { return m_ctx) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get {m_ctx) - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) - { - // Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - } + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + + internal void InitContext ( ctx : context ) = + + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); - internal void InitContext ( ctx : context ) = - { - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); // keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); - } *) -end + From 371db347afe3bfa80568c5cd131ff50c98d6ed93 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 23 Dec 2012 04:00:34 +0000 Subject: [PATCH 272/646] More new ML API. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 +- scripts/update_api.py | 13 +- src/api/ml/z3.ml | 1644 ++++++++++++++++++------------------- 3 files changed, 807 insertions(+), 858 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index f414e9d1a..dde9f944a 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,7 +4,7 @@ *) open Z3 -open Z3.Context +open Z3.Arithmetic exception ExampleException of string @@ -16,9 +16,9 @@ let _ = Printf.printf "Running Z3 version %s\n" Version.to_string ; let cfg = [("model", "true"); ("proof", "false")] in let ctx = (new context cfg) in - let is = (mk_symbol_int ctx 42) in - let ss = (mk_symbol_string ctx "mySymbol") in - let bs = (mk_bool_sort ctx) in + let is = (Symbol.mk_int ctx 42) in + let ss = (Symbol.mk_string ctx "mySymbol") in + let bs = (Sort.mk_bool ctx) in let ints = (mk_int_sort ctx) in let rs = (mk_real_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); diff --git a/scripts/update_api.py b/scripts/update_api.py index 27f7dd507..acaa9478e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1154,8 +1154,11 @@ def mk_ml(): for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) - ml_native.write('\nexternal is_null : ptr -> bool\n') + ml_native.write('\n') + ml_native.write('external is_null : ptr -> bool\n') ml_native.write(' = "n_is_null"\n\n') + ml_native.write('external mk_null : unit -> ptr\n') + ml_native.write(' = "n_mk_null"\n\n') ml_native.write('exception Exception of string\n\n') # ML declarations @@ -1295,6 +1298,14 @@ def mk_ml(): ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') ml_wrapper.write('}\n\n') + ml_wrapper.write('CAMLprim value n_mk_null( void ) {\n') + ml_wrapper.write(' CAMLparam0();\n') + ml_wrapper.write(' CAMLlocal1(result);\n') + ml_wrapper.write(' void * z3_result = 0;\n') + ml_wrapper.write(' result = caml_alloc_custom(&default_custom_ops, sizeof(void*), 0, 1);\n') + ml_wrapper.write(' memcpy( Data_custom_val(result), &z3_result, sizeof(void*));\n') + ml_wrapper.write(' CAMLreturn (result);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 5f67e11e2..f6454b797 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -593,6 +593,10 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +let patternaton (a : pattern array) = + let f (e : pattern) = e#gno in + Array.map f a + (** Parameter description objects *) class param_descrs ctx = object (self) @@ -1607,6 +1611,306 @@ struct *) let mk_or ( ctx : context ) ( args : bool_expr array ) = (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) + + (** + Create a numeral of a given sort. + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + *) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + create_expr ctx (Z3native.mk_numeral ctx#gno v ty#gno) + + (** + Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + *) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_int ctx#gno v ty#gno) +end + +(** Quantifier expressions *) +module Quantifiers = +struct + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Pattern = + struct + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms x#gnc x#gno + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + end + + (** + Indicates whether the quantifier is universal. + *) + let is_universal ( x : quantifier ) = + lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + + (** + Indicates whether the quantifier is existential. + *) + let is_existential ( x : quantifier ) = not (is_universal x) + + (** + The weight of the quantifier. + *) + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + + (** + The number of patterns. + *) + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + + (** + The patterns. + *) + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of no-patterns. + *) + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + + (** + The no-patterns. + *) + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of bound variables. + *) + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + + (** + The symbols for the bound variables. + *) + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + Array.init n f + + (** + The sorts of the bound variables. + *) + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + Array.init n f + + (** + The body of the quantifier. + *) + let get_body ( x : quantifier ) = + (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + + (** + Creates a new bound variable. + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + *) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + + (** + Create a quantifier pattern. + *) + let mk_pattern ( ctx : context ) ( terms : expr array ) = + if (Array.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) + + (** + Create a universal Quantifier. + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. + + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + *) + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (Array.length sorts) != (Array.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + + (** + Create a universal Quantifier. + *) + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + (** + Create an existential Quantifier. + + *) + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (Array.length sorts) != (Array.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + + (** + Create an existential Quantifier. + *) + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + + (** + Create a Quantifier. + *) + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (universal) then + (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + else + (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + + + (** + Create a Quantifier. + *) + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (universal) then + mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + else + mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id end (** Functions to manipulate Array expressions *) @@ -1777,71 +2081,71 @@ struct *) let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) -(** - Create a set type. -*) -let mk_sort ( ctx : context ) ( ty : sort) = - (new set_sort ctx)#cnstr_s ty + (** + Create a set type. + *) + let mk_sort ( ctx : context ) ( ty : sort) = + (new set_sort ctx)#cnstr_s ty -(** - Create an empty set. -*) -let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) - - (** - Create the full set. - *) -let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + (** + Create an empty set. + *) + let mk_empty ( ctx : context ) ( domain : sort ) = + (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + + (** + Create the full set. + *) + let mk_full ( ctx : context ) ( domain : sort ) = + create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) -(** - Add an element to the set. -*) -let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) - - (** - Remove an element from a set. - *) -let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) - - (** - Take the union of a list of sets. - *) -let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) - -(** - Take the intersection of a list of sets. -*) -let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + (** + Add an element to the set. + *) + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + + (** + Remove an element from a set. + *) + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + + (** + Take the union of a list of sets. + *) + let mk_union ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + + (** + Take the intersection of a list of sets. + *) + let mk_intersection ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) -(** - Take the difference between two sets. -*) -let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + (** + Take the difference between two sets. + *) + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) -(** - Take the complement of a set. -*) -let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + (** + Take the complement of a set. + *) + let mk_complement ( ctx : context ) ( arg : expr ) = + create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) -(** - Check for set membership. -*) -let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + (** + Check for set membership. + *) + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) - (** - Check for subsetness of sets. - *) -let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + (** + Check for subsetness of sets. + *) + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) end @@ -2001,148 +2305,6 @@ struct Array.init n f end - -(** Quantifier expressions *) -module Quantifiers = -struct - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - *) - let get_index ( x : expr ) = - if not (AST.is_var x) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value x#gnc x#gno - - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) - module Pattern = - struct - (** - The number of terms in the pattern. - *) - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms x#gnc x#gno - - (** - The terms in the pattern. - *) - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the pattern. - *) - let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno - end - - (** - Indicates whether the quantifier is universal. - *) - let is_universal ( x : quantifier ) = - lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE - - (** - Indicates whether the quantifier is existential. - *) - let is_existential ( x : quantifier ) = not (is_universal x) - - (** - The weight of the quantifier. - *) - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno - - (** - The number of patterns. - *) - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno - - (** - The patterns. - *) - let get_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in - Array.init n f - - (** - The number of no-patterns. - *) - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno - - (** - The no-patterns. - *) - let get_no_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in - Array.init n f - - (** - The number of bound variables. - *) - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno - - (** - The symbols for the bound variables. - *) - let get_bound_variable_names ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in - Array.init n f - - (** - The sorts of the bound variables. - *) - let get_bound_variable_sorts ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in - Array.init n f - - (** - The body of the quantifier. - *) - let get_body ( x : quantifier ) = - (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) - - (** - Creates a new bound variable. - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) - - (** - Create a quantifier pattern. - *) - let mk_pattern ( ctx : context ) ( terms : expr array ) = - if (Array.length terms) == 0 then - raise (Z3native.Exception "Cannot create a pattern from zero terms") - else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) -end (** Functions to manipulate Datatype expressions *) module Datatypes = @@ -2638,7 +2800,54 @@ struct The result has at most decimal places.*) let to_decimal_string ( x : algebraic_num ) ( precision : int ) = Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** + Create a real from a fraction. + + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + *) + let mk_real_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + (new rat_num ctx)#cnstr_obj (Z3native.mk_real ctx#gno num den) + + (** + Create a real numeral. + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + *) + let mk_real_numeral_s ( ctx : context ) ( v : string ) = + (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_real_sort ctx)#gno) + + (** + Create a real numeral. + + @param v value of the numeral. + @return A Term with value and sort Real + *) + let mk_real_numeral_i ( ctx : context ) ( v : int ) = + (new rat_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_real_sort ctx)#gno) + + (** + Create an integer numeral. + @param v A string representing the Term value in decimal notation. + *) + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + (new int_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_int_sort ctx)#gno) + + (** + Create an integer numeral. + @param v value of the numeral. + @return A Term with value and sort Integer + *) + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + (new int_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_int_sort ctx)#gno) + (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno end @@ -3386,10 +3595,18 @@ struct *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) - + + (** + Create a bit-vector numeral. + + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + *) + let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = + (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_sort ctx size)#gno) end -(** Functions to manipulate Proof objects *) +(** Functions to manipulate proof expressions *) module Proofs = struct (** @@ -4567,933 +4784,654 @@ end (* STUFF FROM THE CONTEXT *) (** - -(* NUMERALS *) - -(* GENERAL NUMERALS *) -(** - Create a Term of a given sort. -*) - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - public Expr MkNumeral(string v, Sort ty) - - create_expr ctx (Z3native.mk_numeral ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(int v, Sort ty) - - create_expr ctx (Z3native.mk_int ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(uint v, Sort ty) - - create_expr ctx (Z3native.mk_unsigned_int ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(long v, Sort ty) - - create_expr ctx (Z3native.mk_int64 ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(ulong v, Sort ty) - - create_expr ctx (Z3native.mk_unsigned_int64 ctx#gno v, ty#gno) - -(* REALS *) -(** - Create a real from a fraction. -*) - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - public RatNum MkReal(int num, int den) - - if (den == 0) - throw new Z3Exception("Denominator is zero"); - - new RatNum(this, Z3native.mk_real ctx#gno num, den) - -(** - Create a real numeral. -*) - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - public RatNum MkReal(string v) - - new RatNum(this, Z3native.mk_numeral ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(int v) - - new RatNum(this, Z3native.mk_int ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(uint v) - - new RatNum(this, Z3native.mk_unsigned_int ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(long v) - - new RatNum(this, Z3native.mk_int64 ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(ulong v) - - new RatNum(this, Z3native.mk_unsigned_int64 ctx#gno v, RealSort#gno) - -(* INTEGERS *) -(** - Create an integer numeral. -*) - @param v A string representing the Term value in decimal notation. - public IntNum MkInt(string v) - - new IntNum(this, Z3native.mk_numeral ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(int v) - - new IntNum(this, Z3native.mk_int ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(uint v) - - new IntNum(this, Z3native.mk_unsigned_int ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(long v) - - new IntNum(this, Z3native.mk_int64 ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(ulong v) - - new IntNum(this, Z3native.mk_unsigned_int64 ctx#gno v, IntSort#gno) - -(* BIT-VECTORS *) -(** - Create a bit-vector numeral. -*) - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) string v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) int v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) uint v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) long v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) ulong v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - - // Numerals - -(* QUANTIFIERS *) -(** - Create a universal Quantifier. - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. -*) - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a universal Quantifier. -*) - public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create an existential Quantifier. -*) - - public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create an existential Quantifier. -*) - public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a Quantifier. -*) - public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - if (universal) - MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a Quantifier. -*) - public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - if (universal) - MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - - // Expr - (* OPTIONS *) (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. *) - - - - - public Z3_ast_print_mode PrintMode + + + + + public Z3_ast_print_mode PrintMode - set { Z3native.set_ast_print_mode ctx#gno (uint)value); } + set { Z3native.set_ast_print_mode ctx#gno (uint)value); } (* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Convert a benchmark into an SMT-LIB formatted string. *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) - Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula#gno); + Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula#gno); (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - Parse the given file using the SMT-LIB parser. + Parse the given file using the SMT-LIB parser. *) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) + public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let[] SMTLIBFormulas + let[] SMTLIBFormulas - get + get - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) - res; + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) + res; (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) + public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let[] SMTLIBAssumptions + let[] SMTLIBAssumptions - get + get - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) - res; + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) + res; (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) + public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Func_Decl[] SMTLIBDecls + public Func_Decl[] SMTLIBDecls - get + get - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) - res; + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) + res; (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) + public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Sort[] SMTLIBSorts + public Sort[] SMTLIBSorts - get + get - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) - res; + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) + res; (** - Parse the given string using the SMT-LIB2 parser. + Parse the given string using the SMT-LIB2 parser. *) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (** - Parse the given file using the SMT-LIB2 parser. + Parse the given file using the SMT-LIB2 parser. *) - - let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (* GOALS *) (** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. *) - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - new Goal(this, models, unsatCores, proofs); + new Goal(this, models, unsatCores, proofs); (* PARAMETERSETS *) (** - Creates a new ParameterSet. + Creates a new ParameterSet. *) - public Params MkParams ( ctx : context ) = + public Params MkParams ( ctx : context ) = - new Params(this); + new Params(this); (* TACTICS *) (** - The number of supported tactics. + The number of supported tactics. *) - public uint NumTactics + public uint NumTactics - get {Z3native.get_num_tactics ctx#gno); } + get {Z3native.get_num_tactics ctx#gno); } (** - The names of all supported tactics. + The names of all supported tactics. *) - public string[] TacticNames + public string[] TacticNames - get + get - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name ctx#gno i); - res; + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name ctx#gno i); + res; (** - Returns a string containing a description of the tactic with the given name. + Returns a string containing a description of the tactic with the given name. *) - public string TacticDescription(string name) + public string TacticDescription(string name) - Z3native.tactic_get_descr ctx#gno name); + Z3native.tactic_get_descr ctx#gno name); (** - Creates a new Tactic. + Creates a new Tactic. *) - public Tactic MkTactic(string name) + public Tactic MkTactic(string name) - new Tactic(this, name); + new Tactic(this, name); (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . *) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) - last = ts[ts.Length - 1]#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); + last = ts[ts.Length - 1]#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); - if (last != IntPtr.Zero) + if (last != IntPtr.Zero) - last = Z3native.tactic_and_then ctx#gno t2#gno last); - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) + last = Z3native.tactic_and_then ctx#gno t2#gno last); + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) - else - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + else + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - - Shorthand for AndThen. + Create a tactic that applies to a Goal and + then to every subgoal produced by . + + Shorthand for AndThen. *) - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - AndThen(t1, t2, ts); + AndThen(t1, t2, ts); (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. *) - public Tactic OrElse(Tactic t1, Tactic t2) + public Tactic OrElse(Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. *) - public Tactic TryFor(Tactic t, uint ms) + public Tactic TryFor(Tactic t, uint ms) - new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) + new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) (** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. *) - public Tactic When(Probe p, Tactic t) + public Tactic When(Probe p, Tactic t) - new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) + new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. *) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) + public Tactic Cond(Probe p, Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. *) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) + new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) (** - Create a tactic that just returns the given goal. + Create a tactic that just returns the given goal. *) - public Tactic Skip ( ctx : context ) = + public Tactic Skip ( ctx : context ) = - new Tactic(this, Z3native.tactic_skip ctx#gno) + new Tactic(this, Z3native.tactic_skip ctx#gno) (** - Create a tactic always fails. + Create a tactic always fails. *) - public Tactic Fail ( ctx : context ) = + public Tactic Fail ( ctx : context ) = - new Tactic(this, Z3native.tactic_fail ctx#gno) + new Tactic(this, Z3native.tactic_fail ctx#gno) (** - Create a tactic that fails if the probe evaluates to false. + Create a tactic that fails if the probe evaluates to false. *) - public Tactic FailIf(Probe p) + public Tactic FailIf(Probe p) - new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) + new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) - public Tactic FailIfNotDecided ( ctx : context ) = + public Tactic FailIfNotDecided ( ctx : context ) = - new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) + new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) (** - Create a tactic that applies using the given set of parameters . + Create a tactic that applies using the given set of parameters . *) - public Tactic UsingParams(Tactic t, Params p) + public Tactic UsingParams(Tactic t, Params p) - new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) + new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) (** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - public Tactic With(Tactic t, Params p) + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + public Tactic With(Tactic t, Params p) - UsingParams(t, p); + UsingParams(t, p); (** - Create a tactic that applies the given tactics in parallel. + Create a tactic that applies the given tactics in parallel. *) - public Tactic ParOr(params Tactic[] t) + public Tactic ParOr(params Tactic[] t) - new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) + new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. *) - public Tactic ParAndThen(Tactic t1, Tactic t2) + public Tactic ParAndThen(Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) (** - Interrupt the execution of a Z3 procedure. + Interrupt the execution of a Z3 procedure. *) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = - Z3native.interrupt ctx#gno); + Z3native.interrupt ctx#gno); (* PROBES *) (** - The number of supported Probes. + The number of supported Probes. *) - public uint NumProbes + public uint NumProbes - get {Z3native.get_num_probes ctx#gno); } + get {Z3native.get_num_probes ctx#gno); } (** - The names of all supported Probes. + The names of all supported Probes. *) - public string[] ProbeNames + public string[] ProbeNames - get + get - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name ctx#gno i); - res; + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name ctx#gno i); + res; (** - Returns a string containing a description of the probe with the given name. + Returns a string containing a description of the probe with the given name. *) - public string ProbeDescription(string name) + public string ProbeDescription(string name) - Z3native.probe_get_descr ctx#gno name); + Z3native.probe_get_descr ctx#gno name); (** - Creates a new Probe. + Creates a new Probe. *) - public Probe MkProbe(string name) + public Probe MkProbe(string name) - new Probe(this, name); + new Probe(this, name); (** - Create a probe that always evaluates to . + Create a probe that always evaluates to . *) - public Probe Const(double val) + public Probe Const(double val) - new Probe(this, Z3native.probe_const ctx#gno val) + new Probe(this, Z3native.probe_const ctx#gno val) (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - public Probe Lt(Probe p1, Probe p2) + public Probe Lt(Probe p1, Probe p2) - new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by *) - public Probe Gt(Probe p1, Probe p2) + public Probe Gt(Probe p1, Probe p2) - new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by *) - public Probe Le(Probe p1, Probe p2) + public Probe Le(Probe p1, Probe p2) - new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by *) - public Probe Ge(Probe p1, Probe p2) + public Probe Ge(Probe p1, Probe p2) - new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by *) - public Probe Eq(Probe p1, Probe p2) + public Probe Eq(Probe p1, Probe p2) - new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". + Create a probe that evaluates to "true" when the value + and evaluate to "true". *) - public Probe And(Probe p1, Probe p2) + public Probe And(Probe p1, Probe p2) - new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". + Create a probe that evaluates to "true" when the value + or evaluate to "true". *) - public Probe Or(Probe p1, Probe p2) + public Probe Or(Probe p1, Probe p2) - new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". + Create a probe that evaluates to "true" when the value + does not evaluate to "true". *) - public Probe Not(Probe p) + public Probe Not(Probe p) - new Probe(this, Z3native.probe_not ctx#gno p#gno) + new Probe(this, Z3native.probe_not ctx#gno p#gno) (* SOLVERS *) (** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) - public Solver MkSolver(Symbol logic = null) + public Solver MkSolver(Symbol logic = null) - if (logic == null) - new Solver(this, Z3native.mk_solver ctx#gno) - else - new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) + if (logic == null) + new Solver(this, Z3native.mk_solver ctx#gno) + else + new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - - public Solver MkSolver(string logic) + + public Solver MkSolver(string logic) - MkSolver(MkSymbol(logic) + MkSolver(MkSymbol(logic) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - let mk_Simple_Solver ( ctx : context ) ctx : context ) = + let mk_Simple_Solver( ctx : context ) ctx : context ) = - new Solver(this, Z3native.mk_simple_solver ctx#gno) + new Solver(this, Z3native.mk_simple_solver ctx#gno) (** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) - public Solver MkSolver(Tactic t) + public Solver MkSolver(Tactic t) - new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) + new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) (* FIXEDPOINTS *) (** - Create a Fixedpoint context. + Create a Fixedpoint context. *) - public Fixedpoint MkFixedpoint ( ctx : context ) = + public Fixedpoint MkFixedpoint ( ctx : context ) = - new Fixedpoint(this); + new Fixedpoint(this); (* MISCELLANEOUS *) (** - Wraps an AST. + Wraps an AST. *) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) - AST.Create(this, nativeObject); + AST.Create(this, nativeObject); (** - Unwraps an AST. + Unwraps an AST. *) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) - a#gno; + a#gno; (** - a string describing all available parameters to Expr.Simplify. + a string describing all available parameters to Expr.Simplify. *) - public string SimplifyHelp ( ctx : context ) = + public string SimplifyHelp ( ctx : context ) = - Z3native.simplify_get_help ctx#gno); + Z3native.simplify_get_help ctx#gno); (** - Retrieves parameter descriptions for simplifier. + Retrieves parameter descriptions for simplifier. *) - public ParamDescrs SimplifyParameterDescriptions + public ParamDescrs SimplifyParameterDescriptions - get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } + get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } (** - Enable/disable printing of warning messages to the console. + Enable/disable printing of warning messages to the console. *) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) - Z3native.toggle_warning_messages((enabled) ? 1 : 0); + Z3native.toggle_warning_messages((enabled) ? 1 : 0); (* ERROR HANDLING *) (** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. *) - public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); + public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); (** - The OnError event. + The OnError event. *) - public event ErrorHandler OnError = null; + public event ErrorHandler OnError = null; (* PARAMETERS *) (** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) - - public void UpdateParamValue(string id, string value) + + public void UpdateParamValue(string id, string value) - Z3native.update_param_value ctx#gno id, value); + Z3native.update_param_value ctx#gno id, value); (** - Get a configuration parameter. - - Returns null if the parameter value does not exist. - + Get a configuration parameter. + + Returns null if the parameter value does not exist. + *) - public string GetParamValue(string id) + public string GetParamValue(string id) - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value ctx#gno id, out res); - if (r == (int)Z3_lbool.L_FALSE) - null; - else - Marshal.PtrToStringAnsi(res); + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value ctx#gno id, out res); + if (r == (int)Z3_lbool.L_FALSE) + null; + else + Marshal.PtrToStringAnsi(res); (* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get {m_ctx) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get {m_ctx) - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - internal void InitContext ( ctx : context ) = + internal void InitContext ( ctx : context ) = - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); *) - From 39e538a8bc4bb2c1dbf7cbdd0b65576d101d5224 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 02:47:41 +0000 Subject: [PATCH 273/646] More new ML API; Status: everything is there except for error handling. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 1498 +++++++++++++++++++++++++--------------------- 1 file changed, 809 insertions(+), 689 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f6454b797..088bfbd6f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,33 +7,52 @@ open Z3enums -(**/**) +(** Context objects. -class virtual idisposable = -object - method virtual dispose : unit -end +Most interactions with Z3 are interpreted in some context; most users will only +require one such object, but power users may require more than one. To start using +Z3, do -(** Context objects *) + + let ctx = (new context [||]) in + (...) + + +where [||] is a (possibly empty) list of pairs of strings, which can +be used to set options on the context, e.g., like so: + + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (new context cfg) in + (...) + + +*) class context settings = +(**/**) object (self) - inherit idisposable - val mutable m_n_ctx : Z3native.z3_context = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = Z3native.mk_context_rc cfg in Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; v +(* CMW: Install error handler here! + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); +*) + val mutable m_obj_cnt : int = 0 initializer (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) let f = fun o -> o#dispose in let v = self in - Gc.finalise f v + Gc.finalise f v; method dispose : unit = if m_obj_cnt == 0 then ( @@ -47,13 +66,14 @@ object (self) method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx +(**/**) end +(**/**) (** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) - inherit idisposable val mutable m_ctx : context = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init @@ -100,9 +120,10 @@ end (** Parameter set objects *) -class params ctx obj = +class params ctx = object (self) - inherit z3object ctx obj as super + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = Z3native.params_inc_ref nc o method decref nc o = Z3native.params_dec_ref nc o end @@ -264,6 +285,10 @@ object (self) method decref nc o = super#decref nc o end +let func_declaton (a : func_decl array) = + let f (e : func_decl) = e#gno in + Array.map f a + class parameter = object (self) val mutable m_kind : parameter_kind = PARAMETER_INT; @@ -624,6 +649,10 @@ object (self) method decref nc o = Z3native.tactic_dec_ref nc o end +let tacticaton (a : tactic array) = + let f (e : tactic) = e#gno in + Array.map f a + (** Function interpretation entry objects *) class func_entry ctx = object (self) @@ -715,6 +744,15 @@ object (self) method decref nc o = Z3native.solver_dec_ref nc o end +(** Fixedpoint objects *) +class fixedpoint ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.fixedpoint_inc_ref nc o + method decref nc o = Z3native.fixedpoint_dec_ref nc o +end + (**/**) @@ -1294,6 +1332,33 @@ struct x else (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) + +(** + Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. +*) + let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = + create_ast ctx ptr + +(** + Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. +*) + let unwrap_ast ( a : ast ) = a#gno end (** General expressions (terms), including Boolean logic *) @@ -1308,6 +1373,18 @@ struct | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) +(** + a string describing all available parameters to Expr.Simplify. +*) + let get_simplify_help ( ctx : context ) = + Z3native.simplify_get_help ctx#gno + +(** + Retrieves parameter descriptions for simplifier. +*) + let get_simplify_parameter_descrs ( ctx : context ) = + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs ctx#gno) + (** The function declaration of the function that is applied in this expression. *) @@ -4087,6 +4164,30 @@ end *) module Params = struct +(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) +module ParamDescrs = +struct + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno +end + (** Adds a parameter setting. *) @@ -4135,37 +4236,18 @@ struct let add_s_symbol (p : params) (name : string) (value : symbol) = add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + (** + Creates a new parameter set + *) + let mk_params ( ctx : context ) = + (new params ctx)#cnstr_obj (Z3native.mk_params ctx#gno) + (** A string representation of the parameter set. *) let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end -(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) -module ParamDescrs = -struct - - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) - - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f - - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno - -end - (** Goals A goal (aka problem). A goal is essentially a @@ -4258,6 +4340,22 @@ struct Z3native.tactic_dec_ref x#gnc tn ; (new goal x#gc)#cnstr_obj res + + (** + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. + @param models Indicates whether model generation should be enabled. + @param unsat_cores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + *) + let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = + (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno + (int_of_lbool (if models then L_TRUE else L_FALSE)) + (int_of_lbool (if unsat_cores then L_TRUE else L_FALSE)) + (int_of_lbool (if proofs then L_TRUE else L_FALSE))) + (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno end @@ -4272,6 +4370,33 @@ end *) module Tactic = struct +(** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) +module ApplyResult = +struct + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals x#gnc x#gno + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in + Array.init n f + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno +end + (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno @@ -4291,6 +4416,147 @@ struct let get_solver ( x : tactic ) = (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) + (** + The number of supported tactics. + *) + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics ctx#gno + + (** + The names of all supported tactics. + *) + let get_tactic_names ( ctx : context ) = + let n = (get_num_tactics ctx ) in + let f i = (Z3native.get_tactic_name ctx#gno i) in + Array.init n f + + + (** + Returns a string containing a description of the tactic with the given name. + *) + let get_tactic_description ( ctx : context ) ( name : string ) = + Z3native.tactic_get_descr ctx#gno name + + (** + Creates a new Tactic. + *) + let mk_tactic ( ctx : context ) ( name : string ) = + (new tactic ctx)#cnstr_obj (Z3native.mk_tactic ctx#gno name) + + (** + Create a tactic that applies to a Goal and + then to every subgoal produced by . + *) + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array option ) = + match + match ts with + | None -> None + | Some(rts) -> ( + let f p c = (match p with + | None -> (Some c#gno) + | Some(x) -> (Some (Z3native.tactic_and_then ctx#gno c#gno x))) in + Array.fold_left f None rts) + with + | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + | Some(x) -> + let o = (Z3native.tactic_and_then ctx#gno t2#gno x) in + (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno o) + + (** + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. + *) + let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + + (** + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. + *) + let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for ctx#gno t#gno ms) + + (** + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. + *) + (* CMW: when is a keyword *) + let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_when ctx#gno p#gno t#gno) + + (** + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. + *) + let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + + (** + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. + *) + let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat ctx#gno t#gno max) + + (** + Create a tactic that just returns the given goal. + *) + let skip ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_skip ctx#gno) + + (** + Create a tactic always fails. + *) + let fail ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail ctx#gno) + + (** + Create a tactic that fails if the probe evaluates to false. + *) + let fail_if ( ctx : context ) ( p : probe ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if ctx#gno p#gno) + + (** + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). + *) + let fail_if_not_decided ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided ctx#gno) + + (** + Create a tactic that applies using the given set of parameters . + *) + let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params ctx#gno t#gno p#gno) + + (** + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + (* CMW: with is a keyword *) + let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + using_params ctx t p + + (** + Create a tactic that applies the given tactics in parallel. + *) + let par_or ( ctx : context ) ( t : tactic array ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or ctx#gno (Array.length t) (tacticaton t)) + + (** + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. + *) + let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + + (** + Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. + *) + let interrupt ( ctx : context ) = + Z3native.interrupt ctx#gno end (** Models @@ -4337,7 +4603,7 @@ struct let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end (** @@ -4513,33 +4779,6 @@ struct let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno end -(** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) -module ApplyResult = -struct - (** The number of Subgoals. *) - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals x#gnc x#gno - - (** Retrieves the subgoals from the apply_result. *) - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in - Array.init n f - - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = - (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) - - (** A string representation of the ApplyResult. *) - let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno -end - (** Solvers *) module Solver = struct @@ -4615,10 +4854,8 @@ struct let get ( x : statistics ) ( key : string ) = let f p c = (if (Entry.get_key c) = key then (Some c) else p) in Array.fold_left f None (get_entries x) - end - (** A string that describes all available solver parameters. *) @@ -4755,12 +4992,222 @@ struct let get_statistics ( x : solver ) = (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + (** + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. + *) + let mk_solver ( ctx : context ) ( logic : symbol option) = + match logic with + | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver ctx#gno) + | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic ctx#gno x#gno) + + (** + Creates a new (incremental) solver. + + *) + let mk_solver_s ( ctx : context ) ( logic : string ) = + mk_solver ctx (Some ((Symbol.mk_string ctx logic) :> symbol)) + + (** + Creates a new (incremental) solver. + *) + let mk_simple_solver ( ctx : context ) = + (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver ctx#gno) + + (** + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. + *) + let mk_solver_t ( ctx : context ) ( t : tactic ) = + (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic ctx#gno t#gno) + (** A string representation of the solver. *) let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno end +(** Fixedpoint solving *) +module Fixedpoints = +struct + (** + A string that describes all available fixedpoint solver parameters. + *) + let get_help ( x : fixedpoint ) = + Z3native.fixedpoint_get_help x#gnc x#gno + + (** + Sets the fixedpoint solver parameters. + *) + let set_params ( x : fixedpoint ) ( p : params )= + Z3native.fixedpoint_set_params x#gnc x#gno p#gno + + (** + Retrieves parameter descriptions for Fixedpoint solver. + *) + let get_param_descrs ( x : fixedpoint ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.fixedpoint_get_param_descrs x#gnc x#gno) + + (** + Assert a constraints into the fixedpoint solver. + *) + let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in + Array.map f constraints + + (** + Register predicate as recursive relation. + *) + let register_relation ( x : fixedpoint ) ( f : func_decl ) = + Z3native.fixedpoint_register_relation x#gnc x#gno f#gno + + (** + Add rule into the fixedpoint solver. + *) + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + match name with + | None -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno (Z3native.mk_null()) + | Some(y) -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno y#gno + + (** + Add table fact to the fixedpoint solver. + *) + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = + Z3native.fixedpoint_add_fact x#gnc x#gno pred#gno (Array.length args) args + + (** + Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. + *) + let query ( x : fixedpoint ) ( query : bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query x#gnc x#gno query#gno)) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + (** + Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. + *) + let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + match (lbool_of_int (Z3native.fixedpoint_query_relations x#gnc x#gno (Array.length relations) (func_declaton relations))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + (** + Creates a backtracking point. + + *) + let push ( x : fixedpoint ) = + Z3native.fixedpoint_push x#gnc x#gno + + (** + Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + + *) + let pop ( x : fixedpoint ) = + Z3native.fixedpoint_pop x#gnc x#gno + + (** + Update named rule into in the fixedpoint solver. + *) + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + Z3native.fixedpoint_update_rule x#gnc x#gno rule#gno name#gno + + (** + Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. + *) + let get_answer ( x : fixedpoint ) = + let q = (Z3native.fixedpoint_get_answer x#gnc x#gno) in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + Retrieve explanation why fixedpoint engine returned status Unknown. + *) + let get_reason_unknown ( x : fixedpoint ) = + Z3native.fixedpoint_get_reason_unknown x#gnc x#gno + + (** + Retrieve the number of levels explored for a given predicate. + *) + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = + Z3native.fixedpoint_get_num_levels x#gnc x#gno predicate#gno + + (** + Retrieve the cover of a predicate. + *) + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta x#gnc x#gno level predicate#gno) in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + Add property about the predicate. + The property is added at level. + *) + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover x#gnc x#gno level predicate#gno, property#gno + + (** + Retrieve internal string representation of fixedpoint object. + *) + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string x#gnc x#gno 0 [||] + + (** + Instrument the Datalog engine on which table representation to use for recursive predicate. + *) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + Z3native.fixedpoint_set_predicate_representation x#gnc x#gno f#gno (Array.length kinds) (symbolaton kinds) + + (** + Convert benchmark given as set of axioms, rules and queries to a string. + *) + let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = + Z3native.fixedpoint_to_string x#gnc x#gno (Array.length queries) (astaton queries) + + (** + Retrieve set of rules added to fixedpoint context. + *) + let get_rules ( x : fixedpoint ) = + let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_rules x#gnc x#gno)) in + let n = (AST.ASTVector.get_size v) in + let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + Array.init n f + + (** + Retrieve set of assertions added to fixedpoint context. + *) + let get_assertions ( x : fixedpoint ) = + let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_assertions x#gnc x#gno)) in + let n = (AST.ASTVector.get_size v) in + let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + Array.init n f + + (** + Create a Fixedpoint context. + *) + let mk_fixedpoint ( ctx : context ) = + (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) +end + (** Probes Probes are used to inspect a goal (aka problem) and collect information that may be used to decide @@ -4778,660 +5225,333 @@ struct *) let apply ( x : probe ) (g : goal) = Z3native.probe_apply x#gnc x#gno g#gno + + (** + The number of supported Probes. + *) + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes ctx#gno + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name ctx#gno i) in + Array.init n f + + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr ctx#gno name + + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + + (** + Create a probe that always evaluates to . + *) + let const ( ctx : context ) ( v : float ) = + (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by + *) + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) end - -(* STUFF FROM THE CONTEXT *) - -(** -(* OPTIONS *) +(** Global and context options + + Note: This module contains functions that set parameters/options for context + objects as well as functions that set options that are used globally, across + contexts.*) +module Options = +struct (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + *) - - - - - public Z3_ast_print_mode PrintMode + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value ctx#gno id value - set { Z3native.set_ast_print_mode ctx#gno (uint)value); } - -(* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Get a configuration parameter. + + Returns None if the parameter value does not exist. + *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value ctx#gno id) in + if ((lbool_of_int r) == L_FALSE) then + None + else + Some v - Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula#gno); + (** + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + + + + + *) + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode ctx#gno (int_of_ast_print_mode value) (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. + Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages (int_of_lbool (if enabled then L_TRUE else L_FALSE)) +end - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) +(** Functions for handling SMT and SMT2 expressions and files *) +module SMT = +struct + (** + Convert a benchmark into an SMT-LIB formatted string. -(** - Parse the given file using the SMT-LIB parser. -*) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) - -(** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) - -(** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - let[] SMTLIBFormulas - - get - - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) - res; - - -(** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) - -(** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - let[] SMTLIBAssumptions - - get - - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) - res; - - -(** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) - -(** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public Func_Decl[] SMTLIBDecls - - get - - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) - res; - - -(** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) - -(** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public Sort[] SMTLIBSorts - - get - - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) - res; - - -(** - Parse the given string using the SMT-LIB2 parser. -*) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) - -(** - Parse the given file using the SMT-LIB2 parser. -*) - - let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) - -(* GOALS *) -(** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. -*) - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - - new Goal(this, models, unsatCores, proofs); - -(* PARAMETERSETS *) -(** - Creates a new ParameterSet. -*) - public Params MkParams ( ctx : context ) = - - new Params(this); - -(* TACTICS *) -(** - The number of supported tactics. -*) - public uint NumTactics - - get {Z3native.get_num_tactics ctx#gno); } - -(** - The names of all supported tactics. -*) - public string[] TacticNames - - get - - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name ctx#gno i); - res; - - -(** - Returns a string containing a description of the tactic with the given name. -*) - public string TacticDescription(string name) - - Z3native.tactic_get_descr ctx#gno name); - -(** - Creates a new Tactic. -*) - public Tactic MkTactic(string name) - - new Tactic(this, name); - -(** - Create a tactic that applies to a Goal and - then to every subgoal produced by . -*) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) - - last = ts[ts.Length - 1]#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); - - if (last != IntPtr.Zero) - - last = Z3native.tactic_and_then ctx#gno t2#gno last); - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + *) + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + Z3native.benchmark_to_smtlib_string ctx#gno name logic status attributes + (Array.length assumptions) (astaton assumptions) + formula#gno + (** + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. + *) + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) - -(** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - - Shorthand for AndThen. -*) - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - - AndThen(t1, t2, ts); - -(** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. -*) - public Tactic OrElse(Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) - -(** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. -*) - public Tactic TryFor(Tactic t, uint ms) - - new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) - -(** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. -*) - public Tactic When(Probe p, Tactic t) - - new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) - -(** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. -*) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) - -(** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. -*) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - - new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) - -(** - Create a tactic that just returns the given goal. -*) - public Tactic Skip ( ctx : context ) = - - new Tactic(this, Z3native.tactic_skip ctx#gno) - -(** - Create a tactic always fails. -*) - public Tactic Fail ( ctx : context ) = - - new Tactic(this, Z3native.tactic_fail ctx#gno) - -(** - Create a tactic that fails if the probe evaluates to false. -*) - public Tactic FailIf(Probe p) - - new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) - -(** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). -*) - public Tactic FailIfNotDecided ( ctx : context ) = - - new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) - -(** - Create a tactic that applies using the given set of parameters . -*) - public Tactic UsingParams(Tactic t, Params p) - - new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) - -(** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - public Tactic With(Tactic t, Params p) - - UsingParams(t, p); - -(** - Create a tactic that applies the given tactics in parallel. -*) - public Tactic ParOr(params Tactic[] t) - - new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) - -(** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. -*) - public Tactic ParAndThen(Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) - -(** - Interrupt the execution of a Z3 procedure. -*) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = - - Z3native.interrupt ctx#gno); - -(* PROBES *) -(** - The number of supported Probes. -*) - public uint NumProbes - - get {Z3native.get_num_probes ctx#gno); } - -(** - The names of all supported Probes. -*) - public string[] ProbeNames - - get - - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name ctx#gno i); - res; - - -(** - Returns a string containing a description of the probe with the given name. -*) - public string ProbeDescription(string name) - - Z3native.probe_get_descr ctx#gno name); - -(** - Creates a new Probe. -*) - public Probe MkProbe(string name) - - new Probe(this, name); - -(** - Create a probe that always evaluates to . -*) - public Probe Const(double val) - - new Probe(this, Z3native.probe_const ctx#gno val) - -(** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by -*) - public Probe Lt(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by -*) - public Probe Gt(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by -*) - public Probe Le(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by -*) - public Probe Ge(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by -*) - public Probe Eq(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - and evaluate to "true". -*) - public Probe And(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - or evaluate to "true". -*) - public Probe Or(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". -*) - public Probe Not(Probe p) - - new Probe(this, Z3native.probe_not ctx#gno p#gno) - -(* SOLVERS *) -(** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. -*) - public Solver MkSolver(Symbol logic = null) - - if (logic == null) - new Solver(this, Z3native.mk_solver ctx#gno) + Z3native.parse_smtlib_string ctx#gno str + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + + (** + Parse the given file using the SMT-LIB parser. + + *) + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) + Z3native.parse_smtlib_file ctx#gno file_name + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (** + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas ctx#gno -(** - Creates a new (incremental) solver. -*) - - public Solver MkSolver(string logic) + (** + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_formulas ( ctx : context ) = + let n = (get_num_smtlib_formulas ctx ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_formula ctx#gno i)) :> bool_expr) in + Array.init n f - MkSolver(MkSymbol(logic) -(** - Creates a new (incremental) solver. -*) - let mk_Simple_Solver( ctx : context ) ctx : context ) = + (** + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions ctx#gno - new Solver(this, Z3native.mk_simple_solver ctx#gno) + (** + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_assumptions ( ctx : context ) = + let n = (get_num_smtlib_assumptions ctx ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i)) :> bool_expr ) in + Array.init n f -(** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. -*) - public Solver MkSolver(Tactic t) + (** + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls ctx#gno - new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) + (** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_decls ( ctx : context ) = + let n = (get_num_smtlib_decls ctx) in + let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl ctx#gno i) in + Array.init n f -(* FIXEDPOINTS *) -(** - Create a Fixedpoint context. -*) - public Fixedpoint MkFixedpoint ( ctx : context ) = + (** + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts ctx#gno - new Fixedpoint(this); + (** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_sorts ( ctx : context ) = + let n = (get_num_smtlib_sorts ctx) in + let f i = (create_sort ctx (Z3native.get_smtlib_sort ctx#gno i)) in + Array.init n f -(* MISCELLANEOUS *) -(** - Wraps an AST. -*) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) + (** + Parse the given string using the SMT-LIB2 parser. - AST.Create(this, nativeObject); - -(** - Unwraps an AST. -*) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) - - a#gno; - -(** - a string describing all available parameters to Expr.Simplify. -*) - public string SimplifyHelp ( ctx : context ) = - - Z3native.simplify_get_help ctx#gno); - -(** - Retrieves parameter descriptions for simplifier. -*) - public ParamDescrs SimplifyParameterDescriptions - - get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } - -(** - Enable/disable printing of warning messages to the console. -*) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) - - Z3native.toggle_warning_messages((enabled) ? 1 : 0); - -(* ERROR HANDLING *) -(** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. -*) - public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); - -(** - The OnError event. -*) - public event ErrorHandler OnError = null; - -(* PARAMETERS *) -(** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. -*) - - public void UpdateParamValue(string id, string value) - - Z3native.update_param_value ctx#gno id, value); - -(** - Get a configuration parameter. - - Returns null if the parameter value does not exist. - -*) - public string GetParamValue(string id) - - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value ctx#gno id, out res); - if (r == (int)Z3_lbool.L_FALSE) - null; + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + *) + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - Marshal.PtrToStringAnsi(res); + Z3native.parse_smtlib2_string ctx#gno str + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) -(* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get {m_ctx) + (** + Parse the given file using the SMT-LIB2 parser. + + *) + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib2_string ctx#gno file_name + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) +end - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) +(* - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. +(** + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. +*) + public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - internal void InitContext ( ctx : context ) = + internal Z3native.error_handler m_n_err_handler = null; - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) + + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. *) From a42e21ede1c4fece515ee532be1b2ce80296e2df Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 03:00:39 +0000 Subject: [PATCH 274/646] ML API: mk_context added. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 4 +- src/api/ml/z3.ml | 687 +++++++++++++++++++------------------- 2 files changed, 349 insertions(+), 342 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index dde9f944a..32c9458f5 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,8 +14,8 @@ let _ = else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = [("model", "true"); ("proof", "false")] in - let ctx = (new context cfg) in + let cfg = (Some [("model", "true"); ("proof", "false")]) in + let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in let bs = (Sort.mk_bool ctx) in diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 088bfbd6f..fee6f9fe0 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,29 +7,9 @@ open Z3enums -(** Context objects. - -Most interactions with Z3 are interpreted in some context; most users will only -require one such object, but power users may require more than one. To start using -Z3, do - - - let ctx = (new context [||]) in - (...) - - -where [||] is a (possibly empty) list of pairs of strings, which can -be used to set options on the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (new context cfg) in - (...) - - -*) -class context settings = (**/**) + +class context settings = object (self) val mutable m_n_ctx : Z3native.z3_context = let cfg = Z3native.mk_config in @@ -66,11 +46,37 @@ object (self) method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx -(**/**) end (**/**) +(** Create a context object. + +Most interactions with Z3 are interpreted in some context; many users will only +require one such object, but power users may require more than one. To start using +Z3, do + + + let ctx = (mk_context None) in + (...) + + +where a list of pairs of strings may be passed to set options on +the context, e.g., like so: + + + let cfg = (Some [("model", "true"); ("...", "...")]) in + let ctx = (mk_context cfg) in + (...) + +*) +let mk_context ( cfg : ( string * string ) list option ) = + match cfg with + | None -> new context [] + | Some(x) -> new context x + +(**/**) + (** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) @@ -4559,224 +4565,114 @@ end Z3native.interrupt ctx#gno end -(** Models +(** Probes - A Model contains interpretations (assignments) of constants and functions. *) -module Model = + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = struct - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) - module FuncInterp = - struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null np) then - None - else - Some (create_expr x#gc np) - - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl x#gnc n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno - - (** The function declarations of the constants in the model. *) - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.init n f - - - (** The number of function interpretations in the model. *) - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno - - (** The function declarations of the function interpretations in the model. *) - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - Array.init n f - - (** All symbols that have an interpretation in the model. *) - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in - if (lbool_of_int r) == L_FALSE then - raise (ModelEvaluationFailedException "evaluation failed") - else - create_expr x#gc v + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply x#gnc x#gno g#gno - (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - + (** + The number of supported Probes. *) - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes ctx#gno + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name ctx#gno i) in Array.init n f + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr ctx#gno name - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + + (** + Create a probe that always evaluates to . *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - Array.init n f - - (** Conversion of models to strings. - A string representation of the model. + let const ( ctx : context ) ( v : float ) = + (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) end (** Solvers *) @@ -5032,6 +4928,227 @@ struct let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno end + +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr x#gc np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl x#gnc n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in + if (lbool_of_int r) == L_FALSE then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr x#gc v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno +end + (** Fixedpoint solving *) module Fixedpoints = struct @@ -5208,116 +5325,6 @@ struct (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe = -struct - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply x#gnc x#gno g#gno - - (** - The number of supported Probes. - *) - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes ctx#gno - - (** - The names of all supported Probes. - *) - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name ctx#gno i) in - Array.init n f - - (** - Returns a string containing a description of the probe with the given name. - *) - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr ctx#gno name - - (** - Creates a new Probe. - *) - let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) - - (** - Create a probe that always evaluates to . - *) - let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) - let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) -end - (** Global and context options Note: This module contains functions that set parameters/options for context From bffef2e8083f2d42877a6701923c3792a41c23dd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 15:16:16 +0000 Subject: [PATCH 275/646] New ML API bugfixes and first example. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 122 ++++++++++++++++++++++++++++++++++++++ scripts/update_api.py | 10 +++- src/api/ml/z3.ml | 112 +++++++++++++++++----------------- 3 files changed, 186 insertions(+), 58 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 32c9458f5..945c9a494 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,10 +4,131 @@ *) open Z3 +open Z3.Symbol +open Z3.Sort +open Z3.Expr +open Z3.FuncDecl +open Z3.Goal +open Z3.Tactic +open Z3.Probe +open Z3.Solver open Z3.Arithmetic exception ExampleException of string + +(** + Some basic tests. +*) +let basic_tests ( ctx : context ) = + Printf.printf "BasicTests\n" ; + let qi = (mk_int ctx 1) in + let fname = ((mk_string ctx "f") :> symbol) in + let x = ((mk_string ctx "x") :> symbol) in + let y = ((mk_string ctx "y") :> symbol) in + let bs = (Sort.mk_bool ctx) in + let domain = [| bs; bs |] in + let f = (FuncDecl.mk_func_decl ctx fname domain bs) in + let fapp = (mk_app ctx f + [| (mk_const ctx x bs); (mk_const ctx y bs) |]) in + let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in + let domain2 = [| bs |] in + let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in + let trivial_eq = (mk_eq ctx fapp fapp) in + let nontrivial_eq = (mk_eq ctx fapp fapp2) in + let g = (mk_goal ctx true false false) in + (Goal.assert_ g [| trivial_eq |]) ; + (Goal.assert_ g [| nontrivial_eq |]) ; + Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; + let solver = (mk_solver ctx None) in + (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; + if (check solver None) != SATISFIABLE then + raise (ExampleException "") + else + Printf.printf "Test passed.\n" ; + () + +(* + ApplyResult ar = ApplyTactic(ctx, ctx.MkTactic("simplify"), g); + if (ar.NumSubgoals == 1 && (ar.Subgoals[0].IsDecidedSat || ar.Subgoals[0].IsDecidedUnsat)) + throw new TestFailedException(); + + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) + throw new TestFailedException(); + + g.Assert(ctx.MkEq(ctx.MkNumeral(1, ctx.MkBitVecSort(32)), + ctx.MkNumeral(2, ctx.MkBitVecSort(32)))); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + + Goal g2 = ctx.MkGoal(true, true); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) + throw new TestFailedException(); + + g2 = ctx.MkGoal(true, true); + g2.Assert(ctx.MkFalse()); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + Goal g3 = ctx.MkGoal(true, true); + Expr xc = ctx.MkConst(ctx.MkSymbol("x"), ctx.IntSort); + Expr yc = ctx.MkConst(ctx.MkSymbol("y"), ctx.IntSort); + g3.Assert(ctx.MkEq(xc, ctx.MkNumeral(1, ctx.IntSort))); + g3.Assert(ctx.MkEq(yc, ctx.MkNumeral(2, ctx.IntSort))); + BoolExpr constr = ctx.MkEq(xc, yc); + g3.Assert(constr); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g3); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + ModelConverterTest(ctx); + + // Real num/den test. + RatNum rn = ctx.MkReal(42, 43); + Expr inum = rn.Numerator; + Expr iden = rn.Denominator; + Console.WriteLine("Numerator: " + inum + " Denominator: " + iden); + if (inum.ToString() != "42" || iden.ToString() != "43") + throw new TestFailedException(); + + if (rn.ToDecimalString(3) != "0.976?") + throw new TestFailedException(); + + BigIntCheck(ctx, ctx.MkReal("-1231231232/234234333")); + BigIntCheck(ctx, ctx.MkReal("-123123234234234234231232/234234333")); + BigIntCheck(ctx, ctx.MkReal("-234234333")); + BigIntCheck(ctx, ctx.MkReal("234234333/2")); + + + string bn = "1234567890987654321"; + + if (ctx.MkInt(bn).BigInteger.ToString() != bn) + throw new TestFailedException(); + + if (ctx.MkBV(bn, 128).BigInteger.ToString() != bn) + throw new TestFailedException(); + + if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn) + throw new TestFailedException(); + + // Error handling test. + try + { + IntExpr i = ctx.MkInt("1/2"); + throw new TestFailedException(); // unreachable + } + catch (Z3Exception) + { + } + } +*) + + let _ = if not (Log.open_ "z3.log") then raise (ExampleException "Log couldn't be opened.") @@ -27,6 +148,7 @@ let _ = Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); Printf.printf "Disposing...\n"; + basic_tests ctx ; Gc.full_major () ); Printf.printf "Exiting.\n"; diff --git a/scripts/update_api.py b/scripts/update_api.py index acaa9478e..5d95a12f8 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -159,7 +159,7 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I # Mapping to ML types Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', STRING : 'string', STRING_PTR : 'char**', - BOOL : 'int', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } + BOOL : 'bool', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -1109,7 +1109,9 @@ def arrayparams(params): def ml_unwrap(t, ts, s): if t == STRING: return '(' + ts + ') String_val(' + s + ')' - elif t == BOOL or t == INT or t == PRINT_MODE or t == ERROR_CODE: + elif t == BOOL: + return '(' + ts + ') Bool_val(' + s + ')' + elif t == INT or t == PRINT_MODE or t == ERROR_CODE: return '(' + ts + ') Int_val(' + s + ')' elif t == UINT: return '(' + ts + ') Unsigned_int_val(' + s + ')' @@ -1125,7 +1127,9 @@ def ml_unwrap(t, ts, s): def ml_set_wrap(t, d, n): if t == VOID: return d + ' = Val_unit;' - elif t == BOOL or t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: + elif t == BOOL: + return d + ' = Val_bool(' + n + ');' + elif t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: return d + ' = Val_int(' + n + ');' elif t == INT64 or t == UINT64: return d + ' = Val_long(' + n + ');' diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index fee6f9fe0..b4d58711c 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -874,7 +874,7 @@ struct if a#gnc != b#gnc then false else - ((lbool_of_int (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_sort a#gnc a#gno b#gno) (** Returns a unique identifier for the sort. @@ -922,10 +922,10 @@ let create_expr ctx obj = else let s = Z3native.get_sort ctx#gno obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in - if (lbool_of_int (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + if (Z3native.is_algebraic_number ctx#gno obj) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if ((lbool_of_int (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + if (Z3native.is_numeral_ast ctx#gno obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -1016,6 +1016,7 @@ struct raise (Z3native.Exception "parameter is not a ratinoal string") else x#rational + end (** Creates a new function declaration. @@ -1058,7 +1059,6 @@ struct let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = (new func_decl ctx)#cnstr_pdr prefix [||] range - end (** Comparison operator. @@ -1071,7 +1071,7 @@ struct if a#gnc == a#gnc then false else - ((lbool_of_int (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_func_decl a#gnc a#gno b#gno) (** A string representations of the function declaration. *) @@ -1202,7 +1202,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( m : ast_map ) ( key : ast ) = - (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + (Z3native.ast_map_contains m#gnc m#gno key#gno) (** Finds the value associated with the key . @@ -1313,7 +1313,7 @@ struct if a#gnc == b#gnc then false else - ((lbool_of_int (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_ast a#gnc a#gno b#gno) (** Object Comparison. @@ -1472,13 +1472,13 @@ struct (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast x#gnc x#gno) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = lbool_of_int (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted x#gnc x#gno (** The Sort of the term. @@ -1489,9 +1489,9 @@ struct Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (AST.is_expr x) && - (lbool_of_int (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno))) == L_TRUE + (Z3native.is_eq_sort x#gnc + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno)) (** Indicates whether the term represents a constant. @@ -1774,7 +1774,7 @@ struct Indicates whether the quantifier is universal. *) let is_universal ( x : quantifier ) = - lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + Z3native.is_quantifier_forall x#gnc x#gno (** Indicates whether the quantifier is existential. @@ -1879,7 +1879,7 @@ struct if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) (match patterns with | None -> [||] | Some(x) -> (patternaton x)) @@ -1888,7 +1888,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1905,7 +1905,7 @@ struct *) let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) @@ -1913,7 +1913,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1931,7 +1931,7 @@ struct if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) (match patterns with | None -> [||] | Some(x) -> (patternaton x)) @@ -1940,7 +1940,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1957,7 +1957,7 @@ struct *) let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) @@ -1965,7 +1965,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -2046,7 +2046,7 @@ struct Indicates whether the term is of an array sort. *) let is_array ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (Z3native.is_app x#gnc x#gno) && ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) (** The domain of the array sort. *) @@ -2252,7 +2252,7 @@ struct Indicates whether the term is of an array sort. *) let is_finite_domain ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (Z3native.is_app x#gnc x#gno) && (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) (** @@ -2263,7 +2263,7 @@ struct (** The size of the finite domain sort. *) let get_size (x : finite_domain_sort) = let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v + if r then v else raise (Z3native.Exception "Conversion failed.") end @@ -2274,8 +2274,8 @@ struct Indicates whether the term is of a relation sort. *) let is_relation ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + ((Z3native.is_app x#gnc x#gno) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2604,7 +2604,7 @@ struct Indicates whether the term is of integer sort. *) let is_int ( x : expr ) = - ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + (Z3native.is_numeral_ast x#gnc x#gno) && ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) (** @@ -2706,12 +2706,13 @@ struct (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number x#gnc x#gno (** Retrieve the int value. *) - let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if r then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3219,9 +3220,10 @@ struct let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno (** Retrieve the int value. *) - let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + let get_int ( x : bitvec_num ) = + let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if r then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3613,7 +3615,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3621,7 +3623,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3645,7 +3647,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3669,7 +3671,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -4198,7 +4200,7 @@ end Adds a parameter setting. *) let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) + Z3native.params_set_bool p#gnc p#gno name#gno value (** Adds a parameter setting. @@ -4291,11 +4293,12 @@ struct (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : bool_expr array ) = let f e = Z3native.goal_assert x#gnc x#gno e#gno in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = - (lbool_of_int (Z3native.goal_inconsistent x#gnc x#gno)) == L_TRUE + Z3native.goal_inconsistent x#gnc x#gno (** The depth of the goal. This tracks how many transformations were applied to it. *) @@ -4318,11 +4321,11 @@ struct (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = - (lbool_of_int (Z3native.goal_is_decided_sat x#gnc x#gno)) == L_TRUE + Z3native.goal_is_decided_sat x#gnc x#gno (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = - (lbool_of_int (Z3native.goal_is_decided_unsat x#gnc x#gno)) == L_TRUE + Z3native.goal_is_decided_unsat x#gnc x#gno (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = @@ -4357,10 +4360,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno - (int_of_lbool (if models then L_TRUE else L_FALSE)) - (int_of_lbool (if unsat_cores then L_TRUE else L_FALSE)) - (int_of_lbool (if proofs then L_TRUE else L_FALSE))) + (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno @@ -4729,7 +4729,7 @@ struct let n = (get_size x ) in let f i = ( let k = Z3native.stats_get_key x#gnc x#gno i in - if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + if (Z3native.stats_is_uint x#gnc x#gno i) then ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) else ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) @@ -4800,7 +4800,8 @@ struct *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** The number of assertions in the solver. @@ -5049,7 +5050,7 @@ struct else match sk with | ARRAY_SORT -> - if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + if not (Z3native.is_as_array x#gnc n) then raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl x#gnc n in @@ -5105,8 +5106,8 @@ struct The evaluation of in the model. *) let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in - if (lbool_of_int r) == L_FALSE then + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno completion) in + if not r then raise (ModelEvaluationFailedException "evaluation failed") else create_expr x#gc v @@ -5175,7 +5176,8 @@ struct *) let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** Register predicate as recursive relation. @@ -5353,7 +5355,7 @@ struct *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value ctx#gno id) in - if ((lbool_of_int r) == L_FALSE) then + if not r then None else Some v @@ -5383,7 +5385,7 @@ struct all contexts globally. *) let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages (int_of_lbool (if enabled then L_TRUE else L_FALSE)) + Z3native.toggle_warning_messages enabled end (** Functions for handling SMT and SMT2 expressions and files *) From cef9c2fa6901b549d4459902a07409b35ba59353 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 26 Dec 2012 16:54:45 +0000 Subject: [PATCH 276/646] more ML Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 58 +++++++++++++++++++++------------------ src/api/ml/z3.ml | 4 +++ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 945c9a494..7fcd2e9f7 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -10,11 +10,12 @@ open Z3.Expr open Z3.FuncDecl open Z3.Goal open Z3.Tactic +open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic -exception ExampleException of string +exception TestFailedException of string (** @@ -43,32 +44,37 @@ let basic_tests ( ctx : context ) = let solver = (mk_solver ctx None) in (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; if (check solver None) != SATISFIABLE then - raise (ExampleException "") + raise (TestFailedException "") else Printf.printf "Test passed.\n" ; - () - -(* - ApplyResult ar = ApplyTactic(ctx, ctx.MkTactic("simplify"), g); - if (ar.NumSubgoals == 1 && (ar.Subgoals[0].IsDecidedSat || ar.Subgoals[0].IsDecidedUnsat)) - throw new TestFailedException(); - - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) - throw new TestFailedException(); - - g.Assert(ctx.MkEq(ctx.MkNumeral(1, ctx.MkBitVecSort(32)), - ctx.MkNumeral(2, ctx.MkBitVecSort(32)))); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - - Goal g2 = ctx.MkGoal(true, true); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) - throw new TestFailedException(); - + () ; + let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + let g2 = (mk_goal ctx true true false) in + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + () +(* g2 = ctx.MkGoal(true, true); g2.Assert(ctx.MkFalse()); ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); @@ -131,7 +137,7 @@ let basic_tests ( ctx : context ) = let _ = if not (Log.open_ "z3.log") then - raise (ExampleException "Log couldn't be opened.") + raise (TestFailedException "Log couldn't be opened.") else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b4d58711c..8806a70ee 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -4391,6 +4391,10 @@ struct let n = (get_num_subgoals x) in let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in Array.init n f + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoal ( x : apply_result ) ( i : int ) = + (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. From 597409c8acbb8df351c50b83f60c893efe033f2f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Dec 2012 15:51:42 +0000 Subject: [PATCH 277/646] ML API bugfixes More ML examples Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 165 ++++++++++++++++++++++++++------------ scripts/mk_util.py | 6 +- src/api/ml/z3.ml | 5 ++ 3 files changed, 124 insertions(+), 52 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 7fcd2e9f7..0e8122ae0 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -17,6 +17,50 @@ open Z3.Arithmetic exception TestFailedException of string +(** + Model Converter test +*) +let model_converter_test ( ctx : context ) = + Printf.printf "ModelConverterTest\n"; + let xr = ((mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let yr = ((mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let g4 = (mk_goal ctx true false false ) in + (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; + (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; + (Goal.assert_ g4 [| (mk_gt ctx yr (mk_real_numeral_nd ctx 1 1)) |]) ; + ( + let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") None) g4 None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + let solver = (mk_solver ctx None) in + let f e = (Solver.assert_ solver [| e |]) in + ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; + let q = (check solver None) in + if q != SATISFIABLE then + raise (TestFailedException "") + else + let m = (get_model solver) in + match m with + | None -> raise (TestFailedException "") + | Some (m) -> + Printf.printf "Solver says: %s\n" (string_of_status q) ; + Printf.printf "Model: \n%s\n" (Model.to_string m) ; + Printf.printf "Converted Model: \n%s\n" (Model.to_string (convert_model ar 0 m)) + ) (** Some basic tests. @@ -41,59 +85,78 @@ let basic_tests ( ctx : context ) = (Goal.assert_ g [| trivial_eq |]) ; (Goal.assert_ g [| nontrivial_eq |]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; - let solver = (mk_solver ctx None) in - (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver None) != SATISFIABLE then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" ; - () ; - let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in - if ((get_num_subgoals ar) == 1 && - ((is_decided_sat (get_subgoal ar 0)) || - (is_decided_unsat (get_subgoal ar 0)))) then + ( + let solver = (mk_solver ctx None) in + (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; + if (check solver None) != SATISFIABLE then raise (TestFailedException "") else - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) - (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) - ; - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - let g2 = (mk_goal ctx true true false) in - let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - () -(* - g2 = ctx.MkGoal(true, true); - g2.Assert(ctx.MkFalse()); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - Goal g3 = ctx.MkGoal(true, true); - Expr xc = ctx.MkConst(ctx.MkSymbol("x"), ctx.IntSort); - Expr yc = ctx.MkConst(ctx.MkSymbol("y"), ctx.IntSort); - g3.Assert(ctx.MkEq(xc, ctx.MkNumeral(1, ctx.IntSort))); - g3.Assert(ctx.MkEq(yc, ctx.MkNumeral(2, ctx.IntSort))); - BoolExpr constr = ctx.MkEq(xc, yc); - g3.Assert(constr); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g3); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - ModelConverterTest(ctx); - + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + ; + ( + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g2 = (mk_goal ctx true true false) in + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g2 = (mk_goal ctx true true false) in + (Goal.assert_ g2 [| (mk_false ctx) |]) ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g3 = (mk_goal ctx true true false) in + let xc = (mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_int_sort ctx)) in + let yc = (mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_int_sort ctx)) in + (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; + (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; + let constr = (mk_eq ctx xc yc) in + (Goal.assert_ g3 [| constr |] ) ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ) ; + model_converter_test ctx +(* // Real num/den test. RatNum rn = ctx.MkReal(42, 43); Expr inum = rn.Numerator; diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 9b5ab1a7a..9587951ba 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -353,9 +353,13 @@ def check_ml(): r = exec_cmd([OCAMLC, 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') + os.remove('hello.cmi') + os.remove('hello.cmo') + os.remove('a.out') r = exec_cmd([OCAMLBUILD]) if r != 0: raise MKException('Failed testing ocamlbuild. Set environment variable OCAMLBUILD with the path to ocamlbuild') + shutil.rmtree('_build') find_ml_lib() def find_ml_lib(): @@ -499,7 +503,7 @@ def display_help(exit_code): if IS_WINDOWS: print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.") print(" -j, --java generate Java bindings.") - print(" --ml generate Ocaml bindinds.") + print(" --ml generate OCaml bindings.") print(" --staticlib build Z3 static library.") if not IS_WINDOWS: print(" -g, --gmp use GMP.") diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8806a70ee..c0711b4eb 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -4684,6 +4684,11 @@ module Solver = struct type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let string_of_status ( s : status) = match s with + | UNSATISFIABLE -> "unsatisfiable" + | SATISFIABLE -> "satisfiable" + | _ -> "unknown" + (** Objects that track statistical information about solvers. *) module Statistics = struct From d0591334a262679f0f9f72541fe2d28c4097a068 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 15:32:25 +0000 Subject: [PATCH 278/646] ML API: made native layer ANSI-C compliant to avoid compilation issues. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 12 ++++++---- scripts/update_api.py | 55 ++++++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 9587951ba..028d6c8d7 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -345,21 +345,20 @@ def check_ml(): t.commit() if is_verbose(): print "Testing %s..." % OCAMLC - r = exec_cmd([OCAMLC, 'hello.ml']) + r = exec_cmd([OCAMLC, '-o', 'a.out', 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlc compiler. Set environment variable OCAMLC with the path to the Ocaml compiler') if is_verbose(): print "Testing %s..." % OCAMLOPT - r = exec_cmd([OCAMLC, 'hello.ml']) + r = exec_cmd([OCAMLC, '-o', 'a.out', 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') os.remove('hello.cmi') os.remove('hello.cmo') os.remove('a.out') - r = exec_cmd([OCAMLBUILD]) + r = exec_cmd([OCAMLBUILD, '-version']) if r != 0: raise MKException('Failed testing ocamlbuild. Set environment variable OCAMLBUILD with the path to ocamlbuild') - shutil.rmtree('_build') find_ml_lib() def find_ml_lib(): @@ -1350,7 +1349,10 @@ class MLComponent(Component): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + if WINDOWS: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + else: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) diff --git a/scripts/update_api.py b/scripts/update_api.py index 5d95a12f8..1986f4a7e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1262,39 +1262,39 @@ def mk_ml(): ml_wrapper.write('#include \n\n') ml_wrapper.write('#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal1(X6); \n') + ml_wrapper.write(' CAMLlocal1(X6) \n') ml_wrapper.write('#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal2(X6,X7); \n') + ml_wrapper.write(' CAMLlocal2(X6,X7) \n') ml_wrapper.write('#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal3(X6,X7,X8); \n') + ml_wrapper.write(' CAMLlocal3(X6,X7,X8) \n') ml_wrapper.write('\n') ml_wrapper.write('#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam2(X6,X7); \n') + ml_wrapper.write(' CAMLxparam2(X6,X7) \n') ml_wrapper.write('#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam3(X6,X7,X8); \n') + ml_wrapper.write(' CAMLxparam3(X6,X7,X8) \n') ml_wrapper.write('#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9); \n') + ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9) \n') ml_wrapper.write('#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam2(X11,X12); \n') + ml_wrapper.write(' CAMLxparam2(X11,X12) \n') ml_wrapper.write('#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') + ml_wrapper.write(' CAMLxparam3(X11,X12,X13) \n') ml_wrapper.write('\n\n') ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') - ml_wrapper.write(' identifier: (char*) "default handling",\n') - ml_wrapper.write(' finalize: custom_finalize_default,\n') - ml_wrapper.write(' compare: custom_compare_default,\n') - ml_wrapper.write(' hash: custom_hash_default,\n') - ml_wrapper.write(' serialize: custom_serialize_default,\n') - ml_wrapper.write(' deserialize: custom_deserialize_default\n') + ml_wrapper.write(' (char*) "default handling",\n') + ml_wrapper.write(' custom_finalize_default,\n') + ml_wrapper.write(' custom_compare_default,\n') + ml_wrapper.write(' custom_hash_default,\n') + ml_wrapper.write(' custom_serialize_default,\n') + ml_wrapper.write(' custom_deserialize_default\n') ml_wrapper.write('};\n\n') ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') @@ -1358,7 +1358,10 @@ def mk_ml(): i = i + 1 ml_wrapper.write(');\n') - # preprocess arrays, strings, in/out arguments + if len(ap) != 0: + ml_wrapper.write(' unsigned _i;\n') + + # declare locals, preprocess arrays, strings, in/out arguments i = 0 for param in params: k = param_kind(param) @@ -1372,22 +1375,32 @@ def mk_ml(): elif k == IN_ARRAY or k == INOUT_ARRAY: t = param_type(param) ts = type2str(t) - ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) - ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) _a%s[i] = %s;\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', i)'))) + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * _a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) elif k == IN: t = param_type(param) ml_wrapper.write(' %s _a%s = %s;\n' % (type2str(t), i, ml_unwrap(t, type2str(t), 'a' + str(i)))) elif k == OUT: ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) elif k == INOUT: - ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) - + ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) + i = i + 1 + + if result != VOID: + ml_wrapper.write(' %s z3_result;\n' % type2str(result)) + + i = 0 + for param in params: + k = param_kind(param) + if k == IN_ARRAY or k == INOUT_ARRAY: + t = param_type(param) + ts = type2str(t) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { _a%s[_i] = %s; }\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', _i)'))) i = i + 1 # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('%s z3_result = ' % type2str(result)) + ml_wrapper.write('z3_result = ') ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1412,7 +1425,7 @@ def mk_ml(): for p in params: if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) - ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) { value t; %s Store_field(_a%s, i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[i]'), i)) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 From 297604bee2850a857acd7e0b278fc901165f1a98 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 18:49:19 +0000 Subject: [PATCH 279/646] ML API: linker fix --- scripts/mk_util.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 028d6c8d7..ce4ed7118 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1349,10 +1349,7 @@ class MLComponent(Component): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - if WINDOWS: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) - else: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) -L%s -lcamlrun\n' % (libfile, os.path.join('api', 'ml', 'z3native'), OCAML_LIB)) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) From 35ef2d1c407bf20da54dae59e892776542ba8034 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 18:56:19 +0000 Subject: [PATCH 280/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ce4ed7118..68ede3b81 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1349,7 +1349,10 @@ class MLComponent(Component): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) -L%s -lcamlrun\n' % (libfile, os.path.join('api', 'ml', 'z3native'), OCAML_LIB)) + if IS_WINDOWS: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + else: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) -L%s -lcamlrun\n' % (libfile, os.path.join('api', 'ml', 'z3native'), OCAML_LIB)) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) From 7aef3fa5c6eaebb3fe9651b734ee8b7d51f91c76 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 22:44:55 +0000 Subject: [PATCH 281/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 68ede3b81..ae2418be1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1348,7 +1348,7 @@ class MLComponent(Component): for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I"%s" -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) if IS_WINDOWS: out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) else: From 9eea0f3232dc554c12531c7398581eaad6cec17b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 20:56:49 +0000 Subject: [PATCH 282/646] ML API: build system changes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 65 +++++++++++++++++++++++----------------------- src/api/ml/README | 5 ++++ 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ae2418be1..9edbf2658 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -33,8 +33,7 @@ EXAMP_DEBUG_FLAG='' LDFLAGS=getenv("LDFLAGS", "") JNI_HOME=getenv("JNI_HOME", None) OCAMLC=getenv("OCAMLC", "ocamlc") -OCAMLOPT=getenv("OCAMLC", "ocamlopt") -OCAMLBUILD=getenv("OCAMLBUILD", "ocamlbuild") +OCAMLOPT=getenv("OCAMLOPT", "ocamlopt") OCAML_LIB=getenv("OCAML_LIB", None) CXX_COMPILERS=['g++', 'clang++'] @@ -350,15 +349,12 @@ def check_ml(): raise MKException('Failed testing ocamlc compiler. Set environment variable OCAMLC with the path to the Ocaml compiler') if is_verbose(): print "Testing %s..." % OCAMLOPT - r = exec_cmd([OCAMLC, '-o', 'a.out', 'hello.ml']) + r = exec_cmd([OCAMLOPT, '-o', 'a.out', 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') os.remove('hello.cmi') os.remove('hello.cmo') os.remove('a.out') - r = exec_cmd([OCAMLBUILD, '-version']) - if r != 0: - raise MKException('Failed testing ocamlbuild. Set environment variable OCAMLBUILD with the path to ocamlbuild') find_ml_lib() def find_ml_lib(): @@ -520,7 +516,6 @@ def display_help(exit_code): print(" JNI_HOME JNI bindings directory (only relevant if -j or --java option is provided)") print(" OCAMLC Ocaml byte-code compiler (only relevant with --ml)") print(" OCAMLOPT Ocaml native compiler (only relevant with --ml)") - print(" OCAMLBUILD Ocaml build system (only relevant with --ml)") print(" OCAML_LIB Ocaml library directory (only relevant with --ml)") exit(exit_code) @@ -1336,27 +1331,29 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): - deffile = open('%s.mllib' % os.path.join(self.src_dir, "z3"), 'w') + src_dir = self.to_src_dir + sub_dir = os.path.join('api', 'ml') + mk_dir(os.path.join(BUILD_DIR, sub_dir)) + for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): + shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): + shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + out.write('z3.cmxa:') for mlfile in get_ml_files(self.src_dir): - deffile.write('%s\n' % (string.upper(mlfile[0]) + mlfile[1:-3])) - deffile.close() - - bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') - mk_dir(bld_dir) - libfile = '%s$(SO_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) + out.write(' %s' % os.path.join(src_dir, mlfile)) + out.write('\n') + out.write('\tpushd %s && %s ' % (sub_dir, OCAMLOPT)) + if DEBUG_MODE: + out.write('-g ') + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cmxa -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) + out.write('z3.cma:') for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I"%s" -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - if IS_WINDOWS: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) - else: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT) -L%s -lcamlrun\n' % (libfile, os.path.join('api', 'ml', 'z3native'), OCAML_LIB)) - out.write('z3.cmxa: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) - out.write('z3.cma: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -custom,-cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3native$(OBJ_EXT) z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR)) + out.write('\tpushd %s && %s ' % (sub_dir, OCAMLC)) + if DEBUG_MODE: + out.write('-g ') + out.write('-custom -ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cma -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) out.write('ml: z3.cmxa z3.cma\n') out.write('\n') @@ -1485,7 +1482,10 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\tocamlc -g -o ml_example.byte -I . z3.cma -I api/ml') + out.write('\t%s ' % OCAMLC) + if DEBUG_MODE: + out.write('-g ') + out.write('-custom -o ml_example.byte -I . z3.cma -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1493,7 +1493,10 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\tocamlopt -g -o ml_example -I . z3.cmxa -I api/ml') + out.write('\t%s ' % OCAMLOPT) + if DEBUG_MODE: + out.write('-g ') + out.write('-o ml_example($EXE_EXT) -I . z3.cmxa -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1648,10 +1651,9 @@ def mk_config(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) if is_ml_enabled(): - print('Ocaml Compiler: %s' % OCAMLC) - print('Ocaml Native: %s' % OCAMLOPT) - print('Ocamlbuild: %s' % OCAMLBUILD) - print('Ocaml Library: %s' % OCAML_LIB) + print('OCaml Compiler: %s' % OCAMLC) + print('OCaml Native: %s' % OCAMLOPT) + print('OCaml Library: %s' % OCAML_LIB) else: global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG OS_DEFINES = "" @@ -1774,9 +1776,8 @@ def mk_config(): if is_ml_enabled(): print('Ocaml Compiler: %s' % OCAMLC) print('Ocaml Native: %s' % OCAMLOPT) - print('Ocamlbuild: %s' % OCAMLBUILD) print('Ocaml Library: %s' % OCAML_LIB) - + def mk_install(out): out.write('install: ') for c in get_components(): diff --git a/src/api/ml/README b/src/api/ml/README index 925fced59..beee7d864 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -1,3 +1,8 @@ This directory is work in progress. We are currently working on a brand new ML API. + +On Windows, there are no less than four different ports of OCaml. The Z3 build +system assumes that either the win32 or the win64 port is installed. This means +that OCaml will use `cl' as the underlying C compiler and not the cygwin or +mingw compilers. \ No newline at end of file From 9d965b5fec5b4d28c86971d78b3391e39977e143 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 21:02:44 +0000 Subject: [PATCH 283/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 9edbf2658..34a25781a 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -354,7 +354,10 @@ def check_ml(): raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') os.remove('hello.cmi') os.remove('hello.cmo') + os.remove('hello.cmx') + os.remove('hello.obj') os.remove('a.out') + t.__del__() find_ml_lib() def find_ml_lib(): From b48c4449788a25bd4e14887614569516fae54d18 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 21:22:45 +0000 Subject: [PATCH 284/646] ML API: build system fix --- scripts/mk_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 34a25781a..c1f899f6d 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -357,7 +357,6 @@ def check_ml(): os.remove('hello.cmx') os.remove('hello.obj') os.remove('a.out') - t.__del__() find_ml_lib() def find_ml_lib(): From 1865ca58c3b2b9dc4a33de0dd6537bdf0e0897e2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 21:34:40 +0000 Subject: [PATCH 285/646] ML API: build system fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c1f899f6d..75e2af52d 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -355,7 +355,6 @@ def check_ml(): os.remove('hello.cmi') os.remove('hello.cmo') os.remove('hello.cmx') - os.remove('hello.obj') os.remove('a.out') find_ml_lib() From be3fb0ef18a95ac75e3595872ab3698f37f93c34 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 10 Jan 2013 17:25:55 +0000 Subject: [PATCH 286/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 75e2af52d..5530a7afd 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1339,23 +1339,26 @@ class MLComponent(Component): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - out.write('z3.cmxa:') + out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s api/ml/z3native.c $(CXX_OUTFLAG) api/ml/z3native$(OBJ_EXT)\n' % get_component(API_COMPONENT).to_src_dir) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG) libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') - out.write('\tpushd %s && %s ' % (sub_dir, OCAMLOPT)) + out.write('\tcd %s && %s ' % (sub_dir, OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cmxa -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) - out.write('z3.cma:') + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cmxa -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('api/ml/z3.cma: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\tpushd %s && %s ' % (sub_dir, OCAMLC)) + out.write('\tcd %s && %s ' % (sub_dir, OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-custom -ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cma -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) - out.write('ml: z3.cmxa z3.cma\n') + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cma -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') def main_component(self): @@ -1479,29 +1482,29 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: z3.cma ') + out.write('ml_example.byte: api/ml/z3.cma ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I . z3.cma -I api/ml') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" z3.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example($EXE_EXT): z3.cmxa ml_example.byte') + out.write('ml_example$(EXE_EXT): api/ml/z3.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example($EXE_EXT) -I . z3.cmxa -I api/ml') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" z3.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('_ex_%s: ml_example.byte ml_example($EXE_EXT)\n\n' % self.name) + out.write('_ex_%s: ml_example.byte ml_example$(EXE_EXT)\n\n' % self.name) class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): From 381d552f9676bee85cd22e5cf0aa931066d57ea1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 10 Jan 2013 18:39:43 +0000 Subject: [PATCH 287/646] ML API: build system fixes --- scripts/mk_util.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5530a7afd..554bb4259 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -351,11 +351,11 @@ def check_ml(): print "Testing %s..." % OCAMLOPT r = exec_cmd([OCAMLOPT, '-o', 'a.out', 'hello.ml']) if r != 0: - raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler') - os.remove('hello.cmi') - os.remove('hello.cmo') - os.remove('hello.cmx') - os.remove('a.out') + raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler. Note that ocamlopt may require flexlink to be in your path.') + rmf('hello.cmi') + rmf('hello.cmo') + rmf('hello.cmx') + rmf('a.out') find_ml_lib() def find_ml_lib(): @@ -1340,8 +1340,8 @@ class MLComponent(Component): for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s api/ml/z3native.c $(CXX_OUTFLAG) api/ml/z3native$(OBJ_EXT)\n' % get_component(API_COMPONENT).to_src_dir) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG) libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s api/ml/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, get_component(API_COMPONENT).to_src_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) From 0e59d056298fc0eadeec20584f3c3d3cb31d5a26 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 11 Jan 2013 14:33:28 +0000 Subject: [PATCH 288/646] ML API: changed context from object to normal type. Removed optional array parameters. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 +- src/api/ml/z3.ml | 661 ++++++++++++++++++-------------------- 2 files changed, 323 insertions(+), 346 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 0e8122ae0..129f73d4d 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -38,7 +38,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ); ( - let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") None) g4 None) in + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") [||]) g4 None) in if ((get_num_subgoals ar) == 1 && ((is_decided_sat (get_subgoal ar 0)) || (is_decided_unsat (get_subgoal ar 0)))) then @@ -49,7 +49,7 @@ let model_converter_test ( ctx : context ) = let solver = (mk_solver ctx None) in let f e = (Solver.assert_ solver [| e |]) in ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; - let q = (check solver None) in + let q = (check solver [||]) in if q != SATISFIABLE then raise (TestFailedException "") else @@ -88,7 +88,7 @@ let basic_tests ( ctx : context ) = ( let solver = (mk_solver ctx None) in (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver None) != SATISFIABLE then + if (check solver [||]) != SATISFIABLE then raise (TestFailedException "") else Printf.printf "Test passed.\n" @@ -204,7 +204,7 @@ let _ = else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = (Some [("model", "true"); ("proof", "false")]) in + let cfg = [("model", "true"); ("proof", "false")] in let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c0711b4eb..c91d909bc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,46 +7,39 @@ open Z3enums +type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } + (**/**) +let context_dispose ctx = + if ctx.m_n_obj_cnt == 0 then ( + (* Printf.printf "Disposing context \n" ; *) + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; + (* re-queue for finalization? *) + ) -class context settings = -object (self) - val mutable m_n_ctx : Z3native.z3_context = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - v - +let context_init settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + (* Printf.printf "Installing finalizer on context \n" ; *) + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> context_dispose o in + Gc.finalise f res; + res (* CMW: Install error handler here! m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. Z3native.set_error_handler(m_ctx, m_n_err_handler); GC.SuppressFinalize(this); *) - val mutable m_obj_cnt : int = 0 - - initializer - (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v; - - method dispose : unit = - if m_obj_cnt == 0 then ( - (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) - (Z3native.del_context m_n_ctx) - ) else ( - Printf.printf "NOT DISPOSING context %d because it still has %d objects alive\n" (Oo.id self) m_obj_cnt; - (* re-queue for finalization? *) - ) - - method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 - method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 - method gno = m_n_ctx -end +let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) +let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) +let context_gno ctx = ctx.m_n_ctx (**/**) @@ -70,10 +63,8 @@ the context, e.g., like so: (...) *) -let mk_context ( cfg : ( string * string ) list option ) = - match cfg with - | None -> new context [] - | Some(x) -> new context x +let mk_context ( cfg : ( string * string ) list ) = + context_init cfg (**/**) @@ -85,8 +76,8 @@ object (self) initializer (match m_n_obj with - | Some (x) -> self#incref m_ctx#gno x; - m_ctx#add_one_ctx_obj + | Some (x) -> self#incref (context_gno m_ctx) x; + (context_add1 m_ctx) | None -> () ); (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) @@ -101,8 +92,8 @@ object (self) (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) (match m_n_obj with | Some (x) -> - self#decref m_ctx#gno x; - m_ctx#sub_one_ctx_obj ; + self#decref (context_gno m_ctx) x; + (context_sub1 m_ctx) ; m_n_obj <- None; | None -> () ); @@ -112,16 +103,16 @@ object (self) | None -> raise (Z3native.Exception "Z3 object lost") method sno (ctx : context) o = - m_ctx#add_one_ctx_obj ; - self#incref ctx#gno o ; + (context_add1 m_ctx) ; + self#incref (context_gno ctx) o ; (match m_n_obj with - | Some(x) -> self#decref ctx#gno x ; m_ctx#sub_one_ctx_obj + | Some(x) -> self#decref (context_gno ctx) x ; (context_sub1 m_ctx) | None -> () ); m_n_obj <- Some o method gc = m_ctx - method gnc = m_ctx#gno + method gnc = (context_gno m_ctx) end @@ -134,37 +125,38 @@ object (self) method decref nc o = Z3native.params_dec_ref nc o end + (** Symbol objects *) -class symbol ctx = +class symbol ctx = object (self) - inherit z3object ctx None as super + inherit z3object ctx None as super method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = () method decref nc o = () end +(** Int symbol objects *) +class int_symbol ctx = +object(self) + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol (context_gno ctx) i)) ; self +end + +(** String symbol objects *) +class string_symbol ctx = +object(self) + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol (context_gno ctx) name)) ; self +end + let symbolaton (a : symbol array) = let f (e : symbol) = e#gno in Array.map f a -(** Int symbol objects *) -class int_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol ctx#gno i)) ; self -end - -(** String symbol objects *) -class string_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol ctx#gno name)) ; self -end - let create_symbol ctx no = - match (symbol_kind_of_int (Z3native.get_symbol_kind ctx#gno no)) with + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) @@ -205,7 +197,7 @@ class array_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort (context_gno ctx) domain#gno range#gno)) ; self end (** Bit-vector sort objects *) @@ -241,7 +233,7 @@ class uninterpreted_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self + method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) s#gno)) ; self end (** Finite domain sort objects *) @@ -249,7 +241,7 @@ class finite_domain_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) s#gno sz)) ; self end (** Relation sort objects *) @@ -273,7 +265,7 @@ object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in (self#sno ctx x) ; self end @@ -284,8 +276,8 @@ class func_decl ctx = object (self) inherit ast ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o method decref nc o = super#decref nc o @@ -341,7 +333,7 @@ object (self) val mutable _testerdecls : func_decl array option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) name#gno (Array.length enum_names) (symbolaton enum_names)) in _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; (self#sno ctx r) ; @@ -368,7 +360,7 @@ object (self) val mutable _taildecl : func_decl option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) name#gno elem_sort#gno) in _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; @@ -426,7 +418,7 @@ object (self) if m_n != (Array.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else - let o = (Z3native.mk_constructor ctx#gno name#gno recognizer#gno m_n (symbolaton field_names) + let o = (Z3native.mk_constructor (context_gno ctx) name#gno recognizer#gno m_n (symbolaton field_names) (sortaton sorts) sort_refs) in self#sno ctx o ; @@ -473,7 +465,7 @@ object (self) Gc.finalise f v method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ca ( c : constructor array ) = - self#sno ctx (Z3native.mk_constructor_list ctx#gno (Array.length c) (constructoraton c)) ; + self#sno ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (constructoraton c)) ; self end @@ -486,11 +478,11 @@ class datatype_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (constructoraton constructors)))) ; self + method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) name#gno (Array.length constructors) (constructoraton constructors)))) ; self end let create_sort ctx obj = - match (sort_kind_of_int (Z3native.get_sort_kind ctx#gno obj)) with + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) obj)) with | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) @@ -900,7 +892,7 @@ struct Create a new Boolean sort. *) let mk_bool ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort (context_gno ctx)) (** Create a new uninterpreted sort. @@ -917,15 +909,15 @@ end (**/**) let create_expr ctx obj = - if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then (((new quantifier ctx)#cnstr_obj obj) :> expr) else - let s = Z3native.get_sort ctx#gno obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in - if (Z3native.is_algebraic_number ctx#gno obj) then + let s = Z3native.get_sort (context_gno ctx) obj in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) obj) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if (Z3native.is_numeral_ast ctx#gno obj) && + if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -943,11 +935,11 @@ let create_expr ctx obj = | _ -> (new expr ctx)#cnstr_obj obj let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = - let o = Z3native.mk_app ctx#gno f#gno (Array.length args) (astaton args) in + let o = Z3native.mk_app (context_gno ctx) f#gno (Array.length args) (astaton args) in create_expr ctx o let create_ast ctx no = - match (ast_kind_of_int (Z3native.get_ast_kind ctx#gno no)) with + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) | SORT_AST -> ((create_sort ctx no) :> ast) @@ -1188,7 +1180,7 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = @@ -1337,7 +1329,7 @@ struct if x#gc == to_ctx then x else - (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) + (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) (** Wraps an AST. @@ -1383,13 +1375,13 @@ struct a string describing all available parameters to Expr.Simplify. *) let get_simplify_help ( ctx : context ) = - Z3native.simplify_get_help ctx#gno + Z3native.simplify_get_help (context_gno ctx) (** Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs ctx#gno) + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -1462,7 +1454,7 @@ struct if x#gc == to_ctx then x else - create_expr to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno) + create_expr to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx)) (** Returns a string representation of the expression. @@ -1578,7 +1570,7 @@ struct Creates a new Constant of sort and named . *) let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const ctx#gno name#gno range#gno) + create_expr ctx (Z3native.mk_const (context_gno ctx) name#gno range#gno) (** @@ -1600,7 +1592,7 @@ struct name prefixed with . *) let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = - create_expr ctx (Z3native.mk_fresh_const ctx#gno prefix range#gno) + create_expr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix range#gno) (** Create a Boolean constant. @@ -1624,13 +1616,13 @@ struct The true Term. *) let mk_true ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_true ctx#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_false ctx#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1642,19 +1634,19 @@ struct Creates the equality = . *) let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq ctx#gno x#gno y#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq (context_gno ctx) x#gno y#gno) (** Creates a distinct term. *) let mk_distinct ( ctx : context ) ( args : expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct (context_gno ctx) (Array.length args) (astaton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_not ctx#gno a#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_not (context_gno ctx) a#gno) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1663,37 +1655,37 @@ struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite ctx#gno t1#gno t2#gno t3#gno) + create_expr ctx (Z3native.mk_ite (context_gno ctx) t1#gno t2#gno t3#gno) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor (context_gno ctx) t1#gno t2#gno) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_and ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_and (context_gno ctx) (Array.length args) (astaton args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_or (context_gno ctx) (Array.length args) (astaton args)) (** Create a numeral of a given sort. @@ -1702,7 +1694,7 @@ struct @return A Term with value and sort *) let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - create_expr ctx (Z3native.mk_numeral ctx#gno v ty#gno) + create_expr ctx (Z3native.mk_numeral (context_gno ctx) v ty#gno) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1712,7 +1704,7 @@ struct @return A Term with value and type *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_int ctx#gno v ty#gno) + create_expr ctx (Z3native.mk_int (context_gno ctx) v ty#gno) end (** Quantifier expressions *) @@ -1845,7 +1837,7 @@ struct @param ty The sort of the variable *) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + create_expr ctx (Z3native.mk_bound (context_gno ctx) index ty#gno) (** Create a quantifier pattern. @@ -1854,7 +1846,7 @@ struct if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (astaton terms)) (** Create a universal Quantifier. @@ -1875,27 +1867,24 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno true + else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno true + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) @@ -1903,51 +1892,45 @@ struct (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = - if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno true + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno true + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) body#gno) (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno false + else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno false + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) @@ -1955,31 +1938,28 @@ struct (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = - if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno false + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno false + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) body#gno) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1989,7 +1969,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2081,7 +2061,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - ((create_expr ctx (Z3native.mk_select ctx#gno a#gno i#gno)) :> array_expr) + ((create_expr ctx (Z3native.mk_select (context_gno ctx) a#gno i#gno)) :> array_expr) (** Array update. @@ -2100,7 +2080,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_store ctx#gno a#gno i#gno v#gno) + (new array_expr ctx)#cnstr_obj (Z3native.mk_store (context_gno ctx) a#gno i#gno v#gno) (** Create a constant array. @@ -2111,7 +2091,7 @@ struct *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array ctx#gno domain#gno v#gno) + (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array (context_gno ctx) domain#gno v#gno) (** Maps f on the argument arrays. @@ -2124,7 +2104,7 @@ struct *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = - ((create_expr ctx (Z3native.mk_map ctx#gno f#gno (Array.length args) (astaton args))) :> array_expr) + ((create_expr ctx (Z3native.mk_map (context_gno ctx) f#gno (Array.length args) (astaton args))) :> array_expr) (** Access the array default value. @@ -2133,7 +2113,7 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - ((create_expr ctx (Z3native.mk_array_default ctx#gno arg#gno)) :> array_expr) + ((create_expr ctx (Z3native.mk_array_default (context_gno ctx) arg#gno)) :> array_expr) end (** Functions to manipulate Set expressions *) @@ -2174,61 +2154,61 @@ struct Create an empty set. *) let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + (create_expr ctx (Z3native.mk_empty_set (context_gno ctx) domain#gno)) (** Create the full set. *) let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + create_expr ctx (Z3native.mk_full_set (context_gno ctx) domain#gno) (** Add an element to the set. *) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + create_expr ctx (Z3native.mk_set_add (context_gno ctx) set#gno element#gno) (** Remove an element from a set. *) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + create_expr ctx (Z3native.mk_set_del (context_gno ctx) set#gno element#gno) (** Take the union of a list of sets. *) let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + create_expr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (astaton args)) (** Take the intersection of a list of sets. *) let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + create_expr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (astaton args)) (** Take the difference between two sets. *) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + create_expr ctx (Z3native.mk_set_difference (context_gno ctx) arg1#gno arg2#gno) (** Take the complement of a set. *) let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + create_expr ctx (Z3native.mk_set_complement (context_gno ctx) arg#gno) (** Check for set membership. *) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + create_expr ctx (Z3native.mk_set_member (context_gno ctx) elem#gno set#gno) (** Check for subsetness of sets. *) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + create_expr ctx (Z3native.mk_set_subset (context_gno ctx) arg1#gno arg2#gno) end @@ -2458,7 +2438,7 @@ struct let n = (Array.length names) in let f e = ( (new constructor_list ctx)#cnstr_ca e ) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (symbolaton names) (constructor_listaton cla)) in let g e = ( (new datatype_sort ctx)#cnstr_obj e) in (Array.map g r) @@ -2592,13 +2572,13 @@ struct Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort (context_gno ctx)) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort (context_gno ctx)) (** Indicates whether the term is of integer sort. @@ -2761,75 +2741,75 @@ struct Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - (create_expr ctx (Z3native.mk_unary_minus ctx#gno t#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) t#gno) :> arith_expr) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - (create_expr ctx (Z3native.mk_div ctx#gno t1#gno t2#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_div (context_gno ctx) t1#gno t2#gno) :> arith_expr) (** Create an expression representing t1 mod t2. The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_mod ctx#gno t1#gno t2#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_mod (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_rem ctx#gno t1#gno t2#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_rem (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 ^ t2. *) let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (create_expr ctx (Z3native.mk_power ctx#gno t1#gno t2#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_power (context_gno ctx) t1#gno t2#gno) :> arith_expr) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_le ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_le (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge (context_gno ctx) t1#gno t2#gno) (** Coerce an integer to a real. @@ -2842,7 +2822,7 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real ctx#gno t#gno) + (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real (context_gno ctx) t#gno) (** Coerce a real to an integer. @@ -2852,13 +2832,13 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int ctx#gno t#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int (context_gno ctx) t#gno) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int ctx#gno t#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int (context_gno ctx) t#gno) (** Return a upper bound for a given real algebraic number. @@ -2898,7 +2878,7 @@ struct raise (Z3native.Exception "Denominator is zero") else - (new rat_num ctx)#cnstr_obj (Z3native.mk_real ctx#gno num den) + (new rat_num ctx)#cnstr_obj (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2906,7 +2886,7 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_real_sort ctx)#gno) + (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create a real numeral. @@ -2915,14 +2895,14 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_real_sort ctx)#gno) + (new rat_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_int_sort ctx)#gno) + (new int_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) (** Create an integer numeral. @@ -2930,7 +2910,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_int_sort ctx)#gno) + (new int_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -2944,7 +2924,7 @@ struct Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3245,91 +3225,91 @@ struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) (** Unsigned division. @@ -3341,7 +3321,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) (** Signed division. @@ -3356,7 +3336,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) (** Unsigned remainder. @@ -3366,7 +3346,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) (** Signed remainder. @@ -3378,7 +3358,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) (** Two's complement signed remainder (sign follows divisor). @@ -3387,7 +3367,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than @@ -3395,7 +3375,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult (context_gno ctx) t1#gno t2#gno) (** Two's complement signed less-than @@ -3403,7 +3383,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than or equal to. @@ -3411,7 +3391,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule (context_gno ctx) t1#gno t2#gno) (** Two's complement signed less-than or equal to. @@ -3419,7 +3399,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle (context_gno ctx) t1#gno t2#gno) (** Unsigned greater than or equal to. @@ -3427,7 +3407,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge (context_gno ctx) t1#gno t2#gno) (** Two's complement signed greater than or equal to. @@ -3435,7 +3415,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge (context_gno ctx) t1#gno t2#gno) (** Unsigned greater-than. @@ -3443,7 +3423,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt (context_gno ctx) t1#gno t2#gno) (** Two's complement signed greater-than. @@ -3451,7 +3431,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt (context_gno ctx) t1#gno t2#gno) (** Bit-vector concatenation. @@ -3462,7 +3442,7 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat (context_gno ctx) t1#gno t2#gno) (** Bit-vector extraction. @@ -3473,7 +3453,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract ctx#gno high low t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) (** Bit-vector sign extension. @@ -3483,7 +3463,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext (context_gno ctx) i t#gno) (** Bit-vector zero extension. @@ -3494,7 +3474,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext (context_gno ctx) i t#gno) (** Bit-vector repetition. @@ -3502,7 +3482,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat (context_gno ctx) i t#gno) (** Shift left. @@ -3517,7 +3497,7 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl (context_gno ctx) t1#gno t2#gno) (** Logical shift right @@ -3531,7 +3511,7 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr (context_gno ctx) t1#gno t2#gno) (** Arithmetic shift right @@ -3547,7 +3527,7 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr (context_gno ctx) t1#gno t2#gno) (** Rotate Left. @@ -3556,7 +3536,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left (context_gno ctx) i t#gno) (** Rotate Right. @@ -3565,7 +3545,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right (context_gno ctx) i t#gno) (** Rotate Left. @@ -3574,7 +3554,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left (context_gno ctx) t1#gno t2#gno) (** Rotate Right. @@ -3584,7 +3564,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right (context_gno ctx) t1#gno t2#gno) (** Create an bit bit-vector from the integer argument . @@ -3597,7 +3577,7 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv ctx#gno n t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv (context_gno ctx) n t#gno) (** Create an integer from the bit-vector argument . @@ -3615,7 +3595,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno signed) + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3623,7 +3603,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3631,7 +3611,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3639,7 +3619,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3647,7 +3627,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3655,7 +3635,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3663,7 +3643,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow ctx#gno t#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow (context_gno ctx) t#gno) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3671,7 +3651,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3679,7 +3659,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow (context_gno ctx) t1#gno t2#gno) (** Create a bit-vector numeral. @@ -3688,7 +3668,7 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_sort ctx size)#gno) + (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) end (** Functions to manipulate proof expressions *) @@ -4248,7 +4228,7 @@ end Creates a new parameter set *) let mk_params ( ctx : context ) = - (new params ctx)#cnstr_obj (Z3native.mk_params ctx#gno) + (new params ctx)#cnstr_obj (Z3native.mk_params (context_gno ctx)) (** A string representation of the parameter set. @@ -4329,7 +4309,7 @@ struct (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno to_ctx#gno) + (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : params option ) = @@ -4360,7 +4340,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno models unsat_cores proofs) + (new goal ctx)#cnstr_obj (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno @@ -4429,14 +4409,14 @@ end (** The number of supported tactics. *) - let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics ctx#gno + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) (** The names of all supported tactics. *) let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in - let f i = (Z3native.get_tactic_name ctx#gno i) in + let f i = (Z3native.get_tactic_name (context_gno ctx) i) in Array.init n f @@ -4444,39 +4424,34 @@ end Returns a string containing a description of the tactic with the given name. *) let get_tactic_description ( ctx : context ) ( name : string ) = - Z3native.tactic_get_descr ctx#gno name + Z3native.tactic_get_descr (context_gno ctx) name (** Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - (new tactic ctx)#cnstr_obj (Z3native.mk_tactic ctx#gno name) + (new tactic ctx)#cnstr_obj (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and then to every subgoal produced by . *) - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array option ) = - match - match ts with - | None -> None - | Some(rts) -> ( - let f p c = (match p with - | None -> (Some c#gno) - | Some(x) -> (Some (Z3native.tactic_and_then ctx#gno c#gno x))) in - Array.fold_left f None rts) - with - | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = + let f p c = (match p with + | None -> (Some c#gno) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) c#gno x))) in + match (Array.fold_left f None ts) with + | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno t2#gno) | Some(x) -> - let o = (Z3native.tactic_and_then ctx#gno t2#gno x) in - (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno o) + let o = (Z3native.tactic_and_then (context_gno ctx) t2#gno x) in + (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else (context_gno ctx) t1#gno t2#gno) (** Create a tactic that applies to a goal for milliseconds. @@ -4484,7 +4459,7 @@ end If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for ctx#gno t#gno ms) + (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for (context_gno ctx) t#gno ms) (** Create a tactic that applies to a given goal if the probe @@ -4494,52 +4469,52 @@ end *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when ctx#gno p#gno t#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) p#gno t#gno) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) p#gno t1#gno t2#gno) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat ctx#gno t#gno max) + (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat (context_gno ctx) t#gno max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_skip ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if ctx#gno p#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) p#gno) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params ctx#gno t#gno p#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params (context_gno ctx) t#gno p#gno) (** Create a tactic that applies using the given set of parameters . @@ -4552,21 +4527,21 @@ end Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or ctx#gno (Array.length t) (tacticaton t)) + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (tacticaton t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then (context_gno ctx) t1#gno t2#gno) (** Interrupt the execution of a Z3 procedure. This procedure can be used to interrupt: solvers, simplifiers and tactics. *) let interrupt ( ctx : context ) = - Z3native.interrupt ctx#gno + Z3native.interrupt (context_gno ctx) end (** Probes @@ -4591,68 +4566,68 @@ struct The number of supported Probes. *) let get_num_probes ( ctx : context ) = - Z3native.get_num_probes ctx#gno + Z3native.get_num_probes (context_gno ctx) (** The names of all supported Probes. *) let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name ctx#gno i) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in Array.init n f (** Returns a string containing a description of the probe with the given name. *) let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr ctx#gno name + Z3native.probe_get_descr (context_gno ctx) name (** Creates a new Probe. *) let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + (new probe ctx)#cnstr_obj (Z3native.mk_probe (context_gno ctx) name) (** Create a probe that always evaluates to . *) let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + (new probe ctx)#cnstr_obj (Z3native.probe_const (context_gno ctx) v) (** Create a probe that evaluates to "true" when the value returned by is less than the value returned by *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_lt (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is greater than the value returned by *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_gt (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is less than or equal the value returned by *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_le (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is greater than or equal the value returned by *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_ge (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is equal to the value returned by *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_eq (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4660,7 +4635,7 @@ struct *) (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_and (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4668,7 +4643,7 @@ struct *) (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_or (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4676,7 +4651,7 @@ struct *) (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) end (** Solvers *) @@ -4836,11 +4811,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array option) = + let check ( x : solver ) ( assumptions : bool_expr array) = let r = - match assumptions with - | None -> lbool_of_int (Z3native.solver_check x#gnc x#gno) - | Some (ass) -> lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length ass) (astaton ass)) + if ((Array.length assumptions) == 0) then + lbool_of_int (Z3native.solver_check x#gnc x#gno) + else + lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length assumptions) (astaton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -4907,8 +4883,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver ctx#gno) - | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic ctx#gno x#gno) + | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver (context_gno ctx)) + | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic (context_gno ctx) x#gno) (** Creates a new (incremental) solver. @@ -4921,7 +4897,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver ctx#gno) + (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver (context_gno ctx)) (** Creates a solver that is implemented using the given tactic. @@ -4930,7 +4906,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic ctx#gno t#gno) + (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno) (** A string representation of the solver. @@ -5333,7 +5309,7 @@ struct Create a Fixedpoint context. *) let mk_fixedpoint ( ctx : context ) = - (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) + (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint (context_gno ctx)) end (** Global and context options @@ -5354,7 +5330,7 @@ struct *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value ctx#gno id value + Z3native.update_param_value (context_gno ctx) id value (** Get a configuration parameter. @@ -5363,7 +5339,7 @@ struct *) let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value ctx#gno id) in + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then None else @@ -5385,7 +5361,7 @@ struct *) let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode ctx#gno (int_of_ast_print_mode value) + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) (** Enable/disable printing of warning messages to the console. @@ -5412,7 +5388,7 @@ struct @return A string representation of the benchmark. *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = - Z3native.benchmark_to_smtlib_string ctx#gno name logic status attributes + Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes (Array.length assumptions) (astaton assumptions) formula#gno @@ -5425,92 +5401,93 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib_string ctx#gno str + Z3native.parse_smtlib_string (context_gno ctx) str cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib_file ctx#gno file_name + Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas ctx#gno + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_formula ctx#gno i)) :> bool_expr) in + let f i = ((create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) :> bool_expr) in Array.init n f (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions ctx#gno + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i)) :> bool_expr ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) :> bool_expr ) in Array.init n f (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls ctx#gno + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl ctx#gno i) in + let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts ctx#gno + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (create_sort ctx (Z3native.get_smtlib_sort ctx#gno i)) in + let f i = (create_sort ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5519,41 +5496,41 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string ctx#gno str + Z3native.parse_smtlib2_string (context_gno ctx) str cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string ctx#gno file_name + Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) end (* From bbd1e465bb73b3dd8a757142b2c59c42552c2795 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 00:01:50 +0000 Subject: [PATCH 289/646] ML API: bugfixes; starting to replace objects with normal types. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 3 +- scripts/update_api.py | 3 +- src/api/ml/z3.ml | 711 ++++++++++++++++++++------------------ 3 files changed, 382 insertions(+), 335 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 129f73d4d..97985a7bc 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,6 +14,7 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic +open Z3.Fixedpoints exception TestFailedException of string @@ -216,8 +217,8 @@ let _ = Printf.printf "bool sort: %s\n" (Sort.to_string bs); Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); - Printf.printf "Disposing...\n"; basic_tests ctx ; + Printf.printf "Disposing...\n"; Gc.full_major () ); Printf.printf "Exiting.\n"; diff --git a/scripts/update_api.py b/scripts/update_api.py index 1986f4a7e..c730a325e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1300,7 +1300,8 @@ def mk_ml(): ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') - ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') + ml_wrapper.write(' void * t = * (void**) Data_custom_val(p);\n') + ml_wrapper.write(' return Val_bool(t == 0);\n') ml_wrapper.write('}\n\n') ml_wrapper.write('CAMLprim value n_mk_null( void ) {\n') ml_wrapper.write(' CAMLparam0();\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c91d909bc..1e8ffe92e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,9 +7,13 @@ open Z3enums -type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } + +(**/**) + +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) -(**/**) let context_dispose ctx = if ctx.m_n_obj_cnt == 0 then ( (* Printf.printf "Disposing context \n" ; *) @@ -19,7 +23,7 @@ let context_dispose ctx = (* re-queue for finalization? *) ) -let context_init settings = +let context_cnstr settings = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; @@ -50,7 +54,7 @@ require one such object, but power users may require more than one. To start usi Z3, do - let ctx = (mk_context None) in + let ctx = (mk_context []) in (...) @@ -58,17 +62,18 @@ where a list of pairs of strings may be passed to set options on the context, e.g., like so: - let cfg = (Some [("model", "true"); ("...", "...")]) in + let cfg = [("model", "true"); ("...", "...")] in let ctx = (mk_context cfg) in (...) *) let mk_context ( cfg : ( string * string ) list ) = - context_init cfg + context_cnstr cfg + + +(* type z3object = { m_ctx : context; m_n_obj : Z3native.ptr option; } *) (**/**) - -(** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) val mutable m_ctx : context = ctx_init @@ -669,15 +674,6 @@ object (self) method decref nc o = Z3native.func_interp_dec_ref nc o end -(** Model objects *) -class model ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.model_inc_ref nc o - method decref nc o = Z3native.model_dec_ref nc o -end - (** Tactic application result objects *) class apply_result ctx = object (self) @@ -724,32 +720,38 @@ object (self) method is_float = m_is_float end -(** Statistics objects *) -class statistics ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.stats_inc_ref nc o - method decref nc o = Z3native.stats_dec_ref nc o -end -(** Solver objects *) -class solver ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.solver_inc_ref nc o - method decref nc o = Z3native.solver_dec_ref nc o -end +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } -(** Fixedpoint objects *) -class fixedpoint ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.fixedpoint_inc_ref nc o - method decref nc o = Z3native.fixedpoint_dec_ref nc o -end +let z3obj_gc o = o.m_ctx +let z3obj_gnc o = (context_gno o.m_ctx) + +let z3obj_gno o = o.m_n_obj +let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + +let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + +let z3obj_cnstr o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o (**/**) @@ -1878,7 +1880,6 @@ struct (astaton names) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1900,7 +1901,6 @@ struct (Array.length patterns) (patternaton patterns) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1924,7 +1924,6 @@ struct (astaton names) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1946,7 +1945,6 @@ struct (Array.length patterns) (patternaton patterns) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -4347,6 +4345,240 @@ struct end +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + type model = z3_native_object + + (**/**) + let model_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : model = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr (z3obj_gc x) np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if not (Z3native.is_as_array (z3obj_gnc x) n) then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp (z3obj_gc x))#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) t#gno completion) in + if not r then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr (z3obj_gc x) v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) +end + + (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. @@ -4380,8 +4612,8 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = - (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.model_cnstr x#gc (Z3native.apply_result_convert_model x#gnc x#gno i (z3obj_gno m)) (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno @@ -4401,11 +4633,6 @@ end | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) - (** creates a solver that is implemented using the given tactic. - *) - let get_solver ( x : tactic ) = - (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) - (** The number of supported tactics. *) @@ -4654,9 +4881,23 @@ struct (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) end + (** Solvers *) module Solver = struct + type solver = z3_native_object + +(**/**) + let solver_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : solver = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.solver_inc_ref ; + dec_ref = Z3native.solver_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res +(**/**) + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE let string_of_status ( s : status) = match s with @@ -4667,6 +4908,18 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = struct + type statistics = z3_native_object + + (**/**) + let statistics_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : statistics = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.stats_inc_ref ; + dec_ref = Z3native.stats_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** Statistical data is organized into pairs of [Key, Entry], where every @@ -4703,20 +4956,20 @@ struct end (** A string representation of the statistical data. *) - let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) (** The number of statistical data. *) - let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) (** The data entries. *) let get_entries ( x : statistics ) = let n = (get_size x ) in let f i = ( - let k = Z3native.stats_get_key x#gnc x#gno i in - if (Z3native.stats_is_uint x#gnc x#gno i) then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in + if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -4725,7 +4978,7 @@ struct *) let get_keys ( x : statistics ) = let n = (get_size x) in - let f i = (Z3native.stats_get_key x#gnc x#gno i) in + let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** @@ -4739,51 +4992,51 @@ struct (** A string that describes all available solver parameters. *) - let get_help ( x : solver ) = Z3native.solver_get_help x#gnc x#gno + let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) (** Sets the solver parameters. *) let set_parameters ( x : solver ) ( value : params )= - Z3native.solver_set_params x#gnc x#gno value#gno + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) value#gno (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.solver_get_param_descrs x#gnc x#gno) + (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). *) - let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes x#gnc x#gno + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) (** Creates a backtracking point. *) - let push ( x : solver ) = Z3native.solver_push x#gnc x#gno + let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) (** Backtracks backtracking points. Note that an exception is thrown if is not smaller than NumScopes *) - let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n (** Resets the Solver. This removes all assertions from the solver. *) - let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno + let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) (** Assert a constraint (or multiple) into the solver. *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = - let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in ignore (Array.map f constraints) ; () @@ -4791,7 +5044,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -4799,9 +5052,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get a i)#gno) in + let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -4814,9 +5067,9 @@ struct let check ( x : solver ) ( assumptions : bool_expr array) = let r = if ((Array.length assumptions) == 0) then - lbool_of_int (Z3native.solver_check x#gnc x#gno) + lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length assumptions) (astaton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (astaton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -4830,11 +5083,11 @@ struct if its results was not SATISFIABLE, or if model production is not enabled. *) let get_model ( x : solver ) = - let q = Z3native.solver_get_model x#gnc x#gno in + let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then None else - Some ((new model x#gc)#cnstr_obj q) + Some (Model.model_cnstr (z3obj_gc x) q) (** The proof of the last Check. @@ -4843,11 +5096,11 @@ struct if its results was not UNSATISFIABLE, or if proof production is disabled. *) let get_proof ( x : solver ) = - let q = Z3native.solver_get_proof x#gnc x#gno in + let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** The unsat core of the last Check. @@ -4857,7 +5110,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in + let cn = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -4865,14 +5118,14 @@ struct (** A brief justification of why the last call to Check returned UNKNOWN. *) - let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown x#gnc x#gno + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) (** Solver statistics. *) let get_statistics ( x : solver ) = - (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + (Statistics.statistics_cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -4883,8 +5136,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver (context_gno ctx)) - | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic (context_gno ctx) x#gno) + | None -> (solver_cnstr ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (solver_cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) (** Creates a new (incremental) solver. @@ -4897,7 +5150,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver (context_gno ctx)) + (solver_cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -4906,261 +5159,54 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno) + (solver_cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) (** A string representation of the solver. *) - let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno + let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) -module Model = -struct - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) - module FuncInterp = - struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null np) then - None - else - Some (create_expr x#gc np) - - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if not (Z3native.is_as_array x#gnc n) then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl x#gnc n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno - - (** The function declarations of the constants in the model. *) - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.init n f - - - (** The number of function interpretations in the model. *) - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno - - (** The function declarations of the function interpretations in the model. *) - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - Array.init n f - - (** All symbols that have an interpretation in the model. *) - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. - *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno completion) in - if not r then - raise (ModelEvaluationFailedException "evaluation failed") - else - create_expr x#gc v - - (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - - *) - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in - Array.init n f - - - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of - *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - Array.init n f - - (** Conversion of models to strings. - A string representation of the model. - *) - let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno -end - (** Fixedpoint solving *) module Fixedpoints = struct + type fixedpoint = z3_native_object + +(**/**) + let fixedpoint_cnstr ( ctx : context ) = + let res : fixedpoint = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.fixedpoint_inc_ref ; + dec_ref = Z3native.fixedpoint_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; + (z3obj_cnstr res) ; + res +(**/**) + (** A string that describes all available fixedpoint solver parameters. *) let get_help ( x : fixedpoint ) = - Z3native.fixedpoint_get_help x#gnc x#gno + Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) (** Sets the fixedpoint solver parameters. *) let set_params ( x : fixedpoint ) ( p : params )= - Z3native.fixedpoint_set_params x#gnc x#gno p#gno + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) p#gno (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.fixedpoint_get_param_descrs x#gnc x#gno) + (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. *) let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = - let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in ignore (Array.map f constraints) ; () @@ -5168,21 +5214,21 @@ struct Register predicate as recursive relation. *) let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation x#gnc x#gno f#gno + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) f#gno (** Add rule into the fixedpoint solver. *) let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno (Z3native.mk_null()) - | Some(y) -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno y#gno + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno y#gno (** Add table fact to the fixedpoint solver. *) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact x#gnc x#gno pred#gno (Array.length args) args + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) pred#gno (Array.length args) args (** Query the fixedpoint solver. @@ -5191,7 +5237,7 @@ struct The query is unsatisfiable if there are no derivations satisfying the query variables. *) let query ( x : fixedpoint ) ( query : bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query x#gnc x#gno query#gno)) with + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) query#gno)) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5203,7 +5249,7 @@ struct The query is unsatisfiable if there are no derivations satisfying any of the relations. *) let query_r ( x : fixedpoint ) ( relations : func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations x#gnc x#gno (Array.length relations) (func_declaton relations))) with + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (func_declaton relations))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5213,7 +5259,7 @@ struct *) let push ( x : fixedpoint ) = - Z3native.fixedpoint_push x#gnc x#gno + Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) (** Backtrack one backtracking point. @@ -5222,94 +5268,93 @@ struct *) let pop ( x : fixedpoint ) = - Z3native.fixedpoint_pop x#gnc x#gno + Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) (** Update named rule into in the fixedpoint solver. *) let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = - Z3native.fixedpoint_update_rule x#gnc x#gno rule#gno name#gno + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno name#gno (** Retrieve satisfying instance or instances of solver, or definitions for the recursive predicates that show unsatisfiability. *) let get_answer ( x : fixedpoint ) = - let q = (Z3native.fixedpoint_get_answer x#gnc x#gno) in + let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. *) let get_reason_unknown ( x : fixedpoint ) = - Z3native.fixedpoint_get_reason_unknown x#gnc x#gno + Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) (** Retrieve the number of levels explored for a given predicate. *) let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels x#gnc x#gno predicate#gno + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) predicate#gno (** Retrieve the cover of a predicate. *) let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta x#gnc x#gno level predicate#gno) in + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level predicate#gno) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover x#gnc x#gno level predicate#gno, property#gno + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level predicate#gno property#gno (** Retrieve internal string representation of fixedpoint object. *) - let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string x#gnc x#gno 0 [||] + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = - Z3native.fixedpoint_set_predicate_representation x#gnc x#gno f#gno (Array.length kinds) (symbolaton kinds) + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (symbolaton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string x#gnc x#gno (Array.length queries) (astaton queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (astaton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_rules x#gnc x#gno)) in + let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_assertions x#gnc x#gno)) in + let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = - (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint (context_gno ctx)) + let mk_fixedpoint ( ctx : context ) = fixedpoint_cnstr ctx end (** Global and context options From bcc0c14233fa0af46e95c945692726218d61eae3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 01:15:23 +0000 Subject: [PATCH 290/646] ML API: moved more objects into normal types. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 1 - src/api/ml/z3.ml | 766 +++++++++++++++++++------------------- 2 files changed, 392 insertions(+), 375 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 97985a7bc..38b5fe642 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,7 +14,6 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic -open Z3.Fixedpoints exception TestFailedException of string diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 1e8ffe92e..545c7c227 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -20,7 +20,7 @@ let context_dispose ctx = (Z3native.del_context ctx.m_n_ctx) ) else ( Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) let context_cnstr settings = @@ -38,7 +38,7 @@ let context_cnstr settings = (* CMW: Install error handler here! m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + GC.SuppressFinalize(this); *) let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) @@ -49,23 +49,23 @@ let context_gno ctx = ctx.m_n_ctx (** Create a context object. -Most interactions with Z3 are interpreted in some context; many users will only -require one such object, but power users may require more than one. To start using -Z3, do + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do - + let ctx = (mk_context []) in (...) - + -where a list of pairs of strings may be passed to set options on -the context, e.g., like so: + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: - + let cfg = [("model", "true"); ("...", "...")] in let ctx = (mk_context cfg) in (...) - + *) let mk_context ( cfg : ( string * string ) list ) = context_cnstr cfg @@ -656,70 +656,6 @@ let tacticaton (a : tactic array) = let f (e : tactic) = e#gno in Array.map f a -(** Function interpretation entry objects *) -class func_entry ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.func_entry_inc_ref nc o - method decref nc o = Z3native.func_entry_dec_ref nc o -end - -(** Function interpretation objects *) -class func_interp ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.func_interp_inc_ref nc o - method decref nc o = Z3native.func_interp_dec_ref nc o -end - -(** Tactic application result objects *) -class apply_result ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.apply_result_inc_ref nc o - method decref nc o = Z3native.apply_result_dec_ref nc o -end - -(** Probe objects *) -class probe ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.probe_inc_ref nc o - method decref nc o = Z3native.probe_dec_ref nc o -end - -(** Statistical value objects *) -class statistics_entry = -object (self) - val mutable m_key : string = "" - val mutable m_is_int = false - val mutable m_is_float = false - val mutable m_int = 0 - val mutable m_float = 0.0 - - method cnstr_si k v = - m_key <- k; - m_is_int <- true; - m_int <- v; - self - - method cnstr_sd k v = - m_key <- k; - m_is_float <- true; - m_float <- v; - self - - method key = m_key - method int = m_int - method float = m_float - method is_int = m_is_int - method is_float = m_is_float -end - type z3_native_object = { m_ctx : context ; @@ -1012,46 +948,46 @@ struct x#rational end - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name domain range + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name domain range - (** - Creates a new function declaration. - *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = + mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range - (** - Creates a fresh function declaration with a name prefixed with . - - - *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix domain range + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix domain range - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name [||] range + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name [||] range - (** - Creates a new constant function declaration. - *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix [||] range + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix [||] range (** @@ -1333,31 +1269,31 @@ struct else (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) -(** - Wraps an AST. + (** + Wraps an AST. - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. -*) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create_ast ctx ptr + create_ast ctx ptr -(** - Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. -*) + (** + Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + *) let unwrap_ast ( a : ast ) = a#gno end @@ -1373,17 +1309,17 @@ struct | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) -(** - a string describing all available parameters to Expr.Simplify. -*) + (** + a string describing all available parameters to Expr.Simplify. + *) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) -(** - Retrieves parameter descriptions for simplifier. -*) - let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) + (** + Retrieves parameter descriptions for simplifier. + *) + let get_simplify_parameter_descrs ( ctx : context ) = + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -2691,7 +2627,7 @@ struct let (r, v) = Z3native.get_numeral_int x#gnc x#gno in if r then v else raise (Z3native.Exception "Conversion failed.") - + (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3202,7 +3138,7 @@ struct let (r, v) = Z3native.get_numeral_int x#gnc x#gno in if r then v else raise (Z3native.Exception "Conversion failed.") - + (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -4150,29 +4086,29 @@ end *) module Params = struct -(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) -module ParamDescrs = -struct + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs = + struct - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno -end + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno + end (** Adds a parameter setting. @@ -4353,11 +4289,11 @@ struct type model = z3_native_object (**/**) - let model_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.model_inc_ref ; - dec_ref = Z3native.model_dec_ref } in + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res @@ -4370,6 +4306,18 @@ struct *) module FuncInterp = struct + type func_interp = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_interp = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_interp_inc_ref ; + dec_ref = Z3native.func_interp_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** Function interpretations entries @@ -4377,23 +4325,36 @@ struct *) module FuncEntry = struct + type func_entry = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_entry = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_entry_inc_ref ; + dec_ref = Z3native.func_entry_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + create_expr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) (** The arguments of the function entry. *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + let f i = (create_expr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4408,25 +4369,25 @@ struct (** The number of entries in the function interpretation. *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) (** The entries in the function interpretation *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + let f i = (FuncEntry.cnstr (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + let get_else ( x : func_interp ) = create_expr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) (** A string representation of the function interpretation. @@ -4486,7 +4447,7 @@ struct | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp (z3obj_gc x))#cnstr_obj n) + if (Z3native.is_null n) then None else Some (FuncInterp.cnstr (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) @@ -4579,6 +4540,130 @@ struct end +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = +struct + type probe = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : probe = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.probe_inc_ref ; + dec_ref = Z3native.probe_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. + *) + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) g#gno + + (** + The number of supported Probes. + *) + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes (context_gno ctx) + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in + Array.init n f + + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr (context_gno ctx) name + + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (cnstr ctx (Z3native.mk_probe (context_gno ctx) name)) + + (** + Create a probe that always evaluates to . + *) + let const ( ctx : context ) ( v : float ) = + (cnstr ctx (Z3native.probe_const (context_gno ctx) v)) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by + *) + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (cnstr ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) +end + + (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. @@ -4588,36 +4673,49 @@ end *) module Tactic = struct -(** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) -module ApplyResult = -struct - (** The number of Subgoals. *) - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals x#gnc x#gno + (** Tactic application results - (** Retrieves the subgoals from the apply_result. *) - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in - Array.init n f - - (** Retrieves the subgoals from the apply_result. *) - let get_subgoal ( x : apply_result ) ( i : int ) = - (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) - - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.model_cnstr x#gc (Z3native.apply_result_convert_model x#gnc x#gno i (z3obj_gno m)) - - (** A string representation of the ApplyResult. *) - let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno -end + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) + module ApplyResult = + struct + type apply_result = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : apply_result = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.apply_result_inc_ref ; + dec_ref = Z3native.apply_result_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoal ( x : apply_result ) ( i : int ) = + (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.cnstr (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) + end (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno @@ -4630,8 +4728,8 @@ end (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : goal ) ( p : params option ) = match p with - | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) - | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) + | None -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply x#gnc x#gno g#gno)) + | Some (pn) -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno)) (** The number of supported tactics. @@ -4695,15 +4793,15 @@ end If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) p#gno t#gno) + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) t#gno) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) p#gno t1#gno t2#gno) + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) t1#gno t2#gno) (** Create a tactic that keeps applying until the goal is not @@ -4727,8 +4825,8 @@ end (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) p#gno) + let fail_if ( ctx : context ) ( p : Probe.probe ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) @@ -4771,124 +4869,14 @@ end Z3native.interrupt (context_gno ctx) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe = -struct - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply x#gnc x#gno g#gno - - (** - The number of supported Probes. - *) - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes (context_gno ctx) - - (** - The names of all supported Probes. - *) - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name (context_gno ctx) i) in - Array.init n f - - (** - Returns a string containing a description of the probe with the given name. - *) - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr (context_gno ctx) name - - (** - Creates a new Probe. - *) - let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe (context_gno ctx) name) - - (** - Create a probe that always evaluates to . - *) - let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const (context_gno ctx) v) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) - let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) -end - (** Solvers *) module Solver = struct type solver = z3_native_object -(**/**) - let solver_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.solver_inc_ref ; @@ -4896,7 +4884,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res -(**/**) + (**/**) type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE @@ -4911,7 +4899,7 @@ struct type statistics = z3_native_object (**/**) - let statistics_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.stats_inc_ref ; @@ -4919,28 +4907,58 @@ struct (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res - (**/**) + (**/**) (** - Statistical data is organized into pairs of [Key, Entry], where every - Entry is either a DoubleEntry or a UIntEntry + Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) module Entry = struct + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + + (**/**) + let cnstr_si k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = true ; + m_is_float = false ; + m_int = v ; + m_float = 0.0 + } in + res + + let cnstr_sd k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = false ; + m_is_float = true ; + m_int = 0 ; + m_float = v + } in + res + (**/**) + (** The key of the entry. *) - let get_key (x : statistics_entry) = x#key + let get_key (x : statistics_entry) = x.m_key (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x#int + let get_int (x : statistics_entry) = x.m_int (** The float-value of the entry. *) - let get_float (x : statistics_entry) = x#float + let get_float (x : statistics_entry) = x.m_float (** True if the entry is uint-valued. *) - let is_int (x : statistics_entry) = x#is_int + let is_int (x : statistics_entry) = x.m_is_int (** True if the entry is double-valued. *) - let is_float (x : statistics_entry) = x#is_float + let is_float (x : statistics_entry) = x.m_is_float (** The string representation of the the entry's value. *) let to_string_value (x : statistics_entry) = @@ -4967,9 +4985,9 @@ struct let f i = ( let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -5087,7 +5105,7 @@ struct if (Z3native.is_null q) then None else - Some (Model.model_cnstr (z3obj_gc x) q) + Some (Model.cnstr (z3obj_gc x) q) (** The proof of the last Check. @@ -5125,7 +5143,7 @@ struct Solver statistics. *) let get_statistics ( x : solver ) = - (Statistics.statistics_cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + (Statistics.cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -5136,8 +5154,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (solver_cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (solver_cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) + | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) (** Creates a new (incremental) solver. @@ -5150,7 +5168,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (solver_cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) + (cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -5159,7 +5177,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (solver_cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) + (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) (** A string representation of the solver. @@ -5169,12 +5187,12 @@ end (** Fixedpoint solving *) -module Fixedpoints = +module Fixedpoint = struct type fixedpoint = z3_native_object -(**/**) - let fixedpoint_cnstr ( ctx : context ) = + (**/**) + let cnstr ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.fixedpoint_inc_ref ; @@ -5182,7 +5200,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_cnstr res) ; res -(**/**) + (**/**) (** A string that describes all available fixedpoint solver parameters. @@ -5320,7 +5338,7 @@ struct Retrieve internal string representation of fixedpoint object. *) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) @@ -5354,7 +5372,7 @@ struct (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = fixedpoint_cnstr ctx + let mk_fixedpoint ( ctx : context ) = cnstr ctx end (** Global and context options @@ -5365,24 +5383,24 @@ end module Options = struct -(** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - -*) + (** + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + + *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value -(** - Get a configuration parameter. - - Returns None if the parameter value does not exist. - -*) + (** + Get a configuration parameter. + + Returns None if the parameter value does not exist. + + *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then @@ -5408,12 +5426,12 @@ struct let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) -(** - Enable/disable printing of warning messages to the console. + (** + Enable/disable printing of warning messages to the console. - Note that this function is static and effects the behaviour of - all contexts globally. -*) + Note that this function is static and effects the behaviour of + all contexts globally. + *) let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled end @@ -5581,17 +5599,17 @@ end (* (** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. *) - public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); + public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - internal Z3native.error_handler m_n_err_handler = null; + internal Z3native.error_handler m_n_err_handler = null; - internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) + internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. *) From d0fea5e7404c9e99ace0930a80f8f207a67a25af Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 23:18:05 +0000 Subject: [PATCH 291/646] ML API: moved more objects into normal types. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 734 ++++++++++++++++++++++++++--------------------- 1 file changed, 412 insertions(+), 322 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 545c7c227..8c0f24c4b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,13 +7,30 @@ open Z3enums -type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } - -(**/**) - +(**/**) +(* Some helpers. *) + let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) +let mk_list ( f : int -> 'a ) ( n : int ) = + let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = + if (i >= n) then + tail + else + (mk_list' f (i+1) n ((f i) :: tail)) + in + mk_list' f 0 n [] +(**/**) + + +(**/**) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +(**/**) +type context = z3_native_context + +(**/**) + let context_dispose ctx = if ctx.m_n_obj_cnt == 0 then ( (* Printf.printf "Disposing context \n" ; *) @@ -71,8 +88,6 @@ let mk_context ( cfg : ( string * string ) list ) = context_cnstr cfg -(* type z3object = { m_ctx : context; m_n_obj : Z3native.ptr option; } *) - (**/**) class virtual z3object ctx_init obj_init = object (self) @@ -120,17 +135,6 @@ object (self) method gnc = (context_gno m_ctx) end - -(** Parameter set objects *) -class params ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.params_inc_ref nc o - method decref nc o = Z3native.params_dec_ref nc o -end - - (** Symbol objects *) class symbol ctx = object (self) @@ -292,44 +296,6 @@ let func_declaton (a : func_decl array) = let f (e : func_decl) = e#gno in Array.map f a -class parameter = -object (self) - val mutable m_kind : parameter_kind = PARAMETER_INT; - val mutable m_i : int = 0 - val mutable m_d : float = 0.0 - val mutable m_sym : symbol option = None - val mutable m_srt : sort option = None - val mutable m_ast : ast option = None - val mutable m_fd : func_decl option = None - val mutable m_r : string = "" - - method cnstr_int i = m_kind <- PARAMETER_INT; m_i <- i - method cnstr_double d = m_kind <- PARAMETER_DOUBLE; m_d <- d - method cnstr_symbol sym = m_kind <- PARAMETER_SYMBOL; m_sym <- sym - method cnstr_sort srt = m_kind <- PARAMETER_SORT; m_srt <- srt - method cnstr_ast ast = m_kind <- PARAMETER_AST; m_ast <- ast - method cnstr_func_decl fd = m_kind <- PARAMETER_FUNC_DECL; m_fd <- fd - method cnstr_rational r = m_kind <- PARAMETER_RATIONAL; m_r <- r - - method kind = m_kind - method int = m_i - method double = m_d - method symbol = match m_sym with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter symbol") - method sort = match m_srt with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter sort") - method ast = match m_ast with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter ast") - method func_decl = match m_fd with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter func_decl") - method rational = m_r -end - - (** Enum sort objects *) class enum_sort ctx = object (self) @@ -499,26 +465,6 @@ let create_sort ctx obj = | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") -(** AST vector objects *) -class ast_vector ctx = -object (self) - inherit z3object ctx None - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.ast_vector_inc_ref nc o - method decref nc o = Z3native.ast_vector_dec_ref nc o -end - - -(** AST map objects *) -class ast_map ctx = -object (self) - inherit z3object ctx None - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.ast_map_inc_ref nc o - method decref nc o = Z3native.ast_map_dec_ref nc o -end - - (** Expression objects *) class expr ctx = object(self) @@ -625,37 +571,6 @@ let patternaton (a : pattern array) = let f (e : pattern) = e#gno in Array.map f a -(** Parameter description objects *) -class param_descrs ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.param_descrs_inc_ref nc o - method decref nc o = Z3native.param_descrs_dec_ref nc o -end - -(** Goal objects *) -class goal ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.goal_inc_ref nc o - method decref nc o = Z3native.goal_dec_ref nc o -end - -(** Tactic objects *) -class tactic ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.tactic_inc_ref nc o - method decref nc o = Z3native.tactic_dec_ref nc o -end - -let tacticaton (a : tactic array) = - let f (e : tactic) = e#gno in - Array.map f a - type z3_native_object = { m_ctx : context ; @@ -689,6 +604,10 @@ let z3obj_cnstr o = let f = fun o -> (z3obj_dispose o) in Gc.finalise f o +let array_to_native a = + let f e = (z3obj_gno e) in + Array.map f a + (**/**) @@ -890,62 +809,153 @@ let create_ast ctx no = (** Function declarations *) module FuncDecl = struct + (** Parameters of Func_Decls *) module Parameter = struct + type parameter = { + m_kind : parameter_kind ; + m_i : int ; + m_d : float ; + m_sym : symbol option ; + m_srt : sort option ; + m_ast : ast option ; + m_fd : func_decl option ; + m_r : string ; + } + + (**/**) + let cnstr_int i = { + m_kind = PARAMETER_INT ; + m_i = i ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_double d = { + m_kind = PARAMETER_DOUBLE ; + m_i = 0 ; + m_d = d ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_symbol sym = { + m_kind = PARAMETER_SYMBOL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = sym ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_sort srt = { + m_kind = PARAMETER_SORT ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = srt ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_ast ast = { + m_kind = PARAMETER_AST ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = ast ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_func_decl fd ={ + m_kind = PARAMETER_FUNC_DECL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = fd ; + m_r = "" ; + } + + let cnstr_rational r = { + m_kind = PARAMETER_RATIONAL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = r ; + } + (**/**) + (** The kind of the parameter. *) - let get_kind (x : parameter) = x#kind + let get_kind ( x : parameter ) = x.m_kind (**The int value of the parameter.*) - let get_int (x : parameter) = - if (x#kind != PARAMETER_INT) then + let get_int ( x : parameter ) = + if ((get_kind x) != PARAMETER_INT) then raise (Z3native.Exception "parameter is not an int") else - x#int + x.m_i (**The double value of the parameter.*) - let get_double (x : parameter) = - if (x#kind != PARAMETER_DOUBLE) then + let get_double ( x : parameter ) = + if ((get_kind x) != PARAMETER_DOUBLE) then raise (Z3native.Exception "parameter is not a double") else - x#double + x.m_d (**The Symbol value of the parameter.*) - let get_symbol (x : parameter) = - if (x#kind != PARAMETER_SYMBOL) then + let get_symbol ( x : parameter ) = + if ((get_kind x) != PARAMETER_SYMBOL) then raise (Z3native.Exception "parameter is not a symbol") else - x#symbol + x.m_sym (**The Sort value of the parameter.*) - let get_sort (x : parameter) = - if (x#kind != PARAMETER_SORT) then + let get_sort ( x : parameter ) = + if ((get_kind x) != PARAMETER_SORT) then raise (Z3native.Exception "parameter is not a sort") else - x#sort + x.m_srt (**The AST value of the parameter.*) - let get_ast (x : parameter) = - if (x#kind != PARAMETER_AST) then + let get_ast ( x : parameter ) = + if ((get_kind x) != PARAMETER_AST) then raise (Z3native.Exception "parameter is not an ast") else - x#ast + x.m_ast (**The FunctionDeclaration value of the parameter.*) - let get_ast (x : parameter) = - if (x#kind != PARAMETER_FUNC_DECL) then + let get_ast ( x : parameter ) = + if ((get_kind x) != PARAMETER_FUNC_DECL) then raise (Z3native.Exception "parameter is not an function declaration") else - x#func_decl + x.m_fd (**The rational string value of the parameter.*) - let get_rational (x : parameter) = - if (x#kind != PARAMETER_RATIONAL) then + let get_rational ( x : parameter ) = + if ((get_kind x) != PARAMETER_RATIONAL) then raise (Z3native.Exception "parameter is not a ratinoal string") else - x#rational + x.m_r end (** @@ -1051,7 +1061,7 @@ struct The number of parameters of the function declaration *) let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) - + (** The parameters of the function declaration *) @@ -1059,15 +1069,15 @@ struct let n = (get_num_parameters x) in let f i = ( match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with - | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) - | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) - | PARAMETER_SORT -> (new parameter)#cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) - | PARAMETER_AST -> (new parameter)#cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) - | PARAMETER_FUNC_DECL -> (new parameter)#cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) - | PARAMETER_RATIONAL -> (new parameter)#cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) + | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) + | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) + | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) + | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) + | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) + | PARAMETER_RATIONAL -> Parameter.cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) ) in - Array.init n f + mk_list f n (** Create expression that applies function to arguments. @@ -1083,9 +1093,22 @@ struct (** Vectors of ASTs *) module ASTVector = struct + type ast_vector = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_vector = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_vector_inc_ref ; + dec_ref = Z3native.ast_vector_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** The size of the vector *) let get_size ( x : ast_vector ) = - Z3native.ast_vector_size x#gnc x#gno + Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) (** Retrieves the i-th object in the vector. @@ -1093,16 +1116,16 @@ struct @return An AST *) let get ( x : ast_vector ) ( i : int ) = - create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + create_ast (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set x#gnc x#gno i value#gno + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i value#gno (** Resize the vector to . @param newSize The new size of the vector. *) let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize x#gnc x#gno new_size + Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size (** Add the AST to the back of the vector. The size @@ -1110,7 +1133,7 @@ struct @param a An AST *) let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push x#gnc x#gno a#gno + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) a#gno (** Translates all ASTs in the vector to . @@ -1118,60 +1141,73 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno (context_gno to_ctx)) + cnstr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string x#gnc x#gno + Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) end (** Map from AST to AST *) module ASTMap = struct + type ast_map = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Checks whether the map contains the key . @param k An AST @return True if is a key in the map, false otherwise. *) - let contains ( m : ast_map ) ( key : ast ) = - (Z3native.ast_map_contains m#gnc m#gno key#gno) + let contains ( x : ast_map ) ( key : ast ) = + (Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) key#gno) (** Finds the value associated with the key . This function signs an error when is not a key in the map. @param k An AST *) - let find ( m : ast_map ) ( key : ast ) = - create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + let find ( x : ast_map ) ( key : ast ) = + create_ast (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) key#gno) (** Stores or replaces a new key/value pair in the map. @param k The key AST @param v The value AST *) - let insert ( m : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) key#gno value#gno (** Erases the key from the map. @param k An AST *) - let erase ( m : ast_map ) ( key : ast ) = - Z3native.ast_map_erase m#gnc m#gno key#gno + let erase ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) key#gno (** Removes all keys from the map. *) - let reset ( m : ast_map ) = - Z3native.ast_map_reset m#gnc m#gno + let reset ( x : ast_map ) = + Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) (** The size of the map *) - let get_size ( m : ast_map ) = - Z3native.ast_map_size m#gnc m#gno + let get_size ( x : ast_map ) = + Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) (** The keys stored in the map. *) - let get_keys ( m : ast_map ) = - (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + let get_keys ( x : ast_map ) = + ASTVector.cnstr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) - let to_strnig ( m : ast_map ) = - Z3native.ast_map_to_string m#gnc m#gno + let to_string ( x : ast_map ) = + Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end (** @@ -1297,6 +1333,125 @@ struct let unwrap_ast ( a : ast ) = a#gno end + +(** + Parameter sets (of Solvers, Tactics, ...) + + A Params objects represents a configuration in the form of symbol/value pairs. +*) +module Params = +struct + type params = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs = + struct + type param_descrs = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : param_descrs = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.param_descrs_inc_ref ; + dec_ref = Z3native.param_descrs_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params ) = + Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in + let f i = create_symbol (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) + end + + (** + Adds a parameter setting. + *) + let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_int ( x : params ) (name : symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_double ( x : params ) ( name : symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool ( x : params ) ( name : string) ( value : bool ) = + add_bool x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_int ( x : params) ( name : string ) ( value : int ) = + add_int x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_double ( x : params ) ( name : string ) ( value : float ) = + add_double x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = + add_symbol x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Creates a new parameter set + *) + let mk_params ( ctx : context ) = + cnstr ctx (Z3native.mk_params (context_gno ctx)) + + (** + A string representation of the parameter set. + *) + let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) +end + + (** General expressions (terms), including Boolean logic *) module Expr = struct @@ -1305,9 +1460,9 @@ struct @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : params option ) = match p with + let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) - | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) + | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1319,7 +1474,7 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.cnstr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -4079,96 +4234,6 @@ struct let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** - Parameter sets (of Solvers, Tactics, ...) - - A Params objects represents a configuration in the form of symbol/value pairs. -*) -module Params = -struct - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs = - struct - - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) - - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f - - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno - end - - (** - Adds a parameter setting. - *) - let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_int (p : params) (name : symbol) (value : int) = - Z3native.params_set_uint p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_double (p : params) (name : symbol) (value : float) = - Z3native.params_set_double p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_symbol (p : params) (name : symbol) (value : symbol) = - Z3native.params_set_symbol p#gnc p#gno name#gno value#gno - - (** - Adds a parameter setting. - *) - let add_s_bool (p : params) (name : string) (value : bool) = - add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_int (p : params) (name : string) (value : int) = - add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_double (p : params) (name : string) (value : float) = - add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_symbol (p : params) (name : string) (value : symbol) = - add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Creates a new parameter set - *) - let mk_params ( ctx : context ) = - (new params ctx)#cnstr_obj (Z3native.mk_params (context_gno ctx)) - - (** - A string representation of the parameter set. - *) - let to_string (p : params) = Z3native.params_to_string p#gnc p#gno -end (** Goals @@ -4177,6 +4242,18 @@ end tactics and solvers. *) module Goal = struct + type goal = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : goal = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.goal_inc_ref ; + dec_ref = Z3native.goal_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** The precision of the goal. @@ -4185,7 +4262,7 @@ struct An over approximation is applied when the objective is to find a proof for a given goal. *) let get_precision ( x : goal ) = - goal_prec_of_int (Z3native.goal_precision x#gnc x#gno) + goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) (** Indicates whether the goal is precise. *) let is_precise ( x : goal ) = @@ -4206,62 +4283,62 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : bool_expr array ) = - let f e = Z3native.goal_assert x#gnc x#gno e#gno in + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) e#gno in ignore (Array.map f constraints) ; () (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = - Z3native.goal_inconsistent x#gnc x#gno + Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) (** The depth of the goal. This tracks how many transformations were applied to it. *) - let get_depth ( x : goal ) = Z3native.goal_depth x#gnc x#gno + let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) (** Erases all formulas from the given goal. *) - let reset ( x : goal ) = Z3native.goal_reset x#gnc x#gno + let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) (** The number of formulas in the goal. *) - let get_size ( x : goal ) = Z3native.goal_size x#gnc x#gno + let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr x#gc)#cnstr_obj (Z3native.goal_formula x#gnc x#gno i) in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) - let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs x#gnc x#gno + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = - Z3native.goal_is_decided_sat x#gnc x#gno + Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = - Z3native.goal_is_decided_unsat x#gnc x#gno + Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno (context_gno to_ctx)) + cnstr to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : params option ) = - let tn = Z3native.mk_tactic x#gnc "simplify" in - Z3native.tactic_inc_ref x#gnc tn ; + let simplify ( x : goal ) ( p : Params.params option ) = + let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in + Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with - | None -> Z3native.tactic_apply x#gnc tn x#gno - | Some(pn) -> Z3native.tactic_apply_ex x#gnc tn x#gno pn#gno + | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) + | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) in - Z3native.apply_result_inc_ref x#gnc arn ; - let sg = Z3native.apply_result_get_num_subgoals x#gnc arn in + Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; + let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in let res = if sg == 0 then raise (Z3native.Exception "No subgoals") else - Z3native.apply_result_get_subgoal x#gnc arn 0 in - Z3native.apply_result_dec_ref x#gnc arn ; - Z3native.tactic_dec_ref x#gnc tn ; - (new goal x#gc)#cnstr_obj res + Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in + Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; + Z3native.tactic_dec_ref (z3obj_gnc x) tn ; + cnstr (z3obj_gc x) res (** @@ -4274,10 +4351,10 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + cnstr ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) - let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno + let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) end @@ -4326,7 +4403,7 @@ struct module FuncEntry = struct type func_entry = z3_native_object - + (**/**) let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; @@ -4528,7 +4605,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n_univ = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4568,8 +4645,8 @@ struct A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) g#gno + let apply ( x : probe ) (g : Goal.goal) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** The number of supported Probes. @@ -4673,6 +4750,19 @@ end *) module Tactic = struct + type tactic = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : tactic = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.tactic_inc_ref ; + dec_ref = Z3native.tactic_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Tactic application results ApplyResult objects represent the result of an application of a @@ -4699,12 +4789,12 @@ struct (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in - let f i = (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = - (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. @@ -4718,18 +4808,17 @@ struct end (** A string containing a description of parameters accepted by the tactic. *) - let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno - + let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.tactic_get_param_descrs x#gnc x#gno) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with - | None -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply x#gnc x#gno g#gno)) - | Some (pn) -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno)) + | None -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) (** The number of supported tactics. @@ -4755,7 +4844,7 @@ struct Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - (new tactic ctx)#cnstr_obj (Z3native.mk_tactic (context_gno ctx) name) + cnstr ctx (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and @@ -4763,20 +4852,21 @@ struct *) let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = let f p c = (match p with - | None -> (Some c#gno) - | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) c#gno x))) in + | None -> (Some (z3obj_gno c)) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in match (Array.fold_left f None ts) with - | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno t2#gno) + | None -> + cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> - let o = (Z3native.tactic_and_then (context_gno ctx) t2#gno x) in - (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno o) + let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in + cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else (context_gno ctx) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that applies to a goal for milliseconds. @@ -4784,7 +4874,7 @@ struct If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for (context_gno ctx) t#gno ms) + cnstr ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) (** Create a tactic that applies to a given goal if the probe @@ -4794,72 +4884,72 @@ struct *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) t#gno) + cnstr ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat (context_gno ctx) t#gno max) + cnstr ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_skip (context_gno ctx)) + cnstr ctx (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail (context_gno ctx)) + cnstr ctx (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : Probe.probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + cnstr ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + cnstr ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params (context_gno ctx) t#gno p#gno) + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + cnstr ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p (** Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (tacticaton t)) + cnstr ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then (context_gno ctx) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Interrupt the execution of a Z3 procedure. @@ -5015,14 +5105,14 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( value : params )= - Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) value#gno + let set_parameters ( x : solver ) ( p : Params.params )= + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5062,7 +5152,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5070,7 +5160,7 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f @@ -5128,7 +5218,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5176,8 +5266,8 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : tactic ) = - (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** A string representation of the solver. @@ -5211,14 +5301,14 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : params )= - Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) p#gno + let set_params ( x : fixedpoint ) ( p : Params.params )= + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. @@ -5355,7 +5445,7 @@ struct Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f @@ -5364,7 +5454,7 @@ struct Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f From 69138924e5fd834f2890dceea371e503215ae3f7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 13 Jan 2013 00:02:38 +0000 Subject: [PATCH 292/646] ML API: Symbols are now normal types with visible hierarchy. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 468 ++++++++++++++++++++++++----------------------- 1 file changed, 241 insertions(+), 227 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8c0f24c4b..378988d59 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -135,39 +135,145 @@ object (self) method gnc = (context_gno m_ctx) end -(** Symbol objects *) -class symbol ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = () - method decref nc o = () -end -(** Int symbol objects *) -class int_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol (context_gno ctx) i)) ; self -end -(** String symbol objects *) -class string_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol (context_gno ctx) name)) ; self -end +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } -let symbolaton (a : symbol array) = - let f (e : symbol) = e#gno in +let z3obj_gc o = o.m_ctx +let z3obj_gnc o = (context_gno o.m_ctx) + +let z3obj_gno o = o.m_n_obj +let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + +let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + +let z3obj_cnstr o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + +let z3obj_nil_ref x y = () + +let array_to_native a = + let f e = (z3obj_gno e) in Array.map f a +(**/**) -let create_symbol ctx no = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) - | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) + +(** Symbols are used to name several term and type constructors *) +module Symbol = +struct + (** Int symbol objects *) + type int_symbol = z3_native_object + + (** String symbol objects *) + and string_symbol = z3_native_object + + and symbol = + | IntSymbol of int_symbol + | StringSymbol of string_symbol + + (**/**) + let cnstr_i ( ctx : context ) ( no : Z3native.ptr ) = + let res : int_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + let cnstr_s ( ctx : context ) ( no : Z3native.ptr ) = + let res : string_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + + let gnc ( x : symbol ) = + match x with + | IntSymbol(n) -> (z3obj_gnc n) + | StringSymbol(n) -> (z3obj_gnc n) + + let gno ( x : symbol ) = + match x with + | IntSymbol(n) -> (z3obj_gno n) + | StringSymbol(n) -> (z3obj_gno n) + + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> IntSymbol (cnstr_i ctx no) + | STRING_SYMBOL -> StringSymbol (cnstr_s ctx no) + + let aton a = + let f e = (gno e) in + Array.map f a + (**/**) + + (** The kind of the symbol (int or string) *) + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) + + (** Indicates whether the symbol is of Int kind *) + let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL + + (** Indicates whether the symbol is of string kind. *) + let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL + + (** The int value of the symbol. *) + let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + + (** The string value of the symbol. *) + let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + + (** A string representation of the symbol. *) + let to_string ( o : symbol ) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) + | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) + + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_int ( ctx : context ) ( i : int ) = + IntSymbol (cnstr_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + + (** Creates a new symbol using a string. *) + let mk_string ( ctx : context ) ( s : string ) = + StringSymbol (cnstr_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + + (** Create an array of symbols. *) + let mk_ints ( ctx : context ) ( names : int array ) = + let f elem = mk_int ( ctx : context ) elem in + (Array.map f names) + + (** Create an array of symbols. *) + let mk_strings ( ctx : context ) ( names : string array ) = + let f elem = mk_string ( ctx : context ) elem in + (Array.map f names) +end + +(**/**) (** AST objects *) class ast ctx = @@ -242,7 +348,7 @@ class uninterpreted_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) s#gno)) ; self + method cnstr_s (s : Symbol.symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; self end (** Finite domain sort objects *) @@ -250,7 +356,7 @@ class finite_domain_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) s#gno sz)) ; self + method cnstr_si (s : Symbol.symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno s) sz)) ; self end (** Relation sort objects *) @@ -273,8 +379,8 @@ class tuple_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + method cnstr_siss (name : Symbol.symbol) (num_fields: int) (field_names : Symbol.symbol array) (field_sorts : sort array) = + let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) num_fields (Symbol.aton field_names) (astaton field_sorts)) in (self#sno ctx x) ; self end @@ -285,7 +391,7 @@ class func_decl ctx = object (self) inherit ast ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_ndr (name : Symbol.symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (astaton domain) range#gno)) ; self method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o @@ -303,8 +409,8 @@ object (self) val mutable _constdecls : func_decl array option = None val mutable _testerdecls : func_decl array option = None method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) name#gno (Array.length enum_names) (symbolaton enum_names)) in + method cnstr_ss (name : Symbol.symbol) (enum_names : Symbol.symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; (self#sno ctx r) ; @@ -330,8 +436,8 @@ object (self) val mutable _headdecl : func_decl option = None val mutable _taildecl : func_decl option = None method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) name#gno elem_sort#gno) in + method cnstr_ss (name : Symbol.symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) elem_sort#gno) in _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; @@ -381,7 +487,7 @@ object (self) let v = self in Gc.finalise f v - method cnstr_ssssi (name : symbol) (recognizer : symbol) (field_names : symbol array) (sorts : sort array) (sort_refs : int array) = + method cnstr_ssssi (name : Symbol.symbol) (recognizer : Symbol.symbol) (field_names : Symbol.symbol array) (sorts : sort array) (sort_refs : int array) = m_n <- (Array.length field_names) ; if m_n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -389,7 +495,7 @@ object (self) if m_n != (Array.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else - let o = (Z3native.mk_constructor (context_gno ctx) name#gno recognizer#gno m_n (symbolaton field_names) + let o = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) m_n (Symbol.aton field_names) (sortaton sorts) sort_refs) in self#sno ctx o ; @@ -449,7 +555,7 @@ class datatype_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) name#gno (Array.length constructors) (constructoraton constructors)))) ; self + method cnstr_sc (name : Symbol.symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (constructoraton constructors)))) ; self end let create_sort ctx obj = @@ -571,43 +677,6 @@ let patternaton (a : pattern array) = let f (e : pattern) = e#gno in Array.map f a - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - -let z3obj_gc o = o.m_ctx -let z3obj_gnc o = (context_gno o.m_ctx) - -let z3obj_gno o = o.m_n_obj -let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - -let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - -let z3obj_cnstr o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - -let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a - (**/**) @@ -656,58 +725,6 @@ struct string_of_int rev ^ "." end -(** Symbols are used to name several term and type constructors *) -module Symbol = -struct - (** The kind of the symbol (int or string) *) - let kind (o : symbol) = (symbol_kind_of_int (Z3native.get_symbol_kind o#gnc o#gno)) - - (** Indicates whether the symbol is of Int kind *) - let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL - - (** Indicates whether the symbol is of string kind. *) - let is_string_symbol (o : symbol) = (kind o) == STRING_SYMBOL - - (** The int value of the symbol. *) - let get_int (o : int_symbol) = Z3native.get_symbol_int o#gnc o#gno - - (** The string value of the symbol. *) - let get_string (o : string_symbol) = Z3native.get_symbol_string o#gnc o#gno - - (** A string representation of the symbol. *) - let to_string (o : symbol) = - match (kind o) with - | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) - | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) - - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) - let mk_int ( ctx : context ) i = - (new int_symbol ctx)#cnstr_int i - - (** Creates a new symbol using a string. *) - let mk_string ( ctx : context ) s = - (new string_symbol ctx)#cnstr_string s - - (** - Create an array of symbols. - *) - let mk_ints ( ctx : context ) ( names : int array ) = - let f elem = mk_int ( ctx : context ) elem in - (Array.map f names) - - (** - Create an array of symbols. - *) - let mk_strings ( ctx : context ) ( names : string array ) = - let f elem = mk_string ( ctx : context ) elem in - (Array.map f names) -end - (** The Sort module implements type information for ASTs *) module Sort = @@ -738,7 +755,7 @@ struct (** The name of the sort *) - let get_name (x : sort) = (create_symbol x#gc (Z3native.get_sort_name x#gnc x#gno)) + let get_name (x : sort) = (Symbol.create x#gc (Z3native.get_sort_name x#gnc x#gno)) (** A string representation of the sort. @@ -754,14 +771,14 @@ struct (** Create a new uninterpreted sort. *) - let mk_uninterpreted ( ctx : context ) (s : symbol) = + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = (new uninterpreted_sort ctx)#cnstr_s s (** Create a new uninterpreted sort. *) - let mk_uninterpreted_s ( ctx : context ) (s : string) = - mk_uninterpreted ctx ((Symbol.mk_string ( ctx : context ) s) :> symbol) + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) end (**/**) @@ -817,7 +834,7 @@ struct m_kind : parameter_kind ; m_i : int ; m_d : float ; - m_sym : symbol option ; + m_sym : Symbol.symbol option ; m_srt : sort option ; m_ast : ast option ; m_fd : func_decl option ; @@ -961,14 +978,14 @@ struct (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort) = (new func_decl ctx)#cnstr_ndr name domain range (** Creates a new function declaration. *) let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** Creates a fresh function declaration with a name prefixed with . @@ -981,7 +998,7 @@ struct (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort) = (new func_decl ctx)#cnstr_ndr name [||] range @@ -989,7 +1006,7 @@ struct Creates a new constant function declaration. *) let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + (new func_decl ctx)#cnstr_ndr (Symbol.mk_string ctx name) [||] range (** Creates a fresh constant function declaration with a name prefixed with . @@ -1055,7 +1072,7 @@ struct (** The name of the function declaration *) - let get_name (x : func_decl) = (create_symbol x#gc (Z3native.get_decl_name x#gnc x#gno)) + let get_name (x : func_decl) = (Symbol.create x#gc (Z3native.get_decl_name x#gnc x#gno)) (** The number of parameters of the function declaration @@ -1071,7 +1088,7 @@ struct match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (Symbol.create x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) @@ -1375,13 +1392,13 @@ struct Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) name#gno)) + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) (** Retrieve all names of parameters. *) let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in - let f i = create_symbol (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The size of the ParamDescrs. *) @@ -1394,50 +1411,50 @@ struct (** Adds a parameter setting. *) - let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = - Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_int ( x : params ) (name : symbol ) ( value : int ) = - Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_double ( x : params ) ( name : symbol ) ( value : float ) = - Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = - Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) name#gno value#gno + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) (** Adds a parameter setting. *) - let add_s_bool ( x : params ) ( name : string) ( value : bool ) = - add_bool x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = + add_bool x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + add_int x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + add_double x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) - let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = - add_symbol x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + add_symbol x (Symbol.mk_string (z3obj_gc x) name) value (** Creates a new parameter set @@ -1662,15 +1679,15 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const (context_gno ctx) name#gno range#gno) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_expr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) range#gno) (** Creates a new Constant of sort and named . *) let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) range + mk_const ctx (Symbol.mk_string ctx name)range (** @@ -1690,14 +1707,14 @@ struct (** Create a Boolean constant. *) - let mk_bool_const ( ctx : context ) ( name : symbol ) = + let mk_bool_const ( ctx : context ) ( name : Symbol.symbol ) = ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) (** Create a Boolean constant. *) let mk_bool_const_s ( ctx : context ) ( name : string ) = - mk_bool_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_bool_const ctx (Symbol.mk_string ctx name) (** Create a new function application. @@ -1907,7 +1924,7 @@ struct *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + let f i = (Symbol.create x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in Array.init n f (** @@ -1960,7 +1977,7 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1968,23 +1985,23 @@ struct (match weight with | None -> 1 | Some(x) -> x) (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1994,8 +2011,8 @@ struct else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expraton bound_constants) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) @@ -2004,7 +2021,7 @@ struct Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -2012,23 +2029,23 @@ struct (match weight with | None -> 1 | Some(x) -> x) (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -2038,8 +2055,8 @@ struct else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expraton bound_constants) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) @@ -2048,7 +2065,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -2058,7 +2075,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2128,14 +2145,14 @@ struct (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) (** Create an array constant. *) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) domain range + mk_const ctx (Symbol.mk_string ctx name) domain range (** Array read. @@ -2307,14 +2324,14 @@ struct (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) size = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) size = (new finite_domain_sort ctx)#cnstr_si name size (** Create a new finite domain sort. *) let mk_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si ((Symbol.mk_string ctx name) :> symbol) size + (new finite_domain_sort ctx)#cnstr_si (Symbol.mk_string ctx name) size (** @@ -2488,7 +2505,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array) = (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs @@ -2502,32 +2519,32 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - mk_constructor ctx ((Symbol.mk_string ctx name) :> symbol) recognizer field_names sorts sort_refs + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : constructor array) = (new datatype_sort ctx)#cnstr_sc name constructors (** Create a new datatype sort. *) let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = - mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) constructors + mk_sort ctx (Symbol.mk_string ctx name) constructors (** Create mutually recursive datatypes. @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : constructor array array ) = let n = (Array.length names) in let f e = ( (new constructor_list ctx)#cnstr_ca e ) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (symbolaton names) (constructor_listaton cla)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (constructor_listaton cla)) in let g e = ( (new datatype_sort ctx)#cnstr_obj e) in (Array.map g r) @@ -2535,7 +2552,7 @@ struct let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = mk_sorts ctx ( - let f e = ((Symbol.mk_string ctx e) :> symbol) in + let f e = (Symbol.mk_string ctx e) in Array.map f names ) c @@ -2581,10 +2598,8 @@ struct *) let mk_sort_s ( ctx : context ) name enum_names = (new enum_sort ctx)#cnstr_ss - ((Symbol.mk_string ( ctx : context ) name) :> symbol) - (let f e = (e :> symbol) in - (Array.map f (Symbol.mk_strings ( ctx : context ) enum_names)) - ) + (Symbol.mk_string ctx name) + (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) let get_const_decls (x : enum_sort) = x#const_decls @@ -2599,15 +2614,14 @@ struct (** Create a new list sort. *) - let mk_sort ( ctx : context ) (name : symbol) elem_sort = + let mk_sort ( ctx : context ) (name : Symbol.symbol) elem_sort = (new list_sort ctx)#cnstr_ss name elem_sort (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = - mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) elem_sort - + mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) let get_nil_decl (x : list_sort) = x#nil_decl @@ -2805,26 +2819,26 @@ struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : symbol ) = + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) (** Creates an integer constant. *) let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_int_const ctx (Symbol.mk_string ctx name) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : symbol ) = + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) (** Creates a real constant. *) let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_real_const ctx (Symbol.mk_string ctx name) (** Create an expression representing t[0] + t[1] + .... @@ -3300,14 +3314,14 @@ struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) (** Creates a bit-vector constant. *) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) size + mk_const ctx (Symbol.mk_string ctx name) size (** Bitwise negation. @@ -5242,17 +5256,17 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : symbol option) = + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) + | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) (** Creates a new (incremental) solver. *) let mk_solver_s ( ctx : context ) ( logic : string ) = - mk_solver ctx (Some ((Symbol.mk_string ctx logic) :> symbol)) + mk_solver ctx (Some (Symbol.mk_string ctx logic)) (** Creates a new (incremental) solver. @@ -5327,10 +5341,10 @@ struct (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno y#gno + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno y) (** Add table fact to the fixedpoint solver. @@ -5381,8 +5395,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno name#gno + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5432,8 +5446,8 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (symbolaton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (Symbol.aton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. @@ -5554,7 +5568,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5564,17 +5578,17 @@ struct else Z3native.parse_smtlib_string (context_gno ctx) str cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5584,10 +5598,10 @@ struct else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** @@ -5649,7 +5663,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5659,17 +5673,17 @@ struct else Z3native.parse_smtlib2_string (context_gno ctx) str cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5679,10 +5693,10 @@ struct else Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) end From 048e8c1a978101cb54654f95a92e30479015e1d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Jan 2013 11:37:39 +0000 Subject: [PATCH 293/646] ML API: updated example Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 38b5fe642..3b13a2462 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -22,8 +22,8 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = ((mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_real_sort ctx )) :> arith_expr) in - let yr = ((mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let xr = ((mk_const ctx (Symbol.mk_string ctx "x") (mk_real_sort ctx )) :> arith_expr) in + let yr = ((mk_const ctx (Symbol.mk_string ctx "y") (mk_real_sort ctx )) :> arith_expr) in let g4 = (mk_goal ctx true false false ) in (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; @@ -68,9 +68,9 @@ let model_converter_test ( ctx : context ) = let basic_tests ( ctx : context ) = Printf.printf "BasicTests\n" ; let qi = (mk_int ctx 1) in - let fname = ((mk_string ctx "f") :> symbol) in - let x = ((mk_string ctx "x") :> symbol) in - let y = ((mk_string ctx "y") :> symbol) in + let fname = (mk_string ctx "f") in + let x = (mk_string ctx "x") in + let y = (mk_string ctx "y") in let bs = (Sort.mk_bool ctx) in let domain = [| bs; bs |] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in @@ -142,8 +142,8 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_int_sort ctx)) in - let yc = (mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_int_sort ctx)) in + let xc = (mk_const ctx (Symbol.mk_string ctx "x") (mk_int_sort ctx)) in + let yc = (mk_const ctx (Symbol.mk_string ctx "y") (mk_int_sort ctx)) in (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; let constr = (mk_eq ctx xc yc) in @@ -211,8 +211,8 @@ let _ = let bs = (Sort.mk_bool ctx) in let ints = (mk_int_sort ctx) in let rs = (mk_real_sort ctx) in - Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); - Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); + Printf.printf "int symbol: %s\n" (Symbol.to_string is); + Printf.printf "string symbol: %s\n" (Symbol.to_string ss); Printf.printf "bool sort: %s\n" (Sort.to_string bs); Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); From 7befc262d13c02fe736fa49bf87dac2a777e84e2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Jan 2013 17:51:16 +0000 Subject: [PATCH 294/646] ML API: added functions for global parameter management. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 378988d59..0dfb173c4 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -5700,6 +5700,53 @@ struct (func_declaton decls) end + +(* Global functions *) + +(** + * Set a global (or module) parameter, which is shared by all Z3 contexts. + * + * When a Z3 module is initialized it will use the value of these parameters + * when Z3_params objects are not provided. + * The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + * The character '.' is a delimiter (more later). + * The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + * Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + * This function can be used to set parameters for a specific Z3 module. + * This can be done by using .. + * For example: + * (set_global_param "pp.decimal" "true") + * will set the parameter "decimal" in the module "pp" to true. +*) +let set_global_param ( id : string ) ( value : string ) = + (Z3native.global_param_set id value) + +(** + * Get a global (or module) parameter. + * + * Returns None if the parameter does not exist. + * The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + * This function cannot be invoked simultaneously from different threads without synchronization. + * The result string stored in param_value is stored in a shared location. +*) +let get_global_param ( id : string ) = + let (r, v) = (Z3native.global_param_get id) in + if not r then + None + else + Some v + +(** + * Restore the value of all global (and module) parameters. + * + * This command will not affect already created objects (such as tactics and solvers) + * +*) +let global_param_reset_all = + Z3native.global_param_reset_all + + + (* (** From 1eae7a6bacb962d7ad109f73e0c778255f6d48cb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 17 Jan 2013 19:47:51 +0000 Subject: [PATCH 295/646] ML API: Added Solver.assert_and_track Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0dfb173c4..f5c3e3d82 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -5159,8 +5159,42 @@ struct *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in - ignore (Array.map f constraints) ; - () + ignore (Array.map f constraints) + + (** + * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + *) + let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + if ((Array.length cs) != (Array.length ps)) then + raise (Z3native.Exception "Argument size mismatch") + else + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) e#gno (Array.get ps i)#gno) in + ignore (Array.iteri f cs) + + (** + * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + *) + let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) c#gno p#gno (** The number of assertions in the solver. From 49cd4e2d3542f00e5be5f6bdafe0a4b5daa9fc00 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 31 Jan 2013 12:51:31 +0000 Subject: [PATCH 296/646] ML build Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 554bb4259..bea2939b6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1335,29 +1335,30 @@ class MLComponent(Component): src_dir = self.to_src_dir sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) + api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s api/ml/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, get_component(API_COMPONENT).to_src_dir)) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') - out.write('\tcd %s && %s ' % (sub_dir, OCAMLOPT)) + out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cmxa -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) - out.write('api/ml/z3.cma: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\tcd %s && %s ' % (sub_dir, OCAMLC)) + out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cma -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') From 7b51dc9bdd06e54b65229bdee9914367b665b23b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Feb 2013 21:18:25 +0000 Subject: [PATCH 297/646] Checkpoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2989 ++++++++++++++++++++++++---------------------- 1 file changed, 1544 insertions(+), 1445 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f5c3e3d82..0e47912ae 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,6 +7,51 @@ open Z3enums +(** Interaction logging for Z3 + + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log = +struct + (** Open an interaction log file. + @param filename the name of the file to open. + @return True if opening the log file succeeds, false otherwise. + *) + (* CMW: "open" seems to be a reserved keyword? *) + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) + + (** Closes the interaction log. *) + let close = Z3native.close_log + + (** Appends a user-provided string to the interaction log. + @param s the string to append*) + let append s = Z3native.append_log s +end + +(** Version information *) +module Version = +struct + (** The major version. *) + let major = let (x, _, _, _) = Z3native.get_version in x + + (** The minor version. *) + let minor = let (_, x, _, _) = Z3native.get_version in x + + (** The build version. *) + let build = let (_, _, x, _) = Z3native.get_version in x + + (** The revision. *) + let revision = let (_, _, _, x) = Z3native.get_version in x + + (** A string representation of the version information. *) + let to_string = + let (mj, mn, bld, rev) = Z3native.get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + (**/**) (* Some helpers. *) @@ -40,7 +85,7 @@ let context_dispose ctx = (* re-queue for finalization? *) ) -let context_cnstr settings = +let context_create settings = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; @@ -85,7 +130,7 @@ let context_gno ctx = ctx.m_n_ctx *) let mk_context ( cfg : ( string * string ) list ) = - context_cnstr cfg + context_create cfg (**/**) @@ -165,7 +210,7 @@ let z3obj_dispose o = ) ; o.m_n_obj <- null -let z3obj_cnstr o = +let z3obj_create o = let f = fun o -> (z3obj_dispose o) in Gc.finalise f o @@ -184,44 +229,51 @@ struct type int_symbol = z3_native_object (** String symbol objects *) - and string_symbol = z3_native_object + type string_symbol = z3_native_object - and symbol = - | IntSymbol of int_symbol - | StringSymbol of string_symbol + (** Symbol Objects *) + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol (**/**) - let cnstr_i ( ctx : context ) ( no : Z3native.ptr ) = + let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res - let cnstr_s ( ctx : context ) ( no : Z3native.ptr ) = + + let create_s ( ctx : context ) ( no : Z3native.ptr ) = let res : string_symbol = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res + + let gc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gc n) + | S_Str(n) -> (z3obj_gc n) let gnc ( x : symbol ) = match x with - | IntSymbol(n) -> (z3obj_gnc n) - | StringSymbol(n) -> (z3obj_gnc n) + | S_Int(n) -> (z3obj_gnc n) + | S_Str(n) -> (z3obj_gnc n) let gno ( x : symbol ) = match x with - | IntSymbol(n) -> (z3obj_gno n) - | StringSymbol(n) -> (z3obj_gno n) + | S_Int(n) -> (z3obj_gno n) + | S_Str(n) -> (z3obj_gno n) let create ( ctx : context ) ( no : Z3native.ptr ) = match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> IntSymbol (cnstr_i ctx no) - | STRING_SYMBOL -> StringSymbol (cnstr_s ctx no) + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) let aton a = let f e = (gno e) in @@ -256,11 +308,11 @@ struct The legal range of unsigned integers is 0 to 2^30-1. *) let mk_int ( ctx : context ) ( i : int ) = - IntSymbol (cnstr_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) (** Creates a new symbol using a string. *) let mk_string ( ctx : context ) ( s : string ) = - StringSymbol (cnstr_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) (** Create an array of symbols. *) let mk_ints ( ctx : context ) ( names : int array ) = @@ -273,853 +325,47 @@ struct (Array.map f names) end -(**/**) - -(** AST objects *) -class ast ctx = -object (self) - inherit z3object ctx None as super (* CMW: derive from icomparable? *) - method cnstr_obj obj = (self#sno ctx obj) ; self - - method incref nc o = Z3native.inc_ref nc o - method decref nc o = Z3native.dec_ref nc o -end - -let astaton (a : ast array) = - let f (e : ast) = e#gno in - Array.map f a - -(** Sort objects *) -class sort ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let sortaton (a : sort array) = - let f (e : sort) = e#gno in - Array.map f a - -(** Arithmetic sort objects, i.e., Int or Real. *) -class arith_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Array sorts objects *) -class array_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort (context_gno ctx) domain#gno range#gno)) ; self -end - -(** Bit-vector sort objects *) -class bitvec_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Boolean sort objects *) -class bool_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Int sort objects *) -class int_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Real sort objects *) -class real_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Uninterpreted sort objects *) -class uninterpreted_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : Symbol.symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; self -end - -(** Finite domain sort objects *) -class finite_domain_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : Symbol.symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno s) sz)) ; self -end - -(** Relation sort objects *) -class relation_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Set sort objects *) -class set_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : sort) = (self#sno ctx s#gno) ; self -end - -(** Tuple sort objects *) -class tuple_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_siss (name : Symbol.symbol) (num_fields: int) (field_names : Symbol.symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) num_fields (Symbol.aton field_names) (astaton field_sorts)) in - (self#sno ctx x) ; - self -end - - -(** Function declaration objects *) -class func_decl ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : Symbol.symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self - - method incref nc o = super#incref nc o - method decref nc o = super#decref nc o -end - -let func_declaton (a : func_decl array) = - let f (e : func_decl) = e#gno in - Array.map f a - -(** Enum sort objects *) -class enum_sort ctx = -object (self) - inherit sort ctx as super - val mutable _constdecls : func_decl array option = None - val mutable _testerdecls : func_decl array option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : Symbol.symbol) (enum_names : Symbol.symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in - _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; - _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; - (self#sno ctx r) ; - self - - method const_decls = match _constdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing const decls") - - method tester_decls = match _testerdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tester decls") -end - -(** List sort objects *) -class list_sort ctx = -object (self) - inherit sort ctx as super - val mutable _nildecl : func_decl option = None - val mutable _is_nildecl : func_decl option = None - val mutable _consdecl : func_decl option = None - val mutable _is_consdecl : func_decl option = None - val mutable _headdecl : func_decl option = None - val mutable _taildecl : func_decl option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : Symbol.symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) elem_sort#gno) in - _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; - _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; - _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; - _is_consdecl <- Some ((new func_decl ctx)#cnstr_obj d) ; - _headdecl <- Some ((new func_decl ctx)#cnstr_obj e) ; - _taildecl <- Some ((new func_decl ctx)#cnstr_obj f) ; - (self#sno ctx r) ; - self - - method nil_decl = match _nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing nil decl") - - method is_nil_decl = match _is_nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decl") - - method cons_decl = match _consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decl") - - method is_cons_decl = match _is_consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decl") - - method head_decl = match _headdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decl") - - method tail_decl = match _taildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decl") -end - -(** Constructor objects *) -class constructor ctx = -object (self) - inherit z3object ctx None as super - val mutable m_n : int = 0 - val mutable m_tester_decl : func_decl option = None - val mutable m_constructor_decl : func_decl option = None - val mutable m_accessor_decls : func_decl array option = None - method incref nc o = () - method decref nc o = () - initializer - let f = fun o -> Z3native.del_constructor o#gnc o#gno in - let v = self in - Gc.finalise f v - - method cnstr_ssssi (name : Symbol.symbol) (recognizer : Symbol.symbol) (field_names : Symbol.symbol array) (sorts : sort array) (sort_refs : int array) = - m_n <- (Array.length field_names) ; - if m_n != (Array.length sorts) then - raise (Z3native.Exception "Number of field names does not match number of sorts") - else - if m_n != (Array.length sort_refs) then - raise (Z3native.Exception "Number of field names does not match number of sort refs") - else - let o = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) m_n (Symbol.aton field_names) - (sortaton sorts) - sort_refs) in - self#sno ctx o ; - self - - method private init = - match m_tester_decl with - | None -> - let (a, b, c) = (Z3native.query_constructor self#gnc self#gno m_n) in - m_constructor_decl <- Some ((new func_decl ctx)#cnstr_obj a) ; - m_tester_decl <- Some ((new func_decl ctx)#cnstr_obj b) ; - m_accessor_decls <- Some (let f e = ((new func_decl ctx)#cnstr_obj e) in Array.map f c) ; - () - | _ -> () - - method get_n = m_n - - method tester_decl = match m_tester_decl with - | Some(x) -> x - | None -> self#init ; self#tester_decl - - method constructor_decl = match m_constructor_decl with - | Some(x) -> x - | None -> self#init ; self#constructor_decl - - method accessor_decls = match m_accessor_decls with - | Some(x) -> x - | None -> self#init ; self#accessor_decls -end - -let constructoraton (a : constructor array) = - let f (e : constructor) = e#gno in - Array.map f a - -(** Constructor list objects *) -class constructor_list ctx = -object (self) - inherit z3object ctx None - method incref nc o = () - method decref nc o = () - initializer - let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in - let v = self in - Gc.finalise f v - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ca ( c : constructor array ) = - self#sno ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (constructoraton c)) ; - self -end - -let constructor_listaton (a : constructor_list array) = - let f (e : constructor_list) = e#gno in - Array.map f a - -(** Datatype sort objects *) -class datatype_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : Symbol.symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (constructoraton constructors)))) ; self -end - -let create_sort ctx obj = - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) obj)) with - | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) - | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) - | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) - | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) - | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) - | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) - | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) - | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) - | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - -(** Expression objects *) -class expr ctx = -object(self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let expraton (a : expr array) = - let f (e : expr) = e#gno in - Array.map f a - -(** Boolean expression objects *) -class bool_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Arithmetic expression objects (int/real) *) -class arith_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Int expression objects *) -class int_expr ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Real expression objects *) -class real_expr ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Bit-vector expression objects *) -class bitvec_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Array expression objects *) -class array_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Datatype expression objects *) -class datatype_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Integer numeral expression objects *) -class int_num ctx = -object (self) - inherit int_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Rational numeral expression objects *) -class rat_num ctx = -object (self) - inherit real_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Bit-vector numeral expression objects *) -class bitvec_num ctx = -object (self) - inherit bitvec_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Algebraic numeral expression objects *) -class algebraic_num ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Quantifier objects *) -class quantifier ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Quantifier pattern objects *) -class pattern ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let patternaton (a : pattern array) = - let f (e : pattern) = e#gno in - Array.map f a - -(**/**) - - -(** Interaction logging for Z3 - - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) -module Log = -struct - (** Open an interaction log file. - @param filename the name of the file to open. - @return True if opening the log file succeeds, false otherwise. - *) - (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - - (** Closes the interaction log. *) - let close = Z3native.close_log - - (** Appends a user-provided string to the interaction log. - @param s the string to append*) - let append s = Z3native.append_log s -end - -(** Version information *) -module Version = -struct - (** The major version. *) - let major = let (x, _, _, _) = Z3native.get_version in x - - (** The minor version. *) - let minor = let (_, x, _, _) = Z3native.get_version in x - - (** The build version. *) - let build = let (_, _, x, _) = Z3native.get_version in x - - (** The revision. *) - let revision = let (_, _, _, x) = Z3native.get_version in x - - (** A string representation of the version information. *) - let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end - - -(** The Sort module implements type information for ASTs *) -module Sort = -struct - (** - Comparison operator. - @param a A sort - @param b A sort - @return True if and are from the same context - and represent the same sort; false otherwise. - *) - let ( = ) (a : sort) (b : sort) = (a == b) || - if a#gnc != b#gnc then - false - else - (Z3native.is_eq_sort a#gnc a#gno b#gno) - - (** - Returns a unique identifier for the sort. - *) - let get_id (x : sort) = Z3native.get_sort_id x#gnc x#gno - - (** - The kind of the sort. - *) - let get_sort_kind (x : sort) = (sort_kind_of_int (Z3native.get_sort_kind x#gnc x#gno)) - - (** - The name of the sort - *) - let get_name (x : sort) = (Symbol.create x#gc (Z3native.get_sort_name x#gnc x#gno)) - - (** - A string representation of the sort. - *) - let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno - - (** - Create a new Boolean sort. - *) - let mk_bool ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort (context_gno ctx)) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = - (new uninterpreted_sort ctx)#cnstr_s s - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_s ( ctx : context ) ( s : string ) = - mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) -end - -(**/**) -let create_expr ctx obj = - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then - (((new quantifier ctx)#cnstr_obj obj) :> expr) - else - let s = Z3native.get_sort (context_gno ctx) obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (((new algebraic_num ctx)#cnstr_obj obj) :> expr) - else - if (Z3native.is_numeral_ast (context_gno ctx) obj) && - (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - match sk with - | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) - | REAL_SORT -> (((new rat_num ctx)#cnstr_obj obj) :> expr) - | BV_SORT -> (((new bitvec_num ctx)#cnstr_obj obj) :> expr) - | _ -> raise (Z3native.Exception "Unsupported numeral object") - else - match sk with - | BOOL_SORT -> (((new bool_expr ctx)#cnstr_obj obj) :> expr) - | INT_SORT -> (((new int_expr ctx)#cnstr_obj obj) :> expr) - | REAL_SORT -> (((new real_expr ctx)#cnstr_obj obj) :> expr) - | BV_SORT -> (((new bitvec_expr ctx)#cnstr_obj obj) :> expr) - | ARRAY_SORT -> (((new array_expr ctx)#cnstr_obj obj) :> expr) - | DATATYPE_SORT -> (((new datatype_expr ctx)#cnstr_obj obj) :> expr) - | _ -> (new expr ctx)#cnstr_obj obj - -let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = - let o = Z3native.mk_app (context_gno ctx) f#gno (Array.length args) (astaton args) in - create_expr ctx o - -let create_ast ctx no = - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) - | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) - | SORT_AST -> ((create_sort ctx no) :> ast) - | APP_AST - | NUMERAL_AST - | VAR_AST -> ((create_expr ctx no) :> ast) - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") -(**/**) - -(** Function declarations *) -module FuncDecl = -struct - - (** Parameters of Func_Decls *) - module Parameter = - struct - type parameter = { - m_kind : parameter_kind ; - m_i : int ; - m_d : float ; - m_sym : Symbol.symbol option ; - m_srt : sort option ; - m_ast : ast option ; - m_fd : func_decl option ; - m_r : string ; - } - - (**/**) - let cnstr_int i = { - m_kind = PARAMETER_INT ; - m_i = i ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_double d = { - m_kind = PARAMETER_DOUBLE ; - m_i = 0 ; - m_d = d ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_symbol sym = { - m_kind = PARAMETER_SYMBOL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = sym ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_sort srt = { - m_kind = PARAMETER_SORT ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = srt ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_ast ast = { - m_kind = PARAMETER_AST ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = ast ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_func_decl fd ={ - m_kind = PARAMETER_FUNC_DECL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = fd ; - m_r = "" ; - } - - let cnstr_rational r = { - m_kind = PARAMETER_RATIONAL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = r ; - } - (**/**) - - (** - The kind of the parameter. - *) - let get_kind ( x : parameter ) = x.m_kind - - (**The int value of the parameter.*) - let get_int ( x : parameter ) = - if ((get_kind x) != PARAMETER_INT) then - raise (Z3native.Exception "parameter is not an int") - else - x.m_i - - (**The double value of the parameter.*) - let get_double ( x : parameter ) = - if ((get_kind x) != PARAMETER_DOUBLE) then - raise (Z3native.Exception "parameter is not a double") - else - x.m_d - - (**The Symbol value of the parameter.*) - let get_symbol ( x : parameter ) = - if ((get_kind x) != PARAMETER_SYMBOL) then - raise (Z3native.Exception "parameter is not a symbol") - else - x.m_sym - - (**The Sort value of the parameter.*) - let get_sort ( x : parameter ) = - if ((get_kind x) != PARAMETER_SORT) then - raise (Z3native.Exception "parameter is not a sort") - else - x.m_srt - - (**The AST value of the parameter.*) - let get_ast ( x : parameter ) = - if ((get_kind x) != PARAMETER_AST) then - raise (Z3native.Exception "parameter is not an ast") - else - x.m_ast - - (**The FunctionDeclaration value of the parameter.*) - let get_ast ( x : parameter ) = - if ((get_kind x) != PARAMETER_FUNC_DECL) then - raise (Z3native.Exception "parameter is not an function declaration") - else - x.m_fd - - (**The rational string value of the parameter.*) - let get_rational ( x : parameter ) = - if ((get_kind x) != PARAMETER_RATIONAL) then - raise (Z3native.Exception "parameter is not a ratinoal string") - else - x.m_r - end - - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name domain range - - (** - Creates a new function declaration. - *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx (Symbol.mk_string ctx name) domain range - - (** - Creates a fresh function declaration with a name prefixed with . - - - *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix domain range - - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name [||] range - - - (** - Creates a new constant function declaration. - *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr (Symbol.mk_string ctx name) [||] range - - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix [||] range - - - (** - Comparison operator. - @param a A func_decl - @param b A func_decl - @return True if and are from the same context - and represent the same func_decl; false otherwise. - *) - let ( = ) (a : func_decl) (b : func_decl) = (a == b) || - if a#gnc == a#gnc then - false - else - (Z3native.is_eq_func_decl a#gnc a#gno b#gno) - (** - A string representations of the function declaration. - *) - let to_string (x : func_decl) = Z3native.func_decl_to_string x#gnc x#gno - - (** - Returns a unique identifier for the function declaration. - *) - let get_id (x : func_decl) = Z3native.get_func_decl_id x#gnc x#gno - - (** - The arity of the function declaration - *) - let get_arity (x : func_decl) = Z3native.get_arity x#gnc x#gno - - (** - The size of the domain of the function declaration - - *) - let get_domain_size (x : func_decl) = Z3native.get_domain_size x#gnc x#gno - - (** - The domain of the function declaration - *) - let get_domain (x : func_decl) = - let n = (get_domain_size x) in - let f i = create_sort x#gc (Z3native.get_domain x#gnc x#gno i) in - Array.init n f - - (** - The range of the function declaration - *) - let get_range (x : func_decl) = - create_sort x#gc (Z3native.get_range x#gnc x#gno) - - (** - The kind of the function declaration. - *) - let get_decl_kind (x : func_decl) = (decl_kind_of_int (Z3native.get_decl_kind x#gnc x#gno)) - - (** - The name of the function declaration - *) - let get_name (x : func_decl) = (Symbol.create x#gc (Z3native.get_decl_name x#gnc x#gno)) - - (** - The number of parameters of the function declaration - *) - let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) - - (** - The parameters of the function declaration - *) - let get_parameters (x : func_decl) = - let n = (get_num_parameters x) in - let f i = ( - match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with - | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) - | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (Symbol.create x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) - | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) - | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) - | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) - | PARAMETER_RATIONAL -> Parameter.cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) - ) in - mk_list f n - - (** - Create expression that applies function to arguments. - @param args The arguments - *) - let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args - -end (** The abstract syntax tree (AST) module *) -module AST = -struct +module rec AST : +sig + type ast = z3_native_object + + val create : context -> Z3native.ptr -> ast + val aton : ast array -> Z3native.ptr array + + val is_expr : ast -> bool + val is_var : ast -> bool +end = struct + type ast = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let aton (a : ast array) = + let f (e : ast) = (z3obj_gno e) in + Array.map f a + + (** Vectors of ASTs *) module ASTVector = struct type ast_vector = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; dec_ref = Z3native.ast_vector_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1133,11 +379,11 @@ struct @return An AST *) let get ( x : ast_vector ) ( i : int ) = - create_ast (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + create (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i value#gno + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) (** Resize the vector to . @param newSize The new size of the vector. *) @@ -1150,7 +396,7 @@ struct @param a An AST *) let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) a#gno + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) (** Translates all ASTs in the vector to . @@ -1158,7 +404,7 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - cnstr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = @@ -1171,13 +417,13 @@ struct type ast_map = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_map_inc_ref ; dec_ref = Z3native.ast_map_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1185,7 +431,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( x : ast_map ) ( key : ast ) = - (Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) key#gno) + Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (** Finds the value associated with the key . @@ -1193,7 +439,7 @@ struct @param k An AST *) let find ( x : ast_map ) ( key : ast ) = - create_ast (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) key#gno) + create (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) (** Stores or replaces a new key/value pair in the map. @@ -1201,14 +447,14 @@ struct @param v The value AST *) let insert ( x : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) key#gno value#gno + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) (** Erases the key from the map. @param k An AST *) let erase ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) key#gno + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (** Removes all keys from the map. *) let reset ( x : ast_map ) = @@ -1220,7 +466,7 @@ struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.cnstr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -1231,23 +477,23 @@ struct The AST's hash code. @return A hash code *) - let get_hash_code ( x : ast) = Z3native.get_ast_hash x#gnc x#gno + let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) (** A unique identifier for the AST (unique among all ASTs). *) - let get_id ( x : ast) = Z3native.get_ast_id x#gnc x#gno + let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) (** The kind of the AST. *) - let get_ast_kind ( x : ast) = (ast_kind_of_int (Z3native.get_ast_kind x#gnc x#gno)) + let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) (** Indicates whether the AST is an Expr *) - let is_expr ( x : ast) = - match get_ast_kind ( x : ast) with + let is_expr ( x : ast ) = + match get_ast_kind ( x : ast ) with | APP_AST | NUMERAL_AST | QUANTIFIER_AST @@ -1257,33 +503,33 @@ struct (** Indicates whether the AST is a bound variable *) - let is_var ( x : ast) = (get_ast_kind x) == VAR_AST + let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST (** Indicates whether the AST is a Quantifier *) - let is_quantifier ( x : ast) = (get_ast_kind x) == QUANTIFIER_AST + let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST (** Indicates whether the AST is a Sort *) - let is_sort ( x : ast) = (get_ast_kind x) == SORT_AST + let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST (** Indicates whether the AST is a FunctionDeclaration *) - let is_func_decl ( x : ast) = (get_ast_kind x) == FUNC_DECL_AST + let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST (** A string representation of the AST. *) - let to_string ( x : ast) = Z3native.ast_to_string x#gnc x#gno + let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) (** A string representation of the AST in s-expression notation. *) - let to_sexpr ( x : ast) = Z3native.ast_to_string x#gnc x#gno + let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) (** Comparison operator. @@ -1292,11 +538,11 @@ struct @return True if and are from the same context and represent the same sort; false otherwise. *) - let ( = ) (a : expr) (b : expr) = (a == b) || - if a#gnc == b#gnc then + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + if (z3obj_gnc a) != (z3obj_gnc b) then false else - (Z3native.is_eq_ast a#gnc a#gno b#gno) + Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) (** Object Comparison. @@ -1316,11 +562,11 @@ struct @param ctx A context @return A copy of the AST which is associated with *) - let translate ( x : ast) to_ctx = - if x#gc == to_ctx then + let translate ( x : ast ) ( to_ctx : context ) = + if (z3obj_gnc x) == (context_gno to_ctx) then x else - (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) + create to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Wraps an AST. @@ -1334,7 +580,7 @@ struct @param nativeObject The native pointer to wrap. *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create_ast ctx ptr + create ctx ptr (** Unwraps an AST. @@ -1347,43 +593,413 @@ struct @param a The AST to unwrap. *) - let unwrap_ast ( a : ast ) = a#gno + let unwrap_ast ( x : ast ) = (z3obj_gno x) + + (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST -> (match (FuncDecl.create ctx no) with FuncDecl.FuncDecl(x) -> x) + | SORT_AST -> (match (Sort.create ctx no) with Sort.Sort(x) -> x) + | QUANTIFIER_AST -> (match (Quantifiers.create ctx no) with Quantifiers.Quantifier(Expr.Expr(x)) -> x) + | APP_AST + | NUMERAL_AST + | VAR_AST -> (match (Expr.create ctx no) with Expr.Expr(x) -> x) + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") +(**/**) end +(** The Sort module implements type information for ASTs *) +and Sort : +sig + type sort = Sort of AST.ast + type bitvec_sort = BitvecSort of sort + type uninterpreted_sort = UninterpretedSort of sort + + val create : context -> Z3native.ptr -> sort + val gno : sort -> Z3native.ptr + val gnc : sort -> Z3native.ptr + val aton : sort array -> Z3native.ptr array +end = struct + type sort = Sort of AST.ast + type bitvec_sort = BitvecSort of sort + type uninterpreted_sort = UninterpretedSort of sort + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) + let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) + let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let aton : sort array -> Z3native.ptr array = fun a -> + let f e = (gno e) in + Array.map f a + + let create : context -> Z3native.ptr -> sort = fun ctx no -> + let q : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno q ctx no) ; + (z3obj_create q) ; + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + + (** + Comparison operator. + @param a A sort + @param b A sort + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) : sort -> sort -> bool = fun a b -> + (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) + + (** + Returns a unique identifier for the sort. + *) + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) + + (** + The kind of the sort. + *) + let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) + + (** + The name of the sort + *) + let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) + + (** + A string representation of the sort. + *) + let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; + (z3obj_create res) ; + UninterpretedSort(Sort(res)) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) +end + + +(** Function declarations *) +and FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + + val create : context -> Z3native.ptr -> func_decl + val gno : func_decl -> Z3native.ptr + val gnc : func_decl -> Z3native.ptr + + val get_domain_size : func_decl -> int + val get_decl_kind : func_decl -> Z3enums.decl_kind +end = struct + open Sort + + type func_decl = FuncDecl of AST.ast + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) + let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) + + let aton (a : func_decl array) = + let f (e : func_decl) = (gno e) in + Array.map f a + + (** Parameters of Func_Decls *) + module Parameter = + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) + let get_kind ( x : parameter ) = + (match x with + | P_Int(_) -> PARAMETER_INT + | P_Dbl(_) -> PARAMETER_DOUBLE + | P_Sym(_) -> PARAMETER_SYMBOL + | P_Srt(_) -> PARAMETER_SORT + | P_Ast(_) -> PARAMETER_AST + | P_Fdl(_) -> PARAMETER_FUNC_DECL + | P_Rat(_) -> PARAMETER_RATIONAL) + + (**The int value of the parameter.*) + let get_int ( x : parameter ) = + match x with + | P_Int(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an int") + + (**The double value of the parameter.*) + let get_float ( x : parameter ) = + match x with + | P_Dbl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a double") + + (**The Symbol value of the parameter.*) + let get_symbol ( x : parameter ) = + match x with + | P_Sym(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a symbol") + + (**The Sort value of the parameter.*) + let get_sort ( x : parameter ) = + match x with + | P_Srt(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a sort") + + (**The AST value of the parameter.*) + let get_ast ( x : parameter ) = + match x with + | P_Ast(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an ast") + + (**The FunctionDeclaration value of the parameter.*) + let get_func_decl ( x : parameter ) = + match x with + | P_Fdl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a func_decl") + + (**The rational string value of the parameter.*) + let get_func_decl ( x : parameter ) = + match x with + | P_Rat(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a rational string") + end + + open Parameter + + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + create_ndr ctx name domain range + + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + mk_func_decl ctx (Symbol.mk_string ctx name) domain range + + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + create_pdr ctx prefix domain range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_ndr ctx name [||] range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + create_ndr ctx (Symbol.mk_string ctx name) [||] range + + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + create_pdr ctx prefix [||] range + + + (** + Comparison operator. + @param a A func_decl + @param b A func_decl + @return True if and are from the same context + and represent the same func_decl; false otherwise. + *) + let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) + + (** + A string representations of the function declaration. + *) + let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) + + (** + Returns a unique identifier for the function declaration. + *) + let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) + + (** + The arity of the function declaration + *) + let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) + + (** + The size of the domain of the function declaration + + *) + let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) + + (** + The domain of the function declaration + *) + let get_domain ( x : func_decl ) = + let n = (get_domain_size x) in + let f i = Sort.create (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + Array.init n f + + (** + The range of the function declaration + *) + let get_range ( x : func_decl ) = + Sort.create (gc x) (Z3native.get_range (gnc x) (gno x)) + + (** + The kind of the function declaration. + *) + let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) + + (** + The name of the function declaration + *) + let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) + + (** + The number of parameters of the function declaration + *) + let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) + + (** + The parameters of the function declaration + *) + let get_parameters ( x : func_decl ) = + let n = (get_num_parameters x) in + let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with + | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + ) in + mk_list f n + + (** + Create expression that applies function to arguments. + @param args The arguments + *) + let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.create_fa (gc x) x args +end + (** Parameter sets (of Solvers, Tactics, ...) A Params objects represents a configuration in the form of symbol/value pairs. *) -module Params = -struct +and Params : +sig + type params = z3_native_object + + val create : context -> Z3native.ptr -> params + + module ParamDescrs : sig + type param_descrs = z3_native_object + + val create : context -> Z3native.ptr -> param_descrs + end +end = struct type params = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.params_inc_ref ; dec_ref = Z3native.params_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs = - struct + module ParamDescrs : + sig + type param_descrs = z3_native_object + + val create : context -> Z3native.ptr -> param_descrs + end = struct type param_descrs = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.param_descrs_inc_ref ; dec_ref = Z3native.param_descrs_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1449,7 +1065,6 @@ struct *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = add_double x (Symbol.mk_string (z3obj_gc x) name) value - (** Adds a parameter setting. *) @@ -1460,7 +1075,7 @@ struct Creates a new parameter set *) let mk_params ( ctx : context ) = - cnstr ctx (Z3native.mk_params (context_gno ctx)) + create ctx (Z3native.mk_params (context_gno ctx)) (** A string representation of the parameter set. @@ -1468,18 +1083,69 @@ struct let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end - (** General expressions (terms), including Boolean logic *) -module Expr = -struct +and Expr : +sig + type expr = Expr of AST.ast + + val create : context -> Z3native.ptr -> expr + val create_fa : context -> FuncDecl.func_decl -> expr array -> expr + val gc : expr -> context + val gno : expr -> Z3native.ptr + val gnc : expr -> Z3native.ptr + val aton : expr array -> Z3native.ptr array + + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val get_func_decl : expr -> FuncDecl.func_decl +end = struct + type expr = Expr of AST.ast + + let create ( ctx : context ) ( obj : Z3native.ptr ) = + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then + (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) + else + let s = Z3native.get_sort (context_gno ctx) obj in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) obj) then + (match (Arithmetic.create_algebraic_num ctx obj) with Arithmetic.AlgebraicNum(Arithmetic.Expr(e)) -> e) + else + if (Z3native.is_numeral_ast (context_gno ctx) obj) && + (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + match sk with + | INT_SORT -> (match (Arithmetic.create_int_num ctx obj) with Arithmetic.IntNum(Arithmetic.IntExpr(Arithmetic.Expr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.create_rat_num ctx obj) with Arithmetic.RatNum(Arithmetic.RealExpr(Arithmetic.Expr(e))) -> e) + | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) + | _ -> raise (Z3native.Exception "Unsupported numeral object") + else + match sk with + | BOOL_SORT -> (match (Booleans.create ctx obj) with Booleans.BoolExpr(e) -> e) + | INT_SORT -> (match (Arithmetic.create_int_expr ctx obj) with Arithmetic.IntExpr(Arithmetic.Expr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.create_real_expr ctx obj) with Arithmetic.RealExpr(Arithmetic.Expr(e)) -> e) + | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) + | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) + | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) + | _ -> Expr(AST.create ctx obj) + + let aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (z3obj_gno a) in + Array.map f a + + let create_fa ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = + let o = Z3native.mk_app (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args) in + Expr.create ctx o + + let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) + let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) + let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) - | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno (z3obj_gno pp)) + | None -> Expr.create (gc x) (Z3native.simplify (gnc x) (gno x)) + | Some pp -> Expr.create (gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1491,29 +1157,29 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.cnstr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.create ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = (new func_decl x#gc)#cnstr_obj (Z3native.get_app_decl x#gnc x#gno) + let get_func_decl ( x : expr ) = FuncDecl.create (gc x) (Z3native.get_app_decl (gnc x) (gno x)) (** Indicates whether the expression is the true or false expression or something else (L_UNDEF). *) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) (** The number of arguments of the expression. *) - let get_num_args ( x : expr ) = Z3native.get_app_num_args x#gnc x#gno + let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) (** The arguments of the expression. *) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = create_expr x#gc (Z3native.get_app_arg x#gnc x#gno i) in + let f i = create (gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in Array.init n f (** @@ -1524,7 +1190,7 @@ struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - x#sno x#gc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + create (gc x) (Z3native.update_term (gnc x) (gno x) (Array.length args) (aton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -1537,7 +1203,7 @@ struct if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - create_expr x#gc (Z3native.substitute x#gnc x#gno (Array.length from) (expraton from) (expraton to_)) + create (gc x) (Z3native.substitute (gnc x) (gno x) (Array.length from) (aton from) (aton to_)) (** Substitute every occurrence of from in the expression with to. @@ -1552,7 +1218,7 @@ struct For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) let substitute_vars ( x : expr ) to_ = - create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) + create (gc x) (Z3native.substitute_vars (gnc x) (gno x) (Array.length to_) (aton to_)) (** @@ -1561,46 +1227,46 @@ struct @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = - if x#gc == to_ctx then + if (gc x) == to_ctx then x else - create_expr to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx)) + create to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) (** Returns a string representation of the expression. *) - let to_string ( x : expr ) = Z3native.ast_to_string x#gnc x#gno + let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast x#gnc x#gno) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted x#gnc x#gno + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) (** The Sort of the term. *) - let get_sort ( x : expr ) = create_sort x#gc (Z3native.get_sort x#gnc x#gno) + let get_sort ( x : expr ) = Sort.create (gc x) (Z3native.get_sort (gnc x) (gno x)) (** Indicates whether the term has Boolean sort. *) - let is_bool ( x : expr ) = (AST.is_expr x) && - (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno)) - + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) + (** Indicates whether the term represents a constant. *) - let is_const ( x : expr ) = (AST.is_expr x) && + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && - FuncDecl.get_domain_size(get_func_decl x) == 0 + (FuncDecl.get_domain_size (get_func_decl x)) == 0 (** Indicates whether the term is the constant true. @@ -1679,123 +1345,36 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) range#gno) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = + create ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) (** Creates a new Constant of sort and named . *) - let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name)range + let mk_const_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + mk_const ctx (Symbol.mk_string ctx name) range (** Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : func_decl ) = - create_expr_fa ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = + create_fa ctx f [||] (** Creates a fresh constant of sort and a name prefixed with . *) - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = - create_expr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix range#gno) - - (** - Create a Boolean constant. - *) - let mk_bool_const ( ctx : context ) ( name : Symbol.symbol ) = - ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) - - (** - Create a Boolean constant. - *) - let mk_bool_const_s ( ctx : context ) ( name : string ) = - mk_bool_const ctx (Symbol.mk_string ctx name) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = + create ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = - create_expr_fa ctx f args - - (** - The true Term. - *) - let mk_true ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_true (context_gno ctx)) - - (** - The false Term. - *) - let mk_false ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_false (context_gno ctx)) - - (** - Creates a Boolean value. - *) - let mk_bool ( ctx : context ) ( value : bool) = - if value then mk_true ctx else mk_false ctx - - (** - Creates the equality = . - *) - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq (context_gno ctx) x#gno y#gno) - - (** - Creates a distinct term. - *) - let mk_distinct ( ctx : context ) ( args : expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct (context_gno ctx) (Array.length args) (astaton args)) - - (** - Mk an expression representing not(a). - *) - let mk_not ( ctx : context ) ( a : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_not (context_gno ctx) a#gno) - - (** - Create an expression representing an if-then-else: ite(t1, t2, t3). - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - *) - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite (context_gno ctx) t1#gno t2#gno t3#gno) - - (** - Create an expression representing t1 iff t2. - *) - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing t1 -> t2. - *) - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing t1 xor t2. - *) - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing the AND of args - *) - let mk_and ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_and (context_gno ctx) (Array.length args) (astaton args)) - - (** - Create an expression representing the OR of args - *) - let mk_or ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_or (context_gno ctx) (Array.length args) (astaton args)) + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = + create_fa ctx f args (** Create a numeral of a given sort. @@ -1803,8 +1382,8 @@ struct @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. @return A Term with value and sort *) - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - create_expr ctx (Z3native.mk_numeral (context_gno ctx) v ty#gno) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : Sort.sort ) = + create ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1813,13 +1392,147 @@ struct @param ty Sort of the numeral @return A Term with value and type *) - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_int (context_gno ctx) v ty#gno) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = + create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + + let aton (a : expr array) = + let f (e : expr) = (gno e) in + Array.map f a +end + +(** Boolean expressions *) +and Booleans : +sig + type bool_expr = BoolExpr of Expr.expr + type bool_sort = BoolSort of Sort.sort + + val create : context -> Z3native.ptr -> bool_expr + val aton : bool_expr array -> Z3native.ptr array +end = struct + type bool_expr = BoolExpr of Expr.expr + type bool_sort = BoolSort of Sort.sort + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.create ctx no) in + BoolExpr(Expr.Expr(a)) + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) + + let aton ( a : bool_expr array ) = + let f (e : bool_expr) = (gno e) in + Array.map f a + + let mk_sort ( ctx : context ) = + BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) + + (** + Create a Boolean constant. + *) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let s = (match (mk_sort ctx) with BoolSort(q) -> q) in + BoolExpr(Expr.mk_const ctx name s) + + (** + Create a Boolean constant. + *) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) + + (** + The true Term. + *) + let mk_true ( ctx : context ) = + create ctx (Z3native.mk_true (context_gno ctx)) + + (** + The false Term. + *) + let mk_false ( ctx : context ) = + create ctx (Z3native.mk_false (context_gno ctx)) + + (** + Creates a Boolean value. + *) + let mk_val ( ctx : context ) ( value : bool ) = + if value then mk_true ctx else mk_false ctx + + (** + Creates the equality = . + *) + let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = + create ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + (** + Creates a distinct term. + *) + let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = + create ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + + (** + Mk an expression representing not(a). + *) + let mk_not ( ctx : context ) ( a : bool_expr ) = + create ctx (Z3native.mk_not (context_gno ctx) (gno a)) + + (** + Create an expression representing an if-then-else: ite(t1, t2, t3). + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + *) + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + create ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + + (** + Create an expression representing t1 iff t2. + *) + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + + (** + Create an expression representing t1 -> t2. + *) + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + (** + Create an expression representing t1 xor t2. + *) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + + (** + Create an expression representing the AND of args + *) + let mk_and ( ctx : context ) ( args : bool_expr array ) = + create ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + + (** + Create an expression representing the OR of args + *) + let mk_or ( ctx : context ) ( args : bool_expr array ) = + create ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) end (** Quantifier expressions *) -module Quantifiers = -struct +and Quantifiers : +sig + type quantifier = Quantifier of Expr.expr + + val create : context -> Z3native.ptr -> quantifier +end = struct + type quantifier = Quantifier of Expr.expr + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.create ctx no) in + Quantifier(Expr.Expr(a)) + + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) + + (** The de-Burijn index of a bound variable. @@ -1838,11 +1551,11 @@ struct on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its index. *) - let get_index ( x : expr ) = - if not (AST.is_var x) then + let get_index ( x : Expr.expr ) = + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value x#gnc x#gno + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) (** Quantifier patterns @@ -1850,33 +1563,57 @@ struct non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Pattern = - struct + module Patterns : + sig + type pattern = Pattern of AST.ast + + val create : context -> Z3native.ptr -> pattern + val aton : pattern array -> Z3native.ptr array + end = struct + type pattern = Pattern of AST.ast + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + Pattern(res) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + (** The number of terms in the pattern. *) let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms x#gnc x#gno + Z3native.get_pattern_num_terms (gnc x) (gno x) (** The terms in the pattern. *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in - let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f (** A string representation of the pattern. *) - let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + + let aton (a : pattern array) = + let f (e : pattern) = (gno e) in + Array.map f a end (** Indicates whether the quantifier is universal. *) let is_universal ( x : quantifier ) = - Z3native.is_quantifier_forall x#gnc x#gno + Z3native.is_quantifier_forall (gnc x) (gno x) (** Indicates whether the quantifier is existential. @@ -1886,45 +1623,45 @@ struct (** The weight of the quantifier. *) - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) (** The number of patterns. *) - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) (** The patterns. *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + let f i = (Patterns.create (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** The number of no-patterns. *) - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) (** The no-patterns. *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + let f i = (Patterns.create (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** The number of bound variables. *) - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) (** The symbols for the bound variables. *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (Symbol.create x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in Array.init n f (** @@ -1932,31 +1669,31 @@ struct *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + let f i = (Sort.create (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f (** The body of the quantifier. *) let get_body ( x : quantifier ) = - (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + Booleans.create (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @param index The de-Bruijn index of the variable @param ty The sort of the variable *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound (context_gno ctx) index ty#gno) + let mk_bound ( ctx : context ) ( index : int ) ( ty : Sort.sort ) = + Expr.create ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) (** Create a quantifier pattern. *) - let mk_pattern ( ctx : context ) ( terms : expr array ) = + let mk_pattern ( ctx : context ) ( terms : Expr.expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (astaton terms)) + Patterns.create ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (Expr.aton terms)) (** Create a universal Quantifier. @@ -1977,95 +1714,96 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (patternaton patterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (Patterns.aton patterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - body#gno) + create ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - body#gno) + create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Expr.gno body)) + (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (patternaton patterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (Patterns.aton patterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) - + create ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - body#gno) + create ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - body#gno) + create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Expr.gno body)) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -2075,7 +1813,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2083,75 +1821,104 @@ struct end (** Functions to manipulate Array expressions *) -module Arrays = -struct +and Arrays : +sig + type array_expr = ArrayExpr of Expr.expr + type array_sort = ArraySort of Sort.sort + + val create_expr : context -> Z3native.ptr -> array_expr +end = struct + type array_expr = ArrayExpr of Expr.expr + type array_sort = ArraySort of Sort.sort + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + ArrayExpr(e) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + ArraySort(s) + + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gno s) + + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gno e) + + let aton (a : array_expr array) = + let f (e : array_expr) = (egno e) in + Array.map f a + + (** Create a new array sort. *) - let mk_sort ( ctx : context ) domain range = - (new array_sort ctx)#cnstr_dr domain range + let mk_sort ( ctx : context ) ( domain : Sort.sort ) ( range : Sort.sort ) = + create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** Indicates whether the term is an array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). Array store takes at least 3 arguments. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the function passed as parameter. *) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) (** Indicates whether the term is of an array sort. *) - let is_array ( x : expr ) = - (Z3native.is_app x#gnc x#gno) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + let is_array ( x : Expr.expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + let get_domain ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) + let get_range ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort ) ( range : Sort.sort ) = + ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** Create an array constant. *) - let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( domain : Sort.sort ) ( range : Sort.sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range (** @@ -2166,8 +1933,8 @@ struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - ((create_expr ctx (Z3native.mk_select (context_gno ctx) a#gno i#gno)) :> array_expr) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) = + create_expr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) (** Array update. @@ -2185,8 +1952,8 @@ struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_store (context_gno ctx) a#gno i#gno v#gno) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) ( v : Expr.expr ) = + create_expr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) (** Create a constant array. @@ -2196,8 +1963,8 @@ struct *) - let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array (context_gno ctx) domain#gno v#gno) + let mk_const_array ( ctx : context ) ( domain : Sort.sort ) ( v : Expr.expr ) = + create_expr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) (** Maps f on the argument arrays. @@ -2209,8 +1976,8 @@ struct *) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = - ((create_expr ctx (Z3native.mk_map (context_gno ctx) f#gno (Array.length args) (astaton args))) :> array_expr) + let mk_map ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : array_expr array ) = + create_expr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args)) (** Access the array default value. @@ -2219,149 +1986,184 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - ((create_expr ctx (Z3native.mk_array_default (context_gno ctx) arg#gno)) :> array_expr) + create_expr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) -module Sets = -struct +and Sets : +sig + type set_sort = SetSort of Sort.sort + +end = struct + type set_sort = SetSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + SetSort(s) + (** Indicates whether the term is set union *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) (** Create a set type. *) - let mk_sort ( ctx : context ) ( ty : sort) = - (new set_sort ctx)#cnstr_s ty + let mk_sort ( ctx : context ) ( ty : Sort.sort ) = + create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. *) - let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set (context_gno ctx) domain#gno)) + let mk_empty ( ctx : context ) ( domain : Sort.sort ) = + (Expr.create ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) (** Create the full set. *) - let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set (context_gno ctx) domain#gno) + let mk_full ( ctx : context ) ( domain : Sort.sort ) = + Expr.create ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) (** Add an element to the set. *) - let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add (context_gno ctx) set#gno element#gno) + let mk_set_add ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) (** Remove an element from a set. *) - let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del (context_gno ctx) set#gno element#gno) + let mk_del ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) (** Take the union of a list of sets. *) - let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (astaton args)) + let mk_union ( ctx : context ) ( args : Expr.expr array ) = + Expr.create ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (Expr.aton args)) (** Take the intersection of a list of sets. *) - let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (astaton args)) + let mk_intersection ( ctx : context ) ( args : Expr.expr array ) = + Expr.create ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (Expr.aton args)) (** Take the difference between two sets. *) - let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference (context_gno ctx) arg1#gno arg2#gno) + let mk_difference ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) (** Take the complement of a set. *) - let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement (context_gno ctx) arg#gno) + let mk_complement ( ctx : context ) ( arg : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) (** Check for set membership. *) - let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member (context_gno ctx) elem#gno set#gno) + let mk_membership ( ctx : context ) ( elem : Expr.expr ) ( set : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) (** Check for subsetness of sets. *) - let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset (context_gno ctx) arg1#gno arg2#gno) + let mk_subset ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) end (** Functions to manipulate Finite Domain expressions *) -module FiniteDomains = -struct - (** - Create a new finite domain sort. - *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) size = - (new finite_domain_sort ctx)#cnstr_si name size +and FiniteDomains : +sig + type finite_domain_sort = FiniteDomainSort of Sort.sort + +end = struct + type finite_domain_sort = FiniteDomainSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + FiniteDomainSort(s) + + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) (** Create a new finite domain sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si (Symbol.mk_string ctx name) size + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + create_sort ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size) + + (** + Create a new finite domain sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_sort ctx (Symbol.mk_string ctx name) size (** Indicates whether the term is of an array sort. *) - let is_finite_domain ( x : expr ) = - (Z3native.is_app x#gnc x#gno) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + let is_finite_domain ( x : Expr.expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) (** The size of the finite domain sort. *) - let get_size (x : finite_domain_sort) = - let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + let get_size ( x : finite_domain_sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end (** Functions to manipulate Relation expressions *) -module Relations = -struct +and Relations : +sig + type relation_sort = RelationSort of Sort.sort + +end = struct + type relation_sort = RelationSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + RelationSort(s) + + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) + (** Indicates whether the term is of a relation sort. *) - let is_relation ( x : expr ) = - ((Z3native.is_app x#gnc x#gno) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT)) + let is_relation ( x : Expr.expr ) = + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2370,40 +2172,40 @@ struct The function takes n+1 arguments, where the first argument is the relation and the remaining n elements correspond to the n columns of the relation. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) (** Indicates whether the term is an empty relation *) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) (** Indicates whether the term is a test for the emptiness of a relation *) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) (** Indicates whether the term is a relational join *) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_join ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) (** Indicates whether the term is the union or convex hull of two relations. The function takes two arguments. *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) (** Indicates whether the term is the widening of two relations The function takes two arguments. *) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_widen ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). The function takes one argument. *) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_project ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) (** Indicates whether the term is a relation filter @@ -2414,7 +2216,7 @@ struct corresponding to the columns of the relation. So the first column in the relation has index 0. *) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) (** Indicates whether the term is an intersection of a relation with the negation of another. @@ -2429,7 +2231,7 @@ struct target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with ( x : expr ) on the columns c1, d1, .., cN, dN. *) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_negation_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) (** Indicates whether the term is the renaming of a column in a relation @@ -2437,12 +2239,12 @@ struct The function takes one argument. The parameters contain the renaming as a cycle. *) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_rename ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) (** Indicates whether the term is the complement of a relation *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) (** Indicates whether the term is a relational select @@ -2451,7 +2253,7 @@ struct The function takes n+1 arguments, where the first argument is a relation, and the remaining n arguments correspond to a record. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) (** Indicates whether the term is a relational clone (copy) @@ -2462,38 +2264,153 @@ struct for terms of kind to perform destructive updates to the first argument. *) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_clone ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) (** The arity of the relation sort. *) - let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) (** The sorts of the columns of the relation sort. *) - let get_column_sorts (x : relation_sort) = + let get_column_sorts ( x : relation_sort ) = let n = get_arity x in - let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + let f i = (create_sort (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in Array.init n f end (** Functions to manipulate Datatype expressions *) -module Datatypes = -struct +and Datatypes : +sig + type datatype_expr = DatatypeExpr of Expr.expr + type datatype_sort = DatatypeSort of Sort.sort + + val create_expr : context -> Z3native.ptr -> datatype_expr +end = struct + type datatype_expr = DatatypeExpr of Expr.expr + type datatype_sort = DatatypeSort of Sort.sort + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + DatatypeExpr(e) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + DatatypeSort(s) + + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) + + (** Constructors *) module Constructor = struct + type constructor_extra = { + m_n : int; + mutable m_tester_decl : FuncDecl.func_decl option; + mutable m_constructor_decl : FuncDecl.func_decl option ; + mutable m_accessor_decls : FuncDecl.func_decl array option} + type constructor = Constructor of (z3_native_object * constructor_extra) + + let create_ssssi ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + let n = (Array.length field_names) in + if n != (Array.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if n != (Array.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) + (Symbol.gno recognizer) + n + (Symbol.aton field_names) + (Sort.aton sorts) + sort_refs) in + let no : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + let ex : constructor_extra = { m_n = n; + m_tester_decl = None; + m_constructor_decl = None; + m_accessor_decls = None} in + (z3obj_sno no ctx ptr) ; + (z3obj_create no) ; + let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f no ; + Constructor(no, ex) + + let init_extra ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_tester_decl with + | None -> + let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in + ex.m_constructor_decl <- Some (FuncDecl.create (z3obj_gc no) a) ; + ex.m_tester_decl <- Some (FuncDecl.create (z3obj_gc no) b) ; + ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; + () + | _ -> () + + let get_n ( x : constructor ) = + match x with Constructor(no, ex) -> + ex.m_n + + let rec tester_decl ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_tester_decl with + | Some(s) -> s + | None -> init_extra x ; tester_decl x + + let rec constructor_decl ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_constructor_decl with + | Some(s) -> s + | None -> init_extra x ; constructor_decl x + + let rec accessor_decls ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_accessor_decls with + | Some(s) -> s + | None -> init_extra x ; accessor_decls x + + let aton ( a : constructor array ) = + let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in + Array.map f a + + (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = x#get_n + let get_num_fields ( x : constructor ) = get_n x (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = x#constructor_decl + let get_constructor_decl ( x : constructor ) = constructor_decl x (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = x#tester_decl + let get_tester_decl ( x : constructor ) = tester_decl x (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = x#accessor_decls + let get_accessor_decls ( x : constructor ) = accessor_decls x end + (** Constructor list objects *) + module ConstructorList = + struct + type constructor_list = z3_native_object + + let create ( ctx : context )( c : Constructor.constructor array ) = + let res : constructor_list = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Constructor.aton c))) ; + (z3obj_create res) ; + let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f res; + res + + let aton (a : constructor_list array) = + let f (e : constructor_list) = (z3obj_gno e) in + Array.map f a + end + (* DATATYPES *) (** Create a datatype constructor. @@ -2505,8 +2422,8 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = + Constructor.create_ssssi ctx name recognizer field_names sorts sort_refs (** @@ -2519,20 +2436,21 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : constructor array) = - (new datatype_sort ctx)#cnstr_sc name constructors + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array) = + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Constructor.aton constructors)) in + create_sort ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2540,16 +2458,16 @@ struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in - let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let f e = (ConstructorList.create ctx e) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (constructor_listaton cla)) in - let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (ConstructorList.aton cla)) in + let g e = (create_sort ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2558,130 +2476,230 @@ struct c (** The number of constructors of the datatype sort. *) - let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) (** The range of the array sort. *) - let get_constructors (x : datatype_sort) = + let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f (** The recognizers. *) - let get_recognizers (x : datatype_sort) = + let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f (** The constructor accessors. *) - let get_accessors (x : datatype_sort) = + let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in - let ds = (Z3native.get_domain_size fd#gnc fd#gno) in - let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + let fd = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in + let g j = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in Array.init ds g ) in Array.init n f end (** Functions to manipulate Enumeration expressions *) -module Enumerations = -struct - (** - Create a new enumeration sort. - *) - let mk_sort ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss name enum_names +and Enumerations : +sig + type enum_sort_data + type enum_sort = EnumSort of (Sort.sort * enum_sort_data) +end = struct + type enum_sort_data = { mutable _constdecls : FuncDecl.func_decl array ; + mutable _testerdecls : FuncDecl.func_decl array } + type enum_sort = EnumSort of (Sort.sort * enum_sort_data) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + let s = (Sort.create ctx no) in + let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; + _testerdecls = (let f e = FuncDecl.create ctx e in (Array.map f tdecls)) } in + EnumSort(s, e) + + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) + (** Create a new enumeration sort. *) - let mk_sort_s ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss - (Symbol.mk_string ctx name) - (Symbol.mk_strings ctx enum_names) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in + create_sort ctx a b c + + (** + Create a new enumeration sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = + mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = x#const_decls + let get_const_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._constdecls (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = x#tester_decls + let get_tester_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._testerdecls end (** Functions to manipulate List expressions *) -module Lists = -struct - (** - Create a new list sort. - *) - let mk_sort ( ctx : context ) (name : Symbol.symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort +and Lists : +sig + type list_sort_data + type list_sort = ListSort of (Sort.sort * list_sort_data) - (** - Create a new list sort. - *) +end = struct + type list_sort_data = { _nildecl : FuncDecl.func_decl ; + _is_nildecl : FuncDecl.func_decl ; + _consdecl : FuncDecl.func_decl ; + _is_consdecl : FuncDecl.func_decl ; + _headdecl : FuncDecl.func_decl ; + _taildecl : FuncDecl.func_decl } + type list_sort = ListSort of (Sort.sort * list_sort_data) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + let s = (Sort.create ctx no) in + let e = {_nildecl = FuncDecl.create ctx nildecl; + _is_nildecl = FuncDecl.create ctx is_nildecl; + _consdecl = FuncDecl.create ctx consdecl; + _is_consdecl = FuncDecl.create ctx is_consdecl; + _headdecl = FuncDecl.create ctx headdecl; + _taildecl = FuncDecl.create ctx taildecl} in + ListSort(s, e) + + let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) + + + (** Create a new list sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + create_sort ctx r a b c d e f + + (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = x#nil_decl + let get_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._nildecl (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = x#is_nil_decl + let get_is_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_nildecl (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = x#cons_decl + let get_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._consdecl (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = x#is_cons_decl + let get_is_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_consdecl (** The declaration of the head function of this list sort. *) - let get_head_decl (x : list_sort) = x#head_decl + let get_head_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._headdecl (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = x#tail_decl + let get_tail_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._taildecl (** The empty list. *) - let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] + let nil ( x : list_sort ) = Expr.create_fa (sgc x) (get_nil_decl x) [||] end (** Functions to manipulate Tuple expressions *) -module Tuples = -struct - (** - Create a new tuple sort. - *) - let mk_sort ( ctx : context ) name field_names field_sorts = - (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts +and Tuples : +sig + type tuple_sort = TupleSort of Sort.sort +end = struct + type tuple_sort = TupleSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + TupleSort(s) + + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) + + (** Create a new tuple sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = + let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Symbol.aton field_names) (Sort.aton field_sorts)) in + (* CMW: leaks a,b? *) + create_sort ctx r (** The constructor function of the tuple. *) - let get_mk_decl (x : tuple_sort) = - (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + let get_mk_decl ( x : tuple_sort ) = + FuncDecl.create (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) (** The number of fields in the tuple. *) - let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) (** The field declarations. *) - let get_field_decls (x : tuple_sort) = + let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in - let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + let f i = FuncDecl.create (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end (** Functions to manipulate arithmetic expressions *) -module Arithmetic = -struct +and Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type int_sort = IntSort of Sort.sort + type real_sort = RealSort of Sort.sort + + type arith_expr = Expr of Expr.expr + type int_expr = IntExpr of arith_expr + type real_expr = RealExpr of arith_expr + + type int_num = IntNum of int_expr + type rat_num = RatNum of real_expr + type algebraic_num = AlgebraicNum of arith_expr + + + val create_arith_expr : context -> Z3native.ptr -> arith_expr + val create_int_expr : context -> Z3native.ptr -> int_expr + val create_real_expr : context -> Z3native.ptr -> real_expr + val create_int_num : context -> Z3native.ptr -> int_num + val create_rat_num : context -> Z3native.ptr -> rat_num + val create_algebraic_num : context -> Z3native.ptr -> algebraic_num +end = struct + type arith_sort = ArithSort of Sort.sort + type int_sort = IntSort of Sort.sort + type real_sort = RealSort of Sort.sort + + type arith_expr = ArithExpr of Expr.expr + type int_expr = IntExpr of arith_expr + type real_expr = RealExpr of arith_expr + + type int_num = IntNum of int_expr + type rat_num = RatNum of real_expr + type algebraic_num = AlgebraicNum of arith_expr + + let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = + ArithExpr(Expr.create ctx no) + + let create_int_expr ( ctx : context ) ( no : Z3native.ptr ) = + IntExpr(create_arith_expr ctx no) + + let create_real_expr ( ctx : context ) ( no : Z3native.ptr ) = + RealExpr(create_arith_expr ctx no) + + let create_int_num ( ctx : context ) ( no : Z3native.ptr ) = + IntNum(create_int_expr ctx no) + + let create_rat_num ( ctx : context ) ( no : Z3native.ptr ) = + RatNum(create_real_expr ctx no) + (** Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort (context_gno ctx)) + (new int_sort ctx)#create_obj (Z3native.mk_int_sort (context_gno ctx)) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort (context_gno ctx)) + (new real_sort ctx)#create_obj (Z3native.mk_real_sort (context_gno ctx)) (** Indicates whether the term is of integer sort. @@ -2802,11 +2820,11 @@ struct (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + (new int_num x#gc)#create_obj (Z3native.get_numerator x#gnc x#gno) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + (new int_num x#gc)#create_obj (Z3native.get_denominator x#gnc x#gno) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2844,75 +2862,92 @@ struct Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - (create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) t#gno) :> arith_expr) + ArithExpr(create ctx (Z3native.mk_unary_minus (context_gno ctx) + (gno (match t with ArithExpr(b) -> b)))) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - (create_expr ctx (Z3native.mk_div (context_gno ctx) t1#gno t2#gno) :> arith_expr) + ArithExpr(create ctx (Z3native.mk_div (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 mod t2. The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_mod (context_gno ctx) t1#gno t2#gno) + IntExpr(create ctx (Z3native.mk_mod (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_rem (context_gno ctx) t1#gno t2#gno) + IntExpr(create ctx (Z3native.mk_rem (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 ^ t2. *) - let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (create_expr ctx (Z3native.mk_power (context_gno ctx) t1#gno t2#gno) :> arith_expr) + let mk_power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + ArithExpr(create_expr ctx (Z3native.mk_power (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_lt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_le (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_le (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_gt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_ge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Coerce an integer to a real. @@ -2925,7 +2960,8 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real (context_gno ctx) t#gno) + RealExpr(create (Z3native.mk_int2real (context_gno ctx) + (gno (match t with BoolExpr(b) -> b)))) (** Coerce a real to an integer. @@ -2935,14 +2971,14 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int (context_gno ctx) t#gno) + (new int_expr ctx)#create_obj (Z3native.mk_real2int (context_gno ctx) t#gno) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int (context_gno ctx) t#gno) - + BoolExpr(create ctx (Z3native.mk_is_int (context_gno ctx) + (gno (match t with BoolExpr(b) -> b)))) (** Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^. @@ -2951,7 +2987,7 @@ struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) (** Return a lower bound for the given real algebraic number. @@ -2961,7 +2997,7 @@ struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2981,7 +3017,7 @@ struct raise (Z3native.Exception "Denominator is zero") else - (new rat_num ctx)#cnstr_obj (Z3native.mk_real (context_gno ctx) num den) + (new rat_num ctx)#create_obj (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2989,7 +3025,7 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) + (new rat_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create a real numeral. @@ -2998,14 +3034,14 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) + (new rat_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) + (new int_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) (** Create an integer numeral. @@ -3013,7 +3049,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) + (new int_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3021,13 +3057,30 @@ end (** Functions to manipulate bit-vector expressions *) -module BitVectors = -struct +and BitVectors : +sig + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val create_expr : context -> Z3native.ptr -> bitvec_expr + val create_num : context -> Z3native.ptr -> bitvec_num +end = struct + type bitvec_expr = Expr of Expr.expr + type bitvec_num = BitVecExpr of bitvec_expr + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + BitVecExpr(e) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + let e = (create_expr ctx no) in + BitVecNum(e) + (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort (context_gno ctx) size) + (new bitvec_sort ctx)#create_obj (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3328,91 +3381,91 @@ struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) (** Unsigned division. @@ -3424,7 +3477,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) (** Signed division. @@ -3439,7 +3492,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) (** Unsigned remainder. @@ -3449,7 +3502,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) (** Signed remainder. @@ -3461,7 +3514,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) (** Two's complement signed remainder (sign follows divisor). @@ -3470,7 +3523,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than @@ -3478,7 +3531,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvult (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed less-than @@ -3486,7 +3541,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvslt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned less-than or equal to. @@ -3494,7 +3551,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvule (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed less-than or equal to. @@ -3502,7 +3561,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsle (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned greater than or equal to. @@ -3510,7 +3571,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvuge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed greater than or equal to. @@ -3518,7 +3581,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned greater-than. @@ -3526,7 +3591,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvugt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed greater-than. @@ -3534,7 +3601,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsgt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Bit-vector concatenation. @@ -3545,7 +3614,9 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat (context_gno ctx) t1#gno t2#gno) + BitVectors.BitVecExpr(create ctx (Z3native.mk_concat (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Bit-vector extraction. @@ -3556,7 +3627,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) (** Bit-vector sign extension. @@ -3566,7 +3637,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_sign_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Bit-vector zero extension. @@ -3577,7 +3648,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_zero_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Bit-vector repetition. @@ -3585,7 +3656,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_repeat (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Shift left. @@ -3600,7 +3671,9 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvshl (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Logical shift right @@ -3614,7 +3687,9 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvlshr (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Arithmetic shift right @@ -3630,7 +3705,9 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvashr (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Rotate Left. @@ -3639,7 +3716,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_rotate_left (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) (** Rotate Right. @@ -3648,7 +3725,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_rotate_right (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) (** Rotate Left. @@ -3657,7 +3734,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_ext_rotate_left (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Rotate Right. @@ -3667,7 +3746,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_ext_rotate_right (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an bit bit-vector from the integer argument . @@ -3680,7 +3761,7 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv (context_gno ctx) n t#gno) + BitVecExpr(create ctx (Z3native.mk_int2bv (context_gno ctx) n (gno (match t with IntExpr(b) -> b)))) (** Create an integer from the bit-vector argument . @@ -3698,7 +3779,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) + (new int_expr ctx)#create_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3706,7 +3787,10 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3714,23 +3798,30 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow (context_gno ctx) t1#gno t2#gno) - + BoolExpr(create ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) + (** Create a predicate that checks that the bit-wise subtraction does not overflow. The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow (context_gno ctx) t1#gno t2#gno) - + BoolExpr(create ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) + (** Create a predicate that checks that the bit-wise subtraction does not underflow. The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3738,7 +3829,9 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3746,7 +3839,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow (context_gno ctx) t#gno) + BoolExpr(create ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (gno (match t with BitVecExpr(b) -> b)))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3754,7 +3847,10 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3762,7 +3858,9 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create a bit-vector numeral. @@ -3771,12 +3869,13 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) + (new bitvec_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) end (** Functions to manipulate proof expressions *) -module Proofs = -struct +and Proofs : +sig +end = struct (** Indicates whether the term is a Proof for the expression 'true'. *) @@ -4259,13 +4358,13 @@ struct type goal = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.goal_inc_ref ; dec_ref = Z3native.goal_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4318,7 +4417,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new bool_expr (z3obj_gc x))#create_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4334,7 +4433,7 @@ struct (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - cnstr to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : Params.params option ) = @@ -4352,7 +4451,7 @@ struct Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; Z3native.tactic_dec_ref (z3obj_gnc x) tn ; - cnstr (z3obj_gc x) res + create (z3obj_gc x) res (** @@ -4365,7 +4464,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - cnstr ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) @@ -4380,13 +4479,13 @@ struct type model = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.model_inc_ref ; dec_ref = Z3native.model_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4400,13 +4499,13 @@ struct type func_interp = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.func_interp_inc_ref ; dec_ref = Z3native.func_interp_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4419,13 +4518,13 @@ struct type func_entry = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.func_entry_inc_ref ; dec_ref = Z3native.func_entry_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4467,7 +4566,7 @@ struct *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in - let f i = (FuncEntry.cnstr (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4534,11 +4633,11 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + get_func_interp x ((new func_decl f#gc)#create_obj fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in - if (Z3native.is_null n) then None else Some (FuncInterp.cnstr (z3obj_gc x) n) + if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) @@ -4546,7 +4645,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4556,15 +4655,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4619,7 +4718,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4644,13 +4743,13 @@ struct type probe = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.probe_inc_ref ; dec_ref = Z3native.probe_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4686,48 +4785,48 @@ struct Creates a new Probe. *) let mk_probe ( ctx : context ) ( name : string ) = - (cnstr ctx (Z3native.mk_probe (context_gno ctx) name)) + (create ctx (Z3native.mk_probe (context_gno ctx) name)) (** Create a probe that always evaluates to . *) let const ( ctx : context ) ( v : float ) = - (cnstr ctx (Z3native.probe_const (context_gno ctx) v)) + (create ctx (Z3native.probe_const (context_gno ctx) v)) (** Create a probe that evaluates to "true" when the value returned by is less than the value returned by *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is greater than the value returned by *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is less than or equal the value returned by *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is greater than or equal the value returned by *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is equal to the value returned by *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4735,7 +4834,7 @@ struct *) (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4743,7 +4842,7 @@ struct *) (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4751,7 +4850,7 @@ struct *) (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = - (cnstr ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) + (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) end @@ -4767,13 +4866,13 @@ struct type tactic = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.tactic_inc_ref ; dec_ref = Z3native.tactic_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4786,13 +4885,13 @@ struct type apply_result = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.apply_result_inc_ref ; dec_ref = Z3native.apply_result_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4803,19 +4902,19 @@ struct (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in - let f i = Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = - Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. #return A model for g *) let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.cnstr (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) @@ -4826,13 +4925,13 @@ struct (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with - | None -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) - | Some (pn) -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) + | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) (** The number of supported tactics. @@ -4858,7 +4957,7 @@ struct Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - cnstr ctx (Z3native.mk_tactic (context_gno ctx) name) + create ctx (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and @@ -4870,17 +4969,17 @@ struct | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in match (Array.fold_left f None ts) with | None -> - cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in - cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that applies to a goal for milliseconds. @@ -4888,7 +4987,7 @@ struct If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - cnstr ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) + create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) (** Create a tactic that applies to a given goal if the probe @@ -4898,52 +4997,52 @@ struct *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - cnstr ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) + create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - cnstr ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) + create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - cnstr ctx (Z3native.tactic_skip (context_gno ctx)) + create ctx (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - cnstr ctx (Z3native.tactic_fail (context_gno ctx)) + create ctx (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : Probe.probe ) = - cnstr ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - cnstr ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - cnstr ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) + create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . @@ -4956,14 +5055,14 @@ struct Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - cnstr ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) + create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Interrupt the execution of a Z3 procedure. @@ -4980,13 +5079,13 @@ struct type solver = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.solver_inc_ref ; dec_ref = Z3native.solver_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5003,13 +5102,13 @@ struct type statistics = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.stats_inc_ref ; dec_ref = Z3native.stats_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5028,7 +5127,7 @@ struct mutable m_float : float } (**/**) - let cnstr_si k v = + let create_si k v = let res : statistics_entry = { m_key = k ; m_is_int = true ; @@ -5038,7 +5137,7 @@ struct } in res - let cnstr_sd k v = + let create_sd k v = let res : statistics_entry = { m_key = k ; m_is_int = false ; @@ -5089,9 +5188,9 @@ struct let f i = ( let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - (Entry.cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -5126,7 +5225,7 @@ struct Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5200,7 +5299,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5208,9 +5307,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in + let f i = ((new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -5225,7 +5324,7 @@ struct if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (astaton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (AST.aton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5243,7 +5342,7 @@ struct if (Z3native.is_null q) then None else - Some (Model.cnstr (z3obj_gc x) q) + Some (Model.create (z3obj_gc x) q) (** The proof of the last Check. @@ -5266,7 +5365,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5281,7 +5380,7 @@ struct Solver statistics. *) let get_statistics ( x : solver ) = - (Statistics.cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -5292,8 +5391,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with - | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) + | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) (** Creates a new (incremental) solver. @@ -5306,7 +5405,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) + (create ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -5315,7 +5414,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = - (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) + (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** A string representation of the solver. @@ -5330,13 +5429,13 @@ struct type fixedpoint = z3_native_object (**/**) - let cnstr ( ctx : context ) = + let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.fixedpoint_inc_ref ; dec_ref = Z3native.fixedpoint_dec_ref } in (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5356,7 +5455,7 @@ struct Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. @@ -5487,30 +5586,30 @@ struct Convert benchmark given as set of axioms, rules and queries to a string. *) let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (astaton queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (AST.aton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = cnstr ctx + let mk_fixedpoint ( ctx : context ) = create ctx end (** Global and context options @@ -5590,7 +5689,7 @@ struct *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (astaton assumptions) + (Array.length assumptions) (AST.aton assumptions) formula#gno (** @@ -5613,7 +5712,7 @@ struct Z3native.parse_smtlib_string (context_gno ctx) str cs (Symbol.aton sort_names) - (astaton sorts) + (AST.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5633,7 +5732,7 @@ struct Z3native.parse_smtlib_file (context_gno ctx) file_name cs (Symbol.aton sort_names) - (astaton sorts) + (AST.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5675,7 +5774,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = (new func_decl ctx)#create_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5708,7 +5807,7 @@ struct Z3native.parse_smtlib2_string (context_gno ctx) str cs (Symbol.aton sort_names) - (astaton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5728,7 +5827,7 @@ struct Z3native.parse_smtlib2_string (context_gno ctx) file_name cs (Symbol.aton sort_names) - (astaton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) From 0138d0c11c283c1d3457055975df69fdac9b5410 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Feb 2013 23:18:55 +0000 Subject: [PATCH 298/646] Checkpoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 643 ++++++++++++++++++++++++++--------------------- 1 file changed, 355 insertions(+), 288 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0e47912ae..58c319d4d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1097,6 +1097,7 @@ sig val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val get_func_decl : expr -> FuncDecl.func_decl + val is_numeral : expr -> bool end = struct type expr = Expr of AST.ast @@ -1107,20 +1108,20 @@ end = struct let s = Z3native.get_sort (context_gno ctx) obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.create_algebraic_num ctx obj) with Arithmetic.AlgebraicNum(Arithmetic.Expr(e)) -> e) + (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.Expr(e)) -> e) else if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with - | INT_SORT -> (match (Arithmetic.create_int_num ctx obj) with Arithmetic.IntNum(Arithmetic.IntExpr(Arithmetic.Expr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.create_rat_num ctx obj) with Arithmetic.RatNum(Arithmetic.RealExpr(Arithmetic.Expr(e))) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.Expr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.Expr(e))) -> e) | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) | _ -> raise (Z3native.Exception "Unsupported numeral object") else match sk with - | BOOL_SORT -> (match (Booleans.create ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.create_int_expr ctx obj) with Arithmetic.IntExpr(Arithmetic.Expr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.create_real_expr ctx obj) with Arithmetic.RealExpr(Arithmetic.Expr(e)) -> e) + | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.Expr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.Expr(e)) -> e) | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) @@ -1406,16 +1407,20 @@ sig type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort - val create : context -> Z3native.ptr -> bool_expr + val create_expr : context -> Z3native.ptr -> bool_expr + val create_sort : context -> Z3native.ptr -> bool_sort val aton : bool_expr array -> Z3native.ptr array end = struct type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort - let create ( ctx : context ) ( no : Z3native.ptr ) = + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in BoolExpr(Expr.Expr(a)) + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(Sort.create ctx no) + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) @@ -1444,13 +1449,13 @@ end = struct The true Term. *) let mk_true ( ctx : context ) = - create ctx (Z3native.mk_true (context_gno ctx)) + create_expr ctx (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - create ctx (Z3native.mk_false (context_gno ctx)) + create_expr ctx (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1462,19 +1467,19 @@ end = struct Creates the equality = . *) let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = - create ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + create_expr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) (** Creates a distinct term. *) let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = - create ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + create_expr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - create ctx (Z3native.mk_not (context_gno ctx) (gno a)) + create_expr ctx (Z3native.mk_not (context_gno ctx) (gno a)) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1483,36 +1488,36 @@ end = struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + create_expr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - create ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + create_expr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - create ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) + create_expr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) end (** Quantifier expressions *) @@ -1676,7 +1681,7 @@ end = struct The body of the quantifier. *) let get_body ( x : quantifier ) = - Booleans.create (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + Booleans.create_expr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @@ -2643,416 +2648,478 @@ end and Arithmetic : sig type arith_sort = ArithSort of Sort.sort - type int_sort = IntSort of Sort.sort - type real_sort = RealSort of Sort.sort - type arith_expr = Expr of Expr.expr - type int_expr = IntExpr of arith_expr - type real_expr = RealExpr of arith_expr - - type int_num = IntNum of int_expr - type rat_num = RatNum of real_expr - type algebraic_num = AlgebraicNum of arith_expr - - val create_arith_expr : context -> Z3native.ptr -> arith_expr - val create_int_expr : context -> Z3native.ptr -> int_expr - val create_real_expr : context -> Z3native.ptr -> real_expr - val create_int_num : context -> Z3native.ptr -> int_num - val create_rat_num : context -> Z3native.ptr -> rat_num - val create_algebraic_num : context -> Z3native.ptr -> algebraic_num + val create_expr : context -> Z3native.ptr -> arith_expr + val aton : arith_expr array -> Z3native.ptr array + + module Integers : sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val create_sort : context -> Z3native.ptr -> int_sort + val create_expr : context -> Z3native.ptr -> int_expr + val create_num : context -> Z3native.ptr -> int_num + end + + module Reals : sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val create_sort : context -> Z3native.ptr -> real_sort + val create_expr : context -> Z3native.ptr -> real_expr + val create_num : context -> Z3native.ptr -> rat_num + end + + module AlgebraicNumbers : sig + type algebraic_num = AlgebraicNum of arith_expr + + val create_num : context -> Z3native.ptr -> algebraic_num + end + end = struct type arith_sort = ArithSort of Sort.sort - type int_sort = IntSort of Sort.sort - type real_sort = RealSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - type int_expr = IntExpr of arith_expr - type real_expr = RealExpr of arith_expr - - type int_num = IntNum of int_expr - type rat_num = RatNum of real_expr - type algebraic_num = AlgebraicNum of arith_expr let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) - let create_int_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(create_arith_expr ctx no) + let create_arith_sort ( ctx : context ) ( no : Z3native.ptr ) = + ArithSort(Sort.create ctx no) - let create_real_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(create_arith_expr ctx no) + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) - let create_int_num ( ctx : context ) ( no : Z3native.ptr ) = - IntNum(create_int_expr ctx no) - let create_rat_num ( ctx : context ) ( no : Z3native.ptr ) = - RatNum(create_real_expr ctx no) - - (** - Create a new integer sort. - *) - let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#create_obj (Z3native.mk_int_sort (context_gno ctx)) + module rec Integers : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr - (** - Create a real sort. - *) - let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#create_obj (Z3native.mk_real_sort (context_gno ctx)) + val create_sort : context -> Z3native.ptr -> int_sort + val create_expr : context -> Z3native.ptr -> int_expr + val create_num : context -> Z3native.ptr -> int_num + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + IntSort(create_arith_sort ctx no) + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + IntExpr(create_arith_expr ctx no) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + IntNum(create_expr ctx no) + + let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) + let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) + let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) + let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) + let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) + let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) + let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) + let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) + let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + + (** Create a new integer sort. *) + let mk_sort ( ctx : context ) = + create_sort ctx (Z3native.mk_int_sort (context_gno ctx)) + + (** Retrieve the int value. *) + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + (** + Creates an integer constant. + *) + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + + (** + Creates an integer constant. + *) + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx (Symbol.mk_string ctx name) + + (** + Create an expression representing t1 mod t2. + The arguments must have int type. + *) + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + create_expr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + + (** + Create an expression representing t1 rem t2. + The arguments must have int type. + *) + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + create_expr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + + (** + Create an integer numeral. + @param v A string representing the Term value in decimal notation. + *) + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Create an integer numeral. + @param v value of the numeral. + @return A Term with value and sort Integer + *) + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + *) + let mk_int2real ( ctx : context ) ( t : int_expr ) = + Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + end + + and Reals : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val create_sort : context -> Z3native.ptr -> real_sort + val create_expr : context -> Z3native.ptr -> real_expr + val create_num : context -> Z3native.ptr -> rat_num + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + RealSort(create_arith_sort ctx no) + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + RealExpr(create_arith_expr ctx no) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + RatNum(create_expr ctx no) + + let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) + let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) + let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) + let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) + let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) + let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) + let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) + let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) + let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) + + (** Create a real sort. *) + let mk_sort ( ctx : context ) = + create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + Integers.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + Integers.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + (** Creates a real constant. *) + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + + (** Creates a real constant. *) + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx (Symbol.mk_string ctx name) + + (** + Create a real from a fraction. + + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + *) + let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + create_num ctx (Z3native.mk_real (context_gno ctx) num den) + + (** + Create a real numeral. + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + *) + let mk_numeral_s ( ctx : context ) ( v : string ) = + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Create a real numeral. + + @param v value of the numeral. + @return A Term with value and sort Real + *) + let mk_numeral_i ( ctx : context ) ( v : int ) = + create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + (** Creates an expression that checks whether a real number is an integer. *) + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + Booleans.create_expr ctx (Z3native.mk_is_int (context_gno ctx) (egno t)) + + (** + Coerce a real to an integer. + + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + *) + let mk_real2int ( ctx : context ) ( t : real_expr ) = + Integers.create_expr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)) + end + + and AlgebraicNumbers : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val create_num : context -> Z3native.ptr -> algebraic_num + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + AlgebraicNum(create_arith_expr ctx no) + + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) + let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) + let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + Reals.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + Reals.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + end + + let aton (a : arith_expr array) = + let f (e : arith_expr) = (egno e) in + Array.map f a (** Indicates whether the term is of integer sort. *) - let is_int ( x : expr ) = - (Z3native.is_numeral_ast x#gnc x#gno) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + let is_int ( x : Expr.expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) (** Indicates whether the term is an arithmetic numeral. *) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) (** Indicates whether the term is a less-than-or-equal *) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) (** Indicates whether the term is a greater-than-or-equal *) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) (** Indicates whether the term is a less-than *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) (** Indicates whether the term is a greater-than *) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) (** Indicates whether the term is addition (binary) *) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) (** Indicates whether the term is subtraction (binary) *) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) (** Indicates whether the term is a unary minus *) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) (** Indicates whether the term is multiplication (binary) *) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) (** Indicates whether the term is division (binary) *) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) (** Indicates whether the term is integer division (binary) *) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) (** Indicates whether the term is remainder (binary) *) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) (** Indicates whether the term is modulus (binary) *) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) (** Indicates whether the term is a coercion of integer to real (unary) *) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) (** Indicates whether the term is a coercion of real to integer (unary) *) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) (** Indicates whether the term is of sort real. *) - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + let is_real ( x : Expr.expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) (** Indicates whether the term is an integer numeral. *) - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + let is_int_numeral ( x : Expr.expr ) = (Expr.is_numeral x) && (is_int x) (** Indicates whether the term is a real numeral. *) - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + let is_rat_num ( x : Expr.expr ) = (Expr.is_numeral x) && (is_real x) (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number x#gnc x#gno - - (** Retrieve the int value. *) - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if r then v - else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) - let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno - - (** The numerator of a rational numeral. *) - let get_numerator ( x : rat_num ) = - (new int_num x#gc)#create_obj (Z3native.get_numerator x#gnc x#gno) - - (** The denominator of a rational numeral. *) - let get_denominator ( x : rat_num ) = - (new int_num x#gc)#create_obj (Z3native.get_denominator x#gnc x#gno) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : rat_num ) (precision : int) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** Returns a string representation of the numeral. *) - let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno - - (** - Creates an integer constant. - *) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = - ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) - - (** - Creates an integer constant. - *) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) - - (** - Creates a real constant. - *) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = - ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) - - (** - Creates a real constant. - *) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let is_algebraic_number ( x : Expr.expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) (** Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - ArithExpr(create ctx (Z3native.mk_unary_minus (context_gno ctx) - (gno (match t with ArithExpr(b) -> b)))) + Arithmetic.create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t)) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - ArithExpr(create ctx (Z3native.mk_div (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an expression representing t1 mod t2. - The arguments must have int type. - *) - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - IntExpr(create ctx (Z3native.mk_mod (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an expression representing t1 rem t2. - The arguments must have int type. - *) - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - IntExpr(create ctx (Z3native.mk_rem (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Arithmetic.create_expr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 ^ t2. *) - let mk_power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - ArithExpr(create_expr ctx (Z3native.mk_power (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Arithmetic.create_expr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 < t2 *) - let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_lt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 <= t2 *) - let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_le (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 > t2 *) - let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_gt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 >= t2 *) - let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_ge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - *) - let mk_int2real ( ctx : context ) ( t : int_expr ) = - RealExpr(create (Z3native.mk_int2real (context_gno ctx) - (gno (match t with BoolExpr(b) -> b)))) - - (** - Coerce a real to an integer. - - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - *) - let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#create_obj (Z3native.mk_real2int (context_gno ctx) t#gno) - - (** - Creates an expression that checks whether a real number is an integer. - *) - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - BoolExpr(create ctx (Z3native.mk_is_int (context_gno ctx) - (gno (match t with BoolExpr(b) -> b)))) - (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) - - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** - Create a real from a fraction. - - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - *) - let mk_real_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = - if (den == 0) then - raise (Z3native.Exception "Denominator is zero") - else - - (new rat_num ctx)#create_obj (Z3native.mk_real (context_gno ctx) num den) - - (** - Create a real numeral. - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - *) - let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) - - (** - Create a real numeral. - - @param v value of the numeral. - @return A Term with value and sort Real - *) - let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) - - (** - Create an integer numeral. - @param v A string representing the Term value in decimal notation. - *) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) - - (** - Create an integer numeral. - @param v value of the numeral. - @return A Term with value and sort Integer - *) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) - - (** Returns a string representation of the numeral. *) - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno + let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) end From 276c5a5cdcab12fe3df8eb8b2aacceeed117d74f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 5 Feb 2013 00:19:06 +0000 Subject: [PATCH 299/646] ML API: No more objects; type hierarchy exposed; clean separation into modules. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 691 ++++++++++++++++++++++++----------------------- 1 file changed, 357 insertions(+), 334 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 58c319d4d..4cf41f420 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -334,6 +334,13 @@ sig val create : context -> Z3native.ptr -> ast val aton : ast array -> Z3native.ptr array + module ASTVectors : sig + type ast_vector + val create : context -> Z3native.ptr -> ast_vector + val get_size : ast_vector -> int + val get : ast_vector -> int -> ast + end + val is_expr : ast -> bool val is_var : ast -> bool end = struct @@ -354,7 +361,7 @@ end = struct (** Vectors of ASTs *) - module ASTVector = + module ASTVectors = struct type ast_vector = z3_native_object @@ -401,7 +408,7 @@ end = struct (** Translates all ASTs in the vector to . @param to_ctx A context - @return A new ASTVector + @return A new ASTVectors *) let translate ( x : ast_vector ) ( to_ctx : context ) = create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) @@ -466,7 +473,7 @@ end = struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVectors.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -613,16 +620,15 @@ end and Sort : sig type sort = Sort of AST.ast - type bitvec_sort = BitvecSort of sort type uninterpreted_sort = UninterpretedSort of sort val create : context -> Z3native.ptr -> sort - val gno : sort -> Z3native.ptr + val gc : sort -> context val gnc : sort -> Z3native.ptr + val gno : sort -> Z3native.ptr val aton : sort array -> Z3native.ptr array end = struct type sort = Sort of AST.ast - type bitvec_sort = BitvecSort of sort type uninterpreted_sort = UninterpretedSort of sort let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) @@ -713,11 +719,14 @@ sig type func_decl = FuncDecl of AST.ast val create : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context val gno : func_decl -> Z3native.ptr val gnc : func_decl -> Z3native.ptr + val aton : func_decl array -> Z3native.ptr array val get_domain_size : func_decl -> int val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_arity : func_decl -> int end = struct open Sort @@ -1098,6 +1107,7 @@ sig val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val get_func_decl : expr -> FuncDecl.func_decl val is_numeral : expr -> bool + val to_string : expr -> string end = struct type expr = Expr of AST.ast @@ -1108,20 +1118,20 @@ end = struct let s = Z3native.get_sort (context_gno ctx) obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.Expr(e)) -> e) + (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.ArithExpr(e)) -> e) else if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with - | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.Expr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.Expr(e))) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e))) -> e) | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) | _ -> raise (Z3native.Exception "Unsupported numeral object") else match sk with | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.Expr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.Expr(e)) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e)) -> e) | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) @@ -1409,6 +1419,9 @@ sig val create_expr : context -> Z3native.ptr -> bool_expr val create_sort : context -> Z3native.ptr -> bool_sort + val gc : bool_expr -> context + val gnc : bool_expr -> Z3native.ptr + val gno : bool_expr -> Z3native.ptr val aton : bool_expr array -> Z3native.ptr array end = struct type bool_expr = BoolExpr of Expr.expr @@ -2648,9 +2661,10 @@ end and Arithmetic : sig type arith_sort = ArithSort of Sort.sort - type arith_expr = Expr of Expr.expr + type arith_expr = ArithExpr of Expr.expr val create_expr : context -> Z3native.ptr -> arith_expr + val create_sort : context -> Z3native.ptr -> arith_sort val aton : arith_expr array -> Z3native.ptr array module Integers : sig @@ -2679,14 +2693,53 @@ sig val create_num : context -> Z3native.ptr -> algebraic_num end + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr array -> Arithmetic.arith_expr + val mk_mul : context -> arith_expr array -> Arithmetic.arith_expr + val mk_sub : context -> arith_expr array -> Arithmetic.arith_expr + val mk_unary_minus : + context -> arith_expr -> Arithmetic.arith_expr + val mk_div : + context -> arith_expr -> arith_expr -> Arithmetic.arith_expr + val mk_power : + context -> arith_expr -> arith_expr -> Arithmetic.arith_expr + val mk_lt : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_le : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_gt : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_ge : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + end = struct type arith_sort = ArithSort of Sort.sort type arith_expr = ArithExpr of Expr.expr - let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) - let create_arith_sort ( ctx : context ) ( no : Z3native.ptr ) = + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = ArithSort(Sort.create ctx no) let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) @@ -2712,10 +2765,10 @@ end = struct type int_num = IntNum of int_expr let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - IntSort(create_arith_sort ctx no) + IntSort(Arithmetic.create_sort ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(create_arith_expr ctx no) + IntExpr(Arithmetic.create_expr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = IntNum(create_expr ctx no) @@ -2796,6 +2849,19 @@ end = struct *) let mk_int2real ( ctx : context ) ( t : int_expr ) = Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + + (** + Create an bit bit-vector from the integer argument . + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + *) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + BitVectors.create_expr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t)) end and Reals : @@ -2813,10 +2879,10 @@ end = struct type rat_num = RatNum of real_expr let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - RealSort(create_arith_sort ctx no) + RealSort(Arithmetic.create_sort ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(create_arith_expr ctx no) + RealExpr(Arithmetic.create_expr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = RatNum(create_expr ctx no) @@ -2914,7 +2980,7 @@ end = struct type algebraic_num = AlgebraicNum of arith_expr let create_num ( ctx : context ) ( no : Z3native.ptr ) = - AlgebraicNum(create_arith_expr ctx no) + AlgebraicNum(Arithmetic.create_expr ctx no) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) @@ -3126,316 +3192,330 @@ end (** Functions to manipulate bit-vector expressions *) and BitVectors : sig + type bitvec_sort = BitVecSort of Sort.sort type bitvec_expr = BitVecExpr of Expr.expr type bitvec_num = BitVecNum of bitvec_expr + val create_sort : context -> Z3native.ptr -> bitvec_sort val create_expr : context -> Z3native.ptr -> bitvec_expr val create_num : context -> Z3native.ptr -> bitvec_num end = struct - type bitvec_expr = Expr of Expr.expr - type bitvec_num = BitVecExpr of bitvec_expr + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + BitVecSort(Sort.create ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in - BitVecExpr(e) + BitVecExpr(Expr.create ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - let e = (create_expr ctx no) in - BitVecNum(e) + BitVecNum(create_expr ctx no) + + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) + let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) + let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) + let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) + let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#create_obj (Z3native.mk_bv_sort (context_gno ctx) size) + create_sort ctx (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. *) - let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + let is_bv ( x : Expr.expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_ult ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_slt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_and ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_or ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_not ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) (** The size of a bit-vector sort. *) - let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno + let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a bit-vector constant. *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) + BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) (** Creates a bit-vector constant. @@ -3448,91 +3528,91 @@ end = struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3544,7 +3624,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3559,7 +3639,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3569,7 +3649,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3581,7 +3661,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3590,7 +3670,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3598,9 +3678,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvult (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed less-than @@ -3608,9 +3686,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvslt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than or equal to. @@ -3618,9 +3694,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvule (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed less-than or equal to. @@ -3628,9 +3702,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsle (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2)) (** Unsigned greater than or equal to. @@ -3638,19 +3710,15 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvuge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed greater than or equal to. The arguments must have the same bit-vector sort. *) - let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Booleans.create_expr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2)) (** Unsigned greater-than. @@ -3658,9 +3726,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvugt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed greater-than. @@ -3668,9 +3734,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsgt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector concatenation. @@ -3681,9 +3745,7 @@ end = struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVectors.BitVecExpr(create ctx (Z3native.mk_concat (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3694,7 +3756,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) + create_expr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3704,7 +3766,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_sign_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3715,7 +3777,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_zero_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3723,7 +3785,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_repeat (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3738,9 +3800,8 @@ end = struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvshl (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + (** Logical shift right @@ -3754,9 +3815,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvlshr (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3772,9 +3831,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvashr (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3783,7 +3840,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_rotate_left (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3792,7 +3849,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_rotate_right (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3801,9 +3858,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_ext_rotate_left (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3813,22 +3868,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_ext_rotate_right (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an bit bit-vector from the integer argument . - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - *) - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVecExpr(create ctx (Z3native.mk_int2bv (context_gno ctx) n (gno (match t with IntExpr(b) -> b)))) + create_expr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3845,8 +3885,8 @@ end = struct The argument must be of bit-vector sort. *) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#create_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = + Arithmetic.Integers.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3854,10 +3894,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3865,19 +3902,15 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - + Booleans.create_expr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2)) + (** Create a predicate that checks that the bit-wise subtraction does not overflow. The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2)) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3885,10 +3918,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3896,17 +3926,15 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2)) (** Create a predicate that checks that the bit-wise negation does not overflow. The arguments must be of bit-vector sort. *) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - BoolExpr(create ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (gno (match t with BitVecExpr(b) -> b)))) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = + Booleans.create_expr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t)) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3914,10 +3942,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3925,9 +3950,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2)) (** Create a bit-vector numeral. @@ -3936,7 +3959,7 @@ end = struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) end (** Functions to manipulate proof expressions *) @@ -3946,17 +3969,17 @@ end = struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -3967,7 +3990,7 @@ end = struct [mp T1 T2]: q The second antecedents may also be a proof for (iff p q). *) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. @@ -3976,7 +3999,7 @@ end = struct equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. *) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -3986,7 +4009,7 @@ end = struct [symmetry T1]: (R s t) T1 is the antecedent of this proof object. *) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -3997,7 +4020,7 @@ end = struct T2: (R s u) [trans T1 T2]: (R t u) *) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -4017,7 +4040,7 @@ end = struct if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. *) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -4030,7 +4053,7 @@ end = struct Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. *) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -4039,7 +4062,7 @@ end = struct T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -4056,7 +4079,7 @@ end = struct Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. *) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -4065,7 +4088,7 @@ end = struct T1: (and l_1 ... l_n) [and-elim T1]: l_i *) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -4074,7 +4097,7 @@ end = struct T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) *) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -4088,11 +4111,11 @@ end = struct Remark: if f is bool, then = is iff. Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) + (= (+ ( x : Expr.expr ) 0) x) + (= (+ ( x : Expr.expr ) 1 2) (+ 3 x)) + (iff (or ( x : Expr.expr ) false) x) *) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -4107,14 +4130,14 @@ end = struct - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -4123,7 +4146,7 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents *) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -4136,7 +4159,7 @@ end = struct This proof object has no antecedents *) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_push_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -4148,34 +4171,34 @@ end = struct This proof object has no antecedents. *) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_elim_unused_vars ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. + (iff (forall (x) (or (not (= ( x : Expr.expr ) t)) P[x])) P[t]) + if ( x : Expr.expr ) does not occur in t. This proof object has no antecedents. Several variables can be eliminated simultaneously. *) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_der ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) *) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. Mark a hypothesis in a natural deduction style proof. *) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -4187,7 +4210,7 @@ end = struct It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. *) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -4198,7 +4221,7 @@ end = struct T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true @@ -4206,7 +4229,7 @@ end = struct T1: p [iff-true T1]: (iff p true) *) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false @@ -4214,7 +4237,7 @@ end = struct T1: (not p) [iff-false T1]: (iff p false) *) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -4226,7 +4249,7 @@ end = struct This proof object has no antecedents. Remark: if f is bool, then = is iff. *) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -4261,7 +4284,7 @@ end = struct unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -4283,7 +4306,7 @@ end = struct Otherwise: [def-intro]: (= n e) *) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -4292,7 +4315,7 @@ end = struct F is 'equivalent' to n, given that T1 is a proof that n is a name for F. *) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq @@ -4300,7 +4323,7 @@ end = struct T1: (iff p q) [iff~ T1]: (~ p q) *) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -4327,7 +4350,7 @@ end = struct NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. *) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -4351,7 +4374,7 @@ end = struct [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) *) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -4362,7 +4385,7 @@ end = struct This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -4371,19 +4394,19 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step Proof for: - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + [sk]: (~ (not (forall ( x : Expr.expr ) (p ( x : Expr.expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : Expr.expr ) (p ( x : Expr.expr ) y)) (p (sk y) y)) This proof object has no antecedents. *) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -4393,7 +4416,7 @@ end = struct T2: (~ p q) [mp~ T1 T2]: q *) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -4411,7 +4434,7 @@ end = struct (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_theory_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end @@ -4462,8 +4485,8 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : bool_expr array ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) e#gno in + let assert_ ( x : goal ) ( constraints : Booleans.bool_expr array ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) in ignore (Array.map f constraints) ; () @@ -4484,7 +4507,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr (z3obj_gc x))#create_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Booleans.create_expr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4599,7 +4622,7 @@ struct Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - create_expr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + Expr.create (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. @@ -4611,7 +4634,7 @@ struct *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (create_expr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (Expr.create (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4639,7 +4662,7 @@ struct (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = create_expr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + let get_else ( x : func_interp ) = Expr.create (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation @@ -4666,31 +4689,31 @@ struct (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = + let get_const_interp ( x : model ) ( f : FuncDecl.func_decl ) = if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") else - let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in if (Z3native.is_null np) then None else - Some (create_expr (z3obj_gc x) np) + Some (Expr.create (z3obj_gc x) np) (** Retrieves the interpretation (the assignment) of in the model. A Constant An expression if the constant has an interpretation in the model, null otherwise. *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + let get_const_interp_e ( x : model ) ( a : Expr.expr ) = get_const_interp x (Expr.get_func_decl a) (** Retrieves the interpretation (the assignment) of a non-constant in the model. A function declaration of non-zero arity A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range f#gnc f#gno))) in + let rec get_func_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in if (Z3native.is_null n) then None else @@ -4700,10 +4723,10 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x ((new func_decl f#gc)#create_obj fd) + get_func_interp x (FuncDecl.create (z3obj_gc x) fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else - let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) @@ -4712,7 +4735,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4722,15 +4745,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4751,15 +4774,15 @@ struct The evaluation of in the model. *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) t#gno completion) in + let eval ( x : model ) ( t : Expr.expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else - create_expr (z3obj_gc x) v + Expr.create (z3obj_gc x) v (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + let evaluate ( x : model ) ( t : Expr.expr ) ( completion : bool ) = eval x t completion (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -4775,7 +4798,7 @@ struct *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in - let f i = (create_sort (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (Sort.create (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f @@ -4784,10 +4807,10 @@ struct An uninterpreted sort An array of expressions, where each is an element of the universe of *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in + let sort_universe ( x : model ) ( s : Sort.sort ) = + let n_univ = AST.ASTVectors.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVectors.get_size n_univ) in + let f i = (AST.ASTVectors.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -5323,8 +5346,8 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : bool_expr array ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in + let assert_ ( x : solver ) ( constraints : Booleans.bool_expr array ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in ignore (Array.map f constraints) (** @@ -5340,11 +5363,11 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : Booleans.bool_expr array ) ( ps : Booleans.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) e#gno (Array.get ps i)#gno) in + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) (Booleans.gno (Array.get ps i))) in ignore (Array.iteri f cs) (** @@ -5359,24 +5382,24 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) c#gno p#gno + let assert_and_track ( x : solver ) ( c : Booleans.bool_expr ) ( p : Booleans.bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno c) (Booleans.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVector.get_size a) + let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVectors.get_size a) (** The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get a i)#gno) in + let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVectors.get_size a) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get a i)) in Array.init n f (** @@ -5386,12 +5409,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array) = + let check ( x : solver ) ( assumptions : Booleans.bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (AST.aton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Booleans.aton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5422,7 +5445,7 @@ struct if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** The unsat core of the last Check. @@ -5432,9 +5455,9 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size cn) in - let f i = (AST.ASTVector.get cn i) in + let cn = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVectors.get_size cn) in + let f i = (AST.ASTVectors.get cn i) in Array.init n f (** @@ -5527,30 +5550,30 @@ struct (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in + let assert_ ( x : fixedpoint ) ( constraints : Booleans.bool_expr array ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in ignore (Array.map f constraints) ; () (** Register predicate as recursive relation. *) - let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) f#gno + let register_relation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) = + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno y) (** Add table fact to the fixedpoint solver. *) - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) pred#gno (Array.length args) args + let add_fact ( x : fixedpoint ) ( pred : FuncDecl.func_decl ) ( args : int array ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args (** Query the fixedpoint solver. @@ -5558,8 +5581,8 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) query#gno)) with + let query ( x : fixedpoint ) ( query : Booleans.bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Booleans.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5570,8 +5593,8 @@ struct The query is satisfiable if there is an instance of some relation that is non-empty. The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - let query_r ( x : fixedpoint ) ( relations : func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (func_declaton relations))) with + let query_r ( x : fixedpoint ) ( relations : FuncDecl.func_decl array ) = + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (FuncDecl.aton relations))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5595,8 +5618,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5607,7 +5630,7 @@ struct if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. @@ -5618,25 +5641,25 @@ struct (** Retrieve the number of levels explored for a given predicate. *) - let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) predicate#gno + let get_num_levels ( x : fixedpoint ) ( predicate : FuncDecl.func_decl ) = + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) (** Retrieve the cover of a predicate. *) - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level predicate#gno) in + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level predicate#gno property#gno + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) ( property : Expr.expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) (** Retrieve internal string representation of fixedpoint object. @@ -5646,31 +5669,31 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (Symbol.aton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) ( kinds : Symbol.symbol array ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Symbol.aton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (AST.aton queries) + let to_string_q ( x : fixedpoint ) ( queries : Booleans.bool_expr array ) = + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Booleans.aton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in + let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVectors.get_size v) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in + let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVectors.get_size v) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in Array.init n f (** @@ -5754,10 +5777,10 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Booleans.bool_expr array ) ( formula : Booleans.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (AST.aton assumptions) - formula#gno + (Array.length assumptions) (Booleans.aton assumptions) + (Booleans.gno formula) (** Parse the given string using the SMT-LIB parser. @@ -5768,7 +5791,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5779,16 +5802,16 @@ struct Z3native.parse_smtlib_string (context_gno ctx) str cs (Symbol.aton sort_names) - (AST.aton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5799,10 +5822,10 @@ struct Z3native.parse_smtlib_file (context_gno ctx) file_name cs (Symbol.aton sort_names) - (AST.aton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. @@ -5814,7 +5837,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) :> bool_expr) in + let f i = Booleans.create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i) in Array.init n f @@ -5828,7 +5851,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) :> bool_expr ) in + let f i = Booleans.create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i) in Array.init n f (** @@ -5841,7 +5864,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#create_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = FuncDecl.create ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5854,7 +5877,7 @@ struct *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (create_sort ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + let f i = (Sort.create ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5863,7 +5886,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5877,13 +5900,13 @@ struct (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5897,7 +5920,7 @@ struct (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) end From 34a72942bfbf752e7eb02e81672539fd31252620 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 5 Feb 2013 00:51:20 +0000 Subject: [PATCH 300/646] ML API: documentation fixes. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 246 +++++++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 105 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4cf41f420..aeb9c0d03 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -331,8 +331,10 @@ module rec AST : sig type ast = z3_native_object +(**/**) val create : context -> Z3native.ptr -> ast val aton : ast array -> Z3native.ptr array +(**/**) module ASTVectors : sig type ast_vector @@ -346,6 +348,7 @@ sig end = struct type ast = z3_native_object + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -358,7 +361,7 @@ end = struct let aton (a : ast array) = let f (e : ast) = (z3obj_gno e) in Array.map f a - + (**/**) (** Vectors of ASTs *) module ASTVectors = @@ -615,7 +618,6 @@ end = struct (**/**) end - (** The Sort module implements type information for ASTs *) and Sort : sig @@ -631,6 +633,7 @@ end = struct type sort = Sort of AST.ast type uninterpreted_sort = UninterpretedSort of sort + (**/**) let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -657,6 +660,7 @@ end = struct | FINITE_DOMAIN_SORT | RELATION_SORT -> Sort(q) | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + (**/**) (** @@ -728,10 +732,9 @@ sig val get_decl_kind : func_decl -> Z3enums.decl_kind val get_arity : func_decl -> int end = struct - open Sort - type func_decl = FuncDecl of AST.ast + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res = { m_ctx = ctx ; m_n_obj = null ; @@ -741,7 +744,7 @@ end = struct (z3obj_create res) ; FuncDecl(res) - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -750,7 +753,7 @@ end = struct (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -766,7 +769,8 @@ end = struct let aton (a : func_decl array) = let f (e : func_decl) = (gno e) in Array.map f a - + (**/**) + (** Parameters of Func_Decls *) module Parameter = struct @@ -833,18 +837,16 @@ end = struct | _ -> raise (Z3native.Exception "parameter is not a rational string") end - open Parameter - (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = create_ndr ctx name domain range (** Creates a new function declaration. *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** @@ -852,19 +854,19 @@ end = struct *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = create_pdr ctx prefix domain range (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = create_ndr ctx name [||] range (** Creates a new constant function declaration. *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range (** @@ -872,7 +874,7 @@ end = struct *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = create_pdr ctx prefix [||] range @@ -945,13 +947,13 @@ end = struct let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n @@ -977,6 +979,7 @@ sig type param_descrs = z3_native_object val create : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit end end = struct type params = z3_native_object @@ -998,6 +1001,7 @@ end = struct type param_descrs = z3_native_object val create : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit end = struct type param_descrs = z3_native_object @@ -1025,7 +1029,7 @@ end = struct let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - + (** The size of the ParamDescrs. *) let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) @@ -1092,7 +1096,7 @@ end = struct let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end -(** General expressions (terms), including Boolean logic *) +(** General expressions (terms) *) and Expr : sig type expr = Expr of AST.ast @@ -1111,6 +1115,7 @@ sig end = struct type expr = Expr of AST.ast + (**/**) let create ( ctx : context ) ( obj : Z3native.ptr ) = if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) @@ -1148,7 +1153,12 @@ end = struct let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) - + + let aton (a : expr array) = + let f (e : expr) = (gno e) in + Array.map f a + (**/**) + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier @@ -1405,10 +1415,6 @@ end = struct *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) - - let aton (a : expr array) = - let f (e : expr) = (gno e) in - Array.map f a end (** Boolean expressions *) @@ -1427,6 +1433,7 @@ end = struct type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in BoolExpr(Expr.Expr(a)) @@ -1441,6 +1448,7 @@ end = struct let aton ( a : bool_expr array ) = let f (e : bool_expr) = (gno e) in Array.map f a + (**/**) let mk_sort ( ctx : context ) = BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) @@ -1542,6 +1550,7 @@ sig end = struct type quantifier = Quantifier of Expr.expr + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in Quantifier(Expr.Expr(a)) @@ -1549,7 +1558,61 @@ end = struct let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - + (**/**) + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Patterns : + sig + type pattern = Pattern of AST.ast + + val create : context -> Z3native.ptr -> pattern + val aton : pattern array -> Z3native.ptr array + end = struct + type pattern = Pattern of AST.ast + + (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + Pattern(res) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + + let aton (a : pattern array) = + let f (e : pattern) = (gno e) in + Array.map f a + (**/**) + + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms (gnc x) (gno x) + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + end (** The de-Burijn index of a bound variable. @@ -1575,58 +1638,6 @@ end = struct else Z3native.get_index_value (Expr.gnc x) (Expr.gno x) - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) - module Patterns : - sig - type pattern = Pattern of AST.ast - - val create : context -> Z3native.ptr -> pattern - val aton : pattern array -> Z3native.ptr array - end = struct - type pattern = Pattern of AST.ast - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - Pattern(res) - - let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) - let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) - let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - - (** - The number of terms in the pattern. - *) - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - - (** - The terms in the pattern. - *) - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - Array.init n f - - (** - A string representation of the pattern. - *) - let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) - - let aton (a : pattern array) = - let f (e : pattern) = (gno e) in - Array.map f a - end - (** Indicates whether the quantifier is universal. *) @@ -1849,6 +1860,7 @@ end = struct type array_expr = ArrayExpr of Expr.expr type array_sort = ArraySort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let e = (Expr.create ctx no) in ArrayExpr(e) @@ -1868,7 +1880,7 @@ end = struct let aton (a : array_expr array) = let f (e : array_expr) = (egno e) in Array.map f a - + (**/**) (** Create a new array sort. @@ -2120,6 +2132,7 @@ sig end = struct type finite_domain_sort = FiniteDomainSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in FiniteDomainSort(s) @@ -2127,7 +2140,8 @@ end = struct let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) + (** Create a new finite domain sort. *) @@ -2168,6 +2182,7 @@ sig end = struct type relation_sort = RelationSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in RelationSort(s) @@ -2175,7 +2190,8 @@ end = struct let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) + (** Indicates whether the term is of a relation sort. *) @@ -2306,6 +2322,7 @@ end = struct type datatype_expr = DatatypeExpr of Expr.expr type datatype_sort = DatatypeSort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let e = (Expr.create ctx no) in DatatypeExpr(e) @@ -2317,19 +2334,24 @@ end = struct let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) (** Constructors *) - module Constructor = - struct + module Constructor : sig + type constructor + val create : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> constructor + val aton : constructor array -> Z3native.ptr array + end = struct type constructor_extra = { m_n : int; mutable m_tester_decl : FuncDecl.func_decl option; mutable m_constructor_decl : FuncDecl.func_decl option ; mutable m_accessor_decls : FuncDecl.func_decl array option} + type constructor = Constructor of (z3_native_object * constructor_extra) - let create_ssssi ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + (**/**) + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2356,6 +2378,10 @@ end = struct let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; Constructor(no, ex) + + let aton ( a : constructor array ) = + let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in + Array.map f a let init_extra ( x : constructor ) = match x with Constructor(no, ex) -> @@ -2367,7 +2393,8 @@ end = struct ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; () | _ -> () - + (**/**) + let get_n ( x : constructor ) = match x with Constructor(no, ex) -> ex.m_n @@ -2389,12 +2416,7 @@ end = struct match ex.m_accessor_decls with | Some(s) -> s | None -> init_extra x ; accessor_decls x - - let aton ( a : constructor array ) = - let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in - Array.map f a - - + (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2413,6 +2435,7 @@ end = struct struct type constructor_list = z3_native_object + (**/**) let create ( ctx : context )( c : Constructor.constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; @@ -2427,6 +2450,7 @@ end = struct let aton (a : constructor_list array) = let f (e : constructor_list) = (z3obj_gno e) in Array.map f a + (**/**) end (* DATATYPES *) @@ -2441,7 +2465,7 @@ end = struct referring to one of the recursive datatypes that is declared. *) let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = - Constructor.create_ssssi ctx name recognizer field_names sorts sort_refs + Constructor.create ctx name recognizer field_names sorts sort_refs (** @@ -2530,6 +2554,7 @@ end = struct mutable _testerdecls : FuncDecl.func_decl array } type enum_sort = EnumSort of (Sort.sort * enum_sort_data) + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (Sort.create ctx no) in let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; @@ -2539,7 +2564,7 @@ end = struct let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) - + (**/**) (** Create a new enumeration sort. @@ -2576,6 +2601,7 @@ end = struct _taildecl : FuncDecl.func_decl } type list_sort = ListSort of (Sort.sort * list_sort_data) + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (Sort.create ctx no) in let e = {_nildecl = FuncDecl.create ctx nildecl; @@ -2589,7 +2615,7 @@ end = struct let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) - + (**/**) (** Create a new list sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = @@ -2629,6 +2655,7 @@ sig end = struct type tuple_sort = TupleSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in TupleSort(s) @@ -2636,6 +2663,7 @@ end = struct let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) + (**/**) (** Create a new tuple sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = @@ -2736,6 +2764,7 @@ end = struct type arith_sort = ArithSort of Sort.sort type arith_expr = ArithExpr of Expr.expr + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) @@ -2749,6 +2778,10 @@ end = struct let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + let aton (a : arith_expr array) = + let f (e : arith_expr) = (egno e) in + Array.map f a + (**/**) module rec Integers : sig @@ -2764,6 +2797,7 @@ end = struct type int_expr = IntExpr of arith_expr type int_num = IntNum of int_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = IntSort(Arithmetic.create_sort ctx no) @@ -2782,6 +2816,7 @@ end = struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + (**/**) (** Create a new integer sort. *) let mk_sort ( ctx : context ) = @@ -2878,6 +2913,7 @@ end = struct type real_expr = RealExpr of arith_expr type rat_num = RatNum of real_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = RealSort(Arithmetic.create_sort ctx no) @@ -2896,7 +2932,8 @@ end = struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - + (**/**) + (** Create a real sort. *) let mk_sort ( ctx : context ) = create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) @@ -2979,12 +3016,14 @@ end = struct end = struct type algebraic_num = AlgebraicNum of arith_expr + (**/**) let create_num ( ctx : context ) ( no : Z3native.ptr ) = AlgebraicNum(Arithmetic.create_expr ctx no) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + (**/**) (** Return a upper bound for a given real algebraic number. @@ -3015,10 +3054,6 @@ end = struct let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) end - let aton (a : arith_expr array) = - let f (e : arith_expr) = (egno e) in - Array.map f a - (** Indicates whether the term is of integer sort. *) @@ -3188,7 +3223,6 @@ end = struct Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) end - (** Functions to manipulate bit-vector expressions *) and BitVectors : sig @@ -3204,6 +3238,7 @@ end = struct type bitvec_expr = BitVecExpr of Expr.expr type bitvec_num = BitVecNum of bitvec_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = BitVecSort(Sort.create ctx no) @@ -3222,6 +3257,7 @@ end = struct let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) + (**/**) (** Create a new bit-vector sort. From 23febf13c40b56d7e7fe3fa4bd071c1b8c57c87d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 19:49:27 +0000 Subject: [PATCH 301/646] ML API: basic structure and interface Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 81 +- scripts/update_api.py | 30 +- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 2714 +++++++++++++++++++---------------------- 4 files changed, 1380 insertions(+), 1447 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index bea2939b6..a187bf9cb 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1340,10 +1340,17 @@ class MLComponent(Component): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + cmis = '%s/z3enums.cmi %s/z3native.cmi %s/z3.cmi' % (src_dir,src_dir,src_dir) + out.write('%s/z3enums.cmi: %s/z3enums.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3enums.mli\n' % (OCAMLC,src_dir,src_dir)) + out.write('%s/z3native.cmi: %s/z3native.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3native.mli\n' % (OCAMLC,src_dir,src_dir)) + out.write('%s/z3.cmi: %s/z3.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3.mli\n' % (OCAMLC,src_dir,src_dir)) out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') @@ -1351,7 +1358,7 @@ class MLComponent(Component): if DEBUG_MODE: out.write('-g ') out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) - out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') @@ -2716,6 +2723,76 @@ def mk_z3consts_ml(api_files): linenum = linenum + 1 if VERBOSE: print "Generated '%s/z3enums.ml'" % ('%s' % gendir) + efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') + efile.write('(* Automatically generated file *)\n\n') + efile.write('(** The enumeration types of Z3. *)\n\n') + for api_file in api_files: + api_file_c = ml.find_file(api_file, ml.name) + api_file = os.path.join(api_file_c.src_dir, api_file) + + api = open(api_file, 'r') + + SEARCHING = 0 + FOUND_ENUM = 1 + IN_ENUM = 2 + + mode = SEARCHING + decls = {} + idx = 0 + + linenum = 1 + for line in api: + m1 = blank_pat.match(line) + m2 = comment_pat.match(line) + if m1 or m2: + # skip blank lines and comments + linenum = linenum + 1 + elif mode == SEARCHING: + m = typedef_pat.match(line) + if m: + mode = FOUND_ENUM + m = typedef2_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + elif mode == FOUND_ENUM: + m = openbrace_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + else: + assert False, "Invalid %s, line: %s" % (api_file, linenum) + else: + assert mode == IN_ENUM + words = re.split('[^\-a-zA-Z0-9_]+', line) + m = closebrace_pat.match(line) + if m: + name = words[1] + if name not in DeprecatedEnums: + efile.write('(** %s *)\n' % name[3:]) + efile.write('type %s =\n' % name[3:]) # strip Z3_ + for k, i in decls.iteritems(): + efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write('\n') + efile.write('(** Convert %s to int*)\n' % name[3:]) + efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_ + efile.write('(** Convert int to %s*)\n' % name[3:]) + efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ + efile.write('\n') + mode = SEARCHING + else: + if words[2] != '': + if len(words[2]) > 1 and words[2][1] == 'x': + idx = int(words[2], 16) + else: + idx = int(words[2]) + decls[words[1]] = idx + idx = idx + 1 + linenum = linenum + 1 + if VERBOSE: + print "Generated '%s/z3enums.mli'" % ('%s' % gendir) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index c730a325e..6e9c14355 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1147,49 +1147,66 @@ def mk_ml(): return ml_dir = get_component('ml').src_dir ml_nativef = os.path.join(ml_dir, 'z3native.ml') + ml_nativefi = os.path.join(ml_dir, 'z3native.mli') ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') + ml_i = open(ml_nativefi, 'w') ml_native.write('(* Automatically generated file *)\n\n') ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') + ml_i.write('(* Automatically generated file *)\n\n') + ml_i.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_native.write('open Z3enums\n\n') ml_native.write('(**/**)\n') ml_native.write('type ptr\n') + ml_i.write('type ptr\n') ml_native.write('and z3_symbol = ptr\n') + ml_i.write('and z3_symbol = ptr\n') for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) + ml_i.write('and %s = ptr\n' % v.lower()) ml_native.write('\n') - ml_native.write('external is_null : ptr -> bool\n') - ml_native.write(' = "n_is_null"\n\n') - ml_native.write('external mk_null : unit -> ptr\n') - ml_native.write(' = "n_mk_null"\n\n') + ml_i.write('\n') + ml_native.write('external is_null : ptr -> bool\n = "n_is_null"\n\n') + ml_native.write('external mk_null : unit -> ptr\n = "n_mk_null"\n\n') ml_native.write('exception Exception of string\n\n') + ml_i.write('val is_null : ptr -> bool\n') + ml_i.write('val mk_null : unit -> ptr\n') + ml_i.write('exception Exception of string\n\n') # ML declarations - ml_native.write(' module ML2C = struct\n\n') + ml_native.write('module ML2C = struct\n\n') for name, result, params in _dotnet_decls: ml_native.write(' external n_%s : ' % ml_method_name(name)) + ml_i.write('val %s : ' % ml_method_name(name)) ip = inparams(params) op = outparams(params) if len(ip) == 0: - ml_native.write(' unit -> ') + ml_native.write(' unit -> ') for p in ip: ml_native.write('%s -> ' % param2ml(p)) + ml_i.write('%s -> ' % param2ml(p)) if len(op) > 0: ml_native.write('(') + ml_i.write('(') first = True if result != VOID or len(op) == 0: ml_native.write('%s' % type2ml(result)) + ml_i.write('%s' % type2ml(result)) first = False for p in op: if first: first = False else: ml_native.write(' * ') + ml_i.write(' * ') ml_native.write('%s' % param2ml(p)) + ml_i.write('%s' % param2ml(p)) if len(op) > 0: ml_native.write(')') + ml_i.write(')') ml_native.write('\n') + ml_i.write('\n') ml_native.write(' = "n_%s"\n' % ml_method_name(name)) if len(ip) > 5: ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) @@ -1201,6 +1218,7 @@ def mk_ml(): ip = inparams(params) op = outparams(params) ml_native.write(' let %s ' % ml_method_name(name)) + first = True i = 0; for p in params: diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index ad5442327..abcefa4af 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.ml -hide Z3 + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.mli -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index aeb9c0d03..ea8c9576e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,8 +7,479 @@ open Z3enums -(** Interaction logging for Z3 +(* Some helpers. *) +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) + +(* Internal types *) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = z3_native_context + + + +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } + + +(* Symbol types *) +type int_symbol = z3_native_object +type string_symbol = z3_native_object + +type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + +(* AST types *) +type ast = z3_native_object +type ast_vector = z3_native_object +type ast_map = z3_native_object + +(* FuncDecl types *) +type func_decl = FuncDecl of ast + +(* Sort types *) +type sort = Sort of ast +type uninterpreted_sort = UninterpretedSort of sort +type bool_sort = BoolSort of sort +type array_sort = ArraySort of sort +type set_sort = SetSort of sort +type datatype_sort = DatatypeSort of sort +type relation_sort = RelationSort of sort +type finite_domain_sort = FiniteDomainSort of sort +type enum_sort = EnumSort of sort +type list_sort = ListSort of sort +type tuple_sort = TupleSort of sort +type arith_sort = ArithSort of sort +type bitvec_sort = BitVecSort of sort + +type int_sort = IntSort of arith_sort +type real_sort = RealSort of arith_sort + +(* FuncDecl parameters *) +type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of symbol + | P_Srt of sort + | P_Ast of ast + | P_Fdl of func_decl + | P_Rat of string +type params = z3_native_object +type param_descrs = z3_native_object + +(* Expr types *) +type expr = Expr of ast + +type bool_expr = BoolExpr of expr +type arith_expr = ArithExpr of expr +type int_expr = IntExpr of arith_expr +type real_expr = RealExpr of arith_expr +type bitvec_expr = BitVecExpr of expr +type array_expr = ArrayExpr of expr +type datatype_expr = DatatypeExpr of expr + +(* Numerals *) +type int_num = IntNum of int_expr +type rat_num = RatNum of real_expr +type algebraic_num = AlgebraicNum of arith_expr +type bitvec_num = BitVecNum of bitvec_expr + +(* Quantifier stuff *) +type quantifier = Quantifier of expr +type pattern = Pattern of ast + +(* Datatype stuff *) +type constructor_extra = { + m_n : int; + mutable m_tester_decl : func_decl option; + mutable m_constructor_decl : func_decl option ; + mutable m_accessor_decls : func_decl array option} + +type constructor = Constructor of (z3_native_object * constructor_extra) +type constructor_list = z3_native_object + +(* Tactical interface *) +type goal = z3_native_object +type model = z3_native_object +type func_interp = z3_native_object +type func_entry = z3_native_object +type probe = z3_native_object +type tactic = z3_native_object +type apply_result = z3_native_object +type solver = z3_native_object +type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE +type statistics = z3_native_object +type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } +type fixedpoint = z3_native_object + + +(** Internal stuff *) +module Internal = +struct + let dispose_context ctx = + if ctx.m_n_obj_cnt == 0 then ( + (* Printf.printf "Disposing context \n" ; *) + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; + (* re-queue for finalization? *) + ) + + let create_context settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + (* Printf.printf "Installing finalizer on context \n" ; *) + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + (* CMW: Install error handler here! + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); + *) + + let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) + let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) + let context_gno ctx = ctx.m_n_ctx + + + let z3obj_gc o = o.m_ctx + let z3obj_gnc o = (context_gno o.m_ctx) + + let z3obj_gno o = o.m_n_obj + let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + + let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + + let z3obj_create o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + + let z3obj_nil_ref x y = () + + let array_to_native a = + let f e = (z3obj_gno e) in + Array.map f a + + (* Internal coercions *) + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + + let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + + and expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (ptr_of_ast a) in + Array.map f a + + let expr_of_func_app : context -> func_decl -> expr array -> expr = fun ctx f args -> + match f with FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (ptr_of_ast fa) (Array.length args) (expr_aton args) in + expr_of_ptr ctx o +end + + +open Internal + + + +(* Sort coercions *) +let ast_of_sort s = match s with Sort(x) -> x +let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x +let sort_of_bool_sort s = match s with BoolSort(x) -> x +let sort_of_array_sort s = match s with ArraySort(x) -> x +let sort_of_set_sort s = match s with SetSort(x) -> x +let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x +let sort_of_relation_sort s = match s with RelationSort(x) -> x +let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x +let sort_of_enum_sort s = match s with EnumSort(x) -> x +let sort_of_list_sort s = match s with ListSort(x) -> x +let sort_of_tuple_sort s = match s with TupleSort(x) -> x +let sort_of_arith_sort s = match s with ArithSort(x) -> x +let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x +let arith_sort_of_int_sort s = match s with IntSort(x) -> x +let arith_sort_of_real_sort s = match s with RealSort(x) -> x + +let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + +let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + +let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + +let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + +let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + +let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + +let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + +let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + +let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + +let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + +(* FuncDecl coercions *) +let ast_of_func_decl f = match f with FuncDecl(x) -> x + +(* Expr coercions *) +let ast_of_expr e = match e with Expr(a) -> a +let expr_of_bool_expr e = match e with BoolExpr(x) -> x +let expr_of_arith_expr e = match e with ArithExpr(x) -> x +let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x +let expr_of_array_expr e = match e with ArrayExpr(x) -> x +let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + +let arith_expr_of_int_expr e = match e with IntExpr(x) -> x +let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + +let int_expr_of_int_num e = match e with IntNum(x) -> x +let real_expr_of_rat_num e = match e with RatNum(x) -> x +let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x +let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + +let expr_of_quantifier e = match e with Quantifier(x) -> x +let ast_of_pattern e = match e with Pattern(x) -> x + + +let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + +let bool_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) + +let arith_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + +let bitvec_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + +let array_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + +let datatype_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + +let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + +let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + +let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(no))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + +let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(no))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + +let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + +let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(no)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + +let quantifier_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + +let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + + + +(** Interaction logging for Z3 Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) module Log = @@ -28,6 +499,7 @@ struct let append s = Z3native.append_log s end + (** Version information *) module Version = struct @@ -52,11 +524,6 @@ struct string_of_int rev ^ "." end -(**/**) -(* Some helpers. *) - -let null = Z3native.mk_null() -let is_null o = (Z3native.is_null o) let mk_list ( f : int -> 'a ) ( n : int ) = let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = @@ -66,49 +533,8 @@ let mk_list ( f : int -> 'a ) ( n : int ) = (mk_list' f (i+1) n ((f i) :: tail)) in mk_list' f 0 n [] -(**/**) -(**/**) -type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } -(**/**) -type context = z3_native_context - -(**/**) - -let context_dispose ctx = - if ctx.m_n_obj_cnt == 0 then ( - (* Printf.printf "Disposing context \n" ; *) - (Z3native.del_context ctx.m_n_ctx) - ) else ( - Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) - ) - -let context_create settings = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - (* Printf.printf "Installing finalizer on context \n" ; *) - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> context_dispose o in - Gc.finalise f res; - res -(* CMW: Install error handler here! - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); -*) - -let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) -let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) -let context_gno ctx = ctx.m_n_ctx - -(**/**) - (** Create a context object. Most interactions with Z3 are interpreted in some context; many users will only @@ -130,113 +556,14 @@ let context_gno ctx = ctx.m_n_ctx *) let mk_context ( cfg : ( string * string ) list ) = - context_create cfg + create_context cfg -(**/**) -class virtual z3object ctx_init obj_init = -object (self) - val mutable m_ctx : context = ctx_init - val mutable m_n_obj : Z3native.ptr option = obj_init - - initializer - (match m_n_obj with - | Some (x) -> self#incref (context_gno m_ctx) x; - (context_add1 m_ctx) - | None -> () - ); - (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v - - method virtual incref : Z3native.ptr -> Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> Z3native.ptr -> unit - - method dispose = - (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) - (match m_n_obj with - | Some (x) -> - self#decref (context_gno m_ctx) x; - (context_sub1 m_ctx) ; - m_n_obj <- None; - | None -> () - ); - - method gno = match m_n_obj with - | Some(x) -> x - | None -> raise (Z3native.Exception "Z3 object lost") - - method sno (ctx : context) o = - (context_add1 m_ctx) ; - self#incref (context_gno ctx) o ; - (match m_n_obj with - | Some(x) -> self#decref (context_gno ctx) x ; (context_sub1 m_ctx) - | None -> () - ); - m_n_obj <- Some o - - method gc = m_ctx - method gnc = (context_gno m_ctx) -end - - - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - -let z3obj_gc o = o.m_ctx -let z3obj_gnc o = (context_gno o.m_ctx) - -let z3obj_gno o = o.m_n_obj -let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - -let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - -let z3obj_create o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - -let z3obj_nil_ref x y = () - -let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a -(**/**) (** Symbols are used to name several term and type constructors *) module Symbol = -struct - (** Int symbol objects *) - type int_symbol = z3_native_object - - (** String symbol objects *) - type string_symbol = z3_native_object - - (** Symbol Objects *) - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - - (**/**) +struct let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; @@ -255,6 +582,11 @@ struct (z3obj_create res) ; res + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) + let gc ( x : symbol ) = match x with | S_Int(n) -> (z3obj_gc n) @@ -269,17 +601,7 @@ struct match x with | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) - - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) - - let aton a = - let f e = (gno e) in - Array.map f a - (**/**) - + (** The kind of the symbol (int or string) *) let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) @@ -327,48 +649,11 @@ end (** The abstract syntax tree (AST) module *) -module rec AST : -sig - type ast = z3_native_object - -(**/**) - val create : context -> Z3native.ptr -> ast - val aton : ast array -> Z3native.ptr array -(**/**) - - module ASTVectors : sig - type ast_vector - val create : context -> Z3native.ptr -> ast_vector - val get_size : ast_vector -> int - val get : ast_vector -> int -> ast - end - - val is_expr : ast -> bool - val is_var : ast -> bool -end = struct - type ast = z3_native_object - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let aton (a : ast array) = - let f (e : ast) = (z3obj_gno e) in - Array.map f a - (**/**) - +module AST = +struct (** Vectors of ASTs *) - module ASTVectors = + module ASTVector = struct - type ast_vector = z3_native_object - - (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; @@ -377,7 +662,7 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The size of the vector *) let get_size ( x : ast_vector ) = @@ -411,7 +696,7 @@ end = struct (** Translates all ASTs in the vector to . @param to_ctx A context - @return A new ASTVectors + @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) @@ -423,10 +708,8 @@ end = struct (** Map from AST to AST *) module ASTMap = - struct - type ast_map = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; @@ -435,7 +718,7 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Checks whether the map contains the key . @param k An AST @@ -476,7 +759,7 @@ end = struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVectors.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -576,7 +859,7 @@ end = struct if (z3obj_gnc x) == (context_gno to_ctx) then x else - create to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Wraps an AST. @@ -590,7 +873,7 @@ end = struct @param nativeObject The native pointer to wrap. *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create ctx ptr + ast_of_ptr ctx ptr (** Unwraps an AST. @@ -603,66 +886,17 @@ end = struct @param a The AST to unwrap. *) - let unwrap_ast ( x : ast ) = (z3obj_gno x) - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST -> (match (FuncDecl.create ctx no) with FuncDecl.FuncDecl(x) -> x) - | SORT_AST -> (match (Sort.create ctx no) with Sort.Sort(x) -> x) - | QUANTIFIER_AST -> (match (Quantifiers.create ctx no) with Quantifiers.Quantifier(Expr.Expr(x)) -> x) - | APP_AST - | NUMERAL_AST - | VAR_AST -> (match (Expr.create ctx no) with Expr.Expr(x) -> x) - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") -(**/**) + let unwrap_ast ( x : ast ) = (z3obj_gno x) end (** The Sort module implements type information for ASTs *) -and Sort : -sig - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - val create : context -> Z3native.ptr -> sort - val gc : sort -> context - val gnc : sort -> Z3native.ptr - val gno : sort -> Z3native.ptr - val aton : sort array -> Z3native.ptr array -end = struct - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - (**/**) +module Sort = +struct + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - let aton : sort array -> Z3native.ptr array = fun a -> - let f e = (gno e) in - Array.map f a - - let create : context -> Z3native.ptr -> sort = fun ctx no -> - let q : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno q ctx no) ; - (z3obj_create q) ; - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - (**/**) - - (** Comparison operator. @param a A sort @@ -700,7 +934,7 @@ end = struct (** Create a new uninterpreted sort. *) - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let mk_uninterpreted ( ctx : context ) ( s : symbol ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -718,71 +952,37 @@ end (** Function declarations *) -and FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - - val create : context -> Z3native.ptr -> func_decl - val gc : func_decl -> context - val gno : func_decl -> Z3native.ptr - val gnc : func_decl -> Z3native.ptr - val aton : func_decl array -> Z3native.ptr array - - val get_domain_size : func_decl -> int - val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_arity : func_decl -> int -end = struct - type func_decl = FuncDecl of AST.ast - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - FuncDecl(res) - - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = +module FuncDecl = +struct + (**/**) + let create_ndr ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + let f x = (ptr_of_ast (ast_of_sort x)) in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + let f x = (ptr_of_ast (ast_of_sort x)) in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - - let aton (a : func_decl array) = - let f (e : func_decl) = (gno e) in - Array.map f a - (**/**) + (**/**) (** Parameters of Func_Decls *) module Parameter = - struct - type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - + struct (** The kind of the parameter. *) let get_kind ( x : parameter ) = (match x with @@ -840,13 +1040,13 @@ end = struct (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = create_ndr ctx name domain range (** Creates a new function declaration. *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** @@ -854,19 +1054,19 @@ end = struct *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = create_pdr ctx prefix domain range (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort ) = create_ndr ctx name [||] range (** Creates a new constant function declaration. *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range (** @@ -874,7 +1074,7 @@ end = struct *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = create_pdr ctx prefix [||] range @@ -917,14 +1117,14 @@ end = struct *) let get_domain ( x : func_decl ) = let n = (get_domain_size x) in - let f i = Sort.create (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in Array.init n f (** The range of the function declaration *) let get_range ( x : func_decl ) = - Sort.create (gc x) (Z3native.get_range (gnc x) (gno x)) + sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) (** The kind of the function declaration. @@ -947,13 +1147,13 @@ end = struct let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> Parameter.P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> Parameter.P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> P_Ast (ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n @@ -961,7 +1161,7 @@ end = struct Create expression that applies function to arguments. @param args The arguments *) - let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.create_fa (gc x) x args + let apply ( x : func_decl ) ( args : expr array ) = expr_of_func_app (gc x) x args end (** @@ -969,43 +1169,12 @@ end A Params objects represents a configuration in the form of symbol/value pairs. *) -and Params : -sig - type params = z3_native_object - - val create : context -> Z3native.ptr -> params - - module ParamDescrs : sig - type param_descrs = z3_native_object - - val create : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - end -end = struct - type params = z3_native_object - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : params = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.params_inc_ref ; - dec_ref = Z3native.params_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - (**/**) - +module Params = +struct (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs : - sig - type param_descrs = z3_native_object - - val create : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - end = struct - type param_descrs = z3_native_object - - (**/**) + module ParamDescrs = + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; @@ -1014,14 +1183,14 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Validate a set of parameters. *) let validate ( x : param_descrs ) ( p : params ) = Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + let get_kind ( x : param_descrs ) ( name : symbol ) = (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) (** Retrieve all names of parameters. *) @@ -1040,25 +1209,25 @@ end = struct (** Adds a parameter setting. *) - let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + let add_int ( x : params ) (name : symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + let add_double ( x : params ) ( name : symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) (** @@ -1081,14 +1250,20 @@ end = struct (** Adds a parameter setting. *) - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = add_symbol x (Symbol.mk_string (z3obj_gc x) name) value (** Creates a new parameter set *) let mk_params ( ctx : context ) = - create ctx (Z3native.mk_params (context_gno ctx)) + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; + (z3obj_create res) ; + res (** A string representation of the parameter set. @@ -1097,76 +1272,16 @@ end = struct end (** General expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - - val create : context -> Z3native.ptr -> expr - val create_fa : context -> FuncDecl.func_decl -> expr array -> expr - val gc : expr -> context - val gno : expr -> Z3native.ptr - val gnc : expr -> Z3native.ptr - val aton : expr array -> Z3native.ptr array - - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - val get_func_decl : expr -> FuncDecl.func_decl - val is_numeral : expr -> bool - val to_string : expr -> string -end = struct - type expr = Expr of AST.ast - - (**/**) - let create ( ctx : context ) ( obj : Z3native.ptr ) = - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then - (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) - else - let s = Z3native.get_sort (context_gno ctx) obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.ArithExpr(e)) -> e) - else - if (Z3native.is_numeral_ast (context_gno ctx) obj) && - (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - match sk with - | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e))) -> e) - | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) - | _ -> raise (Z3native.Exception "Unsupported numeral object") - else - match sk with - | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e)) -> e) - | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) - | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) - | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) - | _ -> Expr(AST.create ctx obj) - - let aton ( a : expr array ) = - let f ( e : expr ) = match e with Expr(a) -> (z3obj_gno a) in - Array.map f a - - let create_fa ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = - let o = Z3native.mk_app (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args) in - Expr.create ctx o - - let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) - let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) - let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) - - let aton (a : expr array) = - let f (e : expr) = (gno e) in - Array.map f a - (**/**) - +module Expr = +struct (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> Expr.create (gc x) (Z3native.simplify (gnc x) (gno x)) - | Some pp -> Expr.create (gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) + let simplify ( x : expr ) ( p : params option ) = match p with + | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) + | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1183,24 +1298,24 @@ end = struct (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = FuncDecl.create (gc x) (Z3native.get_app_decl (gnc x) (gno x)) + let get_func_decl ( x : expr ) = func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the expression is the true or false expression or something else (L_UNDEF). *) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) (** The number of arguments of the expression. *) - let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) + let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) (** The arguments of the expression. *) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = create (gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in + let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in Array.init n f (** @@ -1211,7 +1326,7 @@ end = struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - create (gc x) (Z3native.update_term (gnc x) (gno x) (Array.length args) (aton args)) + expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -1224,7 +1339,7 @@ end = struct if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - create (gc x) (Z3native.substitute (gnc x) (gno x) (Array.length from) (aton from) (aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) (** Substitute every occurrence of from in the expression with to. @@ -1239,48 +1354,47 @@ end = struct For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) let substitute_vars ( x : expr ) to_ = - create (gc x) (Z3native.substitute_vars (gnc x) (gno x) (Array.length to_) (aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) - (** Translates (copies) the term to the Context . @param ctx A context @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = - if (gc x) == to_ctx then + if (c_of_expr x) == to_ctx then x else - create to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) + expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) (** Returns a string representation of the expression. *) - let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) + let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) (** The Sort of the term. *) - let get_sort ( x : expr ) = Sort.create (gc x) (Z3native.get_sort (gnc x) (gno x)) + let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (gnc x) - (Z3native.mk_bool_sort (gnc x)) - (Z3native.get_sort (gnc x) (gno x))) + (Z3native.is_eq_sort (nc_of_expr x) + (Z3native.mk_bool_sort (nc_of_expr x)) + (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) (** Indicates whether the term represents a constant. @@ -1366,14 +1480,14 @@ end = struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = - create ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) + let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) (** Creates a new Constant of sort and named . *) - let mk_const_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range @@ -1381,21 +1495,21 @@ end = struct Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = - create_fa ctx f [||] + let mk_const_f ( ctx : context ) ( f : func_decl ) = + expr_of_func_app ctx f [||] (** Creates a fresh constant of sort and a name prefixed with . *) - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = - create ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = - create_fa ctx f args + let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = + expr_of_func_app ctx f args (** Create a numeral of a given sort. @@ -1403,8 +1517,8 @@ end = struct @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. @return A Term with value and sort *) - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : Sort.sort ) = - create ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1413,50 +1527,31 @@ end = struct @param ty Sort of the numeral @return A Term with value and type *) - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = - create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end (** Boolean expressions *) -and Booleans : -sig - type bool_expr = BoolExpr of Expr.expr - type bool_sort = BoolSort of Sort.sort +module Boolean = +struct + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let a = (ast_of_ptr ctx no) in + BoolExpr(Expr(a)) - val create_expr : context -> Z3native.ptr -> bool_expr - val create_sort : context -> Z3native.ptr -> bool_sort - val gc : bool_expr -> context - val gnc : bool_expr -> Z3native.ptr - val gno : bool_expr -> Z3native.ptr - val aton : bool_expr array -> Z3native.ptr array -end = struct - type bool_expr = BoolExpr of Expr.expr - type bool_sort = BoolSort of Sort.sort - - (**/**) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.create ctx no) in - BoolExpr(Expr.Expr(a)) + let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(sort_of_ptr ctx no) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(Sort.create ctx no) - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) - - let aton ( a : bool_expr array ) = - let f (e : bool_expr) = (gno e) in - Array.map f a - (**/**) + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (ptr_of_expr e) let mk_sort ( ctx : context ) = - BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) + BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) (** Create a Boolean constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) @@ -1470,13 +1565,13 @@ end = struct The true Term. *) let mk_true ( ctx : context ) = - create_expr ctx (Z3native.mk_true (context_gno ctx)) + bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - create_expr ctx (Z3native.mk_false (context_gno ctx)) + bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1487,20 +1582,20 @@ end = struct (** Creates the equality = . *) - let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = - create_expr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) (** Creates a distinct term. *) - let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = - create_expr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_distinct ( ctx : context ) ( args : expr array ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - create_expr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1509,103 +1604,70 @@ end = struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - create_expr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - create_expr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) end (** Quantifier expressions *) -and Quantifiers : -sig - type quantifier = Quantifier of Expr.expr - - val create : context -> Z3native.ptr -> quantifier -end = struct - type quantifier = Quantifier of Expr.expr - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.create ctx no) in - Quantifier(Expr.Expr(a)) - - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - (**/**) - +module Quantifier = +struct + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) + (** Quantifier patterns Patterns comprise a list of terms. The list should be non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Patterns : - sig - type pattern = Pattern of AST.ast - - val create : context -> Z3native.ptr -> pattern - val aton : pattern array -> Z3native.ptr array - end = struct - type pattern = Pattern of AST.ast - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - Pattern(res) - + module Pattern = struct let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - let aton (a : pattern array) = - let f (e : pattern) = (gno e) in - Array.map f a - (**/**) - (** The number of terms in the pattern. *) let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - + Z3native.get_pattern_num_terms (gnc x) (gno x) + (** The terms in the pattern. *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in - let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f (** @@ -1632,11 +1694,11 @@ end = struct on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its index. *) - let get_index ( x : Expr.expr ) = - if not (AST.is_var (match x with Expr.Expr(a) -> a)) then + let get_index ( x : expr ) = + if not (AST.is_var (match x with Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value (Expr.gnc x) (Expr.gno x) + Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) (** Indicates whether the quantifier is universal. @@ -1664,7 +1726,7 @@ end = struct *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = (Patterns.create (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1677,7 +1739,7 @@ end = struct *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = (Patterns.create (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1698,31 +1760,31 @@ end = struct *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (Sort.create (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f (** The body of the quantifier. *) let get_body ( x : quantifier ) = - Booleans.create_expr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @param index The de-Bruijn index of the variable @param ty The sort of the variable *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : Sort.sort ) = - Expr.create ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) (** Create a quantifier pattern. *) - let mk_pattern ( ctx : context ) ( terms : Expr.expr array ) = + let mk_pattern ( ctx : context ) ( terms : expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Patterns.create ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (Expr.aton terms)) + Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) (** Create a universal Quantifier. @@ -1743,96 +1805,96 @@ end = struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (Patterns.aton patterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) - + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) + (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (ptr_of_expr body))) (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (Patterns.aton patterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) - + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (ptr_of_expr body))) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1842,7 +1904,7 @@ end = struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1850,42 +1912,29 @@ end = struct end (** Functions to manipulate Array expressions *) -and Arrays : -sig - type array_expr = ArrayExpr of Expr.expr - type array_sort = ArraySort of Sort.sort - - val create_expr : context -> Z3native.ptr -> array_expr -end = struct - type array_expr = ArrayExpr of Expr.expr - type array_sort = ArraySort of Sort.sort - - (**/**) +module Array_ = +struct + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in + let e = (expr_of_ptr ctx no) in ArrayExpr(e) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in ArraySort(s) - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gno s) + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gno e) + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - let aton (a : array_expr array) = - let f (e : array_expr) = (egno e) in - Array.map f a - (**/**) - (** Create a new array sort. *) - let mk_sort ( ctx : context ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** @@ -1893,62 +1942,62 @@ end = struct It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). Array store takes at least 3 arguments. *) - let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the function passed as parameter. *) - let is_as_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) (** Indicates whether the term is of an array sort. *) - let is_array ( x : Expr.expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) + let is_array ( x : expr ) = + (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_domain ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + let get_range ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** Create an array constant. *) - let mk_const_s ( ctx : context ) ( name : string ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range (** @@ -1963,8 +2012,8 @@ end = struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) = - create_expr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) (** Array update. @@ -1982,8 +2031,8 @@ end = struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) ( v : Expr.expr ) = - create_expr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) (** Create a constant array. @@ -1993,8 +2042,8 @@ end = struct *) - let mk_const_array ( ctx : context ) ( domain : Sort.sort ) ( v : Expr.expr ) = - create_expr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) (** Maps f on the argument arrays. @@ -2006,8 +2055,9 @@ end = struct *) - let mk_map ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : array_expr array ) = - create_expr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args)) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + let m x = (ptr_of_expr (expr_of_array_expr x)) in + expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) (** Access the array default value. @@ -2016,137 +2066,122 @@ end = struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - create_expr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) -and Sets : -sig - type set_sort = SetSort of Sort.sort - -end = struct - type set_sort = SetSort of Sort.sort - +module Set = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in SetSort(s) (** Indicates whether the term is set union *) - let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_intersect ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_difference ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_subset ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) (** Create a set type. *) - let mk_sort ( ctx : context ) ( ty : Sort.sort ) = + let mk_sort ( ctx : context ) ( ty : sort ) = create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. *) - let mk_empty ( ctx : context ) ( domain : Sort.sort ) = - (Expr.create ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) + let mk_empty ( ctx : context ) ( domain : sort ) = + (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) (** Create the full set. *) - let mk_full ( ctx : context ) ( domain : Sort.sort ) = - Expr.create ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) + let mk_full ( ctx : context ) ( domain : sort ) = + expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) (** Add an element to the set. *) - let mk_set_add ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) (** Remove an element from a set. *) - let mk_del ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) (** Take the union of a list of sets. *) - let mk_union ( ctx : context ) ( args : Expr.expr array ) = - Expr.create ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_union ( ctx : context ) ( args : expr array ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) (** Take the intersection of a list of sets. *) - let mk_intersection ( ctx : context ) ( args : Expr.expr array ) = - Expr.create ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_intersection ( ctx : context ) ( args : expr array ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) (** Take the difference between two sets. *) - let mk_difference ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) (** Take the complement of a set. *) - let mk_complement ( ctx : context ) ( arg : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) + let mk_complement ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) (** Check for set membership. *) - let mk_membership ( ctx : context ) ( elem : Expr.expr ) ( set : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) (** Check for subsetness of sets. *) - let mk_subset ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) end (** Functions to manipulate Finite Domain expressions *) -and FiniteDomains : -sig - type finite_domain_sort = FiniteDomainSort of Sort.sort - -end = struct - type finite_domain_sort = FiniteDomainSort of Sort.sort - - (**/**) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) - +module FiniteDomain = +struct + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) + (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - create_sort ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size) + let mk_sort ( ctx : context ) ( name : symbol ) ( size : int ) = + let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in + FiniteDomainSort(s) (** Create a new finite domain sort. @@ -2158,14 +2193,15 @@ end = struct (** Indicates whether the term is of an array sort. *) - let is_finite_domain ( x : Expr.expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == FINITE_DOMAIN_SORT) + let is_finite_domain ( x : expr ) = + let nc = (nc_of_expr x) in + (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. *) - let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) (** The size of the finite domain sort. *) let get_size ( x : finite_domain_sort ) = @@ -2175,29 +2211,25 @@ end = struct end (** Functions to manipulate Relation expressions *) -and Relations : -sig - type relation_sort = RelationSort of Sort.sort - -end = struct - type relation_sort = RelationSort of Sort.sort - - (**/**) +module Relation = +struct + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in RelationSort(s) - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) + (** Indicates whether the term is of a relation sort. *) - let is_relation ( x : Expr.expr ) = - ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == RELATION_SORT)) + let is_relation ( x : expr ) = + let nc = (nc_of_expr x) in + ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2206,40 +2238,40 @@ end = struct The function takes n+1 arguments, where the first argument is the relation and the remaining n elements correspond to the n columns of the relation. *) - let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) (** Indicates whether the term is an empty relation *) - let is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) (** Indicates whether the term is a test for the emptiness of a relation *) - let is_is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) (** Indicates whether the term is a relational join *) - let is_join ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) (** Indicates whether the term is the union or convex hull of two relations. The function takes two arguments. *) - let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) (** Indicates whether the term is the widening of two relations The function takes two arguments. *) - let is_widen ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). The function takes one argument. *) - let is_project ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) (** Indicates whether the term is a relation filter @@ -2250,7 +2282,7 @@ end = struct corresponding to the columns of the relation. So the first column in the relation has index 0. *) - let is_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) (** Indicates whether the term is an intersection of a relation with the negation of another. @@ -2265,7 +2297,7 @@ end = struct target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with ( x : expr ) on the columns c1, d1, .., cN, dN. *) - let is_negation_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) (** Indicates whether the term is the renaming of a column in a relation @@ -2273,12 +2305,12 @@ end = struct The function takes one argument. The parameters contain the renaming as a cycle. *) - let is_rename ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) (** Indicates whether the term is the complement of a relation *) - let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) (** Indicates whether the term is a relational select @@ -2287,7 +2319,7 @@ end = struct The function takes n+1 arguments, where the first argument is a relation, and the remaining n arguments correspond to a record. *) - let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) (** Indicates whether the term is a relational clone (copy) @@ -2298,7 +2330,7 @@ end = struct for terms of kind to perform destructive updates to the first argument. *) - let is_clone ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) (** The arity of the relation sort. *) let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) @@ -2312,46 +2344,22 @@ end = struct end (** Functions to manipulate Datatype expressions *) -and Datatypes : -sig - type datatype_expr = DatatypeExpr of Expr.expr - type datatype_sort = DatatypeSort of Sort.sort - - val create_expr : context -> Z3native.ptr -> datatype_expr -end = struct - type datatype_expr = DatatypeExpr of Expr.expr - type datatype_sort = DatatypeSort of Sort.sort - - (**/**) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in - DatatypeExpr(e) - +module Datatype = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in DatatypeSort(s) - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) + (** Constructors *) - module Constructor : sig - type constructor - val create : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> constructor - val aton : constructor array -> Z3native.ptr array - end = struct - type constructor_extra = { - m_n : int; - mutable m_tester_decl : FuncDecl.func_decl option; - mutable m_constructor_decl : FuncDecl.func_decl option ; - mutable m_accessor_decls : FuncDecl.func_decl array option} - - type constructor = Constructor of (z3_native_object * constructor_extra) - - (**/**) - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + module Constructor = + struct + + let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2362,8 +2370,8 @@ end = struct let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) n - (Symbol.aton field_names) - (Sort.aton sorts) + (let f x = (Symbol.gno x) in (Array.map f field_names)) + (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) sort_refs) in let no : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -2379,21 +2387,17 @@ end = struct Gc.finalise f no ; Constructor(no, ex) - let aton ( a : constructor array ) = - let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in - Array.map f a - let init_extra ( x : constructor ) = match x with Constructor(no, ex) -> match ex.m_tester_decl with | None -> let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in - ex.m_constructor_decl <- Some (FuncDecl.create (z3obj_gc no) a) ; - ex.m_tester_decl <- Some (FuncDecl.create (z3obj_gc no) b) ; - ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; + ex.m_constructor_decl <- Some (func_decl_of_ptr (z3obj_gc no) a) ; + ex.m_tester_decl <- Some (func_decl_of_ptr (z3obj_gc no) b) ; + ex.m_accessor_decls <- Some (let f e = (func_decl_of_ptr (z3obj_gc no) e) in Array.map f c) ; () | _ -> () - (**/**) + let get_n ( x : constructor ) = match x with Constructor(no, ex) -> @@ -2433,24 +2437,18 @@ end = struct (** Constructor list objects *) module ConstructorList = struct - type constructor_list = z3_native_object - - (**/**) - let create ( ctx : context )( c : Constructor.constructor array ) = + + let create ( ctx : context ) ( c : constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Constructor.aton c))) ; + let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f res; res - - let aton (a : constructor_list array) = - let f (e : constructor_list) = (z3obj_gno e) in - Array.map f a - (**/**) end (* DATATYPES *) @@ -2464,7 +2462,7 @@ end = struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2478,21 +2476,22 @@ end = struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array) = - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Constructor.aton constructors)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in create_sort ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2500,16 +2499,17 @@ end = struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = + let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = let n = (Array.length names) in - let f e = (ConstructorList.create ctx e) in + let f e = (ptr_of_ast (ConstructorList.create ctx e)) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (ConstructorList.aton cla)) in + let f2 x = (Symbol.gno x) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in let g e = (create_sort ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2523,54 +2523,50 @@ end = struct (** The range of the array sort. *) let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f (** The recognizers. *) let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f (** The constructor accessors. *) let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in Array.init ds g ) in Array.init n f end (** Functions to manipulate Enumeration expressions *) -and Enumerations : -sig - type enum_sort_data - type enum_sort = EnumSort of (Sort.sort * enum_sort_data) -end = struct - type enum_sort_data = { mutable _constdecls : FuncDecl.func_decl array ; - mutable _testerdecls : FuncDecl.func_decl array } - type enum_sort = EnumSort of (Sort.sort * enum_sort_data) - - (**/**) +module Enumeration = +struct + let _constdecls = Hashtbl.create 0 + let _testerdecls = Hashtbl.create 0 + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = - let s = (Sort.create ctx no) in - let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; - _testerdecls = (let f e = FuncDecl.create ctx e in (Array.map f tdecls)) } in - EnumSort(s, e) + let s = (sort_of_ptr ctx no) in + let res = EnumSort(s) in + Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; + Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; + res - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) - (**/**) + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) (** Create a new enumeration sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( enum_names : symbol array ) = + let f x = Symbol.gno x in + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in create_sort ctx a b c (** @@ -2580,45 +2576,40 @@ end = struct mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._constdecls + let get_const_decls ( x : enum_sort ) = Hashtbl.find _constdecls x (** The test predicates for the constants in the enumeration. *) - let get_tester_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._testerdecls + let get_tester_decls ( x : enum_sort ) = Hashtbl.find _testerdecls x end (** Functions to manipulate List expressions *) -and Lists : -sig - type list_sort_data - type list_sort = ListSort of (Sort.sort * list_sort_data) - -end = struct - type list_sort_data = { _nildecl : FuncDecl.func_decl ; - _is_nildecl : FuncDecl.func_decl ; - _consdecl : FuncDecl.func_decl ; - _is_consdecl : FuncDecl.func_decl ; - _headdecl : FuncDecl.func_decl ; - _taildecl : FuncDecl.func_decl } - type list_sort = ListSort of (Sort.sort * list_sort_data) - - (**/**) +module List_ = +struct + let _nildecls = Hashtbl.create 0 + let _is_nildecls = Hashtbl.create 0 + let _consdecls = Hashtbl.create 0 + let _is_consdecls = Hashtbl.create 0 + let _headdecls = Hashtbl.create 0 + let _taildecls = Hashtbl.create 0 + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (Sort.create ctx no) in - let e = {_nildecl = FuncDecl.create ctx nildecl; - _is_nildecl = FuncDecl.create ctx is_nildecl; - _consdecl = FuncDecl.create ctx consdecl; - _is_consdecl = FuncDecl.create ctx is_consdecl; - _headdecl = FuncDecl.create ctx headdecl; - _taildecl = FuncDecl.create ctx taildecl} in - ListSort(s, e) + let s = (sort_of_ptr ctx no) in + let res = ListSort(s) in + Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; + Hashtbl.add _is_nildecls res (func_decl_of_ptr ctx is_nildecl) ; + Hashtbl.add _consdecls res (func_decl_of_ptr ctx consdecl) ; + Hashtbl.add _is_consdecls res (func_decl_of_ptr ctx is_consdecl) ; + Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; + Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; + res - let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) - (**/**) + let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) + (** Create a new list sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = + let mk_sort ( ctx : context ) ( name : symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in create_sort ctx r a b c d e f @@ -2627,53 +2618,51 @@ end = struct mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._nildecl + let get_nil_decl ( x : list_sort ) = (Hashtbl.find _nildecls x) (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_nildecl + let get_is_nil_decl ( x : list_sort ) = (Hashtbl.find _is_nildecls x) (** The declaration of the cons function of this list sort. *) - let get_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._consdecl + let get_cons_decl ( x : list_sort ) = (Hashtbl.find _consdecls x) (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_consdecl + let get_is_cons_decl ( x : list_sort ) = (Hashtbl.find _is_consdecls x) (** The declaration of the head function of this list sort. *) - let get_head_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._headdecl + let get_head_decl ( x : list_sort ) = (Hashtbl.find _headdecls x) (** The declaration of the tail function of this list sort. *) - let get_tail_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._taildecl + let get_tail_decl ( x : list_sort ) = (Hashtbl.find _taildecls x) (** The empty list. *) - let nil ( x : list_sort ) = Expr.create_fa (sgc x) (get_nil_decl x) [||] + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] end (** Functions to manipulate Tuple expressions *) -and Tuples : -sig - type tuple_sort = TupleSort of Sort.sort -end = struct - type tuple_sort = TupleSort of Sort.sort - - (**/**) +module Tuple = +struct + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in TupleSort(s) - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) + (** Create a new tuple sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = - let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Symbol.aton field_names) (Sort.aton field_sorts)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( field_names : symbol array ) ( field_sorts : sort array ) = + let f x = Symbol.gno x in + let f2 x = ptr_of_ast (ast_of_sort x) in + let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in (* CMW: leaks a,b? *) create_sort ctx r (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = - FuncDecl.create (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) (** The number of fields in the tuple. *) let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) @@ -2681,131 +2670,37 @@ end = struct (** The field declarations. *) let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in - let f i = FuncDecl.create (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end (** Functions to manipulate arithmetic expressions *) -and Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val create_expr : context -> Z3native.ptr -> arith_expr - val create_sort : context -> Z3native.ptr -> arith_sort - val aton : arith_expr array -> Z3native.ptr array - - module Integers : sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val create_sort : context -> Z3native.ptr -> int_sort - val create_expr : context -> Z3native.ptr -> int_expr - val create_num : context -> Z3native.ptr -> int_num - end - - module Reals : sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val create_sort : context -> Z3native.ptr -> real_sort - val create_expr : context -> Z3native.ptr -> real_expr - val create_num : context -> Z3native.ptr -> rat_num - end - - module AlgebraicNumbers : sig - type algebraic_num = AlgebraicNum of arith_expr - - val create_num : context -> Z3native.ptr -> algebraic_num - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr array -> Arithmetic.arith_expr - val mk_mul : context -> arith_expr array -> Arithmetic.arith_expr - val mk_sub : context -> arith_expr array -> Arithmetic.arith_expr - val mk_unary_minus : - context -> arith_expr -> Arithmetic.arith_expr - val mk_div : - context -> arith_expr -> arith_expr -> Arithmetic.arith_expr - val mk_power : - context -> arith_expr -> arith_expr -> Arithmetic.arith_expr - val mk_lt : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_le : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_gt : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_ge : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - -end = struct - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - (**/**) +module Arithmetic = +struct + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - ArithExpr(Expr.create ctx no) + arith_expr_of_expr (expr_of_ptr ctx no) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - ArithSort(Sort.create ctx no) + arith_sort_of_sort (sort_of_ptr ctx no) - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (c_of_expr e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - let aton (a : arith_expr array) = - let f (e : arith_expr) = (egno e) in - Array.map f a - (**/**) - - module rec Integers : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val create_sort : context -> Z3native.ptr -> int_sort - val create_expr : context -> Z3native.ptr -> int_expr - val create_num : context -> Z3native.ptr -> int_num - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - (**/**) + module Integer = + struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - IntSort(Arithmetic.create_sort ctx no) + int_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(Arithmetic.create_expr ctx no) + int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - IntNum(create_expr ctx no) + int_num_of_int_expr (create_expr ctx no) let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) @@ -2816,7 +2711,7 @@ end = struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - (**/**) + (** Create a new integer sort. *) let mk_sort ( ctx : context ) = @@ -2834,7 +2729,7 @@ end = struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_int_const ( ctx : context ) ( name : symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) (** @@ -2848,14 +2743,14 @@ end = struct The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - create_expr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - create_expr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) (** Create an integer numeral. @@ -2883,7 +2778,7 @@ end = struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) (** Create an bit bit-vector from the integer argument . @@ -2896,32 +2791,19 @@ end = struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVectors.create_expr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t)) + bitvec_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end - and Reals : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val create_sort : context -> Z3native.ptr -> real_sort - val create_expr : context -> Z3native.ptr -> real_expr - val create_num : context -> Z3native.ptr -> rat_num - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - (**/**) + module Real = + struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - RealSort(Arithmetic.create_sort ctx no) + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(Arithmetic.create_expr ctx no) - + real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + let create_num ( ctx : context ) ( no : Z3native.ptr ) = - RatNum(create_expr ctx no) + rat_num_of_real_expr (create_expr ctx no) let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) @@ -2932,7 +2814,7 @@ end = struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - (**/**) + (** Create a real sort. *) let mk_sort ( ctx : context ) = @@ -2940,11 +2822,11 @@ end = struct (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - Integers.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + Integer.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - Integers.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + Integer.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2955,7 +2837,7 @@ end = struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_real_const ( ctx : context ) ( name : symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) (** Creates a real constant. *) @@ -2995,7 +2877,7 @@ end = struct (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Booleans.create_expr ctx (Z3native.mk_is_int (context_gno ctx) (egno t)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) (** Coerce a real to an integer. @@ -3005,25 +2887,18 @@ end = struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integers.create_expr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)) + int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end - and AlgebraicNumbers : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val create_num : context -> Z3native.ptr -> algebraic_num - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - (**/**) + module AlgebraicNumber = + struct let create_num ( ctx : context ) ( no : Z3native.ptr ) = - AlgebraicNum(Arithmetic.create_expr ctx no) + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - (**/**) + (** Return a upper bound for a given real algebraic number. @@ -3033,7 +2908,7 @@ end = struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - Reals.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + Real.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) (** Return a lower bound for the given real algebraic number. @@ -3043,7 +2918,7 @@ end = struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - Reals.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + Real.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -3057,207 +2932,197 @@ end = struct (** Indicates whether the term is of integer sort. *) - let is_int ( x : Expr.expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) (** Indicates whether the term is an arithmetic numeral. *) - let is_arithmetic_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) (** Indicates whether the term is a less-than-or-equal *) - let is_le ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) (** Indicates whether the term is a greater-than-or-equal *) - let is_ge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) (** Indicates whether the term is a less-than *) - let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) (** Indicates whether the term is a greater-than *) - let is_gt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) (** Indicates whether the term is addition (binary) *) - let is_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) (** Indicates whether the term is subtraction (binary) *) - let is_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) (** Indicates whether the term is a unary minus *) - let is_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) (** Indicates whether the term is multiplication (binary) *) - let is_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) (** Indicates whether the term is division (binary) *) - let is_div ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) (** Indicates whether the term is integer division (binary) *) - let is_idiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) (** Indicates whether the term is remainder (binary) *) - let is_remainder ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) (** Indicates whether the term is modulus (binary) *) - let is_modulus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) (** Indicates whether the term is a coercion of integer to real (unary) *) - let is_inttoreal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) (** Indicates whether the term is a coercion of real to integer (unary) *) - let is_real_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - let is_real_is_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) (** Indicates whether the term is of sort real. *) - let is_real ( x : Expr.expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) (** Indicates whether the term is an integer numeral. *) - let is_int_numeral ( x : Expr.expr ) = (Expr.is_numeral x) && (is_int x) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) (** Indicates whether the term is a real numeral. *) - let is_rat_num ( x : Expr.expr ) = (Expr.is_numeral x) && (is_real x) + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : Expr.expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) (** Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 ^ t2. *) let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end (** Functions to manipulate bit-vector expressions *) -and BitVectors : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val create_sort : context -> Z3native.ptr -> bitvec_sort - val create_expr : context -> Z3native.ptr -> bitvec_expr - val create_num : context -> Z3native.ptr -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - (**/**) +module BitVector = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - BitVecSort(Sort.create ctx no) + bitvec_sort_of_sort (sort_of_ptr ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - BitVecExpr(Expr.create ctx no) + bitvec_expr_of_expr (expr_of_ptr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - BitVecNum(create_expr ctx no) + bitvec_num_of_bitvec_expr (create_expr ctx no) let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (c_of_expr e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (nc_of_expr e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (ptr_of_expr e) let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - (**/**) + (** Create a new bit-vector sort. @@ -3268,272 +3133,272 @@ end = struct (** Indicates whether the terms is of bit-vector sort. *) - let is_bv ( x : Expr.expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) + let is_bv ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) (** The size of a bit-vector sort. *) let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) @@ -3550,7 +3415,7 @@ end = struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) (** @@ -3564,91 +3429,91 @@ end = struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3660,7 +3525,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3675,7 +3540,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3685,7 +3550,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3697,7 +3562,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3706,7 +3571,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3714,7 +3579,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than @@ -3722,7 +3587,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) (** Unsigned less-than or equal to. @@ -3730,7 +3595,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than or equal to. @@ -3738,7 +3603,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater than or equal to. @@ -3746,7 +3611,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater than or equal to. @@ -3754,7 +3619,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater-than. @@ -3762,7 +3627,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater-than. @@ -3770,7 +3635,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) (** Bit-vector concatenation. @@ -3781,7 +3646,7 @@ end = struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3792,7 +3657,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3802,7 +3667,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3813,7 +3678,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3821,7 +3686,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3836,7 +3701,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) (** @@ -3851,7 +3716,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3867,7 +3732,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3876,7 +3741,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3885,7 +3750,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3894,7 +3759,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3904,7 +3769,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3922,7 +3787,7 @@ end = struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integers.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + Arithmetic.Integer.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3930,7 +3795,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3938,7 +3803,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3946,7 +3811,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3954,7 +3819,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3962,7 +3827,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3970,7 +3835,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3978,7 +3843,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3986,7 +3851,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a bit-vector numeral. @@ -3994,28 +3859,27 @@ end = struct @param v A string representing the value in decimal notation. @param size the size of the bit-vector *) - let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = + let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) end (** Functions to manipulate proof expressions *) -and Proofs : -sig -end = struct +module Proof = +struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_asserted ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_goal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -4026,7 +3890,7 @@ end = struct [mp T1 T2]: q The second antecedents may also be a proof for (iff p q). *) - let is_modus_ponens ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. @@ -4035,7 +3899,7 @@ end = struct equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. *) - let is_reflexivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -4045,7 +3909,7 @@ end = struct [symmetry T1]: (R s t) T1 is the antecedent of this proof object. *) - let is_symmetry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -4056,7 +3920,7 @@ end = struct T2: (R s u) [trans T1 T2]: (R t u) *) - let is_transitivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -4076,7 +3940,7 @@ end = struct if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. *) - let is_Transitivity_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -4089,7 +3953,7 @@ end = struct Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. *) - let is_monotonicity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -4098,7 +3962,7 @@ end = struct T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - let is_quant_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -4115,7 +3979,7 @@ end = struct Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. *) - let is_distributivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -4124,7 +3988,7 @@ end = struct T1: (and l_1 ... l_n) [and-elim T1]: l_i *) - let is_and_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -4133,7 +3997,7 @@ end = struct T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) *) - let is_or_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -4147,11 +4011,11 @@ end = struct Remark: if f is bool, then = is iff. Examples: - (= (+ ( x : Expr.expr ) 0) x) - (= (+ ( x : Expr.expr ) 1 2) (+ 3 x)) - (iff (or ( x : Expr.expr ) false) x) + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) - let is_rewrite ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -4166,14 +4030,14 @@ end = struct - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - let is_rewrite_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - let is_pull_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -4182,7 +4046,7 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents *) - let is_pull_quant_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -4195,7 +4059,7 @@ end = struct This proof object has no antecedents *) - let is_push_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -4207,34 +4071,34 @@ end = struct This proof object has no antecedents. *) - let is_elim_unused_vars ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : Expr.expr ) t)) P[x])) P[t]) - if ( x : Expr.expr ) does not occur in t. + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. This proof object has no antecedents. Several variables can be eliminated simultaneously. *) - let is_der ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) *) - let is_quant_inst ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. Mark a hypothesis in a natural deduction style proof. *) - let is_hypothesis ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -4246,7 +4110,7 @@ end = struct It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. *) - let is_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -4257,7 +4121,7 @@ end = struct T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - let is_unit_resolution ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true @@ -4265,7 +4129,7 @@ end = struct T1: p [iff-true T1]: (iff p true) *) - let is_iff_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false @@ -4273,7 +4137,7 @@ end = struct T1: (not p) [iff-false T1]: (iff p false) *) - let is_iff_false ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -4285,7 +4149,7 @@ end = struct This proof object has no antecedents. Remark: if f is bool, then = is iff. *) - let is_commutativity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -4320,7 +4184,7 @@ end = struct unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). *) - let is_def_axiom ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -4342,7 +4206,7 @@ end = struct Otherwise: [def-intro]: (= n e) *) - let is_def_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -4351,7 +4215,7 @@ end = struct F is 'equivalent' to n, given that T1 is a proof that n is a name for F. *) - let is_apply_def ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq @@ -4359,7 +4223,7 @@ end = struct T1: (iff p q) [iff~ T1]: (~ p q) *) - let is_iff_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -4386,7 +4250,7 @@ end = struct NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. *) - let is_nnf_pos ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -4410,7 +4274,7 @@ end = struct [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) *) - let is_nnf_neg ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -4421,7 +4285,7 @@ end = struct This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_nnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -4430,19 +4294,19 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_cnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step Proof for: - [sk]: (~ (not (forall ( x : Expr.expr ) (p ( x : Expr.expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : Expr.expr ) (p ( x : Expr.expr ) y)) (p (sk y) y)) + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) This proof object has no antecedents. *) - let is_skolemize ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -4452,7 +4316,7 @@ end = struct T2: (~ p q) [mp~ T1 T2]: q *) - let is_modus_ponens_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -4470,7 +4334,7 @@ end = struct (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - let is_theory_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end @@ -4480,10 +4344,8 @@ end of formulas, that can be solved and/or transformed using tactics and solvers. *) module Goal = -struct - type goal = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; @@ -4492,7 +4354,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The precision of the goal. @@ -4521,8 +4383,8 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : Booleans.bool_expr array ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) in + let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () @@ -4543,7 +4405,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = Booleans.create_expr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4562,7 +4424,7 @@ struct create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : Params.params option ) = + let simplify ( x : goal ) ( p : params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with @@ -4602,9 +4464,7 @@ end A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - type model = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; @@ -4613,7 +4473,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Function interpretations @@ -4622,9 +4482,7 @@ struct *) module FuncInterp = struct - type func_interp = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; @@ -4633,17 +4491,15 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Function interpretations entries An Entry object represents an element in the finite map used to a function interpretation. *) module FuncEntry = - struct - type func_entry = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; @@ -4652,13 +4508,13 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - Expr.create (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. @@ -4670,7 +4526,7 @@ struct *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (Expr.create (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4698,7 +4554,7 @@ struct (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = Expr.create (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation @@ -4725,7 +4581,7 @@ struct (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let get_const_interp ( x : model ) ( f : func_decl ) = if (FuncDecl.get_arity f) != 0 || (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") @@ -4734,19 +4590,19 @@ struct if (Z3native.is_null np) then None else - Some (Expr.create (z3obj_gc x) np) + Some (expr_of_ptr (z3obj_gc x) np) (** Retrieves the interpretation (the assignment) of in the model. A Constant An expression if the constant has an interpretation in the model, null otherwise. *) - let get_const_interp_e ( x : model ) ( a : Expr.expr ) = get_const_interp x (Expr.get_func_decl a) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) (** Retrieves the interpretation (the assignment) of a non-constant in the model. A function declaration of non-zero arity A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let rec get_func_interp ( x : model ) ( f : func_decl ) = let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in @@ -4759,7 +4615,7 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x (FuncDecl.create (z3obj_gc x) fd) + get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in @@ -4771,7 +4627,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4781,15 +4637,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4810,15 +4666,15 @@ struct The evaluation of in the model. *) - let eval ( x : model ) ( t : Expr.expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else - Expr.create (z3obj_gc x) v + expr_of_ptr (z3obj_gc x) v (** Alias for eval. *) - let evaluate ( x : model ) ( t : Expr.expr ) ( completion : bool ) = + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -4834,7 +4690,7 @@ struct *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in - let f i = (Sort.create (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f @@ -4843,10 +4699,10 @@ struct An uninterpreted sort An array of expressions, where each is an element of the universe of *) - let sort_universe ( x : model ) ( s : Sort.sort ) = - let n_univ = AST.ASTVectors.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in - let n = (AST.ASTVectors.get_size n_univ) in - let f i = (AST.ASTVectors.get n_univ i) in + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -4866,9 +4722,7 @@ end *) module Probe = struct - type probe = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; @@ -4877,14 +4731,14 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Execute the probe over the goal. A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : Goal.goal) = + let apply ( x : probe ) (g : goal) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** @@ -4988,10 +4842,8 @@ end It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. *) module Tactic = -struct - type tactic = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; @@ -5000,7 +4852,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Tactic application results @@ -5008,9 +4860,7 @@ struct tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct - type apply_result = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; @@ -5019,7 +4869,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = @@ -5039,7 +4889,7 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) @@ -5054,7 +4904,7 @@ struct Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = + let apply ( x : tactic ) ( g : goal ) ( p : params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) @@ -5122,14 +4972,14 @@ struct If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** @@ -5154,7 +5004,7 @@ struct (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : Probe.probe ) = + let fail_if ( ctx : context ) ( p : probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** @@ -5167,14 +5017,14 @@ struct (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = using_params ctx t p (** @@ -5201,10 +5051,8 @@ end (** Solvers *) module Solver = -struct - type solver = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; @@ -5213,9 +5061,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) - - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" @@ -5224,10 +5070,8 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = - struct - type statistics = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; @@ -5236,7 +5080,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Statistical data is organized into pairs of \[Key, Entry\], where every @@ -5245,14 +5089,7 @@ struct *) module Entry = struct - type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } - - (**/**) + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -5272,7 +5109,7 @@ struct m_float = v } in res - (**/**) + (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key @@ -5344,7 +5181,7 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( p : Params.params )= + let set_parameters ( x : solver ) ( p : params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** @@ -5382,8 +5219,8 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : Booleans.bool_expr array ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in + let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) (** @@ -5399,11 +5236,11 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : Booleans.bool_expr array ) ( ps : Booleans.bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) (Booleans.gno (Array.get ps i))) in + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in ignore (Array.iteri f cs) (** @@ -5418,24 +5255,24 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : Booleans.bool_expr ) ( p : Booleans.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno c) (Booleans.gno p) + let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVectors.get_size a) + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVector.get_size a) (** The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVectors.get_size a) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get a i)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size a) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f (** @@ -5445,12 +5282,13 @@ struct *) - let check ( x : solver ) ( assumptions : Booleans.bool_expr array) = + let check ( x : solver ) ( assumptions : bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Booleans.aton assumptions)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5481,7 +5319,7 @@ struct if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** The unsat core of the last Check. @@ -5491,9 +5329,9 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVectors.get_size cn) in - let f i = (AST.ASTVectors.get cn i) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in Array.init n f (** @@ -5515,7 +5353,7 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = + let mk_solver ( ctx : context ) ( logic : symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) @@ -5539,7 +5377,7 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + let mk_solver_t ( ctx : context ) ( t : tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** @@ -5551,10 +5389,7 @@ end (** Fixedpoint solving *) module Fixedpoint = -struct - type fixedpoint = z3_native_object - - (**/**) +struct let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; @@ -5563,7 +5398,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_create res) ; res - (**/**) + (** A string that describes all available fixedpoint solver parameters. @@ -5574,7 +5409,7 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : Params.params )= + let set_params ( x : fixedpoint ) ( p : params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** @@ -5586,29 +5421,29 @@ struct (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : Booleans.bool_expr array ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in + let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () (** Register predicate as recursive relation. *) - let register_relation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) = + let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) (** Add table fact to the fixedpoint solver. *) - let add_fact ( x : fixedpoint ) ( pred : FuncDecl.func_decl ) ( args : int array ) = + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args (** @@ -5617,11 +5452,11 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : Booleans.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Booleans.gno query))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN + let query ( x : fixedpoint ) ( query : bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN (** Query the fixedpoint solver. @@ -5629,11 +5464,12 @@ struct The query is satisfiable if there is an instance of some relation that is non-empty. The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - let query_r ( x : fixedpoint ) ( relations : FuncDecl.func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (FuncDecl.aton relations))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN + let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + let f x = ptr_of_ast (ast_of_func_decl x) in + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN (** Creates a backtracking point. @@ -5654,8 +5490,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5666,7 +5502,7 @@ struct if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. @@ -5677,25 +5513,25 @@ struct (** Retrieve the number of levels explored for a given predicate. *) - let get_num_levels ( x : fixedpoint ) ( predicate : FuncDecl.func_decl ) = + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) (** Retrieve the cover of a predicate. *) - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) = + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) ( property : Expr.expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) (** Retrieve internal string representation of fixedpoint object. @@ -5705,31 +5541,33 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) ( kinds : Symbol.symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Symbol.aton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + let f2 x = (Symbol.gno x) in + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : Booleans.bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Booleans.aton queries) + let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = + let f x = ptr_of_expr (expr_of_bool_expr x) in + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVectors.get_size v) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVectors.get_size v) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** @@ -5813,10 +5651,10 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Booleans.bool_expr array ) ( formula : Booleans.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (Booleans.aton assumptions) - (Booleans.gno formula) + (Array.length assumptions) (let f x = ptr_of_expr (expr_of_bool_expr x) in (Array.map f assumptions)) + (Boolean.gno formula) (** Parse the given string using the SMT-LIB parser. @@ -5827,7 +5665,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5837,17 +5675,17 @@ struct else Z3native.parse_smtlib_string (context_gno ctx) str cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5857,11 +5695,11 @@ struct else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)) (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. @@ -5873,7 +5711,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = Booleans.create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i) in + let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f @@ -5887,7 +5725,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = Booleans.create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i) in + let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f (** @@ -5900,7 +5738,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = FuncDecl.create ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5913,7 +5751,7 @@ struct *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (Sort.create ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5922,7 +5760,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5930,19 +5768,19 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.aton sort_names) - (Sort.aton sorts) - cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5950,13 +5788,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string (context_gno ctx) file_name + bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) end From a27945f297c20a5af0794d3c8bbff1b1612c7268 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 20:04:11 +0000 Subject: [PATCH 302/646] ML API: got rid of "extra" objects on types. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 73 +++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 50 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index ea8c9576e..aa919e7fc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -93,13 +93,7 @@ type quantifier = Quantifier of expr type pattern = Pattern of ast (* Datatype stuff *) -type constructor_extra = { - m_n : int; - mutable m_tester_decl : func_decl option; - mutable m_constructor_decl : func_decl option ; - mutable m_accessor_decls : func_decl array option} - -type constructor = Constructor of (z3_native_object * constructor_extra) +type constructor = z3_native_object type constructor_list = z3_native_object (* Tactical interface *) @@ -2358,7 +2352,8 @@ struct (** Constructors *) module Constructor = struct - + let _counts = Hashtbl.create 0 + let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then @@ -2373,53 +2368,31 @@ struct (let f x = (Symbol.gno x) in (Array.map f field_names)) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) sort_refs) in - let no : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - let ex : constructor_extra = { m_n = n; - m_tester_decl = None; - m_constructor_decl = None; - m_accessor_decls = None} in + let no : constructor = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + Hashtbl.add _counts no n ; (z3obj_sno no ctx ptr) ; (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; - Constructor(no, ex) + no - let init_extra ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_tester_decl with - | None -> - let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in - ex.m_constructor_decl <- Some (func_decl_of_ptr (z3obj_gc no) a) ; - ex.m_tester_decl <- Some (func_decl_of_ptr (z3obj_gc no) b) ; - ex.m_accessor_decls <- Some (let f e = (func_decl_of_ptr (z3obj_gc no) e) in Array.map f c) ; - () - | _ -> () - - - let get_n ( x : constructor ) = - match x with Constructor(no, ex) -> - ex.m_n + let get_n ( x : constructor ) = (Hashtbl.find _counts x) - let rec tester_decl ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_tester_decl with - | Some(s) -> s - | None -> init_extra x ; tester_decl x - let rec constructor_decl ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_constructor_decl with - | Some(s) -> s - | None -> init_extra x ; constructor_decl x + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + func_decl_of_ptr (z3obj_gc x) a + + let rec tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + func_decl_of_ptr (z3obj_gc x) b let rec accessor_decls ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_accessor_decls with - | Some(s) -> s - | None -> init_extra x ; accessor_decls x + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let f y = func_decl_of_ptr (z3obj_gc x) y in + Array.map f c (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2443,7 +2416,7 @@ struct m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let f x =(z3obj_gno x) in (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in @@ -2462,7 +2435,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2483,8 +2456,8 @@ struct (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = - let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array ) = + let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in create_sort ctx x From 5f41a40a63eb31a823628b7b77f73b17b1e9bcbf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 22:49:19 +0000 Subject: [PATCH 303/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a187bf9cb..e32ca14f9 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1332,40 +1332,49 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): + CP_CMD = "cp" + if IS_WINDOWS: + CP_CMD = "copy" src_dir = self.to_src_dir sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): - shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) + out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): - shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - cmis = '%s/z3enums.cmi %s/z3native.cmi %s/z3.cmi' % (src_dir,src_dir,src_dir) - out.write('%s/z3enums.cmi: %s/z3enums.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3enums.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('%s/z3native.cmi: %s/z3native.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3native.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('%s/z3.cmi: %s/z3.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) + out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) + out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + modules = ["z3enums", "z3native", "z3"] # dependencies in this order! + prev = '' + for m in modules: + out.write('%s/%s.mli: %s/%s.ml %s\n' % (sub_dir,m,sub_dir,m,prev)) + out.write('\t%s -I %s -i -c %s/%s.ml > %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m,sub_dir,m)) + prev = prev + ' ' + sub_dir + '/' + m + '.mli' + cmis = '' + for m in modules: + out.write('%s/%s.cmi: %s/%s.mli\n' % (sub_dir,m,sub_dir,m)) + out.write('\t%s -I %s -c %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m)) + cmis = cmis + ' ' + sub_dir + '/' + m + '.cmi' + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(src_dir, mlfile)) + out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) + out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') From fd2ae5f60e28c8523be6dac66b41a7e1d9e67421 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 23:42:50 +0000 Subject: [PATCH 304/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 54 +++++++++++++++++++++-------------- src/api/ml/z3.ml | 60 ++++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 3b13a2462..49db6fb50 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -7,6 +7,7 @@ open Z3 open Z3.Symbol open Z3.Sort open Z3.Expr +open Z3.Boolean open Z3.FuncDecl open Z3.Goal open Z3.Tactic @@ -22,12 +23,20 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = ((mk_const ctx (Symbol.mk_string ctx "x") (mk_real_sort ctx )) :> arith_expr) in - let yr = ((mk_const ctx (Symbol.mk_string ctx "y") (mk_real_sort ctx )) :> arith_expr) in + let xr = (arith_expr_of_expr + (Expr.mk_const ctx (Symbol.mk_string ctx "x") + (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in + let yr = (arith_expr_of_expr + (Expr.mk_const ctx (Symbol.mk_string ctx "y") + (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; - (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; - (Goal.assert_ g4 [| (mk_gt ctx yr (mk_real_numeral_nd ctx 1 1)) |]) ; + (Goal.assert_ g4 [| (mk_gt ctx xr + (arith_expr_of_real_expr (real_expr_of_rat_num + (Real.mk_numeral_nd ctx 10 1)))) |]) ; + (Goal.assert_ g4 [| (mk_eq ctx + (expr_of_arith_expr yr) + (expr_of_arith_expr (mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |] ))) |] ) ; + (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -67,15 +76,15 @@ let model_converter_test ( ctx : context ) = *) let basic_tests ( ctx : context ) = Printf.printf "BasicTests\n" ; - let qi = (mk_int ctx 1) in +(* let qi = (mk_int ctx 1) in *) let fname = (mk_string ctx "f") in let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in - let bs = (Sort.mk_bool ctx) in + let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in let domain = [| bs; bs |] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f - [| (mk_const ctx x bs); (mk_const ctx y bs) |]) in + [| (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) |]) in let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in let domain2 = [| bs |] in let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in @@ -110,8 +119,11 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) - (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + (Goal.assert_ g [| (mk_eq ctx + (mk_numeral_int ctx 1 + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) + (mk_numeral_int ctx 2 + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) |] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -132,7 +144,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [| (mk_false ctx) |]) ; + (Goal.assert_ g2 [| (Boolean.mk_false ctx) |]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -142,10 +154,10 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (mk_const ctx (Symbol.mk_string ctx "x") (mk_int_sort ctx)) in - let yc = (mk_const ctx (Symbol.mk_string ctx "y") (mk_int_sort ctx)) in - (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; - (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; + let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in + let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in + (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; + (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; let constr = (mk_eq ctx xc yc) in (Goal.assert_ g3 [| constr |] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in @@ -208,14 +220,14 @@ let _ = let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in - let bs = (Sort.mk_bool ctx) in - let ints = (mk_int_sort ctx) in - let rs = (mk_real_sort ctx) in + let bs = (Boolean.mk_sort ctx) in + let ints = (Integer.mk_sort ctx) in + let rs = (Real.mk_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string is); Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string bs); - Printf.printf "int sort: %s\n" (Sort.to_string ints); - Printf.printf "real sort: %s\n" (Sort.to_string rs); + Printf.printf "bool sort: %s\n" (Sort.to_string (sort_of_bool_sort bs)); + Printf.printf "int sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_int_sort ints))); + Printf.printf "real sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_real_sort rs))); basic_tests ctx ; Printf.printf "Disposing...\n"; Gc.full_major () diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index aa919e7fc..651102bc8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -240,7 +240,7 @@ struct Expr(z3_native_object_of_ast_ptr ctx no) else let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) no) then Expr(z3_native_object_of_ast_ptr ctx no) else @@ -376,92 +376,99 @@ let expr_of_ast a = Expr(a) let bool_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.BOOL_SORT) then raise (Z3native.Exception "Invalid coercion") else BoolExpr(e) let arith_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then raise (Z3native.Exception "Invalid coercion") else ArithExpr(e) let bitvec_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.BV_SORT) then raise (Z3native.Exception "Invalid coercion") else BitVecExpr(e) let array_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.ARRAY_SORT) then raise (Z3native.Exception "Invalid coercion") else ArrayExpr(e) let datatype_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.DATATYPE_SORT) then raise (Z3native.Exception "Invalid coercion") else DatatypeExpr(e) let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.INT_SORT) then raise (Z3native.Exception "Invalid coercion") else IntExpr(e) let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.REAL_SORT) then raise (Z3native.Exception "Invalid coercion") else RealExpr(e) let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(no))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else IntNum(e) let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(no))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else RatNum(e) let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc no) (z3obj_gno no))) then + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else AlgebraicNum(e) let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(no)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else BitVecNum(e) let quantifier_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in if (q != Z3enums.QUANTIFIER_AST) then raise (Z3native.Exception "Invalid coercion") else @@ -4378,7 +4385,8 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) From 09aa02759f3501492f0f710ae50848687f4eb22a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 11:49:00 +0000 Subject: [PATCH 305/646] ML API: Build system and error handling fixes. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 8 ++++++-- scripts/update_api.py | 12 ++++++++++++ src/api/ml/z3.ml | 6 +----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e32ca14f9..a30e074b0 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1341,10 +1341,14 @@ class MLComponent(Component): api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) + if IS_WINDOWS: str = str.replace('/','\\') + out.write(str) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) + if IS_WINDOWS: str = str.replace('/','\\') + out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: diff --git a/scripts/update_api.py b/scripts/update_api.py index 6e9c14355..e5c66dd39 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1169,9 +1169,11 @@ def mk_ml(): ml_i.write('\n') ml_native.write('external is_null : ptr -> bool\n = "n_is_null"\n\n') ml_native.write('external mk_null : unit -> ptr\n = "n_mk_null"\n\n') + ml_native.write('external set_internal_error_handler : ptr -> unit\n = "n_set_internal_error_handler"\n\n') ml_native.write('exception Exception of string\n\n') ml_i.write('val is_null : ptr -> bool\n') ml_i.write('val mk_null : unit -> ptr\n') + ml_i.write('val set_internal_error_handler : ptr -> unit\n\n') ml_i.write('exception Exception of string\n\n') # ML declarations @@ -1329,6 +1331,16 @@ def mk_ml(): ml_wrapper.write(' memcpy( Data_custom_val(result), &z3_result, sizeof(void*));\n') ml_wrapper.write(' CAMLreturn (result);\n') ml_wrapper.write('}\n\n') + ml_wrapper.write('void MLErrorHandler(Z3_context c, Z3_error_code e)\n') + ml_wrapper.write('{\n') + ml_wrapper.write(' // Internal do-nothing error handler. This is required to avoid that Z3 calls exit()\n') + ml_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') + ml_wrapper.write(' // wrappers below.\n') + ml_wrapper.write('}\n\n') + ml_wrapper.write('void n_set_internal_error_handler(Z3_context c)\n') + ml_wrapper.write('{\n') + ml_wrapper.write(' Z3_set_error_handler(c, MLErrorHandler);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 651102bc8..45faae468 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -135,16 +135,12 @@ struct let v = Z3native.mk_context_rc cfg in Z3native.del_config(cfg) ; Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; (* Printf.printf "Installing finalizer on context \n" ; *) let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in let f = fun o -> dispose_context o in Gc.finalise f res; res - (* CMW: Install error handler here! - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); - *) let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) From 2af1f81ae17a42801384c5e543edcdbc16b4dcfd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 18:37:52 +0000 Subject: [PATCH 306/646] ML API: Cleanup Signed-off-by: Christoph M. Wintersteiger --- examples/ml/Makefile | 4 +- examples/ml/ml_example.ml | 5 +- scripts/update_api.py | 2 + src/api/ml/z3.ml | 2247 +++++++++++++++++++------------------ 4 files changed, 1159 insertions(+), 1099 deletions(-) diff --git a/examples/ml/Makefile b/examples/ml/Makefile index 4b3e7c4d2..a7f8e6ee0 100644 --- a/examples/ml/Makefile +++ b/examples/ml/Makefile @@ -3,5 +3,5 @@ # in the top-level build directory. all: - OCAML_COMPAT=c ocamlc -g -annot -o ml_example.byte -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cma ml_example.ml - ocamlopt -g -annot -o ml_example -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml + OCAML_COMPAT=c C:/ocamlw32/bin/ocamlc -g -annot -o ml_example.byte -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cma ml_example.ml + C:/ocamlw32/bin/ocamlopt -g -annot -o ml_example -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 49db6fb50..6dfe11623 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -15,6 +15,9 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic +open Z3.Arithmetic.Integer +open Z3.Arithmetic.Real +open Z3.BitVector exception TestFailedException of string @@ -35,7 +38,7 @@ let model_converter_test ( ctx : context ) = (Real.mk_numeral_nd ctx 10 1)))) |]) ; (Goal.assert_ g4 [| (mk_eq ctx (expr_of_arith_expr yr) - (expr_of_arith_expr (mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |] ))) |] ) ; + (expr_of_arith_expr (Arithmetic.mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |]) ) ) |] ) ; (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in diff --git a/scripts/update_api.py b/scripts/update_api.py index e5c66dd39..a0b7e6250 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1155,6 +1155,7 @@ def mk_ml(): ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_i.write('(* Automatically generated file *)\n\n') ml_i.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') + ml_i.write('(**/**)\n\n'); ml_native.write('open Z3enums\n\n') ml_native.write('(**/**)\n') ml_native.write('type ptr\n') @@ -1214,6 +1215,7 @@ def mk_ml(): ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) ml_native.write('\n') ml_native.write(' end\n\n') + ml_i.write('\n(**/**)\n'); # Exception wrappers for name, result, params in _dotnet_decls: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 45faae468..c261fce05 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -16,104 +16,11 @@ let is_null o = (Z3native.is_null o) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context - - type z3_native_object = { m_ctx : context ; mutable m_n_obj : Z3native.ptr ; inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - - -(* Symbol types *) -type int_symbol = z3_native_object -type string_symbol = z3_native_object - -type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - -(* AST types *) -type ast = z3_native_object -type ast_vector = z3_native_object -type ast_map = z3_native_object - -(* FuncDecl types *) -type func_decl = FuncDecl of ast - -(* Sort types *) -type sort = Sort of ast -type uninterpreted_sort = UninterpretedSort of sort -type bool_sort = BoolSort of sort -type array_sort = ArraySort of sort -type set_sort = SetSort of sort -type datatype_sort = DatatypeSort of sort -type relation_sort = RelationSort of sort -type finite_domain_sort = FiniteDomainSort of sort -type enum_sort = EnumSort of sort -type list_sort = ListSort of sort -type tuple_sort = TupleSort of sort -type arith_sort = ArithSort of sort -type bitvec_sort = BitVecSort of sort - -type int_sort = IntSort of arith_sort -type real_sort = RealSort of arith_sort - -(* FuncDecl parameters *) -type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of symbol - | P_Srt of sort - | P_Ast of ast - | P_Fdl of func_decl - | P_Rat of string -type params = z3_native_object -type param_descrs = z3_native_object - -(* Expr types *) -type expr = Expr of ast - -type bool_expr = BoolExpr of expr -type arith_expr = ArithExpr of expr -type int_expr = IntExpr of arith_expr -type real_expr = RealExpr of arith_expr -type bitvec_expr = BitVecExpr of expr -type array_expr = ArrayExpr of expr -type datatype_expr = DatatypeExpr of expr - -(* Numerals *) -type int_num = IntNum of int_expr -type rat_num = RatNum of real_expr -type algebraic_num = AlgebraicNum of arith_expr -type bitvec_num = BitVecNum of bitvec_expr - -(* Quantifier stuff *) -type quantifier = Quantifier of expr -type pattern = Pattern of ast - -(* Datatype stuff *) -type constructor = z3_native_object -type constructor_list = z3_native_object - -(* Tactical interface *) -type goal = z3_native_object -type model = z3_native_object -type func_interp = z3_native_object -type func_entry = z3_native_object -type probe = z3_native_object -type tactic = z3_native_object -type apply_result = z3_native_object -type solver = z3_native_object -type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE -type statistics = z3_native_object -type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } -type fixedpoint = z3_native_object (** Internal stuff *) @@ -121,11 +28,9 @@ module Internal = struct let dispose_context ctx = if ctx.m_n_obj_cnt == 0 then ( - (* Printf.printf "Disposing context \n" ; *) (Z3native.del_context ctx.m_n_ctx) ) else ( - Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) + Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; ) let create_context settings = @@ -136,7 +41,6 @@ struct Z3native.del_config(cfg) ; Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; Z3native.set_internal_error_handler v ; - (* Printf.printf "Installing finalizer on context \n" ; *) let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in let f = fun o -> dispose_context o in Gc.finalise f res; @@ -178,16 +82,6 @@ struct let array_to_native a = let f e = (z3obj_gno e) in Array.map f a - - (* Internal coercions *) - let context_of_ast ( x : ast ) = (z3obj_gc x) - let nc_of_ast ( x : ast ) = (z3obj_gnc x) - let ptr_of_ast ( x : ast ) = (z3obj_gno x) - - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> let res : z3_native_object = { m_ctx = ctx ; @@ -196,323 +90,25 @@ struct dec_ref = Z3native.dec_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; - res - - let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> - let q = (z3_native_object_of_ast_ptr ctx no) in - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then - raise (Z3native.Exception "Invalid coercion") - else - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - - let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - FuncDecl(z3_native_object_of_ast_ptr ctx no) - - let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST - | SORT_AST - | QUANTIFIER_AST - | APP_AST - | NUMERAL_AST - | VAR_AST -> z3_native_object_of_ast_ptr ctx no - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") - - and expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then - Expr(z3_native_object_of_ast_ptr ctx no) - else - let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) no) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - raise (Z3native.Exception "Unsupported numeral object") - else - Expr(z3_native_object_of_ast_ptr ctx no) - - let expr_aton ( a : expr array ) = - let f ( e : expr ) = match e with Expr(a) -> (ptr_of_ast a) in - Array.map f a - - let expr_of_func_app : context -> func_decl -> expr array -> expr = fun ctx f args -> - match f with FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (ptr_of_ast fa) (Array.length args) (expr_aton args) in - expr_of_ptr ctx o + res end - open Internal - - -(* Sort coercions *) -let ast_of_sort s = match s with Sort(x) -> x -let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x -let sort_of_bool_sort s = match s with BoolSort(x) -> x -let sort_of_array_sort s = match s with ArraySort(x) -> x -let sort_of_set_sort s = match s with SetSort(x) -> x -let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x -let sort_of_relation_sort s = match s with RelationSort(x) -> x -let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x -let sort_of_enum_sort s = match s with EnumSort(x) -> x -let sort_of_list_sort s = match s with ListSort(x) -> x -let sort_of_tuple_sort s = match s with TupleSort(x) -> x -let sort_of_arith_sort s = match s with ArithSort(x) -> x -let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x -let arith_sort_of_int_sort s = match s with IntSort(x) -> x -let arith_sort_of_real_sort s = match s with RealSort(x) -> x - -let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - -let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - -let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - -let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - -let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - -let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - -let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - -let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - -let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - -let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - -(* FuncDecl coercions *) -let ast_of_func_decl f = match f with FuncDecl(x) -> x - -(* Expr coercions *) -let ast_of_expr e = match e with Expr(a) -> a -let expr_of_bool_expr e = match e with BoolExpr(x) -> x -let expr_of_arith_expr e = match e with ArithExpr(x) -> x -let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x -let expr_of_array_expr e = match e with ArrayExpr(x) -> x -let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - -let arith_expr_of_int_expr e = match e with IntExpr(x) -> x -let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - -let int_expr_of_int_num e = match e with IntNum(x) -> x -let real_expr_of_rat_num e = match e with RatNum(x) -> x -let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x -let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - -let expr_of_quantifier e = match e with Quantifier(x) -> x -let ast_of_pattern e = match e with Pattern(x) -> x - - -let expr_of_ast a = - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Expr(a) - -let bool_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - -let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - -let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - -let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - -let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - -let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - -let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - -let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - -let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - -let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - -let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - -let quantifier_of_expr e = - match e with Expr(a) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.QUANTIFIER_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Quantifier(e) - -let pattern_of_ast a = - (* CMW: Unchecked ok? *) - Pattern(a) - - - -(** Interaction logging for Z3 - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) module Log = struct - (** Open an interaction log file. - @param filename the name of the file to open. - @return True if opening the log file succeeds, false otherwise. - *) - (* CMW: "open" seems to be a reserved keyword? *) let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - - (** Closes the interaction log. *) let close = Z3native.close_log - - (** Appends a user-provided string to the interaction log. - @param s the string to append*) let append s = Z3native.append_log s end -(** Version information *) module Version = struct - (** The major version. *) let major = let (x, _, _, _) = Z3native.get_version in x - - (** The minor version. *) let minor = let (_, x, _, _) = Z3native.get_version in x - - (** The build version. *) let build = let (_, _, x, _) = Z3native.get_version in x - - (** The revision. *) let revision = let (_, _, _, x) = Z3native.get_version in x - - (** A string representation of the version information. *) let to_string = let (mj, mn, bld, rev) = Z3native.get_version in string_of_int mj ^ "." ^ @@ -532,35 +128,21 @@ let mk_list ( f : int -> 'a ) ( n : int ) = mk_list' f 0 n [] -(** Create a context object. - - Most interactions with Z3 are interpreted in some context; many users will only - require one such object, but power users may require more than one. To start using - Z3, do - - - let ctx = (mk_context []) in - (...) - - - where a list of pairs of strings may be passed to set options on - the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (mk_context cfg) in - (...) - -*) let mk_context ( cfg : ( string * string ) list ) = create_context cfg - - -(** Symbols are used to name several term and type constructors *) module Symbol = -struct +struct + (* Symbol types *) + type int_symbol = z3_native_object + type string_symbol = z3_native_object + + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + + let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; @@ -588,7 +170,7 @@ struct match x with | S_Int(n) -> (z3obj_gc n) | S_Str(n) -> (z3obj_gc n) - + let gnc ( x : symbol ) = match x with | S_Int(n) -> (z3obj_gnc n) @@ -599,59 +181,55 @@ struct | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) - (** The kind of the symbol (int or string) *) - let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) - - (** Indicates whether the symbol is of Int kind *) + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL - - (** Indicates whether the symbol is of string kind. *) let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - - (** The int value of the symbol. *) let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - - (** The string value of the symbol. *) let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) - - (** A string representation of the symbol. *) let to_string ( o : symbol ) = match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) let mk_int ( ctx : context ) ( i : int ) = S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) - (** Creates a new symbol using a string. *) let mk_string ( ctx : context ) ( s : string ) = S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - (** Create an array of symbols. *) let mk_ints ( ctx : context ) ( names : int array ) = let f elem = mk_int ( ctx : context ) elem in (Array.map f names) - (** Create an array of symbols. *) let mk_strings ( ctx : context ) ( names : string array ) = let f elem = mk_string ( ctx : context ) elem in (Array.map f names) end -(** The abstract syntax tree (AST) module *) module AST = -struct - (** Vectors of ASTs *) +struct + type ast = z3_native_object + + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + module ASTVector = struct - let create ( ctx : context ) ( no : Z3native.ptr ) = + type ast_vector = z3_native_object + + let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; @@ -659,55 +237,34 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** The size of the vector *) + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) - (** - Retrieves the i-th object in the vector. - @param i Index - @return An AST - *) let get ( x : ast_vector ) ( i : int ) = - create (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) - (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) - (** Resize the vector to . - @param newSize The new size of the vector. *) let resize ( x : ast_vector ) ( new_size : int ) = Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size - (** - Add the AST to the back of the vector. The size - is increased by 1. - @param a An AST - *) let push ( x : ast_vector ) ( a : ast ) = Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) - (** - Translates all ASTs in the vector to . - @param to_ctx A context - @return A new ASTVector - *) let translate ( x : ast_vector ) ( to_ctx : context ) = - create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) end - (** Map from AST to AST *) module ASTMap = struct + type ast_map = z3_native_object - let create ( ctx : context ) ( no : Z3native.ptr ) = + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_map_inc_ref ; @@ -715,73 +272,36 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** Checks whether the map contains the key . - @param k An AST - @return True if is a key in the map, false otherwise. *) + let contains ( x : ast_map ) ( key : ast ) = Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - (** Finds the value associated with the key . - - This function signs an error when is not a key in the map. - @param k An AST - *) let find ( x : ast_map ) ( key : ast ) = - create (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) + ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - (** - Stores or replaces a new key/value pair in the map. - @param k The key AST - @param v The value AST - *) let insert ( x : ast_map ) ( key : ast ) ( value : ast) = Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) - (** - Erases the key from the map. - @param k An AST - *) let erase ( x : ast_map ) ( key : ast ) = Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - (** Removes all keys from the map. *) let reset ( x : ast_map ) = Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) - (** The size of the map *) let get_size ( x : ast_map ) = Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) - (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) - (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end - (** - The AST's hash code. - @return A hash code - *) let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) - - (** - A unique identifier for the AST (unique among all ASTs). - *) let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) - - (** - The kind of the AST. - *) let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) - (** - Indicates whether the AST is an Expr - *) let is_expr ( x : ast ) = match get_ast_kind ( x : ast ) with | APP_AST @@ -790,117 +310,77 @@ struct | VAR_AST -> true | _ -> false - (** - Indicates whether the AST is a bound variable - *) let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST - - (** - Indicates whether the AST is a Quantifier - *) let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST - - - (** - Indicates whether the AST is a Sort - *) let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST - - (** - Indicates whether the AST is a FunctionDeclaration - *) let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST - (** - A string representation of the AST. - *) let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - - (** - A string representation of the AST in s-expression notation. - *) let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - (** - Comparison operator. - @param a An AST - @param b An AST - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || if (z3obj_gnc a) != (z3obj_gnc b) then false else Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) - (** - Object Comparison. - @param other Another ast - @return Negative if the object should be sorted before , positive if after else zero. - *) let compare a b = if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - (** Operator < *) let ( < ) (a : ast) (b : ast) = (compare a b) - (** - Translates (copies) the AST to the Context . - @param ctx A context - @return A copy of the AST which is associated with - *) let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then x else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** - Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - *) - let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - ast_of_ptr ctx ptr - - (** - Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - *) + let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr let unwrap_ast ( x : ast ) = (z3obj_gno x) end -(** The Sort module implements type information for ASTs *) +open AST + + module Sort = struct - + type sort = Sort of AST.ast + type uninterpreted_sort = UninterpretedSort of sort + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let ast_of_sort s = match s with Sort(x) -> x + let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x + + let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - - (** - Comparison operator. - @param a A sort - @param b A sort - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + let ( = ) : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then @@ -908,30 +388,13 @@ struct else (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) - (** - Returns a unique identifier for the sort. - *) + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) - - (** - The kind of the sort. - *) let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) - - (** - The name of the sort - *) let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) - - (** - A string representation of the sort. - *) let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted ( ctx : context ) ( s : symbol ) = + + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -940,24 +403,76 @@ struct (z3obj_create res) ; UninterpretedSort(Sort(res)) - (** - Create a new uninterpreted sort. - *) let mk_uninterpreted_s ( ctx : context ) ( s : string ) = mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) end +open Sort -(** Function declarations *) -module FuncDecl = -struct - (**/**) - let create_ndr ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = + +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + val func_decl_of_ptr : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context + val gnc : func_decl -> Z3native.ptr + val gno : func_decl -> Z3native.ptr + module Parameter : + sig + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + val get_kind : parameter -> Z3enums.parameter_kind + val get_int : parameter -> int + val get_float : parameter -> float + val get_symbol : parameter -> Symbol.symbol + val get_sort : parameter -> Sort.sort + val get_ast : parameter -> AST.ast + val get_func_decl : parameter -> func_decl + val get_rational : parameter -> string + end + val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + val ( = ) : func_decl -> func_decl -> bool + val to_string : func_decl -> string + val get_id : func_decl -> int + val get_arity : func_decl -> int + val get_domain_size : func_decl -> int + val get_domain : func_decl -> Sort.sort array + val get_range : func_decl -> Sort.sort + val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_name : func_decl -> Symbol.symbol + val get_num_parameters : func_decl -> int + val get_parameters : func_decl -> Parameter.parameter list + val apply : func_decl -> Expr.expr array -> Expr.expr +end = struct + type func_decl = FuncDecl of AST.ast + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let ast_of_func_decl f = match f with FuncDecl(x) -> x + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (ptr_of_ast (ast_of_sort x)) in + let f x = (AST.ptr_of_ast (ast_of_sort x)) in (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) @@ -967,20 +482,26 @@ struct m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (ptr_of_ast (ast_of_sort x)) in + let f x = (AST.ptr_of_ast (ast_of_sort x)) in (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) - let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - (**/**) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - (** Parameters of Func_Decls *) module Parameter = - struct - (** The kind of the parameter. *) + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + let get_kind ( x : parameter ) = (match x with | P_Int(_) -> PARAMETER_INT @@ -991,188 +512,137 @@ struct | P_Fdl(_) -> PARAMETER_FUNC_DECL | P_Rat(_) -> PARAMETER_RATIONAL) - (**The int value of the parameter.*) let get_int ( x : parameter ) = match x with | P_Int(x) -> x | _ -> raise (Z3native.Exception "parameter is not an int") - - (**The double value of the parameter.*) + let get_float ( x : parameter ) = match x with | P_Dbl(x) -> x | _ -> raise (Z3native.Exception "parameter is not a double") - - (**The Symbol value of the parameter.*) + let get_symbol ( x : parameter ) = match x with | P_Sym(x) -> x | _ -> raise (Z3native.Exception "parameter is not a symbol") - (**The Sort value of the parameter.*) let get_sort ( x : parameter ) = match x with | P_Srt(x) -> x | _ -> raise (Z3native.Exception "parameter is not a sort") - (**The AST value of the parameter.*) let get_ast ( x : parameter ) = match x with | P_Ast(x) -> x | _ -> raise (Z3native.Exception "parameter is not an ast") - (**The FunctionDeclaration value of the parameter.*) let get_func_decl ( x : parameter ) = match x with | P_Fdl(x) -> x | _ -> raise (Z3native.Exception "parameter is not a func_decl") - (**The rational string value of the parameter.*) - let get_func_decl ( x : parameter ) = + let get_rational ( x : parameter ) = match x with | P_Rat(x) -> x | _ -> raise (Z3native.Exception "parameter is not a rational string") end - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = create_ndr ctx name domain range - (** - Creates a new function declaration. - *) let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range - (** - Creates a fresh function declaration with a name prefixed with . - - - *) let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = create_pdr ctx prefix domain range - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort ) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = create_ndr ctx name [||] range - (** - Creates a new constant function declaration. - *) let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = create_pdr ctx prefix [||] range - (** - Comparison operator. - @param a A func_decl - @param b A func_decl - @return True if and are from the same context - and represent the same func_decl; false otherwise. - *) let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || if (gnc a) != (gnc b) then false else (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) - (** - A string representations of the function declaration. - *) let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) - (** - Returns a unique identifier for the function declaration. - *) let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) - (** - The arity of the function declaration - *) let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) - (** - The size of the domain of the function declaration - - *) let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) - (** - The domain of the function declaration - *) let get_domain ( x : func_decl ) = let n = (get_domain_size x) in let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in Array.init n f - (** - The range of the function declaration - *) let get_range ( x : func_decl ) = sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) - (** - The kind of the function declaration. - *) let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) - (** - The name of the function declaration - *) let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) - (** - The number of parameters of the function declaration - *) let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) - (** - The parameters of the function declaration - *) let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> P_Ast (ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n - (** - Create expression that applies function to arguments. - @param args The arguments - *) - let apply ( x : func_decl ) ( args : expr array ) = expr_of_func_app (gc x) x args + let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.expr_of_func_app (gc x) x args end -(** - Parameter sets (of Solvers, Tactics, ...) - A Params objects represents a configuration in the form of symbol/value pairs. -*) -module Params = -struct - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) +and Params : +sig + type params = z3_native_object + module ParamDescrs : + sig + type param_descrs + val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + val get_names : param_descrs -> Symbol.symbol array + val get_size : param_descrs -> int + val to_string : param_descrs -> string + end + val add_bool : params -> Symbol.symbol -> bool -> unit + val add_int : params -> Symbol.symbol -> int -> unit + val add_double : params -> Symbol.symbol -> float -> unit + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + val add_s_bool : params -> string -> bool -> unit + val add_s_int : params -> string -> int -> unit + val add_s_double : params -> string -> float -> unit + val add_s_symbol : params -> string -> Symbol.symbol -> unit + val mk_params : context -> params + val to_string : params -> string +end = struct + type params = z3_native_object + module ParamDescrs = - struct - - let create ( ctx : context ) ( no : Z3native.ptr ) = + struct + type param_descrs = z3_native_object + + let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.param_descrs_inc_ref ; @@ -1180,79 +650,46 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params ) = Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) - (** Retrieve all names of parameters. *) let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) - - (** Retrieves a string representation of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) end - (** - Adds a parameter setting. - *) - let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_int ( x : params ) (name : symbol ) ( value : int ) = + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_double ( x : params ) ( name : symbol ) ( value : float ) = + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - (** - Adds a parameter setting. - *) let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = add_bool x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) let add_s_int ( x : params) ( name : string ) ( value : int ) = add_int x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = add_double x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) - let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = + + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - (** - Creates a new parameter set - *) let mk_params ( ctx : context ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; @@ -1262,21 +699,107 @@ struct (z3obj_create res) ; res - (** - A string representation of the parameter set. - *) let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end (** General expressions (terms) *) -module Expr = -struct +and Expr : +sig + type expr = Expr of AST.ast + val expr_of_ptr : context -> Z3native.ptr -> expr + val c_of_expr : expr -> context + val nc_of_expr : expr -> Z3native.ptr + val ptr_of_expr : expr -> Z3native.ptr + val expr_aton : expr array -> Z3native.ptr array + val ast_of_expr : expr -> AST.ast + val expr_of_ast : AST.ast -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr + val simplify : expr -> Params.params option -> expr + val get_simplify_help : context -> string + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + val get_func_decl : expr -> FuncDecl.func_decl + val get_bool_value : expr -> Z3enums.lbool + val get_num_args : expr -> int + val get_args : expr -> expr array + val update : expr -> expr array -> expr + val substitute : expr -> expr array -> expr array -> expr + val substitute_one : expr -> expr -> expr -> expr + val substitute_vars : expr -> expr array -> expr + val translate : expr -> context -> expr + val to_string : expr -> string + val is_numeral : expr -> bool + val is_well_sorted : expr -> bool + val get_sort : expr -> Sort.sort + val is_bool : expr -> bool + val is_const : expr -> bool + val is_true : expr -> bool + val is_false : expr -> bool + val is_eq : expr -> bool + val is_distinct : expr -> bool + val is_ite : expr -> bool + val is_and : expr -> bool + val is_or : expr -> bool + val is_iff : expr -> bool + val is_xor : expr -> bool + val is_not : expr -> bool + val is_implies : expr -> bool + val is_label : expr -> bool + val is_oeq : expr -> bool + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val mk_const_s : context -> string -> Sort.sort -> expr + val mk_const_f : context -> FuncDecl.func_decl -> expr + val mk_fresh_const : context -> string -> Sort.sort -> expr + val mk_app : context -> FuncDecl.func_decl -> expr array -> expr + val mk_numeral_string : context -> string -> Sort.sort -> expr + val mk_numeral_int : context -> int -> Sort.sort -> expr +end = struct + type expr = Expr of AST.ast + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + + let ast_of_expr e = match e with Expr(a) -> a + + let expr_aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in + Array.map f a + + let expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr = fun ctx f args -> + match f with FuncDecl.FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in + expr_of_ptr ctx o + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : params option ) = match p with + let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) @@ -1290,12 +813,12 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.create ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the expression is the true or false expression @@ -1477,7 +1000,7 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -1492,8 +1015,7 @@ struct Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : func_decl ) = - expr_of_func_app ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] (** Creates a fresh constant of sort and a @@ -1505,8 +1027,7 @@ struct (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = - expr_of_func_app ctx f args + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args (** Create a numeral of a given sort. @@ -1528,19 +1049,44 @@ struct expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end +open FuncDecl +open Expr + (** Boolean expressions *) module Boolean = -struct +struct + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (ast_of_ptr ctx no) in - BoolExpr(Expr(a)) + let a = (AST.ast_of_ptr ctx no) in + BoolExpr(Expr.Expr(a)) + + let bool_expr_of_expr e = + match e with Expr.Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = BoolSort(sort_of_ptr ctx no) - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (ptr_of_expr e) + let sort_of_bool_sort s = match s with BoolSort(x) -> x + + let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + + let expr_of_bool_expr e = match e with BoolExpr(x) -> x + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) let mk_sort ( ctx : context ) = BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) @@ -1548,7 +1094,7 @@ struct (** Create a Boolean constant. *) - let mk_const ( ctx : context ) ( name : symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) @@ -1638,17 +1184,38 @@ end (** Quantifier expressions *) module Quantifier = struct + type quantifier = Quantifier of expr + + let expr_of_quantifier e = match e with Quantifier(x) -> x + + let quantifier_of_expr e = + match e with Expr.Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) - + (** Quantifier patterns Patterns comprise a list of terms. The list should be non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Pattern = struct + module Pattern = + struct + type pattern = Pattern of ast + + let ast_of_pattern e = match e with Pattern(x) -> x + + let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) @@ -1692,7 +1259,7 @@ struct index. *) let get_index ( x : expr ) = - if not (AST.is_var (match x with Expr(a) -> a)) then + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) @@ -1723,7 +1290,7 @@ struct *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1736,7 +1303,7 @@ struct *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1781,7 +1348,7 @@ struct if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) (** Create a universal Quantifier. @@ -1802,14 +1369,14 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) else @@ -1817,21 +1384,21 @@ struct (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true @@ -1839,7 +1406,7 @@ struct (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) @@ -1847,14 +1414,14 @@ struct Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) else @@ -1862,21 +1429,21 @@ struct (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false @@ -1884,14 +1451,14 @@ struct (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1901,7 +1468,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1911,14 +1478,35 @@ end (** Functions to manipulate Array expressions *) module Array_ = struct + type array_sort = ArraySort of sort + type array_expr = ArrayExpr of expr - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let e = (expr_of_ptr ctx no) in ArrayExpr(e) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in - ArraySort(s) + ArraySort(s) + + let sort_of_array_sort s = match s with ArraySort(x) -> x + + let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + + let array_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + + let expr_of_array_expr e = match e with ArrayExpr(x) -> x let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) @@ -1932,7 +1520,7 @@ struct Create a new array sort. *) let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** Indicates whether the term is an array store. @@ -1979,16 +1567,15 @@ struct ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - + let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** @@ -2010,7 +1597,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) (** Array update. @@ -2029,7 +1616,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) + array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) (** Create a constant array. @@ -2040,7 +1627,7 @@ struct *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) + array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) (** Maps f on the argument arrays. @@ -2054,7 +1641,7 @@ struct *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in - expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) (** Access the array default value. @@ -2063,16 +1650,20 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) module Set = struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type set_sort = SetSort of sort + + let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in SetSort(s) + let sort_of_set_sort s = match s with SetSort(x) -> x + (** Indicates whether the term is set union *) @@ -2102,7 +1693,7 @@ struct Create a set type. *) let mk_sort ( ctx : context ) ( ty : sort ) = - create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. @@ -2169,14 +1760,24 @@ end (** Functions to manipulate Finite Domain expressions *) module FiniteDomain = struct + type finite_domain_sort = FiniteDomainSort of sort + + let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x + + let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - + (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( size : int ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in FiniteDomainSort(s) @@ -2210,15 +1811,24 @@ end (** Functions to manipulate Relation expressions *) module Relation = struct - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type relation_sort = RelationSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in RelationSort(s) + let sort_of_relation_sort s = match s with RelationSort(x) -> x + + let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - + (** Indicates whether the term is of a relation sort. @@ -2335,29 +1945,53 @@ struct (** The sorts of the columns of the relation sort. *) let get_column_sorts ( x : relation_sort ) = let n = get_arity x in - let f i = (create_sort (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in Array.init n f end (** Functions to manipulate Datatype expressions *) module Datatype = -struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = +struct + type datatype_sort = DatatypeSort of sort + type datatype_expr = DatatypeExpr of expr + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in DatatypeSort(s) + let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x + + let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + + let datatype_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + + let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - + (** Constructors *) module Constructor = struct + type constructor = z3_native_object + let _counts = Hashtbl.create 0 - let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2366,11 +2000,11 @@ struct raise (Z3native.Exception "Number of field names does not match number of sort refs") else let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) - (Symbol.gno recognizer) - n - (let f x = (Symbol.gno x) in (Array.map f field_names)) - (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - sort_refs) in + (Symbol.gno recognizer) + n + (let f x = (Symbol.gno x) in (Array.map f field_names)) + (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + sort_refs) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -2383,7 +2017,7 @@ struct no let get_n ( x : constructor ) = (Hashtbl.find _counts x) - + let rec constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in func_decl_of_ptr (z3obj_gc x) a @@ -2391,12 +2025,12 @@ struct let rec tester_decl ( x : constructor ) = let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in func_decl_of_ptr (z3obj_gc x) b - + let rec accessor_decls ( x : constructor ) = let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in let f y = func_decl_of_ptr (z3obj_gc x) y in Array.map f c - + (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2413,8 +2047,9 @@ struct (** Constructor list objects *) module ConstructorList = struct - - let create ( ctx : context ) ( c : constructor array ) = + type constructor_list = z3_native_object + + let create ( ctx : context ) ( c : Constructor.constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -2438,7 +2073,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2452,22 +2087,22 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in - create_sort ctx x + sort_of_ptr ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2475,17 +2110,17 @@ struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in - let f e = (ptr_of_ast (ConstructorList.create ctx e)) in + let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in let cla = (Array.map f c) in let f2 x = (Symbol.gno x) in let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in - let g e = (create_sort ctx e) in + let g e = (sort_of_ptr ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2522,17 +2157,21 @@ end (** Functions to manipulate Enumeration expressions *) module Enumeration = -struct +struct + type enum_sort = EnumSort of sort + let _constdecls = Hashtbl.create 0 let _testerdecls = Hashtbl.create 0 - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; res + let sort_of_enum_sort s = match s with EnumSort(x) -> x + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) @@ -2540,10 +2179,10 @@ struct (** Create a new enumeration sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( enum_names : symbol array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = let f x = Symbol.gno x in let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in - create_sort ctx a b c + sort_of_ptr ctx a b c (** Create a new enumeration sort. @@ -2561,14 +2200,16 @@ end (** Functions to manipulate List expressions *) module List_ = struct + type list_sort = ListSort of sort + let _nildecls = Hashtbl.create 0 let _is_nildecls = Hashtbl.create 0 let _consdecls = Hashtbl.create 0 let _is_consdecls = Hashtbl.create 0 let _headdecls = Hashtbl.create 0 let _taildecls = Hashtbl.create 0 - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in let res = ListSort(s) in Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; @@ -2578,16 +2219,18 @@ struct Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; res + + let sort_of_list_sort s = match s with ListSort(x) -> x let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - + + (** Create a new list sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( elem_sort : sort ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - create_sort ctx r a b c d e f + sort_of_ptr ctx r a b c d e f (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = @@ -2618,23 +2261,26 @@ end (** Functions to manipulate Tuple expressions *) module Tuple = struct - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type tuple_sort = TupleSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in TupleSort(s) + let sort_of_tuple_sort s = match s with TupleSort(x) -> x + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - + (** Create a new tuple sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( field_names : symbol array ) ( field_sorts : sort array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = let f x = Symbol.gno x in let f2 x = ptr_of_ast (ast_of_sort x) in let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in (* CMW: leaks a,b? *) - create_sort ctx r + sort_of_ptr ctx r (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = @@ -2651,13 +2297,144 @@ struct end (** Functions to manipulate arithmetic expressions *) -module Arithmetic = -struct - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> arith_sort + val expr_of_arith_expr : arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> arith_expr - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end + + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr array -> arith_expr + val mk_mul : context -> arith_expr array -> arith_expr + val mk_sub : context -> arith_expr array -> arith_expr + val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end = struct + type arith_sort = ArithSort of sort + type arith_expr = ArithExpr of expr + + let arith_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + + let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_expr_of_expr (expr_of_ptr ctx no) + + let sort_of_arith_sort s = match s with ArithSort(x) -> x + let expr_of_arith_expr e = match e with ArithExpr(x) -> x + + let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + + let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = arith_sort_of_sort (sort_of_ptr ctx no) let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) @@ -2667,16 +2444,72 @@ struct let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - module Integer = - struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (create_expr ctx no) + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + + let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + + let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_num_of_int_expr (int_expr_of_ptr ctx no) + + let arith_sort_of_int_sort s = match s with IntSort(x) -> x + let arith_expr_of_int_expr e = match e with IntExpr(x) -> x + let int_expr_of_int_num e = match e with IntNum(x) -> x + + let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + + let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) @@ -2687,11 +2520,11 @@ struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - + (** Create a new integer sort. *) let mk_sort ( ctx : context ) = - create_sort ctx (Z3native.mk_int_sort (context_gno ctx)) + int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) (** Retrieve the int value. *) let get_int ( x : int_num ) = @@ -2705,7 +2538,7 @@ struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : symbol ) = + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) (** @@ -2719,21 +2552,21 @@ struct The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) (** Create an integer numeral. @@ -2741,7 +2574,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) (** Coerce an integer to a real. @@ -2754,7 +2587,7 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) (** Create an bit bit-vector from the integer argument . @@ -2767,19 +2600,76 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - bitvec_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end - module Real = - struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (create_expr ctx no) + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : real_sort -> arith_sort + val real_sort_of_arith_sort : arith_sort -> real_sort + val arith_expr_of_real_expr : real_expr -> arith_expr + val real_expr_of_rat_num : rat_num -> real_expr + val real_expr_of_arith_expr : arith_expr -> real_expr + val rat_num_of_real_expr : real_expr -> rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let arith_sort_of_real_sort s = match s with RealSort(x) -> x + let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + let real_expr_of_rat_num e = match e with RatNum(x) -> x + + let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + + let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + + let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + rat_num_of_real_expr (real_expr_of_ptr ctx no) + + let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + + let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) @@ -2790,19 +2680,19 @@ struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - + (** Create a real sort. *) let mk_sort ( ctx : context ) = - create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) + real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - Integer.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - Integer.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2813,7 +2703,7 @@ struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : symbol ) = + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) (** Creates a real constant. *) @@ -2832,7 +2722,7 @@ struct if (den == 0) then raise (Z3native.Exception "Denominator is zero") else - create_num ctx (Z3native.mk_real (context_gno ctx) num den) + rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2840,7 +2730,7 @@ struct @return A Term with value and sort Real *) let mk_numeral_s ( ctx : context ) ( v : string ) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) (** Create a real numeral. @@ -2849,11 +2739,11 @@ struct @return A Term with value and sort Real *) let mk_numeral_i ( ctx : context ) ( v : int ) = - create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) (** Coerce a real to an integer. @@ -2863,18 +2753,39 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end - module AlgebraicNumber = - struct - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x + + let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + + let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - + (** Return a upper bound for a given real algebraic number. @@ -2884,7 +2795,7 @@ struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) (** Return a lower bound for the given real algebraic number. @@ -2894,7 +2805,7 @@ struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - Real.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -3056,38 +2967,186 @@ struct Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end (** Functions to manipulate bit-vector expressions *) -module BitVector = -struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + val mk_sort : context -> int -> bitvec_sort + val is_bv : Expr.expr -> bool + val is_bv_numeral : Expr.expr -> bool + val is_bv_bit1 : Expr.expr -> bool + val is_bv_bit0 : Expr.expr -> bool + val is_bv_uminus : Expr.expr -> bool + val is_bv_add : Expr.expr -> bool + val is_bv_sub : Expr.expr -> bool + val is_bv_mul : Expr.expr -> bool + val is_bv_sdiv : Expr.expr -> bool + val is_bv_udiv : Expr.expr -> bool + val is_bv_SRem : Expr.expr -> bool + val is_bv_urem : Expr.expr -> bool + val is_bv_smod : Expr.expr -> bool + val is_bv_sdiv0 : Expr.expr -> bool + val is_bv_udiv0 : Expr.expr -> bool + val is_bv_srem0 : Expr.expr -> bool + val is_bv_urem0 : Expr.expr -> bool + val is_bv_smod0 : Expr.expr -> bool + val is_bv_ule : Expr.expr -> bool + val is_bv_sle : Expr.expr -> bool + val is_bv_uge : Expr.expr -> bool + val is_bv_sge : Expr.expr -> bool + val is_bv_ult : Expr.expr -> bool + val is_bv_slt : Expr.expr -> bool + val is_bv_ugt : Expr.expr -> bool + val is_bv_sgt : Expr.expr -> bool + val is_bv_and : Expr.expr -> bool + val is_bv_or : Expr.expr -> bool + val is_bv_not : Expr.expr -> bool + val is_bv_xor : Expr.expr -> bool + val is_bv_nand : Expr.expr -> bool + val is_bv_nor : Expr.expr -> bool + val is_bv_xnor : Expr.expr -> bool + val is_bv_concat : Expr.expr -> bool + val is_bv_signextension : Expr.expr -> bool + val is_bv_zeroextension : Expr.expr -> bool + val is_bv_extract : Expr.expr -> bool + val is_bv_repeat : Expr.expr -> bool + val is_bv_reduceor : Expr.expr -> bool + val is_bv_reduceand : Expr.expr -> bool + val is_bv_comp : Expr.expr -> bool + val is_bv_shiftleft : Expr.expr -> bool + val is_bv_shiftrightlogical : Expr.expr -> bool + val is_bv_shiftrightarithmetic : Expr.expr -> bool + val is_bv_rotateleft : Expr.expr -> bool + val is_bv_rotateright : Expr.expr -> bool + val is_bv_rotateleftextended : Expr.expr -> bool + val is_bv_rotaterightextended : Expr.expr -> bool + val is_int_to_bv : Expr.expr -> bool + val is_bv_to_int : Expr.expr -> bool + val is_bv_carry : Expr.expr -> bool + val is_bv_xor3 : Expr.expr -> bool + val get_size : bitvec_sort -> int + val get_int : bitvec_num -> int + val to_string : bitvec_num -> string + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> bitvec_expr + val mk_not : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_numeral : context -> string -> int -> bitvec_num +end = struct + type bitvec_sort = BitVecSort of sort + type bitvec_expr = BitVecExpr of expr + type bitvec_num = BitVecNum of bitvec_expr + + let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x + + let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + + let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = bitvec_sort_of_sort (sort_of_ptr ctx no) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let bitvec_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + + let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = bitvec_expr_of_expr (expr_of_ptr ctx no) - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (create_expr ctx no) + let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + + let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) + + let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x + let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) @@ -3098,13 +3157,13 @@ struct let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - + (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - create_sort ctx (Z3native.mk_bv_sort (context_gno ctx) size) + bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3391,8 +3450,8 @@ struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) (** Creates a bit-vector constant. @@ -3426,70 +3485,70 @@ struct The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3501,7 +3560,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3516,7 +3575,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3526,7 +3585,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3538,7 +3597,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3547,7 +3606,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3555,7 +3614,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than @@ -3563,7 +3622,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) (** Unsigned less-than or equal to. @@ -3571,7 +3630,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than or equal to. @@ -3579,7 +3638,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater than or equal to. @@ -3587,7 +3646,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater than or equal to. @@ -3595,7 +3654,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater-than. @@ -3603,7 +3662,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater-than. @@ -3611,7 +3670,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) (** Bit-vector concatenation. @@ -3622,7 +3681,7 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3633,7 +3692,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3643,7 +3702,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3654,7 +3713,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3662,7 +3721,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3677,8 +3736,8 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - + bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + (** Logical shift right @@ -3692,7 +3751,7 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3708,7 +3767,7 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3717,7 +3776,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3726,7 +3785,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3735,7 +3794,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3745,7 +3804,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3763,7 +3822,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3771,7 +3830,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3779,7 +3838,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3787,7 +3846,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3795,7 +3854,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3803,7 +3862,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3811,7 +3870,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3819,7 +3878,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3827,7 +3886,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a bit-vector numeral. @@ -3836,7 +3895,7 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) + bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) end (** Functions to manipulate proof expressions *) @@ -4321,7 +4380,8 @@ end tactics and solvers. *) module Goal = struct - + type goal = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; @@ -4330,7 +4390,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** The precision of the goal. @@ -4359,7 +4419,7 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () @@ -4381,7 +4441,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f @@ -4401,7 +4461,7 @@ struct create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : params option ) = + let simplify ( x : goal ) ( p : Params.params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with @@ -4441,7 +4501,8 @@ end A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - + type model = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; @@ -4450,7 +4511,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Function interpretations @@ -4459,7 +4520,8 @@ struct *) module FuncInterp = struct - + type func_interp = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; @@ -4468,7 +4530,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Function interpretations entries @@ -4476,7 +4538,8 @@ struct *) module FuncEntry = struct - + type func_entry = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; @@ -4485,7 +4548,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Return the (symbolic) value of this entry. @@ -4677,7 +4740,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4699,7 +4762,8 @@ end *) module Probe = struct - + type probe = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; @@ -4708,14 +4772,14 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Execute the probe over the goal. A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : goal) = + let apply ( x : probe ) ( g : Goal.goal ) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** @@ -4820,7 +4884,8 @@ end *) module Tactic = struct - + type tactic = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; @@ -4829,7 +4894,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Tactic application results @@ -4837,7 +4902,8 @@ struct tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct - + type apply_result = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; @@ -4846,7 +4912,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = @@ -4866,7 +4932,7 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) @@ -4878,10 +4944,10 @@ struct (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) @@ -4949,14 +5015,14 @@ struct If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** @@ -4981,7 +5047,7 @@ struct (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : probe ) = + let fail_if ( ctx : context ) ( p : Probe.probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** @@ -4994,14 +5060,14 @@ struct (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p (** @@ -5029,7 +5095,9 @@ end (** Solvers *) module Solver = struct - + type solver = z3_native_object + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; @@ -5038,7 +5106,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" @@ -5048,7 +5116,8 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = struct - + type statistics = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; @@ -5066,7 +5135,13 @@ struct *) module Entry = struct - + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -5086,7 +5161,7 @@ struct m_float = v } in res - + (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key @@ -5142,11 +5217,9 @@ struct let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** - The value of a particular statistical counter. - *) + (** The value of a particular statistical counter. *) let get ( x : statistics ) ( key : string ) = - let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in Array.fold_left f None (get_entries x) end @@ -5158,14 +5231,14 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( p : params )= + let set_parameters ( x : solver ) ( p : Params.params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5196,7 +5269,7 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) @@ -5213,7 +5286,7 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else @@ -5232,14 +5305,14 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5247,9 +5320,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f (** @@ -5259,12 +5332,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array) = + let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - let f x = (ptr_of_expr (expr_of_bool_expr x)) in + let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) in match r with @@ -5306,7 +5379,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5330,7 +5403,7 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : symbol option ) = + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) @@ -5354,7 +5427,7 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : tactic ) = + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** @@ -5366,7 +5439,9 @@ end (** Fixedpoint solving *) module Fixedpoint = -struct +struct + type fixedpoint = z3_native_object + let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; @@ -5375,7 +5450,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_create res) ; res - + (** A string that describes all available fixedpoint solver parameters. @@ -5386,19 +5461,19 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : params )= + let set_params ( x : fixedpoint ) ( p : Params.params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () @@ -5412,7 +5487,7 @@ struct (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) @@ -5429,11 +5504,11 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : bool_expr ) = + let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN (** Query the fixedpoint solver. @@ -5444,9 +5519,9 @@ struct let query_r ( x : fixedpoint ) ( relations : func_decl array ) = let f x = ptr_of_ast (ast_of_func_decl x) in match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN (** Creates a backtracking point. @@ -5467,7 +5542,7 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) (** @@ -5518,33 +5593,33 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = let f2 x = (Symbol.gno x) in Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - let f x = ptr_of_expr (expr_of_bool_expr x) in + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = + let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** @@ -5628,9 +5703,9 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (let f x = ptr_of_expr (expr_of_bool_expr x) in (Array.map f assumptions)) + (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) (Boolean.gno formula) (** @@ -5642,7 +5717,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5662,7 +5737,7 @@ struct Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5688,7 +5763,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f @@ -5702,7 +5777,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f (** @@ -5737,7 +5812,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5745,19 +5820,19 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) - cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5765,13 +5840,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) - cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) end @@ -5818,23 +5893,3 @@ let get_global_param ( id : string ) = *) let global_param_reset_all = Z3native.global_param_reset_all - - - -(* - -(** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. -*) - public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - - internal Z3native.error_handler m_n_err_handler = null; - - internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) - - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - -*) From 9d15c958562df323be46cd0465036fde21d1765e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 19:49:09 +0000 Subject: [PATCH 307/646] ML API: proper use of datatype API for list/enum/constructor. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 47 ++++++++++++++++++++------------------------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index abcefa4af..96fd0a55d 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.mli -hide Z3 + ocamldoc -html -d doc -I _build -sort *.mli -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c261fce05..344e542f7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2159,15 +2159,10 @@ end module Enumeration = struct type enum_sort = EnumSort of sort - - let _constdecls = Hashtbl.create 0 - let _testerdecls = Hashtbl.create 0 let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in - Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; - Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; res let sort_of_enum_sort s = match s with EnumSort(x) -> x @@ -2191,33 +2186,27 @@ struct mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls ( x : enum_sort ) = Hashtbl.find _constdecls x + let get_const_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + Array.init n f (** The test predicates for the constants in the enumeration. *) - let get_tester_decls ( x : enum_sort ) = Hashtbl.find _testerdecls x + let get_tester_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + Array.init n f + end (** Functions to manipulate List expressions *) module List_ = struct type list_sort = ListSort of sort - - let _nildecls = Hashtbl.create 0 - let _is_nildecls = Hashtbl.create 0 - let _consdecls = Hashtbl.create 0 - let _is_consdecls = Hashtbl.create 0 - let _headdecls = Hashtbl.create 0 - let _taildecls = Hashtbl.create 0 let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in let res = ListSort(s) in - Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; - Hashtbl.add _is_nildecls res (func_decl_of_ptr ctx is_nildecl) ; - Hashtbl.add _consdecls res (func_decl_of_ptr ctx consdecl) ; - Hashtbl.add _is_consdecls res (func_decl_of_ptr ctx is_consdecl) ; - Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; - Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; res let sort_of_list_sort s = match s with ListSort(x) -> x @@ -2237,22 +2226,28 @@ struct mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl ( x : list_sort ) = (Hashtbl.find _nildecls x) + let get_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl ( x : list_sort ) = (Hashtbl.find _is_nildecls x) + let get_is_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) (** The declaration of the cons function of this list sort. *) - let get_cons_decl ( x : list_sort ) = (Hashtbl.find _consdecls x) + let get_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl ( x : list_sort ) = (Hashtbl.find _is_consdecls x) + let get_is_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) (** The declaration of the head function of this list sort. *) - let get_head_decl ( x : list_sort ) = (Hashtbl.find _headdecls x) + let get_head_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) (** The declaration of the tail function of this list sort. *) - let get_tail_decl ( x : list_sort ) = (Hashtbl.find _taildecls x) + let get_tail_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) (** The empty list. *) let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] From 576591086df79e48c7316a23ca2b30eeae69c8ca Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 22:07:18 +0000 Subject: [PATCH 308/646] ML API savepoint Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2595 +--------------------------------------------- 1 file changed, 50 insertions(+), 2545 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 344e542f7..b1e40fcac 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -338,7 +338,7 @@ struct else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr + let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr let unwrap_ast ( x : ast ) = (z3obj_gno x) end @@ -744,6 +744,7 @@ sig val is_not : expr -> bool val is_implies : expr -> bool val is_label : expr -> bool + val is_label_lit : expr -> bool val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr @@ -794,257 +795,97 @@ end = struct let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in expr_of_ptr ctx o - (** - Returns a simplified version of the expression. - @param p A set of parameters to configure the simplifier - - *) let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) - (** - a string describing all available parameters to Expr.Simplify. - *) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) - (** - Retrieves parameter descriptions for simplifier. - *) let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - - (** - The function declaration of the function that is applied in this expression. - *) let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the expression is the true or false expression - or something else (L_UNDEF). - *) let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) - (** - The number of arguments of the expression. - *) let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) - (** - The arguments of the expression. - *) let get_args ( x : expr ) = let n = (get_num_args x) in let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in Array.init n f - (** - Update the arguments of the expression using the arguments - The number of new arguments should coincide with the current number of arguments. - *) let update ( x : expr ) args = if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) - (** - Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. - - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. - *) let substitute ( x : expr ) from to_ = if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) - (** - Substitute every occurrence of from in the expression with to. - - *) let substitute_one ( x : expr ) from to_ = substitute ( x : expr ) [| from |] [| to_ |] - (** - Substitute the free variables in the expression with the expressions in - - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. - *) let substitute_vars ( x : expr ) to_ = expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) - (** - Translates (copies) the term to the Context . - @param ctx A context - @return A copy of the term which is associated with - *) let translate ( x : expr ) to_ctx = if (c_of_expr x) == to_ctx then x else expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) - (** - Returns a string representation of the expression. - *) let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) - (** - Indicates whether the term is a numeral - *) let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. - *) let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) - (** - The Sort of the term. - *) let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the term has Boolean sort. - *) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (Z3native.is_eq_sort (nc_of_expr x) (Z3native.mk_bool_sort (nc_of_expr x)) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) - (** - Indicates whether the term represents a constant. - *) let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - - (** - Indicates whether the term is the constant true. - *) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - - (** - Indicates whether the term is the constant false. - *) let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - - (** - Indicates whether the term is an equality predicate. - *) let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - - (** - Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). - *) let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - - (** - Indicates whether the term is a ternary if-then-else term - *) let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - - (** - Indicates whether the term is an n-ary conjunction - *) let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - - (** - Indicates whether the term is an n-ary disjunction - *) let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - - (** - Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) - *) let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - - (** - Indicates whether the term is an exclusive or - *) let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - - (** - Indicates whether the term is a negation - *) let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - - (** - Indicates whether the term is an implication - *) let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - - (** - Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. - *) let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - - (** - Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) - *) - - (** - Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. - *) + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - (** - Creates a new Constant of sort and named . - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) - - (** - Creates a new Constant of sort and named . - *) let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range - - (** - Creates a constant from the func_decl . - @param f An expression of a 0-arity function - *) let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] - (** - Creates a fresh constant of sort and a - name prefixed with . - *) let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - (** - Create a new function application. - *) let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args - (** - Create a numeral of a given sort. - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - *) let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) - (** - Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end @@ -1052,7 +893,6 @@ end open FuncDecl open Expr -(** Boolean expressions *) module Boolean = struct type bool_sort = BoolSort of Sort.sort @@ -1091,97 +931,53 @@ struct let mk_sort ( ctx : context ) = BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) - (** - Create a Boolean constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) - (** - Create a Boolean constant. - *) let mk_const_s ( ctx : context ) ( name : string ) = mk_const ctx (Symbol.mk_string ctx name) - (** - The true Term. - *) let mk_true ( ctx : context ) = bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) - (** - The false Term. - *) let mk_false ( ctx : context ) = bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) - (** - Creates a Boolean value. - *) let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx - (** - Creates the equality = . - *) let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) - (** - Creates a distinct term. - *) let mk_distinct ( ctx : context ) ( args : expr array ) = bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Mk an expression representing not(a). - *) let mk_not ( ctx : context ) ( a : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - (** - Create an expression representing an if-then-else: ite(t1, t2, t3). - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - (** - Create an expression representing t1 iff t2. - *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing t1 -> t2. - *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing t1 xor t2. - *) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing the AND of args - *) let mk_and ( ctx : context ) ( args : bool_expr array ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) - (** - Create an expression representing the OR of args - *) let mk_or ( ctx : context ) ( args : bool_expr array ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) end -(** Quantifier expressions *) + module Quantifier = struct type quantifier = Quantifier of expr @@ -1200,12 +996,6 @@ struct let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) module Pattern = struct type pattern = Pattern of ast @@ -1220,155 +1010,68 @@ struct let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - (** - The number of terms in the pattern. - *) let get_num_terms ( x : pattern ) = Z3native.get_pattern_num_terms (gnc x) (gno x) - (** - The terms in the pattern. - *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f - (** - A string representation of the pattern. - *) let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) end - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - *) let get_index ( x : expr ) = if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) - (** - Indicates whether the quantifier is universal. - *) let is_universal ( x : quantifier ) = Z3native.is_quantifier_forall (gnc x) (gno x) - (** - Indicates whether the quantifier is existential. - *) let is_existential ( x : quantifier ) = not (is_universal x) - (** - The weight of the quantifier. - *) let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) - (** - The number of patterns. - *) let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) - (** - The patterns. - *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f - (** - The number of no-patterns. - *) let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) - (** - The no-patterns. - *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f - (** - The number of bound variables. - *) let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) - (** - The symbols for the bound variables. - *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in Array.init n f - (** - The sorts of the bound variables. - *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f - (** - The body of the quantifier. - *) let get_body ( x : quantifier ) = Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) - (** - Creates a new bound variable. - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - *) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - (** - Create a quantifier pattern. - *) let mk_pattern ( ctx : context ) ( terms : expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) - (** - Create a universal Quantifier. - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. - - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - *) let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") @@ -1390,9 +1093,6 @@ struct (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - (** - Create a universal Quantifier. - *) let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true @@ -1410,10 +1110,6 @@ struct (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) - (** - Create an existential Quantifier. - - *) let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") @@ -1435,9 +1131,6 @@ struct (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - (** - Create an existential Quantifier. - *) let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false @@ -1455,19 +1148,12 @@ struct (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) - (** - Create a Quantifier. - *) let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - - (** - Create a Quantifier. - *) let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id @@ -1475,7 +1161,7 @@ struct mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id end -(** Functions to manipulate Array expressions *) + module Array_ = struct type array_sort = ArraySort of sort @@ -1516,144 +1202,46 @@ struct let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - (** - Create a new array sort. - *) let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - (** - Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. - *) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - - (** - Indicates whether the term is an array select. - *) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - - (** - Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. - *) let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - - (** - Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. - *) let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - - (** - Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. - *) let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - - (** - Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. - *) let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) - - (** - Indicates whether the term is of an array sort. - *) let is_array ( x : expr ) = (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) - (** The domain of the array sort. *) let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - - (** The range of the array sort. *) let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - (** - Create an array constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) - (** - Create an array constant. - *) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range - (** - Array read. - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - - - *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) - - (** - Array update. - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - - - *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + + let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) - (** - Create a constant array. - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - - - *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) - (** - Maps f on the argument arrays. - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - - - - *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) - (** - Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end -(** Functions to manipulate Set expressions *) + module Set = struct type set_sort = SetSort of sort @@ -1664,100 +1252,49 @@ struct let sort_of_set_sort s = match s with SetSort(x) -> x - (** - Indicates whether the term is set union - *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - - (** - Indicates whether the term is set intersection - *) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - - (** - Indicates whether the term is set difference - *) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - - (** - Indicates whether the term is set complement - *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - - (** - Indicates whether the term is set subset - *) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) - - (** - Create a set type. - *) let mk_sort ( ctx : context ) ( ty : sort ) = set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - (** - Create an empty set. - *) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + + let mk_empty ( ctx : context ) ( domain : sort ) = (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) - (** - Create the full set. - *) let mk_full ( ctx : context ) ( domain : sort ) = expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) - (** - Add an element to the set. - *) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - (** - Remove an element from a set. - *) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - (** - Take the union of a list of sets. - *) let mk_union ( ctx : context ) ( args : expr array ) = expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Take the intersection of a list of sets. - *) let mk_intersection ( ctx : context ) ( args : expr array ) = expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Take the difference between two sets. - *) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) - (** - Take the complement of a set. - *) let mk_complement ( ctx : context ) ( arg : expr ) = expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) - (** - Check for set membership. - *) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) - (** - Check for subsetness of sets. - *) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) end -(** Functions to manipulate Finite Domain expressions *) + module FiniteDomain = struct type finite_domain_sort = FiniteDomainSort of sort @@ -1774,41 +1311,28 @@ struct let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - (** - Create a new finite domain sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in FiniteDomainSort(s) - (** - Create a new finite domain sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = mk_sort ctx (Symbol.mk_string ctx name) size - (** - Indicates whether the term is of an array sort. - *) let is_finite_domain ( x : expr ) = let nc = (nc_of_expr x) in (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) - (** - Indicates whether the term is a less than predicate over a finite domain. - *) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - (** The size of the finite domain sort. *) let get_size ( x : finite_domain_sort ) = let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end -(** Functions to manipulate Relation expressions *) + module Relation = struct type relation_sort = RelationSort of sort @@ -1830,119 +1354,27 @@ struct let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - (** - Indicates whether the term is of a relation sort. - *) let is_relation ( x : expr ) = let nc = (nc_of_expr x) in ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) - (** - Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. - *) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - - (** - Indicates whether the term is an empty relation - *) let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - - (** - Indicates whether the term is a test for the emptiness of a relation - *) let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - - (** - Indicates whether the term is a relational join - *) let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - - (** - Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. - *) let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - - (** - Indicates whether the term is the widening of two relations - The function takes two arguments. - *) let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - - (** - Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. - *) let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - - (** - Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. - *) let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - - (** - Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. - *) let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - - (** - Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. - *) let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - - (** - Indicates whether the term is the complement of a relation - *) let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - - (** - Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. - *) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - - (** - Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind - to perform destructive updates to the first argument. - *) let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - (** The arity of the relation sort. *) let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) - (** The sorts of the columns of the relation sort. *) let get_column_sorts ( x : relation_sort ) = let n = get_arity x in let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in @@ -1950,7 +1382,7 @@ struct end -(** Functions to manipulate Datatype expressions *) + module Datatype = struct type datatype_sort = DatatypeSort of sort @@ -1983,14 +1415,10 @@ struct let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - - (** Constructors *) module Constructor = struct type constructor = z3_native_object - let _counts = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then @@ -2009,42 +1437,29 @@ struct m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - Hashtbl.add _counts no n ; (z3obj_sno no ctx ptr) ; (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; no + + let get_num_fields ( x : constructor ) = Z3native.get_arity (z3obj_gnc x) (z3obj_gno x) - let get_n ( x : constructor ) = (Hashtbl.find _counts x) - - let rec constructor_decl ( x : constructor ) = - let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let get_constructor_decl ( x : constructor ) = + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in func_decl_of_ptr (z3obj_gc x) a - let rec tester_decl ( x : constructor ) = - let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let get_tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in func_decl_of_ptr (z3obj_gc x) b - - let rec accessor_decls ( x : constructor ) = - let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + + let get_accessor_decls ( x : constructor ) = + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in let f y = func_decl_of_ptr (z3obj_gc x) y in Array.map f c - (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = get_n x - - (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = constructor_decl x - - (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = tester_decl x - - (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = accessor_decls x end - (** Constructor list objects *) module ConstructorList = struct type constructor_list = z3_native_object @@ -2062,54 +1477,21 @@ struct res end - (* DATATYPES *) - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - - (** - Create a new datatype sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in sort_of_ptr ctx x - (** - Create a new datatype sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors - (** - Create mutually recursive datatypes. - @param names names of datatype sorts - @param c list of constructors, one list per sort. - *) let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in @@ -2119,7 +1501,6 @@ struct let g e = (sort_of_ptr ctx e) in (Array.map g r) - (** Create mutually recursive data-types. *) let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( @@ -2128,22 +1509,18 @@ struct ) c - (** The number of constructors of the datatype sort. *) let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) - (** The range of the array sort. *) let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f - (** The recognizers. *) let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f - (** The constructor accessors. *) let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( @@ -2155,7 +1532,7 @@ struct Array.init n f end -(** Functions to manipulate Enumeration expressions *) + module Enumeration = struct type enum_sort = EnumSort of sort @@ -2171,27 +1548,19 @@ struct let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - (** - Create a new enumeration sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = let f x = Symbol.gno x in let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in sort_of_ptr ctx a b c - (** - Create a new enumeration sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - (** The function declarations of the constants in the enumeration. *) let get_const_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in Array.init n f - (** The test predicates for the constants in the enumeration. *) let get_tester_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in @@ -2199,7 +1568,7 @@ struct end -(** Functions to manipulate List expressions *) + module List_ = struct type list_sort = ListSort of sort @@ -2214,46 +1583,36 @@ struct let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - - (** Create a new list sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in sort_of_ptr ctx r a b c d e f - (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort - (** The declaration of the nil function of this list sort. *) let get_nil_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) - (** The declaration of the isNil function of this list sort. *) let get_is_nil_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) - (** The declaration of the cons function of this list sort. *) let get_cons_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) - (** The declaration of the isCons function of this list sort. *) let get_is_cons_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) - (** The declaration of the head function of this list sort. *) let get_head_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) - (** The declaration of the tail function of this list sort. *) let get_tail_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - (** The empty list. *) let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] end -(** Functions to manipulate Tuple expressions *) + module Tuple = struct type tuple_sort = TupleSort of sort @@ -2268,30 +1627,24 @@ struct let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - - (** Create a new tuple sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = let f x = Symbol.gno x in let f2 x = ptr_of_ast (ast_of_sort x) in - let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in - (* CMW: leaks a,b? *) + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in sort_of_ptr ctx r - (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) - (** The number of fields in the tuple. *) let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) - (** The field declarations. *) let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end -(** Functions to manipulate arithmetic expressions *) + module rec Arithmetic : sig type arith_sort = ArithSort of Sort.sort @@ -2516,84 +1869,37 @@ end = struct let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - - (** Create a new integer sort. *) let mk_sort ( ctx : context ) = int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - (** - Creates an integer constant. - *) let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - (** - Creates an integer constant. - *) let mk_int_const_s ( ctx : context ) ( name : string ) = mk_int_const ctx (Symbol.mk_string ctx name) - (** - Create an expression representing t1 mod t2. - The arguments must have int type. - *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) - (** - Create an expression representing t1 rem t2. - The arguments must have int type. - *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - (** - Create an integer numeral. - @param v A string representing the Term value in decimal notation. - *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Create an integer numeral. - @param v value of the numeral. - @return A Term with value and sort Integer - *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - *) let mk_int2real ( ctx : context ) ( t : int_expr ) = Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) - (** - Create an bit bit-vector from the integer argument . - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end @@ -2677,76 +1983,41 @@ end = struct let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - (** Create a real sort. *) let mk_sort ( ctx : context ) = real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) - (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) let to_decimal_string ( x : rat_num ) ( precision : int ) = Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - (** Returns a string representation of the numeral. *) let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - (** Creates a real constant. *) let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - (** Creates a real constant. *) let mk_real_const_s ( ctx : context ) ( name : string ) = mk_real_const ctx (Symbol.mk_string ctx name) - (** - Create a real from a fraction. - - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - *) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then raise (Z3native.Exception "Denominator is zero") else rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) - (** - Create a real numeral. - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - *) let mk_numeral_s ( ctx : context ) ( v : string ) = rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Create a real numeral. - - @param v value of the numeral. - @return A Term with value and sort Real - *) let mk_numeral_i ( ctx : context ) ( v : int ) = rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) - (** - Coerce a real to an integer. - - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - *) let mk_real2int ( ctx : context ) ( t : real_expr ) = Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end @@ -2782,208 +2053,97 @@ end = struct let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) let to_upper ( x : algebraic_num ) ( precision : int ) = Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) let to_lower ( x : algebraic_num ) precision = Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) let to_decimal_string ( x : algebraic_num ) ( precision : int ) = Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) end - (** - Indicates whether the term is of integer sort. - *) let is_int ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) - (** - Indicates whether the term is an arithmetic numeral. - *) let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - (** - Indicates whether the term is a less-than-or-equal - *) let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - (** - Indicates whether the term is a greater-than-or-equal - *) let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - (** - Indicates whether the term is a less-than - *) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - (** - Indicates whether the term is a greater-than - *) let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - (** - Indicates whether the term is addition (binary) - *) let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - (** - Indicates whether the term is subtraction (binary) - *) let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - (** - Indicates whether the term is a unary minus - *) let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - (** - Indicates whether the term is multiplication (binary) - *) let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - (** - Indicates whether the term is division (binary) - *) let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - (** - Indicates whether the term is integer division (binary) - *) let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - (** - Indicates whether the term is remainder (binary) - *) let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - (** - Indicates whether the term is modulus (binary) - *) let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - (** - Indicates whether the term is a coercion of integer to real (unary) - *) let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - (** - Indicates whether the term is a coercion of real to integer (unary) - *) let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - (** - Indicates whether the term is a check that tests whether a real is integral (unary) - *) let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - (** - Indicates whether the term is of sort real. - *) let is_real ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) - - (** - Indicates whether the term is an integer numeral. - *) let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - (** - Indicates whether the term is a real numeral. - *) let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - (** - Indicates whether the term is an algebraic number - *) let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) - (** - Create an expression representing t[0] + t[1] + .... - *) let mk_add ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing t[0] * t[1] * .... - *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing t[0] - t[1] - .... - *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing -t. - *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) - (** - Create an expression representing t1 / t2. - *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 ^ t2. - *) let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 < t2 - *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 <= t2 - *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 > t2 - *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 >= t2 - *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end -(** Functions to manipulate bit-vector expressions *) + and BitVector : sig type bitvec_sort = BitVecSort of Sort.sort @@ -3089,8 +2249,10 @@ sig val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr @@ -3154,1225 +2316,213 @@ end = struct let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - (** - Create a new bit-vector sort. - *) let mk_sort ( ctx : context ) size = bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) - - (** - Indicates whether the terms is of bit-vector sort. - *) let is_bv ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) - - (** - Indicates whether the term is a bit-vector numeral - *) let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - - (** - Indicates whether the term is a one-bit bit-vector with value one - *) let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - - (** - Indicates whether the term is a one-bit bit-vector with value zero - *) let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - - (** - Indicates whether the term is a bit-vector unary minus - *) let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - - (** - Indicates whether the term is a bit-vector addition (binary) - *) let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - - (** - Indicates whether the term is a bit-vector subtraction (binary) - *) let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - - (** - Indicates whether the term is a bit-vector multiplication (binary) - *) let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - - (** - Indicates whether the term is a bit-vector signed division (binary) - *) let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - - (** - Indicates whether the term is a bit-vector unsigned division (binary) - *) let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - - (** - Indicates whether the term is a bit-vector signed remainder (binary) - *) let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - - (** - Indicates whether the term is a bit-vector unsigned remainder (binary) - *) let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - - (** - Indicates whether the term is a bit-vector signed modulus - *) let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - - (** - Indicates whether the term is a bit-vector signed division by zero - *) let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - - (** - Indicates whether the term is a bit-vector unsigned division by zero - *) let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - - (** - Indicates whether the term is a bit-vector signed remainder by zero - *) let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - - (** - Indicates whether the term is a bit-vector unsigned remainder by zero - *) let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - - (** - Indicates whether the term is a bit-vector signed modulus by zero - *) let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - - (** - Indicates whether the term is an unsigned bit-vector less-than-or-equal - *) let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - - (** - Indicates whether the term is a signed bit-vector less-than-or-equal - *) let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - - (** - Indicates whether the term is an unsigned bit-vector greater-than-or-equal - *) let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - - (** - Indicates whether the term is a signed bit-vector greater-than-or-equal - *) let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - - (** - Indicates whether the term is an unsigned bit-vector less-than - *) let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - - (** - Indicates whether the term is a signed bit-vector less-than - *) let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - - (** - Indicates whether the term is an unsigned bit-vector greater-than - *) let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - - (** - Indicates whether the term is a signed bit-vector greater-than - *) let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - - (** - Indicates whether the term is a bit-wise AND - *) let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - - (** - Indicates whether the term is a bit-wise OR - *) let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - - (** - Indicates whether the term is a bit-wise NOT - *) let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - - (** - Indicates whether the term is a bit-wise XOR - *) let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - - (** - Indicates whether the term is a bit-wise NAND - *) let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - - (** - Indicates whether the term is a bit-wise NOR - *) let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - - (** - Indicates whether the term is a bit-wise XNOR - *) let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - - (** - Indicates whether the term is a bit-vector concatenation (binary) - *) let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - - (** - Indicates whether the term is a bit-vector sign extension - *) let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - - (** - Indicates whether the term is a bit-vector zero extension - *) let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - - (** - Indicates whether the term is a bit-vector extraction - *) let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - - (** - Indicates whether the term is a bit-vector repetition - *) let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - - (** - Indicates whether the term is a bit-vector reduce OR - *) let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - - (** - Indicates whether the term is a bit-vector reduce AND - *) let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - - (** - Indicates whether the term is a bit-vector comparison - *) let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - - (** - Indicates whether the term is a bit-vector shift left - *) let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - - (** - Indicates whether the term is a bit-vector logical shift right - *) let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - - (** - Indicates whether the term is a bit-vector arithmetic shift left - *) let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - - (** - Indicates whether the term is a bit-vector rotate left - *) let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - - (** - Indicates whether the term is a bit-vector rotate right - *) let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - - (** - Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. - *) let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - - (** - Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. - *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - - (** - Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - *) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - - (** - Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - *) let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - - (** - Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) - *) let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - - (** - Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) - *) let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - - (** The size of a bit-vector sort. *) let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - - (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - (** - Creates a bit-vector constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) - - (** - Creates a bit-vector constant. - *) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = mk_const ctx (Symbol.mk_string ctx name) size - - (** - Bitwise negation. - The argument must have a bit-vector sort. - *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - - (** - Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. - *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - - (** - Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. - *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - - (** - Bitwise conjunction. - The arguments must have a bit-vector sort. - *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise disjunction. - The arguments must have a bit-vector sort. - *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise XOR. - The arguments must have a bit-vector sort. - *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise NAND. - The arguments must have a bit-vector sort. - *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise NOR. - The arguments must have a bit-vector sort. - *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise XNOR. - The arguments must have a bit-vector sort. - *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - - (** - Standard two's complement unary minus. - The arguments must have a bit-vector sort. - *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - - (** - Two's complement addition. - The arguments must have the same bit-vector sort. - *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement subtraction. - The arguments must have the same bit-vector sort. - *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement multiplication. - The arguments must have the same bit-vector sort. - *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned division. - - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. - *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - - (** - Signed division. - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned remainder. - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - - (** - Signed remainder. - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement signed remainder (sign follows divisor). - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned less-than - - The arguments must have the same bit-vector sort. - *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed less-than - - The arguments must have the same bit-vector sort. - *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned greater-than. - - The arguments must have the same bit-vector sort. - *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. - *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - - (** - Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). - *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - - (** - Bit-vector extraction. - - Extract the bits down to from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. - The argument must have a bit-vector sort. - *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - - (** - Bit-vector sign extension. - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. - The argument must have a bit-vector sort. - *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - - (** - Bit-vector zero extension. - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. - The argument must have a bit-vector sort. - *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - - (** - Bit-vector repetition. - - The argument must have a bit-vector sort. - *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - - (** - Shift left. - - - It is equivalent to multiplication by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - - - (** - Logical shift right - - It is equivalent to unsigned division by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - - (** - Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - - (** - Rotate Left. - - Rotate bits of \c t to the left \c i times. - The argument must have a bit-vector sort. - *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - - (** - Rotate Right. - - Rotate bits of \c t to the right \c i times. - The argument must have a bit-vector sort. - *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - - (** - Rotate Left. - - Rotate bits of to the left times. - The arguments must have the same bit-vector sort. - *) - let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - - (** - Rotate Right. - - - Rotate bits of to the right times. - The arguments must have the same bit-vector sort. - *) - let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - - (** - Create an integer from the bit-vector argument . - - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in . - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of bit-vector sort. - *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - - (** - Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - - (** - Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a bit-vector numeral. - - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - *) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) end -(** Functions to manipulate proof expressions *) + module Proof = struct - (** - Indicates whether the term is a Proof for the expression 'true'. - *) let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - - (** - Indicates whether the term is a proof for a fact asserted by the user. - *) let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - - (** - Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. - *) let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - - (** - Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). - *) let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - - (** - Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. - *) let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - - (** - Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. - *) let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - - (** - Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) - *) let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - - (** - Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. - *) let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - - - (** - Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. - *) let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - - (** - Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - *) let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - - (** - Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. - *) let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - - (** - Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i - *) let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - - (** - Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) - *) let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - - (** - Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) - *) let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - - (** - Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - *) let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - - (** - Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - *) let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - - (** - Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents - *) let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - - (** - Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents - *) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - - (** - Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. - *) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - - (** - Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. - *) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - - (** - Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) - *) let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - - (** - Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. - *) let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - - (** - Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. - *) let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - - (** - Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - *) let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - - (** - Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) - *) let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - - (** - Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) - *) let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - - (** - Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. - *) let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - - (** - Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). - *) let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - - (** - Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) - *) let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - - (** - Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. - *) let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - - (** - Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) - *) let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - - (** - Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. - *) let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - - (** - Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) - *) let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - - (** - Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - - (** - Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - - (** - Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. - *) let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - - (** - Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q - *) let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - - (** - Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - *) let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** Goals - - A goal (aka problem). A goal is essentially a - of formulas, that can be solved and/or transformed using - tactics and solvers. *) module Goal = struct type goal = z3_native_object @@ -4386,76 +2536,52 @@ struct (z3obj_create res) ; res - - (** The precision of the goal. - - Goals can be transformed using over and under approximations. - An under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. - *) let get_precision ( x : goal ) = goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) - (** Indicates whether the goal is precise. *) let is_precise ( x : goal ) = (get_precision x) == GOAL_PRECISE - (** Indicates whether the goal is an under-approximation. *) let is_underapproximation ( x : goal ) = (get_precision x) == GOAL_UNDER - (** Indicates whether the goal is an over-approximation. *) let is_overapproximation ( x : goal ) = (get_precision x) == GOAL_OVER - (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - (** Adds the constraints to the given goal. *) - (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () - (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) - (** The depth of the goal. - This tracks how many transformations were applied to it. *) let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) - (** Erases all formulas from the given goal. *) let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) - (** The number of formulas in the goal. *) let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) - (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f - (** The number of formulas, subformulas and terms in the goal. *) let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) - (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) - (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) - (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : Params.params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; @@ -4473,27 +2599,13 @@ struct Z3native.tactic_dec_ref (z3obj_gnc x) tn ; create (z3obj_gc x) res - - (** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. - @param models Indicates whether model generation should be enabled. - @param unsat_cores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) - (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) module Model = struct type model = z3_native_object @@ -4507,12 +2619,6 @@ struct (z3obj_create res) ; res - - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) module FuncInterp = struct type func_interp = z3_native_object @@ -4526,11 +2632,6 @@ struct (z3obj_create res) ; res - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) module FuncEntry = struct type func_entry = z3_native_object @@ -4544,61 +2645,33 @@ struct (z3obj_create res) ; res - - (** - Return the (symbolic) value of this entry. - *) let get_value ( x : func_entry ) = expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) - (** - The number of arguments of the entry. - *) let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) - (** - The arguments of the function entry. - *) let get_args ( x : func_entry ) = let n = (get_num_args x) in let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - (** - A string representation of the function entry. - *) let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end - (** - The number of entries in the function interpretation. - *) let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) - (** - The entries in the function interpretation - *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - (** - The (symbolic) `else' value of the function interpretation. - *) let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) - (** - The arity of the function interpretation - *) let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) - (** - A string representation of the function interpretation. - *) let to_string ( x : func_interp ) = let f c p = ( let n = (FuncEntry.get_num_args c) in @@ -4613,9 +2686,6 @@ struct Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") end - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) let get_const_interp ( x : model ) ( f : func_decl ) = if (FuncDecl.get_arity f) != 0 || (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then @@ -4627,16 +2697,9 @@ struct else Some (expr_of_ptr (z3obj_gc x) np) - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) let rec get_func_interp ( x : model ) ( f : func_decl ) = let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then @@ -4659,23 +2722,18 @@ struct (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) - (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - - (** The number of function interpretations in the model. *) let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) - (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in @@ -4683,24 +2741,8 @@ struct let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) exception ModelEvaluationFailedException of string - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. - *) let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in if not r then @@ -4708,53 +2750,26 @@ struct else expr_of_ptr (z3obj_gc x) v - (** Alias for eval. *) let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion - (** The number of uninterpreted sorts that the model has an interpretation for. *) let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - - *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of - *) let sort_universe ( x : model ) ( s : sort ) = let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f - - (** Conversion of models to strings. - A string representation of the model. - *) + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) module Probe = struct type probe = z3_native_object @@ -4769,114 +2784,52 @@ struct res - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) let apply ( x : probe ) ( g : Goal.goal ) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) - (** - The number of supported Probes. - *) let get_num_probes ( ctx : context ) = Z3native.get_num_probes (context_gno ctx) - (** - The names of all supported Probes. - *) let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in let f i = (Z3native.get_probe_name (context_gno ctx) i) in Array.init n f - (** - Returns a string containing a description of the probe with the given name. - *) let get_probe_description ( ctx : context ) ( name : string ) = Z3native.probe_get_descr (context_gno ctx) name - (** - Creates a new Probe. - *) let mk_probe ( ctx : context ) ( name : string ) = (create ctx (Z3native.mk_probe (context_gno ctx) name)) - (** - Create a probe that always evaluates to . - *) let const ( ctx : context ) ( v : float ) = (create ctx (Z3native.probe_const (context_gno ctx) v)) - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) end -(** Tactics - - Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) module Tactic = struct type tactic = z3_native_object @@ -4890,11 +2843,6 @@ struct (z3obj_create res) ; res - - (** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct type apply_result = z3_native_object @@ -4908,75 +2856,46 @@ struct (z3obj_create res) ; res - - (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) - (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) - (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) end - (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) - (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) - (** - The number of supported tactics. - *) let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) - (** - The names of all supported tactics. - *) let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in let f i = (Z3native.get_tactic_name (context_gno ctx) i) in Array.init n f - - (** - Returns a string containing a description of the tactic with the given name. - *) let get_tactic_description ( ctx : context ) ( name : string ) = Z3native.tactic_get_descr (context_gno ctx) name - (** - Creates a new Tactic. - *) let mk_tactic ( ctx : context ) ( name : string ) = create ctx (Z3native.mk_tactic (context_gno ctx) name) - (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - *) let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = let f p c = (match p with | None -> (Some (z3obj_gno c)) @@ -4988,106 +2907,50 @@ struct let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) - (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. - *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - (** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. - *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) - (** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. - *) - (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) - (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. - *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) - (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. - *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) - (** - Create a tactic that just returns the given goal. - *) let skip ( ctx : context ) = create ctx (Z3native.tactic_skip (context_gno ctx)) - (** - Create a tactic always fails. - *) let fail ( ctx : context ) = create ctx (Z3native.tactic_fail (context_gno ctx)) - (** - Create a tactic that fails if the probe evaluates to false. - *) let fail_if ( ctx : context ) ( p : Probe.probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) - (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). - *) let fail_if_not_decided ( ctx : context ) = create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) - (** - Create a tactic that applies using the given set of parameters . - *) let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) - (** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - (* CMW: with is a keyword *) let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p - (** - Create a tactic that applies the given tactics in parallel. - *) let par_or ( ctx : context ) ( t : tactic array ) = create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) - (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. - *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - (** - Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. - *) let interrupt ( ctx : context ) = Z3native.interrupt (context_gno ctx) end -(** Solvers *) module Solver = struct type solver = z3_native_object @@ -5102,13 +2965,11 @@ struct (z3obj_create res) ; res - let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" | SATISFIABLE -> "satisfiable" | _ -> "unknown" - (** Objects that track statistical information about solvers. *) module Statistics = struct type statistics = z3_native_object @@ -5123,11 +2984,6 @@ struct res - (** - Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - - *) module Entry = struct type statistics_entry = { @@ -5158,22 +3014,11 @@ struct res - (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key - - (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x.m_int - - (** The float-value of the entry. *) + let get_int (x : statistics_entry) = x.m_int let get_float (x : statistics_entry) = x.m_float - - (** True if the entry is uint-valued. *) let is_int (x : statistics_entry) = x.m_is_int - - (** True if the entry is double-valued. *) let is_float (x : statistics_entry) = x.m_is_float - - (** The string representation of the the entry's value. *) let to_string_value (x : statistics_entry) = if (is_int x) then string_of_int (get_int x) @@ -5181,18 +3026,13 @@ struct string_of_float (get_float x) else raise (Z3native.Exception "Unknown statistical entry type") - - (** The string representation of the entry (key and value) *) let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) end - (** A string representation of the statistical data. *) let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) - (** The number of statistical data. *) let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) - (** The data entries. *) let get_entries ( x : statistics ) = let n = (get_size x ) in let f i = ( @@ -5204,129 +3044,56 @@ struct ) in Array.init n f - (** - The statistical counters. - *) let get_keys ( x : statistics ) = let n = (get_size x) in let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** The value of a particular statistical counter. *) let get ( x : statistics ) ( key : string ) = let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in Array.fold_left f None (get_entries x) end - (** - A string that describes all available solver parameters. - *) let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) - (** - Sets the solver parameters. - *) let set_parameters ( x : solver ) ( p : Params.params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - (** - Retrieves parameter descriptions for solver. - *) let get_param_descrs ( x : solver ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** - The current number of backtracking points (scopes). - - - *) let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) - (** - Creates a backtracking point. - - *) let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) - (** - Backtracks backtracking points. - Note that an exception is thrown if is not smaller than NumScopes - - *) let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n - (** - Resets the Solver. - This removes all assertions from the solver. - *) let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - (** - Assert a constraint (or multiple) into the solver. - *) let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) - (** - * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using - * and the Boolean literals - * provided using with assumptions. - *) - let assert_and_track ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in ignore (Array.iteri f cs) - (** - * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using - * and the Boolean literals - * provided using with assumptions. - *) let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) - (** - The number of assertions in the solver. - *) let get_num_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) - - (** - The set of asserted formulas. - *) let get_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f - (** - Checks whether the assertions in the solver are consistent or not. - - - - - *) let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = let r = if ((Array.length assumptions) == 0) then @@ -5340,12 +3107,6 @@ struct | L_FALSE -> UNSATISFIABLE | _ -> UNKNOWN - (** - The model of the last Check. - - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. - *) let get_model ( x : solver ) = let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then @@ -5353,12 +3114,6 @@ struct else Some (Model.create (z3obj_gc x) q) - (** - The proof of the last Check. - - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. - *) let get_proof ( x : solver ) = let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then @@ -5366,73 +3121,35 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - The unsat core of the last Check. - - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. - *) let get_unsat_core ( x : solver ) = let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f - (** - A brief justification of why the last call to Check returned UNKNOWN. - *) let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - (** - Solver statistics. - *) let get_statistics ( x : solver ) = (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) - (** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. - *) let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) - (** - Creates a new (incremental) solver. - - *) let mk_solver_s ( ctx : context ) ( logic : string ) = mk_solver ctx (Some (Symbol.mk_string ctx logic)) - (** - Creates a new (incremental) solver. - *) let mk_simple_solver ( ctx : context ) = (create ctx (Z3native.mk_simple_solver (context_gno ctx))) - (** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. - *) let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) - (** - A string representation of the solver. - *) let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Fixedpoint solving *) module Fixedpoint = struct type fixedpoint = z3_native_object @@ -5447,70 +3164,37 @@ struct res - (** - A string that describes all available fixedpoint solver parameters. - *) let get_help ( x : fixedpoint ) = Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) - (** - Sets the fixedpoint solver parameters. - *) let set_params ( x : fixedpoint ) ( p : Params.params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - (** - Retrieves parameter descriptions for Fixedpoint solver. - *) let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** - Assert a constraints into the fixedpoint solver. - *) let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () - (** - Register predicate as recursive relation. - *) let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - (** - Add rule into the fixedpoint solver. - *) let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - (** - Add table fact to the fixedpoint solver. - *) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args - (** - Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. - *) let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - (** - Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. - *) let query_r ( x : fixedpoint ) ( relations : func_decl array ) = let f x = ptr_of_ast (ast_of_func_decl x) in match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with @@ -5518,32 +3202,15 @@ struct | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - (** - Creates a backtracking point. - - *) let push ( x : fixedpoint ) = Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) - (** - Backtrack one backtracking point. - - Note that an exception is thrown if Pop is called without a corresponding Push - - *) let pop ( x : fixedpoint ) = Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - (** - Update named rule into in the fixedpoint solver. - *) let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) - (** - Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. - *) let get_answer ( x : fixedpoint ) = let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in if (Z3native.is_null q) then @@ -5551,21 +3218,12 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - Retrieve explanation why fixedpoint engine returned status Unknown. - *) let get_reason_unknown ( x : fixedpoint ) = Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - (** - Retrieve the number of levels explored for a given predicate. - *) let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) - (** - Retrieve the cover of a predicate. - *) let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then @@ -5573,82 +3231,40 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - Add property about the predicate. - The property is added at level. - *) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) - (** - Retrieve internal string representation of fixedpoint object. - *) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - (** - Instrument the Datalog engine on which table representation to use for recursive predicate. - *) let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = let f2 x = (Symbol.gno x) in Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) - (** - Convert benchmark given as set of axioms, rules and queries to a string. - *) let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) - (** - Retrieve set of rules added to fixedpoint context. - *) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f - (** - Retrieve set of assertions added to fixedpoint context. - *) let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f - (** - Create a Fixedpoint context. - *) let mk_fixedpoint ( ctx : context ) = create ctx end -(** Global and context options - - Note: This module contains functions that set parameters/options for context - objects as well as functions that set options that are used globally, across - contexts.*) module Options = struct - (** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - - *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value - (** - Get a configuration parameter. - - Returns None if the parameter value does not exist. - - *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then @@ -5656,62 +3272,21 @@ struct else Some v - (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - - - - *) let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - (** - Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. - *) let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled end -(** Functions for handling SMT and SMT2 expressions and files *) + module SMT = struct - (** - Convert a benchmark into an SMT-LIB formatted string. - - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) (Boolean.gno formula) - (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. - *) let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5728,10 +3303,6 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)) - (** - Parse the given file using the SMT-LIB parser. - - *) let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5748,65 +3319,34 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)) - (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) - (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f - - (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) - (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f - (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) - (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f - (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - - (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) + let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f - (** - Parse the given string using the SMT-LIB2 parser. - - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - *) let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5823,10 +3363,6 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)))) - (** - Parse the given file using the SMT-LIB2 parser. - - *) let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5845,34 +3381,9 @@ struct end -(* Global functions *) - -(** - * Set a global (or module) parameter, which is shared by all Z3 contexts. - * - * When a Z3 module is initialized it will use the value of these parameters - * when Z3_params objects are not provided. - * The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - * The character '.' is a delimiter (more later). - * The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - * Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - * This function can be used to set parameters for a specific Z3 module. - * This can be done by using .. - * For example: - * (set_global_param "pp.decimal" "true") - * will set the parameter "decimal" in the module "pp" to true. -*) let set_global_param ( id : string ) ( value : string ) = (Z3native.global_param_set id value) -(** - * Get a global (or module) parameter. - * - * Returns None if the parameter does not exist. - * The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. - * This function cannot be invoked simultaneously from different threads without synchronization. - * The result string stored in param_value is stored in a shared location. -*) let get_global_param ( id : string ) = let (r, v) = (Z3native.global_param_get id) in if not r then @@ -5880,11 +3391,5 @@ let get_global_param ( id : string ) = else Some v -(** - * Restore the value of all global (and module) parameters. - * - * This command will not affect already created objects (such as tactics and solvers) - * -*) let global_param_reset_all = Z3native.global_param_reset_all From a0f6d1d3dfcab9f5c8b79a1aaa2fba8d9ee67f42 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 00:29:51 +0000 Subject: [PATCH 309/646] ML API: replaced arrays with lists. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 46 ++-- src/api/ml/z3.ml | 507 +++++++++++++++++++------------------- 2 files changed, 279 insertions(+), 274 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 6dfe11623..31f31d566 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -33,13 +33,13 @@ let model_converter_test ( ctx : context ) = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [| (mk_gt ctx xr + (Goal.assert_ g4 [ (mk_gt ctx xr (arith_expr_of_real_expr (real_expr_of_rat_num - (Real.mk_numeral_nd ctx 10 1)))) |]) ; - (Goal.assert_ g4 [| (mk_eq ctx + (Real.mk_numeral_nd ctx 10 1)))) ]) ; + (Goal.assert_ g4 [ (mk_eq ctx (expr_of_arith_expr yr) - (expr_of_arith_expr (Arithmetic.mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |]) ) ) |] ) ; - (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; + (expr_of_arith_expr (Arithmetic.mk_add ctx [ xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) ]) ) ) ] ) ; + (Goal.assert_ g4 [ (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -50,7 +50,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ); ( - let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") [||]) g4 None) in + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") []) g4 None) in if ((get_num_subgoals ar) == 1 && ((is_decided_sat (get_subgoal ar 0)) || (is_decided_unsat (get_subgoal ar 0)))) then @@ -59,9 +59,9 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ; let solver = (mk_solver ctx None) in - let f e = (Solver.assert_ solver [| e |]) in - ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; - let q = (check solver [||]) in + let f e = (Solver.assert_ solver [ e ]) in + ignore (List.map f (get_formulas (get_subgoal ar 0))) ; + let q = (check solver []) in if q != SATISFIABLE then raise (TestFailedException "") else @@ -84,23 +84,23 @@ let basic_tests ( ctx : context ) = let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in - let domain = [| bs; bs |] in + let domain = [ bs; bs ] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f - [| (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) |]) in - let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in - let domain2 = [| bs |] in + [ (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) ]) in + let fargs2 = [ (mk_fresh_const ctx "cp" bs) ] in + let domain2 = [ bs ] in let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in let trivial_eq = (mk_eq ctx fapp fapp) in let nontrivial_eq = (mk_eq ctx fapp fapp2) in let g = (mk_goal ctx true false false) in - (Goal.assert_ g [| trivial_eq |]) ; - (Goal.assert_ g [| nontrivial_eq |]) ; + (Goal.assert_ g [ trivial_eq ]) ; + (Goal.assert_ g [ nontrivial_eq ]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; ( let solver = (mk_solver ctx None) in - (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver [||]) != SATISFIABLE then + (List.iter (fun a -> (Solver.assert_ solver [ a ])) (get_formulas g)) ; + if (check solver []) != SATISFIABLE then raise (TestFailedException "") else Printf.printf "Test passed.\n" @@ -122,11 +122,11 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [| (mk_eq ctx + (Goal.assert_ g [ (mk_eq ctx (mk_numeral_int ctx 1 (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) (mk_numeral_int ctx 2 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) |] ) + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) ] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -147,7 +147,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [| (Boolean.mk_false ctx) |]) ; + (Goal.assert_ g2 [ (Boolean.mk_false ctx) ]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -159,10 +159,10 @@ let basic_tests ( ctx : context ) = let g3 = (mk_goal ctx true true false) in let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; - (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; + (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; + (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; let constr = (mk_eq ctx xc yc) in - (Goal.assert_ g3 [| constr |] ) ; + (Goal.assert_ g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b1e40fcac..56d319c1a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -79,10 +79,6 @@ struct let z3obj_nil_ref x y = () - let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> let res : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -127,6 +123,9 @@ let mk_list ( f : int -> 'a ) ( n : int ) = in mk_list' f 0 n [] +let list_of_array ( x : _ array ) = + let f i = (Array.get x i) in + mk_list f (Array.length x) let mk_context ( cfg : ( string * string ) list ) = create_context cfg @@ -180,6 +179,10 @@ struct match x with | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) + + let symbol_lton ( a : symbol list ) = + let f ( e : symbol ) = (gno e) in + Array.of_list (List.map f a) let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL @@ -197,13 +200,13 @@ struct let mk_string ( ctx : context ) ( s : string ) = S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - let mk_ints ( ctx : context ) ( names : int array ) = + let mk_ints ( ctx : context ) ( names : int list ) = let f elem = mk_int ( ctx : context ) elem in - (Array.map f names) + (List.map f names) - let mk_strings ( ctx : context ) ( names : string array ) = + let mk_strings ( ctx : context ) ( names : string list ) = let f elem = mk_string ( ctx : context ) elem in - (Array.map f names) + (List.map f names) end @@ -292,7 +295,9 @@ struct Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) let get_keys ( x : ast_map ) = - ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let f i = (ASTVector.get av i) in + mk_list f (ASTVector.get_size av) let to_string ( x : ast_map ) = Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) @@ -376,10 +381,13 @@ struct else UninterpretedSort(s) - let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let sort_lton ( a : sort list ) = + let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) let ( = ) : sort -> sort -> bool = fun a b -> (a == b) || @@ -438,9 +446,9 @@ sig val get_func_decl : parameter -> func_decl val get_rational : parameter -> string end - val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl - val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl - val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl val mk_const_decl_s : context -> string -> Sort.sort -> func_decl val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl @@ -449,13 +457,13 @@ sig val get_id : func_decl -> int val get_arity : func_decl -> int val get_domain_size : func_decl -> int - val get_domain : func_decl -> Sort.sort array + val get_domain : func_decl -> Sort.sort list val get_range : func_decl -> Sort.sort val get_decl_kind : func_decl -> Z3enums.decl_kind val get_name : func_decl -> Symbol.symbol val get_num_parameters : func_decl -> int val get_parameters : func_decl -> Parameter.parameter list - val apply : func_decl -> Expr.expr array -> Expr.expr + val apply : func_decl -> Expr.expr list -> Expr.expr end = struct type func_decl = FuncDecl of AST.ast @@ -467,23 +475,21 @@ end = struct let ast_of_func_decl f = match f with FuncDecl(x) -> x - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (AST.ptr_of_ast (ast_of_sort x)) in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (AST.ptr_of_ast (ast_of_sort x)) in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) @@ -548,23 +554,23 @@ end = struct | _ -> raise (Z3native.Exception "parameter is not a rational string") end - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = create_ndr ctx name domain range - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = create_pdr ctx prefix domain range let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_ndr ctx name [||] range + create_ndr ctx name [] range let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = - create_ndr ctx (Symbol.mk_string ctx name) [||] range + create_ndr ctx (Symbol.mk_string ctx name) [] range let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = - create_pdr ctx prefix [||] range + create_pdr ctx prefix [] range let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || @@ -584,7 +590,7 @@ end = struct let get_domain ( x : func_decl ) = let n = (get_domain_size x) in let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in - Array.init n f + mk_list f n let get_range ( x : func_decl ) = sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) @@ -608,7 +614,7 @@ end = struct ) in mk_list f n - let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.expr_of_func_app (gc x) x args + let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args end @@ -621,7 +627,7 @@ sig val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs val validate : param_descrs -> params -> unit val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - val get_names : param_descrs -> Symbol.symbol array + val get_names : param_descrs -> Symbol.symbol list val get_size : param_descrs -> int val to_string : param_descrs -> string end @@ -660,7 +666,7 @@ end = struct let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) @@ -710,21 +716,21 @@ sig val c_of_expr : expr -> context val nc_of_expr : expr -> Z3native.ptr val ptr_of_expr : expr -> Z3native.ptr - val expr_aton : expr array -> Z3native.ptr array + val expr_lton : expr list -> Z3native.ptr array val ast_of_expr : expr -> AST.ast val expr_of_ast : AST.ast -> expr - val expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr val simplify : expr -> Params.params option -> expr val get_simplify_help : context -> string val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs val get_func_decl : expr -> FuncDecl.func_decl val get_bool_value : expr -> Z3enums.lbool val get_num_args : expr -> int - val get_args : expr -> expr array - val update : expr -> expr array -> expr - val substitute : expr -> expr array -> expr array -> expr + val get_args : expr -> expr list + val update : expr -> expr list -> expr + val substitute : expr -> expr list -> expr list -> expr val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr array -> expr + val substitute_vars : expr -> expr list -> expr val translate : expr -> context -> expr val to_string : expr -> string val is_numeral : expr -> bool @@ -750,7 +756,7 @@ sig val mk_const_s : context -> string -> Sort.sort -> expr val mk_const_f : context -> FuncDecl.func_decl -> expr val mk_fresh_const : context -> string -> Sort.sort -> expr - val mk_app : context -> FuncDecl.func_decl -> expr array -> expr + val mk_app : context -> FuncDecl.func_decl -> expr list -> expr val mk_numeral_string : context -> string -> Sort.sort -> expr val mk_numeral_int : context -> int -> Sort.sort -> expr end = struct @@ -786,13 +792,13 @@ end = struct let ast_of_expr e = match e with Expr(a) -> a - let expr_aton ( a : expr array ) = + let expr_lton ( a : expr list ) = let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in - Array.map f a + Array.of_list (List.map f a) - let expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr = fun ctx f args -> + let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> match f with FuncDecl.FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in expr_of_ptr ctx o let simplify ( x : expr ) ( p : Params.params option ) = match p with @@ -812,25 +818,25 @@ end = struct let get_args ( x : expr ) = let n = (get_num_args x) in let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in - Array.init n f + mk_list f n - let update ( x : expr ) args = - if (Array.length args <> (get_num_args x)) then + let update ( x : expr ) ( args : expr list ) = + if (List.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) + expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (List.length args) (expr_lton args)) let substitute ( x : expr ) from to_ = - if (Array.length from) <> (Array.length to_) then + if (List.length from) <> (List.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (List.length from) (expr_lton from) (expr_lton to_)) let substitute_one ( x : expr ) from to_ = - substitute ( x : expr ) [| from |] [| to_ |] + substitute ( x : expr ) [ from ] [ to_ ] let substitute_vars ( x : expr ) to_ = - expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (List.length to_) (expr_lton to_)) let translate ( x : expr ) to_ctx = if (c_of_expr x) == to_ctx then @@ -876,12 +882,12 @@ end = struct let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) @@ -950,8 +956,8 @@ struct let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) - let mk_distinct ( ctx : context ) ( args : expr array ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_distinct ( ctx : context ) ( args : expr list ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) let mk_not ( ctx : context ) ( a : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) @@ -968,13 +974,13 @@ struct let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - let mk_and ( ctx : context ) ( args : bool_expr array ) = + let mk_and ( ctx : context ) ( args : bool_expr list ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - let mk_or ( ctx : context ) ( args : bool_expr array ) = + let mk_or ( ctx : context ) ( args : bool_expr list ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) end @@ -1016,7 +1022,7 @@ struct let get_terms ( x : pattern ) = let n = (get_num_terms x) in let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) end @@ -1039,26 +1045,26 @@ struct let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_body ( x : quantifier ) = Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) @@ -1066,95 +1072,95 @@ struct let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - let mk_pattern ( ctx : context ) ( terms : expr array ) = - if (Array.length terms) == 0 then + let mk_pattern ( ctx : context ) ( terms : expr list ) = + if (List.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (Array.length sorts) != (Array.length names) then + let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) (ptr_of_expr body))) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (Array.length sorts) != (Array.length names) then + let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) (ptr_of_expr body))) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1233,9 +1239,9 @@ struct let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) let mk_term_array ( ctx : context ) ( arg : array_expr ) = array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) @@ -1274,11 +1280,11 @@ struct let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - let mk_union ( ctx : context ) ( args : expr array ) = - expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_union ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) - let mk_intersection ( ctx : context ) ( args : expr array ) = - expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_intersection ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) @@ -1378,7 +1384,7 @@ struct let get_column_sorts ( x : relation_sort ) = let n = get_arity x in let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in - Array.init n f + mk_list f n end @@ -1418,21 +1424,23 @@ struct module Constructor = struct type constructor = z3_native_object + + let _sizes = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = - let n = (Array.length field_names) in - if n != (Array.length sorts) then + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let n = (List.length field_names) in + if n != (List.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") else - if n != (Array.length sort_refs) then + if n != (List.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) n - (let f x = (Symbol.gno x) in (Array.map f field_names)) - (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - sort_refs) in + (Symbol.symbol_lton field_names) + (sort_lton sorts) + (Array.of_list sort_refs)) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -1441,9 +1449,10 @@ struct (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; + Hashtbl.add _sizes no n ; no - let get_num_fields ( x : constructor ) = Z3native.get_arity (z3obj_gnc x) (z3obj_gno x) + let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x let get_constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in @@ -1455,8 +1464,8 @@ struct let get_accessor_decls ( x : constructor ) = let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - let f y = func_decl_of_ptr (z3obj_gc x) y in - Array.map f c + let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in + mk_list f (Array.length c) end @@ -1464,48 +1473,47 @@ struct struct type constructor_list = z3_native_object - let create ( ctx : context ) ( c : Constructor.constructor array ) = + let create ( ctx : context ) ( c : Constructor.constructor list ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in let f x =(z3obj_gno x) in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f res; res end - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = Constructor.create ctx name recognizer field_names sorts sort_refs - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = let f x = (z3obj_gno x) in - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in sort_of_ptr ctx x - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = mk_sort ctx (Symbol.mk_string ctx name) constructors - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = - let n = (Array.length names) in + let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = + let n = (List.length names) in let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in - let cla = (Array.map f c) in - let f2 x = (Symbol.gno x) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in - let g e = (sort_of_ptr ctx e) in - (Array.map g r) + let cla = (Array.of_list (List.map f c)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in + let g i = (sort_of_ptr ctx (Array.get r i)) in + mk_list g (Array.length r) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in - Array.map f names + List.map f names ) c @@ -1514,12 +1522,12 @@ struct let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in @@ -1527,9 +1535,9 @@ struct let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in - Array.init ds g + mk_list g ds ) in - Array.init n f + mk_list f n end @@ -1537,7 +1545,7 @@ module Enumeration = struct type enum_sort = EnumSort of sort - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in res @@ -1548,23 +1556,22 @@ struct let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = - let f x = Symbol.gno x in - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in - sort_of_ptr ctx a b c + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a (list_of_array b) (list_of_array c) - let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) let get_const_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in - Array.init n f + mk_list f n let get_tester_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in - Array.init n f + mk_list f n end @@ -1609,7 +1616,7 @@ struct let get_tail_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] end @@ -1627,10 +1634,8 @@ struct let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = - let f x = Symbol.gno x in - let f2 x = ptr_of_ast (ast_of_sort x) in - let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in sort_of_ptr ctx r let get_mk_decl ( x : tuple_sort ) = @@ -1641,7 +1646,7 @@ struct let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n end @@ -1746,9 +1751,9 @@ sig val is_int_numeral : Expr.expr -> bool val is_rat_num : Expr.expr -> bool val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr array -> arith_expr - val mk_mul : context -> arith_expr array -> arith_expr - val mk_sub : context -> arith_expr array -> arith_expr + val mk_add : context -> arith_expr list -> arith_expr + val mk_mul : context -> arith_expr list -> arith_expr + val mk_sub : context -> arith_expr list -> arith_expr val mk_unary_minus : context -> arith_expr -> arith_expr val mk_div : context -> arith_expr -> arith_expr -> arith_expr val mk_power : context -> arith_expr -> arith_expr -> arith_expr @@ -2109,17 +2114,17 @@ end = struct let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) - let mk_add ( ctx : context ) ( t : arith_expr array ) = + let mk_add ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_mul ( ctx : context ) ( t : arith_expr array ) = + let mk_mul ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_sub ( ctx : context ) ( t : arith_expr array ) = + let mk_sub ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) @@ -2551,9 +2556,9 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in - ignore (Array.map f constraints) ; + ignore (List.map f constraints) ; () let is_inconsistent ( x : goal ) = @@ -2569,7 +2574,7 @@ struct let n = get_size x in let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in - Array.init n f + mk_list f n let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) @@ -2653,12 +2658,12 @@ struct let get_args ( x : func_entry ) = let n = (get_num_args x) in let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) @@ -2666,7 +2671,7 @@ struct let get_entries ( x : func_interp ) = let n = (get_num_entries x) in let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) @@ -2678,12 +2683,12 @@ struct p ^ let g c p = (p ^ (Expr.to_string c) ^ ", ") in (if n > 1 then "[" else "") ^ - (Array.fold_right + (List.fold_right g (FuncEntry.get_args c) ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") end let get_const_interp ( x : model ) ( f : func_decl ) = @@ -2725,21 +2730,21 @@ struct let get_const_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) let get_func_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) + (mk_list f n_funcs) @ (mk_list g n_consts) exception ModelEvaluationFailedException of string @@ -2758,13 +2763,13 @@ struct let get_sorts ( x : model ) = let n = (get_num_sorts x) in let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let sort_universe ( x : model ) ( s : sort ) = let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in - Array.init n f + mk_list f n let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) end @@ -2793,7 +2798,7 @@ struct let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in let f i = (Z3native.get_probe_name (context_gno ctx) i) in - Array.init n f + mk_list f n let get_probe_description ( ctx : context ) ( name : string ) = Z3native.probe_get_descr (context_gno ctx) name @@ -2862,7 +2867,7 @@ struct let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_subgoal ( x : apply_result ) ( i : int ) = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) @@ -2888,7 +2893,7 @@ struct let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in let f i = (Z3native.get_tactic_name (context_gno ctx) i) in - Array.init n f + mk_list f n let get_tactic_description ( ctx : context ) ( name : string ) = Z3native.tactic_get_descr (context_gno ctx) name @@ -2896,11 +2901,11 @@ struct let mk_tactic ( ctx : context ) ( name : string ) = create ctx (Z3native.mk_tactic (context_gno ctx) name) - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = let f p c = (match p with | None -> (Some (z3obj_gno c)) | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in - match (Array.fold_left f None ts) with + match (List.fold_left f None ts) with | None -> create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> @@ -2940,8 +2945,9 @@ struct let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p - let par_or ( ctx : context ) ( t : tactic array ) = - create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) + let par_or ( ctx : context ) ( t : tactic list ) = + let f e = (z3obj_gno e) in + create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) @@ -3042,16 +3048,16 @@ struct else (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in - Array.init n f + mk_list f n let get_keys ( x : statistics ) = let n = (get_size x) in let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get ( x : statistics ) ( key : string ) = let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in - Array.fold_left f None (get_entries x) + List.fold_left f None (get_entries x) end let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) @@ -3070,16 +3076,16 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (Array.map f constraints) + ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = - if ((Array.length cs) != (Array.length ps)) then + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in - ignore (Array.iteri f cs) + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + ignore (List.iter2 f cs ps) let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) @@ -3092,15 +3098,15 @@ struct let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in - Array.init n f + mk_list f n - let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = + let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = let r = - if ((Array.length assumptions) == 0) then + if ((List.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) in match r with | L_TRUE -> SATISFIABLE @@ -3125,7 +3131,7 @@ struct let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in - Array.init n f + mk_list f n let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) @@ -3173,9 +3179,9 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (Array.map f constraints) ; + ignore (List.map f constraints) ; () let register_relation ( x : fixedpoint ) ( f : func_decl ) = @@ -3186,8 +3192,8 @@ struct | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with @@ -3195,9 +3201,9 @@ struct | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + let query_r ( x : fixedpoint ) ( relations : func_decl list ) = let f x = ptr_of_ast (ast_of_func_decl x) in - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -3236,25 +3242,24 @@ struct let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = - let f2 x = (Symbol.gno x) in - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - Array.init n f + mk_list f n let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - Array.init n f + mk_list f n let mk_fixedpoint ( ctx : context ) = create ctx end @@ -3282,102 +3287,102 @@ end module SMT = struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) + (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) (Boolean.gno formula) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Z3native.parse_smtlib_string (context_gno ctx) str cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in - Array.init n f + mk_list f n let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in - Array.init n f + mk_list f n let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in - Array.init n f + mk_list f n let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in - Array.init n f + mk_list f n - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end From 6417f9e64815f98a59693146f1bc8d6b5c57a2d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 13:25:31 +0000 Subject: [PATCH 310/646] ML API: flat & rich layer in place. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 40 +- src/api/ml/z3.ml | 1458 ++++------------ src/api/ml/z3_rich.ml | 3400 +++++++++++++++++++++++++++++++++++++ src/api/ml/z3_rich.mli | 3072 +++++++++++++++++++++++++++++++++ 4 files changed, 6865 insertions(+), 1105 deletions(-) create mode 100644 src/api/ml/z3_rich.ml create mode 100644 src/api/ml/z3_rich.mli diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 31f31d566..823a08fe2 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -26,20 +26,14 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = (arith_expr_of_expr - (Expr.mk_const ctx (Symbol.mk_string ctx "x") - (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in - let yr = (arith_expr_of_expr - (Expr.mk_const ctx (Symbol.mk_string ctx "y") - (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in + let xr = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Real.mk_sort ctx)) in + let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [ (mk_gt ctx xr - (arith_expr_of_real_expr (real_expr_of_rat_num - (Real.mk_numeral_nd ctx 10 1)))) ]) ; + (Goal.assert_ g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; (Goal.assert_ g4 [ (mk_eq ctx - (expr_of_arith_expr yr) - (expr_of_arith_expr (Arithmetic.mk_add ctx [ xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) ]) ) ) ] ) ; - (Goal.assert_ g4 [ (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) ]) ; + yr + (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1) ])) ]) ; + (Goal.assert_ g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -83,7 +77,7 @@ let basic_tests ( ctx : context ) = let fname = (mk_string ctx "f") in let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in - let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in + let bs = (Boolean.mk_sort ctx) in let domain = [ bs; bs ] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f @@ -123,10 +117,8 @@ let basic_tests ( ctx : context ) = Printf.printf "Test passed.\n" ); (Goal.assert_ g [ (mk_eq ctx - (mk_numeral_int ctx 1 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) - (mk_numeral_int ctx 2 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) ] ) + (mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -157,10 +149,10 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; - (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; + let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Integer.mk_sort ctx)) in + let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Integer.mk_sort ctx)) in + (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; + (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; let constr = (mk_eq ctx xc yc) in (Goal.assert_ g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in @@ -228,9 +220,9 @@ let _ = let rs = (Real.mk_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string is); Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string (sort_of_bool_sort bs)); - Printf.printf "int sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_int_sort ints))); - Printf.printf "real sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_real_sort rs))); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); basic_tests ctx ; Printf.printf "Disposing...\n"; Gc.full_major () diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 56d319c1a..0676f1a39 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -133,52 +133,34 @@ let mk_context ( cfg : ( string * string ) list ) = module Symbol = struct - (* Symbol types *) - type int_symbol = z3_native_object - type string_symbol = z3_native_object - - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - + type symbol = z3_native_object let create_i ( ctx : context ) ( no : Z3native.ptr ) = - let res : int_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in + let res : symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let create_s ( ctx : context ) ( no : Z3native.ptr ) = - let res : string_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in + let res : symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; res let create ( ctx : context ) ( no : Z3native.ptr ) = match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) + | INT_SYMBOL -> (create_i ctx no) + | STRING_SYMBOL -> (create_s ctx no) - let gc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gc n) - | S_Str(n) -> (z3obj_gc n) - - let gnc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gnc n) - | S_Str(n) -> (z3obj_gnc n) - - let gno ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gno n) - | S_Str(n) -> (z3obj_gno n) + let gc ( x : symbol ) = (z3obj_gc x) + let gnc ( x : symbol ) = (z3obj_gnc x) + let gno ( x : symbol ) = (z3obj_gno x) let symbol_lton ( a : symbol list ) = let f ( e : symbol ) = (gno e) in @@ -187,18 +169,18 @@ struct let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + let get_int (o : symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + let get_string (o : symbol ) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) let to_string ( o : symbol ) = match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) let mk_int ( ctx : context ) ( i : int ) = - S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) let mk_string ( ctx : context ) ( s : string ) = - S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) let mk_ints ( ctx : context ) ( names : int list ) = let f elem = mk_int ( ctx : context ) elem in @@ -353,7 +335,6 @@ open AST module Sort = struct type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> let q = (z3_native_object_of_ast_ptr ctx no) in @@ -373,14 +354,7 @@ struct | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") let ast_of_sort s = match s with Sort(x) -> x - let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x - - let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -409,7 +383,7 @@ struct dec_ref = Z3native.dec_ref } in (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; (z3obj_create res) ; - UninterpretedSort(Sort(res)) + Sort(res) let mk_uninterpreted_s ( ctx : context ) ( s : string ) = mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) @@ -713,9 +687,9 @@ and Expr : sig type expr = Expr of AST.ast val expr_of_ptr : context -> Z3native.ptr -> expr - val c_of_expr : expr -> context - val nc_of_expr : expr -> Z3native.ptr - val ptr_of_expr : expr -> Z3native.ptr + val gc : expr -> context + val gnc : expr -> Z3native.ptr + val gno : expr -> Z3native.ptr val expr_lton : expr list -> Z3native.ptr array val ast_of_expr : expr -> AST.ast val expr_of_ast : AST.ast -> expr @@ -762,9 +736,9 @@ sig end = struct type expr = Expr of AST.ast - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + let gc e = match e with Expr(a) -> (z3obj_gc a) + let gnc e = match e with Expr(a) -> (z3obj_gnc a) + let gno e = match e with Expr(a) -> (z3obj_gno a) let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then @@ -802,60 +776,60 @@ end = struct expr_of_ptr ctx o let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) - | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) + | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (gnc x) (gno x)) + | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) - let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) + let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in + let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in mk_list f n let update ( x : expr ) ( args : expr list ) = if (List.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (List.length args) (expr_lton args)) + expr_of_ptr (Expr.gc x) (Z3native.update_term (gnc x) (gno x) (List.length args) (expr_lton args)) let substitute ( x : expr ) from to_ = if (List.length from) <> (List.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (List.length from) (expr_lton from) (expr_lton to_)) + expr_of_ptr (Expr.gc x) (Z3native.substitute (gnc x) (gno x) (List.length from) (expr_lton from) (expr_lton to_)) let substitute_one ( x : expr ) from to_ = substitute ( x : expr ) [ from ] [ to_ ] let substitute_vars ( x : expr ) to_ = - expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (List.length to_) (expr_lton to_)) + expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (gnc x) (gno x) (List.length to_) (expr_lton to_)) let translate ( x : expr ) to_ctx = - if (c_of_expr x) == to_ctx then + if (Expr.gc x) == to_ctx then x else - expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) + expr_of_ptr to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) - let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) + let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) - let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) + let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (nc_of_expr x) - (Z3native.mk_bool_sort (nc_of_expr x)) - (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && @@ -901,86 +875,52 @@ open Expr module Boolean = struct - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.ast_of_ptr ctx no) in - BoolExpr(Expr.Expr(a)) - - let bool_expr_of_expr e = - match e with Expr.Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - - let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(sort_of_ptr ctx no) - - let sort_of_bool_sort s = match s with BoolSort(x) -> x - - let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - - let expr_of_bool_expr e = match e with BoolExpr(x) -> x - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) - let mk_sort ( ctx : context ) = - BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) + (sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - let s = (match (mk_sort ctx) with BoolSort(q) -> q) in - BoolExpr(Expr.mk_const ctx name s) + (Expr.mk_const ctx name (mk_sort ctx)) let mk_const_s ( ctx : context ) ( name : string ) = mk_const ctx (Symbol.mk_string ctx name) let mk_true ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) + expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) let mk_false ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) + expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) + expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) let mk_distinct ( ctx : context ) ( args : expr list ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) - let mk_not ( ctx : context ) ( a : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + let mk_not ( ctx : context ) ( a : expr ) = + expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + let mk_ite ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( t3 : expr ) = + expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + let mk_iff ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + let mk_implies ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - let mk_and ( ctx : context ) ( args : bool_expr list ) = - let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) + let mk_and ( ctx : context ) ( args : expr list ) = + let f x = (Expr.gno (x)) in + expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - let mk_or ( ctx : context ) ( args : bool_expr list ) = - let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) + let mk_or ( ctx : context ) ( args : expr list ) = + let f x = (Expr.gno (x)) in + expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) end @@ -998,9 +938,9 @@ struct else Quantifier(e) - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) module Pattern = struct @@ -1031,7 +971,7 @@ struct if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) let is_universal ( x : quantifier ) = Z3native.is_quantifier_forall (gnc x) (gno x) @@ -1067,7 +1007,7 @@ struct mk_list f n let get_body ( x : quantifier ) = - Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) @@ -1087,7 +1027,7 @@ struct (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1097,7 +1037,7 @@ struct (List.length nopatterns) (expr_lton nopatterns) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1105,7 +1045,7 @@ struct (match weight with | None -> 1 | Some(x) -> x) (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1114,7 +1054,7 @@ struct (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length nopatterns) (expr_lton nopatterns) - (ptr_of_expr body))) + (Expr.gno body))) let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (List.length sorts) != (List.length names) then @@ -1125,7 +1065,7 @@ struct (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -1135,7 +1075,7 @@ struct (List.length nopatterns) (expr_lton nopatterns) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1143,7 +1083,7 @@ struct (match weight with | None -> 1 | Some(x) -> x) (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -1152,7 +1092,7 @@ struct (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length nopatterns) (expr_lton nopatterns) - (ptr_of_expr body))) + (Expr.gno body))) let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then @@ -1170,46 +1110,8 @@ end module Array_ = struct - type array_sort = ArraySort of sort - type array_expr = ArrayExpr of expr - - let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (expr_of_ptr ctx no) in - ArrayExpr(e) - - let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - ArraySort(s) - - let sort_of_array_sort s = match s with ArraySort(x) -> x - - let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - - let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - - let expr_of_array_expr e = match e with ArrayExpr(x) -> x - - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) @@ -1218,48 +1120,40 @@ struct let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) let is_array ( x : expr ) = - (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) - let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + let get_domain ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_domain (Sort.gnc x) (Sort.gno x)) + let get_range ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_range (Sort.gnc x) (Sort.gno x)) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) + (Expr.mk_const ctx name (mk_sort ctx domain range)) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + let mk_select ( ctx : context ) ( a : expr ) ( i : expr ) = + expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (Expr.gno a) (Expr.gno i)) - let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) + let mk_store ( ctx : context ) ( a : expr ) ( i : expr ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (Expr.gno a) (Expr.gno i) (Expr.gno v)) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) + expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = - let m x = (ptr_of_expr (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : expr list ) = + let m x = (Expr.gno x) in + expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) - let mk_term_array ( ctx : context ) ( arg : array_expr ) = - array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + let mk_term_array ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (Expr.gno arg)) end module Set = struct - type set_sort = SetSort of sort - - let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - SetSort(s) - - let sort_of_set_sort s = match s with SetSort(x) -> x - let mk_sort ( ctx : context ) ( ty : sort ) = - set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) @@ -1275,10 +1169,10 @@ struct expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) let mk_union ( ctx : context ) ( args : expr list ) = expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) @@ -1287,53 +1181,37 @@ struct expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) let mk_complement ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) end module FiniteDomain = struct - type finite_domain_sort = FiniteDomainSort of sort - - let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x - - let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in - FiniteDomainSort(s) + (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = mk_sort ctx (Symbol.mk_string ctx name) size - let is_finite_domain ( x : expr ) = - let nc = (nc_of_expr x) in - (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) + let nc = (Expr.gnc x) in + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - let get_size ( x : finite_domain_sort ) = - let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in + let get_size ( x : sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (Sort.gnc x) (Sort.gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end @@ -1341,29 +1219,10 @@ end module Relation = struct - type relation_sort = RelationSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - RelationSort(s) - - let sort_of_relation_sort s = match s with RelationSort(x) -> x - - let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - - let is_relation ( x : expr ) = - let nc = (nc_of_expr x) in - ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) + let nc = (Expr.gnc x) in + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) @@ -1379,48 +1238,17 @@ struct let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) + let get_arity ( x : sort ) = Z3native.get_relation_arity (Sort.gnc x) (Sort.gno x) - let get_column_sorts ( x : relation_sort ) = + let get_column_sorts ( x : sort ) = let n = get_arity x in - let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (Sort.gc x) (Z3native.get_relation_column (Sort.gnc x) (Sort.gno x) i)) in mk_list f n - end module Datatype = struct - type datatype_sort = DatatypeSort of sort - type datatype_expr = DatatypeExpr of expr - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - DatatypeSort(s) - - let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x - - let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - - let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - - let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - module Constructor = struct type constructor = z3_native_object @@ -1517,24 +1345,24 @@ struct ) c - let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) + let get_num_constructors ( x : sort ) = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) - let get_constructors ( x : datatype_sort ) = + let get_constructors ( x : sort ) = let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in mk_list f n - let get_recognizers ( x : datatype_sort ) = + let get_recognizers ( x : sort ) = let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i) in mk_list f n - let get_accessors ( x : datatype_sort ) = + let get_accessors ( x : sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let fd = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + let g j = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) i j) in mk_list g ds ) in mk_list f n @@ -1543,467 +1371,133 @@ end module Enumeration = struct - type enum_sort = EnumSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = - let s = (sort_of_ptr ctx no) in - let res = EnumSort(s) in - res - - let sort_of_enum_sort s = match s with EnumSort(x) -> x - - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in - sort_of_ptr ctx a (list_of_array b) (list_of_array c) + let (a, _, _) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - let get_const_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + let get_const_decls ( x : sort ) = + let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in + let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i)) in mk_list f n - let get_tester_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + let get_tester_decls ( x : sort ) = + let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in + let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i)) in mk_list f n end module List_ = -struct - type list_sort = ListSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - let res = ListSort(s) in - res - - let sort_of_list_sort s = match s with ListSort(x) -> x - - let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - +struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - sort_of_ptr ctx r a b c d e f + let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + sort_of_ptr ctx r let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort - let get_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) + let get_nil_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 0) - let get_is_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) + let get_is_nil_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 0) - let get_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) + let get_cons_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 1) - let get_is_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) + let get_is_cons_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 1) - let get_head_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) + let get_head_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 0) - let get_tail_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) + let get_tail_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 1) - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] + let nil ( x : sort ) = expr_of_func_app (Sort.gc x) (get_nil_decl x) [] end module Tuple = struct - type tuple_sort = TupleSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - TupleSort(s) - - let sort_of_tuple_sort s = match s with TupleSort(x) -> x - - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in sort_of_ptr ctx r - let get_mk_decl ( x : tuple_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + let get_mk_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_mk_decl (Sort.gnc x) (Sort.gno x)) - let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) + let get_num_fields ( x : sort ) = Z3native.get_tuple_sort_num_fields (Sort.gnc x) (Sort.gno x) - let get_field_decls ( x : tuple_sort ) = + let get_field_decls ( x : sort ) = let n = get_num_fields x in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_field_decl (Sort.gnc x) (Sort.gno x) i) in mk_list f n end -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> arith_sort - val expr_of_arith_expr : arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> arith_expr +module Arithmetic = +struct - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr list -> arith_expr - val mk_mul : context -> arith_expr list -> arith_expr - val mk_sub : context -> arith_expr list -> arith_expr - val mk_unary_minus : context -> arith_expr -> arith_expr - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end = struct - type arith_sort = ArithSort of sort - type arith_expr = ArithExpr of expr - - let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - - let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) - - let sort_of_arith_sort s = match s with ArithSort(x) -> x - let expr_of_arith_expr e = match e with ArithExpr(x) -> x - - let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - - let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_sort_of_sort (sort_of_ptr ctx no) - - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (c_of_expr e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - - let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - - let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (int_expr_of_ptr ctx no) - - let arith_sort_of_int_sort s = match s with IntSort(x) -> x - let arith_expr_of_int_expr e = match e with IntExpr(x) -> x - let int_expr_of_int_num e = match e with IntNum(x) -> x - - let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - - let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) - - let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) - let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) - let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) - let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) - let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) - let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) - let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) - let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) - let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - + module Integer = + struct let mk_sort ( ctx : context ) = - int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) + sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + let get_int ( x : expr ) = + let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = - IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + Expr.mk_const ctx name (mk_sort ctx) let mk_int_const_s ( ctx : context ) ( name : string ) = mk_int_const ctx (Symbol.mk_string ctx name) - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + let mk_mod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_int2real ( ctx : context ) ( t : int_expr ) = - Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + let mk_int2real ( ctx : context ) ( t : expr ) = + (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (Expr.gno t))) - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : expr ) = + (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (Expr.gno t))) end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : real_sort -> arith_sort - val real_sort_of_arith_sort : arith_sort -> real_sort - val arith_expr_of_real_expr : real_expr -> arith_expr - val real_expr_of_rat_num : rat_num -> real_expr - val real_expr_of_arith_expr : arith_expr -> real_expr - val rat_num_of_real_expr : real_expr -> rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - let arith_sort_of_real_sort s = match s with RealSort(x) -> x - let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - let real_expr_of_rat_num e = match e with RatNum(x) -> x - - let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - - let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - - let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (real_expr_of_ptr ctx no) - - let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - - let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) - let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) - let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) - let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) - let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) - let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) - let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) - let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) - let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - - + module Real = + struct let mk_sort ( ctx : context ) = - real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) + sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - let get_numerator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + let get_numerator ( x : expr ) = + expr_of_ptr (Expr.gc x) (Z3native.get_numerator (Expr.gnc x) (Expr.gno x)) - let get_denominator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + let get_denominator ( x : expr ) = + expr_of_ptr (Expr.gc x) (Z3native.get_denominator (Expr.gnc x) (Expr.gno x)) - let to_decimal_string ( x : rat_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = - RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + Expr.mk_const ctx name (mk_sort ctx) let mk_real_const_s ( ctx : context ) ( name : string ) = mk_real_const ctx (Symbol.mk_string ctx name) @@ -2012,67 +1506,38 @@ end = struct if (den == 0) then raise (Z3native.Exception "Denominator is zero") else - rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) + expr_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) let mk_numeral_s ( ctx : context ) ( v : string ) = - rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_numeral_i ( ctx : context ) ( v : int ) = - rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + let mk_is_integer ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (Expr.gno t))) - let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + let mk_real2int ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (Expr.gno t))) end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x - - let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - - let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) - - let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) - let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) - let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - - - let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + module AlgebraicNumber = + struct + let to_upper ( x : expr ) ( precision : int ) = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) - let to_lower ( x : algebraic_num ) precision = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + let to_lower ( x : expr ) precision = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) end let is_int ( x : expr ) = - (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) @@ -2107,224 +1572,55 @@ end = struct let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - let mk_add ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_add ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_mul ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_mul ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_sub ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_sub ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) + let mk_unary_minus ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) - let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) + let mk_div ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) + let mk_power ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + let mk_le ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + let mk_gt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) + let mk_ge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) end -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - val mk_sort : context -> int -> bitvec_sort - val is_bv : Expr.expr -> bool - val is_bv_numeral : Expr.expr -> bool - val is_bv_bit1 : Expr.expr -> bool - val is_bv_bit0 : Expr.expr -> bool - val is_bv_uminus : Expr.expr -> bool - val is_bv_add : Expr.expr -> bool - val is_bv_sub : Expr.expr -> bool - val is_bv_mul : Expr.expr -> bool - val is_bv_sdiv : Expr.expr -> bool - val is_bv_udiv : Expr.expr -> bool - val is_bv_SRem : Expr.expr -> bool - val is_bv_urem : Expr.expr -> bool - val is_bv_smod : Expr.expr -> bool - val is_bv_sdiv0 : Expr.expr -> bool - val is_bv_udiv0 : Expr.expr -> bool - val is_bv_srem0 : Expr.expr -> bool - val is_bv_urem0 : Expr.expr -> bool - val is_bv_smod0 : Expr.expr -> bool - val is_bv_ule : Expr.expr -> bool - val is_bv_sle : Expr.expr -> bool - val is_bv_uge : Expr.expr -> bool - val is_bv_sge : Expr.expr -> bool - val is_bv_ult : Expr.expr -> bool - val is_bv_slt : Expr.expr -> bool - val is_bv_ugt : Expr.expr -> bool - val is_bv_sgt : Expr.expr -> bool - val is_bv_and : Expr.expr -> bool - val is_bv_or : Expr.expr -> bool - val is_bv_not : Expr.expr -> bool - val is_bv_xor : Expr.expr -> bool - val is_bv_nand : Expr.expr -> bool - val is_bv_nor : Expr.expr -> bool - val is_bv_xnor : Expr.expr -> bool - val is_bv_concat : Expr.expr -> bool - val is_bv_signextension : Expr.expr -> bool - val is_bv_zeroextension : Expr.expr -> bool - val is_bv_extract : Expr.expr -> bool - val is_bv_repeat : Expr.expr -> bool - val is_bv_reduceor : Expr.expr -> bool - val is_bv_reduceand : Expr.expr -> bool - val is_bv_comp : Expr.expr -> bool - val is_bv_shiftleft : Expr.expr -> bool - val is_bv_shiftrightlogical : Expr.expr -> bool - val is_bv_shiftrightarithmetic : Expr.expr -> bool - val is_bv_rotateleft : Expr.expr -> bool - val is_bv_rotateright : Expr.expr -> bool - val is_bv_rotateleftextended : Expr.expr -> bool - val is_bv_rotaterightextended : Expr.expr -> bool - val is_int_to_bv : Expr.expr -> bool - val is_bv_to_int : Expr.expr -> bool - val is_bv_carry : Expr.expr -> bool - val is_bv_xor3 : Expr.expr -> bool - val get_size : bitvec_sort -> int - val get_int : bitvec_num -> int - val to_string : bitvec_num -> string - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - val mk_const_s : context -> string -> int -> bitvec_expr - val mk_not : context -> bitvec_expr -> Expr.expr - val mk_redand : context -> bitvec_expr -> Expr.expr - val mk_redor : context -> bitvec_expr -> Expr.expr - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_neg : context -> bitvec_expr -> bitvec_expr - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_numeral : context -> string -> int -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of sort - type bitvec_expr = BitVecExpr of expr - type bitvec_num = BitVecNum of bitvec_expr - - let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x - - let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - - let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_sort_of_sort (sort_of_ptr ctx no) - - let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - - let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_expr_of_expr (expr_of_ptr ctx no) - - let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - - let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) - - let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x - let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - - - let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) - let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) - let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (c_of_expr e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (nc_of_expr e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (ptr_of_expr e) - let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) - let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) - let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - - +module BitVector = +struct let mk_sort ( ctx : context ) size = - bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) + sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) @@ -2376,112 +1672,112 @@ end = struct let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) + let get_int ( x : expr ) = + let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) + Expr.mk_const ctx name (mk_sort ctx size) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = mk_const ctx (Symbol.mk_string ctx name) size - let mk_not ( ctx : context ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - let mk_redand ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - let mk_redor ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - let mk_neg ( ctx : context ) ( t : bitvec_expr) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_not ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (Expr.gno t)) + let mk_redand ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (Expr.gno t)) + let mk_redor ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (Expr.gno t)) + let mk_and ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_or ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_nand ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_nor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_xnor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_neg ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (Expr.gno t)) + let mk_add ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_sub ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_mul ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_udiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_sdiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_urem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_srem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_smod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ult ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_slt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_ule ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sle ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_uge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_ugt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sgt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_concat ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (Expr.gno t)) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (Expr.gno t)) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (Expr.gno t)) + let mk_repeat ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (Expr.gno t)) + let mk_shl ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_lshr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ashr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (Expr.gno t)) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (Expr.gno t)) + let mk_ext_rotate_left ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ext_rotate_right ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_bv2int ( ctx : context ) ( t : expr ) ( signed : bool ) = + expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (Expr.gno t) signed) + let mk_add_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_add_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sub_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sub_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_neg_no_overflow ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (Expr.gno t))) + let mk_mul_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_mul_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx size))) end @@ -2556,8 +1852,8 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in + let assert_ ( x : goal ) ( constraints : expr list ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e) in ignore (List.map f constraints) ; () @@ -2572,7 +1868,7 @@ struct let get_formulas ( x : goal ) = let n = get_size x in - let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + let f i = ((expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in mk_list f n @@ -2749,7 +2045,7 @@ struct exception ModelEvaluationFailedException of string let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else @@ -3076,19 +2372,19 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + let assert_ ( x : solver ) ( constraints : expr list ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + let assert_and_track_a ( x : solver ) ( cs : expr list ) ( ps : expr list ) = if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno a) (Expr.gno b)) in ignore (List.iter2 f cs ps) - let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) + let assert_and_track ( x : solver ) ( c : expr ) ( p : expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno c) (Expr.gno p) let get_num_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in @@ -3097,15 +2393,15 @@ struct let get_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + let f i = (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in mk_list f n - let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = + let check ( x : solver ) ( assumptions : expr list ) = let r = if ((List.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in + let f x = (Expr.gno x) in lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) in match r with @@ -3179,24 +2475,24 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + let assert_ ( x : fixedpoint ) ( constraints : expr list ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) ; () let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno y) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) - let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + let query ( x : fixedpoint ) ( query : expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Expr.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -3214,8 +2510,8 @@ struct let pop ( x : fixedpoint ) = Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno name) let get_answer ( x : fixedpoint ) = let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in @@ -3238,27 +2534,27 @@ struct Some (expr_of_ptr (z3obj_gc x) q) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = - let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in + let to_string_q ( x : fixedpoint ) ( queries : expr list ) = + let f x = Expr.gno x in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let mk_fixedpoint ( ctx : context ) = create ctx @@ -3287,10 +2583,10 @@ end module SMT = struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : expr list ) ( formula : expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) - (Boolean.gno formula) + (List.length assumptions) (let f x = Expr.gno (x) in (Array.of_list (List.map f assumptions))) + (Expr.gno formula) let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = let csn = (List.length sort_names) in @@ -3328,14 +2624,14 @@ struct let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + let f i =(expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in mk_list f n let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + let f i = (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in mk_list f n let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) @@ -3360,14 +2656,14 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - + (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = let csn = (List.length sort_names) in let cs = (List.length sorts) in @@ -3376,13 +2672,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml new file mode 100644 index 000000000..052ca5e22 --- /dev/null +++ b/src/api/ml/z3_rich.ml @@ -0,0 +1,3400 @@ +(** + The Z3 ML/Ocaml Interface. + + Copyright (C) 2012 Microsoft Corporation + @author CM Wintersteiger (cwinter) 2012-12-17 +*) + +open Z3enums + +(* Some helpers. *) +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) + + +(* Internal types *) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = z3_native_context + +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } + + +(** Internal stuff *) +module Internal = +struct + let dispose_context ctx = + if ctx.m_n_obj_cnt == 0 then ( + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; + ) + + let create_context settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + + let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) + let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) + let context_gno ctx = ctx.m_n_ctx + + + let z3obj_gc o = o.m_ctx + let z3obj_gnc o = (context_gno o.m_ctx) + + let z3obj_gno o = o.m_n_obj + let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + + let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + + let z3obj_create o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + + let z3obj_nil_ref x y = () + + let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res +end + +open Internal + +module Log = +struct + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) + let close = Z3native.close_log + let append s = Z3native.append_log s +end + + +module Version = +struct + let major = let (x, _, _, _) = Z3native.get_version in x + let minor = let (_, x, _, _) = Z3native.get_version in x + let build = let (_, _, x, _) = Z3native.get_version in x + let revision = let (_, _, _, x) = Z3native.get_version in x + let to_string = + let (mj, mn, bld, rev) = Z3native.get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + + +let mk_list ( f : int -> 'a ) ( n : int ) = + let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = + if (i >= n) then + tail + else + (mk_list' f (i+1) n ((f i) :: tail)) + in + mk_list' f 0 n [] + +let list_of_array ( x : _ array ) = + let f i = (Array.get x i) in + mk_list f (Array.length x) + +let mk_context ( cfg : ( string * string ) list ) = + create_context cfg + + +module Symbol = +struct + (* Symbol types *) + type int_symbol = z3_native_object + type string_symbol = z3_native_object + + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + + + let create_i ( ctx : context ) ( no : Z3native.ptr ) = + let res : int_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let create_s ( ctx : context ) ( no : Z3native.ptr ) = + let res : string_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) + + let gc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gc n) + | S_Str(n) -> (z3obj_gc n) + + let gnc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gnc n) + | S_Str(n) -> (z3obj_gnc n) + + let gno ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gno n) + | S_Str(n) -> (z3obj_gno n) + + let symbol_lton ( a : symbol list ) = + let f ( e : symbol ) = (gno e) in + Array.of_list (List.map f a) + + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) + let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL + let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL + let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + let to_string ( o : symbol ) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) + | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) + + let mk_int ( ctx : context ) ( i : int ) = + S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + + let mk_string ( ctx : context ) ( s : string ) = + S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + + let mk_ints ( ctx : context ) ( names : int list ) = + let f elem = mk_int ( ctx : context ) elem in + (List.map f names) + + let mk_strings ( ctx : context ) ( names : string list ) = + let f elem = mk_string ( ctx : context ) elem in + (List.map f names) +end + + +module AST = +struct + type ast = z3_native_object + + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + + module ASTVector = + struct + type ast_vector = z3_native_object + + let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_vector = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_vector_inc_ref ; + dec_ref = Z3native.ast_vector_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) + + let get ( x : ast_vector ) ( i : int ) = + ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) + + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size + + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) + + let translate ( x : ast_vector ) ( to_ctx : context ) = + ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) + end + + module ASTMap = + struct + type ast_map = z3_native_object + + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let contains ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) + + let find ( x : ast_map ) ( key : ast ) = + ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) + + let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) + + let erase ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) + + let reset ( x : ast_map ) = + Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : ast_map ) = + Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) + + let get_keys ( x : ast_map ) = + let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let f i = (ASTVector.get av i) in + mk_list f (ASTVector.get_size av) + + let to_string ( x : ast_map ) = + Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) + let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) + let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) + + let is_expr ( x : ast ) = + match get_ast_kind ( x : ast ) with + | APP_AST + | NUMERAL_AST + | QUANTIFIER_AST + | VAR_AST -> true + | _ -> false + + let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST + let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST + let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST + let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST + + let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) + let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) + + + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + if (z3obj_gnc a) != (z3obj_gnc b) then + false + else + Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) + + let compare a b = + if (get_id a) < (get_id b) then -1 else + if (get_id a) > (get_id b) then 1 else + 0 + + let ( < ) (a : ast) (b : ast) = (compare a b) + + let translate ( x : ast ) ( to_ctx : context ) = + if (z3obj_gnc x) == (context_gno to_ctx) then + x + else + ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr + let unwrap_ast ( x : ast ) = (z3obj_gno x) +end + +open AST + + +module Sort = +struct + type sort = Sort of AST.ast + type uninterpreted_sort = UninterpretedSort of sort + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let ast_of_sort s = match s with Sort(x) -> x + let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x + + let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) + let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) + let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let sort_lton ( a : sort list ) = + let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) + + let ( = ) : sort -> sort -> bool = fun a b -> + (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) + + + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) + let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) + let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) + let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) + + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; + (z3obj_create res) ; + UninterpretedSort(Sort(res)) + + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) +end + +open Sort + + +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + val func_decl_of_ptr : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context + val gnc : func_decl -> Z3native.ptr + val gno : func_decl -> Z3native.ptr + module Parameter : + sig + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + val get_kind : parameter -> Z3enums.parameter_kind + val get_int : parameter -> int + val get_float : parameter -> float + val get_symbol : parameter -> Symbol.symbol + val get_sort : parameter -> Sort.sort + val get_ast : parameter -> AST.ast + val get_func_decl : parameter -> func_decl + val get_rational : parameter -> string + end + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + val ( = ) : func_decl -> func_decl -> bool + val to_string : func_decl -> string + val get_id : func_decl -> int + val get_arity : func_decl -> int + val get_domain_size : func_decl -> int + val get_domain : func_decl -> Sort.sort list + val get_range : func_decl -> Sort.sort + val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_name : func_decl -> Symbol.symbol + val get_num_parameters : func_decl -> int + val get_parameters : func_decl -> Parameter.parameter list + val apply : func_decl -> Expr.expr list -> Expr.expr +end = struct + type func_decl = FuncDecl of AST.ast + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let ast_of_func_decl f = match f with FuncDecl(x) -> x + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) + let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) + + module Parameter = + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + let get_kind ( x : parameter ) = + (match x with + | P_Int(_) -> PARAMETER_INT + | P_Dbl(_) -> PARAMETER_DOUBLE + | P_Sym(_) -> PARAMETER_SYMBOL + | P_Srt(_) -> PARAMETER_SORT + | P_Ast(_) -> PARAMETER_AST + | P_Fdl(_) -> PARAMETER_FUNC_DECL + | P_Rat(_) -> PARAMETER_RATIONAL) + + let get_int ( x : parameter ) = + match x with + | P_Int(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an int") + + let get_float ( x : parameter ) = + match x with + | P_Dbl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a double") + + let get_symbol ( x : parameter ) = + match x with + | P_Sym(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a symbol") + + let get_sort ( x : parameter ) = + match x with + | P_Srt(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a sort") + + let get_ast ( x : parameter ) = + match x with + | P_Ast(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an ast") + + let get_func_decl ( x : parameter ) = + match x with + | P_Fdl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a func_decl") + + let get_rational ( x : parameter ) = + match x with + | P_Rat(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a rational string") + end + + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = + create_ndr ctx name domain range + + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = + mk_func_decl ctx (Symbol.mk_string ctx name) domain range + + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = + create_pdr ctx prefix domain range + + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_ndr ctx name [] range + + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + create_ndr ctx (Symbol.mk_string ctx name) [] range + + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + create_pdr ctx prefix [] range + + + let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) + + let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) + + let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) + + let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) + + let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) + + let get_domain ( x : func_decl ) = + let n = (get_domain_size x) in + let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + mk_list f n + + let get_range ( x : func_decl ) = + sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) + + let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) + + let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) + + let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) + + let get_parameters ( x : func_decl ) = + let n = (get_num_parameters x) in + let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + ) in + mk_list f n + + let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args +end + + +and Params : +sig + type params = z3_native_object + module ParamDescrs : + sig + type param_descrs + val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + val get_names : param_descrs -> Symbol.symbol list + val get_size : param_descrs -> int + val to_string : param_descrs -> string + end + val add_bool : params -> Symbol.symbol -> bool -> unit + val add_int : params -> Symbol.symbol -> int -> unit + val add_double : params -> Symbol.symbol -> float -> unit + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + val add_s_bool : params -> string -> bool -> unit + val add_s_int : params -> string -> int -> unit + val add_s_double : params -> string -> float -> unit + val add_s_symbol : params -> string -> Symbol.symbol -> unit + val mk_params : context -> params + val to_string : params -> string +end = struct + type params = z3_native_object + + module ParamDescrs = + struct + type param_descrs = z3_native_object + + let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : param_descrs = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.param_descrs_inc_ref ; + dec_ref = Z3native.param_descrs_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let validate ( x : param_descrs ) ( p : params ) = + Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) + + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) + + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in + let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) + + let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = + add_bool x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_int ( x : params) ( name : string ) ( value : int ) = + add_int x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_double ( x : params ) ( name : string ) ( value : float ) = + add_double x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + add_symbol x (Symbol.mk_string (z3obj_gc x) name) value + + let mk_params ( ctx : context ) = + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; + (z3obj_create res) ; + res + + let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) +end + +(** General expressions (terms) *) +and Expr : +sig + type expr = Expr of AST.ast + val expr_of_ptr : context -> Z3native.ptr -> expr + val gc : expr -> context + val gnc : expr -> Z3native.ptr + val gno : expr -> Z3native.ptr + val expr_lton : expr list -> Z3native.ptr array + val ast_of_expr : expr -> AST.ast + val expr_of_ast : AST.ast -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr + val simplify : expr -> Params.params option -> expr + val get_simplify_help : context -> string + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + val get_func_decl : expr -> FuncDecl.func_decl + val get_bool_value : expr -> Z3enums.lbool + val get_num_args : expr -> int + val get_args : expr -> expr list + val update : expr -> expr list -> expr + val substitute : expr -> expr list -> expr list -> expr + val substitute_one : expr -> expr -> expr -> expr + val substitute_vars : expr -> expr list -> expr + val translate : expr -> context -> expr + val to_string : expr -> string + val is_numeral : expr -> bool + val is_well_sorted : expr -> bool + val get_sort : expr -> Sort.sort + val is_bool : expr -> bool + val is_const : expr -> bool + val is_true : expr -> bool + val is_false : expr -> bool + val is_eq : expr -> bool + val is_distinct : expr -> bool + val is_ite : expr -> bool + val is_and : expr -> bool + val is_or : expr -> bool + val is_iff : expr -> bool + val is_xor : expr -> bool + val is_not : expr -> bool + val is_implies : expr -> bool + val is_label : expr -> bool + val is_label_lit : expr -> bool + val is_oeq : expr -> bool + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val mk_const_s : context -> string -> Sort.sort -> expr + val mk_const_f : context -> FuncDecl.func_decl -> expr + val mk_fresh_const : context -> string -> Sort.sort -> expr + val mk_app : context -> FuncDecl.func_decl -> expr list -> expr + val mk_numeral_string : context -> string -> Sort.sort -> expr + val mk_numeral_int : context -> int -> Sort.sort -> expr +end = struct + type expr = Expr of AST.ast + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + + let ast_of_expr e = match e with Expr(a) -> a + + let expr_lton ( a : expr list ) = + let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) + + let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> + match f with FuncDecl.FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in + expr_of_ptr ctx o + + let simplify ( x : expr ) ( p : Params.params option ) = match p with + | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (Expr.gnc x) (Expr.gno x)) + | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (Expr.gnc x) (Expr.gno x) (z3obj_gno pp)) + + let get_simplify_help ( ctx : context ) = + Z3native.simplify_get_help (context_gno ctx) + + let get_simplify_parameter_descrs ( ctx : context ) = + Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (Expr.gnc x) (Expr.gno x)) + + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (Expr.gnc x) (Expr.gno x)) + + let get_num_args ( x : expr ) = Z3native.get_app_num_args (Expr.gnc x) (Expr.gno x) + + let get_args ( x : expr ) = let n = (get_num_args x) in + let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (Expr.gnc x) (Expr.gno x) i) in + mk_list f n + + let update ( x : expr ) ( args : expr list ) = + if (List.length args <> (get_num_args x)) then + raise (Z3native.Exception "Number of arguments does not match") + else + expr_of_ptr (Expr.gc x) (Z3native.update_term (Expr.gnc x) (Expr.gno x) (List.length args) (expr_lton args)) + + let substitute ( x : expr ) from to_ = + if (List.length from) <> (List.length to_) then + raise (Z3native.Exception "Argument sizes do not match") + else + expr_of_ptr (Expr.gc x) (Z3native.substitute (Expr.gnc x) (Expr.gno x) (List.length from) (expr_lton from) (expr_lton to_)) + + let substitute_one ( x : expr ) from to_ = + substitute ( x : expr ) [ from ] [ to_ ] + + let substitute_vars ( x : expr ) to_ = + expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (Expr.gnc x) (Expr.gno x) (List.length to_) (expr_lton to_)) + + let translate ( x : expr ) to_ctx = + if (Expr.gc x) == to_ctx then + x + else + expr_of_ptr to_ctx (Z3native.translate (Expr.gnc x) (Expr.gno x) (context_gno to_ctx)) + + let to_string ( x : expr ) = Z3native.ast_to_string (Expr.gnc x) (Expr.gno x) + + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) + + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (Expr.gnc x) (Expr.gno x) + + let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)) + + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (Expr.gnc x) + (Z3native.mk_bool_sort (Expr.gnc x)) + (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) + + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (get_num_args x) == 0 && + (FuncDecl.get_domain_size (get_func_decl x)) == 0 + + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) + + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = + mk_const ctx (Symbol.mk_string ctx name) range + + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] + + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) + + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args + + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) + + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) +end + +open FuncDecl +open Expr + +module Boolean = +struct + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.ast_of_ptr ctx no) in + BoolExpr(Expr.Expr(a)) + + let bool_expr_of_expr e = + match e with Expr.Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) + + let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(sort_of_ptr ctx no) + + let sort_of_bool_sort s = match s with BoolSort(x) -> x + + let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + + let expr_of_bool_expr e = match e with BoolExpr(x) -> x + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) + + let mk_sort ( ctx : context ) = + BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let s = (match (mk_sort ctx) with BoolSort(q) -> q) in + BoolExpr(Expr.mk_const ctx name s) + + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) + + let mk_true ( ctx : context ) = + bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) + + let mk_false ( ctx : context ) = + bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) + + let mk_val ( ctx : context ) ( value : bool ) = + if value then mk_true ctx else mk_false ctx + + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + let mk_distinct ( ctx : context ) ( args : expr list ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_not ( ctx : context ) ( a : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + + let mk_and ( ctx : context ) ( args : bool_expr list ) = + let f x = (Expr.gno (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) + + let mk_or ( ctx : context ) ( args : bool_expr list ) = + let f x = (Expr.gno (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) +end + + +module Quantifier = +struct + type quantifier = Quantifier of expr + + let expr_of_quantifier e = match e with Quantifier(x) -> x + + let quantifier_of_expr e = + match e with Expr.Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) + + module Pattern = + struct + type pattern = Pattern of ast + + let ast_of_pattern e = match e with Pattern(x) -> x + + let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms (gnc x) (gno x) + + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + mk_list f n + + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + end + + let get_index ( x : expr ) = + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) + + let is_universal ( x : quantifier ) = + Z3native.is_quantifier_forall (gnc x) (gno x) + + let is_existential ( x : quantifier ) = not (is_universal x) + + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) + + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) + + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + mk_list f n + + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) + + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + mk_list f n + + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) + + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in + mk_list f n + + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in + mk_list f n + + let get_body ( x : quantifier ) = + Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) + + let mk_pattern ( ctx : context ) ( terms : expr list ) = + if (List.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) + + let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + + let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (Expr.gno body))) + + let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + + let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (Expr.gno body))) + + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (universal) then + (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + else + (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (universal) then + mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + else + mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id +end + + +module Array_ = +struct + type array_sort = ArraySort of sort + type array_expr = ArrayExpr of expr + + let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (expr_of_ptr ctx no) in + ArrayExpr(e) + + let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + ArraySort(s) + + let sort_of_array_sort s = match s with ArraySort(x) -> x + + let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + + let array_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + + let expr_of_array_expr e = match e with ArrayExpr(x) -> x + + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) + + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) + + let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = + array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_array ( x : expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) + + let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = + ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) + + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + mk_const ctx (Symbol.mk_string ctx name) domain range + + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) + + let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) + + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) + + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = + let m x = (Expr.gno (expr_of_array_expr x)) in + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) + + let mk_term_array ( ctx : context ) ( arg : array_expr ) = + array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) +end + + +module Set = +struct + type set_sort = SetSort of sort + + let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + SetSort(s) + + let sort_of_set_sort s = match s with SetSort(x) -> x + + let mk_sort ( ctx : context ) ( ty : sort ) = + set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + + + let mk_empty ( ctx : context ) ( domain : sort ) = + (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) + + let mk_full ( ctx : context ) ( domain : sort ) = + expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) + + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) + + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) + + let mk_union ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_intersection ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + + let mk_complement ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) + + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) + + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + +end + + +module FiniteDomain = +struct + type finite_domain_sort = FiniteDomainSort of sort + + let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x + + let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in + FiniteDomainSort(s) + + let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_sort ctx (Symbol.mk_string ctx name) size + + + let is_finite_domain ( x : expr ) = + let nc = (Expr.gnc x) in + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) + + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + + let get_size ( x : finite_domain_sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in + if r then v + else raise (Z3native.Exception "Conversion failed.") +end + + +module Relation = +struct + type relation_sort = RelationSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + RelationSort(s) + + let sort_of_relation_sort s = match s with RelationSort(x) -> x + + let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) + + + let is_relation ( x : expr ) = + let nc = (Expr.gnc x) in + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) + + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + + let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) + + let get_column_sorts ( x : relation_sort ) = + let n = get_arity x in + let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + mk_list f n + +end + + +module Datatype = +struct + type datatype_sort = DatatypeSort of sort + type datatype_expr = DatatypeExpr of expr + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + DatatypeSort(s) + + let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x + + let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + + let datatype_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + + let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) + + module Constructor = + struct + type constructor = z3_native_object + + let _sizes = Hashtbl.create 0 + + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let n = (List.length field_names) in + if n != (List.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if n != (List.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) + (Symbol.gno recognizer) + n + (Symbol.symbol_lton field_names) + (sort_lton sorts) + (Array.of_list sort_refs)) in + let no : constructor = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + (z3obj_sno no ctx ptr) ; + (z3obj_create no) ; + let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f no ; + Hashtbl.add _sizes no n ; + no + + let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x + + let get_constructor_decl ( x : constructor ) = + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + func_decl_of_ptr (z3obj_gc x) a + + let get_tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + func_decl_of_ptr (z3obj_gc x) b + + let get_accessor_decls ( x : constructor ) = + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in + mk_list f (Array.length c) + + end + + module ConstructorList = + struct + type constructor_list = z3_native_object + + let create ( ctx : context ) ( c : Constructor.constructor list ) = + let res : constructor_list = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + let f x =(z3obj_gno x) in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; + (z3obj_create res) ; + let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f res; + res + end + + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + Constructor.create ctx name recognizer field_names sorts sort_refs + + + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = + let f x = (z3obj_gno x) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in + sort_of_ptr ctx x + + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = + mk_sort ctx (Symbol.mk_string ctx name) constructors + + let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = + let n = (List.length names) in + let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in + let cla = (Array.of_list (List.map f c)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in + let g i = (sort_of_ptr ctx (Array.get r i)) in + mk_list g (Array.length r) + + let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = + mk_sorts ctx + ( + let f e = (Symbol.mk_string ctx e) in + List.map f names + ) + c + + let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) + + let get_constructors ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + mk_list f n + + let get_recognizers ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + mk_list f n + + let get_accessors ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = ( + let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in + let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + mk_list g ds + ) in + mk_list f n +end + + +module Enumeration = +struct + type enum_sort = EnumSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = + let s = (sort_of_ptr ctx no) in + let res = EnumSort(s) in + res + + let sort_of_enum_sort s = match s with EnumSort(x) -> x + + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a (list_of_array b) (list_of_array c) + + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = + mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) + + let get_const_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + mk_list f n + + let get_tester_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + mk_list f n + +end + + +module List_ = +struct + type list_sort = ListSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + let res = ListSort(s) in + res + + let sort_of_list_sort s = match s with ListSort(x) -> x + + let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + sort_of_ptr ctx r a b c d e f + + let mk_list_s ( ctx : context ) (name : string) elem_sort = + mk_sort ctx (Symbol.mk_string ctx name) elem_sort + + let get_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) + + let get_is_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) + + let get_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) + + let get_is_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) + + let get_head_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) + + let get_tail_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) + + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] +end + + +module Tuple = +struct + type tuple_sort = TupleSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + TupleSort(s) + + let sort_of_tuple_sort s = match s with TupleSort(x) -> x + + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in + sort_of_ptr ctx r + + let get_mk_decl ( x : tuple_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + + let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) + + let get_field_decls ( x : tuple_sort ) = + let n = get_num_fields x in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + mk_list f n +end + + +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> arith_sort + val expr_of_arith_expr : arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> arith_expr + + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end + + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr list -> arith_expr + val mk_mul : context -> arith_expr list -> arith_expr + val mk_sub : context -> arith_expr list -> arith_expr + val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end = struct + type arith_sort = ArithSort of sort + type arith_expr = ArithExpr of expr + + let arith_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + + let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_expr_of_expr (expr_of_ptr ctx no) + + let sort_of_arith_sort s = match s with ArithSort(x) -> x + let expr_of_arith_expr e = match e with ArithExpr(x) -> x + + let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + + let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_sort_of_sort (sort_of_ptr ctx no) + + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + + let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + + let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_num_of_int_expr (int_expr_of_ptr ctx no) + + let arith_sort_of_int_sort s = match s with IntSort(x) -> x + let arith_expr_of_int_expr e = match e with IntExpr(x) -> x + let int_expr_of_int_num e = match e with IntNum(x) -> x + + let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + + let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) + + let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) + let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) + let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) + let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) + let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) + let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) + let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) + let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) + let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + + let mk_sort ( ctx : context ) = + int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) + + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + + let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx (Symbol.mk_string ctx name) + + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_int2real ( ctx : context ) ( t : int_expr ) = + Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + end + + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : real_sort -> arith_sort + val real_sort_of_arith_sort : arith_sort -> real_sort + val arith_expr_of_real_expr : real_expr -> arith_expr + val real_expr_of_rat_num : rat_num -> real_expr + val real_expr_of_arith_expr : arith_expr -> real_expr + val rat_num_of_real_expr : real_expr -> rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let arith_sort_of_real_sort s = match s with RealSort(x) -> x + let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + let real_expr_of_rat_num e = match e with RatNum(x) -> x + + let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + + let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + + let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + rat_num_of_real_expr (real_expr_of_ptr ctx no) + + let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + + let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) + + let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) + let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) + let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) + let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) + let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) + let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) + let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) + let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) + let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) + + + let mk_sort ( ctx : context ) = + real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) + + let get_numerator ( x : rat_num ) = + Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + + let get_denominator ( x : rat_num ) = + Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + + let to_decimal_string ( x : rat_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx (Symbol.mk_string ctx name) + + let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) + + let mk_numeral_s ( ctx : context ) ( v : string ) = + rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_numeral_i ( ctx : context ) ( v : int ) = + rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + + let mk_real2int ( ctx : context ) ( t : real_expr ) = + Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + end + + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x + + let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + + let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) + let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) + let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + + + let to_upper ( x : algebraic_num ) ( precision : int ) = + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + + let to_lower ( x : algebraic_num ) precision = + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + end + + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) + + let mk_add ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_mul ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_sub ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) + + let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) + + let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) + + let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + + let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + + let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + + let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) +end + + +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + val mk_sort : context -> int -> bitvec_sort + val is_bv : Expr.expr -> bool + val is_bv_numeral : Expr.expr -> bool + val is_bv_bit1 : Expr.expr -> bool + val is_bv_bit0 : Expr.expr -> bool + val is_bv_uminus : Expr.expr -> bool + val is_bv_add : Expr.expr -> bool + val is_bv_sub : Expr.expr -> bool + val is_bv_mul : Expr.expr -> bool + val is_bv_sdiv : Expr.expr -> bool + val is_bv_udiv : Expr.expr -> bool + val is_bv_SRem : Expr.expr -> bool + val is_bv_urem : Expr.expr -> bool + val is_bv_smod : Expr.expr -> bool + val is_bv_sdiv0 : Expr.expr -> bool + val is_bv_udiv0 : Expr.expr -> bool + val is_bv_srem0 : Expr.expr -> bool + val is_bv_urem0 : Expr.expr -> bool + val is_bv_smod0 : Expr.expr -> bool + val is_bv_ule : Expr.expr -> bool + val is_bv_sle : Expr.expr -> bool + val is_bv_uge : Expr.expr -> bool + val is_bv_sge : Expr.expr -> bool + val is_bv_ult : Expr.expr -> bool + val is_bv_slt : Expr.expr -> bool + val is_bv_ugt : Expr.expr -> bool + val is_bv_sgt : Expr.expr -> bool + val is_bv_and : Expr.expr -> bool + val is_bv_or : Expr.expr -> bool + val is_bv_not : Expr.expr -> bool + val is_bv_xor : Expr.expr -> bool + val is_bv_nand : Expr.expr -> bool + val is_bv_nor : Expr.expr -> bool + val is_bv_xnor : Expr.expr -> bool + val is_bv_concat : Expr.expr -> bool + val is_bv_signextension : Expr.expr -> bool + val is_bv_zeroextension : Expr.expr -> bool + val is_bv_extract : Expr.expr -> bool + val is_bv_repeat : Expr.expr -> bool + val is_bv_reduceor : Expr.expr -> bool + val is_bv_reduceand : Expr.expr -> bool + val is_bv_comp : Expr.expr -> bool + val is_bv_shiftleft : Expr.expr -> bool + val is_bv_shiftrightlogical : Expr.expr -> bool + val is_bv_shiftrightarithmetic : Expr.expr -> bool + val is_bv_rotateleft : Expr.expr -> bool + val is_bv_rotateright : Expr.expr -> bool + val is_bv_rotateleftextended : Expr.expr -> bool + val is_bv_rotaterightextended : Expr.expr -> bool + val is_int_to_bv : Expr.expr -> bool + val is_bv_to_int : Expr.expr -> bool + val is_bv_carry : Expr.expr -> bool + val is_bv_xor3 : Expr.expr -> bool + val get_size : bitvec_sort -> int + val get_int : bitvec_num -> int + val to_string : bitvec_num -> string + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> bitvec_expr + val mk_not : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_numeral : context -> string -> int -> bitvec_num +end = struct + type bitvec_sort = BitVecSort of sort + type bitvec_expr = BitVecExpr of expr + type bitvec_num = BitVecNum of bitvec_expr + + let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x + + let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + + let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_sort_of_sort (sort_of_ptr ctx no) + + let bitvec_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + + let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_expr_of_expr (expr_of_ptr ctx no) + + let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + + let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) + + let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x + let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + + + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) + let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) + let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) + let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) + let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) + + + let mk_sort ( ctx : context ) size = + bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) + let is_bv ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) + let get_int ( x : bitvec_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) + let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_const ctx (Symbol.mk_string ctx name) size + let mk_not ( ctx : context ) ( t : bitvec_expr ) = + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) + let mk_redand ( ctx : context ) ( t : bitvec_expr) = + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) + let mk_redor ( ctx : context ) ( t : bitvec_expr) = + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) + let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + let mk_neg ( ctx : context ) ( t : bitvec_expr) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) + let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) + let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) + let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) + let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) + let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) + let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) + let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) + let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = + Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) + let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) + let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = + bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) +end + + +module Proof = +struct + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) +end + + +module Goal = +struct + type goal = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : goal = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.goal_inc_ref ; + dec_ref = Z3native.goal_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_precision ( x : goal ) = + goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) + + let is_precise ( x : goal ) = + (get_precision x) == GOAL_PRECISE + + let is_underapproximation ( x : goal ) = + (get_precision x) == GOAL_UNDER + + let is_overapproximation ( x : goal ) = + (get_precision x) == GOAL_OVER + + let is_garbage ( x : goal ) = + (get_precision x) == GOAL_UNDER_OVER + + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in + ignore (List.map f constraints) ; + () + + let is_inconsistent ( x : goal ) = + Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) + + let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) + + let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) + + let get_formulas ( x : goal ) = + let n = get_size x in + let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in + mk_list f n + + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) + + let is_decided_sat ( x : goal ) = + Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) + + let is_decided_unsat ( x : goal ) = + Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) + + let translate ( x : goal ) ( to_ctx : context ) = + create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let simplify ( x : goal ) ( p : Params.params option ) = + let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in + Z3native.tactic_inc_ref (z3obj_gnc x) tn ; + let arn = match p with + | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) + | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) + in + Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; + let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in + let res = if sg == 0 then + raise (Z3native.Exception "No subgoals") + else + Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in + Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; + Z3native.tactic_dec_ref (z3obj_gnc x) tn ; + create (z3obj_gc x) res + + let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = + create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + + let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Model = +struct + type model = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : model = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module FuncInterp = + struct + type func_interp = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_interp = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_interp_inc_ref ; + dec_ref = Z3native.func_interp_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module FuncEntry = + struct + type func_entry = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_entry = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_entry_inc_ref ; + dec_ref = Z3native.func_entry_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_value ( x : func_entry ) = + expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) + + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) + + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) + + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (List.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in + if (Z3native.is_null np) then + None + else + Some (expr_of_ptr (z3obj_gc x) np) + + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if not (Z3native.is_as_array (z3obj_gnc x) n) then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in + get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in + if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) + + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) + + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + (mk_list f n_funcs) @ (mk_list g n_consts) + + exception ModelEvaluationFailedException of string + + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in + if not r then + raise (ModelEvaluationFailedException "evaluation failed") + else + expr_of_ptr (z3obj_gc x) v + + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) + + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + mk_list f n + + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Probe = +struct + type probe = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : probe = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.probe_inc_ref ; + dec_ref = Z3native.probe_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + + let apply ( x : probe ) ( g : Goal.goal ) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) + + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes (context_gno ctx) + + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in + mk_list f n + + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr (context_gno ctx) name + + let mk_probe ( ctx : context ) ( name : string ) = + (create ctx (Z3native.mk_probe (context_gno ctx) name)) + + let const ( ctx : context ) ( v : float ) = + (create ctx (Z3native.probe_const (context_gno ctx) v)) + + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let not_ ( ctx : context ) ( p : probe ) = + (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) +end + + +module Tactic = +struct + type tactic = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : tactic = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.tactic_inc_ref ; + dec_ref = Z3native.tactic_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module ApplyResult = + struct + type apply_result = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : apply_result = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.apply_result_inc_ref ; + dec_ref = Z3native.apply_result_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) + + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_subgoal ( x : apply_result ) ( i : int ) = + Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + + let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) + + let get_param_descrs ( x : tactic ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = + match p with + | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) + + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) + + let get_tactic_names ( ctx : context ) = + let n = (get_num_tactics ctx ) in + let f i = (Z3native.get_tactic_name (context_gno ctx) i) in + mk_list f n + + let get_tactic_description ( ctx : context ) ( name : string ) = + Z3native.tactic_get_descr (context_gno ctx) name + + let mk_tactic ( ctx : context ) ( name : string ) = + create ctx (Z3native.mk_tactic (context_gno ctx) name) + + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = + let f p c = (match p with + | None -> (Some (z3obj_gno c)) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in + match (List.fold_left f None ts) with + | None -> + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + | Some(x) -> + let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) + + let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + + let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = + create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) + + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) + + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) + + let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = + create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) + + let skip ( ctx : context ) = + create ctx (Z3native.tactic_skip (context_gno ctx)) + + let fail ( ctx : context ) = + create ctx (Z3native.tactic_fail (context_gno ctx)) + + let fail_if ( ctx : context ) ( p : Probe.probe ) = + create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + + let fail_if_not_decided ( ctx : context ) = + create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) + + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + using_params ctx t p + + let par_or ( ctx : context ) ( t : tactic list ) = + let f e = (z3obj_gno e) in + create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) + + let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + + let interrupt ( ctx : context ) = + Z3native.interrupt (context_gno ctx) +end + + +module Solver = +struct + type solver = z3_native_object + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : solver = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.solver_inc_ref ; + dec_ref = Z3native.solver_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let string_of_status ( s : status) = match s with + | UNSATISFIABLE -> "unsatisfiable" + | SATISFIABLE -> "satisfiable" + | _ -> "unknown" + + module Statistics = + struct + type statistics = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : statistics = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.stats_inc_ref ; + dec_ref = Z3native.stats_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + + module Entry = + struct + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + + let create_si k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = true ; + m_is_float = false ; + m_int = v ; + m_float = 0.0 + } in + res + + let create_sd k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = false ; + m_is_float = true ; + m_int = 0 ; + m_float = v + } in + res + + + let get_key (x : statistics_entry) = x.m_key + let get_int (x : statistics_entry) = x.m_int + let get_float (x : statistics_entry) = x.m_float + let is_int (x : statistics_entry) = x.m_is_int + let is_float (x : statistics_entry) = x.m_is_float + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) + + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in + if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then + (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + else + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + ) in + mk_list f n + + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get ( x : statistics ) ( key : string ) = + let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in + List.fold_left f None (get_entries x) + end + + let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) + + let set_parameters ( x : solver ) ( p : Params.params )= + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) + + let get_param_descrs ( x : solver ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) + + let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) + + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n + + let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) + + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + ignore (List.map f constraints) + + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + if ((List.length cs) != (List.length ps)) then + raise (Z3native.Exception "Argument size mismatch") + else + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + ignore (List.iter2 f cs ps) + + let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) + + let get_num_assertions ( x : solver ) = + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVector.get_size a) + + let get_assertions ( x : solver ) = + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size a) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + mk_list f n + + let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = + let r = + if ((List.length assumptions) == 0) then + lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) + else + let f x = (Expr.gno (Boolean.expr_of_bool_expr x)) in + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) + in + match r with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN + + let get_model ( x : solver ) = + let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in + if (Z3native.is_null q) then + None + else + Some (Model.create (z3obj_gc x) q) + + let get_proof ( x : solver ) = + let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let get_unsat_core ( x : solver ) = + let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in + mk_list f n + + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) + + let get_statistics ( x : solver ) = + (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = + match logic with + | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) + + let mk_solver_s ( ctx : context ) ( logic : string ) = + mk_solver ctx (Some (Symbol.mk_string ctx logic)) + + let mk_simple_solver ( ctx : context ) = + (create ctx (Z3native.mk_simple_solver (context_gno ctx))) + + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) + + let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Fixedpoint = +struct + type fixedpoint = z3_native_object + + let create ( ctx : context ) = + let res : fixedpoint = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.fixedpoint_inc_ref ; + dec_ref = Z3native.fixedpoint_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; + (z3obj_create res) ; + res + + + let get_help ( x : fixedpoint ) = + Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) + + let set_params ( x : fixedpoint ) ( p : Params.params )= + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) + + let get_param_descrs ( x : fixedpoint ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + ignore (List.map f constraints) ; + () + + let register_relation ( x : fixedpoint ) ( f : func_decl ) = + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) + + let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = + match name with + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) + + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) + + let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + let query_r ( x : fixedpoint ) ( relations : func_decl list ) = + let f x = ptr_of_ast (ast_of_func_decl x) in + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + let push ( x : fixedpoint ) = + Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) + + let pop ( x : fixedpoint ) = + Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) + + let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) + + let get_answer ( x : fixedpoint ) = + let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let get_reason_unknown ( x : fixedpoint ) = + Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) + + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) + + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) + + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] + + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) + + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = + let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) + + let get_rules ( x : fixedpoint ) = + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + mk_list f n + + let get_assertions ( x : fixedpoint ) = + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + mk_list f n + + let mk_fixedpoint ( ctx : context ) = create ctx +end + +module Options = +struct + + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value (context_gno ctx) id value + + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in + if not r then + None + else + Some v + + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) + + let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages enabled +end + + +module SMT = +struct + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = + Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes + (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) + (Boolean.gno formula) + + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) + + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib_file (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) + + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) + + let get_smtlib_formulas ( ctx : context ) = + let n = (get_num_smtlib_formulas ctx ) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + mk_list f n + + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) + + let get_smtlib_assumptions ( ctx : context ) = + let n = (get_num_smtlib_assumptions ctx ) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + mk_list f n + + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) + + let get_smtlib_decls ( ctx : context ) = + let n = (get_num_smtlib_decls ctx) in + let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in + mk_list f n + + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) + + let get_smtlib_sorts ( ctx : context ) = + let n = (get_num_smtlib_sorts ctx) in + let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + mk_list f n + + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) +end + + +let set_global_param ( id : string ) ( value : string ) = + (Z3native.global_param_set id value) + +let get_global_param ( id : string ) = + let (r, v) = (Z3native.global_param_get id) in + if not r then + None + else + Some v + +let global_param_reset_all = + Z3native.global_param_reset_all diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli new file mode 100644 index 000000000..8b6681e11 --- /dev/null +++ b/src/api/ml/z3_rich.mli @@ -0,0 +1,3072 @@ +(** + The Z3 ML/Ocaml Interface. + + Copyright (C) 2012 Microsoft Corporation + @author CM Wintersteiger (cwinter) 2012-12-17 + + NOTE: This is the *rich* version of the interface, using more + type information directly in the type system. Coercion functions + are provided to tran coerce on type into another where applicable. +*) + +(** Context objects. + + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do + + + let ctx = (mk_context []) in + (...) + + + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: + + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (mk_context cfg) in + (...) + +*) +type context + +(** Create a context object *) +val mk_context : (string * string) list -> context + + +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log : +sig + (** Open an interaction log file. + @return True if opening the log file succeeds, false otherwise. *) + (* CMW: "open" seems to be a reserved keyword? *) + val open_ : string -> bool + + (** Closes the interaction log. *) + val close : unit + + (** Appends a user-provided string to the interaction log. *) + val append : string -> unit +end + +(** Version information *) +module Version : +sig + (** The major version. *) + val major : int + + (** The minor version. *) + val minor : int + + (** The build version. *) + val build : int + + (** The revision. *) + val revision : int + + (** A string representation of the version information. *) + val to_string : string +end + +(** Symbols are used to name several term and type constructors *) +module Symbol : +sig + (** Numbered Symbols *) + type int_symbol + + (** Named Symbols *) + type string_symbol + + (** Symbols *) + type symbol = S_Int of int_symbol | S_Str of string_symbol + + (** The kind of the symbol (int or string) *) + val kind : symbol -> Z3enums.symbol_kind + + (** Indicates whether the symbol is of Int kind *) + val is_int_symbol : symbol -> bool + + (** Indicates whether the symbol is of string kind. *) + val is_string_symbol : symbol -> bool + + (** The int value of the symbol. *) + val get_int : int_symbol -> int + + (** The string value of the symbol. *) + val get_string : string_symbol -> string + + (** A string representation of the symbol. *) + val to_string : symbol -> string + + (** Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. *) + val mk_int : context -> int -> symbol + + (** Creates a new symbol using a string. *) + val mk_string : context -> string -> symbol + + (** Create a list of symbols. *) + val mk_ints : context -> int list -> symbol list + + (** Create a list of symbols. *) + val mk_strings : context -> string list -> symbol list +end + +(** The abstract syntax tree (AST) module *) +module AST : +sig + type ast + + (** Vectors of ASTs *) + module ASTVector : + sig + type ast_vector + + (** The size of the vector *) + val get_size : ast_vector -> int + + (** + Retrieves the i-th object in the vector. + @return An AST *) + val get : ast_vector -> int -> ast + + (** Sets the i-th object in the vector. *) + val set : ast_vector -> int -> ast -> unit + + (** Resize the vector to a new size. *) + val resize : ast_vector -> int -> unit + + (** Add an ast to the back of the vector. The size + is increased by 1. *) + val push : ast_vector -> ast -> unit + + (** Translates all ASTs in the vector to another context. + @return A new ASTVector *) + val translate : ast_vector -> context -> ast_vector + + (** Retrieves a string representation of the vector. *) + val to_string : ast_vector -> string + end + + (** Map from AST to AST *) + module ASTMap : + sig + type ast_map + + (** Checks whether the map contains a key. + @return True if the key in the map, false otherwise. *) + val contains : ast_map -> ast -> bool + + (** Finds the value associated with the key. + This function signs an error when the key is not a key in the map. *) + val find : ast_map -> ast -> ast + + (** Stores or replaces a new key/value pair in the map. *) + val insert : ast_map -> ast -> ast -> unit + + (** Erases the key from the map.*) + val erase : ast_map -> ast -> unit + + (** Removes all keys from the map. *) + val reset : ast_map -> unit + + (** The size of the map *) + val get_size : ast_map -> int + + (** The keys stored in the map. *) + val get_keys : ast_map -> ast list + + (** Retrieves a string representation of the map.*) + val to_string : ast_map -> string + end + + (** The AST's hash code. + @return A hash code *) + val get_hash_code : ast -> int + + (** A unique identifier for the AST (unique among all ASTs). *) + val get_id : ast -> int + + (** The kind of the AST. *) + val get_ast_kind : ast -> Z3enums.ast_kind + + (** Indicates whether the AST is an Expr *) + val is_expr : ast -> bool + + (** Indicates whether the AST is a bound variable*) + val is_var : ast -> bool + + (** Indicates whether the AST is a Quantifier *) + val is_quantifier : ast -> bool + + (** Indicates whether the AST is a Sort *) + val is_sort : ast -> bool + + (** Indicates whether the AST is a func_decl *) + val is_func_decl : ast -> bool + + (** A string representation of the AST. *) + val to_string : ast -> string + + (** A string representation of the AST in s-expression notation. *) + val to_sexpr : ast -> string + + (** Comparison operator. + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) + val ( = ) : ast -> ast -> bool + + (** Object Comparison. + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + val compare : ast -> ast -> int + + (** Operator < *) + val ( < ) : ast -> ast -> int + + (** Translates (copies) the AST to another context. + @return A copy of the AST which is associated with the other context. *) + val translate : ast -> context -> ast + + (** Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., + Z3native.inc_ref). *) + val wrap_ast : context -> Z3native.z3_ast -> ast + + (** Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + Z3native.inc_ref). + {!wrap_ast} *) + val unwrap_ast : ast -> Z3native.ptr +end + +(** The Sort module implements type information for ASTs *) +module Sort : +sig + (** Sorts *) + type sort = Sort of AST.ast + + (** Uninterpreted Sorts *) + type uninterpreted_sort = UninterpretedSort of sort + + val ast_of_sort : sort -> AST.ast + val sort_of_uninterpreted_sort : uninterpreted_sort -> sort + val uninterpreted_sort_of_sort : sort -> uninterpreted_sort + + (** Comparison operator. + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) + val ( = ) : sort -> sort -> bool + + (** Returns a unique identifier for the sort. *) + val get_id : sort -> int + + (** The kind of the sort. *) + val get_sort_kind : sort -> Z3enums.sort_kind + + (** The name of the sort *) + val get_name : sort -> Symbol.symbol + + (** A string representation of the sort. *) + val to_string : sort -> string + + (** Create a new uninterpreted sort. *) + val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort + + (** Create a new uninterpreted sort. *) + val mk_uninterpreted_s : context -> string -> uninterpreted_sort +end + +(** Function declarations *) +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + + (** Parameters of Func_Decls *) + module Parameter : + sig + (** Parameters of func_decls *) + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) + val get_kind : parameter -> Z3enums.parameter_kind + + (** The int value of the parameter.*) + val get_int : parameter -> int + + (** The double value of the parameter.*) + val get_float : parameter -> float + + (** The Symbol.Symbol value of the parameter.*) + val get_symbol : parameter -> Symbol.symbol + + (** The Sort value of the parameter.*) + val get_sort : parameter -> Sort.sort + + (** The AST value of the parameter.*) + val get_ast : parameter -> AST.ast + + (** The FunctionDeclaration value of the parameter.*) + val get_func_decl : parameter -> func_decl + + (** The rational string value of the parameter.*) + val get_rational : parameter -> string + end + + (** Creates a new function declaration. *) + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + + (** Creates a new function declaration. *) + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + (** Creates a fresh function declaration with a name prefixed with a prefix string. *) + + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + + (** Creates a fresh constant function declaration with a name prefixed with a prefix string. + {!mk_func_decl} + {!mk_func_decl} *) + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + + (** Comparison operator. + @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) + val ( = ) : func_decl -> func_decl -> bool + + (** A string representations of the function declaration. *) + val to_string : func_decl -> string + + (** Returns a unique identifier for the function declaration. *) + val get_id : func_decl -> int + + (** The arity of the function declaration *) + val get_arity : func_decl -> int + + (** The size of the domain of the function declaration + {!get_arity} *) + val get_domain_size : func_decl -> int + + (** The domain of the function declaration *) + val get_domain : func_decl -> Sort.sort list + + (** The range of the function declaration *) + val get_range : func_decl -> Sort.sort + + (** The kind of the function declaration. *) + val get_decl_kind : func_decl -> Z3enums.decl_kind + + (** The name of the function declaration*) + val get_name : func_decl -> Symbol.symbol + + (** The number of parameters of the function declaration *) + val get_num_parameters : func_decl -> int + + (** The parameters of the function declaration *) + val get_parameters : func_decl -> Parameter.parameter list + + (** Create expression that applies function to arguments. *) + val apply : func_decl -> Expr.expr list -> Expr.expr +end + +(** Parameter sets (of Solvers, Tactics, ...) + + A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) +and Params : +sig + type params + + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs : + sig + type param_descrs + + (** Validate a set of parameters. *) + val validate : param_descrs -> params -> unit + + (** Retrieve kind of parameter. *) + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + + (** Retrieve all names of parameters. *) + val get_names : param_descrs -> Symbol.symbol list + + (** The size of the ParamDescrs. *) + val get_size : param_descrs -> int + + (** Retrieves a string representation of the ParamDescrs. *) + val to_string : param_descrs -> string + end + + (** Adds a parameter setting. *) + val add_bool : params -> Symbol.symbol -> bool -> unit + + (** Adds a parameter setting. *) + val add_int : params -> Symbol.symbol -> int -> unit + + (** Adds a parameter setting. *) + val add_double : params -> Symbol.symbol -> float -> unit + + (** Adds a parameter setting. *) + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + + (** Adds a parameter setting. *) + val add_s_bool : params -> string -> bool -> unit + + (** Adds a parameter setting. *) + val add_s_int : params -> string -> int -> unit + + (** Adds a parameter setting. *) + val add_s_double : params -> string -> float -> unit + + (** Adds a parameter setting. *) + val add_s_symbol : params -> string -> Symbol.symbol -> unit + + (** Creates a new parameter set *) + val mk_params : context -> params + + (** A string representation of the parameter set. *) + val to_string : params -> string +end + +(** General Expressions (terms) *) +and Expr : +sig + type expr = Expr of AST.ast + + val ast_of_expr : Expr.expr -> AST.ast + val expr_of_ast : AST.ast -> Expr.expr + + (** Returns a simplified version of the expression. + {!get_simplify_help} *) + val simplify : Expr.expr -> Params.params option -> expr + + (** A string describing all available parameters to Expr.Simplify. *) + val get_simplify_help : context -> string + + (** Retrieves parameter descriptions for simplifier. *) + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + + (** The function declaration of the function that is applied in this expression. *) + val get_func_decl : Expr.expr -> FuncDecl.func_decl + + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) + val get_bool_value : Expr.expr -> Z3enums.lbool + + (** The number of arguments of the expression. *) + val get_num_args : Expr.expr -> int + + (** The arguments of the expression. *) + val get_args : Expr.expr -> Expr.expr list + + (** Update the arguments of the expression using an array of expressions. + The number of new arguments should coincide with the current number of arguments. *) + val update : Expr.expr -> Expr.expr list -> expr + + (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. *) + val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr + + (** Substitute every occurrence of from in the expression with to. + {!substitute} *) + val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr + + (** Substitute the free variables in the expression with the expressions in the expr array + + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) + val substitute_vars : Expr.expr -> Expr.expr list -> expr + + (** Translates (copies) the term to another context. + @return A copy of the term which is associated with the other context *) + val translate : Expr.expr -> context -> expr + + (** Returns a string representation of the expression. *) + val to_string : Expr.expr -> string + + (** Indicates whether the term is a numeral *) + val is_numeral : Expr.expr -> bool + + (** Indicates whether the term is well-sorted. + @return True if the term is well-sorted, false otherwise. *) + val is_well_sorted : Expr.expr -> bool + + (** The Sort of the term. *) + val get_sort : Expr.expr -> Sort.sort + + (** Indicates whether the term has Boolean sort. *) + val is_bool : Expr.expr -> bool + + (** Indicates whether the term represents a constant. *) + val is_const : Expr.expr -> bool + + (** Indicates whether the term is the constant true. *) + val is_true : Expr.expr -> bool + + (** Indicates whether the term is the constant false. *) + val is_false : Expr.expr -> bool + + (** Indicates whether the term is an equality predicate. *) + val is_eq : Expr.expr -> bool + + (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) + val is_distinct : Expr.expr -> bool + + (** Indicates whether the term is a ternary if-then-else term *) + val is_ite : Expr.expr -> bool + + (** Indicates whether the term is an n-ary conjunction *) + val is_and : Expr.expr -> bool + + (** Indicates whether the term is an n-ary disjunction *) + val is_or : Expr.expr -> bool + + (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) + val is_iff : Expr.expr -> bool + + (** Indicates whether the term is an exclusive or *) + val is_xor : Expr.expr -> bool + + (** Indicates whether the term is a negation *) + val is_not : Expr.expr -> bool + + (** Indicates whether the term is an implication *) + val is_implies : Expr.expr -> bool + + (** Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) + val is_label : Expr.expr -> bool + + (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) + val is_label_lit : Expr.expr -> bool + + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) + val is_oeq : Expr.expr -> bool + + (** Creates a new constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) + val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) + val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) + val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr + + (** Create a numeral of a given sort. + @return A Term with the goven value and sort *) + val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) + val mk_numeral_int : context -> int -> Sort.sort -> expr +end + +(** Boolean expressions *) +module Boolean : +sig + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + + val expr_of_bool_expr : bool_expr -> Expr.expr + val sort_of_bool_sort : bool_sort -> Sort.sort + val bool_sort_of_sort : Sort.sort -> bool_sort + val bool_expr_of_expr : Expr.expr -> bool_expr + + (** Create a Boolean sort *) + val mk_sort : context -> bool_sort + + (** Create a Boolean constant. *) + val mk_const : context -> Symbol.symbol -> bool_expr + + (** Create a Boolean constant. *) + val mk_const_s : context -> string -> bool_expr + + (** The true Term. *) + val mk_true : context -> bool_expr + + (** The false Term. *) + val mk_false : context -> bool_expr + + (** Creates a Boolean value. *) + val mk_val : context -> bool -> bool_expr + + (** Creates the equality between two expr's. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr + + (** Creates a distinct term. *) + val mk_distinct : context -> Expr.expr list -> bool_expr + + (** Mk an expression representing not(a). *) + val mk_not : context -> bool_expr -> bool_expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 iff t2. *) + val mk_iff : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 -> t2. *) + val mk_implies : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 xor t2. *) + val mk_xor : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing the AND of args *) + val mk_and : context -> bool_expr list -> bool_expr + + (** Create an expression representing the OR of args *) + val mk_or : context -> bool_expr list -> bool_expr +end + +(** Quantifier expressions *) +module Quantifier : +sig + type quantifier = Quantifier of Expr.expr + + val expr_of_quantifier : quantifier -> Expr.expr + val quantifier_of_expr : Expr.expr -> quantifier + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. *) + module Pattern : + sig + type pattern = Pattern of AST.ast + + val ast_of_pattern : pattern -> AST.ast + val pattern_of_ast : AST.ast -> pattern + + (** The number of terms in the pattern. *) + val get_num_terms : pattern -> int + + (** The terms in the pattern. *) + val get_terms : pattern -> Expr.expr list + + (** A string representation of the pattern. *) + val to_string : pattern -> string + end + + + (** The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) + val get_index : Expr.expr -> int + + (** Indicates whether the quantifier is universal. *) + val is_universal : quantifier -> bool + + (** Indicates whether the quantifier is existential. *) + val is_existential : quantifier -> bool + + (** The weight of the quantifier. *) + val get_weight : quantifier -> int + + (** The number of patterns. *) + val get_num_patterns : quantifier -> int + + (** The patterns. *) + val get_patterns : quantifier -> Pattern.pattern list + + (** The number of no-patterns. *) + val get_num_no_patterns : quantifier -> int + + (** The no-patterns. *) + val get_no_patterns : quantifier -> Pattern.pattern list + + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) + val get_bound_variable_names : quantifier -> Symbol.symbol list + + (** The sorts of the bound variables. *) + val get_bound_variable_sorts : quantifier -> Sort.sort list + + (** The body of the quantifier. *) + val get_body : quantifier -> Boolean.bool_expr + + (** Creates a new bound variable. *) + val mk_bound : context -> int -> Sort.sort -> Expr.expr + + (** Create a quantifier pattern. *) + val mk_pattern : context -> Expr.expr list -> Pattern.pattern + + (** Create a universal Quantifier. *) + val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a universal Quantifier. *) + val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier +end + +(** Functions to manipulate Array expressions *) +module Array_ : +sig + type array_sort = ArraySort of Sort.sort + type array_expr = ArrayExpr of Expr.expr + + val sort_of_array_sort : array_sort -> Sort.sort + val array_sort_of_sort : Sort.sort -> array_sort + val expr_of_array_expr : array_expr -> Expr.expr + + val array_expr_of_expr : Expr.expr -> array_expr + + (** Create a new array sort. *) + val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort + + (** Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) + val is_store : Expr.expr -> bool + + (** Indicates whether the term is an array select. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) + val is_constant_array : Expr.expr -> bool + + (** Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. *) + val is_default_array : Expr.expr -> bool + + (** Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) + val is_array_map : Expr.expr -> bool + + (** Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) + val is_as_array : Expr.expr -> bool + + (** Indicates whether the term is of an array sort. *) + val is_array : Expr.expr -> bool + + (** The domain of the array sort. *) + val get_domain : array_sort -> Sort.sort + + (** The range of the array sort. *) + val get_range : array_sort -> Sort.sort + + (** Create an array constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr + + (** Create an array constant. *) + val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr + + (** Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + {!Array_.mk_sort} + {!mk_store} *) + val mk_select : context -> array_expr -> Expr.expr -> array_expr + + (** Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + {!Array_.mk_sort} + {!mk_select} *) + val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + + (** Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + {!Array_.mk_sort} + {!mk_select} *) + val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr + + (** Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + {!Array_.mk_sort} + {!mk_select} + {!mk_store} *) + val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr + + (** Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) + val mk_term_array : context -> array_expr -> array_expr +end + +(** Functions to manipulate Set expressions *) +module Set : +sig + type set_sort = SetSort of Sort.sort + + val sort_of_set_sort : set_sort -> Sort.sort + + (** Create a set type. *) + val mk_sort : context -> Sort.sort -> set_sort + + (** Indicates whether the term is set union *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is set intersection *) + val is_intersect : Expr.expr -> bool + + (** Indicates whether the term is set difference *) + val is_difference : Expr.expr -> bool + + (** Indicates whether the term is set complement *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is set subset *) + val is_subset : Expr.expr -> bool + + (** Create an empty set. *) + val mk_empty : context -> Sort.sort -> Expr.expr + + (** Create the full set. *) + val mk_full : context -> Sort.sort -> Expr.expr + + (** Add an element to the set. *) + val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Remove an element from a set. *) + val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the union of a list of sets. *) + val mk_union : context -> Expr.expr list -> Expr.expr + + (** Take the intersection of a list of sets. *) + val mk_intersection : context -> Expr.expr list -> Expr.expr + + (** Take the difference between two sets. *) + val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the complement of a set. *) + val mk_complement : context -> Expr.expr -> Expr.expr + + (** Check for set membership. *) + val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Check for subsetness of sets. *) + val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr +end + +(** Functions to manipulate Finite Domain expressions *) +module FiniteDomain : +sig + type finite_domain_sort = FiniteDomainSort of Sort.sort + + val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort + val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort + + (** Create a new finite domain sort. *) + val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort + + (** Create a new finite domain sort. *) + val mk_sort_s : context -> string -> int -> finite_domain_sort + + (** Indicates whether the term is of an array sort. *) + val is_finite_domain : Expr.expr -> bool + + (** Indicates whether the term is a less than predicate over a finite domain. *) + val is_lt : Expr.expr -> bool + + (** The size of the finite domain sort. *) + val get_size : finite_domain_sort -> int +end + + +(** Functions to manipulate Relation expressions *) +module Relation : +sig + type relation_sort = RelationSort of Sort.sort + + val sort_of_relation_sort : relation_sort -> Sort.sort + val relation_sort_of_sort : Sort.sort -> relation_sort + + (** Indicates whether the term is of a relation sort. *) + val is_relation : Expr.expr -> bool + + (** Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. *) + val is_store : Expr.expr -> bool + + (** Indicates whether the term is an empty relation *) + val is_empty : Expr.expr -> bool + + (** Indicates whether the term is a test for the emptiness of a relation *) + val is_is_empty : Expr.expr -> bool + + (** Indicates whether the term is a relational join *) + val is_join : Expr.expr -> bool + + (** Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is the widening of two relations + The function takes two arguments. *) + val is_widen : Expr.expr -> bool + + (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. *) + val is_project : Expr.expr -> bool + + (** Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) + val is_filter : Expr.expr -> bool + + (** Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) + val is_negation_filter : Expr.expr -> bool + + (** Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. *) + val is_rename : Expr.expr -> bool + + (** Indicates whether the term is the complement of a relation *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) + val is_clone : Expr.expr -> bool + + (** The arity of the relation sort. *) + val get_arity : relation_sort -> int + + (** The sorts of the columns of the relation sort. *) + val get_column_sorts : relation_sort -> relation_sort list +end + +(** Functions to manipulate Datatype expressions *) +module Datatype : +sig + type datatype_sort = DatatypeSort of Sort.sort + type datatype_expr = DatatypeExpr of Expr.expr + + val sort_of_datatype_sort : datatype_sort -> Sort.sort + val datatype_sort_of_sort : Sort.sort -> datatype_sort + val expr_of_datatype_expr : datatype_expr -> Expr.expr + val datatype_expr_of_expr : Expr.expr -> datatype_expr + + (** Datatype Constructors *) + module Constructor : + sig + type constructor + + (** The number of fields of the constructor. *) + val get_num_fields : constructor -> int + + (** The function declaration of the constructor. *) + val get_constructor_decl : constructor -> FuncDecl.func_decl + + (** The function declaration of the tester. *) + val get_tester_decl : constructor -> FuncDecl.func_decl + + (** The function declarations of the accessors *) + val get_accessor_decls : constructor -> FuncDecl.func_decl list + end + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a new datatype sort. *) + val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort + + (** Create a new datatype sort. *) + val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort + + (** Create mutually recursive datatypes. *) + val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list + + (** Create mutually recursive data-types. *) + val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list + + + (** The number of constructors of the datatype sort. *) + val get_num_constructors : datatype_sort -> int + + (** The constructors. *) + val get_constructors : datatype_sort -> FuncDecl.func_decl list + + (** The recognizers. *) + val get_recognizers : datatype_sort -> FuncDecl.func_decl list + + (** The constructor accessors. *) + val get_accessors : datatype_sort -> FuncDecl.func_decl list list +end + +(** Functions to manipulate Enumeration expressions *) +module Enumeration : +sig + type enum_sort = EnumSort of Sort.sort + + val sort_of_enum_sort : enum_sort -> Sort.sort + + (** Create a new enumeration sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort + + (** Create a new enumeration sort. *) + val mk_sort_s : context -> string -> string list -> enum_sort + + (** The function declarations of the constants in the enumeration. *) + val get_const_decls : enum_sort -> FuncDecl.func_decl list + + (** The test predicates for the constants in the enumeration. *) + val get_tester_decls : enum_sort -> FuncDecl.func_decl list +end + +(** Functions to manipulate List expressions *) +module List_ : +sig + type list_sort = ListSort of Sort.sort + + val sort_of_list_sort : list_sort -> Sort.sort + + (** Create a new list sort. *) + val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort + + (** Create a new list sort. *) + val mk_list_s : context -> string -> Sort.sort -> list_sort + + (** The declaration of the nil function of this list sort. *) + val get_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isNil function of this list sort. *) + val get_is_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the cons function of this list sort. *) + val get_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isCons function of this list sort. *) + val get_is_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the head function of this list sort. *) + val get_head_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the tail function of this list sort. *) + val get_tail_decl : list_sort -> FuncDecl.func_decl + + (** The empty list. *) + val nil : list_sort -> Expr.expr +end + +(** Functions to manipulate Tuple expressions *) +module Tuple : +sig + type tuple_sort = TupleSort of Sort.sort + + val sort_of_tuple_sort : tuple_sort -> Sort.sort + + (** Create a new tuple sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort + + (** The constructor function of the tuple. *) + val get_mk_decl : tuple_sort -> FuncDecl.func_decl + + (** The number of fields in the tuple. *) + val get_num_fields : tuple_sort -> int + + (** The field declarations. *) + val get_field_decls : tuple_sort -> FuncDecl.func_decl list +end + +(** Functions to manipulate arithmetic expressions *) +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort + val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr + + (** Integer Arithmetic *) + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort + val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort + val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr + val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr + val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr + val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num + + (** Create a new integer sort. *) + val mk_sort : context -> int_sort + + (** Retrieve the int value. *) + val get_int : int_num -> int + + (** Returns a string representation of the numeral. *) + val to_string : int_num -> string + + (** Creates an integer constant. *) + val mk_int_const : context -> Symbol.symbol -> int_expr + + (** Creates an integer constant. *) + val mk_int_const_s : context -> string -> int_expr + + (** Create an expression representing t1 mod t2. + The arguments must have int type. *) + val mk_mod : context -> int_expr -> int_expr -> int_expr + + (** Create an expression representing t1 rem t2. + The arguments must have int type. *) + val mk_rem : context -> int_expr -> int_expr -> int_expr + + (** Create an integer numeral. *) + val mk_int_numeral_s : context -> string -> int_num + + (** Create an integer numeral. + @return A Term with the given value and sort Integer *) + val mk_int_numeral_i : context -> int -> int_num + + (** Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. *) + val mk_int2real : context -> int_expr -> Real.real_expr + + (** Create an n-bit bit-vector from an integer argument. + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + + (** Real Arithmetic *) + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + (** Create a real sort. *) + val mk_sort : context -> real_sort + + (** The numerator of a rational numeral. *) + val get_numerator : rat_num -> Integer.int_num + + (** The denominator of a rational numeral. *) + val get_denominator : rat_num -> Integer.int_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as indicated by the int argument.*) + val to_decimal_string : rat_num -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : rat_num -> string + + (** Creates a real constant. *) + val mk_real_const : context -> Symbol.symbol -> real_expr + + (** Creates a real constant. *) + val mk_real_const_s : context -> string -> real_expr + + (** Create a real numeral from a fraction. + @return A Term with rational value and sort Real + {!mk_numeral_s} *) + val mk_numeral_nd : context -> int -> int -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_s : context -> string -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_i : context -> int -> rat_num + + (** Creates an expression that checks whether a real number is an integer. *) + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + + (** Coerce a real to an integer. + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) + val mk_real2int : context -> real_expr -> Integer.int_expr + end + + (** Algebraic Numbers *) + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr + val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num + + (** Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_upper : algebraic_num -> int -> Real.rat_num + + (** Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_lower : algebraic_num -> int -> Real.rat_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as the int argument provided.*) + val to_decimal_string : algebraic_num -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : algebraic_num -> string + end + + (** Indicates whether the term is of integer sort. *) + val is_int : Expr.expr -> bool + + (** Indicates whether the term is an arithmetic numeral. *) + val is_arithmetic_numeral : Expr.expr -> bool + + (** Indicates whether the term is a less-than-or-equal *) + val is_le : Expr.expr -> bool + + (** Indicates whether the term is a greater-than-or-equal *) + val is_ge : Expr.expr -> bool + + (** Indicates whether the term is a less-than *) + val is_lt : Expr.expr -> bool + + (** Indicates whether the term is a greater-than *) + val is_gt : Expr.expr -> bool + + (** Indicates whether the term is addition (binary) *) + val is_add : Expr.expr -> bool + + (** Indicates whether the term is subtraction (binary) *) + val is_sub : Expr.expr -> bool + + (** Indicates whether the term is a unary minus *) + val is_uminus : Expr.expr -> bool + + (** Indicates whether the term is multiplication (binary) *) + val is_mul : Expr.expr -> bool + + (** Indicates whether the term is division (binary) *) + val is_div : Expr.expr -> bool + + (** Indicates whether the term is integer division (binary) *) + val is_idiv : Expr.expr -> bool + + (** Indicates whether the term is remainder (binary) *) + val is_remainder : Expr.expr -> bool + + (** Indicates whether the term is modulus (binary) *) + val is_modulus : Expr.expr -> bool + + (** Indicates whether the term is a coercion of integer to real (unary) *) + val is_inttoreal : Expr.expr -> bool + + (** Indicates whether the term is a coercion of real to integer (unary) *) + val is_real_to_int : Expr.expr -> bool + + (** Indicates whether the term is a check that tests whether a real is integral (unary) *) + val is_real_is_int : Expr.expr -> bool + + (** Indicates whether the term is of sort real. *) + val is_real : Expr.expr -> bool + + (** Indicates whether the term is an integer numeral. *) + val is_int_numeral : Expr.expr -> bool + + (** Indicates whether the term is a real numeral. *) + val is_rat_num : Expr.expr -> bool + + (** Indicates whether the term is an algebraic number *) + val is_algebraic_number : Expr.expr -> bool + + (** Create an expression representing t[0] + t[1] + .... *) + val mk_add : context -> arith_expr list -> arith_expr + + (** Create an expression representing t[0] * t[1] * .... *) + val mk_mul : context -> arith_expr list -> arith_expr + + (** Create an expression representing t[0] - t[1] - .... *) + val mk_sub : context -> arith_expr list -> arith_expr + + (** Create an expression representing -t. *) + val mk_unary_minus : context -> arith_expr -> arith_expr + + (** Create an expression representing t1 / t2. *) + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 ^ t2. *) + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 < t2 *) + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 <= t2 *) + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 > t2 *) + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 >= t2 *) + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end + +(** Functions to manipulate bit-vector expressions *) +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + (** Create a new bit-vector sort. *) + val mk_sort : context -> int -> bitvec_sort + + (** Indicates whether the terms is of bit-vector sort. *) + val is_bv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector numeral *) + val is_bv_numeral : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value one *) + val is_bv_bit1 : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value zero *) + val is_bv_bit0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unary minus *) + val is_bv_uminus : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector addition (binary) *) + val is_bv_add : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector subtraction (binary) *) + val is_bv_sub : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector multiplication (binary) *) + val is_bv_mul : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division (binary) *) + val is_bv_sdiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division (binary) *) + val is_bv_udiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder (binary) *) + val is_bv_SRem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) + val is_bv_urem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus *) + val is_bv_smod : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division by zero *) + val is_bv_sdiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division by zero *) + val is_bv_udiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder by zero *) + val is_bv_srem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder by zero *) + val is_bv_urem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus by zero *) + val is_bv_smod0 : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) + val is_bv_ule : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than-or-equal *) + val is_bv_sle : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) + val is_bv_uge : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) + val is_bv_sge : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than *) + val is_bv_ult : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than *) + val is_bv_slt : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than *) + val is_bv_ugt : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than *) + val is_bv_sgt : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise AND *) + val is_bv_and : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise OR *) + val is_bv_or : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOT *) + val is_bv_not : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XOR *) + val is_bv_xor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NAND *) + val is_bv_nand : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOR *) + val is_bv_nor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XNOR *) + val is_bv_xnor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector concatenation (binary) *) + val is_bv_concat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector sign extension *) + val is_bv_signextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector zero extension *) + val is_bv_zeroextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector extraction *) + val is_bv_extract : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector repetition *) + val is_bv_repeat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce OR *) + val is_bv_reduceor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce AND *) + val is_bv_reduceand : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector comparison *) + val is_bv_comp : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector shift left *) + val is_bv_shiftleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector logical shift right *) + val is_bv_shiftrightlogical : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector arithmetic shift left *) + val is_bv_shiftrightarithmetic : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left *) + val is_bv_rotateleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right *) + val is_bv_rotateright : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotateleftextended : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotaterightextended : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + + (** Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_int_to_bv : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_bv_to_int : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) + val is_bv_carry : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) + val is_bv_xor3 : Expr.expr -> bool + + (** The size of a bit-vector sort. *) + val get_size : bitvec_sort -> int + + (** Retrieve the int value. *) + val get_int : bitvec_num -> int + + (** Returns a string representation of the numeral. *) + val to_string : bitvec_num -> string + + (** Creates a bit-vector constant. *) + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + + (** Creates a bit-vector constant. *) + val mk_const_s : context -> string -> int -> bitvec_expr + + (** Bitwise negation. + The argument must have a bit-vector sort. *) + val mk_not : context -> bitvec_expr -> Expr.expr + + (** Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redand : context -> bitvec_expr -> Expr.expr + + (** Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redor : context -> bitvec_expr -> Expr.expr + + (** Bitwise conjunction. + The arguments must have a bit-vector sort. *) + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise disjunction. + The arguments must have a bit-vector sort. *) + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XOR. + The arguments must have a bit-vector sort. *) + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NAND. + The arguments must have a bit-vector sort. *) + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NOR. + The arguments must have a bit-vector sort. *) + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XNOR. + The arguments must have a bit-vector sort. *) + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Standard two's complement unary minus. + The arguments must have a bit-vector sort. *) + val mk_neg : context -> bitvec_expr -> bitvec_expr + + (** Two's complement addition. + The arguments must have the same bit-vector sort. *) + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement subtraction. + The arguments must have the same bit-vector sort. *) + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement multiplication. + The arguments must have the same bit-vector sort. *) + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned less-than + + The arguments must have the same bit-vector sort. *) + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than + + The arguments must have the same bit-vector sort. *) + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). *) + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bit-vector extraction. + + Extract the bits between two limits from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. *) + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. *) + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. *) + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector repetition. *) + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + + (** Shift left. + + It is equivalent to multiplication by 2^x where \c x is the value of third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling.*) + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of \c t to the left \c i times. *) + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of \c t to the right \c i times.*) + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of the second argument to the left.*) + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of the second argument to the right. *) + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Create an integer from the bit-vector argument + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in the argument. + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function.*) + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + + (** Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a bit-vector numeral. *) + val mk_numeral : context -> string -> int -> bitvec_num +end + +(** Functions to manipulate proof expressions *) +module Proof : +sig + (** Indicates whether the term is a Proof for the expression 'true'. *) + val is_true : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact asserted by the user. *) + val is_asserted : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) + val is_goal : Expr.expr -> bool + + (** Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) + val is_modus_ponens : Expr.expr -> bool + + (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) + val is_reflexivity : Expr.expr -> bool + + (** Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) + val is_symmetry : Expr.expr -> bool + + (** Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) + val is_transitivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) + val is_Transitivity_star : Expr.expr -> bool + + (** Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) + val is_monotonicity : Expr.expr -> bool + + (** Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) + val is_quant_intro : Expr.expr -> bool + + (** Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) + val is_distributivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) + val is_and_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) + val is_or_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) + val is_rewrite : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) + val is_rewrite_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) + val is_pull_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) + val is_pull_quant_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) + val is_push_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) + val is_elim_unused_vars : Expr.expr -> bool + + (** Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) + val is_der : Expr.expr -> bool + + (** Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) *) + val is_quant_inst : Expr.expr -> bool + + (** Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. *) + val is_hypothesis : Expr.expr -> bool + + (** Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) + val is_lemma : Expr.expr -> bool + + (** Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) + val is_unit_resolution : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) *) + val is_iff_true : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) *) + val is_iff_false : Expr.expr -> bool + + (** Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) + val is_commutativity : Expr.expr -> bool + + (** Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) + val is_def_axiom : Expr.expr -> bool + + (** Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) + val is_def_intro : Expr.expr -> bool + + (** Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) + val is_apply_def : Expr.expr -> bool + + (** Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) *) + val is_iff_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) + val is_nnf_pos : Expr.expr -> bool + + (** Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) + val is_nnf_neg : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_nnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_cnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) + val is_skolemize : Expr.expr -> bool + + (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) + val is_modus_ponens_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) + val is_theory_lemma : Expr.expr -> bool +end + +(** Goals + + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) +module Goal : +sig + type goal + + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. *) + val get_precision : goal -> Z3enums.goal_prec + + (** Indicates whether the goal is precise. *) + val is_precise : goal -> bool + + (** Indicates whether the goal is an under-approximation. *) + val is_underapproximation : goal -> bool + + (** Indicates whether the goal is an over-approximation. *) + val is_overapproximation : goal -> bool + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) + val is_garbage : goal -> bool + + (** Adds the constraints to the given goal. *) + val assert_ : goal -> Boolean.bool_expr list -> unit + + (** Indicates whether the goal contains `false'. *) + val is_inconsistent : goal -> bool + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) + val get_depth : goal -> int + + (** Erases all formulas from the given goal. *) + val reset : goal -> unit + + (** The number of formulas in the goal. *) + val get_size : goal -> int + + (** The formulas in the goal. *) + val get_formulas : goal -> Boolean.bool_expr list + + (** The number of formulas, subformulas and terms in the goal. *) + val get_num_exprs : goal -> int + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) + val is_decided_sat : goal -> bool + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) + val is_decided_unsat : goal -> bool + + (** Translates (copies) the Goal to another context.. *) + val translate : goal -> context -> goal + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) + val simplify : goal -> Params.params option -> goal + + (** Creates a new Goal. + + Note that the Context must have been created with proof generation support if + the fourth argument is set to true here. *) + val mk_goal : context -> bool -> bool -> bool -> goal + + (** A string representation of the Goal. *) + val to_string : goal -> string +end + +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model : +sig + type model + + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. *) + module FuncInterp : + sig + type func_interp + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. *) + module FuncEntry : + sig + type func_entry + + (** Return the (symbolic) value of this entry. + *) + val get_value : func_entry -> Expr.expr + + (** The number of arguments of the entry. + *) + val get_num_args : func_entry -> int + + (** The arguments of the function entry. + *) + val get_args : func_entry -> Expr.expr list + + (** A string representation of the function entry. + *) + val to_string : func_entry -> string + end + + (** The number of entries in the function interpretation. *) + val get_num_entries : func_interp -> int + + (** The entries in the function interpretation *) + val get_entries : func_interp -> FuncEntry.func_entry list + + (** The (symbolic) `else' value of the function interpretation. *) + val get_else : func_interp -> Expr.expr + + (** The arity of the function interpretation *) + val get_arity : func_interp -> int + + (** A string representation of the function interpretation. *) + val to_string : func_interp -> string + end + + (** Retrieves the interpretation (the assignment) of a func_decl in the model. + An expression if the function has an interpretation in the model, null otherwise. *) + val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of an expression in the model. + An expression if the constant has an interpretation in the model, null otherwise. *) + val get_const_interp_e : model -> Expr.expr -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option + + (** The number of constant interpretations in the model. *) + val get_num_consts : model -> int + + (** The function declarations of the constants in the model. *) + val get_const_decls : model -> FuncDecl.func_decl list + + (** The number of function interpretations in the model. *) + val get_num_funcs : model -> int + + (** The function declarations of the function interpretations in the model. *) + val get_func_decls : model -> FuncDecl.func_decl list + + (** All symbols that have an interpretation in the model. *) + val get_decls : model -> FuncDecl.func_decl list + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** Evaluates an expression in the current model. + + This function may fail if the argument contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + *) + val eval : model -> Expr.expr -> bool -> Expr.expr + + (** Alias for eval. *) + val evaluate : model -> Expr.expr -> bool -> Expr.expr + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + val get_num_sorts : model -> int + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + {!get_num_sorts} + {!sort_universe} *) + val get_sorts : model -> Sort.sort list + + (** The finite set of distinct values that represent the interpretation of a sort. + {!get_sorts} + @returns A list of expressions, where each is an element of the universe of the sort *) + val sort_universe : model -> Sort.sort -> AST.ast list + + (** Conversion of models to strings. + A string representation of the model. *) + val to_string : model -> string +end + +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe : +sig + type probe + + (** Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + val apply : probe -> Goal.goal -> float + + (** The number of supported Probes. *) + val get_num_probes : context -> int + + (** The names of all supported Probes. *) + val get_probe_names : context -> string list + + (** Returns a string containing a description of the probe with the given name. *) + val get_probe_description : context -> string -> string + + (** Creates a new Probe. *) + val mk_probe : context -> string -> probe + + (** Create a probe that always evaluates to a float value. *) + val const : context -> float -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than the value returned by second argument *) + val lt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than the value returned by second argument *) + val gt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than or equal the value returned by second argument *) + val le : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than or equal the value returned by second argument *) + val ge : context -> probe -> probe -> probe + + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is equal the value returned by second argument *) + val eq : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) + val and_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) + val or_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) + val not_ : context -> probe -> probe +end + +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Tactic : +sig + type tactic + + (** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) + module ApplyResult : + sig + type apply_result + + (** The number of Subgoals. *) + val get_num_subgoals : apply_result -> int + + (** Retrieves the subgoals from the apply_result. *) + val get_subgoals : apply_result -> Goal.goal list + + (** Retrieves a subgoal from the apply_result. *) + val get_subgoal : apply_result -> int -> Goal.goal + + (** Convert a model for a subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g *) + val convert_model : apply_result -> int -> Model.model -> Model.model + + (** A string representation of the ApplyResult. *) + val to_string : apply_result -> string + end + + (** A string containing a description of parameters accepted by the tactic. *) + val get_help : tactic -> string + + (** Retrieves parameter descriptions for Tactics. *) + val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs + + (** Apply the tactic to the goal. *) + val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result + + (** The number of supported tactics. *) + val get_num_tactics : context -> int + + (** The names of all supported tactics. *) + val get_tactic_names : context -> string list + + (** Returns a string containing a description of the tactic with the given name. *) + val get_tactic_description : context -> string -> string + + (** Creates a new Tactic. *) + val mk_tactic : context -> string -> tactic + + (** Create a tactic that applies one tactic to a Goal and + then another one to every subgoal produced by the first one. *) + val and_then : context -> tactic -> tactic -> tactic list -> tactic + + (** Create a tactic that first applies one tactic to a Goal and + if it fails then returns the result of another tactic applied to the Goal. *) + val or_else : context -> tactic -> tactic -> tactic + + (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). + + If the tactic does not terminate within the timeout, then it fails. *) + val try_for : context -> tactic -> int -> tactic + + (** Create a tactic that applies one tactic to a given goal if the probe + evaluates to true. + + If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) + val when_ : context -> Probe.probe -> tactic -> tactic + + (** Create a tactic that applies a tactic to a given goal if the probe + evaluates to true and another tactic otherwise. *) + val cond : context -> Probe.probe -> tactic -> tactic -> tactic + + (** Create a tactic that keeps applying one tactic until the goal is not + modified anymore or the maximum number of iterations is reached. *) + val repeat : context -> tactic -> int -> tactic + + (** Create a tactic that just returns the given goal. *) + val skip : context -> tactic + + (** Create a tactic always fails. *) + val fail : context -> tactic + + (** Create a tactic that fails if the probe evaluates to false. *) + val fail_if : context -> Probe.probe -> tactic + + (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) + val fail_if_not_decided : context -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. *) + val using_params : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. + Alias for UsingParams*) + val with_ : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies the given tactics in parallel. *) + val par_or : context -> tactic list -> tactic + + (** Create a tactic that applies a tactic to a given goal and then another tactic + to every subgoal produced by the first one. The subgoals are processed in parallel. *) + val par_and_then : context -> tactic -> tactic -> tactic + + (** Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) + val interrupt : context -> unit +end + +(** Solvers *) +module Solver : +sig + type solver + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + val string_of_status : status -> string + + (** Objects that track statistical information about solvers. *) + module Statistics : + sig + type statistics + + (** Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) + module Entry : + sig + type statistics_entry + + (** The key of the entry. *) + val get_key : statistics_entry -> string + + (** The int-value of the entry. *) + val get_int : statistics_entry -> int + + (** The float-value of the entry. *) + val get_float : statistics_entry -> float + + (** True if the entry is uint-valued. *) + val is_int : statistics_entry -> bool + + (** True if the entry is double-valued. *) + val is_float : statistics_entry -> bool + + (** The string representation of the the entry's value. *) + val to_string_value : statistics_entry -> string + + (** The string representation of the entry (key and value) *) + val to_string : statistics_entry -> string + end + + (** A string representation of the statistical data. *) + val to_string : statistics -> string + + (** The number of statistical data. *) + val get_size : statistics -> int + + (** The data entries. *) + val get_entries : statistics -> Entry.statistics_entry list + + (** The statistical counters. *) + val get_keys : statistics -> string list + + (** The value of a particular statistical counter. *) + val get : statistics -> string -> Entry.statistics_entry option + end + + (** A string that describes all available solver parameters. *) + val get_help : solver -> string + + (** Sets the solver parameters. *) + val set_parameters : solver -> Params.params -> unit + + (** Retrieves parameter descriptions for solver. *) + val get_param_descrs : solver -> Params.ParamDescrs.param_descrs + + (** The current number of backtracking points (scopes). + {!pop} + {!push} *) + val get_num_scopes : solver -> int + + (** Creates a backtracking point. + {!pop} *) + val push : solver -> unit + + (** Backtracks a number of backtracking points. + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) + val pop : solver -> int -> unit + + (** Resets the Solver. + This removes all assertions from the solver. *) + val reset : solver -> unit + + (** Assert a constraint (or multiple) into the solver. *) + val assert_ : solver -> Boolean.bool_expr list -> unit + + (** * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit + + (** * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit + + (** The number of assertions in the solver. *) + val get_num_assertions : solver -> int + + (** The set of asserted formulas. *) + val get_assertions : solver -> Boolean.bool_expr list + + (** Checks whether the assertions in the solver are consistent or not. + + {!Model} + {!get_unsat_core} + {!Proof} *) + val check : solver -> Boolean.bool_expr list -> status + + (** The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. *) + val get_model : solver -> Model.model option + + (** The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. *) + val get_proof : solver -> Expr.expr option + + (** The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. *) + val get_unsat_core : solver -> AST.ast list + + (** A brief justification of why the last call to Check returned UNKNOWN. *) + val get_reason_unknown : solver -> string + + (** Solver statistics. *) + val get_statistics : solver -> Statistics.statistics + + (** Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) + val mk_solver : context -> Symbol.symbol option -> solver + + (** Creates a new (incremental) solver. + {!mk_solver} *) + val mk_solver_s : context -> string -> solver + + (** Creates a new (incremental) solver. *) + val mk_simple_solver : context -> solver + + (** Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) + val mk_solver_t : context -> Tactic.tactic -> solver + + (** A string representation of the solver. *) + val to_string : solver -> string +end + +(** Fixedpoint solving *) +module Fixedpoint : +sig + type fixedpoint + + (** A string that describes all available fixedpoint solver parameters. *) + val get_help : fixedpoint -> string + + (** Sets the fixedpoint solver parameters. *) + val set_params : fixedpoint -> Params.params -> unit + + (** Retrieves parameter descriptions for Fixedpoint solver. *) + val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs + + (** Assert a constraints into the fixedpoint solver. *) + val assert_ : fixedpoint -> Boolean.bool_expr list -> unit + + (** Register predicate as recursive relation. *) + val register_relation : fixedpoint -> FuncDecl.func_decl -> unit + + (** Add rule into the fixedpoint solver. *) + val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit + + (** Add table fact to the fixedpoint solver. *) + val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit + + (** Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) + val query : fixedpoint -> Boolean.bool_expr -> Solver.status + + (** Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) + val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status + + (** Creates a backtracking point. + {!pop} *) + val push : fixedpoint -> unit + + (** Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + {!push} *) + val pop : fixedpoint -> unit + + (** Update named rule into in the fixedpoint solver. *) + val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit + + (** Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. *) + val get_answer : fixedpoint -> Expr.expr option + + (** Retrieve explanation why fixedpoint engine returned status Unknown. *) + val get_reason_unknown : fixedpoint -> string + + (** Retrieve the number of levels explored for a given predicate. *) + val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int + + (** Retrieve the cover of a predicate. *) + val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option + + (** Add property about the predicate. + The property is added at level. *) + val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit + + (** Retrieve internal string representation of fixedpoint object. *) + val to_string : fixedpoint -> string + + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) + val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit + + (** Convert benchmark given as set of axioms, rules and queries to a string. *) + val to_string_q : fixedpoint -> Boolean.bool_expr list -> string + + (** Retrieve set of rules added to fixedpoint context. *) + val get_rules : fixedpoint -> Boolean.bool_expr list + + (** Retrieve set of assertions added to fixedpoint context. *) + val get_assertions : fixedpoint -> Boolean.bool_expr list + + (** Create a Fixedpoint context. *) + val mk_fixedpoint : context -> fixedpoint +end + +(** Global and context options + + Note: This module contains functions that set parameters/options for context + objects as well as functions that set options that are used globally, across + contexts.*) +module Options : +sig + (** Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + {!get_param_value} *) + val update_param_value : context -> string -> string -> unit + + (** Get a configuration parameter. + + Returns None if the parameter value does not exist. + {!update_param_value} *) + val get_param_value : context -> string -> string option + + (** Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) + val set_print_mode : context -> Z3enums.ast_print_mode -> unit + + (** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) + val toggle_warning_messages : bool -> unit +end + +(** Functions for handling SMT and SMT2 expressions and files *) +module SMT : +sig + (** Convert a benchmark into an SMT-LIB formatted string. + + @return A string representation of the benchmark. *) + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string + + (** Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays in the third and fifth argument + don't need to match the names of the sorts and declarations in the arrays in the fourth + and sixth argument. This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) + val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit + + (** Parse the given file using the SMT-LIB parser. + {!parse_smtlib_string} *) + val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit + + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_formulas : context -> int + + (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_formulas : context -> Boolean.bool_expr list + + (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_assumptions : context -> int + + (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_assumptions : context -> Boolean.bool_expr list + + (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_decls : context -> int + + (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_decls : context -> FuncDecl.func_decl list + + (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_sorts : context -> int + + (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_sorts : context -> Sort.sort list + + (** Parse the given string using the SMT-LIB2 parser. + + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) + val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr + + (** Parse the given file using the SMT-LIB2 parser. + {!parse_smtlib2_string} *) + val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr +end + +(** Set a global (or module) parameter, which is shared by all Z3 contexts. + + When a Z3 module is initialized it will use the value of these parameters + when Z3_params objects are not provided. + The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + The character '.' is a delimiter (more later). + The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + This function can be used to set parameters for a specific Z3 module. + This can be done by using .. + For example: + (set_global_param "pp.decimal" "true") + will set the parameter "decimal" in the module "pp" to true. +*) +val set_global_param : string -> string -> unit + +(** Get a global (or module) parameter. + + Returns None if the parameter does not exist. + The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + This function cannot be invoked simultaneously from different threads without synchronization. + The result string stored in param_value is stored in a shared location. +*) +val get_global_param : string -> string option + +(** Restore the value of all global (and module) parameters. + + This command will not affect already created objects (such as tactics and solvers) + {!set_global_param} +*) +val global_param_reset_all : unit From 13416de27e3e6f824f54f0cc1f09ee57da5da58a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 14:17:35 +0000 Subject: [PATCH 311/646] ML API savegame Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 124 +++++++++++++++++++------------------- src/api/ml/z3.ml | 18 +++--- src/api/ml/z3_rich.ml | 43 +++++++------ src/api/ml/z3_rich.mli | 13 ++-- 4 files changed, 96 insertions(+), 102 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 823a08fe2..f7a4cbc00 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -162,70 +162,68 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ) ; - model_converter_test ctx -(* - // Real num/den test. - RatNum rn = ctx.MkReal(42, 43); - Expr inum = rn.Numerator; - Expr iden = rn.Denominator; - Console.WriteLine("Numerator: " + inum + " Denominator: " + iden); - if (inum.ToString() != "42" || iden.ToString() != "43") - throw new TestFailedException(); - - if (rn.ToDecimalString(3) != "0.976?") - throw new TestFailedException(); - - BigIntCheck(ctx, ctx.MkReal("-1231231232/234234333")); - BigIntCheck(ctx, ctx.MkReal("-123123234234234234231232/234234333")); - BigIntCheck(ctx, ctx.MkReal("-234234333")); - BigIntCheck(ctx, ctx.MkReal("234234333/2")); - - - string bn = "1234567890987654321"; - - if (ctx.MkInt(bn).BigInteger.ToString() != bn) - throw new TestFailedException(); - - if (ctx.MkBV(bn, 128).BigInteger.ToString() != bn) - throw new TestFailedException(); - - if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn) - throw new TestFailedException(); - - // Error handling test. - try - { - IntExpr i = ctx.MkInt("1/2"); - throw new TestFailedException(); // unreachable - } - catch (Z3Exception) - { - } - } -*) + model_converter_test ctx ; + (* Real num/den test. *) + let rn = Real.mk_numeral_nd ctx 42 43 in + let inum = (get_numerator rn) in + let iden = get_denominator rn in + Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; + if ((Real.to_string inum) <> "42" or (Real.to_string iden) <> "43") then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + if ((to_decimal_string rn 3) <> "0.976?") then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + if (to_decimal_string (Real.mk_numeral_s ctx "-1231231232/234234333") 5 <> "-5.25640?") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "-123123234234234234231232/234234333") 5 <> "-525641278361333.28170?") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "-234234333") 5 <> "-234234333") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "234234333/2") 5 <> "117117166.5") then + raise (TestFailedException "") + ; + (* Error handling test. *) + try ( + let i = Integer.mk_numeral_s ctx "1/2" in + raise (TestFailedException "") (* unreachable *) + ) + with Z3native.Exception(_) -> ( + Printf.printf "Exception caught, OK.\n" + ) let _ = - if not (Log.open_ "z3.log") then - raise (TestFailedException "Log couldn't be opened.") - else - ( - Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = [("model", "true"); ("proof", "false")] in - let ctx = (mk_context cfg) in - let is = (Symbol.mk_int ctx 42) in - let ss = (Symbol.mk_string ctx "mySymbol") in - let bs = (Boolean.mk_sort ctx) in - let ints = (Integer.mk_sort ctx) in - let rs = (Real.mk_sort ctx) in - Printf.printf "int symbol: %s\n" (Symbol.to_string is); - Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string bs); - Printf.printf "int sort: %s\n" (Sort.to_string ints); - Printf.printf "real sort: %s\n" (Sort.to_string rs); - basic_tests ctx ; - Printf.printf "Disposing...\n"; - Gc.full_major () - ); - Printf.printf "Exiting.\n"; + try ( + if not (Log.open_ "z3.log") then + raise (TestFailedException "Log couldn't be opened.") + else + ( + Printf.printf "Running Z3 version %s\n" Version.to_string ; + let cfg = [("model", "true"); ("proof", "false")] in + let ctx = (mk_context cfg) in + let is = (Symbol.mk_int ctx 42) in + let ss = (Symbol.mk_string ctx "mySymbol") in + let bs = (Boolean.mk_sort ctx) in + let ints = (Integer.mk_sort ctx) in + let rs = (Real.mk_sort ctx) in + Printf.printf "int symbol: %s\n" (Symbol.to_string is); + Printf.printf "string symbol: %s\n" (Symbol.to_string ss); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); + basic_tests ctx ; + Printf.printf "Disposing...\n"; + Gc.full_major () + ); + Printf.printf "Exiting.\n" ; + exit 0 + ) with Z3native.Exception(msg) -> ( + Printf.printf "Z3 EXCEPTION: %s\n" msg ; + exit 1 + ) ;; diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0676f1a39..e62732924 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -11,7 +11,6 @@ open Z3enums let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) - (* Internal types *) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context @@ -21,7 +20,6 @@ type z3_native_object = { mutable m_n_obj : Z3native.ptr ; inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - (** Internal stuff *) module Internal = @@ -1455,11 +1453,11 @@ struct let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_mod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) @@ -1467,10 +1465,10 @@ struct let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = + let mk_numeral_s ( ctx : context ) ( v : string ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = + let mk_numeral_i ( ctx : context ) ( v : int ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_int2real ( ctx : context ) ( t : expr ) = @@ -1496,11 +1494,11 @@ struct let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml index 052ca5e22..0c2f95b6b 100644 --- a/src/api/ml/z3_rich.ml +++ b/src/api/ml/z3_rich.ml @@ -1,4 +1,4 @@ -(** +\(** The Z3 ML/Ocaml Interface. Copyright (C) 2012 Microsoft Corporation @@ -11,7 +11,6 @@ open Z3enums let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) - (* Internal types *) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context @@ -1679,12 +1678,12 @@ sig val mk_sort : context -> int_sort val get_int : int_num -> int val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr + val mk_const_s : context -> string -> int_expr val mk_mod : context -> int_expr -> int_expr -> int_expr val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_s : context -> string -> int_num + val mk_numeral_i : context -> int -> int_num val mk_int2real : context -> int_expr -> Real.real_expr val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end @@ -1709,8 +1708,8 @@ sig val get_denominator : rat_num -> Integer.int_num val to_decimal_string : rat_num -> int -> string val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr + val mk_const_s : context -> string -> real_expr val mk_numeral_nd : context -> int -> int -> rat_num val mk_numeral_s : context -> string -> rat_num val mk_numeral_i : context -> int -> rat_num @@ -1816,12 +1815,12 @@ end = struct val mk_sort : context -> int_sort val get_int : int_num -> int val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr + val mk_const_s : context -> string -> int_expr val mk_mod : context -> int_expr -> int_expr -> int_expr val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_s : context -> string -> int_num + val mk_numeral_i : context -> int -> int_num val mk_int2real : context -> int_expr -> Real.real_expr val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end = struct @@ -1884,11 +1883,11 @@ end = struct let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) @@ -1896,10 +1895,10 @@ end = struct let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = + let mk_numeral_s ( ctx : context ) ( v : string ) = int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = + let mk_numeral_i ( ctx : context ) ( v : int ) = int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) let mk_int2real ( ctx : context ) ( t : int_expr ) = @@ -1930,8 +1929,8 @@ end = struct val get_denominator : rat_num -> Integer.int_num val to_decimal_string : rat_num -> int -> string val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr + val mk_const_s : context -> string -> real_expr val mk_numeral_nd : context -> int -> int -> rat_num val mk_numeral_s : context -> string -> rat_num val mk_numeral_i : context -> int -> rat_num @@ -2002,11 +2001,11 @@ end = struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli index 8b6681e11..f2ecd326d 100644 --- a/src/api/ml/z3_rich.mli +++ b/src/api/ml/z3_rich.mli @@ -34,7 +34,6 @@ type context (** Create a context object *) val mk_context : (string * string) list -> context - (** Interaction logging for Z3 Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) @@ -1219,10 +1218,10 @@ sig val to_string : int_num -> string (** Creates an integer constant. *) - val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr (** Creates an integer constant. *) - val mk_int_const_s : context -> string -> int_expr + val mk_const_s : context -> string -> int_expr (** Create an expression representing t1 mod t2. The arguments must have int type. *) @@ -1233,11 +1232,11 @@ sig val mk_rem : context -> int_expr -> int_expr -> int_expr (** Create an integer numeral. *) - val mk_int_numeral_s : context -> string -> int_num + val mk_numeral_s : context -> string -> int_num (** Create an integer numeral. @return A Term with the given value and sort Integer *) - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_i : context -> int -> int_num (** Coerce an integer to a real. @@ -1291,10 +1290,10 @@ sig val to_string : rat_num -> string (** Creates a real constant. *) - val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr (** Creates a real constant. *) - val mk_real_const_s : context -> string -> real_expr + val mk_const_s : context -> string -> real_expr (** Create a real numeral from a fraction. @return A Term with rational value and sort Real From 74ab6dbd2262509881d7d72e5dcbe6fc0b02d949 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 18:53:29 +0000 Subject: [PATCH 312/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index a0b7e6250..44d871348 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1339,9 +1339,10 @@ def mk_ml(): ml_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') ml_wrapper.write(' // wrappers below.\n') ml_wrapper.write('}\n\n') - ml_wrapper.write('void n_set_internal_error_handler(Z3_context c)\n') + ml_wrapper.write('void n_set_internal_error_handler(value a0)\n') ml_wrapper.write('{\n') - ml_wrapper.write(' Z3_set_error_handler(c, MLErrorHandler);\n') + ml_wrapper.write(' Z3_context _a0 = * (Z3_context*) Data_custom_val(a0);\n') + ml_wrapper.write(' Z3_set_error_handler(_a0, MLErrorHandler);\n') ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) From c37eb794c2d14b710cf8f281c0008781251eac13 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 26 Feb 2013 19:45:45 +0000 Subject: [PATCH 313/646] ML API: renamed assert_ to add Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 24 ++++++++++++------------ src/api/ml/z3.ml | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index f7a4cbc00..c9ed1d948 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -29,11 +29,11 @@ let model_converter_test ( ctx : context ) = let xr = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Real.mk_sort ctx)) in let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; - (Goal.assert_ g4 [ (mk_eq ctx + (Goal.add g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; + (Goal.add g4 [ (mk_eq ctx yr (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1) ])) ]) ; - (Goal.assert_ g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; + (Goal.add g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -53,7 +53,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ; let solver = (mk_solver ctx None) in - let f e = (Solver.assert_ solver [ e ]) in + let f e = (Solver.add solver [ e ]) in ignore (List.map f (get_formulas (get_subgoal ar 0))) ; let q = (check solver []) in if q != SATISFIABLE then @@ -88,12 +88,12 @@ let basic_tests ( ctx : context ) = let trivial_eq = (mk_eq ctx fapp fapp) in let nontrivial_eq = (mk_eq ctx fapp fapp2) in let g = (mk_goal ctx true false false) in - (Goal.assert_ g [ trivial_eq ]) ; - (Goal.assert_ g [ nontrivial_eq ]) ; + (Goal.add g [ trivial_eq ]) ; + (Goal.add g [ nontrivial_eq ]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; ( let solver = (mk_solver ctx None) in - (List.iter (fun a -> (Solver.assert_ solver [ a ])) (get_formulas g)) ; + (List.iter (fun a -> (Solver.add solver [ a ])) (get_formulas g)) ; if (check solver []) != SATISFIABLE then raise (TestFailedException "") else @@ -116,7 +116,7 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [ (mk_eq ctx + (Goal.add g [ (mk_eq ctx (mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) (mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) ; @@ -139,7 +139,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [ (Boolean.mk_false ctx) ]) ; + (Goal.add g2 [ (Boolean.mk_false ctx) ]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -151,10 +151,10 @@ let basic_tests ( ctx : context ) = let g3 = (mk_goal ctx true true false) in let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Integer.mk_sort ctx)) in let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Integer.mk_sort ctx)) in - (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; - (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; + (Goal.add g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; + (Goal.add g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; let constr = (mk_eq ctx xc yc) in - (Goal.assert_ g3 [ constr ] ) ; + (Goal.add g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index e62732924..8eb5427bb 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1850,7 +1850,7 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : expr list ) = + let add ( x : goal ) ( constraints : expr list ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e) in ignore (List.map f constraints) ; () @@ -2370,11 +2370,11 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : expr list ) = + let add ( x : solver ) ( constraints : expr list ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : expr list ) ( ps : expr list ) = + let assert_and_track_l ( x : solver ) ( cs : expr list ) ( ps : expr list ) = if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else @@ -2473,7 +2473,7 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : expr list ) = + let add ( x : fixedpoint ) ( constraints : expr list ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) ; () From 17005a413b346ec04d9baaa68ceee87858721346 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Jun 2013 18:26:07 +0100 Subject: [PATCH 314/646] Removed unnecessary file Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/README-win | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 src/api/ml/README-win diff --git a/src/api/ml/README-win b/src/api/ml/README-win deleted file mode 100644 index 82ddc2652..000000000 --- a/src/api/ml/README-win +++ /dev/null @@ -1,23 +0,0 @@ -The OCaml API for Z3 was tested using OCaml 3.12.1. -You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- To build the OCaml API for Z3: - .\build-lib.cmd - -Remark: The OCaml and C compiler tool chains must be configured in your environment. -Running from the Visual Studio Command Prompt configures the Microsoft C compiler. - -Remark: Building the OCaml API copies some pathnames into files, -so the OCaml API must be recompiled if the Z3 library files are moved. - -See ..\examples\ocaml\build-test.cmd for an example of how to compile and link with Z3. - -Acknowledgements: -The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. -Many thanks to them! From c0df7640396a16c4ea12619997d7917f9cf53ef6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Jun 2013 18:51:40 +0100 Subject: [PATCH 315/646] Updates to ML API. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 43 ++++----- src/api/ml/z3.mli | 233 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 23 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8eb5427bb..4a8fbaa0a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -323,8 +323,8 @@ struct else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + let unwrap_ast ( x : ast ) = (z3obj_gno x) let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr - let unwrap_ast ( x : ast ) = (z3obj_gno x) end open AST @@ -678,6 +678,19 @@ end = struct res let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) + + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value (context_gno ctx) id value + + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in + if not r then + None + else + Some v + + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) end (** General expressions (terms) *) @@ -1106,7 +1119,7 @@ struct end -module Array_ = +module Array = struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) @@ -1389,7 +1402,7 @@ struct end -module List_ = +module List = struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in @@ -2558,26 +2571,6 @@ struct let mk_fixedpoint ( ctx : context ) = create ctx end -module Options = -struct - - let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value (context_gno ctx) id value - - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - - let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages enabled -end - module SMT = struct @@ -2692,3 +2685,7 @@ let get_global_param ( id : string ) = let global_param_reset_all = Z3native.global_param_reset_all + +let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages enabled + diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 2eb9eecb7..1eae4f013 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -756,9 +756,27 @@ and goal_prec = the first conjunct in the body of an implication is position 1 the second conjunct in the body of an implication is position 2 +<<<<<<< HEAD For general implications where the head is a disjunction, the first n positions correspond to the n disjuncts in the head. The next m positions correspond to the m conjuncts in the body. +======= +(** Create a context object + The following parameters can be set: + + - proof (Boolean) Enable proof generation + - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting + - trace (Boolean) Tracing support for VCC + - trace_file_name (String) Trace out file for VCC traces + - timeout (unsigned) default timeout (in milliseconds) used for solvers + - well_sorted_check type checker + - auto_config use heuristics to automatically select solver and configure it + - model model generation for solvers, this parameter can be overwritten when creating a solver + - model_validate validate models produced by solvers + - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver +*) +val mk_context : (string * string) list -> context +>>>>>>> Updates to ML API. The premises can be universally quantified so that the most general non-ground form is: @@ -1084,6 +1102,7 @@ val mk_symbol: context -> symbol_refined -> symbol external mk_int_symbol : context -> int -> symbol = "camlidl_z3_Z3_mk_int_symbol" +<<<<<<< HEAD (** Summary: Create a Z3 symbol using a C string. Symbols are used to name several term and type constructors. @@ -1137,6 +1156,27 @@ type sort_refined = | Sort_datatype of datatype_constructor array | Sort_relation of sort array | Sort_unknown +======= + (** Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + Z3native.inc_ref). + {!wrap_ast} *) + val unwrap_ast : ast -> Z3native.ptr + + (** Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., + Z3native.inc_ref). *) + val wrap_ast : context -> Z3native.z3_ast -> ast +end +>>>>>>> Updates to ML API. (** @@ -1693,6 +1733,7 @@ external mk_bvnot : context -> ast -> ast external mk_bvredand : context -> ast -> ast = "camlidl_z3_Z3_mk_bvredand" +<<<<<<< HEAD (** Summary: \[ [ mk_bvredor c t1 ] \] Take disjunction of bits in vector, return vector of length 1. @@ -1701,6 +1742,41 @@ external mk_bvredand : context -> ast -> ast *) external mk_bvredor : context -> ast -> ast = "camlidl_z3_Z3_mk_bvredor" +======= + (** A string representation of the parameter set. *) + val to_string : params -> string + + (** Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -p + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + {!get_param_value} *) + val update_param_value : context -> string -> string -> unit + + (** Get a configuration parameter. + + Returns None if the parameter value does not exist. + {!update_param_value} *) + val get_param_value : context -> string -> string option + + (** Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) + val set_print_mode : context -> Z3enums.ast_print_mode -> unit +end +>>>>>>> Updates to ML API. (** Summary: \[ [ mk_bvand c t1 t2 ] \] @@ -1931,6 +2007,7 @@ external mk_bvugt : context -> ast -> ast -> ast external mk_bvsgt : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_bvsgt" +<<<<<<< HEAD (** Summary: \[ [ mk_concat c t1 t2 ] \] Concatenate the given bit-vectors. @@ -1941,6 +2018,106 @@ external mk_bvsgt : context -> ast -> ast -> ast *) external mk_concat : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_concat" +======= +(** Functions to manipulate Array expressions *) +module Array : +sig + (** Create a new array sort. *) + val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort + + (** Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) + val is_store : Expr.expr -> bool + + (** Indicates whether the term is an array select. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) + val is_constant_array : Expr.expr -> bool + + (** Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. *) + val is_default_array : Expr.expr -> bool + + (** Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) + val is_array_map : Expr.expr -> bool + + (** Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) + val is_as_array : Expr.expr -> bool + + (** Indicates whether the term is of an array sort. *) + val is_array : Expr.expr -> bool + + (** The domain of the array sort. *) + val get_domain : Sort.sort -> Sort.sort + + (** The range of the array sort. *) + val get_range : Sort.sort -> Sort.sort + + (** Create an array constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> Expr.expr + + (** Create an array constant. *) + val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> Expr.expr + + (** Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + {!Array.mk_sort} + {!mk_store} *) + val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + {!Array.mk_sort} + {!mk_select} *) + val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + {!Array.mk_sort} + {!mk_select} *) + val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr + + (** Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + {!Array.mk_sort} + {!mk_select} + {!mk_store} *) + val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr + + (** Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) + val mk_term_array : context -> Expr.expr -> Expr.expr +end +>>>>>>> Updates to ML API. (** Summary: \[ [ mk_extract c high low t1 ] \] @@ -2259,12 +2436,20 @@ external mk_set_sort : context -> sort -> sort external mk_empty_set : context -> sort -> ast = "camlidl_z3_Z3_mk_empty_set" +<<<<<<< HEAD (** Summary: Create the full set. def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_full_set : context -> sort -> ast = "camlidl_z3_Z3_mk_full_set" +======= +(** Functions to manipulate List expressions *) +module List : +sig + (** Create a new list sort. *) + val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort +>>>>>>> Updates to ML API. (** Summary: Add an element to a set. @@ -8806,6 +8991,7 @@ external theory_get_num_apps : theory -> int external theory_get_app : theory -> int -> ast = "camlidl_z3V3_Z3_theory_get_app" +<<<<<<< HEAD (** {2 {L Deprecated Injective functions API}} *) @@ -9135,6 +9321,12 @@ external get_model_func_decl : context -> model -> int -> func_decl *) external eval_func_decl : context -> model -> func_decl -> bool * ast = "camlidl_z3V3_Z3_eval_func_decl" +======= +(** Functions for handling SMT and SMT2 expressions and files *) +module SMT : +sig + (** Convert a benchmark into an SMT-LIB formatted string. +>>>>>>> Updates to ML API. (** Summary: \[ [ is_array_value c v ] \] @@ -9586,3 +9778,44 @@ val set_new_relevant_callback : theory -> (ast -> unit) -> unit end +<<<<<<< HEAD +======= +(** Set a global (or module) parameter, which is shared by all Z3 contexts. + + When a Z3 module is initialized it will use the value of these parameters + when Z3_params objects are not provided. + The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + The character '.' is a delimiter (more later). + The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + This function can be used to set parameters for a specific Z3 module. + This can be done by using .. + For example: + (set_global_param "pp.decimal" "true") + will set the parameter "decimal" in the module "pp" to true. +*) +val set_global_param : string -> string -> unit + +(** Get a global (or module) parameter. + + Returns None if the parameter does not exist. + The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + This function cannot be invoked simultaneously from different threads without synchronization. + The result string stored in param_value is stored in a shared location. +*) +val get_global_param : string -> string option + +(** Restore the value of all global (and module) parameters. + + This command will not affect already created objects (such as tactics and solvers) + {!set_global_param} +*) + +val global_param_reset_all : unit + + (** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) + val toggle_warning_messages : bool -> unit +>>>>>>> Updates to ML API. From 9726ee4c5faa875c991dca1a4c9d75aa80923355 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Jun 2013 19:12:00 +0100 Subject: [PATCH 316/646] ML API: refactoring Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 74 +- src/api/ml/z3.mli | 11735 +++++++++----------------------------------- 2 files changed, 2454 insertions(+), 9355 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4a8fbaa0a..081433f1f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,6 +7,8 @@ open Z3enums +exception Error = Z3native.Exception + (* Some helpers. *) let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) @@ -283,7 +285,7 @@ struct Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end - let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) + let hash ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) @@ -304,7 +306,7 @@ struct let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + let equal ( a : ast ) ( b : ast ) = (a == b) || if (z3obj_gnc a) != (z3obj_gnc b) then false else @@ -314,8 +316,6 @@ struct if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - - let ( < ) (a : ast) (b : ast) = (compare a b) let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then @@ -361,7 +361,7 @@ struct let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) - let ( = ) : sort -> sort -> bool = fun a b -> + let equal : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then false @@ -424,7 +424,7 @@ sig val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl val mk_const_decl_s : context -> string -> Sort.sort -> func_decl val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - val ( = ) : func_decl -> func_decl -> bool + val equal : func_decl -> func_decl -> bool val to_string : func_decl -> string val get_id : func_decl -> int val get_arity : func_decl -> int @@ -498,7 +498,7 @@ end = struct let get_float ( x : parameter ) = match x with | P_Dbl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a double") + | _ -> raise (Z3native.Exception "parameter is not a float") let get_symbol ( x : parameter ) = match x with @@ -545,7 +545,7 @@ end = struct create_pdr ctx prefix [] range - let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + let equal ( a : func_decl ) ( b : func_decl ) = (a == b) || if (gnc a) != (gnc b) then false else @@ -605,12 +605,8 @@ sig end val add_bool : params -> Symbol.symbol -> bool -> unit val add_int : params -> Symbol.symbol -> int -> unit - val add_double : params -> Symbol.symbol -> float -> unit + val add_float : params -> Symbol.symbol -> float -> unit val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - val add_s_bool : params -> string -> bool -> unit - val add_s_int : params -> string -> int -> unit - val add_s_double : params -> string -> float -> unit - val add_s_symbol : params -> string -> Symbol.symbol -> unit val mk_params : context -> params val to_string : params -> string end = struct @@ -650,24 +646,12 @@ end = struct let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + let add_float ( x : params ) ( name : Symbol.symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = - add_bool x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = - add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - let mk_params ( ctx : context ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; @@ -734,8 +718,6 @@ sig val is_xor : expr -> bool val is_not : expr -> bool val is_implies : expr -> bool - val is_label : expr -> bool - val is_label_lit : expr -> bool val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr @@ -857,8 +839,6 @@ end = struct let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = @@ -1530,20 +1510,20 @@ struct let mk_real2int ( ctx : context ) ( t : expr ) = (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (Expr.gno t))) - end - module AlgebraicNumber = - struct - let to_upper ( x : expr ) ( precision : int ) = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) - - let to_lower ( x : expr ) precision = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) - - let to_decimal_string ( x : expr ) ( precision : int ) = - Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + module AlgebraicNumber = + struct + let to_upper ( x : expr ) ( precision : int ) = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) + + let to_lower ( x : expr ) precision = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) + + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision + + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + end end let is_int ( x : expr ) = @@ -2052,13 +2032,11 @@ struct let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in (mk_list f n_funcs) @ (mk_list g n_consts) - - exception ModelEvaluationFailedException of string - + let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then - raise (ModelEvaluationFailedException "evaluation failed") + None else expr_of_ptr (z3obj_gc x) v @@ -2353,7 +2331,7 @@ struct if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_float_value (z3obj_gnc x) (z3obj_gno x) i)) ) in mk_list f n diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 1eae4f013..570ff8717 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1,766 +1,37 @@ -(* File generated from z3.idl *) +(** + The Z3 ML/Ocaml Interface. + Copyright (C) 2012 Microsoft Corporation + @author CM Wintersteiger (cwinter) 2012-12-17 +*) + +(** General Z3 exceptions + + Many functions in this API may throw an exception; if they do, it is this one.*) +exception Error + +(** Context objects. + + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do + + + let ctx = (mk_context []) in + (...) + + + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: + + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (mk_context cfg) in + (...) + +*) type context -and symbol -and ast -and sort = private ast -and func_decl = private ast -and app = private ast -and pattern = private ast -and params -and param_descrs -and model -and func_interp -and func_entry -and fixedpoint -and ast_vector -and ast_map -and goal -and tactic -and probe -and apply_result -and solver -and stats - - -and constructor -and constructor_list - -and lbool = - | L_FALSE - | L_UNDEF - | L_TRUE - -and symbol_kind = - | INT_SYMBOL - | STRING_SYMBOL - -and parameter_kind = - | PARAMETER_INT - | PARAMETER_DOUBLE - | PARAMETER_RATIONAL - | PARAMETER_SYMBOL - | PARAMETER_SORT - | PARAMETER_AST - | PARAMETER_FUNC_DECL - -and sort_kind = - | UNINTERPRETED_SORT - | BOOL_SORT - | INT_SORT - | REAL_SORT - | BV_SORT - | ARRAY_SORT - | DATATYPE_SORT - | RELATION_SORT - | FINITE_DOMAIN_SORT - | UNKNOWN_SORT - -and ast_kind = - | NUMERAL_AST - | APP_AST - | VAR_AST - | QUANTIFIER_AST - | SORT_AST - | FUNC_DECL_AST - | UNKNOWN_AST - -and decl_kind = - | OP_TRUE - | OP_FALSE - | OP_EQ - | OP_DISTINCT - | OP_ITE - | OP_AND - | OP_OR - | OP_IFF - | OP_XOR - | OP_NOT - | OP_IMPLIES - | OP_OEQ - | OP_ANUM - | OP_AGNUM - | OP_LE - | OP_GE - | OP_LT - | OP_GT - | OP_ADD - | OP_SUB - | OP_UMINUS - | OP_MUL - | OP_DIV - | OP_IDIV - | OP_REM - | OP_MOD - | OP_TO_REAL - | OP_TO_INT - | OP_IS_INT - | OP_POWER - | OP_STORE - | OP_SELECT - | OP_CONST_ARRAY - | OP_ARRAY_MAP - | OP_ARRAY_DEFAULT - | OP_SET_UNION - | OP_SET_INTERSECT - | OP_SET_DIFFERENCE - | OP_SET_COMPLEMENT - | OP_SET_SUBSET - | OP_AS_ARRAY - | OP_BNUM - | OP_BIT1 - | OP_BIT0 - | OP_BNEG - | OP_BADD - | OP_BSUB - | OP_BMUL - | OP_BSDIV - | OP_BUDIV - | OP_BSREM - | OP_BUREM - | OP_BSMOD - | OP_BSDIV0 - | OP_BUDIV0 - | OP_BSREM0 - | OP_BUREM0 - | OP_BSMOD0 - | OP_ULEQ - | OP_SLEQ - | OP_UGEQ - | OP_SGEQ - | OP_ULT - | OP_SLT - | OP_UGT - | OP_SGT - | OP_BAND - | OP_BOR - | OP_BNOT - | OP_BXOR - | OP_BNAND - | OP_BNOR - | OP_BXNOR - | OP_CONCAT - | OP_SIGN_EXT - | OP_ZERO_EXT - | OP_EXTRACT - | OP_REPEAT - | OP_BREDOR - | OP_BREDAND - | OP_BCOMP - | OP_BSHL - | OP_BLSHR - | OP_BASHR - | OP_ROTATE_LEFT - | OP_ROTATE_RIGHT - | OP_EXT_ROTATE_LEFT - | OP_EXT_ROTATE_RIGHT - | OP_INT2BV - | OP_BV2INT - | OP_CARRY - | OP_XOR3 - | OP_PR_UNDEF - | OP_PR_TRUE - | OP_PR_ASSERTED - | OP_PR_GOAL - | OP_PR_MODUS_PONENS - | OP_PR_REFLEXIVITY - | OP_PR_SYMMETRY - | OP_PR_TRANSITIVITY - | OP_PR_TRANSITIVITY_STAR - | OP_PR_MONOTONICITY - | OP_PR_QUANT_INTRO - | OP_PR_DISTRIBUTIVITY - | OP_PR_AND_ELIM - | OP_PR_NOT_OR_ELIM - | OP_PR_REWRITE - | OP_PR_REWRITE_STAR - | OP_PR_PULL_QUANT - | OP_PR_PULL_QUANT_STAR - | OP_PR_PUSH_QUANT - | OP_PR_ELIM_UNUSED_VARS - | OP_PR_DER - | OP_PR_QUANT_INST - | OP_PR_HYPOTHESIS - | OP_PR_LEMMA - | OP_PR_UNIT_RESOLUTION - | OP_PR_IFF_TRUE - | OP_PR_IFF_FALSE - | OP_PR_COMMUTATIVITY - | OP_PR_DEF_AXIOM - | OP_PR_DEF_INTRO - | OP_PR_APPLY_DEF - | OP_PR_IFF_OEQ - | OP_PR_NNF_POS - | OP_PR_NNF_NEG - | OP_PR_NNF_STAR - | OP_PR_CNF_STAR - | OP_PR_SKOLEMIZE - | OP_PR_MODUS_PONENS_OEQ - | OP_PR_TH_LEMMA - | OP_PR_HYPER_RESOLVE - | OP_RA_STORE - | OP_RA_EMPTY - | OP_RA_IS_EMPTY - | OP_RA_JOIN - | OP_RA_UNION - | OP_RA_WIDEN - | OP_RA_PROJECT - | OP_RA_FILTER - | OP_RA_NEGATION_FILTER - | OP_RA_RENAME - | OP_RA_COMPLEMENT - | OP_RA_SELECT - | OP_RA_CLONE - | OP_FD_LT - | OP_LABEL - | OP_LABEL_LIT - | OP_DT_CONSTRUCTOR - | OP_DT_RECOGNISER - | OP_DT_ACCESSOR - | OP_UNINTERPRETED - -and param_kind = - | PK_UINT - | PK_BOOL - | PK_DOUBLE - | PK_SYMBOL - | PK_STRING - | PK_OTHER - | PK_INVALID - -and ast_print_mode = - | PRINT_SMTLIB_FULL - | PRINT_LOW_LEVEL - | PRINT_SMTLIB_COMPLIANT - | PRINT_SMTLIB2_COMPLIANT - -and error_code = - | OK - | SORT_ERROR - | IOB - | INVALID_ARG - | PARSER_ERROR - | NO_PARSER - | INVALID_PATTERN - | MEMOUT_FAIL - | FILE_ACCESS_ERROR - | INTERNAL_FATAL - | INVALID_USAGE - | DEC_REF_ERROR - | EXCEPTION - -and goal_prec = - | GOAL_PRECISE - | GOAL_UNDER - | GOAL_OVER - | GOAL_UNDER_OVER - - -(** -*) -(** - {2 {L Types}} - Most of the types in the API are abstract. - - [context]: manager of all other Z3 objects, global configuration options, etc. - - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. - - [ast]: abstract syntax tree node. That is, the data-structure used in Z3 to represent terms, formulas and types. - - [sort]: kind of AST used to represent types. - - [func_decl]: kind of AST used to represent function symbols. - - [app]: kind of AST used to represent function applications. - - [pattern]: kind of AST used to represent pattern and multi-patterns used to guide quantifier instantiation. - - [params]: parameter set used to configure many components such as: simplifiers, tactics, solvers, etc. - - [model]: model for the constraints asserted into the logical context. - - [func_interp]: interpretation of a function in a model. - - [func_entry]: representation of the value of a [func_interp] at a particular point. - - [fixedpoint]: context for the recursive predicate solver. - - [ast_vector]: vector of [ast] objects. - - [ast_map]: mapping from [ast] to [ast] objects. - - [goal]: set of formulas that can be solved and/or transformed using tactics and solvers. - - [tactic]: basic building block for creating custom solvers for specific problem domains. - - [probe]: function/predicate used to inspect a goal and collect information that may be used to decide which solver and/or preprocessing step will be used. - - [apply_result]: collection of subgoals resulting from applying of a tactic to a goal. - - [solver]: (incremental) solver, possibly specialized by a particular tactic or logic. - - [stats]: statistical data for a solver. -*) -(** - {!lbool} - Lifted Boolean type: [false], [undefined], [true]. -*) -(** - {!symbol_kind} - The different kinds of symbol. - In Z3, a symbol can be represented using integers and strings (See {!get_symbol_kind}). - - {b See also}: {!mk_int_symbol} - - {b See also}: {!mk_string_symbol} -*) -(** - {!parameter_kind} - The different kinds of parameters that can be associated with function symbols. - - {b See also}: {!get_decl_num_parameters} - - {b See also}: {!get_decl_parameter_kind} - - PARAMETER_INT is used for integer parameters. - - PARAMETER_DOUBLE is used for double parameters. - - PARAMETER_RATIONAL is used for parameters that are rational numbers. - - PARAMETER_SYMBOL is used for parameters that are symbols. - - PARAMETER_SORT is used for sort parameters. - - PARAMETER_AST is used for expression parameters. - - PARAMETER_FUNC_DECL is used for function declaration parameters. -*) -(** - {!sort_kind} - The different kinds of Z3 types (See {!get_sort_kind}). -*) -(** - {!ast_kind} - The different kinds of Z3 AST (abstract syntax trees). That is, terms, formulas and types. - - APP_AST: constant and applications - - NUMERAL_AST: numeral constants - - VAR_AST: bound variables - - QUANTIFIER_AST: quantifiers - - SORT_AST: sort - - FUNC_DECL_AST: function declaration - - UNKNOWN_AST: internal -*) -(** - {!decl_kind} - The different kinds of interpreted function kinds. - - OP_TRUE The constant true. - - OP_FALSE The constant false. - - OP_EQ The equality predicate. - - OP_DISTINCT The n-ary distinct predicate (every argument is mutually distinct). - - OP_ITE The ternary if-then-else term. - - OP_AND n-ary conjunction. - - OP_OR n-ary disjunction. - - OP_IFF equivalence (binary). - - OP_XOR Exclusive or. - - OP_NOT Negation. - - OP_IMPLIES Implication. - - OP_OEQ Binary equivalence modulo namings. This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. - - OP_ANUM Arithmetic numeral. - - OP_AGNUM Arithmetic algebraic numeral. Algebraic numbers are used to represent irrational numbers in Z3. - - OP_LE <=. - - OP_GE >=. - - OP_LT <. - - OP_GT >. - - OP_ADD Addition - Binary. - - OP_SUB Binary subtraction. - - OP_UMINUS Unary minus. - - OP_MUL Multiplication - Binary. - - OP_DIV Division - Binary. - - OP_IDIV Integer division - Binary. - - OP_REM Remainder - Binary. - - OP_MOD Modulus - Binary. - - OP_TO_REAL Coercion of integer to real - Unary. - - OP_TO_INT Coercion of real to integer - Unary. - - OP_IS_INT Check if real is also an integer - Unary. - - OP_POWER Power operator x^y. - - OP_STORE Array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. - - OP_SELECT Array select. - - OP_CONST_ARRAY The constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. - - OP_ARRAY_DEFAULT Default value of arrays. For example default(const(v)) = v. The function is unary. - - OP_ARRAY_MAP Array map operator. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. - - OP_SET_UNION Set union between two Booelan arrays (two arrays whose range type is Boolean). The function is binary. - - OP_SET_INTERSECT Set intersection between two Boolean arrays. The function is binary. - - OP_SET_DIFFERENCE Set difference between two Boolean arrays. The function is binary. - - OP_SET_COMPLEMENT Set complement of a Boolean array. The function is unary. - - OP_SET_SUBSET Subset predicate between two Boolean arrays. The relation is binary. - - OP_AS_ARRAY An array value that behaves as the function graph of the - function passed as parameter. - - OP_BNUM Bit-vector numeral. - - OP_BIT1 One bit bit-vector. - - OP_BIT0 Zero bit bit-vector. - - OP_BNEG Unary minus. - - OP_BADD Binary addition. - - OP_BSUB Binary subtraction. - - OP_BMUL Binary multiplication. - - OP_BSDIV Binary signed division. - - OP_BUDIV Binary unsigned int division. - - OP_BSREM Binary signed remainder. - - OP_BUREM Binary unsigned int remainder. - - OP_BSMOD Binary signed modulus. - - OP_BSDIV0 Unary function. bsdiv(x,0) is congruent to bsdiv0(x). - - OP_BUDIV0 Unary function. budiv(x,0) is congruent to budiv0(x). - - OP_BSREM0 Unary function. bsrem(x,0) is congruent to bsrem0(x). - - OP_BUREM0 Unary function. burem(x,0) is congruent to burem0(x). - - OP_BSMOD0 Unary function. bsmod(x,0) is congruent to bsmod0(x). - - OP_ULEQ Unsigned bit-vector <= - Binary relation. - - OP_SLEQ Signed bit-vector <= - Binary relation. - - OP_UGEQ Unsigned bit-vector >= - Binary relation. - - OP_SGEQ Signed bit-vector >= - Binary relation. - - OP_ULT Unsigned bit-vector < - Binary relation. - - OP_SLT Signed bit-vector < - Binary relation. - - OP_UGT Unsigned bit-vector > - Binary relation. - - OP_SGT Signed bit-vector > - Binary relation. - - OP_BAND Bit-wise and - Binary. - - OP_BOR Bit-wise or - Binary. - - OP_BNOT Bit-wise not - Unary. - - OP_BXOR Bit-wise xor - Binary. - - OP_BNAND Bit-wise nand - Binary. - - OP_BNOR Bit-wise nor - Binary. - - OP_BXNOR Bit-wise xnor - Binary. - - OP_CONCAT Bit-vector concatenation - Binary. - - OP_SIGN_EXT Bit-vector sign extension. - - OP_ZERO_EXT Bit-vector zero extension. - - OP_EXTRACT Bit-vector extraction. - - OP_REPEAT Repeat bit-vector n times. - - OP_BREDOR Bit-vector reduce or - Unary. - - OP_BREDAND Bit-vector reduce and - Unary. - - OP_BCOMP . - - OP_BSHL Shift left. - - OP_BLSHR Logical shift right. - - OP_BASHR Arithmetical shift right. - - OP_ROTATE_LEFT Left rotation. - - OP_ROTATE_RIGHT Right rotation. - - OP_EXT_ROTATE_LEFT (extended) Left rotation. Similar to OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. - - OP_EXT_ROTATE_RIGHT (extended) Right rotation. Similar to OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. - - OP_INT2BV Coerce integer to bit-vector. NB. This function - is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - - OP_BV2INT Coerce bit-vector to integer. NB. This function - is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - - OP_CARRY Compute the carry bit in a full-adder. - The meaning is given by the equivalence - (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) - - OP_XOR3 Compute ternary XOR. - The meaning is given by the equivalence - (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) - - OP_PR_UNDEF: Undef/Null proof object. - - OP_PR_TRUE: Proof for the expression 'true'. - - OP_PR_ASSERTED: Proof for a fact asserted by the user. - - OP_PR_GOAL: Proof for a fact (tagged as goal) asserted by the user. - - OP_PR_MODUS_PONENS: Given a proof for p and a proof for (implies p q), produces a proof for q. - {e - T1: p - T2: (implies p q) - [mp T1 T2]: q - } - The second antecedents may also be a proof for (iff p q). - - OP_PR_REFLEXIVITY: A proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. - - OP_PR_SYMMETRY: Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - {e - T1: (R t s) - [symmetry T1]: (R s t) - } - T1 is the antecedent of this proof object. - - OP_PR_TRANSITIVITY: Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - {e - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) - } - - OP_PR_TRANSITIVITY_STAR: Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - {e - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - } - R must be a symmetric and transitive relation. - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. - - OP_PR_MONOTONICITY: Monotonicity proof object. - {e - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - } - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. - - OP_PR_QUANT_INTRO: Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - - OP_PR_DISTRIBUTIVITY: Distributivity proof object. - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. - - OP_PR_AND_ELIM: Given a proof for (and l_1 ... l_n), produces a proof for l_i - {e - T1: (and l_1 ... l_n) - [and-elim T1]: l_i - } - - OP_PR_NOT_OR_ELIM: Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - {e - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) - } - - OP_PR_REWRITE: A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - Examples: - {e - (= (+ x 0) x) - (= (+ x 1 2) (+ 3 x)) - (iff (or x false) x) - } - - OP_PR_REWRITE_STAR: A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - - OP_PR_PULL_QUANT: A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - - OP_PR_PULL_QUANT_STAR: A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents. - - OP_PR_PUSH_QUANT: A proof for: - {e - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - } - This proof object has no antecedents. - - OP_PR_ELIM_UNUSED_VARS: - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - It is used to justify the elimination of unused variables. - This proof object has no antecedents. - - OP_PR_DER: A proof for destructive equality resolution: - (iff (forall (x) (or (not (= x t)) P[x])) P[t]) - if x does not occur in t. - This proof object has no antecedents. - Several variables can be eliminated simultaneously. - - OP_PR_QUANT_INST: A proof of (or (not (forall (x) (P x))) (P a)) - - OP_PR_HYPOTHESIS: Mark a hypothesis in a natural deduction style proof. - - OP_PR_LEMMA: - {e - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - } - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. - - OP_PR_UNIT_RESOLUTION: - {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - } - - OP_PR_IFF_TRUE: - {e - T1: p - [iff-true T1]: (iff p true) - } - - OP_PR_IFF_FALSE: - {e - T1: (not p) - [iff-false T1]: (iff p false) - } - - - OP_PR_COMMUTATIVITY: - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. - - - OP_PR_DEF_AXIOM: Proof object used to justify Tseitin's like axioms: - - {e - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - } - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). - - - OP_PR_DEF_INTRO: Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) - - - OP_PR_APPLY_DEF: - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. - - - OP_PR_IFF_OEQ: - T1: (iff p q) - [iff~ T1]: (~ p q) - - - OP_PR_NNF_POS: Proof for a (positive) NNF step. Example: - {e - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - } - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - {e - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - } - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. - - - - OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples: - {e - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) - } - - OP_PR_NNF_STAR: A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - - - OP_PR_CNF_STAR: A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - - - OP_PR_SKOLEMIZE: Proof for: - - {e - [sk]: (~ (not (forall x (p x y))) (not (p (sk y) y))) - [sk]: (~ (exists x (p x y)) (p (sk y) y)) - } - - This proof object has no antecedents. - - - OP_PR_MODUS_PONENS_OEQ: Modus ponens style rule for equi-satisfiability. - {e - T1: p - T2: (~ p q) - [mp~ T1 T2]: q - } - - - OP_PR_TH_LEMMA: Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - - triangle-eq - Indicates a lemma related to the equivalence: - {e - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - } - - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - - - - OP_PR_HYPER_RESOLVE: Hyper-resolution rule. - - The premises of the rules is a sequence of clauses. - The first clause argument is the main clause of the rule. - One literal from the second, third, .. clause is resolved - with a literal from the first (main) clause. - - Premises of the rules are of the form - {e - (or l0 l1 l2 .. ln) - } - or - {e - (=> (and ln+1 ln+2 .. ln+m) l0) - } - or in the most general (ground) form: - {e - (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)) - } - In other words we use the following (Prolog style) convention for Horn - implications: - The head of a Horn implication is position 0, - the first conjunct in the body of an implication is position 1 - the second conjunct in the body of an implication is position 2 - -<<<<<<< HEAD - For general implications where the head is a disjunction, the - first n positions correspond to the n disjuncts in the head. - The next m positions correspond to the m conjuncts in the body. -======= (** Create a context object The following parameters can be set: @@ -776,387 +47,194 @@ and goal_prec = - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver *) val mk_context : (string * string) list -> context ->>>>>>> Updates to ML API. - The premises can be universally quantified so that the most - general non-ground form is: +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log : +sig + (** Open an interaction log file. + @return True if opening the log file succeeds, false otherwise. *) + (* CMW: "open" seems to be a reserved keyword? *) + val open_ : string -> bool - {e - (forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1))) - } + (** Closes the interaction log. *) + val close : unit - The hyper-resolution rule takes a sequence of parameters. - The parameters are substitutions of bound variables separated by pairs - of literal positions from the main clause and side clause. + (** Appends a user-provided string to the interaction log. *) + val append : string -> unit +end +(** Version information *) +module Version : +sig + (** The major version. *) + val major : int - - OP_RA_STORE: Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements - correspond to the [n] columns of the relation. + (** The minor version. *) + val minor : int - - OP_RA_EMPTY: Creates the empty relation. + (** The build version. *) + val build : int - - OP_RA_IS_EMPTY: Tests if the relation is empty. + (** The revision. *) + val revision : int - - OP_RA_JOIN: Create the relational join. + (** A string representation of the version information. *) + val to_string : string +end - - OP_RA_UNION: Create the union or convex hull of two relations. - The function takes two arguments. +(** Symbols are used to name several term and type constructors *) +module Symbol : +sig + type symbol - - OP_RA_WIDEN: Widen two relations. - The function takes two arguments. + (** The kind of the symbol (int or string) *) + val kind : symbol -> Z3enums.symbol_kind - - OP_RA_PROJECT: Project the columns (provided as numbers in the parameters). - The function takes one argument. + (** Indicates whether the symbol is of Int kind *) + val is_int_symbol : symbol -> bool - - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. + (** Indicates whether the symbol is of string kind. *) + val is_string_symbol : symbol -> bool - - OP_RA_NEGATION_FILTER: Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function + (** The int value of the symbol. *) + val get_int : symbol -> int - target = filter_by_negation(pos, neg, columns) + (** The string value of the symbol. *) + val get_string : symbol -> string - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in x in pos, such that there is no y in neg that agrees with - x on the columns c1, d1, .., cN, dN. + (** A string representation of the symbol. *) + val to_string : symbol -> string + (** Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. *) + val mk_int : context -> int -> symbol - - OP_RA_RENAME: rename columns in the relation. - The function takes one argument. - The parameters contain the renaming as a cycle. + (** Creates a new symbol using a string. *) + val mk_string : context -> string -> symbol - - OP_RA_COMPLEMENT: Complement the relation. + (** Create a list of symbols. *) + val mk_ints : context -> int list -> symbol list - - OP_RA_SELECT: Check if a record is an element of the relation. - The function takes [n+1] arguments, where the first argument is a relation, - and the remaining [n] arguments correspond to a record. + (** Create a list of symbols. *) + val mk_strings : context -> string list -> symbol list +end - - OP_RA_CLONE: Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for [OP_RA_UNION] - to perform destructive updates to the first argument. +(** The abstract syntax tree (AST) module *) +module AST : +sig + type ast + (** Vectors of ASTs *) + module ASTVector : + sig + type ast_vector + + (** The size of the vector *) + val get_size : ast_vector -> int - - OP_FD_LT: A less than predicate over the finite domain FINITE_DOMAIN_SORT. + (** + Retrieves the i-th object in the vector. + @return An AST *) + val get : ast_vector -> int -> ast - - OP_LABEL: A label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. - It takes one argument, a formula. + (** Sets the i-th object in the vector. *) + val set : ast_vector -> int -> ast -> unit - - OP_LABEL_LIT: A label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. + (** Resize the vector to a new size. *) + val resize : ast_vector -> int -> unit - - OP_DT_CONSTRUCTOR: datatype constructor. + (** Add an ast to the back of the vector. The size + is increased by 1. *) + val push : ast_vector -> ast -> unit - - OP_DT_RECOGNISER: datatype recognizer. + (** Translates all ASTs in the vector to another context. + @return A new ASTVector *) + val translate : ast_vector -> context -> ast_vector - - OP_DT_ACCESSOR: datatype accessor. + (** Retrieves a string representation of the vector. *) + val to_string : ast_vector -> string + end - - OP_UNINTERPRETED: kind used for uninterpreted symbols. -*) -(** - {!param_kind} + (** Map from AST to AST *) + module ASTMap : + sig + type ast_map + + (** Checks whether the map contains a key. + @return True if the key in the map, false otherwise. *) + val contains : ast_map -> ast -> bool - The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). + (** Finds the value associated with the key. + This function signs an error when the key is not a key in the map. *) + val find : ast_map -> ast -> ast - - PK_UINT integer parameters. - - PK_BOOL boolean parameters. - - PK_DOUBLE double parameters. - - PK_SYMBOL symbol parameters. - - PK_STRING string parameters. - - PK_OTHER all internal parameter kinds which are not exposed in the API. - - PK_INVALID invalid parameter. -*) -(** - {!ast_print_mode} - Z3 pretty printing modes (See {!set_ast_print_mode}). - - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. - - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. - - PRINT_SMTLIB_COMPLIANT: Print AST nodes in SMTLIB 1.x compliant format. - - PRINT_SMTLIB2_COMPLIANT: Print AST nodes in SMTLIB 2.x compliant format. -*) -(** - {!error_code} - Z3 error codes - - OK: No error. - - SORT_ERROR: User tried to build an invalid (type incorrect) AST. - - IOB: Index out of bounds. - - INVALID_ARG: Invalid argument was provided. - - PARSER_ERROR: An error occurred when parsing a string or file. - - NO_PARSER: Parser output is not available, that is, user didn't invoke {!parse_smtlib_string} or {!parse_smtlib_file}. - - INVALID_PATTERN: Invalid pattern was used to build a quantifier. - - MEMOUT_FAIL: A memory allocation failure was encountered. - - FILE_ACCESS_ERRROR: A file could not be accessed. - - INVALID_USAGE: API call is invalid in the current state. - - INTERNAL_FATAL: An error internal to Z3 occurred. - - DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized. - - EXCEPTION: Internal Z3 exception. Additional details can be retrieved using {!get_error_msg}. -*) -(** - Definitions for update_api.py - def_Type('CONFIG', 'config', 'Config') - def_Type('CONTEXT', 'context', 'ContextObj') - def_Type('AST', 'ast', 'Ast') - def_Type('APP', 'app', 'Ast') - def_Type('SORT', 'sort', 'Sort') - def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') - def_Type('PATTERN', 'pattern', 'Pattern') - def_Type('MODEL', 'model', 'Model') - def_Type('LITERALS', 'literals', 'Literals') - def_Type('CONSTRUCTOR', 'constructor', 'Constructor') - def_Type('CONSTRUCTOR_LIST', 'constructor_list', 'ConstructorList') - def_Type('THEORY', 'theory', 'ctypes.c_void_p') - def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') - def_Type('SOLVER', 'solver', 'SolverObj') - def_Type('GOAL', 'goal', 'GoalObj') - def_Type('TACTIC', 'tactic', 'TacticObj') - def_Type('PARAMS', 'params', 'Params') - def_Type('PROBE', 'probe', 'ProbeObj') - def_Type('STATS', 'stats', 'StatsObj') - def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') - def_Type('AST_MAP', 'ast_map', 'AstMapObj') - def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') - def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') - def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') - def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') - def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') -*) + (** Stores or replaces a new key/value pair in the map. *) + val insert : ast_map -> ast -> ast -> unit -(** Exceptions raised by Z3. It is safe to continue interacting with Z3 after - catching [Error] exceptions. - - {b See also}: {!get_error_msg} -*) -exception Error of context * error_code + (** Erases the key from the map.*) + val erase : ast_map -> ast -> unit -(** - {!goal_prec} - A Goal is essentially a set of formulas. Z3 provide APIs for building strategies/tactics for solving and transforming Goals. Some of these transformations apply under/over approximations. - - GOAL_PRECISE: Approximations/Relaxations were not applied on the goal (sat and unsat answers were preserved). - - GOAL_UNDER: Goal is the product of a under-approximation (sat answers are preserved). - - GOAL_OVER: Goal is the product of an over-approximation (unsat answers are preserved). - - GOAL_UNDER_OVER: Goal is garbage (it is the product of over- and under-approximations, sat and unsat answers are not preserved). -*) -(** - {2 {L Create context}} -*) -(** - Summary: Create a context using the given configuration. - After a context is created, the configuration cannot be changed, - although some parameters can be changed using {!update_param_value}. - All main interaction with Z3 happens in the context of a [context]. - def_API('mk_context', CONTEXT, (_in(CONFIG),)) -*) -external mk_context: (string * string) list -> context = "caml_z3_mk_context" + (** Removes all keys from the map. *) + val reset : ast_map -> unit -(** - Summary: Set a value of a context parameter. - - {b See also}: {!global_param_set} - def_API('update_param_value', VOID, (_in(CONTEXT), _in(STRING), _in(STRING))) -*) -external update_param_value : context -> string -> string -> unit - = "camlidl_z3_Z3_update_param_value" + (** The size of the map *) + val get_size : ast_map -> int -(** - Summary: Return the value of a context parameter. - - {b See also}: {!global_param_get} - def_API('get_param_value', BOOL, (_in(CONTEXT), _in(STRING), _out(STRING))) -*) -external get_param_value : context -> string -> string option - = "camlidl_z3_Z3_get_param_value" + (** The keys stored in the map. *) + val get_keys : ast_map -> ast list -(** - Summary: Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. - def_API('interrupt', VOID, (_in(CONTEXT),)) -*) -external interrupt : context -> unit - = "camlidl_z3_Z3_interrupt" + (** Retrieves a string representation of the map.*) + val to_string : ast_map -> string + end -(** - {2 {L Parameters}} -*) -(** - Summary: Create a Z3 (empty) parameter set. - Starting at Z3 4.0, parameter sets are used to configure many components such as: - simplifiers, tactics, solvers, etc. - def_API('mk_params', PARAMS, (_in(CONTEXT),)) -*) -external mk_params : context -> params - = "camlidl_z3_Z3_mk_params" + (** The AST's hash code. + @return A hash code *) + val hash : ast -> int -(** - Summary: Add a Boolean parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_bool', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(BOOL))) -*) -external params_set_bool : context -> params -> symbol -> bool -> unit - = "camlidl_z3_Z3_params_set_bool" + (** A unique identifier for the AST (unique among all ASTs). *) + val get_id : ast -> int -(** - Summary: Add a unsigned int parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_uint', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(UINT))) -*) -external params_set_uint : context -> params -> symbol -> int -> unit - = "camlidl_z3_Z3_params_set_uint" + (** The kind of the AST. *) + val get_ast_kind : ast -> Z3enums.ast_kind -(** - Summary: Add a double parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_double', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(DOUBLE))) -*) -external params_set_double : context -> params -> symbol -> float -> unit - = "camlidl_z3_Z3_params_set_double" + (** Indicates whether the AST is an Expr *) + val is_expr : ast -> bool -(** - Summary: Add a symbol parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_symbol', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(SYMBOL))) -*) -external params_set_symbol : context -> params -> symbol -> symbol -> unit - = "camlidl_z3_Z3_params_set_symbol" + (** Indicates whether the AST is a bound variable*) + val is_var : ast -> bool -(** - Summary: Convert a parameter set into a string. This function is mainly used for printing the - contents of a parameter set. - def_API('params_to_string', STRING, (_in(CONTEXT), _in(PARAMS))) -*) -external params_to_string : context -> params -> string - = "camlidl_z3_Z3_params_to_string" + (** Indicates whether the AST is a Quantifier *) + val is_quantifier : ast -> bool -(** - Summary: Validate the parameter set [p] against the parameter description set [d]. - The procedure invokes the error handler if [p] is invalid. - def_API('params_validate', VOID, (_in(CONTEXT), _in(PARAMS), _in(PARAM_DESCRS))) -*) -external params_validate : context -> params -> param_descrs -> unit - = "camlidl_z3_Z3_params_validate" + (** Indicates whether the AST is a Sort *) + val is_sort : ast -> bool -(** - {2 {L Parameter Descriptions}} -*) -(** - Summary: Return the kind associated with the given parameter name [n]. - def_API('param_descrs_get_kind', UINT, (_in(CONTEXT), _in(PARAM_DESCRS), _in(SYMBOL))) -*) -external param_descrs_get_kind : context -> param_descrs -> symbol -> param_kind - = "camlidl_z3_Z3_param_descrs_get_kind" + (** Indicates whether the AST is a func_decl *) + val is_func_decl : ast -> bool -(** - Summary: Return the number of parameters in the given parameter description set. - def_API('param_descrs_size', UINT, (_in(CONTEXT), _in(PARAM_DESCRS))) -*) -external param_descrs_size : context -> param_descrs -> int - = "camlidl_z3_Z3_param_descrs_size" + (** A string representation of the AST. *) + val to_string : ast -> string -(** - Summary: Return the number of parameters in the given parameter description set. - - {b Precondition}: i < param_descrs_size c p - def_API('param_descrs_get_name', SYMBOL, (_in(CONTEXT), _in(PARAM_DESCRS), _in(UINT))) -*) -external param_descrs_get_name : context -> param_descrs -> int -> symbol - = "camlidl_z3_Z3_param_descrs_get_name" + (** A string representation of the AST in s-expression notation. *) + val to_sexpr : ast -> string -(** - Summary: Convert a parameter description set into a string. This function is mainly used for printing the - contents of a parameter description set. - def_API('param_descrs_to_string', STRING, (_in(CONTEXT), _in(PARAM_DESCRS))) -*) -external param_descrs_to_string : context -> param_descrs -> string - = "camlidl_z3_Z3_param_descrs_to_string" + (** Comparison operator. + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) + val equal : ast -> ast -> bool -(** - {2 {L Symbols}} -*) + (** Object Comparison. + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + val compare : ast -> ast -> int -(** - Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - - {b See also}: {!symbol_refine} -*) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string + (** Translates (copies) the AST to another context. + @return A copy of the AST which is associated with the other context. *) + val translate : ast -> context -> ast - -(** - Summary: \[ [ mk_symbol c sr ] \] constructs the symbol described by [sr]. - - {b See also}: {!symbol_refine} -*) -val mk_symbol: context -> symbol_refined -> symbol - -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a Z3 symbol using an integer. - Symbols are used to name several term and type constructors. - NB. Not all integers can be passed to this function. - The legal range of unsigned int integers is 0 to 2^30-1. - - {b See also}: {!mk_string_symbol} - def_API('mk_int_symbol', SYMBOL, (_in(CONTEXT), _in(INT))) -*) -external mk_int_symbol : context -> int -> symbol - = "camlidl_z3_Z3_mk_int_symbol" - -<<<<<<< HEAD -(** - Summary: Create a Z3 symbol using a C string. - Symbols are used to name several term and type constructors. - - {b See also}: {!mk_int_symbol} - def_API('mk_string_symbol', SYMBOL, (_in(CONTEXT), _in(STRING))) -*) -external mk_string_symbol : context -> string -> symbol - = "camlidl_z3_Z3_mk_string_symbol" - -(** - {2 {L Sorts}} -*) - -(** - A datatype constructor descriptor. -*) -type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) -} -(** - A datatype is described by a name and constructor descriptors. -*) -type datatype_desc = symbol * datatype_constructor_desc array -(** - A datatype constructor representation. -*) -type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) -} -(** - A datatype is represented by a sort and constructors. -*) -type datatype = sort * datatype_constructor array -(** - Refined view of a {!sort}. - - {b See also}: {!mk_sort} - - {b See also}: {!sort_refine} -*) -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_bv of int - | Sort_finite_domain of symbol * int64 - | Sort_real - | Sort_array of sort * sort - | Sort_datatype of datatype_constructor array - | Sort_relation of sort array - | Sort_unknown -======= (** Unwraps an AST. This function is used for transitions between native and managed objects. It returns the native pointer to the AST. Note that @@ -1176,573 +254,185 @@ type sort_refined = Z3native.inc_ref). *) val wrap_ast : context -> Z3native.z3_ast -> ast end ->>>>>>> Updates to ML API. +(** The Sort module implements type information for ASTs *) +module Sort : +sig + type sort = Sort of AST.ast -(** - Summary: \[ [ mk_sort c sr ] \] constructs the sort described by [sr]. - - {b Precondition}: [sr] is not of form [Sort_relation] or [Sort_unknown], which cannot be directly constructed - - {b See also}: {!mk_datatypes} - - {b See also}: {!sort_refine} -*) -val mk_sort: context -> sort_refined -> sort -(** - \[ [mk_datatypes ctx sorts_to_descriptors] \] creates mutually recursive datatypes described by - [sorts_to_descriptors], which is a function from the sorts of the datatypes to be created to - descriptors of the datatypes' constructors. - - {b See also}: {!Test_mlapi.forest_example} -*) -val mk_datatypes: context -> (sort array -> (datatype_desc array) option) -> datatype array + val ast_of_sort : sort -> AST.ast -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a free (uninterpreted) type using the given name (symbol). - Two free types are considered the same iff the have the same name. - def_API('mk_uninterpreted_sort', SORT, (_in(CONTEXT), _in(SYMBOL))) -*) -external mk_uninterpreted_sort : context -> symbol -> sort - = "camlidl_z3_Z3_mk_uninterpreted_sort" + (** Comparison operator. + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) + val equal : sort -> sort -> bool -(** - Summary: Create the Boolean type. - This type is used to create propositional variables and predicates. - def_API('mk_bool_sort', SORT, (_in(CONTEXT), )) -*) -external mk_bool_sort : context -> sort - = "camlidl_z3_Z3_mk_bool_sort" + (** Returns a unique identifier for the sort. *) + val get_id : sort -> int -(** - Summary: Create the integer type. - This type is not the int type found in programming languages. - A machine integer can be represented using bit-vectors. The function - {!mk_bv_sort} creates a bit-vector type. - - {b See also}: {!mk_bv_sort} - def_API('mk_int_sort', SORT, (_in(CONTEXT), )) -*) -external mk_int_sort : context -> sort - = "camlidl_z3_Z3_mk_int_sort" + (** The kind of the sort. *) + val get_sort_kind : sort -> Z3enums.sort_kind -(** - Summary: Create the real type. - This type is not a floating point number. - Z3 does not have support for floating point numbers yet. - def_API('mk_real_sort', SORT, (_in(CONTEXT), )) -*) -external mk_real_sort : context -> sort - = "camlidl_z3_Z3_mk_real_sort" + (** The name of the sort *) + val get_name : sort -> Symbol.symbol -(** - Summary: Create a bit-vector type of the given size. - This type can also be seen as a machine integer. - - {b Remarks}: The size of the bitvector type must be greater than zero. - def_API('mk_bv_sort', SORT, (_in(CONTEXT), _in(UINT))) -*) -external mk_bv_sort : context -> int -> sort - = "camlidl_z3_Z3_mk_bv_sort" + (** A string representation of the sort. *) + val to_string : sort -> string -(** - Summary: Create a named finite domain sort. - To create constants that belong to the finite domain, - use the APIs for creating numerals and pass a numeric - constant together with the sort returned by this call. - - {b See also}: {!get_finite_domain_sort_size} - def_API('mk_finite_domain_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT64))) -*) -external mk_finite_domain_sort : context -> symbol -> int64 -> sort - = "camlidl_z3_Z3_mk_finite_domain_sort" + (** Create a new uninterpreted sort. *) + val mk_uninterpreted : context -> Symbol.symbol -> sort -(** - Summary: Create an array type. - We usually represent the array type as: {e [domain -> range] }. - Arrays are usually used to model the heap/memory in software verification. - - {b See also}: {!mk_select} - - {b See also}: {!mk_store} - def_API('mk_array_sort', SORT, (_in(CONTEXT), _in(SORT), _in(SORT))) -*) -external mk_array_sort : context -> sort -> sort -> sort - = "camlidl_z3_Z3_mk_array_sort" + (** Create a new uninterpreted sort. *) + val mk_uninterpreted_s : context -> string -> sort +end -(** - Summary: Create a tuple type. - [mk_tuple_sort c name field_names field_sorts] creates a tuple with a constructor named [name], - a [n] fields, where [n] is the size of the arrays [field_names] and [field_sorts]. - @param c logical context - @param mk_tuple_name name of the constructor function associated with the tuple type. - @param num_fields number of fields in the tuple type. - @param field_names name of the projection functions. - @param field_sorts type of the tuple fields. - @param mk_tuple_decl output parameter that will contain the constructor declaration. - @param proj_decl output parameter that will contain the projection function declarations. This field must be a buffer of size [num_fields] allocated by the user. - def_API('mk_tuple_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array - = "camlidl_z3_Z3_mk_tuple_sort" +(** Function declarations *) +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast -(** - Summary: Create a enumeration sort. - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], - it also returns [n] predicates, where [n] is the number of [enums] corresponding - to testing whether an element is one of the enumerants. - @param c logical context - @param name name of the enumeration sort. - @param n number of elemenets in enumeration sort. - @param enum_names names of the enumerated elements. - @param enum_consts constants corresponding to the enumerated elements. - @param enum_testers predicates testing if terms of the enumeration sort correspond to an enumeration. - For example, if this function is called with three symbols A, B, C and the name S, then - [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in - [enum_consts]. The array [enum_testers] has three predicates of type {e (s -> Bool) }. - The first predicate (corresponding to A) is true when applied to A, and false otherwise. - Similarly for the other predicates. - def_API('mk_enumeration_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _out_array(2, FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array - = "camlidl_z3_Z3_mk_enumeration_sort" + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast -(** - Summary: Create a list sort - [mk_list_sort c name elem_sort] creates a list sort of [name], over elements of sort [elem_sort]. - @param c logical context - @param name name of the list sort. - @param elem_sort sort of list elements. - @param nil_decl declaration for the empty list. - @param is_nil_decl test for the empty list. - @param cons_decl declaration for a cons cell. - @param is_cons_decl cons cell test. - @param head_decl list head. - @param tail_decl list tail. - def_API('mk_list_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(SORT), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL))) -*) -external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl - = "camlidl_z3_Z3_mk_list_sort" + (** Parameters of Func_Decls *) + module Parameter : + sig + (** Parameters of func_decls *) + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) + val get_kind : parameter -> Z3enums.parameter_kind -(* -(** - Summary: Create a constructor. - @param c logical context. - @param name constructor name. - @param recognizer name of recognizer function. - @param num_fields number of fields in constructor. - @param field_names names of the constructor fields. - @param sorts field sorts, [None] - if the field sort refers to a recursive sort. - @param sort_refs reference to datatype sort that is an argument to the constructor; if the corresponding - sort reference is [None], - then the value in sort_refs should be an index referring to - one of the recursive datatypes that is declared. - def_API('mk_constructor', CONSTRUCTOR, (_in(CONTEXT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(3, SYMBOL), _in_array(3, SORT), _in_array(3, UINT))) -*) -external mk_constructor : context -> symbol -> symbol -> symbol array -> sort option array -> int array -> constructor - = "camlidl_z3_Z3_mk_constructor_bytecode" "camlidl_z3_Z3_mk_constructor" + (** The int value of the parameter.*) + val get_int : parameter -> int -(** - Summary: Reclaim memory allocated to constructor. - @param c logical context. - @param constr constructor. - def_API('del_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR))) -*) -external del_constructor : context -> constructor -> unit - = "camlidl_z3_Z3_del_constructor" + (** The float value of the parameter.*) + val get_float : parameter -> float -(** - Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. - The datatype may be recursive. Return the datatype sort. - @param c logical context. - @param name name of datatype. - @param num_constructors number of constructors passed in. - @param constructors array of constructor containers. - def_API('mk_datatype', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _inout_array(2, CONSTRUCTOR))) -*) -external mk_datatype : context -> symbol -> constructor array -> sort * constructor array - = "camlidl_z3_Z3_mk_datatype" + (** The Symbol.Symbol value of the parameter.*) + val get_symbol : parameter -> Symbol.symbol -(** - Summary: Create list of constructors. - @param c logical context. - @param num_constructors number of constructors in list. - @param constructors list of constructors. - def_API('mk_constructor_list', CONSTRUCTOR_LIST, (_in(CONTEXT), _in(UINT), _in_array(1, CONSTRUCTOR))) -*) -external mk_constructor_list : context -> constructor array -> constructor_list - = "camlidl_z3_Z3_mk_constructor_list" + (** The Sort value of the parameter.*) + val get_sort : parameter -> Sort.sort -(** - Summary: Reclaim memory allocated for constructor list. - Each constructor inside the constructor list must be independently reclaimed using {!del_constructor}. - @param c logical context. - @param clist constructor list container. - def_API('del_constructor_list', VOID, (_in(CONTEXT), _in(CONSTRUCTOR_LIST))) -*) -external del_constructor_list : context -> constructor_list -> unit - = "camlidl_z3_Z3_del_constructor_list" + (** The AST value of the parameter.*) + val get_ast : parameter -> AST.ast -(** - Summary: Create mutually recursive datatypes. - @param c logical context. - @param num_sorts number of datatype sorts. - @param sort_names names of datatype sorts. - @param sorts array of datatype sorts. - @param constructor_lists list of constructors, one list per sort. - def_API('mk_datatypes', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, SYMBOL), _out_array(1, SORT), _inout_array(1, CONSTRUCTOR_LIST))) -*) -external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array - = "camlidl_z3_Z3_mk_datatypes" + (** The FunctionDeclaration value of the parameter.*) + val get_func_decl : parameter -> func_decl -(** - Summary: Query constructor for declared functions. - @param c logical context. - @param constr constructor container. The container must have been passed in to a {!mk_datatype} call. - @param num_fields number of accessor fields in the constructor. - @param constructor constructor function declaration. - @param tester constructor test function declaration. - @param accessors array of accessor function declarations. - def_API('query_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR), _in(UINT), _out(FUNC_DECL), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array - = "camlidl_z3_Z3_query_constructor" + (** The rational string value of the parameter.*) + val get_rational : parameter -> string + end -*) -(** - {2 {L Constants and Applications}} -*) -(** - Summary: Declare a constant or function. - [mk_func_decl c n d r] creates a function with name [n], domain [d], and range [r]. - The arity of the function is the size of the array [d]. - @param c logical context. - @param s name of the constant or function. - @param domain_size number of arguments. It is 0 when declaring a constant. - @param domain array containing the sort of each argument. The array must contain domain_size elements. It is 0 when declaring a constant. - @param range sort of the constant or the return sort of the function. - After declaring a constant or function, the function - {!mk_app} can be used to create a constant or function - application. - - {b See also}: {!mk_app} - def_API('mk_func_decl', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) -*) -external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3_Z3_mk_func_decl" + (** Creates a new function declaration. *) + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl -(** - Summary: Create a constant or function application. - - {b See also}: {!mk_func_decl} - def_API('mk_app', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) -*) -external mk_app : context -> func_decl -> ast array -> ast - = "camlidl_z3_Z3_mk_app" + (** Creates a new function declaration. *) + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + (** Creates a fresh function declaration with a name prefixed with a prefix string. *) -(** - Summary: Declare and create a constant. - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - - {b See also}: {!mk_func_decl} - - {b See also}: {!mk_app} - def_API('mk_const', AST, (_in(CONTEXT), _in(SYMBOL), _in(SORT))) -*) -external mk_const : context -> symbol -> sort -> ast - = "camlidl_z3_Z3_mk_const" + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl -(** - Summary: Declare a fresh constant or function. - Z3 will generate an unique name for this function declaration. - - {b See also}: {!mk_func_decl} - def_API('mk_fresh_func_decl', FUNC_DECL, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SORT), _in(SORT))) -*) -external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl - = "camlidl_z3_Z3_mk_fresh_func_decl" + (** Creates a new constant function declaration. *) + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl -(** - Summary: Declare and create a fresh constant. - [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - - {b See also}: {!mk_func_decl} - - {b See also}: {!mk_app} - def_API('mk_fresh_const', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) -*) -external mk_fresh_const : context -> string -> sort -> ast - = "camlidl_z3_Z3_mk_fresh_const" + (** Creates a new constant function declaration. *) + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl -(** - {2 {L Propositional Logic and Equality}} -*) -(** - Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) -*) -external mk_true : context -> ast - = "camlidl_z3_Z3_mk_true" + (** Creates a fresh constant function declaration with a name prefixed with a prefix string. + {!mk_func_decl} + {!mk_func_decl} *) + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl -(** - Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) -*) -external mk_false : context -> ast - = "camlidl_z3_Z3_mk_false" + (** Comparison operator. + @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) + val equal : func_decl -> func_decl -> bool -(** - Summary: \[ [ mk_eq c l r ] \] - Create an AST node representing {e l = r }. - The nodes [l] and [r] must have the same type. - def_API('mk_eq', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_eq : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_eq" + (** A string representations of the function declaration. *) + val to_string : func_decl -> string -(** - Summary: \[ [mk_distinct c [| t_1; ...; t_n |]] \] Create an AST - node represeting a distinct construct. It is used for declaring - the arguments t_i pairwise distinct. - The [distinct] construct is used for declaring the arguments pairwise distinct. - That is, {e Forall 0 <= i < j < num_args. not args[i] = args[j] }. - All arguments must have the same sort. - - {b Remarks}: The number of arguments of a distinct construct must be greater than one. - def_API('mk_distinct', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_distinct : context -> ast array -> ast - = "camlidl_z3_Z3_mk_distinct" + (** Returns a unique identifier for the function declaration. *) + val get_id : func_decl -> int -(** - Summary: \[ [ mk_not c a ] \] - Create an AST node representing {e not(a) }. - The node [a] must have Boolean sort. - def_API('mk_not', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_not : context -> ast -> ast - = "camlidl_z3_Z3_mk_not" + (** The arity of the function declaration *) + val get_arity : func_decl -> int -(** - Summary: \[ [ mk_ite c t1 t2 t2 ] \] - Create an AST node representing an if-then-else: {e ite(t1, t2, - t3) }. - The node [t1] must have Boolean sort, [t2] and [t3] must have the same sort. - The sort of the new node is equal to the sort of [t2] and [t3]. - def_API('mk_ite', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) -*) -external mk_ite : context -> ast -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ite" + (** The size of the domain of the function declaration + {!get_arity} *) + val get_domain_size : func_decl -> int + + (** The domain of the function declaration *) + val get_domain : func_decl -> Sort.sort list + + (** The range of the function declaration *) + val get_range : func_decl -> Sort.sort -(** - Summary: \[ [ mk_iff c t1 t2 ] \] - Create an AST node representing {e t1 iff t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_iff', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_iff : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_iff" + (** The kind of the function declaration. *) + val get_decl_kind : func_decl -> Z3enums.decl_kind -(** - Summary: \[ [ mk_implies c t1 t2 ] \] - Create an AST node representing {e t1 implies t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_implies', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_implies : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_implies" + (** The name of the function declaration*) + val get_name : func_decl -> Symbol.symbol -(** - Summary: \[ [ mk_xor c t1 t2 ] \] - Create an AST node representing {e t1 xor t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_xor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_xor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_xor" + (** The number of parameters of the function declaration *) + val get_num_parameters : func_decl -> int -(** - Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. - All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_and', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_and : context -> ast array -> ast - = "camlidl_z3_Z3_mk_and" + (** The parameters of the function declaration *) + val get_parameters : func_decl -> Parameter.parameter list -(** - Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. - All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_or', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_or : context -> ast array -> ast - = "camlidl_z3_Z3_mk_or" + (** Create expression that applies function to arguments. *) + val apply : func_decl -> Expr.expr list -> Expr.expr +end -(** - {2 {L Arithmetic: Integers and Reals}} -*) -(** - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_add', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_add : context -> ast array -> ast - = "camlidl_z3_Z3_mk_add" +(** Parameter sets (of Solvers, Tactics, ...) -(** - Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. - All arguments must have int or real sort. - - {b Remarks}: Z3 has limited support for non-linear arithmetic. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_mul', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_mul : context -> ast array -> ast - = "camlidl_z3_Z3_mk_mul" + A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) +and Params : +sig + type params -(** - Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. - All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_sub', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_sub : context -> ast array -> ast - = "camlidl_z3_Z3_mk_sub" + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs : + sig + type param_descrs -(** - Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. - The arguments must have int or real type. - def_API('mk_unary_minus', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_unary_minus : context -> ast -> ast - = "camlidl_z3_Z3_mk_unary_minus" + (** Validate a set of parameters. *) + val validate : param_descrs -> params -> unit -(** - Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. - The arguments must either both have int type or both have real type. - If the arguments have int type, then the result type is an int type, otherwise the - the result type is real. - def_API('mk_div', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_div : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_div" + (** Retrieve kind of parameter. *) + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind -(** - Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. - The arguments must have int type. - def_API('mk_mod', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_mod : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_mod" + (** Retrieve all names of parameters. *) + val get_names : param_descrs -> Symbol.symbol list -(** - Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. - The arguments must have int type. - def_API('mk_rem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_rem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_rem" + (** The size of the ParamDescrs. *) + val get_size : param_descrs -> int -(** - The arguments must have int or real type. - def_API('mk_power', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_power : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_power" + (** Retrieves a string representation of the ParamDescrs. *) + val to_string : param_descrs -> string + end -(** - Summary: \[ [ mk_lt c t1 t2 ] \] - Create less than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_lt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_lt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_lt" + (** Adds a parameter setting. *) + val add_bool : params -> Symbol.symbol -> bool -> unit -(** - Summary: \[ [ mk_le c t1 t2 ] \] - Create less than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_le', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_le : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_le" + (** Adds a parameter setting. *) + val add_int : params -> Symbol.symbol -> int -> unit -(** - Summary: \[ [ mk_gt c t1 t2 ] \] - Create greater than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_gt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_gt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_gt" + (** Adds a parameter setting. *) + val add_float : params -> Symbol.symbol -> float -> unit -(** - Summary: \[ [ mk_ge c t1 t2 ] \] - Create greater than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_ge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ge" + (** Adds a parameter setting. *) + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit -(** - Summary: \[ [ mk_int2real c t1 ] \] - Coerce an integer to a real. - There is also a converse operation exposed. - It follows the semantics prescribed by the SMT-LIB standard. - You can take the floor of a real by - creating an auxiliary integer constant [k] and - and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. - The node [t1] must have sort integer. - - {b See also}: {!mk_real2int} - - {b See also}: {!mk_is_int} - def_API('mk_int2real', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_int2real : context -> ast -> ast - = "camlidl_z3_Z3_mk_int2real" + (** Creates a new parameter set *) + val mk_params : context -> params -(** - Summary: \[ [ mk_real2int c t1 ] \] - Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard - for the function to_int - - {b See also}: {!mk_int2real} - - {b See also}: {!mk_is_int} - def_API('mk_real2int', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_real2int : context -> ast -> ast - = "camlidl_z3_Z3_mk_real2int" - -(** - Summary: \[ [ mk_is_int c t1 ] \] - Check if a real number is an integer. - - {b See also}: {!mk_int2real} - - {b See also}: {!mk_real2int} - def_API('mk_is_int', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_is_int : context -> ast -> ast - = "camlidl_z3_Z3_mk_is_int" - -(** - {2 {L Bit-vectors}} -*) -(** - Summary: \[ [ mk_bvnot c t1 ] \] - Bitwise negation. - The node [t1] must have a bit-vector sort. - def_API('mk_bvnot', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvnot : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvnot" - -(** - Summary: \[ [ mk_bvredand c t1 ] \] - Take conjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredand', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvredand : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvredand" - -<<<<<<< HEAD -(** - Summary: \[ [ mk_bvredor c t1 ] \] - Take disjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredor', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvredor : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvredor" -======= (** A string representation of the parameter set. *) val to_string : params -> string @@ -1776,249 +466,300 @@ external mk_bvredor : context -> ast -> ast {!Sort.to_string} *) val set_print_mode : context -> Z3enums.ast_print_mode -> unit end ->>>>>>> Updates to ML API. -(** - Summary: \[ [ mk_bvand c t1 t2 ] \] - Bitwise and. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvand', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvand : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvand" +(** General Expressions (terms) *) +and Expr : +sig + type expr = Expr of AST.ast -(** - Summary: \[ [ mk_bvor c t1 t2 ] \] - Bitwise or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvor" + val ast_of_expr : Expr.expr -> AST.ast + val expr_of_ast : AST.ast -> Expr.expr -(** - Summary: \[ [ mk_bvxor c t1 t2 ] \] - Bitwise exclusive-or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvxor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvxor" + (** Returns a simplified version of the expression. + {!get_simplify_help} *) + val simplify : Expr.expr -> Params.params option -> expr -(** - Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnand', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvnand : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvnand" + (** A string describing all available parameters to Expr.Simplify. *) + val get_simplify_help : context -> string -(** - Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvnor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvnor" + (** Retrieves parameter descriptions for simplifier. *) + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs -(** - Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvxnor : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvxnor" + (** The function declaration of the function that is applied in this expression. *) + val get_func_decl : Expr.expr -> FuncDecl.func_decl -(** - Summary: \[ [ mk_bvneg c t1 ] \] - Standard two's complement unary minus. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvneg : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvneg" + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) + val get_bool_value : Expr.expr -> Z3enums.lbool -(** - Summary: \[ [ mk_bvadd c t1 t2 ] \] - Standard two's complement addition. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvadd : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvadd" + (** The number of arguments of the expression. *) + val get_num_args : Expr.expr -> int -(** - Summary: \[ [ mk_bvsub c t1 t2 ] \] - Standard two's complement subtraction. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsub : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsub" + (** The arguments of the expression. *) + val get_args : Expr.expr -> Expr.expr list -(** - Summary: \[ [ mk_bvmul c t1 t2 ] \] - Standard two's complement multiplication. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvmul : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvmul" + (** Update the arguments of the expression using an array of expressions. + The number of new arguments should coincide with the current number of arguments. *) + val update : Expr.expr -> Expr.expr list -> expr -(** - Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - It is defined as the [floor] of {e t1/t2 } if [t2] is - different from zero. If {e t2 } is zero, then the result - is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvudiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvudiv : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvudiv" + (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. *) + val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr -(** - Summary: \[ [ mk_bvsdiv c t1 t2 ] \] - Two's complement signed division. - It is defined in the following way: - - The [floor] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 >= 0 }. - - The [ceiling] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 < 0 }. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsdiv : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsdiv" + (** Substitute every occurrence of from in the expression with to. + {!substitute} *) + val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr -(** - Summary: \[ [ mk_bvurem c t1 t2 ] \] - Unsigned remainder. - It is defined as {e t1 - (t1 /u t2) * t2 }, where {e /u } represents unsigned int division. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvurem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvurem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvurem" + (** Substitute the free variables in the expression with the expressions in the expr array -(** - Summary: \[ [ mk_bvsrem c t1 t2 ] \] - Two's complement signed remainder (sign follows dividend). - It is defined as {e t1 - (t1 /s t2) * t2 }, where {e /s } represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of [t1]. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsmod} - def_API('mk_bvsrem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsrem : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsrem" + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) + val substitute_vars : Expr.expr -> Expr.expr list -> expr -(** - Summary: \[ [ mk_bvsmod c t1 t2 ] \] - Two's complement signed remainder (sign follows divisor). - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsrem} - def_API('mk_bvsmod', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsmod : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsmod" + (** Translates (copies) the term to another context. + @return A copy of the term which is associated with the other context *) + val translate : Expr.expr -> context -> expr -(** - Summary: \[ [ mk_bvult c t1 t2 ] \] - Unsigned less than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvult', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvult : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvult" + (** Returns a string representation of the expression. *) + val to_string : Expr.expr -> string -(** - Summary: \[ [ mk_bvslt c t1 t2 ] \] - Two's complement signed less than. - It abbreviates: - {v - (or (and (= (extract[|m-1|:|m-1|] t1) bit1) - (= (extract[|m-1|:|m-1|] t2) bit0)) - (and (= (extract[|m-1|:|m-1|] t1) (extract[|m-1|:|m-1|] t2)) - (bvult t1 t2))) - v} - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvslt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvslt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvslt" + (** Indicates whether the term is a numeral *) + val is_numeral : Expr.expr -> bool -(** - Summary: \[ [ mk_bvule c t1 t2 ] \] - Unsigned less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvule', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvule : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvule" + (** Indicates whether the term is well-sorted. + @return True if the term is well-sorted, false otherwise. *) + val is_well_sorted : Expr.expr -> bool -(** - Summary: \[ [ mk_bvsle c t1 t2 ] \] - Two's complement signed less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsle', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsle : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsle" + (** The Sort of the term. *) + val get_sort : Expr.expr -> Sort.sort -(** - Summary: \[ [ mk_bvuge c t1 t2 ] \] - Unsigned greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvuge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvuge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvuge" + (** Indicates whether the term has Boolean sort. *) + val is_bool : Expr.expr -> bool -(** - Summary: \[ [ mk_bvsge c t1 t2 ] \] - Two's complement signed greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsge : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsge" + (** Indicates whether the term represents a constant. *) + val is_const : Expr.expr -> bool -(** - Summary: \[ [ mk_bvugt c t1 t2 ] \] - Unsigned greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvugt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvugt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvugt" + (** Indicates whether the term is the constant true. *) + val is_true : Expr.expr -> bool -(** - Summary: \[ [ mk_bvsgt c t1 t2 ] \] - Two's complement signed greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsgt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsgt : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsgt" + (** Indicates whether the term is the constant false. *) + val is_false : Expr.expr -> bool + + (** Indicates whether the term is an equality predicate. *) + val is_eq : Expr.expr -> bool + + (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) + val is_distinct : Expr.expr -> bool + + (** Indicates whether the term is a ternary if-then-else term *) + val is_ite : Expr.expr -> bool + + (** Indicates whether the term is an n-ary conjunction *) + val is_and : Expr.expr -> bool + + (** Indicates whether the term is an n-ary disjunction *) + val is_or : Expr.expr -> bool + + (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) + val is_iff : Expr.expr -> bool + + (** Indicates whether the term is an exclusive or *) + val is_xor : Expr.expr -> bool + + (** Indicates whether the term is a negation *) + val is_not : Expr.expr -> bool + + (** Indicates whether the term is an implication *) + val is_implies : Expr.expr -> bool + + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) + val is_oeq : Expr.expr -> bool + + (** Creates a new constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) + val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) + val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) + val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr + + (** Create a numeral of a given sort. + @return A Term with the goven value and sort *) + val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) + val mk_numeral_int : context -> int -> Sort.sort -> expr +end + +(** Boolean expressions *) +module Boolean : +sig + (** Create a Boolean sort *) + val mk_sort : context -> Sort.sort + + (** Create a Boolean constant. *) + val mk_const : context -> Symbol.symbol -> Expr.expr + + (** Create a Boolean constant. *) + val mk_const_s : context -> string -> Expr.expr + + (** The true Term. *) + val mk_true : context -> Expr.expr + + (** The false Term. *) + val mk_false : context -> Expr.expr + + (** Creates a Boolean value. *) + val mk_val : context -> bool -> Expr.expr + + (** Creates the equality between two expr's. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Creates a distinct term. *) + val mk_distinct : context -> Expr.expr list -> Expr.expr + + (** Mk an expression representing not(a). *) + val mk_not : context -> Expr.expr -> Expr.expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 iff t2. *) + val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 -> t2. *) + val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 xor t2. *) + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing the AND of args *) + val mk_and : context -> Expr.expr list -> Expr.expr + + (** Create an expression representing the OR of args *) + val mk_or : context -> Expr.expr list -> Expr.expr +end + +(** Quantifier expressions *) +module Quantifier : +sig + type quantifier = Quantifier of Expr.expr + + val expr_of_quantifier : quantifier -> Expr.expr + val quantifier_of_expr : Expr.expr -> quantifier + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. *) + module Pattern : + sig + type pattern = Pattern of AST.ast + + val ast_of_pattern : pattern -> AST.ast + val pattern_of_ast : AST.ast -> pattern + + (** The number of terms in the pattern. *) + val get_num_terms : pattern -> int + + (** The terms in the pattern. *) + val get_terms : pattern -> Expr.expr list + + (** A string representation of the pattern. *) + val to_string : pattern -> string + end + + + (** The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) + val get_index : Expr.expr -> int + + (** Indicates whether the quantifier is universal. *) + val is_universal : quantifier -> bool + + (** Indicates whether the quantifier is existential. *) + val is_existential : quantifier -> bool + + (** The weight of the quantifier. *) + val get_weight : quantifier -> int + + (** The number of patterns. *) + val get_num_patterns : quantifier -> int + + (** The patterns. *) + val get_patterns : quantifier -> Pattern.pattern list + + (** The number of no-patterns. *) + val get_num_no_patterns : quantifier -> int + + (** The no-patterns. *) + val get_no_patterns : quantifier -> Pattern.pattern list + + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) + val get_bound_variable_names : quantifier -> Symbol.symbol list + + (** The sorts of the bound variables. *) + val get_bound_variable_sorts : quantifier -> Sort.sort list + + (** The body of the quantifier. *) + val get_body : quantifier -> Expr.expr + + (** Creates a new bound variable. *) + val mk_bound : context -> int -> Sort.sort -> Expr.expr + + (** Create a quantifier pattern. *) + val mk_pattern : context -> Expr.expr list -> Pattern.pattern + + (** Create a universal Quantifier. *) + val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a universal Quantifier. *) + val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier +end -<<<<<<< HEAD -(** - Summary: \[ [ mk_concat c t1 t2 ] \] - Concatenate the given bit-vectors. - The nodes [t1] and [t2] must have (possibly different) bit-vector sorts - The result is a bit-vector of size {e n1+n2 }, where [n1] ([n2)] is the size - of [t1] ([t2)]. - def_API('mk_concat', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_concat : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_concat" -======= (** Functions to manipulate Array expressions *) module Array : sig @@ -2117,7669 +858,2049 @@ sig finite maps with a default range value. *) val mk_term_array : context -> Expr.expr -> Expr.expr end ->>>>>>> Updates to ML API. -(** - Summary: \[ [ mk_extract c high low t1 ] \] - Extract the bits [high] down to [low] from a bitvector of - size [m] to yield a new bitvector of size [n], where {e n = - high - low + 1 }. - The node [t1] must have a bit-vector sort. - def_API('mk_extract', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in(AST))) -*) -external mk_extract : context -> int -> int -> ast -> ast - = "camlidl_z3_Z3_mk_extract" +(** Functions to manipulate Set expressions *) +module Set : +sig + (** Create a set type. *) + val mk_sort : context -> Sort.sort -> Sort.sort -(** - Summary: \[ [ mk_sign_ext c i t1 ] \] - Sign-extend of the given bit-vector to the (signed) equivalent bitvector of - size {e m+i }, where [m] is the size of the given - bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_sign_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_sign_ext : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_sign_ext" + (** Indicates whether the term is set union *) + val is_union : Expr.expr -> bool -(** - Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size {e m+i }, where [m] is the size of the - given bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_zero_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_zero_ext : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_zero_ext" + (** Indicates whether the term is set intersection *) + val is_intersect : Expr.expr -> bool -(** - Summary: \[ [ mk_repeat c i t1 ] \] - Repeat the given bit-vector up length {e i }. - The node [t1] must have a bit-vector sort. - def_API('mk_repeat', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_repeat : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_repeat" + (** Indicates whether the term is set difference *) + val is_difference : Expr.expr -> bool -(** - Summary: \[ [ mk_bvshl c t1 t2 ] \] - Shift left. - It is equivalent to multiplication by {e 2^x } where [x] is the value of the - third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvshl', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvshl : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvshl" + (** Indicates whether the term is set complement *) + val is_complement : Expr.expr -> bool -(** - Summary: \[ [ mk_bvlshr c t1 t2 ] \] - Logical shift right. - It is equivalent to unsigned int division by {e 2^x } where [x] is the - value of the third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvlshr', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvlshr : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvlshr" + (** Indicates whether the term is set subset *) + val is_subset : Expr.expr -> bool -(** - Summary: \[ [ mk_bvashr c t1 t2 ] \] - Arithmetic shift right. - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvashr', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvashr : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvashr" + (** Create an empty set. *) + val mk_empty : context -> Sort.sort -> Expr.expr -(** - Summary: \[ [ mk_rotate_left c i t1 ] \] - Rotate bits of [t1] to the left [i] times. - The node [t1] must have a bit-vector sort. - def_API('mk_rotate_left', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_rotate_left : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_rotate_left" + (** Create the full set. *) + val mk_full : context -> Sort.sort -> Expr.expr -(** - Summary: \[ [ mk_rotate_right c i t1 ] \] - Rotate bits of [t1] to the right [i] times. - The node [t1] must have a bit-vector sort. - def_API('mk_rotate_right', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_rotate_right : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_rotate_right" + (** Add an element to the set. *) + val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: \[ [ mk_ext_rotate_left c t1 t2 ] \] - Rotate bits of [t1] to the left [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_left', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ext_rotate_left : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ext_rotate_left" + (** Remove an element from a set. *) + val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: \[ [ mk_ext_rotate_right c t1 t2 ] \] - Rotate bits of [t1] to the right [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_right', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ext_rotate_right : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_ext_rotate_right" + (** Take the union of a list of sets. *) + val mk_union : context -> Expr.expr list -> Expr.expr -(** - Summary: \[ [ mk_int2bv c n t1 ] \] - Create an [n] bit bit-vector from the integer argument [t1]. - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - The node [t1] must have integer sort. - def_API('mk_int2bv', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_int2bv : context -> int -> ast -> ast - = "camlidl_z3_Z3_mk_int2bv" + (** Take the intersection of a list of sets. *) + val mk_intersection : context -> Expr.expr list -> Expr.expr -(** - Summary: \[ [ mk_bv2int c t1 is_signed ] \] - Create an integer from the bit-vector argument [t1]. - If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. - So the result is non-negative - and in the range {e [0..2^N-1] }, where N are the number of bits in [t1]. - If [is_signed] is true, [t1] is treated as a signed bit-vector. - This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - The node [t1] must have a bit-vector sort. - def_API('mk_bv2int', AST, (_in(CONTEXT), _in(AST), _in(BOOL))) -*) -external mk_bv2int : context -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bv2int" + (** Take the difference between two sets. *) + val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: \[ [ mk_bvadd_no_overflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise addition - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvadd_no_overflow" + (** Take the complement of a set. *) + val mk_complement : context -> Expr.expr -> Expr.expr -(** - Summary: \[ [ mk_bvadd_no_underflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed addition - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvadd_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvadd_no_underflow" + (** Check for set membership. *) + val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: \[ [ mk_bvsub_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed subtraction - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsub_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsub_no_overflow" + (** Check for subsetness of sets. *) + val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr +end -(** - Summary: \[ [ mk_bvsub_no_underflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise subtraction - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvsub_no_underflow" +(** Functions to manipulate Finite Domain expressions *) +module FiniteDomain : +sig + (** Create a new finite domain sort. *) + val mk_sort : context -> Symbol.symbol -> int -> Sort.sort -(** - Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvsdiv_no_overflow" + (** Create a new finite domain sort. *) + val mk_sort_s : context -> string -> int -> Sort.sort -(** - Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when - [t1] is interpreted as a signed bit-vector. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg_no_overflow', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvneg_no_overflow : context -> ast -> ast - = "camlidl_z3_Z3_mk_bvneg_no_overflow" + (** Indicates whether the term is of an array sort. *) + val is_finite_domain : Expr.expr -> bool -(** - Summary: \[ [ mk_bvmul_no_overflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise multiplication - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3_Z3_mk_bvmul_no_overflow" + (** Indicates whether the term is a less than predicate over a finite domain. *) + val is_lt : Expr.expr -> bool -(** - Summary: \[ [ mk_bvmul_no_underflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed multiplication - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvmul_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_bvmul_no_underflow" + (** The size of the finite domain sort. *) + val get_size : Sort.sort -> int +end -(** - {2 {L Arrays}} -*) -(** - Summary: \[ [ mk_select c a i ] \] - Array read. - The argument [a] is the array and [i] is the index of the array that gets read. - The node [a] must have an array sort {e [domain -> range] }, - and [i] must have the sort [domain]. - The sort of the result is [range]. - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_store} - def_API('mk_select', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_select : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_select" -(** - Summary: \[ [ mk_store c a i v ] \] - Array update. - The node [a] must have an array sort {e [domain -> range] }, [i] must have sort [domain], - [v] must have sort range. The sort of the result is {e [domain -> range] }. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to [a] (with respect to [select)] - on all indices except for [i], where it maps to [v] (and the [select] of [a] with - respect to [i] may be a different value). - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_select} - def_API('mk_store', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) -*) -external mk_store : context -> ast -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_store" +(** Functions to manipulate Relation expressions *) +module Relation : +sig + (** Indicates whether the term is of a relation sort. *) + val is_relation : Expr.expr -> bool -(** - Summary: Create the constant array. - The resulting term is an array, such that a [select] on an arbitrary index - produces the value [v]. - @param c logical context. - @param domain domain sort for the array. - @param v value that the array maps to. - def_API('mk_const_array', AST, (_in(CONTEXT), _in(SORT), _in(AST))) -*) -external mk_const_array : context -> sort -> ast -> ast - = "camlidl_z3_Z3_mk_const_array" + (** Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. *) + val is_store : Expr.expr -> bool -(** - Summary: \[ [ mk_map f n args ] \] - map f on the the argument arrays. - The [n] nodes [args] must be of array sorts {e [domain_i -> range_i] }. - The function declaration [f] must have type {e range_1 .. range_n -> range }. - [v] must have sort range. The sort of the result is {e [domain_i -> range] }. - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_store} - - {b See also}: {!mk_select} - def_API('mk_map', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) -*) -external mk_map : context -> func_decl -> int -> ast -> ast - = "camlidl_z3_Z3_mk_map" + (** Indicates whether the term is an empty relation *) + val is_empty : Expr.expr -> bool -(** - Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - @param c logical context. - @param array array value whose default range value is accessed. - def_API('mk_array_default', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_array_default : context -> ast -> ast - = "camlidl_z3_Z3_mk_array_default" + (** Indicates whether the term is a test for the emptiness of a relation *) + val is_is_empty : Expr.expr -> bool -(** - {2 {L Sets}} -*) -(** - Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) -*) -external mk_set_sort : context -> sort -> sort - = "camlidl_z3_Z3_mk_set_sort" + (** Indicates whether the term is a relational join *) + val is_join : Expr.expr -> bool -(** - Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) -*) -external mk_empty_set : context -> sort -> ast - = "camlidl_z3_Z3_mk_empty_set" + (** Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is the widening of two relations + The function takes two arguments. *) + val is_widen : Expr.expr -> bool + + (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. *) + val is_project : Expr.expr -> bool + + (** Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) + val is_filter : Expr.expr -> bool + + (** Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) + val is_negation_filter : Expr.expr -> bool + + (** Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. *) + val is_rename : Expr.expr -> bool + + (** Indicates whether the term is the complement of a relation *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) + val is_clone : Expr.expr -> bool + + (** The arity of the relation sort. *) + val get_arity : Sort.sort -> int + + (** The sorts of the columns of the relation sort. *) + val get_column_sorts : Sort.sort -> Sort.sort list +end + +(** Functions to manipulate Datatype expressions *) +module Datatype : +sig + (** Datatype Constructors *) + module Constructor : + sig + type constructor + + (** The number of fields of the constructor. *) + val get_num_fields : constructor -> int + + (** The function declaration of the constructor. *) + val get_constructor_decl : constructor -> FuncDecl.func_decl + + (** The function declaration of the tester. *) + val get_tester_decl : constructor -> FuncDecl.func_decl + + (** The function declarations of the accessors *) + val get_accessor_decls : constructor -> FuncDecl.func_decl list + end + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a new datatype sort. *) + val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> Sort.sort + + (** Create a new datatype sort. *) + val mk_sort_s : context -> string -> Constructor.constructor list -> Sort.sort + + (** Create mutually recursive datatypes. *) + val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> Sort.sort list + + (** Create mutually recursive data-types. *) + val mk_sorts_s : context -> string list -> Constructor.constructor list list -> Sort.sort list + + + (** The number of constructors of the datatype sort. *) + val get_num_constructors : Sort.sort -> int + + (** The constructors. *) + val get_constructors : Sort.sort -> FuncDecl.func_decl list + + (** The recognizers. *) + val get_recognizers : Sort.sort -> FuncDecl.func_decl list + + (** The constructor accessors. *) + val get_accessors : Sort.sort -> FuncDecl.func_decl list list +end + +(** Functions to manipulate Enumeration expressions *) +module Enumeration : +sig + (** Create a new enumeration sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort + + (** Create a new enumeration sort. *) + val mk_sort_s : context -> string -> string list -> Sort.sort + + (** The function declarations of the constants in the enumeration. *) + val get_const_decls : Sort.sort -> FuncDecl.func_decl list + + (** The test predicates for the constants in the enumeration. *) + val get_tester_decls : Sort.sort -> FuncDecl.func_decl list +end -<<<<<<< HEAD -(** - Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) -*) -external mk_full_set : context -> sort -> ast - = "camlidl_z3_Z3_mk_full_set" -======= (** Functions to manipulate List expressions *) module List : sig (** Create a new list sort. *) val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort ->>>>>>> Updates to ML API. -(** - Summary: Add an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_add', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_add : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_add" + (** Create a new list sort. *) + val mk_list_s : context -> string -> Sort.sort -> Sort.sort -(** - Summary: Remove an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_del', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_del : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_del" + (** The declaration of the nil function of this list sort. *) + val get_nil_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Take the union of a list of sets. - def_API('mk_set_union', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_set_union : context -> ast array -> ast - = "camlidl_z3_Z3_mk_set_union" + (** The declaration of the isNil function of this list sort. *) + val get_is_nil_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Take the intersection of a list of sets. - def_API('mk_set_intersect', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_set_intersect : context -> ast array -> ast - = "camlidl_z3_Z3_mk_set_intersect" + (** The declaration of the cons function of this list sort. *) + val get_cons_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Take the set difference between two sets. - def_API('mk_set_difference', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_difference : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_difference" + (** The declaration of the isCons function of this list sort. *) + val get_is_cons_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_set_complement : context -> ast -> ast - = "camlidl_z3_Z3_mk_set_complement" + (** The declaration of the head function of this list sort. *) + val get_head_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Check for set membership. - The first argument should be an element type of the set. - def_API('mk_set_member', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_member : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_member" + (** The declaration of the tail function of this list sort. *) + val get_tail_decl : Sort.sort -> FuncDecl.func_decl -(** - Summary: Check for subsetness of sets. - def_API('mk_set_subset', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_subset : context -> ast -> ast -> ast - = "camlidl_z3_Z3_mk_set_subset" + (** The empty list. *) + val nil : Sort.sort -> Expr.expr +end -(** - {2 {L Numerals}} -*) +(** Functions to manipulate Tuple expressions *) +module Tuple : +sig + (** Create a new tuple sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> Sort.sort -(** - Summary: \[ [ numeral_refined ] \] is the refined view of a numeral . -*) -type numeral_refined = - | Numeral_int of int * sort - | Numeral_int64 of int64 * sort - | Numeral_large of string * sort - | Numeral_rational of numeral_refined * numeral_refined + (** The constructor function of the tuple. *) + val get_mk_decl : Sort.sort -> FuncDecl.func_decl + (** The number of fields in the tuple. *) + val get_num_fields : Sort.sort -> int -(** - Summary: \[ [ embed_numeral c nr ] \] constructs the numeral described by [nr]. - - {b See also}: {!numeral_refine} -*) -val embed_numeral: context -> numeral_refined -> ast + (** The field declarations. *) + val get_field_decls : Sort.sort -> FuncDecl.func_decl list +end -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a numeral of a given sort. - @param c logical context. - @param numeral A string representing the numeral value in decimal notation. If the given sort is a real, then the numeral can be a rational, that is, a string of the form {e [num]* / [num]* }. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - - {b See also}: {!mk_int} - def_API('mk_numeral', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) -*) -external mk_numeral : context -> string -> sort -> ast - = "camlidl_z3_Z3_mk_numeral" +(** Functions to manipulate arithmetic expressions *) +module Arithmetic : +sig + (** Integer Arithmetic *) + module Integer : + sig + (** Create a new integer sort. *) + val mk_sort : context -> Sort.sort -(** - Summary: Create a real from a fraction. - @param c logical context. - @param num numerator of rational. - @param den denomerator of rational. - - {b Precondition}: den != 0 - - {b See also}: {!mk_numeral} - - {b See also}: {!mk_int} - def_API('mk_real', AST, (_in(CONTEXT), _in(INT), _in(INT))) -*) -external mk_real : context -> int -> int -> ast - = "camlidl_z3_Z3_mk_real" + (** Retrieve the int value. *) + val get_int : Expr.expr -> int -(** - Summary: Create a numeral of an int, bit-vector, or finite-domain sort. - This function can be use to create numerals that fit in a machine integer. - It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int', AST, (_in(CONTEXT), _in(INT), _in(SORT))) -*) -external mk_int : context -> int -> sort -> ast - = "camlidl_z3_Z3_mk_int" + (** Returns a string representation of the numeral. *) + val to_string : Expr.expr -> string -(** - Summary: Create a numeral of a int, bit-vector, or finite-domain sort. - This function can be use to create numerals that fit in a machine long long integer. - It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int64', AST, (_in(CONTEXT), _in(INT64), _in(SORT))) -*) -external mk_int64 : context -> int64 -> sort -> ast - = "camlidl_z3_Z3_mk_int64" + (** Creates an integer constant. *) + val mk_const : context -> Symbol.symbol -> Expr.expr -(** - {2 {L Quantifiers}} -*) -(** - Summary: Create a pattern for quantifier instantiation. - Z3 uses pattern matching to instantiate quantifiers. If a - pattern is not provided for a quantifier, then Z3 will - automatically compute a set of patterns for it. However, for - optimal performance, the user should provide the patterns. - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - a called a multi-pattern. - In general, one can pass in a list of (multi-)patterns in the - quantifier constructor. - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_pattern', PATTERN, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_pattern : context -> ast array -> pattern - = "camlidl_z3_Z3_mk_pattern" + (** Creates an integer constant. *) + val mk_const_s : context -> string -> Expr.expr -(** - Summary: Create a bound variable. - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - {v - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - v} - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper x appears, the higher is its - index. - @param c logical context - @param index de-Bruijn index - @param ty sort of the bound variable - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_bound', AST, (_in(CONTEXT), _in(UINT), _in(SORT))) -*) -external mk_bound : context -> int -> sort -> ast - = "camlidl_z3_Z3_mk_bound" + (** Create an expression representing t1 mod t2. + The arguments must have int type. *) + val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Create a forall formula. It takes an expression [body] that contains bound variables - of the same sorts as the sorts listed in the array [sorts]. The bound variables are de-Bruijn indices created - using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the - bound variables. Z3 applies the convention that the last element in the [decl_names] and [sorts] array - refers to the variable with index 0, the second to last element of [decl_names] and [sorts] refers - to the variable with index 1, etc. - [mk_forall c w p t n b] creates a forall formula, where - [w] is the weight, [p] is an array of patterns, [t] is an array - with the sorts of the bound variables, [n] is an array with the - 'names' of the bound variables, and [b] is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during - instantiation. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_decls number of variables to be bound. - @param sorts the sorts of the bound variables. - @param decl_names names of the bound variables - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_exists} - def_API('mk_forall', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) -*) -external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_bytecode" "camlidl_z3_Z3_mk_forall" + (** Create an expression representing t1 rem t2. + The arguments must have int type. *) + val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Create an exists formula. Similar to {!mk_forall}. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_quantifier} - def_API('mk_exists', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) -*) -external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_bytecode" "camlidl_z3_Z3_mk_exists" + (** Create an integer numeral. *) + val mk_numeral_s : context -> string -> Expr.expr -(** - Summary: Create a quantifier - universal or existential, with pattern hints. - See the documentation for {!mk_forall} for an explanation of the parameters. - @param c logical context. - @param is_forall flag to indicate if this is a universal or existential quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_decls number of variables to be bound. - @param sorts array of sorts of the bound variables. - @param decl_names names of the bound variables. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_quantifier', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, PATTERN), _in(UINT), _in_array(5, SORT), _in_array(5, SYMBOL), _in(AST))) -*) -external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_bytecode" "camlidl_z3_Z3_mk_quantifier" + (** Create an integer numeral. + @return A Term with the given value and sort Integer *) + val mk_numeral_i : context -> int -> Expr.expr -(** - Summary: Create a quantifier - universal or existential, with pattern hints, no patterns, and attributes - @param c logical context. - @param is_forall flag to indicate if this is a universal or existential quantifier. - @param quantifier_id identifier to identify quantifier - @param skolem_id identifier to identify skolem constants introduced by quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_no_patterns number of no_patterns. - @param no_patterns array containing subexpressions to be excluded from inferred patterns. - @param num_decls number of variables to be bound. - @param sorts array of sorts of the bound variables. - @param decl_names names of the bound variables. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_quantifier_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, PATTERN), _in(UINT), _in_array(7, AST), _in(UINT), _in_array(9, SORT), _in_array(9, SYMBOL), _in(AST))) -*) -external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3_Z3_mk_quantifier_ex" + (** Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. *) + val mk_int2real : context -> Expr.expr -> Expr.expr -(** - Summary: Create a universal quantifier using a list of constants that - will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using - the quantifier during instantiation. By default, pass the weight 0. - @param num_bound number of constants to be abstracted into bound variables. - @param bound array of constants to be abstracted into bound variables. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_exists_const} - def_API('mk_forall_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) -*) -external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_const" - -(** - Summary: Similar to {!mk_forall_const}. - Summary: Create an existential quantifier using a list of constants that - will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using - the quantifier during instantiation. By default, pass the weight 0. - @param num_bound number of constants to be abstracted into bound variables. - @param bound array of constants to be abstracted into bound variables. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_forall_const} - def_API('mk_exists_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) -*) -external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_const" - -(** - Summary: Create a universal or existential - quantifier using a list of constants that - will form the set of bound variables. - def_API('mk_quantifier_const', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, APP), _in(UINT), _in_array(5, PATTERN), _in(AST))) -*) -external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_bytecode" "camlidl_z3_Z3_mk_quantifier_const" - -(** - Summary: Create a universal or existential - quantifier using a list of constants that - will form the set of bound variables. - def_API('mk_quantifier_const_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, APP), _in(UINT), _in_array(7, PATTERN), _in(UINT), _in_array(9, AST), _in(AST))) -*) -external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3_Z3_mk_quantifier_const_ex" - -(** - {2 {L Accessors}} -*) -(** - {3 {L Symbols}} -*) - -(** - Summary: \[ [ symbol_refine c s ] \] is the refined view of [s]. -*) -val symbol_refine: context -> symbol -> symbol_refined - -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Return [INT_SYMBOL] if the symbol was constructed - using {!mk_int_symbol}, and [STRING_SYMBOL] if the symbol - was constructed using {!mk_string_symbol}. - def_API('get_symbol_kind', UINT, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_kind : context -> symbol -> symbol_kind - = "camlidl_z3_Z3_get_symbol_kind" - -(** - Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - - {b Precondition}: get_symbol_kind s == INT_SYMBOL - - {b See also}: {!mk_int_symbol} - def_API('get_symbol_int', INT, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_int : context -> symbol -> int - = "camlidl_z3_Z3_get_symbol_int" - -(** - Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - - {b Precondition}: get_symbol_string s == STRING_SYMBOL - - {b See also}: {!mk_string_symbol} - def_API('get_symbol_string', STRING, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_string : context -> symbol -> string - = "camlidl_z3_Z3_get_symbol_string" - -(** - {3 {L Sorts}} -*) - -(** - Summary: \[ [ sort_refine c s ] \] is the refined view of [s]. -*) -val sort_refine: context -> sort -> sort_refined - -(** - Summary: Return the sort name as a symbol. - def_API('get_sort_name', SYMBOL, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_name : context -> sort -> symbol - = "camlidl_z3_Z3_get_sort_name" - -(** - Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - def_API('get_sort_id', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_id : context -> sort -> int - = "camlidl_z3_Z3_get_sort_id" - -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Convert a [sort] into [ast]. - - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. - def_API('sort_to_ast', AST, (_in(CONTEXT), _in(SORT))) -*) -external sort_to_ast : context -> sort -> ast - = "camlidl_z3_Z3_sort_to_ast" - -(** - Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_sort', BOOL, (_in(CONTEXT), _in(SORT), _in(SORT))) -*) -external is_eq_sort : context -> sort -> sort -> bool - = "camlidl_z3_Z3_is_eq_sort" - -(** - Summary: Return the sort kind (e.g., array, tuple, int, bool, etc). - - {b See also}: {!sort_kind} - def_API('get_sort_kind', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_kind : context -> sort -> sort_kind - = "camlidl_z3_Z3_get_sort_kind" - -(** - Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - - {b Precondition}: get_sort_kind c t == BV_SORT - - {b See also}: {!mk_bv_sort} - - {b See also}: {!get_sort_kind} - def_API('get_bv_sort_size', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_bv_sort_size : context -> sort -> int - = "camlidl_z3_Z3_get_bv_sort_size" - -(** - Summary: Return the size of the sort in [r]. Return [None] if the call failed. - That is, get_sort_kind(s) == FINITE_DOMAIN_SORT - def_API('get_finite_domain_sort_size', BOOL, (_in(CONTEXT), _in(SORT), _out(UINT64))) -*) -external get_finite_domain_sort_size : context -> sort -> int64 option - = "camlidl_z3_Z3_get_finite_domain_sort_size" - -(** - Summary: \[ [ get_array_sort_domain c t ] \] - Return the domain of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - - {b See also}: {!get_sort_kind} - def_API('get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT))) -*) -external get_array_sort_domain : context -> sort -> sort - = "camlidl_z3_Z3_get_array_sort_domain" - -(** - Summary: \[ [ get_array_sort_range c t ] \] - Return the range of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - - {b See also}: {!get_sort_kind} - def_API('get_array_sort_range', SORT, (_in(CONTEXT), _in(SORT))) -*) -external get_array_sort_range : context -> sort -> sort - = "camlidl_z3_Z3_get_array_sort_range" - -(** - Summary: \[ [ get_tuple_sort_mk_decl c t ] \] - Return the constructor declaration of the given tuple - sort. - - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_mk_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT))) -*) -external get_tuple_sort_mk_decl : context -> sort -> func_decl - = "camlidl_z3_Z3_get_tuple_sort_mk_decl" - -(** - Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_num_fields', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_tuple_sort_num_fields : context -> sort -> int - = "camlidl_z3_Z3_get_tuple_sort_num_fields" - -(** - Summary: \[ [ get_tuple_sort_field_decl c t i ] \] - Return the i-th field declaration (i.e., projection function declaration) - of the given tuple sort. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: i < get_tuple_sort_num_fields c t - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_field_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_tuple_sort_field_decl : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_tuple_sort_field_decl" - -(** - Summary: Return number of constructors for datatype. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_num_constructors', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_datatype_sort_num_constructors : context -> sort -> int - = "camlidl_z3_Z3_get_datatype_sort_num_constructors" - -(** - Summary: Return idx'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_constructor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_datatype_sort_constructor : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_constructor" - -(** - Summary: Return idx'th recognizer. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_recognizer', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_datatype_sort_recognizer : context -> sort -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_recognizer" - -(** - Summary: Return idx_a'th accessor for the idx_c'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx_c < get_datatype_sort_num_constructors c t - - {b Precondition}: idx_a < get_domain_size c get_datatype_sort_constructor c idx_c - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - def_API('get_datatype_sort_constructor_accessor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT), _in(UINT))) -*) -external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl - = "camlidl_z3_Z3_get_datatype_sort_constructor_accessor" - -(** - Summary: Return arity of relation. - - {b Precondition}: get_sort_kind s == RELATION_SORT - - {b See also}: {!get_relation_column} - def_API('get_relation_arity', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_relation_arity : context -> sort -> int - = "camlidl_z3_Z3_get_relation_arity" - -(** - Summary: Return sort at i'th column of relation sort. - - {b Precondition}: get_sort_kind c s == RELATION_SORT - - {b Precondition}: col < get_relation_arity c s - - {b See also}: {!get_relation_arity} - def_API('get_relation_column', SORT, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_relation_column : context -> sort -> int -> sort - = "camlidl_z3_Z3_get_relation_column" - -(** - {3 {L Function Declarations}} -*) -(** - Summary: Convert a [func_decl] into [ast]. - - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. - def_API('func_decl_to_ast', AST, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external func_decl_to_ast : context -> func_decl -> ast - = "camlidl_z3_Z3_func_decl_to_ast" - -(** - Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_func_decl', BOOL, (_in(CONTEXT), _in(FUNC_DECL), _in(FUNC_DECL))) -*) -external is_eq_func_decl : context -> func_decl -> func_decl -> bool - = "camlidl_z3_Z3_is_eq_func_decl" - -(** - Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - def_API('get_func_decl_id', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_func_decl_id : context -> func_decl -> int - = "camlidl_z3_Z3_get_func_decl_id" - -(** - Summary: Return the constant declaration name as a symbol. - def_API('get_decl_name', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_name : context -> func_decl -> symbol - = "camlidl_z3_Z3_get_decl_name" - -(** - Summary: Return declaration kind corresponding to declaration. - def_API('get_decl_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_kind : context -> func_decl -> decl_kind - = "camlidl_z3_Z3_get_decl_kind" - -(** - Summary: Return the number of parameters of the given declaration. - - {b See also}: {!get_arity} - def_API('get_domain_size', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_domain_size : context -> func_decl -> int - = "camlidl_z3_Z3_get_domain_size" - -(** - Summary: Alias for [get_domain_size]. - - {b See also}: {!get_domain_size} - def_API('get_arity', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_arity : context -> func_decl -> int - = "camlidl_z3_Z3_get_arity" - -(** - Summary: \[ [ get_domain c d i ] \] - Return the sort of the i-th parameter of the given function declaration. - - {b Precondition}: i < get_domain_size d - - {b See also}: {!get_domain_size} - def_API('get_domain', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_domain : context -> func_decl -> int -> sort - = "camlidl_z3_Z3_get_domain" - - -(** - Summary: \[ [ get_domains c d ] \] is the array of parameters of [d]. - - {b See also}: {!get_domain_size} - - {b See also}: {!get_domain} -*) -val get_domains: context -> func_decl -> sort array - -(** - Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - If [d] is a constant (i.e., has zero arguments), then this - function returns the sort of the constant. - def_API('get_range', SORT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_range : context -> func_decl -> sort - = "camlidl_z3_Z3_get_range" - -(** - Summary: Return the number of parameters associated with a declaration. - def_API('get_decl_num_parameters', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_num_parameters : context -> func_decl -> int - = "camlidl_z3_Z3_get_decl_num_parameters" - -(** - Summary: Return the parameter type associated with a declaration. - @param c the context - @param d the function declaration - @param idx is the index of the named parameter it should be between 0 and the number of parameters. - def_API('get_decl_parameter_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind - = "camlidl_z3_Z3_get_decl_parameter_kind" - -(** - Summary: Return the integer value associated with an integer parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_INT - def_API('get_decl_int_parameter', INT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_int_parameter : context -> func_decl -> int -> int - = "camlidl_z3_Z3_get_decl_int_parameter" - -(** - Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_DOUBLE - def_API('get_decl_double_parameter', DOUBLE, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_double_parameter : context -> func_decl -> int -> float - = "camlidl_z3_Z3_get_decl_double_parameter" - -(** - Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SYMBOL - def_API('get_decl_symbol_parameter', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_symbol_parameter : context -> func_decl -> int -> symbol - = "camlidl_z3_Z3_get_decl_symbol_parameter" - -(** - Summary: Return the sort value associated with a sort parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SORT - def_API('get_decl_sort_parameter', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_sort_parameter : context -> func_decl -> int -> sort - = "camlidl_z3_Z3_get_decl_sort_parameter" - -(** - Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_AST - def_API('get_decl_ast_parameter', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_ast_parameter : context -> func_decl -> int -> ast - = "camlidl_z3_Z3_get_decl_ast_parameter" - -(** - Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_FUNC_DECL - def_API('get_decl_func_decl_parameter', FUNC_DECL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl - = "camlidl_z3_Z3_get_decl_func_decl_parameter" - -(** - Summary: Return the rational value, as a string, associated with a rational parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_RATIONAL - def_API('get_decl_rational_parameter', STRING, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_rational_parameter : context -> func_decl -> int -> string - = "camlidl_z3_Z3_get_decl_rational_parameter" - -(** - {3 {L Applications}} -*) -(** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - def_API('app_to_ast', AST, (_in(CONTEXT), _in(APP))) -*) -external app_to_ast : context -> app -> ast - = "camlidl_z3_Z3_app_to_ast" - -(** - Summary: Return the declaration of a constant or function application. - def_API('get_app_decl', FUNC_DECL, (_in(CONTEXT), _in(APP))) -*) -external get_app_decl : context -> app -> func_decl - = "camlidl_z3_Z3_get_app_decl" - -(** - Summary: \[ [ get_app_num_args c a ] \] - Return the number of argument of an application. If [t] - is an constant, then the number of arguments is 0. - def_API('get_app_num_args', UINT, (_in(CONTEXT), _in(APP))) -*) -external get_app_num_args : context -> app -> int - = "camlidl_z3_Z3_get_app_num_args" - -(** - Summary: \[ [ get_app_arg c a i ] \] - Return the i-th argument of the given application. - - {b Precondition}: i < get_num_args c a - def_API('get_app_arg', AST, (_in(CONTEXT), _in(APP), _in(UINT))) -*) -external get_app_arg : context -> app -> int -> ast - = "camlidl_z3_Z3_get_app_arg" - - -(** - Summary: \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - {b See also}: {!get_app_num_args} - - {b See also}: {!get_app_arg} -*) -val get_app_args: context -> app -> ast array - -(** - {3 {L Terms}} -*) - -(** - Summary: \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} -*) -type binder_type = Forall | Exists -(** - Summary: \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} -*) -type term_refined = - | Term_numeral of numeral_refined - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_var of int * sort - - -(** - Summary: \[ [ mk_term c tr ] \] constructs the term described by [tr]. - - {b Precondition}: [tr] is not of form - - {b See also}: {!term_refine} -*) -(* val mk_term: context -> term_refined -> ast *) -(** - Summary: \[ [ term_refine c a ] \] is the refined view of [a]. -*) -val term_refine : context -> ast -> term_refined - -(** - Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_ast', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external is_eq_ast : context -> ast -> ast -> bool - = "camlidl_z3_Z3_is_eq_ast" - -(** - Summary: Return a unique identifier for [t]. - - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - def_API('get_ast_id', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_id : context -> ast -> int - = "camlidl_z3_Z3_get_ast_id" - -(** - Summary: Return a hash code for the given AST. - - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - def_API('get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_hash : context -> ast -> int - = "camlidl_z3_Z3_get_ast_hash" - -(** - Summary: Return the sort of an AST node. - The AST node must be a constant, application, numeral, bound variable, or quantifier. - def_API('get_sort', SORT, (_in(CONTEXT), _in(AST))) -*) -external get_sort : context -> ast -> sort - = "camlidl_z3_Z3_get_sort" - -(** - Summary: Return true if the given expression [t] is well sorted. - def_API('is_well_sorted', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_well_sorted : context -> ast -> bool - = "camlidl_z3_Z3_is_well_sorted" - -(** - Summary: Return L_TRUE if [a] is true, L_FALSE if it is false, and L_UNDEF otherwise. - def_API('get_bool_value', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_bool_value : context -> ast -> lbool - = "camlidl_z3_Z3_get_bool_value" - -(** - Summary: Return the kind of the given AST. - def_API('get_ast_kind', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_kind : context -> ast -> ast_kind - = "camlidl_z3_Z3_get_ast_kind" - -(** - def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_app : context -> ast -> bool - = "camlidl_z3_Z3_is_app" - -(** - def_API('is_numeral_ast', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_numeral_ast : context -> ast -> bool - = "camlidl_z3_Z3_is_numeral_ast" - -(** - Summary: Return true if the give AST is a real algebraic number. - def_API('is_algebraic_number', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_algebraic_number : context -> ast -> bool - = "camlidl_z3_Z3_is_algebraic_number" - -(** - Summary: Convert an [ast] into an [APP_AST]. - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - def_API('to_app', APP, (_in(CONTEXT), _in(AST))) -*) -external to_app : context -> ast -> app - = "camlidl_z3_Z3_to_app" - -(** - Summary: Convert an AST into a FUNC_DECL_AST. This is just type casting. - - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} - def_API('to_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) -*) -external to_func_decl : context -> ast -> func_decl - = "camlidl_z3_Z3_to_func_decl" - -(** - {4 {L Numerals}} -*) - -(** - Summary: \[ [ numeral_refine c a ] \] is the refined view of [a]. - - {b Precondition}: [get_ast_kind c a = NUMERAL_AST] -*) -val numeral_refine : context -> ast -> numeral_refined - -(** - {5 {L Low-level API}} -*) -(** - Summary: Return numeral value, as a string of a numeric constant term - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numeral_string', STRING, (_in(CONTEXT), _in(AST))) -*) -external get_numeral_string : context -> ast -> string - = "camlidl_z3_Z3_get_numeral_string" - -(** - Summary: Return numeral as a string in decimal notation. - The result has at most [precision] decimal places. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST || is_algebraic_number c a - def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_numeral_decimal_string : context -> ast -> int -> string - = "camlidl_z3_Z3_get_numeral_decimal_string" - -(** - Summary: Return the numerator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numerator', AST, (_in(CONTEXT), _in(AST))) -*) -external get_numerator : context -> ast -> ast - = "camlidl_z3_Z3_get_numerator" - -(** - Summary: Return the denominator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_denominator', AST, (_in(CONTEXT), _in(AST))) -*) -external get_denominator : context -> ast -> ast - = "camlidl_z3_Z3_get_denominator" - -(** - Summary: Return numeral value, as a pair of 64 bit numbers if the representation fits. - @param c logical context. - @param a term. - @param num numerator. - @param den denominator. - Return [TRUE] if the numeral value fits in 64 bit numerals, [FALSE] otherwise. - - {b Precondition}: get_ast_kind a == NUMERAL_AST - def_API('get_numeral_small', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) -*) -external get_numeral_small : context -> ast -> bool * int64 * int64 - = "camlidl_z3_Z3_get_numeral_small" - -(** - Summary: \[ [ get_numeral_int c v ] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit in a machine int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int', BOOL, (_in(CONTEXT), _in(AST), _out(INT))) -*) -external get_numeral_int : context -> ast -> bool * int - = "camlidl_z3_Z3_get_numeral_int" - -(** - Summary: \[ [ get_numeral_int64 c v ] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit in a machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) -*) -external get_numeral_int64 : context -> ast -> bool * int64 - = "camlidl_z3_Z3_get_numeral_int64" - -(** - Summary: \[ [ get_numeral_rational_int64 c x y] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit as a rational number as machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_rational_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) -*) -external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 - = "camlidl_z3_Z3_get_numeral_rational_int64" - -(** - Summary: Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_lower', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_algebraic_number_lower : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_algebraic_number_lower" - -(** - Summary: Return a upper bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_upper', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_algebraic_number_upper : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_algebraic_number_upper" - -(** - {4 {L Patterns}} -*) -(** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - def_API('pattern_to_ast', AST, (_in(CONTEXT), _in(PATTERN))) -*) -external pattern_to_ast : context -> pattern -> ast - = "camlidl_z3_Z3_pattern_to_ast" - - -(** - Summary: \[ [ get_pattern_terms c p ] \] is the ast's in pattern. - - {b See also}: {!get_pattern_num_terms} - - {b See also}: {!get_pattern} -*) -val get_pattern_terms: context -> pattern -> ast array;; - -(** - Summary: Return number of terms in pattern. - def_API('get_pattern_num_terms', UINT, (_in(CONTEXT), _in(PATTERN))) -*) -external get_pattern_num_terms : context -> pattern -> int - = "camlidl_z3_Z3_get_pattern_num_terms" - -(** - Summary: Return i'th ast in pattern. - def_API('get_pattern', AST, (_in(CONTEXT), _in(PATTERN), _in(UINT))) -*) -external get_pattern : context -> pattern -> int -> ast - = "camlidl_z3_Z3_get_pattern" - -(** - {4 {L Quantifiers}} -*) -(** - Summary: Return index of de-Brujin bound variable. - - {b Precondition}: get_ast_kind a == VAR_AST - def_API('get_index_value', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_index_value : context -> ast -> int - = "camlidl_z3_Z3_get_index_value" - -(** - Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_quantifier_forall : context -> ast -> bool - = "camlidl_z3_Z3_is_quantifier_forall" - -(** - Summary: Obtain weight of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_weight : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_weight" - -(** - Summary: Return number of patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_patterns', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_patterns : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_patterns" - -(** - Summary: Return i'th pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_pattern_ast', PATTERN, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_pattern_ast : context -> ast -> int -> pattern - = "camlidl_z3_Z3_get_quantifier_pattern_ast" - -(** - Summary: Return number of no_patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_no_patterns', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_no_patterns : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_no_patterns" - -(** - Summary: Return i'th no_pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_no_pattern_ast', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_no_pattern_ast : context -> ast -> int -> ast - = "camlidl_z3_Z3_get_quantifier_no_pattern_ast" - -(** - Summary: Return number of bound variables of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_bound', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_bound : context -> ast -> int - = "camlidl_z3_Z3_get_quantifier_num_bound" - -(** - Summary: Return symbol of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_name', SYMBOL, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_bound_name : context -> ast -> int -> symbol - = "camlidl_z3_Z3_get_quantifier_bound_name" - -(** - Summary: Return sort of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_sort', SORT, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_bound_sort : context -> ast -> int -> sort - = "camlidl_z3_Z3_get_quantifier_bound_sort" - -(** - Summary: Return body of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_body', AST, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_body : context -> ast -> ast - = "camlidl_z3_Z3_get_quantifier_body" - -(** - {3 {L Simplification}} -*) -(** - Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - def_API('simplify', AST, (_in(CONTEXT), _in(AST))) -*) -external simplify : context -> ast -> ast - = "camlidl_z3_Z3_simplify" - -(** - Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - This procedure is similar to {!simplify}, but the behavior of the simplifier - can be configured using the given parameter set. - def_API('simplify_ex', AST, (_in(CONTEXT), _in(AST), _in(PARAMS))) -*) -external simplify_ex : context -> ast -> params -> ast - = "camlidl_z3_Z3_simplify_ex" - -(** - Summary: Return a string describing all available parameters. - def_API('simplify_get_help', STRING, (_in(CONTEXT),)) -*) -external simplify_get_help : context -> string - = "camlidl_z3_Z3_simplify_get_help" - -(** - Summary: Return the parameter description set for the simplify procedure. - def_API('simplify_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT),)) -*) -external simplify_get_param_descrs : context -> param_descrs - = "camlidl_z3_Z3_simplify_get_param_descrs" - -(** - {2 {L Modifiers}} -*) -(** - Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide - with the number of arguments to [a]. - If [a] is a quantifier, then num_args has to be 1. - def_API('update_term', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) -*) -external update_term : context -> ast -> ast array -> ast - = "camlidl_z3_Z3_update_term" - -(** - Summary: Substitute every occurrence of {e from[i] } in [a] with {e to[i] }, for [i] smaller than [num_exprs]. - The result is the new AST. The arrays [from] and [to] must have size [num_exprs]. - For every [i] smaller than [num_exprs], we must have that sort of {e from[i] } must be equal to sort of {e to[i] }. - def_API('substitute', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in_array(2, AST))) -*) -external substitute : context -> ast -> ast array -> ast array -> ast - = "camlidl_z3_Z3_substitute" - -(** - Summary: Substitute the free variables in [a] with the expressions in [to]. - For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term {e to[i] }. - def_API('substitute_vars', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) -*) -external substitute_vars : context -> ast -> ast array -> ast - = "camlidl_z3_Z3_substitute_vars" - -(** - Summary: Translate/Copy the AST [a] from context [source] to context [target]. - AST [a] must have been created using context [source]. - - {b Precondition}: source != target - def_API('translate', AST, (_in(CONTEXT), _in(AST), _in(CONTEXT))) -*) -external translate : context -> ast -> context -> ast - = "camlidl_z3_Z3_translate" - -(** - {2 {L Models}} -*) - -(** - A model assigns uninterpreted sorts to finite universes of distinct values, constants to values, - and arrays and functions to finite maps from argument values to result values plus a default - value for all other arguments. -*) -type model_refined = { - sorts : (sort, ast_vector) Hashtbl.t; - consts : (func_decl, ast) Hashtbl.t; - arrays : (func_decl, (ast, ast) Hashtbl.t * ast) Hashtbl.t; - funcs : (func_decl, (ast array, ast) Hashtbl.t * ast) Hashtbl.t; -} - - -(** - Summary: [model_refine c m] is the refined model of [m]. -*) -val model_refine : context -> model -> model_refined - -(** - Summary: \[ [ model_eval c m t ] \] - Evaluate the AST node [t] in the given model. - Return [None] if the term was not successfully evaluated. - If [model_completion] is TRUE, then Z3 will assign an interpretation for any constant or function that does - not have an interpretation in [m]. These constants and functions were essentially don't cares. - The evaluation may fail for the following reasons: - - [t] contains a quantifier. - - the model [m] is partial, that is, it doesn't have a complete interpretation for uninterpreted functions. - That is, the option {e MODEL_PARTIAL=true } was used. - - [t] is type incorrect. - def_API('model_eval', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _in(BOOL), _out(AST))) -*) -external model_eval : context -> model -> ast -> bool -> ast option - = "camlidl_z3_Z3_model_eval" - -(** - {4 {L Low-level API}} -*) -(** - Summary: Return the interpretation (i.e., assignment) of constant [a] in the model [m]. - Return [None], - if the model does not assign an interpretation for [a]. - That should be interpreted as: the value of [a] does not matter. - - {b Precondition}: get_arity c a == 0 - def_API('model_get_const_interp', AST, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL))) -*) -external model_get_const_interp : context -> model -> func_decl -> ast option - = "camlidl_z3_Z3_model_get_const_interp" - -(** - Summary: Return the interpretation of the function [f] in the model [m]. - Return [None], - if the model does not assign an interpretation for [f]. - That should be interpreted as: the [f] does not matter. - - {b Precondition}: get_arity c f > 0 - def_API('model_get_func_interp', FUNC_INTERP, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL))) -*) -external model_get_func_interp : context -> model -> func_decl -> func_interp option - = "camlidl_z3_Z3_model_get_func_interp" - -(** - Summary: Return the number of constants assigned by the given model. - - {b See also}: {!model_get_const_decl} - def_API('model_get_num_consts', UINT, (_in(CONTEXT), _in(MODEL))) -*) -external model_get_num_consts : context -> model -> int - = "camlidl_z3_Z3_model_get_num_consts" - -(** - Summary: \[ [ model_get_const_decl c m i ] \] - Return the i-th constant in the given model. - - {b Precondition}: i < model_get_num_consts c m - - {b See also}: {!model_eval} - def_API('model_get_const_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external model_get_const_decl : context -> model -> int -> func_decl - = "camlidl_z3_Z3_model_get_const_decl" - -(** - Summary: Return the number of function interpretations in the given model. - A function interpretation is represented as a finite map and an 'else' value. - Each entry in the finite map represents the value of a function given a set of arguments. - def_API('model_get_num_funcs', UINT, (_in(CONTEXT), _in(MODEL))) -*) -external model_get_num_funcs : context -> model -> int - = "camlidl_z3_Z3_model_get_num_funcs" - -(** - Summary: \[ [ model_get_func_decl c m i ] \] - Return the declaration of the i-th function in the given model. - - {b Precondition}: i < model_get_num_funcs c m - - {b See also}: {!model_get_num_funcs} - def_API('model_get_func_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external model_get_func_decl : context -> model -> int -> func_decl - = "camlidl_z3_Z3_model_get_func_decl" - -(** - Summary: Return the number of uninterpreted sorts that [m] assigs an interpretation to. - Z3 also provides an intepretation for uninterpreted sorts used in a formua. - The interpretation for a sort [s] is a finite set of distinct values. We say this finite set is - the "universe" of [s]. - - {b See also}: {!model_get_sort} - - {b See also}: {!model_get_sort_universe} - def_API('model_get_num_sorts', UINT, (_in(CONTEXT), _in(MODEL))) -*) -external model_get_num_sorts : context -> model -> int - = "camlidl_z3_Z3_model_get_num_sorts" - -(** - Summary: Return a uninterpreted sort that [m] assigns an interpretation. - - {b Precondition}: i < model_get_num_sorts c m - - {b See also}: {!model_get_num_sorts} - - {b See also}: {!model_get_sort_universe} - def_API('model_get_sort', SORT, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external model_get_sort : context -> model -> int -> sort - = "camlidl_z3_Z3_model_get_sort" - -(** - Summary: Return the finite set of distinct values that represent the interpretation for sort [s]. - - {b See also}: {!model_get_num_sorts} - - {b See also}: {!model_get_sort} - def_API('model_get_sort_universe', AST_VECTOR, (_in(CONTEXT), _in(MODEL), _in(SORT))) -*) -external model_get_sort_universe : context -> model -> sort -> ast_vector - = "camlidl_z3_Z3_model_get_sort_universe" - -(** - Summary: The {e (_ as-array f) } AST node is a construct for assigning interpretations for arrays in Z3. - It is the array such that forall indices [i] we have that {e (select (_ as-array f) i) } is equal to {e (f i) }. - This procedure returns TRUE if the [a] is an [as-array] AST node. - Z3 current solvers have minimal support for [as_array] nodes. - - {b See also}: {!get_as_array_func_decl} - def_API('is_as_array', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_as_array : context -> ast -> bool - = "camlidl_z3_Z3_is_as_array" - -(** - Summary: Return the function declaration [f] associated with a {e (_ as_array f) } node. - - {b See also}: {!is_as_array} - def_API('get_as_array_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) -*) -external get_as_array_func_decl : context -> ast -> func_decl - = "camlidl_z3_Z3_get_as_array_func_decl" - -(** - Summary: Return the number of entries in the given function interpretation. - A function interpretation is represented as a finite map and an 'else' value. - Each entry in the finite map represents the value of a function given a set of arguments. - This procedure return the number of element in the finite map of [f]. - def_API('func_interp_get_num_entries', UINT, (_in(CONTEXT), _in(FUNC_INTERP))) -*) -external func_interp_get_num_entries : context -> func_interp -> int - = "camlidl_z3_Z3_func_interp_get_num_entries" - -(** - Summary: Return a "point" of the given function intepretation. It represents the - value of [f] in a particular point. - - {b Precondition}: i < func_interp_get_num_entries c f - - {b See also}: {!func_interp_get_num_entries} - def_API('func_interp_get_entry', FUNC_ENTRY, (_in(CONTEXT), _in(FUNC_INTERP), _in(UINT))) -*) -external func_interp_get_entry : context -> func_interp -> int -> func_entry - = "camlidl_z3_Z3_func_interp_get_entry" - -(** - Summary: Return the 'else' value of the given function interpretation. - A function interpretation is represented as a finite map and an 'else' value. - This procedure returns the 'else' value. - def_API('func_interp_get_else', AST, (_in(CONTEXT), _in(FUNC_INTERP))) -*) -external func_interp_get_else : context -> func_interp -> ast - = "camlidl_z3_Z3_func_interp_get_else" - -(** - Summary: Return the arity (number of arguments) of the given function interpretation. - def_API('func_interp_get_arity', UINT, (_in(CONTEXT), _in(FUNC_INTERP))) -*) -external func_interp_get_arity : context -> func_interp -> int - = "camlidl_z3_Z3_func_interp_get_arity" - -(** - Summary: Return the value of this point. - A func_entry object represents an element in the finite map used to encode - a function interpretation. - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_value', AST, (_in(CONTEXT), _in(FUNC_ENTRY))) -*) -external func_entry_get_value : context -> func_entry -> ast - = "camlidl_z3_Z3_func_entry_get_value" - -(** - Summary: Return the number of arguments in a func_entry object. - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_num_args', UINT, (_in(CONTEXT), _in(FUNC_ENTRY))) -*) -external func_entry_get_num_args : context -> func_entry -> int - = "camlidl_z3_Z3_func_entry_get_num_args" - -(** - Summary: Return an argument of a func_entry object. - - {b Precondition}: i < func_entry_get_num_args c e - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_arg', AST, (_in(CONTEXT), _in(FUNC_ENTRY), _in(UINT))) -*) -external func_entry_get_arg : context -> func_entry -> int -> ast - = "camlidl_z3_Z3_func_entry_get_arg" - -(** - {2 {L Interaction logging.}} -*) -(** - Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) -*) -external open_log : string -> bool - = "camlidl_z3_Z3_open_log" - -(** - Summary: Append user-defined string to interaction log. - The interaction log is opened using open_log. - It contains the formulas that are checked using Z3. - You can use this command to append comments, for instance. - extra_API('append_log', VOID, (_in(STRING),)) -*) -external append_log : string -> unit - = "camlidl_z3_Z3_append_log" - -(** - Summary: Close interaction log. - extra_API('close_log', VOID, ()) -*) -external close_log : unit -> unit - = "camlidl_z3_Z3_close_log" - -(** - Summary: Enable/disable printing warning messages to the console. - Warnings are printed after passing [true], warning messages are - suppressed after calling this method with [false]. - def_API('toggle_warning_messages', VOID, (_in(BOOL),)) -*) -external toggle_warning_messages : bool -> unit - = "camlidl_z3_Z3_toggle_warning_messages" - -(** - {2 {L String conversion}} -*) -(** - Summary: Select mode for the format used for pretty-printing AST nodes. - The default mode for pretty printing AST nodes is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - {b See also}: {!ast_to_string} - - {b See also}: {!pattern_to_string} - - {b See also}: {!func_decl_to_string} - def_API('set_ast_print_mode', VOID, (_in(CONTEXT), _in(PRINT_MODE))) -*) -external set_ast_print_mode : context -> ast_print_mode -> unit - = "camlidl_z3_Z3_set_ast_print_mode" - -(** - Summary: Convert the given AST node into a string. - - {b See also}: {!pattern_to_string} - - {b See also}: {!sort_to_string} - def_API('ast_to_string', STRING, (_in(CONTEXT), _in(AST))) -*) -external ast_to_string : context -> ast -> string - = "camlidl_z3_Z3_ast_to_string" - -(** - def_API('pattern_to_string', STRING, (_in(CONTEXT), _in(PATTERN))) -*) -external pattern_to_string : context -> pattern -> string - = "camlidl_z3_Z3_pattern_to_string" - -(** - def_API('sort_to_string', STRING, (_in(CONTEXT), _in(SORT))) -*) -external sort_to_string : context -> sort -> string - = "camlidl_z3_Z3_sort_to_string" - -(** - def_API('func_decl_to_string', STRING, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external func_decl_to_string : context -> func_decl -> string - = "camlidl_z3_Z3_func_decl_to_string" - -(** - Summary: Convert the given model into a string. - def_API('model_to_string', STRING, (_in(CONTEXT), _in(MODEL))) -*) -external model_to_string : context -> model -> string - = "camlidl_z3_Z3_model_to_string" - -(** - Summary: Convert the given benchmark into SMT-LIB formatted string. - @param c - context. - @param name - name of benchmark. The argument is optional. - @param logic - the benchmark logic. - @param status - the status string (sat, unsat, or unknown) - @param attributes - other attributes, such as source, difficulty or category. - @param num_assumptions - number of assumptions. - @param assumptions - auxiliary assumptions. - @param formula - formula to be checked for consistency in conjunction with assumptions. - def_API('benchmark_to_smtlib_string', STRING, (_in(CONTEXT), _in(STRING), _in(STRING), _in(STRING), _in(STRING), _in(UINT), _in_array(5, AST), _in(AST))) -*) -external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3_Z3_benchmark_to_smtlib_string" - -(** - {2 {L Parser interface}} -*) -(** - Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - It returns a formula comprising of the conjunction of assertions in the scope - (up to push/pop) at the end of the string. - def_API('parse_smtlib2_string', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3_Z3_parse_smtlib2_string" - -(** - Summary: Similar to {!parse_smtlib2_string}, but reads the benchmark from a file. - def_API('parse_smtlib2_file', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3_Z3_parse_smtlib2_file" - - -(** - Summary: \[ [ parse_smtlib_string_x c str sort_names sorts decl_names decls ] \] - Parse the given string using the SMT-LIB parser. - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays [sort_names] and [decl_names] don't need to match the names - of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature - since we can use arbitrary names to reference sorts and declarations defined using the API. - - {b See also}: {!parse_smtlib_file_x} -*) -val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) -(** - Summary: Similar to {!parse_smtlib_string_x}, but reads the benchmark from a file. - - {b See also}: {!parse_smtlib_string_x} -*) -val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) -(** - Summary: \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - - {b See also}: {!parse_smtlib_file_formula} - - {b See also}: {!parse_smtlib_string_x} -*) -val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast -(** - Summary: \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - - {b See also}: {!parse_smtlib_string_formula} - - {b See also}: {!parse_smtlib_file_x} -*) -val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - -(** - {4 {L Low-level API}} -*) -(** - Summary: \[ [ parse_smtlib_string c str sort_names sorts decl_names decls ] \] - Parse the given string using the SMT-LIB parser. - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays [sort_names] and [decl_names] don't need to match the names - of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature - since we can use arbitrary names to reference sorts and declarations defined using the C API. - The formulas, assumptions and declarations defined in [str] can be extracted using the functions: - {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, - {!get_smtlib_num_decls}, and {!get_smtlib_decl}. - def_API('parse_smtlib_string', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_string_bytecode" "camlidl_z3_Z3_parse_smtlib_string" - -(** - Summary: Similar to {!parse_smtlib_string}, but reads the benchmark from a file. - def_API('parse_smtlib_file', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_file_bytecode" "camlidl_z3_Z3_parse_smtlib_file" - -(** - Summary: Return the number of SMTLIB formulas parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_formulas', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_formulas : context -> int - = "camlidl_z3_Z3_get_smtlib_num_formulas" - -(** - Summary: \[ [ get_smtlib_formula c i ] \] - Return the i-th formula parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_formulas c - def_API('get_smtlib_formula', AST, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_formula : context -> int -> ast - = "camlidl_z3_Z3_get_smtlib_formula" - -(** - Summary: Return the number of SMTLIB assumptions parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_assumptions', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_assumptions : context -> int - = "camlidl_z3_Z3_get_smtlib_num_assumptions" - -(** - Summary: \[ [ get_smtlib_assumption c i ] \] - Return the i-th assumption parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_assumptions c - def_API('get_smtlib_assumption', AST, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_assumption : context -> int -> ast - = "camlidl_z3_Z3_get_smtlib_assumption" - -(** - Summary: Return the number of declarations parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_decls', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_decls : context -> int - = "camlidl_z3_Z3_get_smtlib_num_decls" - -(** - Summary: \[ [ get_smtlib_decl c i ] \] - Return the i-th declaration parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_decls c - def_API('get_smtlib_decl', FUNC_DECL, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_decl : context -> int -> func_decl - = "camlidl_z3_Z3_get_smtlib_decl" - -(** - Summary: Return the number of sorts parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_sorts', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_sorts : context -> int - = "camlidl_z3_Z3_get_smtlib_num_sorts" - -(** - Summary: \[ [ get_smtlib_sort c i ] \] - Return the i-th sort parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_sorts c - def_API('get_smtlib_sort', SORT, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_sort : context -> int -> sort - = "camlidl_z3_Z3_get_smtlib_sort" - -(* -(** - Summary: \[ [ get_smtlib_error c ] \] - Retrieve that last error message information generated from parsing. - def_API('get_smtlib_error', STRING, (_in(CONTEXT), )) -*) -external get_smtlib_error : context -> string - = "camlidl_z3_Z3_get_smtlib_error" - -*) -(** - {2 {L Error Handling}} -*) -(** - Summary: Set an error. - def_API('set_error', VOID, (_in(CONTEXT), _in(ERROR_CODE))) -*) -external set_error : context -> error_code -> unit - = "camlidl_z3_Z3_set_error" - -(* -(** - Summary: Return a string describing the given error code. - def_API('get_error_msg_ex', STRING, (_in(CONTEXT), _in(ERROR_CODE))) -*) -external get_error_msg_ex : context -> error_code -> string - = "camlidl_z3_Z3_get_error_msg_ex" - -*) - -(** - Summary: Return a string describing the given error code. -*) -val get_error_msg: context -> error_code -> string - -(** - {2 {L Miscellaneous}} -*) -(** - Summary: Return Z3 version number information. - def_API('get_version', VOID, (_out(UINT), _out(UINT), _out(UINT), _out(UINT))) -*) -external get_version : unit -> int * int * int * int - = "camlidl_z3_Z3_get_version" - -(** - Summary: Enable tracing messages tagged as [tag] when Z3 is compiled in debug mode. - It is a NOOP otherwise - def_API('enable_trace', VOID, (_in(STRING),)) -*) -external enable_trace : string -> unit - = "camlidl_z3_Z3_enable_trace" - -(** - Summary: Disable tracing messages tagged as [tag] when Z3 is compiled in debug mode. - It is a NOOP otherwise - def_API('disable_trace', VOID, (_in(STRING),)) -*) -external disable_trace : string -> unit - = "camlidl_z3_Z3_disable_trace" - -(** - {2 {L Fixedpoint facilities}} -*) -(** - Summary: Create a new fixedpoint context. - def_API('mk_fixedpoint', FIXEDPOINT, (_in(CONTEXT), )) -*) -external mk_fixedpoint : context -> fixedpoint - = "camlidl_z3_Z3_mk_fixedpoint" - -(** - Summary: Add a universal Horn clause as a named rule. - The [horn_rule] should be of the form: - {v - horn_rule ::= (forall (bound-vars) horn_rule) - | (=> atoms horn_rule) - | atom - v} - def_API('fixedpoint_add_rule', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST), _in(SYMBOL))) -*) -external fixedpoint_add_rule : context -> fixedpoint -> ast -> symbol -> unit - = "camlidl_z3_Z3_fixedpoint_add_rule" - -(** - Summary: Add a Database fact. - @param c - context - @param d - fixed point context - @param r - relation signature for the row. - @param num_args - number of columns for the given row. - @param args - array of the row elements. - The number of arguments [num_args] should be equal to the number - of sorts in the domain of [r]. Each sort in the domain should be an integral - (bit-vector, Boolean or or finite domain sort). - The call has the same effect as adding a rule where [r] is applied to the arguments. - def_API('fixedpoint_add_fact', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL), _in(UINT), _in_array(3, UINT))) -*) -external fixedpoint_add_fact : context -> fixedpoint -> func_decl -> int array -> unit - = "camlidl_z3_Z3_fixedpoint_add_fact" - -(** - Summary: Assert a constraint to the fixedpoint context. - The constraints are used as background axioms when the fixedpoint engine uses the PDR mode. - They are ignored for standard Datalog mode. - def_API('fixedpoint_assert', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST))) -*) -external fixedpoint_assert : context -> fixedpoint -> ast -> unit - = "camlidl_z3_Z3_fixedpoint_assert" - -(** - Summary: Pose a query against the asserted rules. - {v - query ::= (exists (bound-vars) query) - | literals - v} - query returns - - L_FALSE if the query is unsatisfiable. - - L_TRUE if the query is satisfiable. Obtain the answer by calling {!fixedpoint_get_answer}. - - L_UNDEF if the query was interrupted, timed out or otherwise failed. - def_API('fixedpoint_query', INT, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST))) -*) -external fixedpoint_query : context -> fixedpoint -> ast -> lbool - = "camlidl_z3_Z3_fixedpoint_query" - -(** - Summary: Pose multiple queries against the asserted rules. - The queries are encoded as relations (function declarations). - query returns - - L_FALSE if the query is unsatisfiable. - - L_TRUE if the query is satisfiable. Obtain the answer by calling {!fixedpoint_get_answer}. - - L_UNDEF if the query was interrupted, timed out or otherwise failed. - def_API('fixedpoint_query_relations', INT, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2, FUNC_DECL))) -*) -external fixedpoint_query_relations : context -> fixedpoint -> func_decl array -> lbool - = "camlidl_z3_Z3_fixedpoint_query_relations" - -(** - Summary: Retrieve a formula that encodes satisfying answers to the query. - When used in Datalog mode, the returned answer is a disjunction of conjuncts. - Each conjunct encodes values of the bound variables of the query that are satisfied. - In PDR mode, the returned answer is a single conjunction. - The previous call to fixedpoint_query must have returned L_TRUE. - def_API('fixedpoint_get_answer', AST, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_get_answer : context -> fixedpoint -> ast - = "camlidl_z3_Z3_fixedpoint_get_answer" - -(** - Summary: Retrieve a string that describes the last status returned by {!fixedpoint_query}. - Use this method when {!fixedpoint_query} returns L_UNDEF. - def_API('fixedpoint_get_reason_unknown', STRING, (_in(CONTEXT), _in(FIXEDPOINT) )) -*) -external fixedpoint_get_reason_unknown : context -> fixedpoint -> string - = "camlidl_z3_Z3_fixedpoint_get_reason_unknown" - -(** - Summary: Update a named rule. - A rule with the same name must have been previously created. - def_API('fixedpoint_update_rule', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST), _in(SYMBOL))) -*) -external fixedpoint_update_rule : context -> fixedpoint -> ast -> symbol -> unit - = "camlidl_z3_Z3_fixedpoint_update_rule" - -(** - Summary: Query the PDR engine for the maximal levels properties are known about predicate. - This call retrieves the maximal number of relevant unfoldings - of [pred] with respect to the current exploration state. - Note: this functionality is PDR specific. - def_API('fixedpoint_get_num_levels', UINT, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL))) -*) -external fixedpoint_get_num_levels : context -> fixedpoint -> func_decl -> int - = "camlidl_z3_Z3_fixedpoint_get_num_levels" - -(** - Retrieve the current cover of [pred] up to [level] unfoldings. - Return just the delta that is known at [level]. To - obtain the full set of properties of [pred] one should query - at [level+1] , [level+2] etc, and include [level=-1]. - Note: this functionality is PDR specific. - def_API('fixedpoint_get_cover_delta', AST, (_in(CONTEXT), _in(FIXEDPOINT), _in(INT), _in(FUNC_DECL))) -*) -external fixedpoint_get_cover_delta : context -> fixedpoint -> int -> func_decl -> ast - = "camlidl_z3_Z3_fixedpoint_get_cover_delta" - -(** - Summary: Add property about the predicate [pred]. - Add a property of predicate [pred] at [level]. - It gets pushed forward when possible. - Note: level = -1 is treated as the fixedpoint. So passing -1 for the [level] - means that the property is true of the fixed-point unfolding with respect to [pred]. - Note: this functionality is PDR specific. - def_API('fixedpoint_add_cover', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(INT), _in(FUNC_DECL), _in(AST))) -*) -external fixedpoint_add_cover : context -> fixedpoint -> int -> func_decl -> ast -> unit - = "camlidl_z3_Z3_fixedpoint_add_cover" - -(** - Summary: Retrieve statistics information from the last call to {!fixedpoint_query}. - def_API('fixedpoint_get_statistics', STATS, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_get_statistics : context -> fixedpoint -> stats - = "camlidl_z3_Z3_fixedpoint_get_statistics" - -(** - Summary: Register relation as Fixedpoint defined. - Fixedpoint defined relations have least-fixedpoint semantics. - For example, the relation is empty if it does not occur - in a head or a fact. - def_API('fixedpoint_register_relation', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL))) -*) -external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> unit - = "camlidl_z3_Z3_fixedpoint_register_relation" - -(** - Summary: Configure the predicate representation. - It sets the predicate to use a set of domains given by the list of symbols. - The domains given by the list of symbols must belong to a set - of built-in domains. - def_API('fixedpoint_set_predicate_representation', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL), _in(UINT), _in_array(3, SYMBOL))) -*) -external fixedpoint_set_predicate_representation : context -> fixedpoint -> func_decl -> symbol array -> unit - = "camlidl_z3_Z3_fixedpoint_set_predicate_representation" - -(** - Summary: Retrieve set of rules from fixedpoint context. - def_API('fixedpoint_get_rules', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT))) -*) -external fixedpoint_get_rules : context -> fixedpoint -> ast_vector - = "camlidl_z3_Z3_fixedpoint_get_rules" - -(** - Summary: Retrieve set of background assertions from fixedpoint context. - def_API('fixedpoint_get_assertions', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT))) -*) -external fixedpoint_get_assertions : context -> fixedpoint -> ast_vector - = "camlidl_z3_Z3_fixedpoint_get_assertions" - -(** - Summary: Set parameters on fixedpoint context. - def_API('fixedpoint_set_params', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(PARAMS))) -*) -external fixedpoint_set_params : context -> fixedpoint -> params -> unit - = "camlidl_z3_Z3_fixedpoint_set_params" - -(** - Summary: Return a string describing all fixedpoint available parameters. - def_API('fixedpoint_get_help', STRING, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_get_help : context -> fixedpoint -> string - = "camlidl_z3_Z3_fixedpoint_get_help" - -(** - Summary: Return the parameter description set for the given fixedpoint object. - def_API('fixedpoint_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs - = "camlidl_z3_Z3_fixedpoint_get_param_descrs" - -(** - Summary: Print the current rules and background axioms as a string. - @param c - context. - @param f - fixedpoint context. - @param num_queries - number of additional queries to print. - @param queries - additional queries. - def_API('fixedpoint_to_string', STRING, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2, AST))) -*) -external fixedpoint_to_string : context -> fixedpoint -> ast array -> string - = "camlidl_z3_Z3_fixedpoint_to_string" - -(** - Summary: Parse an SMT-LIB2 string with fixedpoint rules. - Add the rules to the current fixedpoint context. - Return the set of queries in the file. - @param c - context. - @param f - fixedpoint context. - @param s - string containing SMT2 specification. - def_API('fixedpoint_from_string', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(STRING))) -*) -external fixedpoint_from_string : context -> fixedpoint -> string -> ast_vector - = "camlidl_z3_Z3_fixedpoint_from_string" - -(** - Summary: Parse an SMT-LIB2 file with fixedpoint rules. - Add the rules to the current fixedpoint context. - Return the set of queries in the file. - @param c - context. - @param f - fixedpoint context. - @param s - string containing SMT2 specification. - def_API('fixedpoint_from_file', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(STRING))) -*) -external fixedpoint_from_file : context -> fixedpoint -> string -> ast_vector - = "camlidl_z3_Z3_fixedpoint_from_file" - -(** - Summary: Create a backtracking point. - The fixedpoint solver contains a set of rules, added facts and assertions. - The set of rules, facts and assertions are restored upon calling {!fixedpoint_pop}. - - {b See also}: {!fixedpoint_pop} - def_API('fixedpoint_push', VOID, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_push : context -> fixedpoint -> unit - = "camlidl_z3_Z3_fixedpoint_push" - -(** - Summary: Backtrack one backtracking point. - - {b See also}: {!fixedpoint_push} - - {b Precondition}: The number of calls to pop cannot exceed calls to push. - def_API('fixedpoint_pop', VOID, (_in(CONTEXT), _in(FIXEDPOINT))) -*) -external fixedpoint_pop : context -> fixedpoint -> unit - = "camlidl_z3_Z3_fixedpoint_pop" - -(** - {2 {L AST vectors}} -*) -(** - Summary: Return an empty AST vector. - def_API('mk_ast_vector', AST_VECTOR, (_in(CONTEXT),)) -*) -external mk_ast_vector : context -> ast_vector - = "camlidl_z3_Z3_mk_ast_vector" - -(** - Summary: Return the size of the given AST vector. - def_API('ast_vector_size', UINT, (_in(CONTEXT), _in(AST_VECTOR))) -*) -external ast_vector_size : context -> ast_vector -> int - = "camlidl_z3_Z3_ast_vector_size" - -(** - Summary: Return the AST at position [i] in the AST vector [v]. - - {b Precondition}: i < ast_vector_size c v - def_API('ast_vector_get', AST, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT))) -*) -external ast_vector_get : context -> ast_vector -> int -> ast - = "camlidl_z3_Z3_ast_vector_get" - -(** - Summary: Update position [i] of the AST vector [v] with the AST [a]. - - {b Precondition}: i < ast_vector_size c v - def_API('ast_vector_set', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT), _in(AST))) -*) -external ast_vector_set : context -> ast_vector -> int -> ast -> unit - = "camlidl_z3_Z3_ast_vector_set" - -(** - Summary: Resize the AST vector [v]. - def_API('ast_vector_resize', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT))) -*) -external ast_vector_resize : context -> ast_vector -> int -> unit - = "camlidl_z3_Z3_ast_vector_resize" - -(** - Summary: Add the AST [a] in the end of the AST vector [v]. The size of [v] is increased by one. - def_API('ast_vector_push', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(AST))) -*) -external ast_vector_push : context -> ast_vector -> ast -> unit - = "camlidl_z3_Z3_ast_vector_push" - -(** - Summary: Translate the AST vector [v] from context [s] into an AST vector in context [t]. - def_API('ast_vector_translate', AST_VECTOR, (_in(CONTEXT), _in(AST_VECTOR), _in(CONTEXT))) -*) -external ast_vector_translate : context -> ast_vector -> context -> ast_vector - = "camlidl_z3_Z3_ast_vector_translate" - -(** - Summary: Convert AST vector into a string. - def_API('ast_vector_to_string', STRING, (_in(CONTEXT), _in(AST_VECTOR))) -*) -external ast_vector_to_string : context -> ast_vector -> string - = "camlidl_z3_Z3_ast_vector_to_string" - -(** - {2 {L AST maps}} -*) -(** - Summary: Return an empty mapping from AST to AST - def_API('mk_ast_map', AST_MAP, (_in(CONTEXT),) ) -*) -external mk_ast_map : context -> ast_map - = "camlidl_z3_Z3_mk_ast_map" - -(** - Summary: Return true if the map [m] contains the AST key [k]. - def_API('ast_map_contains', BOOL, (_in(CONTEXT), _in(AST_MAP), _in(AST))) -*) -external ast_map_contains : context -> ast_map -> ast -> bool - = "camlidl_z3_Z3_ast_map_contains" - -(** - Summary: Return the value associated with the key [k]. - The procedure invokes the error handler if [k] is not in the map. - def_API('ast_map_find', AST, (_in(CONTEXT), _in(AST_MAP), _in(AST))) -*) -external ast_map_find : context -> ast_map -> ast -> ast - = "camlidl_z3_Z3_ast_map_find" - -(** - Summary: Store/Replace a new key, value pair in the given map. - def_API('ast_map_insert', VOID, (_in(CONTEXT), _in(AST_MAP), _in(AST), _in(AST))) -*) -external ast_map_insert : context -> ast_map -> ast -> ast -> unit - = "camlidl_z3_Z3_ast_map_insert" - -(** - Summary: Erase a key from the map. - def_API('ast_map_erase', VOID, (_in(CONTEXT), _in(AST_MAP), _in(AST))) -*) -external ast_map_erase : context -> ast_map -> ast -> unit - = "camlidl_z3_Z3_ast_map_erase" - -(** - Summary: Remove all keys from the given map. - def_API('ast_map_reset', VOID, (_in(CONTEXT), _in(AST_MAP))) -*) -external ast_map_reset : context -> ast_map -> unit - = "camlidl_z3_Z3_ast_map_reset" - -(** - Summary: Return the size of the given map. - def_API('ast_map_size', UINT, (_in(CONTEXT), _in(AST_MAP))) -*) -external ast_map_size : context -> ast_map -> int - = "camlidl_z3_Z3_ast_map_size" - -(** - Summary: Return the keys stored in the given map. - def_API('ast_map_keys', AST_VECTOR, (_in(CONTEXT), _in(AST_MAP))) -*) -external ast_map_keys : context -> ast_map -> ast_vector - = "camlidl_z3_Z3_ast_map_keys" - -(** - Summary: Convert the given map into a string. - def_API('ast_map_to_string', STRING, (_in(CONTEXT), _in(AST_MAP))) -*) -external ast_map_to_string : context -> ast_map -> string - = "camlidl_z3_Z3_ast_map_to_string" - -(** - {2 {L Goals}} -*) -(** - Summary: Create a goal (aka problem). A goal is essentially a set - of formulas, that can be solved and/or transformed using - tactics and solvers. - If models == true, then model generation is enabled for the new goal. - If unsat_cores == true, then unsat core generation is enabled for the new goal. - If proofs == true, then proof generation is enabled for the new goal. Remark, the - Z3 context c must have been created with proof generation support. - def_API('mk_goal', GOAL, (_in(CONTEXT), _in(BOOL), _in(BOOL), _in(BOOL))) -*) -external mk_goal : context -> bool -> bool -> bool -> goal - = "camlidl_z3_Z3_mk_goal" - -(** - Summary: Return the "precision" of the given goal. Goals can be transformed using over and under approximations. - A under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. - def_API('goal_precision', UINT, (_in(CONTEXT), _in(GOAL))) -*) -external goal_precision : context -> goal -> goal_prec - = "camlidl_z3_Z3_goal_precision" - -(** - Summary: Add a new formula [a] to the given goal. - def_API('goal_assert', VOID, (_in(CONTEXT), _in(GOAL), _in(AST))) -*) -external goal_assert : context -> goal -> ast -> unit - = "camlidl_z3_Z3_goal_assert" - -(** - Summary: Return true if the given goal contains the formula [false]. - def_API('goal_inconsistent', BOOL, (_in(CONTEXT), _in(GOAL))) -*) -external goal_inconsistent : context -> goal -> bool - = "camlidl_z3_Z3_goal_inconsistent" - -(** - Summary: Return the depth of the given goal. It tracks how many transformations were applied to it. - def_API('goal_depth', UINT, (_in(CONTEXT), _in(GOAL))) -*) -external goal_depth : context -> goal -> int - = "camlidl_z3_Z3_goal_depth" - -(** - Summary: Erase all formulas from the given goal. - def_API('goal_reset', VOID, (_in(CONTEXT), _in(GOAL))) -*) -external goal_reset : context -> goal -> unit - = "camlidl_z3_Z3_goal_reset" - -(** - Summary: Return the number of formulas in the given goal. - def_API('goal_size', UINT, (_in(CONTEXT), _in(GOAL))) -*) -external goal_size : context -> goal -> int - = "camlidl_z3_Z3_goal_size" - -(** - Summary: Return a formula from the given goal. - - {b Precondition}: idx < goal_size c g - def_API('goal_formula', AST, (_in(CONTEXT), _in(GOAL), _in(UINT))) -*) -external goal_formula : context -> goal -> int -> ast - = "camlidl_z3_Z3_goal_formula" - -(** - Summary: Return the number of formulas, subformulas and terms in the given goal. - def_API('goal_num_exprs', UINT, (_in(CONTEXT), _in(GOAL))) -*) -external goal_num_exprs : context -> goal -> int - = "camlidl_z3_Z3_goal_num_exprs" - -(** - Summary: Return true if the goal is empty, and it is precise or the product of a under approximation. - def_API('goal_is_decided_sat', BOOL, (_in(CONTEXT), _in(GOAL))) -*) -external goal_is_decided_sat : context -> goal -> bool - = "camlidl_z3_Z3_goal_is_decided_sat" - -(** - Summary: Return true if the goal contains false, and it is precise or the product of an over approximation. - def_API('goal_is_decided_unsat', BOOL, (_in(CONTEXT), _in(GOAL))) -*) -external goal_is_decided_unsat : context -> goal -> bool - = "camlidl_z3_Z3_goal_is_decided_unsat" - -(** - Summary: Copy a goal [g] from the context [source] to a the context [target]. - def_API('goal_translate', GOAL, (_in(CONTEXT), _in(GOAL), _in(CONTEXT))) -*) -external goal_translate : context -> goal -> context -> goal - = "camlidl_z3_Z3_goal_translate" - -(** - Summary: Convert a goal into a string. - def_API('goal_to_string', STRING, (_in(CONTEXT), _in(GOAL))) -*) -external goal_to_string : context -> goal -> string - = "camlidl_z3_Z3_goal_to_string" - -(** - {2 {L Tactics and Probes}} -*) -(** - Summary: Return a tactic associated with the given name. - The complete list of tactics may be obtained using the procedures {!get_num_tactics} and {!get_tactic_name}. - It may also be obtained using the command {e (help-tactics) } in the SMT 2.0 front-end. - Tactics are the basic building block for creating custom solvers for specific problem domains. - def_API('mk_tactic', TACTIC, (_in(CONTEXT), _in(STRING))) -*) -external mk_tactic : context -> string -> tactic - = "camlidl_z3_Z3_mk_tactic" - -(** - Summary: Return a probe associated with the given name. - The complete list of probes may be obtained using the procedures {!get_num_probes} and {!get_probe_name}. - It may also be obtained using the command {e (help-tactics) } in the SMT 2.0 front-end. - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - def_API('mk_probe', PROBE, (_in(CONTEXT), _in(STRING))) -*) -external mk_probe : context -> string -> probe - = "camlidl_z3_Z3_mk_probe" - -(** - Summary: Return a tactic that applies [t1] to a given goal and [t2] - to every subgoal produced by t1. - def_API('tactic_and_then', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) -*) -external tactic_and_then : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_and_then" - -(** - Summary: Return a tactic that first applies [t1] to a given goal, - if it fails then returns the result of [t2] applied to the given goal. - def_API('tactic_or_else', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) -*) -external tactic_or_else : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_or_else" - -(** - Summary: Return a tactic that applies the given tactics in parallel. - def_API('tactic_par_or', TACTIC, (_in(CONTEXT), _in(UINT), _in_array(1, TACTIC))) -*) -external tactic_par_or : context -> tactic array -> tactic - = "camlidl_z3_Z3_tactic_par_or" - -(** - Summary: Return a tactic that applies [t1] to a given goal and then [t2] - to every subgoal produced by t1. The subgoals are processed in parallel. - def_API('tactic_par_and_then', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) -*) -external tactic_par_and_then : context -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_par_and_then" - -(** - Summary: Return a tactic that applies [t] to a given goal for [ms] milliseconds. - If [t] does not terminate in [ms] milliseconds, then it fails. - def_API('tactic_try_for', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(UINT))) -*) -external tactic_try_for : context -> tactic -> int -> tactic - = "camlidl_z3_Z3_tactic_try_for" - -(** - Summary: Return a tactic that applies [t] to a given goal is the probe [p] evaluates to true. - If [p] evaluates to false, then the new tactic behaves like the skip tactic. - def_API('tactic_when', TACTIC, (_in(CONTEXT), _in(PROBE), _in(TACTIC))) -*) -external tactic_when : context -> probe -> tactic -> tactic - = "camlidl_z3_Z3_tactic_when" - -(** - Summary: Return a tactic that applies [t1] to a given goal if the probe [p] evaluates to true, - and [t2] if [p] evaluates to false. - def_API('tactic_cond', TACTIC, (_in(CONTEXT), _in(PROBE), _in(TACTIC), _in(TACTIC))) -*) -external tactic_cond : context -> probe -> tactic -> tactic -> tactic - = "camlidl_z3_Z3_tactic_cond" - -(** - Summary: Return a tactic that keeps applying [t] until the goal is not modified anymore or the maximum - number of iterations [max] is reached. - def_API('tactic_repeat', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(UINT))) -*) -external tactic_repeat : context -> tactic -> int -> tactic - = "camlidl_z3_Z3_tactic_repeat" - -(** - Summary: Return a tactic that just return the given goal. - def_API('tactic_skip', TACTIC, (_in(CONTEXT),)) -*) -external tactic_skip : context -> tactic - = "camlidl_z3_Z3_tactic_skip" - -(** - Summary: Return a tactic that always fails. - def_API('tactic_fail', TACTIC, (_in(CONTEXT),)) -*) -external tactic_fail : context -> tactic - = "camlidl_z3_Z3_tactic_fail" - -(** - Summary: Return a tactic that fails if the probe [p] evaluates to false. - def_API('tactic_fail_if', TACTIC, (_in(CONTEXT), _in(PROBE))) -*) -external tactic_fail_if : context -> probe -> tactic - = "camlidl_z3_Z3_tactic_fail_if" - -(** - Summary: Return a tactic that fails if the goal is not trivially satisfiable (i.e., empty) or - trivially unsatisfiable (i.e., contains false). - def_API('tactic_fail_if_not_decided', TACTIC, (_in(CONTEXT),)) -*) -external tactic_fail_if_not_decided : context -> tactic - = "camlidl_z3_Z3_tactic_fail_if_not_decided" - -(** - Summary: Return a tactic that applies [t] using the given set of parameters. - def_API('tactic_using_params', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(PARAMS))) -*) -external tactic_using_params : context -> tactic -> params -> tactic - = "camlidl_z3_Z3_tactic_using_params" - -(** - Summary: Return a probe that always evaluates to val. - def_API('probe_const', PROBE, (_in(CONTEXT), _in(DOUBLE))) -*) -external probe_const : context -> float -> probe - = "camlidl_z3_Z3_probe_const" - -(** - Summary: Return a probe that evaluates to "true" when the value returned by [p1] is less than the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_lt', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_lt : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_lt" - -(** - Summary: Return a probe that evaluates to "true" when the value returned by [p1] is greater than the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_gt', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_gt : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_gt" - -(** - Summary: Return a probe that evaluates to "true" when the value returned by [p1] is less than or equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_le', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_le : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_le" - -(** - Summary: Return a probe that evaluates to "true" when the value returned by [p1] is greater than or equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_ge', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_ge : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_ge" - -(** - Summary: Return a probe that evaluates to "true" when the value returned by [p1] is equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_eq', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_eq : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_eq" - -(** - Summary: Return a probe that evaluates to "true" when [p1] and [p2] evaluates to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_and', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_and : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_and" - -(** - Summary: Return a probe that evaluates to "true" when [p1] or [p2] evaluates to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_or', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) -*) -external probe_or : context -> probe -> probe -> probe - = "camlidl_z3_Z3_probe_or" - -(** - Summary: Return a probe that evaluates to "true" when [p] does not evaluate to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_not', PROBE, (_in(CONTEXT), _in(PROBE))) -*) -external probe_not : context -> probe -> probe - = "camlidl_z3_Z3_probe_not" - -(** - Summary: Return the number of builtin tactics available in Z3. - def_API('get_num_tactics', UINT, (_in(CONTEXT),)) -*) -external get_num_tactics : context -> int - = "camlidl_z3_Z3_get_num_tactics" - -(** - Summary: Return the name of the idx tactic. - - {b Precondition}: i < get_num_tactics c - def_API('get_tactic_name', STRING, (_in(CONTEXT), _in(UINT))) -*) -external get_tactic_name : context -> int -> string - = "camlidl_z3_Z3_get_tactic_name" - -(** - Summary: Return the number of builtin probes available in Z3. - def_API('get_num_probes', UINT, (_in(CONTEXT),)) -*) -external get_num_probes : context -> int - = "camlidl_z3_Z3_get_num_probes" - -(** - Summary: Return the name of the i probe. - - {b Precondition}: i < get_num_probes c - def_API('get_probe_name', STRING, (_in(CONTEXT), _in(UINT))) -*) -external get_probe_name : context -> int -> string - = "camlidl_z3_Z3_get_probe_name" - -(** - Summary: Return a string containing a description of parameters accepted by the given tactic. - def_API('tactic_get_help', STRING, (_in(CONTEXT), _in(TACTIC))) -*) -external tactic_get_help : context -> tactic -> string - = "camlidl_z3_Z3_tactic_get_help" - -(** - Summary: Return the parameter description set for the given tactic object. - def_API('tactic_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(TACTIC))) -*) -external tactic_get_param_descrs : context -> tactic -> param_descrs - = "camlidl_z3_Z3_tactic_get_param_descrs" - -(** - Summary: Return a string containing a description of the tactic with the given name. - def_API('tactic_get_descr', STRING, (_in(CONTEXT), _in(STRING))) -*) -external tactic_get_descr : context -> string -> string - = "camlidl_z3_Z3_tactic_get_descr" - -(** - Summary: Return a string containing a description of the probe with the given name. - def_API('probe_get_descr', STRING, (_in(CONTEXT), _in(STRING))) -*) -external probe_get_descr : context -> string -> string - = "camlidl_z3_Z3_probe_get_descr" - -(** - Summary: Execute the probe over the goal. The probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - def_API('probe_apply', DOUBLE, (_in(CONTEXT), _in(PROBE), _in(GOAL))) -*) -external probe_apply : context -> probe -> goal -> float - = "camlidl_z3_Z3_probe_apply" - -(** - Summary: Apply tactic [t] to the goal [g]. - def_API('tactic_apply', APPLY_RESULT, (_in(CONTEXT), _in(TACTIC), _in(GOAL))) -*) -external tactic_apply : context -> tactic -> goal -> apply_result - = "camlidl_z3_Z3_tactic_apply" - -(** - Summary: Apply tactic [t] to the goal [g] using the parameter set [p]. - def_API('tactic_apply_ex', APPLY_RESULT, (_in(CONTEXT), _in(TACTIC), _in(GOAL), _in(PARAMS))) -*) -external tactic_apply_ex : context -> tactic -> goal -> params -> apply_result - = "camlidl_z3_Z3_tactic_apply_ex" - -(** - Summary: Convert the [apply_result] object returned by {!tactic_apply} into a string. - def_API('apply_result_to_string', STRING, (_in(CONTEXT), _in(APPLY_RESULT))) -*) -external apply_result_to_string : context -> apply_result -> string - = "camlidl_z3_Z3_apply_result_to_string" - -(** - Summary: Return the number of subgoals in the [apply_result] object returned by {!tactic_apply}. - def_API('apply_result_get_num_subgoals', UINT, (_in(CONTEXT), _in(APPLY_RESULT))) -*) -external apply_result_get_num_subgoals : context -> apply_result -> int - = "camlidl_z3_Z3_apply_result_get_num_subgoals" - -(** - Summary: Return one of the subgoals in the [apply_result] object returned by {!tactic_apply}. - - {b Precondition}: i < apply_result_get_num_subgoals c r - def_API('apply_result_get_subgoal', GOAL, (_in(CONTEXT), _in(APPLY_RESULT), _in(UINT))) -*) -external apply_result_get_subgoal : context -> apply_result -> int -> goal - = "camlidl_z3_Z3_apply_result_get_subgoal" - -(** - Summary: Convert a model for the subgoal [apply_result_get_subgoal(c], r, i) into a model for the original goal [g]. - Where [g] is the goal used to create [r] using [tactic_apply(c], t, g). - def_API('apply_result_convert_model', MODEL, (_in(CONTEXT), _in(APPLY_RESULT), _in(UINT), _in(MODEL))) -*) -external apply_result_convert_model : context -> apply_result -> int -> model -> model - = "camlidl_z3_Z3_apply_result_convert_model" - -(** - {2 {L Solvers}} -*) -(** - Summary: Create a new (incremental) solver. This solver also uses a - set of builtin tactics for handling the first check-sat command, and - check-sat commands that take more than a given number of milliseconds to be solved. - def_API('mk_solver', SOLVER, (_in(CONTEXT),)) -*) -external mk_solver : context -> solver - = "camlidl_z3_Z3_mk_solver" - -(** - Summary: Create a new (incremental) solver. - def_API('mk_simple_solver', SOLVER, (_in(CONTEXT),)) -*) -external mk_simple_solver : context -> solver - = "camlidl_z3_Z3_mk_simple_solver" - -(** - Summary: Create a new solver customized for the given logic. - It behaves like {!mk_solver} if the logic is unknown or unsupported. - def_API('mk_solver_for_logic', SOLVER, (_in(CONTEXT), _in(SYMBOL))) -*) -external mk_solver_for_logic : context -> symbol -> solver - = "camlidl_z3_Z3_mk_solver_for_logic" - -(** - Summary: Create a new solver that is implemented using the given tactic. - The solver supports the commands {!solver_push} and {!solver_pop}, but it - will always solve each {!solver_check} from scratch. - def_API('mk_solver_from_tactic', SOLVER, (_in(CONTEXT), _in(TACTIC))) -*) -external mk_solver_from_tactic : context -> tactic -> solver - = "camlidl_z3_Z3_mk_solver_from_tactic" - -(** - Summary: Return a string describing all solver available parameters. - def_API('solver_get_help', STRING, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_help : context -> solver -> string - = "camlidl_z3_Z3_solver_get_help" - -(** - Summary: Return the parameter description set for the given solver object. - def_API('solver_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_param_descrs : context -> solver -> param_descrs - = "camlidl_z3_Z3_solver_get_param_descrs" - -(** - Summary: Set the given solver using the given parameters. - def_API('solver_set_params', VOID, (_in(CONTEXT), _in(SOLVER), _in(PARAMS))) -*) -external solver_set_params : context -> solver -> params -> unit - = "camlidl_z3_Z3_solver_set_params" - -(** - Summary: Create a backtracking point. - The solver contains a stack of assertions. - - {b See also}: {!solver_pop} - def_API('solver_push', VOID, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_push : context -> solver -> unit - = "camlidl_z3_Z3_solver_push" - -(** - Summary: Backtrack [n] backtracking points. - - {b See also}: {!solver_push} - - {b Precondition}: n <= solver_get_num_scopes c s - def_API('solver_pop', VOID, (_in(CONTEXT), _in(SOLVER), _in(UINT))) -*) -external solver_pop : context -> solver -> int -> unit - = "camlidl_z3_Z3_solver_pop" - -(** - Summary: Remove all assertions from the solver. - def_API('solver_reset', VOID, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_reset : context -> solver -> unit - = "camlidl_z3_Z3_solver_reset" - -(** - Summary: Return the number of backtracking points. - - {b See also}: {!solver_push} - - {b See also}: {!solver_pop} - def_API('solver_get_num_scopes', UINT, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_num_scopes : context -> solver -> int - = "camlidl_z3_Z3_solver_get_num_scopes" - -(** - Summary: Assert a constraint into the solver. - The functions {!solver_check} and {!solver_check_assumptions} should be - used to check whether the logical context is consistent or not. - def_API('solver_assert', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST))) -*) -external solver_assert : context -> solver -> ast -> unit - = "camlidl_z3_Z3_solver_assert" - -(** - Summary: Assert a constraint [a] into the solver, and track it (in the unsat) core using - the Boolean constant [p]. - This API is an alternative to {!solver_check_assumptions} for extracting unsat cores. - Both APIs can be used in the same solver. The unsat core will contain a combination - of the Boolean variables provided using solver_assert_and_track and the Boolean literals - provided using {!solver_check_assumptions}. - - {b Precondition}: [a] must be a Boolean expression - - {b Precondition}: [p] must be a Boolean constant aka variable. - def_API('solver_assert_and_track', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST), _in(AST))) -*) -external solver_assert_and_track : context -> solver -> ast -> ast -> unit - = "camlidl_z3_Z3_solver_assert_and_track" - -(** - Summary: Return the set of asserted formulas as a goal object. - def_API('solver_get_assertions', AST_VECTOR, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_assertions : context -> solver -> ast_vector - = "camlidl_z3_Z3_solver_get_assertions" - -(** - Summary: Check whether the assertions in a given solver are consistent or not. - The function {!solver_get_model} retrieves a model if the - assertions are not unsatisfiable (i.e., the result is not \c - L_FALSE) and model construction is enabled. - The function {!solver_get_proof} retrieves a proof if proof - generation was enabled when the context was created, and the - assertions are unsatisfiable (i.e., the result is [L_FALSE)]. - def_API('solver_check', INT, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_check : context -> solver -> lbool - = "camlidl_z3_Z3_solver_check" - -(** - Summary: Check whether the assertions in the given solver and - optional assumptions are consistent or not. - The function {!solver_get_unsat_core} retrieves the subset of the - assumptions used in the unsatisfiability proof produced by Z3. - - {b See also}: {!solver_check} - def_API('solver_check_assumptions', INT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST))) -*) -external solver_check_assumptions : context -> solver -> ast array -> lbool - = "camlidl_z3_Z3_solver_check_assumptions" - -(** - Summary: Retrieve the model for the last {!solver_check} or {!solver_check_assumptions} - The error handler is invoked if a model is not available because - the commands above were not invoked for the given solver, or if the result was [L_FALSE]. - def_API('solver_get_model', MODEL, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_model : context -> solver -> model - = "camlidl_z3_Z3_solver_get_model" - -(** - Summary: Retrieve the proof for the last {!solver_check} or {!solver_check_assumptions} - The error handler is invoked if proof generation is not enabled, - or if the commands above were not invoked for the given solver, - or if the result was different from [L_FALSE]. - def_API('solver_get_proof', AST, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_proof : context -> solver -> ast - = "camlidl_z3_Z3_solver_get_proof" - -(** - Summary: Retrieve the unsat core for the last {!solver_check_assumptions} - The unsat core is a subset of the assumptions [a]. - def_API('solver_get_unsat_core', AST_VECTOR, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_unsat_core : context -> solver -> ast_vector - = "camlidl_z3_Z3_solver_get_unsat_core" - -(** - Summary: Return a brief justification for an "unknown" result (i.e., L_UNDEF) for - the commands {!solver_check} and {!solver_check_assumptions} - def_API('solver_get_reason_unknown', STRING, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_reason_unknown : context -> solver -> string - = "camlidl_z3_Z3_solver_get_reason_unknown" - -(** - Summary: Return statistics for the given solver. - def_API('solver_get_statistics', STATS, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_get_statistics : context -> solver -> stats - = "camlidl_z3_Z3_solver_get_statistics" - -(** - Summary: Convert a solver into a string. - def_API('solver_to_string', STRING, (_in(CONTEXT), _in(SOLVER))) -*) -external solver_to_string : context -> solver -> string - = "camlidl_z3_Z3_solver_to_string" - -(** - {2 {L Statistics}} -*) - -type stat_datum = Stat_int of int | Stat_float of float -type stats_refined = (string, stat_datum) Hashtbl.t - - -(** - Summary: [stats_refine c s] is the refined stats of [s]. -*) -val stats_refine : context -> stats -> stats_refined - -(** - Summary: Convert a statistics into a string. - def_API('stats_to_string', STRING, (_in(CONTEXT), _in(STATS))) -*) -external stats_to_string : context -> stats -> string - = "camlidl_z3_Z3_stats_to_string" - -(** - {4 {L Low-level API}} -*) -(** - Summary: Return the number of statistical data in [s]. - def_API('stats_size', UINT, (_in(CONTEXT), _in(STATS))) -*) -external stats_size : context -> stats -> int - = "camlidl_z3_Z3_stats_size" - -(** - Summary: Return the key (a string) for a particular statistical data. - - {b Precondition}: idx < stats_size c s - def_API('stats_get_key', STRING, (_in(CONTEXT), _in(STATS), _in(UINT))) -*) -external stats_get_key : context -> stats -> int -> string - = "camlidl_z3_Z3_stats_get_key" - -(** - Summary: Return TRUE if the given statistical data is a unsigned int integer. - - {b Precondition}: idx < stats_size c s - def_API('stats_is_uint', BOOL, (_in(CONTEXT), _in(STATS), _in(UINT))) -*) -external stats_is_uint : context -> stats -> int -> bool - = "camlidl_z3_Z3_stats_is_uint" - -(** - Summary: Return TRUE if the given statistical data is a double. - - {b Precondition}: idx < stats_size c s - def_API('stats_is_double', BOOL, (_in(CONTEXT), _in(STATS), _in(UINT))) -*) -external stats_is_double : context -> stats -> int -> bool - = "camlidl_z3_Z3_stats_is_double" - -(** - Summary: Return the unsigned int value of the given statistical data. - - {b Precondition}: idx < stats_size c s && stats_is_uint c s - def_API('stats_get_uint_value', UINT, (_in(CONTEXT), _in(STATS), _in(UINT))) -*) -external stats_get_uint_value : context -> stats -> int -> int - = "camlidl_z3_Z3_stats_get_uint_value" - -(** - Summary: Return the double value of the given statistical data. - - {b Precondition}: idx < stats_size c s && stats_is_double c s - def_API('stats_get_double_value', DOUBLE, (_in(CONTEXT), _in(STATS), _in(UINT))) -*) -external stats_get_double_value : context -> stats -> int -> float - = "camlidl_z3_Z3_stats_get_double_value" - -(** - {2 {L Deprecated Constraints API}} -*) -(** - Summary: Retrieve congruence class representatives for terms. - The function can be used for relying on Z3 to identify equal terms under the current - set of assumptions. The array of terms and array of class identifiers should have - the same length. The class identifiers are numerals that are assigned to the same - value for their corresponding terms if the current context forces the terms to be - equal. You cannot deduce that terms corresponding to different numerals must be all different, - (especially when using non-convex theories). - All implied equalities are returned by this call. - This means that two terms map to the same class identifier if and only if - the current context implies that they are equal. - A side-effect of the function is a satisfiability check on the assertions on the solver that is passed in. - The function return L_FALSE if the current assertions are not satisfiable. - - {b See also}: {!check_and_get_model} - - {b See also}: {!check} - @deprecated To be moved outside of API. - def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST), _out_array(2, UINT))) -*) -external get_implied_equalities : context -> solver -> ast array -> lbool * int array - = "camlidl_z3_Z3_get_implied_equalities" - - -(** - {2 {L Legacy V3 API}} -*) -module V3 : sig -(** - {2 {L Legacy V3 API}} -*) - -(* File generated from z3V3.idl *) - -type symbol -and literals -and theory -and config -and context -and sort -and func_decl -and ast -and app -and pattern -and model -and constructor -and constructor_list - -and lbool = - | L_FALSE - | L_UNDEF - | L_TRUE - -and symbol_kind = - | INT_SYMBOL - | STRING_SYMBOL - -and parameter_kind = - | PARAMETER_INT - | PARAMETER_DOUBLE - | PARAMETER_RATIONAL - | PARAMETER_SYMBOL - | PARAMETER_SORT - | PARAMETER_AST - | PARAMETER_FUNC_DECL - -and sort_kind = - | UNINTERPRETED_SORT - | BOOL_SORT - | INT_SORT - | REAL_SORT - | BV_SORT - | ARRAY_SORT - | DATATYPE_SORT - | RELATION_SORT - | FINITE_DOMAIN_SORT - | UNKNOWN_SORT - -and ast_kind = - | NUMERAL_AST - | APP_AST - | VAR_AST - | QUANTIFIER_AST - | SORT_AST - | FUNC_DECL_AST - | UNKNOWN_AST - -and decl_kind = - | OP_TRUE - | OP_FALSE - | OP_EQ - | OP_DISTINCT - | OP_ITE - | OP_AND - | OP_OR - | OP_IFF - | OP_XOR - | OP_NOT - | OP_IMPLIES - | OP_OEQ - | OP_ANUM - | OP_AGNUM - | OP_LE - | OP_GE - | OP_LT - | OP_GT - | OP_ADD - | OP_SUB - | OP_UMINUS - | OP_MUL - | OP_DIV - | OP_IDIV - | OP_REM - | OP_MOD - | OP_TO_REAL - | OP_TO_INT - | OP_IS_INT - | OP_POWER - | OP_STORE - | OP_SELECT - | OP_CONST_ARRAY - | OP_ARRAY_MAP - | OP_ARRAY_DEFAULT - | OP_SET_UNION - | OP_SET_INTERSECT - | OP_SET_DIFFERENCE - | OP_SET_COMPLEMENT - | OP_SET_SUBSET - | OP_AS_ARRAY - | OP_BNUM - | OP_BIT1 - | OP_BIT0 - | OP_BNEG - | OP_BADD - | OP_BSUB - | OP_BMUL - | OP_BSDIV - | OP_BUDIV - | OP_BSREM - | OP_BUREM - | OP_BSMOD - | OP_BSDIV0 - | OP_BUDIV0 - | OP_BSREM0 - | OP_BUREM0 - | OP_BSMOD0 - | OP_ULEQ - | OP_SLEQ - | OP_UGEQ - | OP_SGEQ - | OP_ULT - | OP_SLT - | OP_UGT - | OP_SGT - | OP_BAND - | OP_BOR - | OP_BNOT - | OP_BXOR - | OP_BNAND - | OP_BNOR - | OP_BXNOR - | OP_CONCAT - | OP_SIGN_EXT - | OP_ZERO_EXT - | OP_EXTRACT - | OP_REPEAT - | OP_BREDOR - | OP_BREDAND - | OP_BCOMP - | OP_BSHL - | OP_BLSHR - | OP_BASHR - | OP_ROTATE_LEFT - | OP_ROTATE_RIGHT - | OP_EXT_ROTATE_LEFT - | OP_EXT_ROTATE_RIGHT - | OP_INT2BV - | OP_BV2INT - | OP_CARRY - | OP_XOR3 - | OP_PR_UNDEF - | OP_PR_TRUE - | OP_PR_ASSERTED - | OP_PR_GOAL - | OP_PR_MODUS_PONENS - | OP_PR_REFLEXIVITY - | OP_PR_SYMMETRY - | OP_PR_TRANSITIVITY - | OP_PR_TRANSITIVITY_STAR - | OP_PR_MONOTONICITY - | OP_PR_QUANT_INTRO - | OP_PR_DISTRIBUTIVITY - | OP_PR_AND_ELIM - | OP_PR_NOT_OR_ELIM - | OP_PR_REWRITE - | OP_PR_REWRITE_STAR - | OP_PR_PULL_QUANT - | OP_PR_PULL_QUANT_STAR - | OP_PR_PUSH_QUANT - | OP_PR_ELIM_UNUSED_VARS - | OP_PR_DER - | OP_PR_QUANT_INST - | OP_PR_HYPOTHESIS - | OP_PR_LEMMA - | OP_PR_UNIT_RESOLUTION - | OP_PR_IFF_TRUE - | OP_PR_IFF_FALSE - | OP_PR_COMMUTATIVITY - | OP_PR_DEF_AXIOM - | OP_PR_DEF_INTRO - | OP_PR_APPLY_DEF - | OP_PR_IFF_OEQ - | OP_PR_NNF_POS - | OP_PR_NNF_NEG - | OP_PR_NNF_STAR - | OP_PR_CNF_STAR - | OP_PR_SKOLEMIZE - | OP_PR_MODUS_PONENS_OEQ - | OP_PR_TH_LEMMA - | OP_PR_HYPER_RESOLVE - | OP_RA_STORE - | OP_RA_EMPTY - | OP_RA_IS_EMPTY - | OP_RA_JOIN - | OP_RA_UNION - | OP_RA_WIDEN - | OP_RA_PROJECT - | OP_RA_FILTER - | OP_RA_NEGATION_FILTER - | OP_RA_RENAME - | OP_RA_COMPLEMENT - | OP_RA_SELECT - | OP_RA_CLONE - | OP_FD_LT - | OP_LABEL - | OP_LABEL_LIT - | OP_DT_CONSTRUCTOR - | OP_DT_RECOGNISER - | OP_DT_ACCESSOR - | OP_UNINTERPRETED - -and param_kind = - | PK_UINT - | PK_BOOL - | PK_DOUBLE - | PK_SYMBOL - | PK_STRING - | PK_OTHER - | PK_INVALID - -and search_failure = - | NO_FAILURE - | UNKNOWN - | TIMEOUT - | MEMOUT_WATERMARK - | CANCELED - | NUM_CONFLICTS - | THEORY - | QUANTIFIERS - -and ast_print_mode = - | PRINT_SMTLIB_FULL - | PRINT_LOW_LEVEL - | PRINT_SMTLIB_COMPLIANT - | PRINT_SMTLIB2_COMPLIANT - - -(** -*) -(** - {2 {L Types}} - Most of the types in the API are abstract. - - [context]: manager of all other Z3 objects, global configuration options, etc. - - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. - - [ast]: abstract syntax tree node. That is, the data-structure used in Z3 to represent terms, formulas and types. - - [sort]: kind of AST used to represent types. - - [func_decl]: kind of AST used to represent function symbols. - - [app]: kind of AST used to represent function applications. - - [pattern]: kind of AST used to represent pattern and multi-patterns used to guide quantifier instantiation. - - [params]: parameter set used to configure many components such as: simplifiers, tactics, solvers, etc. - - [model]: model for the constraints asserted into the logical context. - - [func_interp]: interpretation of a function in a model. - - [func_entry]: representation of the value of a [func_interp] at a particular point. - - [fixedpoint]: context for the recursive predicate solver. - - [ast_vector]: vector of [ast] objects. - - [ast_map]: mapping from [ast] to [ast] objects. - - [goal]: set of formulas that can be solved and/or transformed using tactics and solvers. - - [tactic]: basic building block for creating custom solvers for specific problem domains. - - [probe]: function/predicate used to inspect a goal and collect information that may be used to decide which solver and/or preprocessing step will be used. - - [apply_result]: collection of subgoals resulting from applying of a tactic to a goal. - - [solver]: (incremental) solver, possibly specialized by a particular tactic or logic. - - [stats]: statistical data for a solver. -*) -(** - {!lbool} - Lifted Boolean type: [false], [undefined], [true]. -*) -(** - {!symbol_kind} - The different kinds of symbol. - In Z3, a symbol can be represented using integers and strings (See {!get_symbol_kind}). - - {b See also}: {!mk_int_symbol} - - {b See also}: {!mk_string_symbol} -*) -(** - {!parameter_kind} - The different kinds of parameters that can be associated with function symbols. - - {b See also}: {!get_decl_num_parameters} - - {b See also}: {!get_decl_parameter_kind} - - PARAMETER_INT is used for integer parameters. - - PARAMETER_DOUBLE is used for double parameters. - - PARAMETER_RATIONAL is used for parameters that are rational numbers. - - PARAMETER_SYMBOL is used for parameters that are symbols. - - PARAMETER_SORT is used for sort parameters. - - PARAMETER_AST is used for expression parameters. - - PARAMETER_FUNC_DECL is used for function declaration parameters. -*) -(** - {!sort_kind} - The different kinds of Z3 types (See {!get_sort_kind}). -*) -(** - {!ast_kind} - The different kinds of Z3 AST (abstract syntax trees). That is, terms, formulas and types. - - - APP_AST: constant and applications - - NUMERAL_AST: numeral constants - - VAR_AST: bound variables - - QUANTIFIER_AST: quantifiers - - SORT_AST: sort - - FUNC_DECL_AST: function declaration - - UNKNOWN_AST: internal -*) -(** - {!decl_kind} - The different kinds of interpreted function kinds. - - - OP_TRUE The constant true. - - - OP_FALSE The constant false. - - - OP_EQ The equality predicate. - - - OP_DISTINCT The n-ary distinct predicate (every argument is mutually distinct). - - - OP_ITE The ternary if-then-else term. - - - OP_AND n-ary conjunction. - - - OP_OR n-ary disjunction. - - - OP_IFF equivalence (binary). - - - OP_XOR Exclusive or. - - - OP_NOT Negation. - - - OP_IMPLIES Implication. - - - OP_OEQ Binary equivalence modulo namings. This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. - - - OP_ANUM Arithmetic numeral. - - - OP_AGNUM Arithmetic algebraic numeral. Algebraic numbers are used to represent irrational numbers in Z3. - - - OP_LE <=. - - - OP_GE >=. - - - OP_LT <. - - - OP_GT >. - - - OP_ADD Addition - Binary. - - - OP_SUB Binary subtraction. - - - OP_UMINUS Unary minus. - - - OP_MUL Multiplication - Binary. - - - OP_DIV Division - Binary. - - - OP_IDIV Integer division - Binary. - - - OP_REM Remainder - Binary. - - - OP_MOD Modulus - Binary. - - - OP_TO_REAL Coercion of integer to real - Unary. - - - OP_TO_INT Coercion of real to integer - Unary. - - - OP_IS_INT Check if real is also an integer - Unary. - - - OP_POWER Power operator x^y. - - - OP_STORE Array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. - - - OP_SELECT Array select. - - - OP_CONST_ARRAY The constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. - - - OP_ARRAY_DEFAULT Default value of arrays. For example default(const(v)) = v. The function is unary. - - - OP_ARRAY_MAP Array map operator. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. - - - OP_SET_UNION Set union between two Booelan arrays (two arrays whose range type is Boolean). The function is binary. - - - OP_SET_INTERSECT Set intersection between two Boolean arrays. The function is binary. - - - OP_SET_DIFFERENCE Set difference between two Boolean arrays. The function is binary. - - - OP_SET_COMPLEMENT Set complement of a Boolean array. The function is unary. - - - OP_SET_SUBSET Subset predicate between two Boolean arrays. The relation is binary. - - - OP_AS_ARRAY An array value that behaves as the function graph of the - function passed as parameter. - - - OP_BNUM Bit-vector numeral. - - - OP_BIT1 One bit bit-vector. - - - OP_BIT0 Zero bit bit-vector. - - - OP_BNEG Unary minus. - - - OP_BADD Binary addition. - - - OP_BSUB Binary subtraction. - - - OP_BMUL Binary multiplication. - - - OP_BSDIV Binary signed division. - - - OP_BUDIV Binary unsigned int division. - - - OP_BSREM Binary signed remainder. - - - OP_BUREM Binary unsigned int remainder. - - - OP_BSMOD Binary signed modulus. - - - OP_BSDIV0 Unary function. bsdiv(x,0) is congruent to bsdiv0(x). - - - OP_BUDIV0 Unary function. budiv(x,0) is congruent to budiv0(x). - - - OP_BSREM0 Unary function. bsrem(x,0) is congruent to bsrem0(x). - - - OP_BUREM0 Unary function. burem(x,0) is congruent to burem0(x). - - - OP_BSMOD0 Unary function. bsmod(x,0) is congruent to bsmod0(x). - - - OP_ULEQ Unsigned bit-vector <= - Binary relation. - - - OP_SLEQ Signed bit-vector <= - Binary relation. - - - OP_UGEQ Unsigned bit-vector >= - Binary relation. - - - OP_SGEQ Signed bit-vector >= - Binary relation. - - - OP_ULT Unsigned bit-vector < - Binary relation. - - - OP_SLT Signed bit-vector < - Binary relation. - - - OP_UGT Unsigned bit-vector > - Binary relation. - - - OP_SGT Signed bit-vector > - Binary relation. - - - OP_BAND Bit-wise and - Binary. - - - OP_BOR Bit-wise or - Binary. - - - OP_BNOT Bit-wise not - Unary. - - - OP_BXOR Bit-wise xor - Binary. - - - OP_BNAND Bit-wise nand - Binary. - - - OP_BNOR Bit-wise nor - Binary. - - - OP_BXNOR Bit-wise xnor - Binary. - - - OP_CONCAT Bit-vector concatenation - Binary. - - - OP_SIGN_EXT Bit-vector sign extension. - - - OP_ZERO_EXT Bit-vector zero extension. - - - OP_EXTRACT Bit-vector extraction. - - - OP_REPEAT Repeat bit-vector n times. - - - OP_BREDOR Bit-vector reduce or - Unary. - - - OP_BREDAND Bit-vector reduce and - Unary. - - - OP_BCOMP . - - - OP_BSHL Shift left. - - - OP_BLSHR Logical shift right. - - - OP_BASHR Arithmetical shift right. - - - OP_ROTATE_LEFT Left rotation. - - - OP_ROTATE_RIGHT Right rotation. - - - OP_EXT_ROTATE_LEFT (extended) Left rotation. Similar to OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. - - - OP_EXT_ROTATE_RIGHT (extended) Right rotation. Similar to OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. - - - OP_INT2BV Coerce integer to bit-vector. NB. This function - is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - - - OP_BV2INT Coerce bit-vector to integer. NB. This function - is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - - - OP_CARRY Compute the carry bit in a full-adder. - The meaning is given by the equivalence - (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) - - - OP_XOR3 Compute ternary XOR. - The meaning is given by the equivalence - (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) - - - OP_PR_UNDEF: Undef/Null proof object. - - - OP_PR_TRUE: Proof for the expression 'true'. - - - OP_PR_ASSERTED: Proof for a fact asserted by the user. - - - OP_PR_GOAL: Proof for a fact (tagged as goal) asserted by the user. - - - OP_PR_MODUS_PONENS: Given a proof for p and a proof for (implies p q), produces a proof for q. - {e - T1: p - T2: (implies p q) - [mp T1 T2]: q - } - The second antecedents may also be a proof for (iff p q). - - - OP_PR_REFLEXIVITY: A proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. - - - OP_PR_SYMMETRY: Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - {e - T1: (R t s) - [symmetry T1]: (R s t) - } - T1 is the antecedent of this proof object. - - - OP_PR_TRANSITIVITY: Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - {e - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) - } - - - OP_PR_TRANSITIVITY_STAR: Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - - Example: - {e - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - } - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. - - - OP_PR_MONOTONICITY: Monotonicity proof object. - {e - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - } - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. - - - OP_PR_QUANT_INTRO: Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - - - OP_PR_DISTRIBUTIVITY: Distributivity proof object. - Given that f (= or) distributes over g (= and), produces a proof for - - (= (f a (g c d)) - (g (f a c) (f a d))) - - If f and g are associative, this proof also justifies the following equality: - - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. - - - OP_PR_AND_ELIM: Given a proof for (and l_1 ... l_n), produces a proof for l_i - - {e - T1: (and l_1 ... l_n) - [and-elim T1]: l_i - } - - OP_PR_NOT_OR_ELIM: Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - - {e - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) - } - - - OP_PR_REWRITE: A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - - Examples: - {e - (= (+ x 0) x) - (= (+ x 1 2) (+ 3 x)) - (iff (or x false) x) - } - - - OP_PR_REWRITE_STAR: A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - - - OP_PR_PULL_QUANT: A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - - - OP_PR_PULL_QUANT_STAR: A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents. - - - OP_PR_PUSH_QUANT: A proof for: - - {e - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - } - This proof object has no antecedents. - - - OP_PR_ELIM_UNUSED_VARS: - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. - - - OP_PR_DER: A proof for destructive equality resolution: - (iff (forall (x) (or (not (= x t)) P[x])) P[t]) - if x does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. - - - OP_PR_QUANT_INST: A proof of (or (not (forall (x) (P x))) (P a)) - - - OP_PR_HYPOTHESIS: Mark a hypothesis in a natural deduction style proof. - - - OP_PR_LEMMA: - - {e - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - } - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. - - - OP_PR_UNIT_RESOLUTION: - {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - } - - - OP_PR_IFF_TRUE: - {e - T1: p - [iff-true T1]: (iff p true) - } - - - OP_PR_IFF_FALSE: - {e - T1: (not p) - [iff-false T1]: (iff p false) - } - - - OP_PR_COMMUTATIVITY: - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. - - - OP_PR_DEF_AXIOM: Proof object used to justify Tseitin's like axioms: - - {e - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - } - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). - - - OP_PR_DEF_INTRO: Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) - - - OP_PR_APPLY_DEF: - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. - - - OP_PR_IFF_OEQ: - T1: (iff p q) - [iff~ T1]: (~ p q) - - - OP_PR_NNF_POS: Proof for a (positive) NNF step. Example: - {e - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - } - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - {e - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - } - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. - - - - OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples: - {e - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) - } - - OP_PR_NNF_STAR: A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - - - OP_PR_CNF_STAR: A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - - - OP_PR_SKOLEMIZE: Proof for: - - {e - [sk]: (~ (not (forall x (p x y))) (not (p (sk y) y))) - [sk]: (~ (exists x (p x y)) (p (sk y) y)) - } - - This proof object has no antecedents. - - - OP_PR_MODUS_PONENS_OEQ: Modus ponens style rule for equi-satisfiability. - {e - T1: p - T2: (~ p q) - [mp~ T1 T2]: q - } - - - OP_PR_TH_LEMMA: Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - - triangle-eq - Indicates a lemma related to the equivalence: - {e - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - } - - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - - - - OP_PR_HYPER_RESOLVE: Hyper-resolution rule. - - The premises of the rules is a sequence of clauses. - The first clause argument is the main clause of the rule. - One literal from the second, third, .. clause is resolved - with a literal from the first (main) clause. - - Premises of the rules are of the form - {e - (or l0 l1 l2 .. ln) - } - or - {e - (=> (and ln+1 ln+2 .. ln+m) l0) - } - or in the most general (ground) form: - {e - (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)) - } - In other words we use the following (Prolog style) convention for Horn - implications: - The head of a Horn implication is position 0, - the first conjunct in the body of an implication is position 1 - the second conjunct in the body of an implication is position 2 - - For general implications where the head is a disjunction, the - first n positions correspond to the n disjuncts in the head. - The next m positions correspond to the m conjuncts in the body. - - The premises can be universally quantified so that the most - general non-ground form is: - - {e - (forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1))) - } - - The hyper-resolution rule takes a sequence of parameters. - The parameters are substitutions of bound variables separated by pairs - of literal positions from the main clause and side clause. - - - - OP_RA_STORE: Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements - correspond to the [n] columns of the relation. - - - OP_RA_EMPTY: Creates the empty relation. - - - OP_RA_IS_EMPTY: Tests if the relation is empty. - - - OP_RA_JOIN: Create the relational join. - - - OP_RA_UNION: Create the union or convex hull of two relations. - The function takes two arguments. - - - OP_RA_WIDEN: Widen two relations. - The function takes two arguments. - - - OP_RA_PROJECT: Project the columns (provided as numbers in the parameters). - The function takes one argument. - - - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. - - - OP_RA_NEGATION_FILTER: Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in x in pos, such that there is no y in neg that agrees with - x on the columns c1, d1, .., cN, dN. - - - - OP_RA_RENAME: rename columns in the relation. - The function takes one argument. - The parameters contain the renaming as a cycle. - - - OP_RA_COMPLEMENT: Complement the relation. - - - OP_RA_SELECT: Check if a record is an element of the relation. - The function takes [n+1] arguments, where the first argument is a relation, - and the remaining [n] arguments correspond to a record. - - - OP_RA_CLONE: Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for [OP_RA_UNION] - to perform destructive updates to the first argument. - - - - OP_FD_LT: A less than predicate over the finite domain FINITE_DOMAIN_SORT. - - - OP_LABEL: A label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. - It takes one argument, a formula. - - - OP_LABEL_LIT: A label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - - - OP_DT_CONSTRUCTOR: datatype constructor. - - - OP_DT_RECOGNISER: datatype recognizer. - - - OP_DT_ACCESSOR: datatype accessor. - - - OP_UNINTERPRETED: kind used for uninterpreted symbols. -*) -(** - {!param_kind} - - The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). - - - PK_UINT integer parameters. - - PK_BOOL boolean parameters. - - PK_DOUBLE double parameters. - - PK_SYMBOL symbol parameters. - - PK_STRING string parameters. - - PK_OTHER all internal parameter kinds which are not exposed in the API. - - PK_INVALID invalid parameter. -*) -(** - {!search_failure} - The different kinds of search failure types. - - - NO_FAILURE: The last search was successful - - UNKNOWN: Undocumented failure reason - - TIMEOUT: Timeout - - MEMOUT_WATERMAK: Search hit a memory high-watermak limit - - CANCELED: External cancel flag was set - - NUM_CONFLICTS: Maximum number of conflicts was reached - - THEORY: Theory is incomplete - - QUANTIFIERS: Logical context contains universal quantifiers -*) -(** - {!ast_print_mode} - Z3 pretty printing modes (See {!set_ast_print_mode}). - - - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. - - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. - - PRINT_SMTLIB_COMPLIANT: Print AST nodes in SMTLIB 1.x compliant format. - - PRINT_SMTLIB2_COMPLIANT: Print AST nodes in SMTLIB 2.x compliant format. -*) -(** - Definitions for update_api.py - def_Type('CONFIG', 'config', 'Config') - def_Type('CONTEXT', 'context', 'ContextObj') - def_Type('AST', 'ast', 'Ast') - def_Type('APP', 'app', 'Ast') - def_Type('SORT', 'sort', 'Sort') - def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') - def_Type('PATTERN', 'pattern', 'Pattern') - def_Type('MODEL', 'model', 'Model') - def_Type('LITERALS', 'literals', 'Literals') - def_Type('CONSTRUCTOR', 'constructor', 'Constructor') - def_Type('CONSTRUCTOR_LIST', 'constructor_list', 'ConstructorList') - def_Type('THEORY', 'theory', 'ctypes.c_void_p') - def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') - def_Type('SOLVER', 'solver', 'SolverObj') - def_Type('GOAL', 'goal', 'GoalObj') - def_Type('TACTIC', 'tactic', 'TacticObj') - def_Type('PARAMS', 'params', 'Params') - def_Type('PROBE', 'probe', 'ProbeObj') - def_Type('STATS', 'stats', 'StatsObj') - def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') - def_Type('AST_MAP', 'ast_map', 'AstMapObj') - def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') - def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') - def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') - def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') - def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') -*) -(** - {2 {L Configuration}} -*) -(** - Summary: Set a global (or module) parameter. - This setting is shared by all Z3 contexts. - When a Z3 module is initialized it will use the value of these parameters - when params objects are not provided. - The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - The character '.' is a delimiter (more later). - The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - This function can be used to set parameters for a specific Z3 module. - This can be done by using .. - For example: - global_param_set('pp.decimal', 'true') - will set the parameter "decimal" in the module "pp" to true. - def_API('global_param_set', VOID, (_in(STRING), _in(STRING))) -*) -external global_param_set : string -> string -> unit - = "camlidl_z3V3_Z3_global_param_set" - -(** - Summary: Restore the value of all global (and module) parameters. - This command will not affect already created objects (such as tactics and solvers). - - {b See also}: {!global_param_set} - def_API('global_param_reset_all', VOID, ()) -*) -external global_param_reset_all : unit -> unit - = "camlidl_z3V3_Z3_global_param_reset_all" - -(** - Summary: Get a global (or module) parameter. - Returns [None] - if the parameter value does not exist. - - {b See also}: {!global_param_set} - The caller must invoke {!global_param_del_value} to delete the value returned at [param_value]. - - {b Remarks}: This function cannot be invoked simultaneously from different threads without synchronization. - The result string stored in param_value is stored in shared location. - def_API('global_param_get', BOOL, (_in(STRING), _out(STRING))) -*) -external global_param_get : string -> string option - = "camlidl_z3V3_Z3_global_param_get" - -(** - {2 {L Create configuration}} -*) -(** - Summary: Create a configuration object for the Z3 context object. - Configurations are created in order to assign parameters prior to creating - contexts for Z3 interaction. For example, if the users wishes to use proof - generation, then call: - [set_param_value cfg "proof" "true"] - - {b Remarks}: Consider using {!mk_context_x} instead of using - explicit configuration objects. The function {!mk_context_x} - receives an array of string pairs. This array represents the - configuration options. - - {b Remarks}: In previous versions of Z3, the [config] was used to store - global and module configurations. Now, we should use [global_param_set]. - The following parameters can be set: - - proof (Boolean) Enable proof generation - - debug_ref_count (Boolean) Enable debug support for ast reference counting - - trace (Boolean) Tracing support for VCC - - trace_file_name (String) Trace out file for VCC traces - - timeout (unsigned) default timeout (in milliseconds) used for solvers - - well_sorted_check type checker - - auto_config use heuristics to automatically select solver and configure it - - model model generation for solvers, this parameter can be overwritten when creating a solver - - model_validate validate models produced by solvers - - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver - - {b See also}: {!set_param_value} - - {b See also}: {!del_config} - def_API('mk_config', CONFIG, ()) -*) -external mk_config : unit -> config - = "camlidl_z3V3_Z3_mk_config" - -(** - Summary: Delete the given configuration object. - - {b See also}: {!mk_config} - def_API('del_config', VOID, (_in(CONFIG),)) -*) -external del_config : config -> unit - = "camlidl_z3V3_Z3_del_config" - -(** - Summary: Set a configuration parameter. - The following parameters can be set for - - {b See also}: {!mk_config} - def_API('set_param_value', VOID, (_in(CONFIG), _in(STRING), _in(STRING))) -*) -external set_param_value : config -> string -> string -> unit - = "camlidl_z3V3_Z3_set_param_value" - -(** - {2 {L Create context}} -*) -(** - Summary: Create a context using the given configuration. - After a context is created, the configuration cannot be changed, - although some parameters can be changed using {!update_param_value}. - All main interaction with Z3 happens in the context of a [context]. - def_API('mk_context', CONTEXT, (_in(CONFIG),)) -*) -external mk_context : config -> context - = "camlidl_z3V3_Z3_mk_context" - -(** - Summary: Delete the given logical context. - - {b See also}: {!mk_context} - def_API('del_context', VOID, (_in(CONTEXT),)) -*) -external del_context : context -> unit - = "camlidl_z3V3_Z3_del_context" - -(** - Summary: Set a value of a context parameter. - - {b See also}: {!global_param_set} - def_API('update_param_value', VOID, (_in(CONTEXT), _in(STRING), _in(STRING))) -*) -external update_param_value : context -> string -> string -> unit - = "camlidl_z3V3_Z3_update_param_value" - -(** - Summary: Return the value of a context parameter. - - {b See also}: {!global_param_get} - def_API('get_param_value', BOOL, (_in(CONTEXT), _in(STRING), _out(STRING))) -*) -external get_param_value : context -> string -> string option - = "camlidl_z3V3_Z3_get_param_value" - -(** - {2 {L Symbols}} -*) -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a Z3 symbol using an integer. - Symbols are used to name several term and type constructors. - NB. Not all integers can be passed to this function. - The legal range of unsigned int integers is 0 to 2^30-1. - - {b See also}: {!mk_string_symbol} - def_API('mk_int_symbol', SYMBOL, (_in(CONTEXT), _in(INT))) -*) -external mk_int_symbol : context -> int -> symbol - = "camlidl_z3V3_Z3_mk_int_symbol" - -(** - Summary: Create a Z3 symbol using a C string. - Symbols are used to name several term and type constructors. - - {b See also}: {!mk_int_symbol} - def_API('mk_string_symbol', SYMBOL, (_in(CONTEXT), _in(STRING))) -*) -external mk_string_symbol : context -> string -> symbol - = "camlidl_z3V3_Z3_mk_string_symbol" - -(** - {2 {L Sorts}} -*) -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a free (uninterpreted) type using the given name (symbol). - Two free types are considered the same iff the have the same name. - def_API('mk_uninterpreted_sort', SORT, (_in(CONTEXT), _in(SYMBOL))) -*) -external mk_uninterpreted_sort : context -> symbol -> sort - = "camlidl_z3V3_Z3_mk_uninterpreted_sort" - -(** - Summary: Create the Boolean type. - This type is used to create propositional variables and predicates. - def_API('mk_bool_sort', SORT, (_in(CONTEXT), )) -*) -external mk_bool_sort : context -> sort - = "camlidl_z3V3_Z3_mk_bool_sort" - -(** - Summary: Create the integer type. - This type is not the int type found in programming languages. - A machine integer can be represented using bit-vectors. The function - {!mk_bv_sort} creates a bit-vector type. - - {b See also}: {!mk_bv_sort} - def_API('mk_int_sort', SORT, (_in(CONTEXT), )) -*) -external mk_int_sort : context -> sort - = "camlidl_z3V3_Z3_mk_int_sort" - -(** - Summary: Create the real type. - This type is not a floating point number. - Z3 does not have support for floating point numbers yet. - def_API('mk_real_sort', SORT, (_in(CONTEXT), )) -*) -external mk_real_sort : context -> sort - = "camlidl_z3V3_Z3_mk_real_sort" - -(** - Summary: Create a bit-vector type of the given size. - This type can also be seen as a machine integer. - - {b Remarks}: The size of the bitvector type must be greater than zero. - def_API('mk_bv_sort', SORT, (_in(CONTEXT), _in(UINT))) -*) -external mk_bv_sort : context -> int -> sort - = "camlidl_z3V3_Z3_mk_bv_sort" - -(** - Summary: Create a named finite domain sort. - To create constants that belong to the finite domain, - use the APIs for creating numerals and pass a numeric - constant together with the sort returned by this call. - - {b See also}: {!get_finite_domain_sort_size} - def_API('mk_finite_domain_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT64))) -*) -external mk_finite_domain_sort : context -> symbol -> int64 -> sort - = "camlidl_z3V3_Z3_mk_finite_domain_sort" - -(** - Summary: Create an array type. - We usually represent the array type as: {e [domain -> range] }. - Arrays are usually used to model the heap/memory in software verification. - - {b See also}: {!mk_select} - - {b See also}: {!mk_store} - def_API('mk_array_sort', SORT, (_in(CONTEXT), _in(SORT), _in(SORT))) -*) -external mk_array_sort : context -> sort -> sort -> sort - = "camlidl_z3V3_Z3_mk_array_sort" - -(** - Summary: Create a tuple type. - [mk_tuple_sort c name field_names field_sorts] creates a tuple with a constructor named [name], - a [n] fields, where [n] is the size of the arrays [field_names] and [field_sorts]. - @param c logical context - @param mk_tuple_name name of the constructor function associated with the tuple type. - @param num_fields number of fields in the tuple type. - @param field_names name of the projection functions. - @param field_sorts type of the tuple fields. - @param mk_tuple_decl output parameter that will contain the constructor declaration. - @param proj_decl output parameter that will contain the projection function declarations. This field must be a buffer of size [num_fields] allocated by the user. - def_API('mk_tuple_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array - = "camlidl_z3V3_Z3_mk_tuple_sort" - -(** - Summary: Create a enumeration sort. - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], - it also returns [n] predicates, where [n] is the number of [enums] corresponding - to testing whether an element is one of the enumerants. - @param c logical context - @param name name of the enumeration sort. - @param n number of elemenets in enumeration sort. - @param enum_names names of the enumerated elements. - @param enum_consts constants corresponding to the enumerated elements. - @param enum_testers predicates testing if terms of the enumeration sort correspond to an enumeration. - For example, if this function is called with three symbols A, B, C and the name S, then - [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in - [enum_consts]. The array [enum_testers] has three predicates of type {e (s -> Bool) }. - The first predicate (corresponding to A) is true when applied to A, and false otherwise. - Similarly for the other predicates. - def_API('mk_enumeration_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _out_array(2, FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array - = "camlidl_z3V3_Z3_mk_enumeration_sort" - -(** - Summary: Create a list sort - [mk_list_sort c name elem_sort] creates a list sort of [name], over elements of sort [elem_sort]. - @param c logical context - @param name name of the list sort. - @param elem_sort sort of list elements. - @param nil_decl declaration for the empty list. - @param is_nil_decl test for the empty list. - @param cons_decl declaration for a cons cell. - @param is_cons_decl cons cell test. - @param head_decl list head. - @param tail_decl list tail. - def_API('mk_list_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(SORT), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL))) -*) -external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl - = "camlidl_z3V3_Z3_mk_list_sort" - -(** - Summary: Create a constructor. - @param c logical context. - @param name constructor name. - @param recognizer name of recognizer function. - @param num_fields number of fields in constructor. - @param field_names names of the constructor fields. - @param sorts field sorts, [None] - if the field sort refers to a recursive sort. - @param sort_refs reference to datatype sort that is an argument to the constructor; if the corresponding - sort reference is [None], - then the value in sort_refs should be an index referring to - one of the recursive datatypes that is declared. - def_API('mk_constructor', CONSTRUCTOR, (_in(CONTEXT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(3, SYMBOL), _in_array(3, SORT), _in_array(3, UINT))) -*) -external mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - = "camlidl_z3V3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" - -(** - Summary: Reclaim memory allocated to constructor. - @param c logical context. - @param constr constructor. - def_API('del_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR))) -*) -external del_constructor : context -> constructor -> unit - = "camlidl_z3V3_Z3_del_constructor" - -(** - Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. - The datatype may be recursive. Return the datatype sort. - @param c logical context. - @param name name of datatype. - @param num_constructors number of constructors passed in. - @param constructors array of constructor containers. - def_API('mk_datatype', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _inout_array(2, CONSTRUCTOR))) -*) -external mk_datatype : context -> symbol -> constructor array -> sort * constructor array - = "camlidl_z3V3_Z3_mk_datatype" - -(** - Summary: Create list of constructors. - @param c logical context. - @param num_constructors number of constructors in list. - @param constructors list of constructors. - def_API('mk_constructor_list', CONSTRUCTOR_LIST, (_in(CONTEXT), _in(UINT), _in_array(1, CONSTRUCTOR))) -*) -external mk_constructor_list : context -> constructor array -> constructor_list - = "camlidl_z3V3_Z3_mk_constructor_list" - -(** - Summary: Reclaim memory allocated for constructor list. - Each constructor inside the constructor list must be independently reclaimed using {!del_constructor}. - @param c logical context. - @param clist constructor list container. - def_API('del_constructor_list', VOID, (_in(CONTEXT), _in(CONSTRUCTOR_LIST))) -*) -external del_constructor_list : context -> constructor_list -> unit - = "camlidl_z3V3_Z3_del_constructor_list" - -(** - Summary: Create mutually recursive datatypes. - @param c logical context. - @param num_sorts number of datatype sorts. - @param sort_names names of datatype sorts. - @param sorts array of datatype sorts. - @param constructor_lists list of constructors, one list per sort. - def_API('mk_datatypes', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, SYMBOL), _out_array(1, SORT), _inout_array(1, CONSTRUCTOR_LIST))) -*) -external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array - = "camlidl_z3V3_Z3_mk_datatypes" - -(** - Summary: Query constructor for declared functions. - @param c logical context. - @param constr constructor container. The container must have been passed in to a {!mk_datatype} call. - @param num_fields number of accessor fields in the constructor. - @param constructor constructor function declaration. - @param tester constructor test function declaration. - @param accessors array of accessor function declarations. - def_API('query_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR), _in(UINT), _out(FUNC_DECL), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) -*) -external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array - = "camlidl_z3V3_Z3_query_constructor" - -(** - {2 {L Constants and Applications}} -*) -(** - Summary: Declare a constant or function. - [mk_func_decl c n d r] creates a function with name [n], domain [d], and range [r]. - The arity of the function is the size of the array [d]. - @param c logical context. - @param s name of the constant or function. - @param domain_size number of arguments. It is 0 when declaring a constant. - @param domain array containing the sort of each argument. The array must contain domain_size elements. It is 0 when declaring a constant. - @param range sort of the constant or the return sort of the function. - After declaring a constant or function, the function - {!mk_app} can be used to create a constant or function - application. - - {b See also}: {!mk_app} - def_API('mk_func_decl', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) -*) -external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_func_decl" - -(** - Summary: Create a constant or function application. - - {b See also}: {!mk_func_decl} - def_API('mk_app', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) -*) -external mk_app : context -> func_decl -> ast array -> ast - = "camlidl_z3V3_Z3_mk_app" - -(** - Summary: Declare and create a constant. - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - - {b See also}: {!mk_func_decl} - - {b See also}: {!mk_app} - def_API('mk_const', AST, (_in(CONTEXT), _in(SYMBOL), _in(SORT))) -*) -external mk_const : context -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_mk_const" - -(** - Summary: Declare a fresh constant or function. - Z3 will generate an unique name for this function declaration. - - {b See also}: {!mk_func_decl} - def_API('mk_fresh_func_decl', FUNC_DECL, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SORT), _in(SORT))) -*) -external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_fresh_func_decl" - -(** - Summary: Declare and create a fresh constant. - [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - - {b See also}: {!mk_func_decl} - - {b See also}: {!mk_app} - def_API('mk_fresh_const', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) -*) -external mk_fresh_const : context -> string -> sort -> ast - = "camlidl_z3V3_Z3_mk_fresh_const" - -(** - {2 {L Propositional Logic and Equality}} -*) -(** - Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) -*) -external mk_true : context -> ast - = "camlidl_z3V3_Z3_mk_true" - -(** - Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) -*) -external mk_false : context -> ast - = "camlidl_z3V3_Z3_mk_false" - -(** - Summary: \[ [ mk_eq c l r ] \] - Create an AST node representing {e l = r }. - The nodes [l] and [r] must have the same type. - def_API('mk_eq', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_eq : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_eq" - -(** - Summary: \[ [mk_distinct c [| t_1; ...; t_n |]] \] Create an AST - node represeting a distinct construct. It is used for declaring - the arguments t_i pairwise distinct. - The [distinct] construct is used for declaring the arguments pairwise distinct. - That is, {e Forall 0 <= i < j < num_args. not args[i] = args[j] }. - All arguments must have the same sort. - - {b Remarks}: The number of arguments of a distinct construct must be greater than one. - def_API('mk_distinct', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_distinct : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_distinct" - -(** - Summary: \[ [ mk_not c a ] \] - Create an AST node representing {e not(a) }. - The node [a] must have Boolean sort. - def_API('mk_not', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_not : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_not" - -(** - Summary: \[ [ mk_ite c t1 t2 t2 ] \] - Create an AST node representing an if-then-else: {e ite(t1, t2, - t3) }. - The node [t1] must have Boolean sort, [t2] and [t3] must have the same sort. - The sort of the new node is equal to the sort of [t2] and [t3]. - def_API('mk_ite', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) -*) -external mk_ite : context -> ast -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ite" - -(** - Summary: \[ [ mk_iff c t1 t2 ] \] - Create an AST node representing {e t1 iff t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_iff', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_iff : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_iff" - -(** - Summary: \[ [ mk_implies c t1 t2 ] \] - Create an AST node representing {e t1 implies t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_implies', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_implies : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_implies" - -(** - Summary: \[ [ mk_xor c t1 t2 ] \] - Create an AST node representing {e t1 xor t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_xor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_xor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_xor" - -(** - Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. - All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_and', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_and : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_and" - -(** - Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. - All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_or', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_or : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_or" - -(** - {2 {L Arithmetic: Integers and Reals}} -*) -(** - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_add', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_add : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_add" - -(** - Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. - All arguments must have int or real sort. - - {b Remarks}: Z3 has limited support for non-linear arithmetic. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_mul', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_mul : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_mul" - -(** - Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. - All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_sub', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_sub : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_sub" - -(** - Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. - The arguments must have int or real type. - def_API('mk_unary_minus', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_unary_minus : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_unary_minus" - -(** - Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. - The arguments must either both have int type or both have real type. - If the arguments have int type, then the result type is an int type, otherwise the - the result type is real. - def_API('mk_div', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_div : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_div" - -(** - Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. - The arguments must have int type. - def_API('mk_mod', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_mod : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_mod" - -(** - Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. - The arguments must have int type. - def_API('mk_rem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_rem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_rem" - -(** - The arguments must have int or real type. - def_API('mk_power', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_power : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_power" - -(** - Summary: \[ [ mk_lt c t1 t2 ] \] - Create less than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_lt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_lt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_lt" - -(** - Summary: \[ [ mk_le c t1 t2 ] \] - Create less than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_le', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_le : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_le" - -(** - Summary: \[ [ mk_gt c t1 t2 ] \] - Create greater than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_gt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_gt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_gt" - -(** - Summary: \[ [ mk_ge c t1 t2 ] \] - Create greater than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_ge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ge" - -(** - Summary: \[ [ mk_int2real c t1 ] \] - Coerce an integer to a real. - There is also a converse operation exposed. - It follows the semantics prescribed by the SMT-LIB standard. - You can take the floor of a real by - creating an auxiliary integer constant [k] and - and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. - The node [t1] must have sort integer. - - {b See also}: {!mk_real2int} - - {b See also}: {!mk_is_int} - def_API('mk_int2real', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_int2real : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_int2real" - -(** - Summary: \[ [ mk_real2int c t1 ] \] - Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard - for the function to_int - - {b See also}: {!mk_int2real} - - {b See also}: {!mk_is_int} - def_API('mk_real2int', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_real2int : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_real2int" - -(** - Summary: \[ [ mk_is_int c t1 ] \] - Check if a real number is an integer. - - {b See also}: {!mk_int2real} - - {b See also}: {!mk_real2int} - def_API('mk_is_int', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_is_int : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_is_int" - -(** - {2 {L Bit-vectors}} -*) -(** - Summary: \[ [ mk_bvnot c t1 ] \] - Bitwise negation. - The node [t1] must have a bit-vector sort. - def_API('mk_bvnot', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvnot : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnot" - -(** - Summary: \[ [ mk_bvredand c t1 ] \] - Take conjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredand', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvredand : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvredand" - -(** - Summary: \[ [ mk_bvredor c t1 ] \] - Take disjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredor', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvredor : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvredor" - -(** - Summary: \[ [ mk_bvand c t1 t2 ] \] - Bitwise and. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvand', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvand : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvand" - -(** - Summary: \[ [ mk_bvor c t1 t2 ] \] - Bitwise or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvor" - -(** - Summary: \[ [ mk_bvxor c t1 t2 ] \] - Bitwise exclusive-or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvxor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvxor" - -(** - Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnand', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvnand : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnand" - -(** - Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvnor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvnor" - -(** - Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvxnor : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvxnor" - -(** - Summary: \[ [ mk_bvneg c t1 ] \] - Standard two's complement unary minus. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvneg : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvneg" - -(** - Summary: \[ [ mk_bvadd c t1 t2 ] \] - Standard two's complement addition. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvadd : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvadd" - -(** - Summary: \[ [ mk_bvsub c t1 t2 ] \] - Standard two's complement subtraction. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsub : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsub" - -(** - Summary: \[ [ mk_bvmul c t1 t2 ] \] - Standard two's complement multiplication. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvmul : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvmul" - -(** - Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - It is defined as the [floor] of {e t1/t2 } if [t2] is - different from zero. If {e t2 } is zero, then the result - is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvudiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvudiv : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvudiv" - -(** - Summary: \[ [ mk_bvsdiv c t1 t2 ] \] - Two's complement signed division. - It is defined in the following way: - - The [floor] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 >= 0 }. - - The [ceiling] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 < 0 }. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsdiv : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsdiv" - -(** - Summary: \[ [ mk_bvurem c t1 t2 ] \] - Unsigned remainder. - It is defined as {e t1 - (t1 /u t2) * t2 }, where {e /u } represents unsigned int division. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvurem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvurem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvurem" - -(** - Summary: \[ [ mk_bvsrem c t1 t2 ] \] - Two's complement signed remainder (sign follows dividend). - It is defined as {e t1 - (t1 /s t2) * t2 }, where {e /s } represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of [t1]. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsmod} - def_API('mk_bvsrem', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsrem : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsrem" - -(** - Summary: \[ [ mk_bvsmod c t1 t2 ] \] - Two's complement signed remainder (sign follows divisor). - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsrem} - def_API('mk_bvsmod', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsmod : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsmod" - -(** - Summary: \[ [ mk_bvult c t1 t2 ] \] - Unsigned less than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvult', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvult : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvult" - -(** - Summary: \[ [ mk_bvslt c t1 t2 ] \] - Two's complement signed less than. - It abbreviates: - {v - (or (and (= (extract[|m-1|:|m-1|] t1) bit1) - (= (extract[|m-1|:|m-1|] t2) bit0)) - (and (= (extract[|m-1|:|m-1|] t1) (extract[|m-1|:|m-1|] t2)) - (bvult t1 t2))) - v} - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvslt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvslt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvslt" - -(** - Summary: \[ [ mk_bvule c t1 t2 ] \] - Unsigned less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvule', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvule : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvule" - -(** - Summary: \[ [ mk_bvsle c t1 t2 ] \] - Two's complement signed less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsle', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsle : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsle" - -(** - Summary: \[ [ mk_bvuge c t1 t2 ] \] - Unsigned greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvuge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvuge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvuge" - -(** - Summary: \[ [ mk_bvsge c t1 t2 ] \] - Two's complement signed greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsge', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsge : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsge" - -(** - Summary: \[ [ mk_bvugt c t1 t2 ] \] - Unsigned greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvugt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvugt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvugt" - -(** - Summary: \[ [ mk_bvsgt c t1 t2 ] \] - Two's complement signed greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsgt', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsgt : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsgt" - -(** - Summary: \[ [ mk_concat c t1 t2 ] \] - Concatenate the given bit-vectors. - The nodes [t1] and [t2] must have (possibly different) bit-vector sorts - The result is a bit-vector of size {e n1+n2 }, where [n1] ([n2)] is the size - of [t1] ([t2)]. - def_API('mk_concat', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_concat : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_concat" - -(** - Summary: \[ [ mk_extract c high low t1 ] \] - Extract the bits [high] down to [low] from a bitvector of - size [m] to yield a new bitvector of size [n], where {e n = - high - low + 1 }. - The node [t1] must have a bit-vector sort. - def_API('mk_extract', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in(AST))) -*) -external mk_extract : context -> int -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_extract" - -(** - Summary: \[ [ mk_sign_ext c i t1 ] \] - Sign-extend of the given bit-vector to the (signed) equivalent bitvector of - size {e m+i }, where [m] is the size of the given - bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_sign_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_sign_ext : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_sign_ext" - -(** - Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size {e m+i }, where [m] is the size of the - given bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_zero_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_zero_ext : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_zero_ext" - -(** - Summary: \[ [ mk_repeat c i t1 ] \] - Repeat the given bit-vector up length {e i }. - The node [t1] must have a bit-vector sort. - def_API('mk_repeat', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_repeat : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_repeat" - -(** - Summary: \[ [ mk_bvshl c t1 t2 ] \] - Shift left. - It is equivalent to multiplication by {e 2^x } where [x] is the value of the - third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvshl', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvshl : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvshl" - -(** - Summary: \[ [ mk_bvlshr c t1 t2 ] \] - Logical shift right. - It is equivalent to unsigned int division by {e 2^x } where [x] is the - value of the third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvlshr', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvlshr : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvlshr" - -(** - Summary: \[ [ mk_bvashr c t1 t2 ] \] - Arithmetic shift right. - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvashr', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvashr : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvashr" - -(** - Summary: \[ [ mk_rotate_left c i t1 ] \] - Rotate bits of [t1] to the left [i] times. - The node [t1] must have a bit-vector sort. - def_API('mk_rotate_left', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_rotate_left : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_rotate_left" - -(** - Summary: \[ [ mk_rotate_right c i t1 ] \] - Rotate bits of [t1] to the right [i] times. - The node [t1] must have a bit-vector sort. - def_API('mk_rotate_right', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_rotate_right : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_rotate_right" - -(** - Summary: \[ [ mk_ext_rotate_left c t1 t2 ] \] - Rotate bits of [t1] to the left [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_left', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ext_rotate_left : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ext_rotate_left" - -(** - Summary: \[ [ mk_ext_rotate_right c t1 t2 ] \] - Rotate bits of [t1] to the right [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_right', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_ext_rotate_right : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_ext_rotate_right" - -(** - Summary: \[ [ mk_int2bv c n t1 ] \] - Create an [n] bit bit-vector from the integer argument [t1]. - NB. This function is essentially treated as uninterpreted. + (** Create an n-bit bit-vector from an integer argument. + + + NB. This function is essentially treated as uninterpreted. So you cannot expect Z3 to precisely reflect the semantics of this function when solving constraints with this function. - The node [t1] must have integer sort. - def_API('mk_int2bv', AST, (_in(CONTEXT), _in(UINT), _in(AST))) -*) -external mk_int2bv : context -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_int2bv" - -(** - Summary: \[ [ mk_bv2int c t1 is_signed ] \] - Create an integer from the bit-vector argument [t1]. - If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. - So the result is non-negative - and in the range {e [0..2^N-1] }, where N are the number of bits in [t1]. - If [is_signed] is true, [t1] is treated as a signed bit-vector. - This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - The node [t1] must have a bit-vector sort. - def_API('mk_bv2int', AST, (_in(CONTEXT), _in(AST), _in(BOOL))) -*) -external mk_bv2int : context -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bv2int" - -(** - Summary: \[ [ mk_bvadd_no_overflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise addition - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvadd_no_overflow" - -(** - Summary: \[ [ mk_bvadd_no_underflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed addition - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvadd_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvadd_no_underflow" - -(** - Summary: \[ [ mk_bvsub_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed subtraction - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsub_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsub_no_overflow" - -(** - Summary: \[ [ mk_bvsub_no_underflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise subtraction - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvsub_no_underflow" - -(** - Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvsdiv_no_overflow" - -(** - Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when - [t1] is interpreted as a signed bit-vector. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg_no_overflow', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_bvneg_no_overflow : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvneg_no_overflow" - -(** - Summary: \[ [ mk_bvmul_no_overflow c t1 t2 is_signed ] \] - Create a predicate that checks that the bit-wise multiplication - of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) -*) -external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast - = "camlidl_z3V3_Z3_mk_bvmul_no_overflow" - -(** - Summary: \[ [ mk_bvmul_no_underflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed multiplication - of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_bvmul_no_underflow : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_bvmul_no_underflow" + + The argument must be of integer sort. *) + val mk_int2bv : context -> int -> Expr.expr -> Expr.expr + end + + (** Real Arithmetic *) + module Real : + sig + (** Create a real sort. *) + val mk_sort : context -> Sort.sort + + (** The numerator of a rational numeral. *) + val get_numerator : Expr.expr-> Expr.expr + + (** The denominator of a rational numeral. *) + val get_denominator : Expr.expr-> Expr.expr + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as indicated by the int argument.*) + val to_decimal_string : Expr.expr-> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : Expr.expr-> string + + (** Creates a real constant. *) + val mk_const : context -> Symbol.symbol -> Expr.expr -(** - {2 {L Arrays}} -*) -(** - Summary: \[ [ mk_select c a i ] \] - Array read. - The argument [a] is the array and [i] is the index of the array that gets read. - The node [a] must have an array sort {e [domain -> range] }, - and [i] must have the sort [domain]. - The sort of the result is [range]. - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_store} - def_API('mk_select', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_select : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_select" - -(** - Summary: \[ [ mk_store c a i v ] \] - Array update. - The node [a] must have an array sort {e [domain -> range] }, [i] must have sort [domain], - [v] must have sort range. The sort of the result is {e [domain -> range] }. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to [a] (with respect to [select)] - on all indices except for [i], where it maps to [v] (and the [select] of [a] with - respect to [i] may be a different value). - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_select} - def_API('mk_store', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) -*) -external mk_store : context -> ast -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_store" - -(** - Summary: Create the constant array. - The resulting term is an array, such that a [select] on an arbitrary index - produces the value [v]. - @param c logical context. - @param domain domain sort for the array. - @param v value that the array maps to. - def_API('mk_const_array', AST, (_in(CONTEXT), _in(SORT), _in(AST))) -*) -external mk_const_array : context -> sort -> ast -> ast - = "camlidl_z3V3_Z3_mk_const_array" - -(** - Summary: \[ [ mk_map f n args ] \] - map f on the the argument arrays. - The [n] nodes [args] must be of array sorts {e [domain_i -> range_i] }. - The function declaration [f] must have type {e range_1 .. range_n -> range }. - [v] must have sort range. The sort of the result is {e [domain_i -> range] }. - - {b See also}: {!mk_array_sort} - - {b See also}: {!mk_store} - - {b See also}: {!mk_select} - def_API('mk_map', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) -*) -external mk_map : context -> func_decl -> int -> ast -> ast - = "camlidl_z3V3_Z3_mk_map" - -(** - Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - @param c logical context. - @param array array value whose default range value is accessed. - def_API('mk_array_default', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_array_default : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_array_default" + (** Creates a real constant. *) + val mk_const_s : context -> string -> Expr.expr -(** - {2 {L Sets}} -*) -(** - Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) -*) -external mk_set_sort : context -> sort -> sort - = "camlidl_z3V3_Z3_mk_set_sort" + (** Create a real numeral from a fraction. + @return A Term with rational value and sort Real + {!mk_numeral_s} *) + val mk_numeral_nd : context -> int -> int -> Expr.expr -(** - Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) -*) -external mk_empty_set : context -> sort -> ast - = "camlidl_z3V3_Z3_mk_empty_set" + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_s : context -> string -> Expr.expr -(** - Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) -*) -external mk_full_set : context -> sort -> ast - = "camlidl_z3V3_Z3_mk_full_set" + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_i : context -> int -> Expr.expr -(** - Summary: Add an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_add', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_add : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_add" + (** Creates an expression that checks whether a real number is an integer. *) + val mk_is_integer : context -> Expr.expr -> Expr.expr -(** - Summary: Remove an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_del', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_del : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_del" + (** Coerce a real to an integer. -(** - Summary: Take the union of a list of sets. - def_API('mk_set_union', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_set_union : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_set_union" + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) + val mk_real2int : context -> Expr.expr -> Expr.expr + + (** Algebraic Numbers *) + module AlgebraicNumber : + sig + (** Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_upper : Expr.expr -> int -> Expr.expr + + (** Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_lower : Expr.expr -> int -> Expr.expr + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as the int argument provided.*) + val to_decimal_string : Expr.expr -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : Expr.expr -> string + end + end -(** - Summary: Take the intersection of a list of sets. - def_API('mk_set_intersect', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_set_intersect : context -> ast array -> ast - = "camlidl_z3V3_Z3_mk_set_intersect" + (** Indicates whether the term is of integer sort. *) + val is_int : Expr.expr -> bool -(** - Summary: Take the set difference between two sets. - def_API('mk_set_difference', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_difference : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_difference" + (** Indicates whether the term is an arithmetic numeral. *) + val is_arithmetic_numeral : Expr.expr -> bool -(** - Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) -*) -external mk_set_complement : context -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_complement" + (** Indicates whether the term is a less-than-or-equal *) + val is_le : Expr.expr -> bool -(** - Summary: Check for set membership. - The first argument should be an element type of the set. - def_API('mk_set_member', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_member : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_member" + (** Indicates whether the term is a greater-than-or-equal *) + val is_ge : Expr.expr -> bool -(** - Summary: Check for subsetness of sets. - def_API('mk_set_subset', AST, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external mk_set_subset : context -> ast -> ast -> ast - = "camlidl_z3V3_Z3_mk_set_subset" + (** Indicates whether the term is a less-than *) + val is_lt : Expr.expr -> bool -(** - {2 {L Numerals}} -*) -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Create a numeral of a given sort. - @param c logical context. - @param numeral A string representing the numeral value in decimal notation. If the given sort is a real, then the numeral can be a rational, that is, a string of the form {e [num]* / [num]* }. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - - {b See also}: {!mk_int} - def_API('mk_numeral', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) -*) -external mk_numeral : context -> string -> sort -> ast - = "camlidl_z3V3_Z3_mk_numeral" - -(** - Summary: Create a real from a fraction. - @param c logical context. - @param num numerator of rational. - @param den denomerator of rational. - - {b Precondition}: den != 0 - - {b See also}: {!mk_numeral} - - {b See also}: {!mk_int} - def_API('mk_real', AST, (_in(CONTEXT), _in(INT), _in(INT))) -*) -external mk_real : context -> int -> int -> ast - = "camlidl_z3V3_Z3_mk_real" - -(** - Summary: Create a numeral of an int, bit-vector, or finite-domain sort. - This function can be use to create numerals that fit in a machine integer. - It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int', AST, (_in(CONTEXT), _in(INT), _in(SORT))) -*) -external mk_int : context -> int -> sort -> ast - = "camlidl_z3V3_Z3_mk_int" - -(** - Summary: Create a numeral of a int, bit-vector, or finite-domain sort. - This function can be use to create numerals that fit in a machine long long integer. - It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int64', AST, (_in(CONTEXT), _in(INT64), _in(SORT))) -*) -external mk_int64 : context -> int64 -> sort -> ast - = "camlidl_z3V3_Z3_mk_int64" + (** Indicates whether the term is a greater-than *) + val is_gt : Expr.expr -> bool -(** - {2 {L Quantifiers}} -*) -(** - Summary: Create a pattern for quantifier instantiation. - Z3 uses pattern matching to instantiate quantifiers. If a - pattern is not provided for a quantifier, then Z3 will - automatically compute a set of patterns for it. However, for - optimal performance, the user should provide the patterns. - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - a called a multi-pattern. - In general, one can pass in a list of (multi-)patterns in the - quantifier constructor. - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_pattern', PATTERN, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) -*) -external mk_pattern : context -> ast array -> pattern - = "camlidl_z3V3_Z3_mk_pattern" - -(** - Summary: Create a bound variable. - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - {v - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - v} - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper x appears, the higher is its - index. - @param c logical context - @param index de-Bruijn index - @param ty sort of the bound variable - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_bound', AST, (_in(CONTEXT), _in(UINT), _in(SORT))) -*) -external mk_bound : context -> int -> sort -> ast - = "camlidl_z3V3_Z3_mk_bound" - -(** - Summary: Create a forall formula. It takes an expression [body] that contains bound variables - of the same sorts as the sorts listed in the array [sorts]. The bound variables are de-Bruijn indices created - using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the - bound variables. Z3 applies the convention that the last element in the [decl_names] and [sorts] array - refers to the variable with index 0, the second to last element of [decl_names] and [sorts] refers - to the variable with index 1, etc. - [mk_forall c w p t n b] creates a forall formula, where - [w] is the weight, [p] is an array of patterns, [t] is an array - with the sorts of the bound variables, [n] is an array with the - 'names' of the bound variables, and [b] is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during - instantiation. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_decls number of variables to be bound. - @param sorts the sorts of the bound variables. - @param decl_names names of the bound variables - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_exists} - def_API('mk_forall', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) -*) -external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" - -(** - Summary: Create an exists formula. Similar to {!mk_forall}. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_quantifier} - def_API('mk_exists', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) -*) -external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" - -(** - Summary: Create a quantifier - universal or existential, with pattern hints. - See the documentation for {!mk_forall} for an explanation of the parameters. - @param c logical context. - @param is_forall flag to indicate if this is a universal or existential quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_decls number of variables to be bound. - @param sorts array of sorts of the bound variables. - @param decl_names names of the bound variables. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_quantifier', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, PATTERN), _in(UINT), _in_array(5, SORT), _in_array(5, SYMBOL), _in(AST))) -*) -external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" - -(** - Summary: Create a quantifier - universal or existential, with pattern hints, no patterns, and attributes - @param c logical context. - @param is_forall flag to indicate if this is a universal or existential quantifier. - @param quantifier_id identifier to identify quantifier - @param skolem_id identifier to identify skolem constants introduced by quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param num_no_patterns number of no_patterns. - @param no_patterns array containing subexpressions to be excluded from inferred patterns. - @param num_decls number of variables to be bound. - @param sorts array of sorts of the bound variables. - @param decl_names names of the bound variables. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_bound} - - {b See also}: {!mk_forall} - - {b See also}: {!mk_exists} - def_API('mk_quantifier_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, PATTERN), _in(UINT), _in_array(7, AST), _in(UINT), _in_array(9, SORT), _in_array(9, SYMBOL), _in(AST))) -*) -external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" - -(** - Summary: Create a universal quantifier using a list of constants that - will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using - the quantifier during instantiation. By default, pass the weight 0. - @param num_bound number of constants to be abstracted into bound variables. - @param bound array of constants to be abstracted into bound variables. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_exists_const} - def_API('mk_forall_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) -*) -external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_forall_const" - -(** - Summary: Similar to {!mk_forall_const}. - Summary: Create an existential quantifier using a list of constants that - will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using - the quantifier during instantiation. By default, pass the weight 0. - @param num_bound number of constants to be abstracted into bound variables. - @param bound array of constants to be abstracted into bound variables. - @param num_patterns number of patterns. - @param patterns array containing the patterns created using {!mk_pattern}. - @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - - {b See also}: {!mk_forall_const} - def_API('mk_exists_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) -*) -external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_exists_const" - -(** - Summary: Create a universal or existential - quantifier using a list of constants that - will form the set of bound variables. - def_API('mk_quantifier_const', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, APP), _in(UINT), _in_array(5, PATTERN), _in(AST))) -*) -external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" - -(** - Summary: Create a universal or existential - quantifier using a list of constants that - will form the set of bound variables. - def_API('mk_quantifier_const_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, APP), _in(UINT), _in_array(7, PATTERN), _in(UINT), _in_array(9, AST), _in(AST))) -*) -external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" + (** Indicates whether the term is addition (binary) *) + val is_add : Expr.expr -> bool -(** - {2 {L Accessors}} -*) -(** - {3 {L Symbols}} -*) -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Return [INT_SYMBOL] if the symbol was constructed - using {!mk_int_symbol}, and [STRING_SYMBOL] if the symbol - was constructed using {!mk_string_symbol}. - def_API('get_symbol_kind', UINT, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_kind : context -> symbol -> symbol_kind - = "camlidl_z3V3_Z3_get_symbol_kind" - -(** - Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - - {b Precondition}: get_symbol_kind s == INT_SYMBOL - - {b See also}: {!mk_int_symbol} - def_API('get_symbol_int', INT, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_int : context -> symbol -> int - = "camlidl_z3V3_Z3_get_symbol_int" - -(** - Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - - {b Precondition}: get_symbol_string s == STRING_SYMBOL - - {b See also}: {!mk_string_symbol} - def_API('get_symbol_string', STRING, (_in(CONTEXT), _in(SYMBOL))) -*) -external get_symbol_string : context -> symbol -> string - = "camlidl_z3V3_Z3_get_symbol_string" + (** Indicates whether the term is subtraction (binary) *) + val is_sub : Expr.expr -> bool -(** - {3 {L Sorts}} -*) -(** - Summary: Return the sort name as a symbol. - def_API('get_sort_name', SYMBOL, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_name : context -> sort -> symbol - = "camlidl_z3V3_Z3_get_sort_name" + (** Indicates whether the term is a unary minus *) + val is_uminus : Expr.expr -> bool -(** - Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - def_API('get_sort_id', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_id : context -> sort -> int - = "camlidl_z3V3_Z3_get_sort_id" + (** Indicates whether the term is multiplication (binary) *) + val is_mul : Expr.expr -> bool -(** - {4 {L Redundant low-level API}} -*) -(** - Summary: Convert a [sort] into [ast]. - - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. - def_API('sort_to_ast', AST, (_in(CONTEXT), _in(SORT))) -*) -external sort_to_ast : context -> sort -> ast - = "camlidl_z3V3_Z3_sort_to_ast" + (** Indicates whether the term is division (binary) *) + val is_div : Expr.expr -> bool -(** - Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_sort', BOOL, (_in(CONTEXT), _in(SORT), _in(SORT))) -*) -external is_eq_sort : context -> sort -> sort -> bool - = "camlidl_z3V3_Z3_is_eq_sort" + (** Indicates whether the term is integer division (binary) *) + val is_idiv : Expr.expr -> bool -(** - Summary: Return the sort kind (e.g., array, tuple, int, bool, etc). - - {b See also}: {!sort_kind} - def_API('get_sort_kind', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_sort_kind : context -> sort -> sort_kind - = "camlidl_z3V3_Z3_get_sort_kind" - -(** - Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - - {b Precondition}: get_sort_kind c t == BV_SORT - - {b See also}: {!mk_bv_sort} - - {b See also}: {!get_sort_kind} - def_API('get_bv_sort_size', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_bv_sort_size : context -> sort -> int - = "camlidl_z3V3_Z3_get_bv_sort_size" + (** Indicates whether the term is remainder (binary) *) + val is_remainder : Expr.expr -> bool -(** - Summary: Return the size of the sort in [r]. Return [None] if the call failed. - That is, get_sort_kind(s) == FINITE_DOMAIN_SORT - def_API('get_finite_domain_sort_size', BOOL, (_in(CONTEXT), _in(SORT), _out(UINT64))) -*) -external get_finite_domain_sort_size : context -> sort -> int64 option - = "camlidl_z3V3_Z3_get_finite_domain_sort_size" - -(** - Summary: \[ [ get_array_sort_domain c t ] \] - Return the domain of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - - {b See also}: {!get_sort_kind} - def_API('get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT))) -*) -external get_array_sort_domain : context -> sort -> sort - = "camlidl_z3V3_Z3_get_array_sort_domain" - -(** - Summary: \[ [ get_array_sort_range c t ] \] - Return the range of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - - {b See also}: {!get_sort_kind} - def_API('get_array_sort_range', SORT, (_in(CONTEXT), _in(SORT))) -*) -external get_array_sort_range : context -> sort -> sort - = "camlidl_z3V3_Z3_get_array_sort_range" - -(** - Summary: \[ [ get_tuple_sort_mk_decl c t ] \] - Return the constructor declaration of the given tuple - sort. - - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_mk_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT))) -*) -external get_tuple_sort_mk_decl : context -> sort -> func_decl - = "camlidl_z3V3_Z3_get_tuple_sort_mk_decl" - -(** - Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_num_fields', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_tuple_sort_num_fields : context -> sort -> int - = "camlidl_z3V3_Z3_get_tuple_sort_num_fields" - -(** - Summary: \[ [ get_tuple_sort_field_decl c t i ] \] - Return the i-th field declaration (i.e., projection function declaration) - of the given tuple sort. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: i < get_tuple_sort_num_fields c t - - {b See also}: {!mk_tuple_sort} - - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_field_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_tuple_sort_field_decl : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_tuple_sort_field_decl" - -(** - Summary: Return number of constructors for datatype. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_num_constructors', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_datatype_sort_num_constructors : context -> sort -> int - = "camlidl_z3V3_Z3_get_datatype_sort_num_constructors" - -(** - Summary: Return idx'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_constructor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_datatype_sort_constructor : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_constructor" - -(** - Summary: Return idx'th recognizer. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_recognizer', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_datatype_sort_recognizer : context -> sort -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_recognizer" - -(** - Summary: Return idx_a'th accessor for the idx_c'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b Precondition}: idx_c < get_datatype_sort_num_constructors c t - - {b Precondition}: idx_a < get_domain_size c get_datatype_sort_constructor c idx_c - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - def_API('get_datatype_sort_constructor_accessor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT), _in(UINT))) -*) -external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl - = "camlidl_z3V3_Z3_get_datatype_sort_constructor_accessor" - -(** - Summary: Return arity of relation. - - {b Precondition}: get_sort_kind s == RELATION_SORT - - {b See also}: {!get_relation_column} - def_API('get_relation_arity', UINT, (_in(CONTEXT), _in(SORT))) -*) -external get_relation_arity : context -> sort -> int - = "camlidl_z3V3_Z3_get_relation_arity" - -(** - Summary: Return sort at i'th column of relation sort. - - {b Precondition}: get_sort_kind c s == RELATION_SORT - - {b Precondition}: col < get_relation_arity c s - - {b See also}: {!get_relation_arity} - def_API('get_relation_column', SORT, (_in(CONTEXT), _in(SORT), _in(UINT))) -*) -external get_relation_column : context -> sort -> int -> sort - = "camlidl_z3V3_Z3_get_relation_column" + (** Indicates whether the term is modulus (binary) *) + val is_modulus : Expr.expr -> bool -(** - {3 {L Function Declarations}} -*) -(** - Summary: Convert a [func_decl] into [ast]. - - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. - def_API('func_decl_to_ast', AST, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external func_decl_to_ast : context -> func_decl -> ast - = "camlidl_z3V3_Z3_func_decl_to_ast" + (** Indicates whether the term is a coercion of integer to real (unary) *) + val is_inttoreal : Expr.expr -> bool -(** - Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_func_decl', BOOL, (_in(CONTEXT), _in(FUNC_DECL), _in(FUNC_DECL))) -*) -external is_eq_func_decl : context -> func_decl -> func_decl -> bool - = "camlidl_z3V3_Z3_is_eq_func_decl" + (** Indicates whether the term is a coercion of real to integer (unary) *) + val is_real_to_int : Expr.expr -> bool -(** - Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - def_API('get_func_decl_id', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_func_decl_id : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_func_decl_id" + (** Indicates whether the term is a check that tests whether a real is integral (unary) *) + val is_real_is_int : Expr.expr -> bool -(** - Summary: Return the constant declaration name as a symbol. - def_API('get_decl_name', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_name : context -> func_decl -> symbol - = "camlidl_z3V3_Z3_get_decl_name" + (** Indicates whether the term is of sort real. *) + val is_real : Expr.expr -> bool -(** - Summary: Return declaration kind corresponding to declaration. - def_API('get_decl_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_kind : context -> func_decl -> decl_kind - = "camlidl_z3V3_Z3_get_decl_kind" + (** Indicates whether the term is an integer numeral. *) + val is_int_numeral : Expr.expr -> bool -(** - Summary: Return the number of parameters of the given declaration. - - {b See also}: {!get_arity} - def_API('get_domain_size', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_domain_size : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_domain_size" + (** Indicates whether the term is a real numeral. *) + val is_rat_num : Expr.expr -> bool -(** - Summary: Alias for [get_domain_size]. - - {b See also}: {!get_domain_size} - def_API('get_arity', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_arity : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_arity" - -(** - Summary: \[ [ get_domain c d i ] \] - Return the sort of the i-th parameter of the given function declaration. - - {b Precondition}: i < get_domain_size d - - {b See also}: {!get_domain_size} - def_API('get_domain', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_domain : context -> func_decl -> int -> sort - = "camlidl_z3V3_Z3_get_domain" - -(** - Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - If [d] is a constant (i.e., has zero arguments), then this - function returns the sort of the constant. - def_API('get_range', SORT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_range : context -> func_decl -> sort - = "camlidl_z3V3_Z3_get_range" + (** Indicates whether the term is an algebraic number *) + val is_algebraic_number : Expr.expr -> bool -(** - Summary: Return the number of parameters associated with a declaration. - def_API('get_decl_num_parameters', UINT, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external get_decl_num_parameters : context -> func_decl -> int - = "camlidl_z3V3_Z3_get_decl_num_parameters" - -(** - Summary: Return the parameter type associated with a declaration. - @param c the context - @param d the function declaration - @param idx is the index of the named parameter it should be between 0 and the number of parameters. - def_API('get_decl_parameter_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind - = "camlidl_z3V3_Z3_get_decl_parameter_kind" + (** Create an expression representing t[0] + t[1] + .... *) + val mk_add : context -> Expr.expr list -> Expr.expr -(** - Summary: Return the integer value associated with an integer parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_INT - def_API('get_decl_int_parameter', INT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_int_parameter : context -> func_decl -> int -> int - = "camlidl_z3V3_Z3_get_decl_int_parameter" + (** Create an expression representing t[0] * t[1] * .... *) + val mk_mul : context -> Expr.expr list -> Expr.expr -(** - Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_DOUBLE - def_API('get_decl_double_parameter', DOUBLE, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_double_parameter : context -> func_decl -> int -> float - = "camlidl_z3V3_Z3_get_decl_double_parameter" + (** Create an expression representing t[0] - t[1] - .... *) + val mk_sub : context -> Expr.expr list -> Expr.expr -(** - Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SYMBOL - def_API('get_decl_symbol_parameter', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_symbol_parameter : context -> func_decl -> int -> symbol - = "camlidl_z3V3_Z3_get_decl_symbol_parameter" + (** Create an expression representing -t. *) + val mk_unary_minus : context -> Expr.expr -> Expr.expr -(** - Summary: Return the sort value associated with a sort parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SORT - def_API('get_decl_sort_parameter', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_sort_parameter : context -> func_decl -> int -> sort - = "camlidl_z3V3_Z3_get_decl_sort_parameter" + (** Create an expression representing t1 / t2. *) + val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_AST - def_API('get_decl_ast_parameter', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_ast_parameter : context -> func_decl -> int -> ast - = "camlidl_z3V3_Z3_get_decl_ast_parameter" + (** Create an expression representing t1 ^ t2. *) + val mk_power : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_FUNC_DECL - def_API('get_decl_func_decl_parameter', FUNC_DECL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl - = "camlidl_z3V3_Z3_get_decl_func_decl_parameter" + (** Create an expression representing t1 < t2 *) + val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Return the rational value, as a string, associated with a rational parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_RATIONAL - def_API('get_decl_rational_parameter', STRING, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) -*) -external get_decl_rational_parameter : context -> func_decl -> int -> string - = "camlidl_z3V3_Z3_get_decl_rational_parameter" + (** Create an expression representing t1 <= t2 *) + val mk_le : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - {3 {L Applications}} -*) -(** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - def_API('app_to_ast', AST, (_in(CONTEXT), _in(APP))) -*) -external app_to_ast : context -> app -> ast - = "camlidl_z3V3_Z3_app_to_ast" + (** Create an expression representing t1 > t2 *) + val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr -(** - Summary: Return the declaration of a constant or function application. - def_API('get_app_decl', FUNC_DECL, (_in(CONTEXT), _in(APP))) -*) -external get_app_decl : context -> app -> func_decl - = "camlidl_z3V3_Z3_get_app_decl" - -(** - Summary: \[ [ get_app_num_args c a ] \] - Return the number of argument of an application. If [t] - is an constant, then the number of arguments is 0. - def_API('get_app_num_args', UINT, (_in(CONTEXT), _in(APP))) -*) -external get_app_num_args : context -> app -> int - = "camlidl_z3V3_Z3_get_app_num_args" - -(** - Summary: \[ [ get_app_arg c a i ] \] - Return the i-th argument of the given application. - - {b Precondition}: i < get_num_args c a - def_API('get_app_arg', AST, (_in(CONTEXT), _in(APP), _in(UINT))) -*) -external get_app_arg : context -> app -> int -> ast - = "camlidl_z3V3_Z3_get_app_arg" + (** Create an expression representing t1 >= t2 *) + val mk_ge : context -> Expr.expr -> Expr.expr -> Expr.expr +end -(** - {3 {L Terms}} -*) -(** - Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - def_API('is_eq_ast', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) -*) -external is_eq_ast : context -> ast -> ast -> bool - = "camlidl_z3V3_Z3_is_eq_ast" +(** Functions to manipulate bit-vector expressions *) +module BitVector : +sig + (** Create a new bit-vector sort. *) + val mk_sort : context -> int -> Sort.sort -(** - Summary: Return a unique identifier for [t]. - - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - def_API('get_ast_id', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_id : context -> ast -> int - = "camlidl_z3V3_Z3_get_ast_id" + (** Indicates whether the terms is of bit-vector sort. *) + val is_bv : Expr.expr -> bool -(** - Summary: Return a hash code for the given AST. - - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - def_API('get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_hash : context -> ast -> int - = "camlidl_z3V3_Z3_get_ast_hash" + (** Indicates whether the term is a bit-vector numeral *) + val is_bv_numeral : Expr.expr -> bool -(** - Summary: Return the sort of an AST node. - The AST node must be a constant, application, numeral, bound variable, or quantifier. - def_API('get_sort', SORT, (_in(CONTEXT), _in(AST))) -*) -external get_sort : context -> ast -> sort - = "camlidl_z3V3_Z3_get_sort" + (** Indicates whether the term is a one-bit bit-vector with value one *) + val is_bv_bit1 : Expr.expr -> bool -(** - Summary: Return true if the given expression [t] is well sorted. - def_API('is_well_sorted', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_well_sorted : context -> ast -> bool - = "camlidl_z3V3_Z3_is_well_sorted" + (** Indicates whether the term is a one-bit bit-vector with value zero *) + val is_bv_bit0 : Expr.expr -> bool -(** - Summary: Return L_TRUE if [a] is true, L_FALSE if it is false, and L_UNDEF otherwise. - def_API('get_bool_value', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_bool_value : context -> ast -> lbool - = "camlidl_z3V3_Z3_get_bool_value" + (** Indicates whether the term is a bit-vector unary minus *) + val is_bv_uminus : Expr.expr -> bool -(** - Summary: Return the kind of the given AST. - def_API('get_ast_kind', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_ast_kind : context -> ast -> ast_kind - = "camlidl_z3V3_Z3_get_ast_kind" + (** Indicates whether the term is a bit-vector addition (binary) *) + val is_bv_add : Expr.expr -> bool -(** - def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_app : context -> ast -> bool - = "camlidl_z3V3_Z3_is_app" + (** Indicates whether the term is a bit-vector subtraction (binary) *) + val is_bv_sub : Expr.expr -> bool -(** - def_API('is_numeral_ast', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_numeral_ast : context -> ast -> bool - = "camlidl_z3V3_Z3_is_numeral_ast" + (** Indicates whether the term is a bit-vector multiplication (binary) *) + val is_bv_mul : Expr.expr -> bool -(** - Summary: Return true if the give AST is a real algebraic number. - def_API('is_algebraic_number', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_algebraic_number : context -> ast -> bool - = "camlidl_z3V3_Z3_is_algebraic_number" + (** Indicates whether the term is a bit-vector signed division (binary) *) + val is_bv_sdiv : Expr.expr -> bool -(** - Summary: Convert an [ast] into an [APP_AST]. - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - def_API('to_app', APP, (_in(CONTEXT), _in(AST))) -*) -external to_app : context -> ast -> app - = "camlidl_z3V3_Z3_to_app" + (** Indicates whether the term is a bit-vector unsigned division (binary) *) + val is_bv_udiv : Expr.expr -> bool -(** - Summary: Convert an AST into a FUNC_DECL_AST. This is just type casting. - - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} - def_API('to_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) -*) -external to_func_decl : context -> ast -> func_decl - = "camlidl_z3V3_Z3_to_func_decl" + (** Indicates whether the term is a bit-vector signed remainder (binary) *) + val is_bv_SRem : Expr.expr -> bool -(** - {4 {L Numerals}} -*) -(** - {5 {L Low-level API}} -*) -(** - Summary: Return numeral value, as a string of a numeric constant term - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numeral_string', STRING, (_in(CONTEXT), _in(AST))) -*) -external get_numeral_string : context -> ast -> string - = "camlidl_z3V3_Z3_get_numeral_string" - -(** - Summary: Return numeral as a string in decimal notation. - The result has at most [precision] decimal places. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST || is_algebraic_number c a - def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_numeral_decimal_string : context -> ast -> int -> string - = "camlidl_z3V3_Z3_get_numeral_decimal_string" + (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) + val is_bv_urem : Expr.expr -> bool -(** - Summary: Return the numerator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numerator', AST, (_in(CONTEXT), _in(AST))) -*) -external get_numerator : context -> ast -> ast - = "camlidl_z3V3_Z3_get_numerator" + (** Indicates whether the term is a bit-vector signed modulus *) + val is_bv_smod : Expr.expr -> bool -(** - Summary: Return the denominator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_denominator', AST, (_in(CONTEXT), _in(AST))) -*) -external get_denominator : context -> ast -> ast - = "camlidl_z3V3_Z3_get_denominator" - -(** - Summary: Return numeral value, as a pair of 64 bit numbers if the representation fits. - @param c logical context. - @param a term. - @param num numerator. - @param den denominator. - Return [TRUE] if the numeral value fits in 64 bit numerals, [FALSE] otherwise. - - {b Precondition}: get_ast_kind a == NUMERAL_AST - def_API('get_numeral_small', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) -*) -external get_numeral_small : context -> ast -> bool * int64 * int64 - = "camlidl_z3V3_Z3_get_numeral_small" - -(** - Summary: \[ [ get_numeral_int c v ] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit in a machine int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int', BOOL, (_in(CONTEXT), _in(AST), _out(INT))) -*) -external get_numeral_int : context -> ast -> bool * int - = "camlidl_z3V3_Z3_get_numeral_int" - -(** - Summary: \[ [ get_numeral_int64 c v ] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit in a machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) -*) -external get_numeral_int64 : context -> ast -> bool * int64 - = "camlidl_z3V3_Z3_get_numeral_int64" - -(** - Summary: \[ [ get_numeral_rational_int64 c x y] \] - Similar to {!get_numeral_string}, but only succeeds if - the value can fit as a rational number as machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_rational_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) -*) -external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 - = "camlidl_z3V3_Z3_get_numeral_rational_int64" - -(** - Summary: Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_lower', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_algebraic_number_lower : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_algebraic_number_lower" - -(** - Summary: Return a upper bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_upper', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_algebraic_number_upper : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_algebraic_number_upper" + (** Indicates whether the term is a bit-vector signed division by zero *) + val is_bv_sdiv0 : Expr.expr -> bool -(** - {4 {L Patterns}} -*) -(** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - def_API('pattern_to_ast', AST, (_in(CONTEXT), _in(PATTERN))) -*) -external pattern_to_ast : context -> pattern -> ast - = "camlidl_z3V3_Z3_pattern_to_ast" + (** Indicates whether the term is a bit-vector unsigned division by zero *) + val is_bv_udiv0 : Expr.expr -> bool -(** - Summary: Return number of terms in pattern. - def_API('get_pattern_num_terms', UINT, (_in(CONTEXT), _in(PATTERN))) -*) -external get_pattern_num_terms : context -> pattern -> int - = "camlidl_z3V3_Z3_get_pattern_num_terms" + (** Indicates whether the term is a bit-vector signed remainder by zero *) + val is_bv_srem0 : Expr.expr -> bool -(** - Summary: Return i'th ast in pattern. - def_API('get_pattern', AST, (_in(CONTEXT), _in(PATTERN), _in(UINT))) -*) -external get_pattern : context -> pattern -> int -> ast - = "camlidl_z3V3_Z3_get_pattern" + (** Indicates whether the term is a bit-vector unsigned remainder by zero *) + val is_bv_urem0 : Expr.expr -> bool -(** - {4 {L Quantifiers}} -*) -(** - Summary: Return index of de-Brujin bound variable. - - {b Precondition}: get_ast_kind a == VAR_AST - def_API('get_index_value', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_index_value : context -> ast -> int - = "camlidl_z3V3_Z3_get_index_value" + (** Indicates whether the term is a bit-vector signed modulus by zero *) + val is_bv_smod0 : Expr.expr -> bool -(** - Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) -*) -external is_quantifier_forall : context -> ast -> bool - = "camlidl_z3V3_Z3_is_quantifier_forall" + (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) + val is_bv_ule : Expr.expr -> bool -(** - Summary: Obtain weight of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_weight : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_weight" + (** Indicates whether the term is a signed bit-vector less-than-or-equal *) + val is_bv_sle : Expr.expr -> bool -(** - Summary: Return number of patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_patterns', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_patterns : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_patterns" + (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) + val is_bv_uge : Expr.expr -> bool -(** - Summary: Return i'th pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_pattern_ast', PATTERN, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_pattern_ast : context -> ast -> int -> pattern - = "camlidl_z3V3_Z3_get_quantifier_pattern_ast" + (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) + val is_bv_sge : Expr.expr -> bool -(** - Summary: Return number of no_patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_no_patterns', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_no_patterns : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_no_patterns" + (** Indicates whether the term is an unsigned bit-vector less-than *) + val is_bv_ult : Expr.expr -> bool -(** - Summary: Return i'th no_pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_no_pattern_ast', AST, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_no_pattern_ast : context -> ast -> int -> ast - = "camlidl_z3V3_Z3_get_quantifier_no_pattern_ast" + (** Indicates whether the term is a signed bit-vector less-than *) + val is_bv_slt : Expr.expr -> bool -(** - Summary: Return number of bound variables of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_bound', UINT, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_num_bound : context -> ast -> int - = "camlidl_z3V3_Z3_get_quantifier_num_bound" + (** Indicates whether the term is an unsigned bit-vector greater-than *) + val is_bv_ugt : Expr.expr -> bool -(** - Summary: Return symbol of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_name', SYMBOL, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_bound_name : context -> ast -> int -> symbol - = "camlidl_z3V3_Z3_get_quantifier_bound_name" + (** Indicates whether the term is a signed bit-vector greater-than *) + val is_bv_sgt : Expr.expr -> bool -(** - Summary: Return sort of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_sort', SORT, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external get_quantifier_bound_sort : context -> ast -> int -> sort - = "camlidl_z3V3_Z3_get_quantifier_bound_sort" + (** Indicates whether the term is a bit-wise AND *) + val is_bv_and : Expr.expr -> bool -(** - Summary: Return body of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_body', AST, (_in(CONTEXT), _in(AST))) -*) -external get_quantifier_body : context -> ast -> ast - = "camlidl_z3V3_Z3_get_quantifier_body" + (** Indicates whether the term is a bit-wise OR *) + val is_bv_or : Expr.expr -> bool -(** - {3 {L Simplification}} -*) -(** - Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - def_API('simplify', AST, (_in(CONTEXT), _in(AST))) -*) -external simplify : context -> ast -> ast - = "camlidl_z3V3_Z3_simplify" + (** Indicates whether the term is a bit-wise NOT *) + val is_bv_not : Expr.expr -> bool -(** - {2 {L Modifiers}} -*) -(** - Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide - with the number of arguments to [a]. - If [a] is a quantifier, then num_args has to be 1. - def_API('update_term', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) -*) -external update_term : context -> ast -> ast array -> ast - = "camlidl_z3V3_Z3_update_term" - -(** - Summary: Substitute every occurrence of {e from[i] } in [a] with {e to[i] }, for [i] smaller than [num_exprs]. - The result is the new AST. The arrays [from] and [to] must have size [num_exprs]. - For every [i] smaller than [num_exprs], we must have that sort of {e from[i] } must be equal to sort of {e to[i] }. - def_API('substitute', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in_array(2, AST))) -*) -external substitute : context -> ast -> ast array -> ast array -> ast - = "camlidl_z3V3_Z3_substitute" + (** Indicates whether the term is a bit-wise XOR *) + val is_bv_xor : Expr.expr -> bool -(** - Summary: Substitute the free variables in [a] with the expressions in [to]. - For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term {e to[i] }. - def_API('substitute_vars', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) -*) -external substitute_vars : context -> ast -> ast array -> ast - = "camlidl_z3V3_Z3_substitute_vars" + (** Indicates whether the term is a bit-wise NAND *) + val is_bv_nand : Expr.expr -> bool -(** - {2 {L Interaction logging.}} -*) -(** - Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) -*) -external open_log : string -> bool - = "camlidl_z3V3_Z3_open_log" - -(** - Summary: Append user-defined string to interaction log. - The interaction log is opened using open_log. - It contains the formulas that are checked using Z3. - You can use this command to append comments, for instance. - extra_API('append_log', VOID, (_in(STRING),)) -*) -external append_log : string -> unit - = "camlidl_z3V3_Z3_append_log" + (** Indicates whether the term is a bit-wise NOR *) + val is_bv_nor : Expr.expr -> bool -(** - Summary: Close interaction log. - extra_API('close_log', VOID, ()) -*) -external close_log : unit -> unit - = "camlidl_z3V3_Z3_close_log" - -(** - Summary: Enable/disable printing warning messages to the console. - Warnings are printed after passing [true], warning messages are - suppressed after calling this method with [false]. - def_API('toggle_warning_messages', VOID, (_in(BOOL),)) -*) -external toggle_warning_messages : bool -> unit - = "camlidl_z3V3_Z3_toggle_warning_messages" + (** Indicates whether the term is a bit-wise XNOR *) + val is_bv_xnor : Expr.expr -> bool -(** - {2 {L String conversion}} -*) -(** - Summary: Select mode for the format used for pretty-printing AST nodes. - The default mode for pretty printing AST nodes is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - {b See also}: {!ast_to_string} - - {b See also}: {!pattern_to_string} - - {b See also}: {!func_decl_to_string} - def_API('set_ast_print_mode', VOID, (_in(CONTEXT), _in(PRINT_MODE))) -*) -external set_ast_print_mode : context -> ast_print_mode -> unit - = "camlidl_z3V3_Z3_set_ast_print_mode" - -(** - Summary: Convert the given AST node into a string. - - {b See also}: {!pattern_to_string} - - {b See also}: {!sort_to_string} - def_API('ast_to_string', STRING, (_in(CONTEXT), _in(AST))) -*) -external ast_to_string : context -> ast -> string - = "camlidl_z3V3_Z3_ast_to_string" + (** Indicates whether the term is a bit-vector concatenation (binary) *) + val is_bv_concat : Expr.expr -> bool -(** - def_API('pattern_to_string', STRING, (_in(CONTEXT), _in(PATTERN))) -*) -external pattern_to_string : context -> pattern -> string - = "camlidl_z3V3_Z3_pattern_to_string" + (** Indicates whether the term is a bit-vector sign extension *) + val is_bv_signextension : Expr.expr -> bool -(** - def_API('sort_to_string', STRING, (_in(CONTEXT), _in(SORT))) -*) -external sort_to_string : context -> sort -> string - = "camlidl_z3V3_Z3_sort_to_string" + (** Indicates whether the term is a bit-vector zero extension *) + val is_bv_zeroextension : Expr.expr -> bool -(** - def_API('func_decl_to_string', STRING, (_in(CONTEXT), _in(FUNC_DECL))) -*) -external func_decl_to_string : context -> func_decl -> string - = "camlidl_z3V3_Z3_func_decl_to_string" + (** Indicates whether the term is a bit-vector extraction *) + val is_bv_extract : Expr.expr -> bool -(** - Summary: Convert the given model into a string. - def_API('model_to_string', STRING, (_in(CONTEXT), _in(MODEL))) -*) -external model_to_string : context -> model -> string - = "camlidl_z3V3_Z3_model_to_string" - -(** - Summary: Convert the given benchmark into SMT-LIB formatted string. - @param c - context. - @param name - name of benchmark. The argument is optional. - @param logic - the benchmark logic. - @param status - the status string (sat, unsat, or unknown) - @param attributes - other attributes, such as source, difficulty or category. - @param num_assumptions - number of assumptions. - @param assumptions - auxiliary assumptions. - @param formula - formula to be checked for consistency in conjunction with assumptions. - def_API('benchmark_to_smtlib_string', STRING, (_in(CONTEXT), _in(STRING), _in(STRING), _in(STRING), _in(STRING), _in(UINT), _in_array(5, AST), _in(AST))) -*) -external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" + (** Indicates whether the term is a bit-vector repetition *) + val is_bv_repeat : Expr.expr -> bool -(** - {2 {L Parser interface}} -*) -(** - Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - It returns a formula comprising of the conjunction of assertions in the scope - (up to push/pop) at the end of the string. - def_API('parse_smtlib2_string', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3V3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" + (** Indicates whether the term is a bit-vector reduce OR *) + val is_bv_reduceor : Expr.expr -> bool -(** - Summary: Similar to {!parse_smtlib2_string}, but reads the benchmark from a file. - def_API('parse_smtlib2_file', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3V3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" + (** Indicates whether the term is a bit-vector reduce AND *) + val is_bv_reduceand : Expr.expr -> bool -(** - {4 {L Low-level API}} -*) -(** - Summary: \[ [ parse_smtlib_string c str sort_names sorts decl_names decls ] \] - Parse the given string using the SMT-LIB parser. - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays [sort_names] and [decl_names] don't need to match the names - of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature - since we can use arbitrary names to reference sorts and declarations defined using the C API. - The formulas, assumptions and declarations defined in [str] can be extracted using the functions: - {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, - {!get_smtlib_num_decls}, and {!get_smtlib_decl}. - def_API('parse_smtlib_string', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3V3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" + (** Indicates whether the term is a bit-vector comparison *) + val is_bv_comp : Expr.expr -> bool -(** - Summary: Similar to {!parse_smtlib_string}, but reads the benchmark from a file. - def_API('parse_smtlib_file', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) -*) -external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3V3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" + (** Indicates whether the term is a bit-vector shift left *) + val is_bv_shiftleft : Expr.expr -> bool -(** - Summary: Return the number of SMTLIB formulas parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_formulas', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_formulas : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_formulas" - -(** - Summary: \[ [ get_smtlib_formula c i ] \] - Return the i-th formula parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_formulas c - def_API('get_smtlib_formula', AST, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_formula : context -> int -> ast - = "camlidl_z3V3_Z3_get_smtlib_formula" + (** Indicates whether the term is a bit-vector logical shift right *) + val is_bv_shiftrightlogical : Expr.expr -> bool -(** - Summary: Return the number of SMTLIB assumptions parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_assumptions', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_assumptions : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_assumptions" - -(** - Summary: \[ [ get_smtlib_assumption c i ] \] - Return the i-th assumption parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_assumptions c - def_API('get_smtlib_assumption', AST, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_assumption : context -> int -> ast - = "camlidl_z3V3_Z3_get_smtlib_assumption" + (** Indicates whether the term is a bit-vector arithmetic shift left *) + val is_bv_shiftrightarithmetic : Expr.expr -> bool -(** - Summary: Return the number of declarations parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_decls', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_decls : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_decls" - -(** - Summary: \[ [ get_smtlib_decl c i ] \] - Return the i-th declaration parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_decls c - def_API('get_smtlib_decl', FUNC_DECL, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_decl : context -> int -> func_decl - = "camlidl_z3V3_Z3_get_smtlib_decl" + (** Indicates whether the term is a bit-vector rotate left *) + val is_bv_rotateleft : Expr.expr -> bool -(** - Summary: Return the number of sorts parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_sorts', UINT, (_in(CONTEXT), )) -*) -external get_smtlib_num_sorts : context -> int - = "camlidl_z3V3_Z3_get_smtlib_num_sorts" - -(** - Summary: \[ [ get_smtlib_sort c i ] \] - Return the i-th sort parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_sorts c - def_API('get_smtlib_sort', SORT, (_in(CONTEXT), _in(UINT))) -*) -external get_smtlib_sort : context -> int -> sort - = "camlidl_z3V3_Z3_get_smtlib_sort" + (** Indicates whether the term is a bit-vector rotate right *) + val is_bv_rotateright : Expr.expr -> bool -(** - Summary: \[ [ get_smtlib_error c ] \] - Retrieve that last error message information generated from parsing. - def_API('get_smtlib_error', STRING, (_in(CONTEXT), )) -*) -external get_smtlib_error : context -> string - = "camlidl_z3V3_Z3_get_smtlib_error" + (** Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotateleftextended : Expr.expr -> bool -(** - {2 {L Miscellaneous}} -*) -(** - Summary: Return Z3 version number information. - def_API('get_version', VOID, (_out(UINT), _out(UINT), _out(UINT), _out(UINT))) -*) -external get_version : unit -> int * int * int * int - = "camlidl_z3V3_Z3_get_version" + (** Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotaterightextended : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) -(** - Summary: Enable tracing messages tagged as [tag] when Z3 is compiled in debug mode. - It is a NOOP otherwise - def_API('enable_trace', VOID, (_in(STRING),)) -*) -external enable_trace : string -> unit - = "camlidl_z3V3_Z3_enable_trace" + (** Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_int_to_bv : Expr.expr -> bool -(** - Summary: Disable tracing messages tagged as [tag] when Z3 is compiled in debug mode. - It is a NOOP otherwise - def_API('disable_trace', VOID, (_in(STRING),)) -*) -external disable_trace : string -> unit - = "camlidl_z3V3_Z3_disable_trace" - -(** - Summary: Reset all allocated resources. - Use this facility on out-of memory errors. - It allows discharging the previous state and resuming afresh. - Any pointers previously returned by the API - become invalid. - def_API('reset_memory', VOID, ()) -*) -external reset_memory : unit -> unit - = "camlidl_z3V3_Z3_reset_memory" + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_bv_to_int : Expr.expr -> bool -(** - {2 {L External Theory Plugins}} -*) -(** - Summary: Create an interpreted theory sort. -*) -external theory_mk_sort : context -> theory -> symbol -> sort - = "camlidl_z3V3_Z3_theory_mk_sort" + (** Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) + val is_bv_carry : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) + val is_bv_xor3 : Expr.expr -> bool -(** - Summary: Create an interpreted theory constant value. Values are assumed to be different from each other. -*) -external theory_mk_value : context -> theory -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_theory_mk_value" + (** The size of a bit-vector sort. *) + val get_size : Sort.sort -> int -(** - Summary: Create an interpreted constant for the given theory. -*) -external theory_mk_constant : context -> theory -> symbol -> sort -> ast - = "camlidl_z3V3_Z3_theory_mk_constant" + (** Retrieve the int value. *) + val get_int : Expr.expr -> int + + (** Returns a string representation of the numeral. *) + val to_string : Expr.expr -> string -(** - Summary: Create an interpreted function declaration for the given theory. -*) -external theory_mk_func_decl : context -> theory -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_theory_mk_func_decl" + (** Creates a bit-vector constant. *) + val mk_const : context -> Symbol.symbol -> int -> Expr.expr -(** - Summary: Return the context where the given theory is installed. -*) -external theory_get_context : theory -> context - = "camlidl_z3V3_Z3_theory_get_context" - -(** - Summary: Assert a theory axiom/lemmas during the search. - An axiom added at search level [n] will remain in the logical context until - level [n] is backtracked. - The callbacks for push ({!set_push_callback}) and pop - ({!set_pop_callback}) can be used to track when the search - level is increased (i.e., new case-split) and decreased (i.e., - case-split is backtracked). - Z3 tracks the theory axioms asserted. So, multiple assertions of the same axiom are - ignored. -*) -external theory_assert_axiom : theory -> ast -> unit - = "camlidl_z3V3_Z3_theory_assert_axiom" - -(** - Summary: Inform to the logical context that [lhs] and [rhs] have the same interpretation - in the model being built by theory [t]. If lhs = rhs is inconsistent with other theories, - then the logical context will backtrack. - For more information, see the paper "Model-Based Theory Combination" in the Z3 website. -*) -external theory_assume_eq : theory -> ast -> ast -> unit - = "camlidl_z3V3_Z3_theory_assume_eq" - -(** - Summary: Enable/disable the simplification of theory axioms asserted using {!theory_assert_axiom}. - By default, the simplification of theory specific operators is disabled. - That is, the reduce theory callbacks are not invoked for theory axioms. - The default behavior is useful when asserting axioms stating properties of theory operators. -*) -external theory_enable_axiom_simplification : theory -> bool -> unit - = "camlidl_z3V3_Z3_theory_enable_axiom_simplification" + (** Creates a bit-vector constant. *) + val mk_const_s : context -> string -> int -> Expr.expr -(** - Summary: Return the root of the equivalence class containing [n]. -*) -external theory_get_eqc_root : theory -> ast -> ast - = "camlidl_z3V3_Z3_theory_get_eqc_root" - -(** - Summary: Return the next element in the equivalence class containing [n]. - The elements in an equivalence class are organized in a circular list. - You can traverse the list by calling this function multiple times - using the result from the previous call. This is illustrated in the - code snippet below. - {v - ast curr = n; - do - curr = theory_get_eqc_next(theory, curr); - while (curr != n); - v} -*) -external theory_get_eqc_next : theory -> ast -> ast - = "camlidl_z3V3_Z3_theory_get_eqc_next" + (** Bitwise negation. + The argument must have a bit-vector sort. *) + val mk_not : context -> Expr.expr -> Expr.expr -(** - Summary: Return the number of parents of [n] that are operators of the given theory. -*) -external theory_get_num_parents : theory -> ast -> int - = "camlidl_z3V3_Z3_theory_get_num_parents" + (** Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redand : context -> Expr.expr -> Expr.expr -(** - Summary: Return the i-th parent of [n]. - See {!theory_get_num_parents}. -*) -external theory_get_parent : theory -> ast -> int -> ast - = "camlidl_z3V3_Z3_theory_get_parent" + (** Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redor : context -> Expr.expr -> Expr.expr + + (** Bitwise conjunction. + The arguments must have a bit-vector sort. *) + val mk_and : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bitwise disjunction. + The arguments must have a bit-vector sort. *) + val mk_or : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bitwise XOR. + The arguments must have a bit-vector sort. *) + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bitwise NAND. + The arguments must have a bit-vector sort. *) + val mk_nand : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bitwise NOR. + The arguments must have a bit-vector sort. *) + val mk_nor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bitwise XNOR. + The arguments must have a bit-vector sort. *) + val mk_xnor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Standard two's complement unary minus. + The arguments must have a bit-vector sort. *) + val mk_neg : context -> Expr.expr -> Expr.expr + + (** Two's complement addition. + The arguments must have the same bit-vector sort. *) + val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement subtraction. + The arguments must have the same bit-vector sort. *) + val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement multiplication. + The arguments must have the same bit-vector sort. *) + val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) + val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned less-than + + The arguments must have the same bit-vector sort. *) + val mk_ult : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement signed less-than + + The arguments must have the same bit-vector sort. *) + val mk_slt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_ule : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sle : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_uge : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sge : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Unsigned greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_ugt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_sgt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). *) + val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Bit-vector extraction. + + Extract the bits between two limits from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. *) + val mk_extract : context -> int -> int -> Expr.expr -> Expr.expr + + (** Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. *) + val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr + + (** Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. *) + val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr + + (** Bit-vector repetition. *) + val mk_repeat : context -> int -> Expr.expr -> Expr.expr + + (** Shift left. + + It is equivalent to multiplication by 2^x where \c x is the value of third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling.*) + val mk_shl : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_lshr : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_ashr : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Rotate Left. + Rotate bits of \c t to the left \c i times. *) + val mk_rotate_left : context -> int -> Expr.expr -> Expr.expr + + (** Rotate Right. + Rotate bits of \c t to the right \c i times.*) + val mk_rotate_right : context -> int -> Expr.expr -> Expr.expr + + (** Rotate Left. + Rotate bits of the second argument to the left.*) + val mk_ext_rotate_left : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Rotate Right. + Rotate bits of the second argument to the right. *) + val mk_ext_rotate_right : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an integer from the bit-vector argument + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in the argument. + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function.*) + val mk_bv2int : context -> Expr.expr -> bool -> Expr.expr + + (** Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr + + (** Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_underflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr + + (** Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sdiv_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_neg_no_overflow : context -> Expr.expr -> Expr.expr + + (** Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr + + (** Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a bit-vector numeral. *) + val mk_numeral : context -> string -> int -> Expr.expr +end + +(** Functions to manipulate proof expressions *) +module Proof : +sig + (** Indicates whether the term is a Proof for the expression 'true'. *) + val is_true : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact asserted by the user. *) + val is_asserted : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) + val is_goal : Expr.expr -> bool + + (** Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) + val is_modus_ponens : Expr.expr -> bool + + (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) + val is_reflexivity : Expr.expr -> bool + + (** Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) + val is_symmetry : Expr.expr -> bool + + (** Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) + val is_transitivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) + val is_Transitivity_star : Expr.expr -> bool + + (** Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) + val is_monotonicity : Expr.expr -> bool + + (** Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) + val is_quant_intro : Expr.expr -> bool + + (** Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) + val is_distributivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) + val is_and_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) + val is_or_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) + val is_rewrite : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) + val is_rewrite_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) + val is_pull_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) + val is_pull_quant_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) + val is_push_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) + val is_elim_unused_vars : Expr.expr -> bool + + (** Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) + val is_der : Expr.expr -> bool + + (** Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) *) + val is_quant_inst : Expr.expr -> bool + + (** Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. *) + val is_hypothesis : Expr.expr -> bool + + (** Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) + val is_lemma : Expr.expr -> bool + + (** Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) + val is_unit_resolution : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) *) + val is_iff_true : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) *) + val is_iff_false : Expr.expr -> bool + + (** Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) + val is_commutativity : Expr.expr -> bool + + (** Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) + val is_def_axiom : Expr.expr -> bool + + (** Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) + val is_def_intro : Expr.expr -> bool + + (** Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) + val is_apply_def : Expr.expr -> bool + + (** Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) *) + val is_iff_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) + val is_nnf_pos : Expr.expr -> bool + + (** Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) + val is_nnf_neg : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_nnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_cnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) + val is_skolemize : Expr.expr -> bool + + (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) + val is_modus_ponens_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) + val is_theory_lemma : Expr.expr -> bool +end + +(** Goals + + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) +module Goal : +sig + type goal + + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. *) + val get_precision : goal -> Z3enums.goal_prec + + (** Indicates whether the goal is precise. *) + val is_precise : goal -> bool + + (** Indicates whether the goal is an under-approximation. *) + val is_underapproximation : goal -> bool + + (** Indicates whether the goal is an over-approximation. *) + val is_overapproximation : goal -> bool + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) + val is_garbage : goal -> bool + + (** Adds the constraints to the given goal. *) + val add : goal -> Expr.expr list -> unit + + (** Indicates whether the goal contains `false'. *) + val is_inconsistent : goal -> bool + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) + val get_depth : goal -> int + + (** Erases all formulas from the given goal. *) + val reset : goal -> unit + + (** The number of formulas in the goal. *) + val get_size : goal -> int + + (** The formulas in the goal. *) + val get_formulas : goal -> Expr.expr list + + (** The number of formulas, subformulas and terms in the goal. *) + val get_num_exprs : goal -> int + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) + val is_decided_sat : goal -> bool + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) + val is_decided_unsat : goal -> bool + + (** Translates (copies) the Goal to another context.. *) + val translate : goal -> context -> goal + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) + val simplify : goal -> Params.params option -> goal + + (** Creates a new Goal. + + Note that the Context must have been created with proof generation support if + the fourth argument is set to true here. *) + val mk_goal : context -> bool -> bool -> bool -> goal + + (** A string representation of the Goal. *) + val to_string : goal -> string +end + +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model : +sig + type model + + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. *) + module FuncInterp : + sig + type func_interp + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. *) + module FuncEntry : + sig + type func_entry + + (** Return the (symbolic) value of this entry. + *) + val get_value : func_entry -> Expr.expr + + (** The number of arguments of the entry. + *) + val get_num_args : func_entry -> int + + (** The arguments of the function entry. + *) + val get_args : func_entry -> Expr.expr list + + (** A string representation of the function entry. + *) + val to_string : func_entry -> string + end -(** - Summary: Return [TRUE] if [n] is an interpreted theory value. -*) -external theory_is_value : theory -> ast -> bool - = "camlidl_z3V3_Z3_theory_is_value" + (** The number of entries in the function interpretation. *) + val get_num_entries : func_interp -> int -(** - Summary: Return [TRUE] if [d] is an interpreted theory declaration. -*) -external theory_is_decl : theory -> func_decl -> bool - = "camlidl_z3V3_Z3_theory_is_decl" + (** The entries in the function interpretation *) + val get_entries : func_interp -> FuncEntry.func_entry list -(** - Summary: Return the number of expressions of the given theory in - the logical context. These are the expressions notified using the - callback {!set_new_elem_callback}. -*) -external theory_get_num_elems : theory -> int - = "camlidl_z3V3_Z3_theory_get_num_elems" + (** The (symbolic) `else' value of the function interpretation. *) + val get_else : func_interp -> Expr.expr -(** - Summary: Return the i-th elem of the given theory in the logical context. - - {b See}: {!theory_get_num_elems} -*) -external theory_get_elem : theory -> int -> ast - = "camlidl_z3V3_Z3_theory_get_elem" + (** The arity of the function interpretation *) + val get_arity : func_interp -> int -(** - Summary: Return the number of theory applications in the logical - context. These are the expressions notified using the callback - {!set_new_app_callback}. -*) -external theory_get_num_apps : theory -> int - = "camlidl_z3V3_Z3_theory_get_num_apps" + (** A string representation of the function interpretation. *) + val to_string : func_interp -> string + end -(** - Summary: Return the i-th application of the given theory in the logical context. - - {b See}: {!theory_get_num_apps} -*) -external theory_get_app : theory -> int -> ast - = "camlidl_z3V3_Z3_theory_get_app" + (** Retrieves the interpretation (the assignment) of a func_decl in the model. + An expression if the function has an interpretation in the model, null otherwise. *) + val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option -<<<<<<< HEAD -(** - {2 {L Deprecated Injective functions API}} -*) -(** - Summary: Create injective function declaration - @deprecated This method just asserts a (universally quantified) formula that asserts that - the new function is injective. It is compatible with the old interface for solving: - {!assert_cnstr}, {!check_assumptions}, etc. - def_API('mk_injective_function', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) -*) -external mk_injective_function : context -> symbol -> sort array -> sort -> func_decl - = "camlidl_z3V3_Z3_mk_injective_function" + (** Retrieves the interpretation (the assignment) of an expression in the model. + An expression if the constant has an interpretation in the model, null otherwise. *) + val get_const_interp_e : model -> Expr.expr -> Expr.expr option -(** - {2 {L Deprecated Constraints API}} -*) -(** - Summary: Set the SMTLIB logic to be used in the given logical context. - It is incorrect to invoke this function after invoking - {!check}, {!check_and_get_model}, {!check_assumptions} and {!push}. - Return [TRUE] if the logic was changed successfully, and [FALSE] otherwise. - @deprecated Subsumed by {!mk_solver_for_logic} - def_API('set_logic', VOID, (_in(CONTEXT), _in(STRING))) -*) -external set_logic : context -> string -> bool - = "camlidl_z3V3_Z3_set_logic" - -(** - Summary: Create a backtracking point. - The logical context can be viewed as a stack of contexts. The - scope level is the number of elements on this stack. The stack - of contexts is simulated using trail (undo) stacks. - - {b See also}: {!pop} - @deprecated Subsumed by {!solver_push} - def_API('push', VOID, (_in(CONTEXT),)) -*) -external push : context -> unit - = "camlidl_z3V3_Z3_push" - -(** - Summary: Backtrack. - Restores the context from the top of the stack, and pops it off the - stack. Any changes to the logical context (by {!assert_cnstr} or - other functions) between the matching {!push} and [pop] - operators are flushed, and the context is completely restored to - what it was right before the {!push}. - - {b See also}: {!push} - @deprecated Subsumed by {!solver_pop} - def_API('pop', VOID, (_in(CONTEXT), _in(UINT))) -*) -external pop : context -> int -> unit - = "camlidl_z3V3_Z3_pop" - -(** - Summary: Retrieve the current scope level. - It retrieves the number of scopes that have been pushed, but not yet popped. - - {b See also}: {!push} - - {b See also}: {!pop} - @deprecated Subsumed by {!solver_get_num_scopes}. - def_API('get_num_scopes', UINT, (_in(CONTEXT),)) -*) -external get_num_scopes : context -> int - = "camlidl_z3V3_Z3_get_num_scopes" + (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option -(** - @deprecated This function has no effect. - def_API('persist_ast', VOID, (_in(CONTEXT), _in(AST), _in(UINT))) -*) -external persist_ast : context -> ast -> int -> unit - = "camlidl_z3V3_Z3_persist_ast" - -(** - Summary: Assert a constraint into the logical context. - After one assertion, the logical context may become - inconsistent. - The functions {!check} or {!check_and_get_model} should be - used to check whether the logical context is consistent or not. - - {b See also}: {!check} - - {b See also}: {!check_and_get_model} - @deprecated Subsumed by {!solver_assert} - def_API('assert_cnstr', VOID, (_in(CONTEXT), _in(AST))) -*) -external assert_cnstr : context -> ast -> unit - = "camlidl_z3V3_Z3_assert_cnstr" - -(** - Summary: Check whether the given logical context is consistent or not. - If the logical context is not unsatisfiable (i.e., the return value is different from [L_FALSE)] - and model construction is enabled (see {!mk_config}), - then a valid model is returned. Otherwise, it is unsafe to use the returned model. - - {b Remarks}: Model construction must be enabled using configuration - parameters (See, {!mk_config}). - - {b See also}: {!check} - @deprecated Subsumed by {!solver_check} - def_API('check_and_get_model', INT, (_in(CONTEXT), _out(MODEL))) -*) -external check_and_get_model : context -> lbool * model - = "camlidl_z3V3_Z3_check_and_get_model" - -(** - Summary: Check whether the given logical context is consistent or not. - The function {!check_and_get_model} should be used when models are needed. - - {b See also}: {!check_and_get_model} - @deprecated Subsumed by {!solver_check} - def_API('check', INT, (_in(CONTEXT),)) -*) -external check : context -> lbool - = "camlidl_z3V3_Z3_check" - -(** - Summary: Check whether the given logical context and optional assumptions is consistent or not. - If the logical context is not unsatisfiable (i.e., the return value is different from [L_FALSE)], - and model construction is enabled (see {!mk_config}), - then a valid model is returned. Otherwise, it is unsafe to use the returned model. - @param c logical context. - @param num_assumptions number of auxiliary assumptions. - @param assumptions array of auxiliary assumptions - @param m optional pointer to a model. - @param proof optional pointer to a proof term. - @param core_size size of unsatisfiable core. - @param core pointer to an array receiving unsatisfiable core. - The unsatisfiable core is a subset of the assumptions, so the array has the same size as the assumptions. - The [core] array is not populated if [core_size] is set to 0. - - {b Precondition}: assumptions comprises of propositional literals. - In other words, you cannot use compound formulas for assumptions, - but should use propositional variables or negations of propositional variables. - - {b See also}: {!check} - @deprecated Subsumed by {!solver_check_assumptions} - def_API('check_assumptions', INT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out(MODEL), _out(AST), _out(UINT), _out_array2(1, 5, AST))) -*) -external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array - = "camlidl_z3V3_Z3_check_assumptions" - -(** - Summary: Delete a model object. - - {b See also}: {!check_and_get_model} - @deprecated Subsumed by solver API - def_API('del_model', VOID, (_in(CONTEXT), _in(MODEL))) -*) -external del_model : context -> model -> unit - = "camlidl_z3V3_Z3_del_model" + (** The number of constant interpretations in the model. *) + val get_num_consts : model -> int -(** - {2 {L Deprecated Search control API}} -*) -(** - Summary: Cancel an ongoing check. - Notifies the current check to abort and return. - This method should be called from a different thread - than the one performing the check. - @deprecated Use {!interrupt} instead. - def_API('soft_check_cancel', VOID, (_in(CONTEXT), )) -*) -external soft_check_cancel : context -> unit - = "camlidl_z3V3_Z3_soft_check_cancel" - -(** - Summary: Retrieve reason for search failure. - If a call to {!check} or {!check_and_get_model} returns L_UNDEF, - use this facility to determine the more detailed cause of search failure. - @deprecated Subsumed by {!solver_get_reason_unknown} - def_API('get_search_failure', UINT, (_in(CONTEXT), )) -*) -external get_search_failure : context -> search_failure - = "camlidl_z3V3_Z3_get_search_failure" + (** The function declarations of the constants in the model. *) + val get_const_decls : model -> FuncDecl.func_decl list -(** - {2 {L Deprecated Labels API}} -*) -(** - Summary: Create a labeled formula. - @param c logical context. - @param s name of the label. - @param is_pos label polarity. - @param f formula being labeled. - A label behaves as an identity function, so the truth value of the - labeled formula is unchanged. Labels are used for identifying - useful sub-formulas when generating counter-examples. - @deprecated Labels are only supported by the old Solver API. - This feature is not essential (it can be simulated using auxiliary Boolean variables). - It is only available for backward compatibility. - def_API('mk_label', AST, (_in(CONTEXT), _in(SYMBOL), _in(BOOL), _in(AST))) -*) -external mk_label : context -> symbol -> bool -> ast -> ast - = "camlidl_z3V3_Z3_mk_label" - -(** - Summary: Retrieve the set of labels that were relevant in - the context of the current satisfied context. - - {b See also}: {!del_literals} - - {b See also}: {!get_num_literals} - - {b See also}: {!get_label_symbol} - - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_relevant_labels', LITERALS, (_in(CONTEXT), )) -*) -external get_relevant_labels : context -> literals - = "camlidl_z3V3_Z3_get_relevant_labels" - -(** - Summary: Retrieve the set of literals that satisfy the current context. - - {b See also}: {!del_literals} - - {b See also}: {!get_num_literals} - - {b See also}: {!get_label_symbol} - - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_relevant_literals', LITERALS, (_in(CONTEXT), )) -*) -external get_relevant_literals : context -> literals - = "camlidl_z3V3_Z3_get_relevant_literals" - -(** - Summary: Retrieve the set of literals that whose assignment were - guess, but not propagated during the search. - - {b See also}: {!del_literals} - - {b See also}: {!get_num_literals} - - {b See also}: {!get_label_symbol} - - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_guessed_literals', LITERALS, (_in(CONTEXT), )) -*) -external get_guessed_literals : context -> literals - = "camlidl_z3V3_Z3_get_guessed_literals" - -(** - Summary: Delete a labels context. - - {b See also}: {!get_relevant_labels} - @deprecated This procedure is based on the old Solver API. - def_API('del_literals', VOID, (_in(CONTEXT), _in(LITERALS))) -*) -external del_literals : context -> literals -> unit - = "camlidl_z3V3_Z3_del_literals" - -(** - Summary: Retrieve the number of label symbols that were returned. - - {b See also}: {!get_relevant_labels} - @deprecated This procedure is based on the old Solver API. - def_API('get_num_literals', UINT, (_in(CONTEXT), _in(LITERALS))) -*) -external get_num_literals : context -> literals -> int - = "camlidl_z3V3_Z3_get_num_literals" + (** The number of function interpretations in the model. *) + val get_num_funcs : model -> int -(** - Summary: Retrieve label symbol at idx. - @deprecated This procedure is based on the old Solver API. - def_API('get_label_symbol', SYMBOL, (_in(CONTEXT), _in(LITERALS), _in(UINT))) -*) -external get_label_symbol : context -> literals -> int -> symbol - = "camlidl_z3V3_Z3_get_label_symbol" + (** The function declarations of the function interpretations in the model. *) + val get_func_decls : model -> FuncDecl.func_decl list -(** - Summary: Retrieve literal expression at idx. - @deprecated This procedure is based on the old Solver API. - def_API('get_literal', AST, (_in(CONTEXT), _in(LITERALS), _in(UINT))) -*) -external get_literal : context -> literals -> int -> ast - = "camlidl_z3V3_Z3_get_literal" - -(** - Summary: Disable label. - The disabled label is not going to be used when blocking the subsequent search. - - {b See also}: {!block_literals} - @deprecated This procedure is based on the old Solver API. - def_API('disable_literal', VOID, (_in(CONTEXT), _in(LITERALS), _in(UINT))) -*) -external disable_literal : context -> literals -> int -> unit - = "camlidl_z3V3_Z3_disable_literal" + (** All symbols that have an interpretation in the model. *) + val get_decls : model -> FuncDecl.func_decl list -(** - Summary: Block subsequent checks using the remaining enabled labels. - @deprecated This procedure is based on the old Solver API. - def_API('block_literals', VOID, (_in(CONTEXT), _in(LITERALS))) -*) -external block_literals : context -> literals -> unit - = "camlidl_z3V3_Z3_block_literals" + (** Evaluates an expression in the current model. + + This function may fail if the argument contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + *) + val eval : model -> Expr.expr -> bool -> Expr.expr option -(** - {2 {L Deprecated Model API}} -*) -(** - Summary: Return the number of constants assigned by the given model. - - {b Remarks}: Consider using {!get_model_constants}. - - {b See also}: {!get_model_constant} - @deprecated use {!model_get_num_consts} - def_API('get_model_num_constants', UINT, (_in(CONTEXT), _in(MODEL))) -*) -external get_model_num_constants : context -> model -> int - = "camlidl_z3V3_Z3_get_model_num_constants" - -(** - Summary: \[ [ get_model_constant c m i ] \] - Return the i-th constant in the given model. - - {b Remarks}: Consider using {!get_model_constants}. - - {b Precondition}: i < get_model_num_constants c m - @deprecated use {!model_get_const_decl} - def_API('get_model_constant', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external get_model_constant : context -> model -> int -> func_decl - = "camlidl_z3V3_Z3_get_model_constant" - -(** - Summary: Return the number of function interpretations in the given model. - A function interpretation is represented as a finite map and an 'else' value. - Each entry in the finite map represents the value of a function given a set of arguments. - @deprecated use {!model_get_num_funcs} - def_API('get_model_num_funcs', UINT, (_in(CONTEXT), _in(MODEL))) -*) -external get_model_num_funcs : context -> model -> int - = "camlidl_z3V3_Z3_get_model_num_funcs" - -(** - Summary: \[ [ get_model_func_decl c m i ] \] - Return the declaration of the i-th function in the given model. - - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - @deprecated use {!model_get_func_decl} - def_API('get_model_func_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) + (** Alias for eval. *) + val evaluate : model -> Expr.expr -> bool -> Expr.expr option + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + val get_num_sorts : model -> int + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + {!get_num_sorts} + {!sort_universe} *) + val get_sorts : model -> Sort.sort list + + (** The finite set of distinct values that represent the interpretation of a sort. + {!get_sorts} + @returns A list of expressions, where each is an element of the universe of the sort *) + val sort_universe : model -> Sort.sort -> AST.ast list + + (** Conversion of models to strings. + A string representation of the model. *) + val to_string : model -> string +end + +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. *) -external get_model_func_decl : context -> model -> int -> func_decl - = "camlidl_z3V3_Z3_get_model_func_decl" - -(** - Summary: Return the value of the given constant or function - in the given model. - @deprecated Consider using {!model_eval} or {!model_get_func_interp} - def_API('eval_func_decl', BOOL, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _out(AST))) +module Probe : +sig + type probe + + (** Execute the probe over the goal. + A probe always produce a float value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + val apply : probe -> Goal.goal -> float + + (** The number of supported Probes. *) + val get_num_probes : context -> int + + (** The names of all supported Probes. *) + val get_probe_names : context -> string list + + (** Returns a string containing a description of the probe with the given name. *) + val get_probe_description : context -> string -> string + + (** Creates a new Probe. *) + val mk_probe : context -> string -> probe + + (** Create a probe that always evaluates to a float value. *) + val const : context -> float -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than the value returned by second argument *) + val lt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than the value returned by second argument *) + val gt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than or equal the value returned by second argument *) + val le : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than or equal the value returned by second argument *) + val ge : context -> probe -> probe -> probe + + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is equal the value returned by second argument *) + val eq : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) + val and_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) + val or_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) + val not_ : context -> probe -> probe +end + +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. *) -external eval_func_decl : context -> model -> func_decl -> bool * ast - = "camlidl_z3V3_Z3_eval_func_decl" -======= +module Tactic : +sig + type tactic + + (** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) + module ApplyResult : + sig + type apply_result + + (** The number of Subgoals. *) + val get_num_subgoals : apply_result -> int + + (** Retrieves the subgoals from the apply_result. *) + val get_subgoals : apply_result -> Goal.goal list + + (** Retrieves a subgoal from the apply_result. *) + val get_subgoal : apply_result -> int -> Goal.goal + + (** Convert a model for a subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g *) + val convert_model : apply_result -> int -> Model.model -> Model.model + + (** A string representation of the ApplyResult. *) + val to_string : apply_result -> string + end + + (** A string containing a description of parameters accepted by the tactic. *) + val get_help : tactic -> string + + (** Retrieves parameter descriptions for Tactics. *) + val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs + + (** Apply the tactic to the goal. *) + val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result + + (** The number of supported tactics. *) + val get_num_tactics : context -> int + + (** The names of all supported tactics. *) + val get_tactic_names : context -> string list + + (** Returns a string containing a description of the tactic with the given name. *) + val get_tactic_description : context -> string -> string + + (** Creates a new Tactic. *) + val mk_tactic : context -> string -> tactic + + (** Create a tactic that applies one tactic to a Goal and + then another one to every subgoal produced by the first one. *) + val and_then : context -> tactic -> tactic -> tactic list -> tactic + + (** Create a tactic that first applies one tactic to a Goal and + if it fails then returns the result of another tactic applied to the Goal. *) + val or_else : context -> tactic -> tactic -> tactic + + (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). + + If the tactic does not terminate within the timeout, then it fails. *) + val try_for : context -> tactic -> int -> tactic + + (** Create a tactic that applies one tactic to a given goal if the probe + evaluates to true. + + If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) + val when_ : context -> Probe.probe -> tactic -> tactic + + (** Create a tactic that applies a tactic to a given goal if the probe + evaluates to true and another tactic otherwise. *) + val cond : context -> Probe.probe -> tactic -> tactic -> tactic + + (** Create a tactic that keeps applying one tactic until the goal is not + modified anymore or the maximum number of iterations is reached. *) + val repeat : context -> tactic -> int -> tactic + + (** Create a tactic that just returns the given goal. *) + val skip : context -> tactic + + (** Create a tactic always fails. *) + val fail : context -> tactic + + (** Create a tactic that fails if the probe evaluates to false. *) + val fail_if : context -> Probe.probe -> tactic + + (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) + val fail_if_not_decided : context -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. *) + val using_params : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. + Alias for UsingParams*) + val with_ : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies the given tactics in parallel. *) + val par_or : context -> tactic list -> tactic + + (** Create a tactic that applies a tactic to a given goal and then another tactic + to every subgoal produced by the first one. The subgoals are processed in parallel. *) + val par_and_then : context -> tactic -> tactic -> tactic + + (** Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) + val interrupt : context -> unit +end + +(** Solvers *) +module Solver : +sig + type solver + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + val string_of_status : status -> string + + (** Objects that track statistical information about solvers. *) + module Statistics : + sig + type statistics + + (** Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) + module Entry : + sig + type statistics_entry + + (** The key of the entry. *) + val get_key : statistics_entry -> string + + (** The int-value of the entry. *) + val get_int : statistics_entry -> int + + (** The float-value of the entry. *) + val get_float : statistics_entry -> float + + (** True if the entry is uint-valued. *) + val is_int : statistics_entry -> bool + + (** True if the entry is float-valued. *) + val is_float : statistics_entry -> bool + + (** The string representation of the the entry's value. *) + val to_string_value : statistics_entry -> string + + (** The string representation of the entry (key and value) *) + val to_string : statistics_entry -> string + end + + (** A string representation of the statistical data. *) + val to_string : statistics -> string + + (** The number of statistical data. *) + val get_size : statistics -> int + + (** The data entries. *) + val get_entries : statistics -> Entry.statistics_entry list + + (** The statistical counters. *) + val get_keys : statistics -> string list + + (** The value of a particular statistical counter. *) + val get : statistics -> string -> Entry.statistics_entry option + end + + (** A string that describes all available solver parameters. *) + val get_help : solver -> string + + (** Sets the solver parameters. *) + val set_parameters : solver -> Params.params -> unit + + (** Retrieves parameter descriptions for solver. *) + val get_param_descrs : solver -> Params.ParamDescrs.param_descrs + + (** The current number of backtracking points (scopes). + {!pop} + {!push} *) + val get_num_scopes : solver -> int + + (** Creates a backtracking point. + {!pop} *) + val push : solver -> unit + + (** Backtracks a number of backtracking points. + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) + val pop : solver -> int -> unit + + (** Resets the Solver. + This removes all assertions from the solver. *) + val reset : solver -> unit + + (** Assert a constraint (or multiple) into the solver. *) + val add : solver -> Expr.expr list -> unit + + (** * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit + + (** * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit + + (** The number of assertions in the solver. *) + val get_num_assertions : solver -> int + + (** The set of asserted formulas. *) + val get_assertions : solver -> Expr.expr list + + (** Checks whether the assertions in the solver are consistent or not. + + {!Model} + {!get_unsat_core} + {!Proof} *) + val check : solver -> Expr.expr list -> status + + (** The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. *) + val get_model : solver -> Model.model option + + (** The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. *) + val get_proof : solver -> Expr.expr option + + (** The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. *) + val get_unsat_core : solver -> AST.ast list + + (** A brief justification of why the last call to Check returned UNKNOWN. *) + val get_reason_unknown : solver -> string + + (** Solver statistics. *) + val get_statistics : solver -> Statistics.statistics + + (** Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) + val mk_solver : context -> Symbol.symbol option -> solver + + (** Creates a new (incremental) solver. + {!mk_solver} *) + val mk_solver_s : context -> string -> solver + + (** Creates a new (incremental) solver. *) + val mk_simple_solver : context -> solver + + (** Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) + val mk_solver_t : context -> Tactic.tactic -> solver + + (** A string representation of the solver. *) + val to_string : solver -> string +end + +(** Fixedpoint solving *) +module Fixedpoint : +sig + type fixedpoint + + (** A string that describes all available fixedpoint solver parameters. *) + val get_help : fixedpoint -> string + + (** Sets the fixedpoint solver parameters. *) + val set_params : fixedpoint -> Params.params -> unit + + (** Retrieves parameter descriptions for Fixedpoint solver. *) + val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs + + (** Assert a constraints into the fixedpoint solver. *) + val add : fixedpoint -> Expr.expr list -> unit + + (** Register predicate as recursive relation. *) + val register_relation : fixedpoint -> FuncDecl.func_decl -> unit + + (** Add rule into the fixedpoint solver. *) + val add_rule : fixedpoint -> Expr.expr -> Symbol.symbol option -> unit + + (** Add table fact to the fixedpoint solver. *) + val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit + + (** Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) + val query : fixedpoint -> Expr.expr -> Solver.status + + (** Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) + val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status + + (** Creates a backtracking point. + {!pop} *) + val push : fixedpoint -> unit + + (** Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + {!push} *) + val pop : fixedpoint -> unit + + (** Update named rule into in the fixedpoint solver. *) + val update_rule : fixedpoint -> Expr.expr -> Symbol.symbol -> unit + + (** Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. *) + val get_answer : fixedpoint -> Expr.expr option + + (** Retrieve explanation why fixedpoint engine returned status Unknown. *) + val get_reason_unknown : fixedpoint -> string + + (** Retrieve the number of levels explored for a given predicate. *) + val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int + + (** Retrieve the cover of a predicate. *) + val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option + + (** Add property about the predicate. + The property is added at level. *) + val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit + + (** Retrieve internal string representation of fixedpoint object. *) + val to_string : fixedpoint -> string + + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) + val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit + + (** Convert benchmark given as set of axioms, rules and queries to a string. *) + val to_string_q : fixedpoint -> Expr.expr list -> string + + (** Retrieve set of rules added to fixedpoint context. *) + val get_rules : fixedpoint -> Expr.expr list + + (** Retrieve set of assertions added to fixedpoint context. *) + val get_assertions : fixedpoint -> Expr.expr list + + (** Create a Fixedpoint context. *) + val mk_fixedpoint : context -> fixedpoint +end + (** Functions for handling SMT and SMT2 expressions and files *) module SMT : sig (** Convert a benchmark into an SMT-LIB formatted string. ->>>>>>> Updates to ML API. -(** - Summary: \[ [ is_array_value c v ] \] - Determine whether the term encodes an array value. - A term encodes an array value if it is a nested sequence of - applications of store on top of a constant array. - The indices to the stores have to be values (for example, integer constants) - so that equality between the indices can be evaluated. - Array values are useful for representing interpretations for arrays. - Return the number of entries mapping to non-default values of the array. - @deprecated Use {!is_as_array} - def_API('is_array_value', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _out(UINT))) -*) -external is_array_value : context -> model -> ast -> bool * int - = "camlidl_z3V3_Z3_is_array_value" + @return A string representation of the benchmark. *) + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Expr.expr list -> Expr.expr -> string -(** - Summary: \[ [ get_array_value c v ] \] - An array values is represented as a dictionary plus a - default (else) value. This function returns the array graph. - - {b Precondition}: TRUE == is_array_value c v &num_entries - @deprecated Use func_interp objects and {!get_as_array_func_decl} - def_API('get_array_value', VOID, (_in(CONTEXT), _in(MODEL), _in(AST), _in(UINT), _out_array(3, AST), _out_array(3, AST), _out (AST))) -*) -external get_array_value : context -> model -> ast -> ast array -> ast array -> ast array * ast array * ast - = "camlidl_z3V3_Z3_get_array_value" + (** Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays in the third and fifth argument + don't need to match the names of the sorts and declarations in the arrays in the fourth + and sixth argument. This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) + val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit -(** - Summary: \[ [ get_model_func_else c m i ] \] - Return the 'else' value of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. - - {b Remarks}: Consider using {!get_model_funcs}. - - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_num_entries} - - {b See also}: {!get_model_func_entry_num_args} - - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_else', AST, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external get_model_func_else : context -> model -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_else" + (** Parse the given file using the SMT-LIB parser. + {!parse_smtlib_string} *) + val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit -(** - Summary: \[ [ get_model_func_num_entries c m i ] \] - Return the number of entries of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. - - {b Remarks}: Consider using {!get_model_funcs}. - - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_else} - - {b See also}: {!get_model_func_entry_num_args} - - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_num_entries', UINT, (_in(CONTEXT), _in(MODEL), _in(UINT))) -*) -external get_model_func_num_entries : context -> model -> int -> int - = "camlidl_z3V3_Z3_get_model_func_num_entries" + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_formulas : context -> int -(** - Summary: \[ [ get_model_func_entry_num_args c m i j ] \] - Return the number of arguments of the j-th entry of the i-th function interpretation in the given - model. - A function interpretation is represented as a finite map and an 'else' value. - This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - {b Remarks}: Consider using {!get_model_funcs}. - - {b Precondition}: i < get_model_num_funcs c m - - {b Precondition}: j < get_model_func_num_entries c m i - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_num_entries } - - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_entry_num_args', UINT, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT))) -*) -external get_model_func_entry_num_args : context -> model -> int -> int -> int - = "camlidl_z3V3_Z3_get_model_func_entry_num_args" + (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_formulas : context -> Expr.expr list -(** - Summary: \[ [ get_model_func_entry_arg c m i j k ] \] - Return the k-th argument of the j-th entry of the i-th function interpretation in the given - model. - A function interpretation is represented as a finite map and an 'else' value. - This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - {b Remarks}: Consider using {!get_model_funcs}. - - {b Precondition}: i < get_model_num_funcs c m - - {b Precondition}: j < get_model_func_num_entries c m i - - {b Precondition}: k < get_model_func_entry_num_args c m i j - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_num_entries } - - {b See also}: {!get_model_func_entry_num_args} - @deprecated Use func_interp objects - def_API('get_model_func_entry_arg', AST, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT), _in(UINT))) -*) -external get_model_func_entry_arg : context -> model -> int -> int -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_entry_arg" + (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_assumptions : context -> int -(** - Summary: \[ [ get_model_func_entry_value c m i j ] \] - Return the return value of the j-th entry of the i-th function interpretation in the given - model. - A function interpretation is represented as a finite map and an 'else' value. - This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - {b Remarks}: Consider using {!get_model_funcs}. - - {b Precondition}: i < get_model_num_funcs c m - - {b Precondition}: j < get_model_func_num_entries c m i - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_num_entries } - @deprecated Use func_interp objects - def_API('get_model_func_entry_value', AST, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT))) -*) -external get_model_func_entry_value : context -> model -> int -> int -> ast - = "camlidl_z3V3_Z3_get_model_func_entry_value" + (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_assumptions : context -> Expr.expr list -(** - Summary: \[ [ eval c m t ] \] - Evaluate the AST node [t] in the given model. - Return a pair: Boolean and value. The Boolean is true if the term was successfully evaluated. - The evaluation may fail for the following reasons: - - [t] contains a quantifier. - - the model [m] is partial, that is, it doesn't have a complete interpretation for uninterpreted functions. - That is, the option {e MODEL_PARTIAL=true } was used. - - [t] is type incorrect. - @deprecated Use {!model_eval} - def_API('eval', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _out(AST))) -*) -external eval : context -> model -> ast -> bool * ast - = "camlidl_z3V3_Z3_eval" + (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_decls : context -> int -(** - Summary: Evaluate declaration given values. - Provides direct way to evaluate declarations - without going over terms. - @deprecated Consider using {!model_eval} and {!substitute_vars} - def_API('eval_decl', BOOL, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _in(UINT), _in_array(3, AST), _out(AST))) -*) -external eval_decl : context -> model -> func_decl -> ast array -> bool * ast - = "camlidl_z3V3_Z3_eval_decl" + (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_decls : context -> FuncDecl.func_decl list -(** - {2 {L Deprecated String conversion API}} -*) -(** - Summary: Convert the given logical context into a string. - This function is mainly used for debugging purposes. It displays - the internal structure of a logical context. - @deprecated This method is obsolete. It just displays the internal representation of - the global solver available for backward compatibility reasons. - def_API('context_to_string', STRING, (_in(CONTEXT),)) -*) -external context_to_string : context -> string - = "camlidl_z3V3_Z3_context_to_string" + (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_sorts : context -> int -(** - Summary: Return runtime statistics as a string. - This function is mainly used for debugging purposes. It displays - statistics of the search activity. - @deprecated This method is based on the old solver API. - Use {!stats_to_string} when using the new solver API. - def_API('statistics_to_string', STRING, (_in(CONTEXT),)) -*) -external statistics_to_string : context -> string - = "camlidl_z3V3_Z3_statistics_to_string" + (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_sorts : context -> Sort.sort list -(** - Summary: Extract satisfying assignment from context as a conjunction. - This function can be used for debugging purposes. It returns a conjunction - of formulas that are assigned to true in the current context. - This conjunction will contain not only the assertions that are set to true - under the current assignment, but will also include additional literals - if there has been a call to {!check} or {!check_and_get_model}. - @deprecated This method is based on the old solver API. - def_API('get_context_assignment', AST, (_in(CONTEXT),)) -*) -external get_context_assignment : context -> ast - = "camlidl_z3V3_Z3_get_context_assignment" - - -(** {2 {L ML Extensions}} *) -(** - \[ [ mk_context_x configs] \] is a shorthand for the context with configurations in [configs]. -*) -val mk_context_x: (string * string) array -> context;; -(** - \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - {b See also}: {!get_app_num_args} - - {b See also}: {!get_app_arg} -*) -val get_app_args: context -> app -> ast array -(** - \[ [ get_app_args c d ] \] is the array of parameters of [d]. - - {b See also}: {!get_domain_size} - - {b See also}: {!get_domain} -*) -val get_domains: context -> func_decl -> sort array -(** - \[ [ get_array_sort c t ] \] is the domain and the range of [t]. - - {b See also}: {!get_array_sort_domain} - - {b See also}: {!get_array_sort_range} -*) -val get_array_sort: context -> sort -> sort * sort -(** - \[ [ get_tuple_sort c ty ] \] is the pair [(mk_decl, fields)] where [mk_decl] is the constructor declaration of [ty], and [fields] is the array of fields in [ty]. - - {b See also}: {!get_tuple_sort_mk_decl} - - {b See also}: {!get_tuple_sort_num_fields} - - {b See also}: {!get_tuple_sort_field_decl} -*) -val get_tuple_sort: context -> sort -> (func_decl * func_decl array) -(** - \[ [ datatype_constructor_refined ] \] is the refinement of a datatype constructor. - It contains the constructor declaration, recognizer, and list of accessor functions. -*) -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array -} -(** - \[ [ get_datatype_sort c ty ] \] is the array of triples [(constructor, recognizer, fields)] where [constructor] is the constructor declaration of [ty], [recognizer] is the recognizer for the [constructor], and [fields] is the array of fields in [ty]. - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} -*) -val get_datatype_sort: context -> sort -> datatype_constructor_refined array -(** - \[ [ get_model_constants c m ] \] is the array of constants in the model [m]. - - {b See also}: {!get_model_num_constants} - - {b See also}: {!get_model_constant} -*) -val get_model_constants: context -> model -> func_decl array -(** - \[ [ get_model_func_entry c m i j ] \] is the [j]'th entry in the [i]'th function in the model [m]. - - {b See also}: {!get_model_func_entry_num_args} - - {b See also}: {!get_model_func_entry_arg} - - {b See also}: {!get_model_func_entry_value} -*) -val get_model_func_entry: context -> model -> int -> int -> (ast array * ast);; -(** - \[ [ get_model_func_entries c m i ] \] is the array of entries in the [i]'th function in the model [m]. - - {b See also}: {!get_model_func_num_entries} - - {b See also}: {!get_model_func_entry} -*) -val get_model_func_entries: context -> model -> int -> (ast array * ast) array;; -(** - \[ [ get_model_funcs c m ] \] is the array of functions in the model [m]. Each function is represented by the triple [(decl, entries, else)], where [decl] is the declaration name for the function, [entries] is the array of entries in the function, and [else] is the default (else) value for the function. - - {b See also}: {!get_model_num_funcs} - - {b See also}: {!get_model_func_decl} - - {b See also}: {!get_model_func_entries} - - {b See also}: {!get_model_func_else} -*) -val get_model_funcs: context -> model -> - (symbol * - (ast array * ast) array * - ast) array -(** - \[ [ get_smtlib_formulas c ] \] is the array of formulas created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - - {b See also}: {!parse_smtlib_file_x} - - {b See also}: {!parse_smtlib_string} - - {b See also}: {!parse_smtlib_file} - - {b See also}: {!get_smtlib_num_formulas} - - {b See also}: {!get_smtlib_formula} -*) -val get_smtlib_formulas: context -> ast array -(** - \[ [get_smtlib_assumptions c] \] is the array of assumptions created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - - {b See also}: {!parse_smtlib_file_x} - - {b See also}: {!parse_smtlib_string} - - {b See also}: {!parse_smtlib_file} - - {b See also}: {!get_smtlib_num_assumptions} - - {b See also}: {!get_smtlib_assumption} -*) -val get_smtlib_assumptions: context -> ast array -(** - \[ [ get_smtlib_decls c ] \] is the array of declarations created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - - {b See also}: {!parse_smtlib_file_x} - - {b See also}: {!parse_smtlib_string} - - {b See also}: {!parse_smtlib_file} - - {b See also}: {!get_smtlib_num_decls} - - {b See also}: {!get_smtlib_decl} -*) -val get_smtlib_decls: context -> func_decl array -(** - \[ [ get_smtlib_parse_results c ] \] is the triple [(get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c)]. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - - {b See also}: {!parse_smtlib_file_x} - - {b See also}: {!parse_smtlib_string} - - {b See also}: {!parse_smtlib_file} - - {b See also}: {!get_smtlib_formulas} - - {b See also}: {!get_smtlib_assumptions} - - {b See also}: {!get_smtlib_decls} -*) -val get_smtlib_parse_results: context -> (ast array * ast array * func_decl array) -(** - \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_formula} - - {b See also}: {!parse_smtlib_string_x} -*) -val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast -(** - \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_formula} - - {b See also}: {!parse_smtlib_file_x} -*) -val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast -(** - \[ [ parse_smtlib_string_x c ... ] \] is [(parse_smtlib_string c ...; get_smtlib_parse_results c)] - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_x} - - {b See also}: {!parse_smtlib_string} - - {b See also}: {!get_smtlib_parse_results} -*) -val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) -(** - \[ [ parse_smtlib_file_x c ... ] \] is [(parse_smtlib_file c ...; get_smtlib_parse_results c)] - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - - {b See also}: {!parse_smtlib_file} - - {b See also}: {!get_smtlib_parse_results} -*) -val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) -(** - \[ [ symbol_refined ] \] is the refinement of a {!symbol} . - - {b See also}: {!symbol_refine} - - {b See also}: {!get_symbol_kind} -*) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string - | Symbol_unknown;; -(** - \[ [ symbol_refine c s ] \] is the refined symbol of [s]. - - {b See also}: {!symbol_refined} - - {b See also}: {!get_symbol_kind} -*) -val symbol_refine: context -> symbol -> symbol_refined;; -(** - \[ [ sort_refined ] \] is the refinement of a {!sort} . - - {b See also}: {!sort_refine} - - {b See also}: {!get_sort_kind} -*) -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_real - | Sort_bv of int - | Sort_array of (sort * sort) - | Sort_datatype of datatype_constructor_refined array - | Sort_relation - | Sort_finite_domain - | Sort_unknown of symbol -(** - \[ [ sort_refine c t ] \] is the refined sort of [t]. - - {b See also}: {!sort_refined} - - {b See also}: {!get_sort_kind} -*) -val sort_refine: context -> sort -> sort_refined;; -(** - \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} -*) -type binder_type = | Forall | Exists -(** - \[ [ numeral_refined ] \] is the refinement of a numeral . - Numerals whose fractional representation can be fit with - 64 bit integers are treated as small. -*) -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string -(** - \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} -*) -type term_refined = - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort -(** - \[ [ term_refine c a ] \] is the refined term of [a]. - - {b See also}: {!term_refined} -*) -val term_refine : context -> ast -> term_refined -(** - \[ [mk_theory c name ] \] create a custom theory. -*) -val mk_theory : context -> string -> theory -(** - \[ [set_delete_callback th cb] \] set callback when theory gets deleted. -*) -val set_delete_callback : theory -> (unit -> unit) -> unit -(** - \[ [set_reduce_app_callback th cb] \] set callback for simplifying theory terms. -*) -val set_reduce_app_callback : theory -> (func_decl -> ast array -> ast option) -> unit -(** - \[ [set_reduce_eq_callback th cb] \] set callback for simplifying equalities over theory terms. -*) -val set_reduce_eq_callback : theory -> (ast -> ast -> ast option) -> unit -(** - \[ [set_reduce_distinct_callback th cb] \] set callback for simplifying disequalities over theory terms. -*) -val set_reduce_distinct_callback : theory -> (ast array -> ast option) -> unit -(** - \[ [set_new_app_callback th cb] \] set callback for registering new application. -*) -val set_new_app_callback : theory -> (ast -> unit) -> unit -(** - \[ [set_new_elem_callback th cb] \] set callback for registering new element. - - {b See also}: the help for the corresponding C API function. -*) -val set_new_elem_callback : theory -> (ast -> unit) -> unit -(** - \[ [set_init_search_callback th cb] \] set callback when Z3 starts searching for a satisfying assignment. -*) -val set_init_search_callback : theory -> (unit -> unit) -> unit -(** - \[ [set_push_callback th cb] \] set callback for a logical context push. -*) -val set_push_callback : theory -> (unit -> unit) -> unit -(** - \[ [set_pop_callback th cb] \] set callback for a logical context pop. -*) -val set_pop_callback : theory -> (unit -> unit) -> unit -(** - \[ [set_restart_callback th cb] \] set callback for search restart. -*) -val set_restart_callback : theory -> (unit -> unit) -> unit -val set_reset_callback : theory -> (unit -> unit) -> unit -val set_final_check_callback : theory -> (unit -> bool) -> unit -val set_new_eq_callback : theory -> (ast -> ast -> unit) -> unit -val set_new_diseq_callback : theory -> (ast -> ast -> unit) -> unit -val set_new_assignment_callback : theory -> (ast -> bool -> unit) -> unit -val set_new_relevant_callback : theory -> (ast -> unit) -> unit + (** Parse the given string using the SMT-LIB2 parser. + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) + val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr + (** Parse the given file using the SMT-LIB2 parser. + {!parse_smtlib2_string} *) + val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr end -<<<<<<< HEAD -======= (** Set a global (or module) parameter, which is shared by all Z3 contexts. When a Z3 module is initialized it will use the value of these parameters @@ -9811,11 +2932,11 @@ val get_global_param : string -> string option {!set_global_param} *) -val global_param_reset_all : unit - - (** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) - val toggle_warning_messages : bool -> unit ->>>>>>> Updates to ML API. +val global_param_reset_all : unit -> unit + +(** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) +val toggle_warning_messages : bool -> unit + From 755ba2a2f7fe710bb4966bd19fbbd457596270d5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 4 Jun 2013 16:46:47 +0100 Subject: [PATCH 317/646] ML API: removing rich layer for now. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3_rich.ml | 3399 ---------------------------------------- src/api/ml/z3_rich.mli | 3071 ------------------------------------ 2 files changed, 6470 deletions(-) delete mode 100644 src/api/ml/z3_rich.ml delete mode 100644 src/api/ml/z3_rich.mli diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml deleted file mode 100644 index 0c2f95b6b..000000000 --- a/src/api/ml/z3_rich.ml +++ /dev/null @@ -1,3399 +0,0 @@ -\(** - The Z3 ML/Ocaml Interface. - - Copyright (C) 2012 Microsoft Corporation - @author CM Wintersteiger (cwinter) 2012-12-17 -*) - -open Z3enums - -(* Some helpers. *) -let null = Z3native.mk_null() -let is_null o = (Z3native.is_null o) - -(* Internal types *) -type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } -type context = z3_native_context - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - - -(** Internal stuff *) -module Internal = -struct - let dispose_context ctx = - if ctx.m_n_obj_cnt == 0 then ( - (Z3native.del_context ctx.m_n_ctx) - ) else ( - Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; - ) - - let create_context settings = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - Z3native.set_internal_error_handler v ; - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> dispose_context o in - Gc.finalise f res; - res - - let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) - let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) - let context_gno ctx = ctx.m_n_ctx - - - let z3obj_gc o = o.m_ctx - let z3obj_gnc o = (context_gno o.m_ctx) - - let z3obj_gno o = o.m_n_obj - let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - - let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - - let z3obj_create o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - - let z3obj_nil_ref x y = () - - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> - let res : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res -end - -open Internal - -module Log = -struct - let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - let close = Z3native.close_log - let append s = Z3native.append_log s -end - - -module Version = -struct - let major = let (x, _, _, _) = Z3native.get_version in x - let minor = let (_, x, _, _) = Z3native.get_version in x - let build = let (_, _, x, _) = Z3native.get_version in x - let revision = let (_, _, _, x) = Z3native.get_version in x - let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end - - -let mk_list ( f : int -> 'a ) ( n : int ) = - let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = - if (i >= n) then - tail - else - (mk_list' f (i+1) n ((f i) :: tail)) - in - mk_list' f 0 n [] - -let list_of_array ( x : _ array ) = - let f i = (Array.get x i) in - mk_list f (Array.length x) - -let mk_context ( cfg : ( string * string ) list ) = - create_context cfg - - -module Symbol = -struct - (* Symbol types *) - type int_symbol = z3_native_object - type string_symbol = z3_native_object - - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - - - let create_i ( ctx : context ) ( no : Z3native.ptr ) = - let res : int_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create_s ( ctx : context ) ( no : Z3native.ptr ) = - let res : string_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) - - let gc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gc n) - | S_Str(n) -> (z3obj_gc n) - - let gnc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gnc n) - | S_Str(n) -> (z3obj_gnc n) - - let gno ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gno n) - | S_Str(n) -> (z3obj_gno n) - - let symbol_lton ( a : symbol list ) = - let f ( e : symbol ) = (gno e) in - Array.of_list (List.map f a) - - let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) - let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL - let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) - let to_string ( o : symbol ) = - match (kind o) with - | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) - | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) - - let mk_int ( ctx : context ) ( i : int ) = - S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) - - let mk_string ( ctx : context ) ( s : string ) = - S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - - let mk_ints ( ctx : context ) ( names : int list ) = - let f elem = mk_int ( ctx : context ) elem in - (List.map f names) - - let mk_strings ( ctx : context ) ( names : string list ) = - let f elem = mk_string ( ctx : context ) elem in - (List.map f names) -end - - -module AST = -struct - type ast = z3_native_object - - let context_of_ast ( x : ast ) = (z3obj_gc x) - let nc_of_ast ( x : ast ) = (z3obj_gnc x) - let ptr_of_ast ( x : ast ) = (z3obj_gno x) - - let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST - | SORT_AST - | QUANTIFIER_AST - | APP_AST - | NUMERAL_AST - | VAR_AST -> z3_native_object_of_ast_ptr ctx no - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") - - module ASTVector = - struct - type ast_vector = z3_native_object - - let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_vector = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_vector_inc_ref ; - dec_ref = Z3native.ast_vector_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_size ( x : ast_vector ) = - Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) - - let get ( x : ast_vector ) ( i : int ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) - - let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) - - let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size - - let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) - - let translate ( x : ast_vector ) ( to_ctx : context ) = - ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) - end - - module ASTMap = - struct - type ast_map = z3_native_object - - let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_map = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_map_inc_ref ; - dec_ref = Z3native.ast_map_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let contains ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let find ( x : ast_map ) ( key : ast ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - - let insert ( x : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) - - let erase ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let reset ( x : ast_map ) = - Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : ast_map ) = - Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) - - let get_keys ( x : ast_map ) = - let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in - let f i = (ASTVector.get av i) in - mk_list f (ASTVector.get_size av) - - let to_string ( x : ast_map ) = - Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) - let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) - let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) - - let is_expr ( x : ast ) = - match get_ast_kind ( x : ast ) with - | APP_AST - | NUMERAL_AST - | QUANTIFIER_AST - | VAR_AST -> true - | _ -> false - - let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST - let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST - let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST - let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST - - let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - - - let ( = ) ( a : ast ) ( b : ast ) = (a == b) || - if (z3obj_gnc a) != (z3obj_gnc b) then - false - else - Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) - - let compare a b = - if (get_id a) < (get_id b) then -1 else - if (get_id a) > (get_id b) then 1 else - 0 - - let ( < ) (a : ast) (b : ast) = (compare a b) - - let translate ( x : ast ) ( to_ctx : context ) = - if (z3obj_gnc x) == (context_gno to_ctx) then - x - else - ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr - let unwrap_ast ( x : ast ) = (z3obj_gno x) -end - -open AST - - -module Sort = -struct - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> - let q = (z3_native_object_of_ast_ptr ctx no) in - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then - raise (Z3native.Exception "Invalid coercion") - else - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - - let ast_of_sort s = match s with Sort(x) -> x - let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x - - let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - - let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) - let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) - let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - - let sort_lton ( a : sort list ) = - let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let ( = ) : sort -> sort -> bool = fun a b -> - (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) - - - let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) - let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) - let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) - let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) - - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; - (z3obj_create res) ; - UninterpretedSort(Sort(res)) - - let mk_uninterpreted_s ( ctx : context ) ( s : string ) = - mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) -end - -open Sort - - -module rec FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - val func_decl_of_ptr : context -> Z3native.ptr -> func_decl - val gc : func_decl -> context - val gnc : func_decl -> Z3native.ptr - val gno : func_decl -> Z3native.ptr - module Parameter : - sig - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - val get_kind : parameter -> Z3enums.parameter_kind - val get_int : parameter -> int - val get_float : parameter -> float - val get_symbol : parameter -> Symbol.symbol - val get_sort : parameter -> Sort.sort - val get_ast : parameter -> AST.ast - val get_func_decl : parameter -> func_decl - val get_rational : parameter -> string - end - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - val ( = ) : func_decl -> func_decl -> bool - val to_string : func_decl -> string - val get_id : func_decl -> int - val get_arity : func_decl -> int - val get_domain_size : func_decl -> int - val get_domain : func_decl -> Sort.sort list - val get_range : func_decl -> Sort.sort - val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_name : func_decl -> Symbol.symbol - val get_num_parameters : func_decl -> int - val get_parameters : func_decl -> Parameter.parameter list - val apply : func_decl -> Expr.expr list -> Expr.expr -end = struct - type func_decl = FuncDecl of AST.ast - - let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - FuncDecl(z3_native_object_of_ast_ptr ctx no) - - let ast_of_func_decl f = match f with FuncDecl(x) -> x - - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) - let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) - let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - - module Parameter = - struct - type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - let get_kind ( x : parameter ) = - (match x with - | P_Int(_) -> PARAMETER_INT - | P_Dbl(_) -> PARAMETER_DOUBLE - | P_Sym(_) -> PARAMETER_SYMBOL - | P_Srt(_) -> PARAMETER_SORT - | P_Ast(_) -> PARAMETER_AST - | P_Fdl(_) -> PARAMETER_FUNC_DECL - | P_Rat(_) -> PARAMETER_RATIONAL) - - let get_int ( x : parameter ) = - match x with - | P_Int(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an int") - - let get_float ( x : parameter ) = - match x with - | P_Dbl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a double") - - let get_symbol ( x : parameter ) = - match x with - | P_Sym(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a symbol") - - let get_sort ( x : parameter ) = - match x with - | P_Srt(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a sort") - - let get_ast ( x : parameter ) = - match x with - | P_Ast(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an ast") - - let get_func_decl ( x : parameter ) = - match x with - | P_Fdl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a func_decl") - - let get_rational ( x : parameter ) = - match x with - | P_Rat(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a rational string") - end - - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - create_ndr ctx name domain range - - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = - mk_func_decl ctx (Symbol.mk_string ctx name) domain range - - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - create_pdr ctx prefix domain range - - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_ndr ctx name [] range - - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = - create_ndr ctx (Symbol.mk_string ctx name) [] range - - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = - create_pdr ctx prefix [] range - - - let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) - - let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) - - let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) - - let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) - - let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) - - let get_domain ( x : func_decl ) = - let n = (get_domain_size x) in - let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in - mk_list f n - - let get_range ( x : func_decl ) = - sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) - - let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) - - let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) - - let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) - - let get_parameters ( x : func_decl ) = - let n = (get_num_parameters x) in - let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) - ) in - mk_list f n - - let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args -end - - -and Params : -sig - type params = z3_native_object - module ParamDescrs : - sig - type param_descrs - val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - val get_names : param_descrs -> Symbol.symbol list - val get_size : param_descrs -> int - val to_string : param_descrs -> string - end - val add_bool : params -> Symbol.symbol -> bool -> unit - val add_int : params -> Symbol.symbol -> int -> unit - val add_double : params -> Symbol.symbol -> float -> unit - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - val add_s_bool : params -> string -> bool -> unit - val add_s_int : params -> string -> int -> unit - val add_s_double : params -> string -> float -> unit - val add_s_symbol : params -> string -> Symbol.symbol -> unit - val mk_params : context -> params - val to_string : params -> string -end = struct - type params = z3_native_object - - module ParamDescrs = - struct - type param_descrs = z3_native_object - - let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : param_descrs = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.param_descrs_inc_ref ; - dec_ref = Z3native.param_descrs_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let validate ( x : param_descrs ) ( p : params ) = - Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) - - let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) - - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in - let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = - Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = - Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = - Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = - Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - - let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = - add_bool x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = - add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - - let mk_params ( ctx : context ) = - let res : params = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.params_inc_ref ; - dec_ref = Z3native.params_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; - (z3obj_create res) ; - res - - let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) -end - -(** General expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - val expr_of_ptr : context -> Z3native.ptr -> expr - val gc : expr -> context - val gnc : expr -> Z3native.ptr - val gno : expr -> Z3native.ptr - val expr_lton : expr list -> Z3native.ptr array - val ast_of_expr : expr -> AST.ast - val expr_of_ast : AST.ast -> expr - val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr - val simplify : expr -> Params.params option -> expr - val get_simplify_help : context -> string - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - val get_func_decl : expr -> FuncDecl.func_decl - val get_bool_value : expr -> Z3enums.lbool - val get_num_args : expr -> int - val get_args : expr -> expr list - val update : expr -> expr list -> expr - val substitute : expr -> expr list -> expr list -> expr - val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr list -> expr - val translate : expr -> context -> expr - val to_string : expr -> string - val is_numeral : expr -> bool - val is_well_sorted : expr -> bool - val get_sort : expr -> Sort.sort - val is_bool : expr -> bool - val is_const : expr -> bool - val is_true : expr -> bool - val is_false : expr -> bool - val is_eq : expr -> bool - val is_distinct : expr -> bool - val is_ite : expr -> bool - val is_and : expr -> bool - val is_or : expr -> bool - val is_iff : expr -> bool - val is_xor : expr -> bool - val is_not : expr -> bool - val is_implies : expr -> bool - val is_label : expr -> bool - val is_label_lit : expr -> bool - val is_oeq : expr -> bool - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - val mk_const_s : context -> string -> Sort.sort -> expr - val mk_const_f : context -> FuncDecl.func_decl -> expr - val mk_fresh_const : context -> string -> Sort.sort -> expr - val mk_app : context -> FuncDecl.func_decl -> expr list -> expr - val mk_numeral_string : context -> string -> Sort.sort -> expr - val mk_numeral_int : context -> int -> Sort.sort -> expr -end = struct - type expr = Expr of AST.ast - - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) - - let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then - Expr(z3_native_object_of_ast_ptr ctx no) - else - let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) no) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - raise (Z3native.Exception "Unsupported numeral object") - else - Expr(z3_native_object_of_ast_ptr ctx no) - - let expr_of_ast a = - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Expr(a) - - let ast_of_expr e = match e with Expr(a) -> a - - let expr_lton ( a : expr list ) = - let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> - match f with FuncDecl.FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in - expr_of_ptr ctx o - - let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (Expr.gnc x) (Expr.gno x)) - | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (Expr.gnc x) (Expr.gno x) (z3obj_gno pp)) - - let get_simplify_help ( ctx : context ) = - Z3native.simplify_get_help (context_gno ctx) - - let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (Expr.gnc x) (Expr.gno x)) - - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (Expr.gnc x) (Expr.gno x)) - - let get_num_args ( x : expr ) = Z3native.get_app_num_args (Expr.gnc x) (Expr.gno x) - - let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (Expr.gnc x) (Expr.gno x) i) in - mk_list f n - - let update ( x : expr ) ( args : expr list ) = - if (List.length args <> (get_num_args x)) then - raise (Z3native.Exception "Number of arguments does not match") - else - expr_of_ptr (Expr.gc x) (Z3native.update_term (Expr.gnc x) (Expr.gno x) (List.length args) (expr_lton args)) - - let substitute ( x : expr ) from to_ = - if (List.length from) <> (List.length to_) then - raise (Z3native.Exception "Argument sizes do not match") - else - expr_of_ptr (Expr.gc x) (Z3native.substitute (Expr.gnc x) (Expr.gno x) (List.length from) (expr_lton from) (expr_lton to_)) - - let substitute_one ( x : expr ) from to_ = - substitute ( x : expr ) [ from ] [ to_ ] - - let substitute_vars ( x : expr ) to_ = - expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (Expr.gnc x) (Expr.gno x) (List.length to_) (expr_lton to_)) - - let translate ( x : expr ) to_ctx = - if (Expr.gc x) == to_ctx then - x - else - expr_of_ptr to_ctx (Z3native.translate (Expr.gnc x) (Expr.gno x) (context_gno to_ctx)) - - let to_string ( x : expr ) = Z3native.ast_to_string (Expr.gnc x) (Expr.gno x) - - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) - - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (Expr.gnc x) (Expr.gno x) - - let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)) - - let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (Expr.gnc x) - (Z3native.mk_bool_sort (Expr.gnc x)) - (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) - - let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (get_num_args x) == 0 && - (FuncDecl.get_domain_size (get_func_decl x)) == 0 - - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) - - let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) range - - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] - - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args - - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) - - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) -end - -open FuncDecl -open Expr - -module Boolean = -struct - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.ast_of_ptr ctx no) in - BoolExpr(Expr.Expr(a)) - - let bool_expr_of_expr e = - match e with Expr.Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - - let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(sort_of_ptr ctx no) - - let sort_of_bool_sort s = match s with BoolSort(x) -> x - - let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - - let expr_of_bool_expr e = match e with BoolExpr(x) -> x - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) - - let mk_sort ( ctx : context ) = - BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - let s = (match (mk_sort ctx) with BoolSort(q) -> q) in - BoolExpr(Expr.mk_const ctx name s) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_true ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) - - let mk_false ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) - - let mk_val ( ctx : context ) ( value : bool ) = - if value then mk_true ctx else mk_false ctx - - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) - - let mk_distinct ( ctx : context ) ( args : expr list ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_not ( ctx : context ) ( a : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - - let mk_and ( ctx : context ) ( args : bool_expr list ) = - let f x = (Expr.gno (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - - let mk_or ( ctx : context ) ( args : bool_expr list ) = - let f x = (Expr.gno (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) -end - - -module Quantifier = -struct - type quantifier = Quantifier of expr - - let expr_of_quantifier e = match e with Quantifier(x) -> x - - let quantifier_of_expr e = - match e with Expr.Expr(a) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.QUANTIFIER_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Quantifier(e) - - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - - module Pattern = - struct - type pattern = Pattern of ast - - let ast_of_pattern e = match e with Pattern(x) -> x - - let pattern_of_ast a = - (* CMW: Unchecked ok? *) - Pattern(a) - - let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) - let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) - let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - mk_list f n - - let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) - end - - let get_index ( x : expr ) = - if not (AST.is_var (match x with Expr.Expr(a) -> a)) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value (Expr.gnc x) (Expr.gno x) - - let is_universal ( x : quantifier ) = - Z3native.is_quantifier_forall (gnc x) (gno x) - - let is_existential ( x : quantifier ) = not (is_universal x) - - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) - - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) - - let get_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) - - let get_no_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) - - let get_bound_variable_names ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in - mk_list f n - - let get_bound_variable_sorts ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in - mk_list f n - - let get_body ( x : quantifier ) = - Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) - - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - - let mk_pattern ( ctx : context ) ( terms : expr list ) = - if (List.length terms) == 0 then - raise (Z3native.Exception "Cannot create a pattern from zero terms") - else - Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) - - let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - else - (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id - else - mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id -end - - -module Array_ = -struct - type array_sort = ArraySort of sort - type array_expr = ArrayExpr of expr - - let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (expr_of_ptr ctx no) in - ArrayExpr(e) - - let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - ArraySort(s) - - let sort_of_array_sort s = match s with ArraySort(x) -> x - - let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - - let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - - let expr_of_array_expr e = match e with ArrayExpr(x) -> x - - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - - let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) - let is_array ( x : expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) - - let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) - - let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) domain range - - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) - - let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) - - let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) - - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = - let m x = (Expr.gno (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) - - let mk_term_array ( ctx : context ) ( arg : array_expr ) = - array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) -end - - -module Set = -struct - type set_sort = SetSort of sort - - let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - SetSort(s) - - let sort_of_set_sort s = match s with SetSort(x) -> x - - let mk_sort ( ctx : context ) ( ty : sort ) = - set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) - - - let mk_empty ( ctx : context ) ( domain : sort ) = - (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) - - let mk_full ( ctx : context ) ( domain : sort ) = - expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) - - let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_union ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_intersection ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) - - let mk_complement ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) - - let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) - - let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) - -end - - -module FiniteDomain = -struct - type finite_domain_sort = FiniteDomainSort of sort - - let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x - - let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in - FiniteDomainSort(s) - - let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_sort ctx (Symbol.mk_string ctx name) size - - - let is_finite_domain ( x : expr ) = - let nc = (Expr.gnc x) in - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) - - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - - let get_size ( x : finite_domain_sort ) = - let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in - if r then v - else raise (Z3native.Exception "Conversion failed.") -end - - -module Relation = -struct - type relation_sort = RelationSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - RelationSort(s) - - let sort_of_relation_sort s = match s with RelationSort(x) -> x - - let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - - - let is_relation ( x : expr ) = - let nc = (Expr.gnc x) in - ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) - - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - - let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) - - let get_column_sorts ( x : relation_sort ) = - let n = get_arity x in - let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in - mk_list f n - -end - - -module Datatype = -struct - type datatype_sort = DatatypeSort of sort - type datatype_expr = DatatypeExpr of expr - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - DatatypeSort(s) - - let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x - - let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - - let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - - let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - - module Constructor = - struct - type constructor = z3_native_object - - let _sizes = Hashtbl.create 0 - - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - let n = (List.length field_names) in - if n != (List.length sorts) then - raise (Z3native.Exception "Number of field names does not match number of sorts") - else - if n != (List.length sort_refs) then - raise (Z3native.Exception "Number of field names does not match number of sort refs") - else - let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) - (Symbol.gno recognizer) - n - (Symbol.symbol_lton field_names) - (sort_lton sorts) - (Array.of_list sort_refs)) in - let no : constructor = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - (z3obj_sno no ctx ptr) ; - (z3obj_create no) ; - let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f no ; - Hashtbl.add _sizes no n ; - no - - let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x - - let get_constructor_decl ( x : constructor ) = - let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) a - - let get_tester_decl ( x : constructor ) = - let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) b - - let get_accessor_decls ( x : constructor ) = - let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in - mk_list f (Array.length c) - - end - - module ConstructorList = - struct - type constructor_list = z3_native_object - - let create ( ctx : context ) ( c : Constructor.constructor list ) = - let res : constructor_list = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - let f x =(z3obj_gno x) in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; - (z3obj_create res) ; - let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f res; - res - end - - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - Constructor.create ctx name recognizer field_names sorts sort_refs - - - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = - let f x = (z3obj_gno x) in - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in - sort_of_ptr ctx x - - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = - mk_sort ctx (Symbol.mk_string ctx name) constructors - - let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = - let n = (List.length names) in - let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in - let cla = (Array.of_list (List.map f c)) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in - let g i = (sort_of_ptr ctx (Array.get r i)) in - mk_list g (Array.length r) - - let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = - mk_sorts ctx - ( - let f e = (Symbol.mk_string ctx e) in - List.map f names - ) - c - - let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) - - let get_constructors ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - mk_list f n - - let get_recognizers ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in - mk_list f n - - let get_accessors ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = ( - let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in - mk_list g ds - ) in - mk_list f n -end - - -module Enumeration = -struct - type enum_sort = EnumSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = - let s = (sort_of_ptr ctx no) in - let res = EnumSort(s) in - res - - let sort_of_enum_sort s = match s with EnumSort(x) -> x - - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in - sort_of_ptr ctx a (list_of_array b) (list_of_array c) - - let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = - mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - - let get_const_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in - mk_list f n - - let get_tester_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in - mk_list f n - -end - - -module List_ = -struct - type list_sort = ListSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - let res = ListSort(s) in - res - - let sort_of_list_sort s = match s with ListSort(x) -> x - - let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - sort_of_ptr ctx r a b c d e f - - let mk_list_s ( ctx : context ) (name : string) elem_sort = - mk_sort ctx (Symbol.mk_string ctx name) elem_sort - - let get_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) - - let get_is_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) - - let get_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) - - let get_is_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) - - let get_head_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) - - let get_tail_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] -end - - -module Tuple = -struct - type tuple_sort = TupleSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - TupleSort(s) - - let sort_of_tuple_sort s = match s with TupleSort(x) -> x - - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = - let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in - sort_of_ptr ctx r - - let get_mk_decl ( x : tuple_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) - - let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) - - let get_field_decls ( x : tuple_sort ) = - let n = get_num_fields x in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in - mk_list f n -end - - -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> arith_sort - val expr_of_arith_expr : arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> arith_expr - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_const : context -> Symbol.symbol -> int_expr - val mk_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_numeral_s : context -> string -> int_num - val mk_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_const : context -> Symbol.symbol -> real_expr - val mk_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr list -> arith_expr - val mk_mul : context -> arith_expr list -> arith_expr - val mk_sub : context -> arith_expr list -> arith_expr - val mk_unary_minus : context -> arith_expr -> arith_expr - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end = struct - type arith_sort = ArithSort of sort - type arith_expr = ArithExpr of expr - - let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - - let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) - - let sort_of_arith_sort s = match s with ArithSort(x) -> x - let expr_of_arith_expr e = match e with ArithExpr(x) -> x - - let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - - let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_sort_of_sort (sort_of_ptr ctx no) - - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_const : context -> Symbol.symbol -> int_expr - val mk_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_numeral_s : context -> string -> int_num - val mk_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - - let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - - let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (int_expr_of_ptr ctx no) - - let arith_sort_of_int_sort s = match s with IntSort(x) -> x - let arith_expr_of_int_expr e = match e with IntExpr(x) -> x - let int_expr_of_int_num e = match e with IntNum(x) -> x - - let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - - let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) - - let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) - let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) - let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) - let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) - let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) - let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) - let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) - let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) - let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - - let mk_sort ( ctx : context ) = - int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - - let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) - - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_int2real ( ctx : context ) ( t : int_expr ) = - Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) - - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) - end - - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : real_sort -> arith_sort - val real_sort_of_arith_sort : arith_sort -> real_sort - val arith_expr_of_real_expr : real_expr -> arith_expr - val real_expr_of_rat_num : rat_num -> real_expr - val real_expr_of_arith_expr : arith_expr -> real_expr - val rat_num_of_real_expr : real_expr -> rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_const : context -> Symbol.symbol -> real_expr - val mk_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - let arith_sort_of_real_sort s = match s with RealSort(x) -> x - let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - let real_expr_of_rat_num e = match e with RatNum(x) -> x - - let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - - let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - - let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (real_expr_of_ptr ctx no) - - let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - - let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) - let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) - let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) - let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) - let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) - let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) - let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) - let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) - let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - - - let mk_sort ( ctx : context ) = - real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - - let get_numerator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) - - let get_denominator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) - - let to_decimal_string ( x : rat_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - - let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = - if (den == 0) then - raise (Z3native.Exception "Denominator is zero") - else - rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) - - let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) - end - - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x - - let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - - let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) - - let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) - let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) - let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - - - let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) - - let to_lower ( x : algebraic_num ) precision = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) - - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - end - - let is_int ( x : expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - - let mk_add ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_mul ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_sub ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) - - let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) - - let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) - - let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) - - let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) - - let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) - - let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) -end - - -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - val mk_sort : context -> int -> bitvec_sort - val is_bv : Expr.expr -> bool - val is_bv_numeral : Expr.expr -> bool - val is_bv_bit1 : Expr.expr -> bool - val is_bv_bit0 : Expr.expr -> bool - val is_bv_uminus : Expr.expr -> bool - val is_bv_add : Expr.expr -> bool - val is_bv_sub : Expr.expr -> bool - val is_bv_mul : Expr.expr -> bool - val is_bv_sdiv : Expr.expr -> bool - val is_bv_udiv : Expr.expr -> bool - val is_bv_SRem : Expr.expr -> bool - val is_bv_urem : Expr.expr -> bool - val is_bv_smod : Expr.expr -> bool - val is_bv_sdiv0 : Expr.expr -> bool - val is_bv_udiv0 : Expr.expr -> bool - val is_bv_srem0 : Expr.expr -> bool - val is_bv_urem0 : Expr.expr -> bool - val is_bv_smod0 : Expr.expr -> bool - val is_bv_ule : Expr.expr -> bool - val is_bv_sle : Expr.expr -> bool - val is_bv_uge : Expr.expr -> bool - val is_bv_sge : Expr.expr -> bool - val is_bv_ult : Expr.expr -> bool - val is_bv_slt : Expr.expr -> bool - val is_bv_ugt : Expr.expr -> bool - val is_bv_sgt : Expr.expr -> bool - val is_bv_and : Expr.expr -> bool - val is_bv_or : Expr.expr -> bool - val is_bv_not : Expr.expr -> bool - val is_bv_xor : Expr.expr -> bool - val is_bv_nand : Expr.expr -> bool - val is_bv_nor : Expr.expr -> bool - val is_bv_xnor : Expr.expr -> bool - val is_bv_concat : Expr.expr -> bool - val is_bv_signextension : Expr.expr -> bool - val is_bv_zeroextension : Expr.expr -> bool - val is_bv_extract : Expr.expr -> bool - val is_bv_repeat : Expr.expr -> bool - val is_bv_reduceor : Expr.expr -> bool - val is_bv_reduceand : Expr.expr -> bool - val is_bv_comp : Expr.expr -> bool - val is_bv_shiftleft : Expr.expr -> bool - val is_bv_shiftrightlogical : Expr.expr -> bool - val is_bv_shiftrightarithmetic : Expr.expr -> bool - val is_bv_rotateleft : Expr.expr -> bool - val is_bv_rotateright : Expr.expr -> bool - val is_bv_rotateleftextended : Expr.expr -> bool - val is_bv_rotaterightextended : Expr.expr -> bool - val is_int_to_bv : Expr.expr -> bool - val is_bv_to_int : Expr.expr -> bool - val is_bv_carry : Expr.expr -> bool - val is_bv_xor3 : Expr.expr -> bool - val get_size : bitvec_sort -> int - val get_int : bitvec_num -> int - val to_string : bitvec_num -> string - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - val mk_const_s : context -> string -> int -> bitvec_expr - val mk_not : context -> bitvec_expr -> Expr.expr - val mk_redand : context -> bitvec_expr -> Expr.expr - val mk_redor : context -> bitvec_expr -> Expr.expr - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_neg : context -> bitvec_expr -> bitvec_expr - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_numeral : context -> string -> int -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of sort - type bitvec_expr = BitVecExpr of expr - type bitvec_num = BitVecNum of bitvec_expr - - let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x - - let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - - let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_sort_of_sort (sort_of_ptr ctx no) - - let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - - let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_expr_of_expr (expr_of_ptr ctx no) - - let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - - let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) - - let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x - let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - - - let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) - let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) - let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) - let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) - let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) - let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - - - let mk_sort ( ctx : context ) size = - bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) - let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) - let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_const ctx (Symbol.mk_string ctx name) size - let mk_not ( ctx : context ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - let mk_redand ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - let mk_redor ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - let mk_neg ( ctx : context ) ( t : bitvec_expr) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) -end - - -module Proof = -struct - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) -end - - -module Goal = -struct - type goal = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : goal = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.goal_inc_ref ; - dec_ref = Z3native.goal_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_precision ( x : goal ) = - goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) - - let is_precise ( x : goal ) = - (get_precision x) == GOAL_PRECISE - - let is_underapproximation ( x : goal ) = - (get_precision x) == GOAL_UNDER - - let is_overapproximation ( x : goal ) = - (get_precision x) == GOAL_OVER - - let is_garbage ( x : goal ) = - (get_precision x) == GOAL_UNDER_OVER - - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in - ignore (List.map f constraints) ; - () - - let is_inconsistent ( x : goal ) = - Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) - - let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) - - let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) - - let get_formulas ( x : goal ) = - let n = get_size x in - let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) - (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in - mk_list f n - - let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) - - let is_decided_sat ( x : goal ) = - Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) - - let is_decided_unsat ( x : goal ) = - Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) - - let translate ( x : goal ) ( to_ctx : context ) = - create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let simplify ( x : goal ) ( p : Params.params option ) = - let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in - Z3native.tactic_inc_ref (z3obj_gnc x) tn ; - let arn = match p with - | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) - | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) - in - Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; - let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in - let res = if sg == 0 then - raise (Z3native.Exception "No subgoals") - else - Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in - Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; - Z3native.tactic_dec_ref (z3obj_gnc x) tn ; - create (z3obj_gc x) res - - let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) - - let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Model = -struct - type model = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : model = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.model_inc_ref ; - dec_ref = Z3native.model_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncInterp = - struct - type func_interp = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_interp = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_interp_inc_ref ; - dec_ref = Z3native.func_interp_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncEntry = - struct - type func_entry = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_entry = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_entry_inc_ref ; - dec_ref = Z3native.func_entry_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_value ( x : func_entry ) = - expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) - - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) - - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) - - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) - - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (List.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null np) then - None - else - Some (expr_of_ptr (z3obj_gc x) np) - - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if not (Z3native.is_as_array (z3obj_gnc x) n) then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in - if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) - - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) - - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - (mk_list f n_funcs) @ (mk_list g n_consts) - - exception ModelEvaluationFailedException of string - - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in - if not r then - raise (ModelEvaluationFailedException "evaluation failed") - else - expr_of_ptr (z3obj_gc x) v - - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) - - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - mk_list f n - - let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Probe = -struct - type probe = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : probe = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.probe_inc_ref ; - dec_ref = Z3native.probe_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - let apply ( x : probe ) ( g : Goal.goal ) = - Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) - - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes (context_gno ctx) - - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name (context_gno ctx) i) in - mk_list f n - - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr (context_gno ctx) name - - let mk_probe ( ctx : context ) ( name : string ) = - (create ctx (Z3native.mk_probe (context_gno ctx) name)) - - let const ( ctx : context ) ( v : float ) = - (create ctx (Z3native.probe_const (context_gno ctx) v)) - - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let not_ ( ctx : context ) ( p : probe ) = - (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) -end - - -module Tactic = -struct - type tactic = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : tactic = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.tactic_inc_ref ; - dec_ref = Z3native.tactic_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module ApplyResult = - struct - type apply_result = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : apply_result = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.apply_result_inc_ref ; - dec_ref = Z3native.apply_result_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) - - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_subgoal ( x : apply_result ) ( i : int ) = - Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) - - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) - - let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) - - let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = - match p with - | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) - | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) - - let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) - - let get_tactic_names ( ctx : context ) = - let n = (get_num_tactics ctx ) in - let f i = (Z3native.get_tactic_name (context_gno ctx) i) in - mk_list f n - - let get_tactic_description ( ctx : context ) ( name : string ) = - Z3native.tactic_get_descr (context_gno ctx) name - - let mk_tactic ( ctx : context ) ( name : string ) = - create ctx (Z3native.mk_tactic (context_gno ctx) name) - - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = - let f p c = (match p with - | None -> (Some (z3obj_gno c)) - | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in - match (List.fold_left f None ts) with - | None -> - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - | Some(x) -> - let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) - - let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) - - let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) - - let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) - - let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) - - let skip ( ctx : context ) = - create ctx (Z3native.tactic_skip (context_gno ctx)) - - let fail ( ctx : context ) = - create ctx (Z3native.tactic_fail (context_gno ctx)) - - let fail_if ( ctx : context ) ( p : Probe.probe ) = - create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) - - let fail_if_not_decided ( ctx : context ) = - create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) - - let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) - - let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - using_params ctx t p - - let par_or ( ctx : context ) ( t : tactic list ) = - let f e = (z3obj_gno e) in - create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) - - let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let interrupt ( ctx : context ) = - Z3native.interrupt (context_gno ctx) -end - - -module Solver = -struct - type solver = z3_native_object - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : solver = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.solver_inc_ref ; - dec_ref = Z3native.solver_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let string_of_status ( s : status) = match s with - | UNSATISFIABLE -> "unsatisfiable" - | SATISFIABLE -> "satisfiable" - | _ -> "unknown" - - module Statistics = - struct - type statistics = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : statistics = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.stats_inc_ref ; - dec_ref = Z3native.stats_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - module Entry = - struct - type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } - - let create_si k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = true ; - m_is_float = false ; - m_int = v ; - m_float = 0.0 - } in - res - - let create_sd k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = false ; - m_is_float = true ; - m_int = 0 ; - m_float = v - } in - res - - - let get_key (x : statistics_entry) = x.m_key - let get_int (x : statistics_entry) = x.m_int - let get_float (x : statistics_entry) = x.m_float - let is_int (x : statistics_entry) = x.m_is_int - let is_float (x : statistics_entry) = x.m_is_float - let to_string_value (x : statistics_entry) = - if (is_int x) then - string_of_int (get_int x) - else if (is_float x) then - string_of_float (get_float x) - else - raise (Z3native.Exception "Unknown statistical entry type") - let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) - end - - let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : statistics ) = - let n = (get_size x ) in - let f i = ( - let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in - if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) - else - (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) - ) in - mk_list f n - - let get_keys ( x : statistics ) = - let n = (get_size x) in - let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get ( x : statistics ) ( key : string ) = - let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in - List.fold_left f None (get_entries x) - end - - let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_parameters ( x : solver ) ( p : Params.params )= - Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : solver ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) - - let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n - - let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (List.map f constraints) - - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = - if ((List.length cs) != (List.length ps)) then - raise (Z3native.Exception "Argument size mismatch") - else - let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in - ignore (List.iter2 f cs ps) - - let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) - - let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVector.get_size a) - - let get_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size a) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in - mk_list f n - - let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = - let r = - if ((List.length assumptions) == 0) then - lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) - else - let f x = (Expr.gno (Boolean.expr_of_bool_expr x)) in - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) - in - match r with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN - - let get_model ( x : solver ) = - let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (Model.create (z3obj_gc x) q) - - let get_proof ( x : solver ) = - let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size cn) in - let f i = (AST.ASTVector.get cn i) in - mk_list f n - - let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_statistics ( x : solver ) = - (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) - - let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = - match logic with - | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) - - let mk_solver_s ( ctx : context ) ( logic : string ) = - mk_solver ctx (Some (Symbol.mk_string ctx logic)) - - let mk_simple_solver ( ctx : context ) = - (create ctx (Z3native.mk_simple_solver (context_gno ctx))) - - let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = - (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) - - let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Fixedpoint = -struct - type fixedpoint = z3_native_object - - let create ( ctx : context ) = - let res : fixedpoint = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.fixedpoint_inc_ref ; - dec_ref = Z3native.fixedpoint_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; - (z3obj_create res) ; - res - - - let get_help ( x : fixedpoint ) = - Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_params ( x : fixedpoint ) ( p : Params.params )= - Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (List.map f constraints) ; - () - - let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - - let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = - match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) - - let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let query_r ( x : fixedpoint ) ( relations : func_decl list ) = - let f x = ptr_of_ast (ast_of_func_decl x) in - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let push ( x : fixedpoint ) = - Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : fixedpoint ) = - Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - - let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) - - let get_answer ( x : fixedpoint ) = - let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_reason_unknown ( x : fixedpoint ) = - Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) - - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) - - let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = - let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) - - let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let mk_fixedpoint ( ctx : context ) = create ctx -end - -module Options = -struct - - let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value (context_gno ctx) id value - - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - - let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages enabled -end - - -module SMT = -struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = - Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) - (Boolean.gno formula) - - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_file (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) - - let get_smtlib_formulas ( ctx : context ) = - let n = (get_num_smtlib_formulas ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) - - let get_smtlib_assumptions ( ctx : context ) = - let n = (get_num_smtlib_assumptions ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) - - let get_smtlib_decls ( ctx : context ) = - let n = (get_num_smtlib_decls ctx) in - let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in - mk_list f n - - let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - - let get_smtlib_sorts ( ctx : context ) = - let n = (get_num_smtlib_sorts ctx) in - let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in - mk_list f n - - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) -end - - -let set_global_param ( id : string ) ( value : string ) = - (Z3native.global_param_set id value) - -let get_global_param ( id : string ) = - let (r, v) = (Z3native.global_param_get id) in - if not r then - None - else - Some v - -let global_param_reset_all = - Z3native.global_param_reset_all diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli deleted file mode 100644 index f2ecd326d..000000000 --- a/src/api/ml/z3_rich.mli +++ /dev/null @@ -1,3071 +0,0 @@ -(** - The Z3 ML/Ocaml Interface. - - Copyright (C) 2012 Microsoft Corporation - @author CM Wintersteiger (cwinter) 2012-12-17 - - NOTE: This is the *rich* version of the interface, using more - type information directly in the type system. Coercion functions - are provided to tran coerce on type into another where applicable. -*) - -(** Context objects. - - Most interactions with Z3 are interpreted in some context; many users will only - require one such object, but power users may require more than one. To start using - Z3, do - - - let ctx = (mk_context []) in - (...) - - - where a list of pairs of strings may be passed to set options on - the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (mk_context cfg) in - (...) - -*) -type context - -(** Create a context object *) -val mk_context : (string * string) list -> context - -(** Interaction logging for Z3 - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) -module Log : -sig - (** Open an interaction log file. - @return True if opening the log file succeeds, false otherwise. *) - (* CMW: "open" seems to be a reserved keyword? *) - val open_ : string -> bool - - (** Closes the interaction log. *) - val close : unit - - (** Appends a user-provided string to the interaction log. *) - val append : string -> unit -end - -(** Version information *) -module Version : -sig - (** The major version. *) - val major : int - - (** The minor version. *) - val minor : int - - (** The build version. *) - val build : int - - (** The revision. *) - val revision : int - - (** A string representation of the version information. *) - val to_string : string -end - -(** Symbols are used to name several term and type constructors *) -module Symbol : -sig - (** Numbered Symbols *) - type int_symbol - - (** Named Symbols *) - type string_symbol - - (** Symbols *) - type symbol = S_Int of int_symbol | S_Str of string_symbol - - (** The kind of the symbol (int or string) *) - val kind : symbol -> Z3enums.symbol_kind - - (** Indicates whether the symbol is of Int kind *) - val is_int_symbol : symbol -> bool - - (** Indicates whether the symbol is of string kind. *) - val is_string_symbol : symbol -> bool - - (** The int value of the symbol. *) - val get_int : int_symbol -> int - - (** The string value of the symbol. *) - val get_string : string_symbol -> string - - (** A string representation of the symbol. *) - val to_string : symbol -> string - - (** Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. *) - val mk_int : context -> int -> symbol - - (** Creates a new symbol using a string. *) - val mk_string : context -> string -> symbol - - (** Create a list of symbols. *) - val mk_ints : context -> int list -> symbol list - - (** Create a list of symbols. *) - val mk_strings : context -> string list -> symbol list -end - -(** The abstract syntax tree (AST) module *) -module AST : -sig - type ast - - (** Vectors of ASTs *) - module ASTVector : - sig - type ast_vector - - (** The size of the vector *) - val get_size : ast_vector -> int - - (** - Retrieves the i-th object in the vector. - @return An AST *) - val get : ast_vector -> int -> ast - - (** Sets the i-th object in the vector. *) - val set : ast_vector -> int -> ast -> unit - - (** Resize the vector to a new size. *) - val resize : ast_vector -> int -> unit - - (** Add an ast to the back of the vector. The size - is increased by 1. *) - val push : ast_vector -> ast -> unit - - (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) - val translate : ast_vector -> context -> ast_vector - - (** Retrieves a string representation of the vector. *) - val to_string : ast_vector -> string - end - - (** Map from AST to AST *) - module ASTMap : - sig - type ast_map - - (** Checks whether the map contains a key. - @return True if the key in the map, false otherwise. *) - val contains : ast_map -> ast -> bool - - (** Finds the value associated with the key. - This function signs an error when the key is not a key in the map. *) - val find : ast_map -> ast -> ast - - (** Stores or replaces a new key/value pair in the map. *) - val insert : ast_map -> ast -> ast -> unit - - (** Erases the key from the map.*) - val erase : ast_map -> ast -> unit - - (** Removes all keys from the map. *) - val reset : ast_map -> unit - - (** The size of the map *) - val get_size : ast_map -> int - - (** The keys stored in the map. *) - val get_keys : ast_map -> ast list - - (** Retrieves a string representation of the map.*) - val to_string : ast_map -> string - end - - (** The AST's hash code. - @return A hash code *) - val get_hash_code : ast -> int - - (** A unique identifier for the AST (unique among all ASTs). *) - val get_id : ast -> int - - (** The kind of the AST. *) - val get_ast_kind : ast -> Z3enums.ast_kind - - (** Indicates whether the AST is an Expr *) - val is_expr : ast -> bool - - (** Indicates whether the AST is a bound variable*) - val is_var : ast -> bool - - (** Indicates whether the AST is a Quantifier *) - val is_quantifier : ast -> bool - - (** Indicates whether the AST is a Sort *) - val is_sort : ast -> bool - - (** Indicates whether the AST is a func_decl *) - val is_func_decl : ast -> bool - - (** A string representation of the AST. *) - val to_string : ast -> string - - (** A string representation of the AST in s-expression notation. *) - val to_sexpr : ast -> string - - (** Comparison operator. - @return True if the two ast's are from the same context - and represent the same sort; false otherwise. *) - val ( = ) : ast -> ast -> bool - - (** Object Comparison. - @return Negative if the first ast should be sorted before the second, positive if after else zero. *) - val compare : ast -> ast -> int - - (** Operator < *) - val ( < ) : ast -> ast -> int - - (** Translates (copies) the AST to another context. - @return A copy of the AST which is associated with the other context. *) - val translate : ast -> context -> ast - - (** Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., - Z3native.inc_ref). *) - val wrap_ast : context -> Z3native.z3_ast -> ast - - (** Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - Z3native.inc_ref). - {!wrap_ast} *) - val unwrap_ast : ast -> Z3native.ptr -end - -(** The Sort module implements type information for ASTs *) -module Sort : -sig - (** Sorts *) - type sort = Sort of AST.ast - - (** Uninterpreted Sorts *) - type uninterpreted_sort = UninterpretedSort of sort - - val ast_of_sort : sort -> AST.ast - val sort_of_uninterpreted_sort : uninterpreted_sort -> sort - val uninterpreted_sort_of_sort : sort -> uninterpreted_sort - - (** Comparison operator. - @return True if the two sorts are from the same context - and represent the same sort; false otherwise. *) - val ( = ) : sort -> sort -> bool - - (** Returns a unique identifier for the sort. *) - val get_id : sort -> int - - (** The kind of the sort. *) - val get_sort_kind : sort -> Z3enums.sort_kind - - (** The name of the sort *) - val get_name : sort -> Symbol.symbol - - (** A string representation of the sort. *) - val to_string : sort -> string - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted_s : context -> string -> uninterpreted_sort -end - -(** Function declarations *) -module rec FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - - (** Parameters of Func_Decls *) - module Parameter : - sig - (** Parameters of func_decls *) - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - (** The kind of the parameter. *) - val get_kind : parameter -> Z3enums.parameter_kind - - (** The int value of the parameter.*) - val get_int : parameter -> int - - (** The double value of the parameter.*) - val get_float : parameter -> float - - (** The Symbol.Symbol value of the parameter.*) - val get_symbol : parameter -> Symbol.symbol - - (** The Sort value of the parameter.*) - val get_sort : parameter -> Sort.sort - - (** The AST value of the parameter.*) - val get_ast : parameter -> AST.ast - - (** The FunctionDeclaration value of the parameter.*) - val get_func_decl : parameter -> func_decl - - (** The rational string value of the parameter.*) - val get_rational : parameter -> string - end - - (** Creates a new function declaration. *) - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new function declaration. *) - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - (** Creates a fresh function declaration with a name prefixed with a prefix string. *) - - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - - (** Creates a fresh constant function declaration with a name prefixed with a prefix string. - {!mk_func_decl} - {!mk_func_decl} *) - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - - (** Comparison operator. - @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) - val ( = ) : func_decl -> func_decl -> bool - - (** A string representations of the function declaration. *) - val to_string : func_decl -> string - - (** Returns a unique identifier for the function declaration. *) - val get_id : func_decl -> int - - (** The arity of the function declaration *) - val get_arity : func_decl -> int - - (** The size of the domain of the function declaration - {!get_arity} *) - val get_domain_size : func_decl -> int - - (** The domain of the function declaration *) - val get_domain : func_decl -> Sort.sort list - - (** The range of the function declaration *) - val get_range : func_decl -> Sort.sort - - (** The kind of the function declaration. *) - val get_decl_kind : func_decl -> Z3enums.decl_kind - - (** The name of the function declaration*) - val get_name : func_decl -> Symbol.symbol - - (** The number of parameters of the function declaration *) - val get_num_parameters : func_decl -> int - - (** The parameters of the function declaration *) - val get_parameters : func_decl -> Parameter.parameter list - - (** Create expression that applies function to arguments. *) - val apply : func_decl -> Expr.expr list -> Expr.expr -end - -(** Parameter sets (of Solvers, Tactics, ...) - - A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) -and Params : -sig - type params - - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs : - sig - type param_descrs - - (** Validate a set of parameters. *) - val validate : param_descrs -> params -> unit - - (** Retrieve kind of parameter. *) - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - - (** Retrieve all names of parameters. *) - val get_names : param_descrs -> Symbol.symbol list - - (** The size of the ParamDescrs. *) - val get_size : param_descrs -> int - - (** Retrieves a string representation of the ParamDescrs. *) - val to_string : param_descrs -> string - end - - (** Adds a parameter setting. *) - val add_bool : params -> Symbol.symbol -> bool -> unit - - (** Adds a parameter setting. *) - val add_int : params -> Symbol.symbol -> int -> unit - - (** Adds a parameter setting. *) - val add_double : params -> Symbol.symbol -> float -> unit - - (** Adds a parameter setting. *) - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - - (** Adds a parameter setting. *) - val add_s_bool : params -> string -> bool -> unit - - (** Adds a parameter setting. *) - val add_s_int : params -> string -> int -> unit - - (** Adds a parameter setting. *) - val add_s_double : params -> string -> float -> unit - - (** Adds a parameter setting. *) - val add_s_symbol : params -> string -> Symbol.symbol -> unit - - (** Creates a new parameter set *) - val mk_params : context -> params - - (** A string representation of the parameter set. *) - val to_string : params -> string -end - -(** General Expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - - val ast_of_expr : Expr.expr -> AST.ast - val expr_of_ast : AST.ast -> Expr.expr - - (** Returns a simplified version of the expression. - {!get_simplify_help} *) - val simplify : Expr.expr -> Params.params option -> expr - - (** A string describing all available parameters to Expr.Simplify. *) - val get_simplify_help : context -> string - - (** Retrieves parameter descriptions for simplifier. *) - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - - (** The function declaration of the function that is applied in this expression. *) - val get_func_decl : Expr.expr -> FuncDecl.func_decl - - (** Indicates whether the expression is the true or false expression - or something else (L_UNDEF). *) - val get_bool_value : Expr.expr -> Z3enums.lbool - - (** The number of arguments of the expression. *) - val get_num_args : Expr.expr -> int - - (** The arguments of the expression. *) - val get_args : Expr.expr -> Expr.expr list - - (** Update the arguments of the expression using an array of expressions. - The number of new arguments should coincide with the current number of arguments. *) - val update : Expr.expr -> Expr.expr list -> expr - - (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. - - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. *) - val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr - - (** Substitute every occurrence of from in the expression with to. - {!substitute} *) - val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr - - (** Substitute the free variables in the expression with the expressions in the expr array - - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) - val substitute_vars : Expr.expr -> Expr.expr list -> expr - - (** Translates (copies) the term to another context. - @return A copy of the term which is associated with the other context *) - val translate : Expr.expr -> context -> expr - - (** Returns a string representation of the expression. *) - val to_string : Expr.expr -> string - - (** Indicates whether the term is a numeral *) - val is_numeral : Expr.expr -> bool - - (** Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. *) - val is_well_sorted : Expr.expr -> bool - - (** The Sort of the term. *) - val get_sort : Expr.expr -> Sort.sort - - (** Indicates whether the term has Boolean sort. *) - val is_bool : Expr.expr -> bool - - (** Indicates whether the term represents a constant. *) - val is_const : Expr.expr -> bool - - (** Indicates whether the term is the constant true. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is the constant false. *) - val is_false : Expr.expr -> bool - - (** Indicates whether the term is an equality predicate. *) - val is_eq : Expr.expr -> bool - - (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) - val is_distinct : Expr.expr -> bool - - (** Indicates whether the term is a ternary if-then-else term *) - val is_ite : Expr.expr -> bool - - (** Indicates whether the term is an n-ary conjunction *) - val is_and : Expr.expr -> bool - - (** Indicates whether the term is an n-ary disjunction *) - val is_or : Expr.expr -> bool - - (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) - val is_iff : Expr.expr -> bool - - (** Indicates whether the term is an exclusive or *) - val is_xor : Expr.expr -> bool - - (** Indicates whether the term is a negation *) - val is_not : Expr.expr -> bool - - (** Indicates whether the term is an implication *) - val is_implies : Expr.expr -> bool - - (** Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) - val is_label : Expr.expr -> bool - - (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) - val is_label_lit : Expr.expr -> bool - - (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) - val is_oeq : Expr.expr -> bool - - (** Creates a new constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - - (** Creates a new constant. *) - val mk_const_s : context -> string -> Sort.sort -> expr - - (** Creates a constant from the func_decl. *) - val mk_const_f : context -> FuncDecl.func_decl -> expr - - (** Creates a fresh constant with a name prefixed with a string. *) - val mk_fresh_const : context -> string -> Sort.sort -> expr - - (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - - (** Create a numeral of a given sort. - @return A Term with the goven value and sort *) - val mk_numeral_string : context -> string -> Sort.sort -> expr - - (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @return A Term with the given value and sort *) - val mk_numeral_int : context -> int -> Sort.sort -> expr -end - -(** Boolean expressions *) -module Boolean : -sig - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - val expr_of_bool_expr : bool_expr -> Expr.expr - val sort_of_bool_sort : bool_sort -> Sort.sort - val bool_sort_of_sort : Sort.sort -> bool_sort - val bool_expr_of_expr : Expr.expr -> bool_expr - - (** Create a Boolean sort *) - val mk_sort : context -> bool_sort - - (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> bool_expr - - (** Create a Boolean constant. *) - val mk_const_s : context -> string -> bool_expr - - (** The true Term. *) - val mk_true : context -> bool_expr - - (** The false Term. *) - val mk_false : context -> bool_expr - - (** Creates a Boolean value. *) - val mk_val : context -> bool -> bool_expr - - (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr - - (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr list -> bool_expr - - (** Mk an expression representing not(a). *) - val mk_not : context -> bool_expr -> bool_expr - - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) - val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 iff t2. *) - val mk_iff : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 -> t2. *) - val mk_implies : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 xor t2. *) - val mk_xor : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing the AND of args *) - val mk_and : context -> bool_expr list -> bool_expr - - (** Create an expression representing the OR of args *) - val mk_or : context -> bool_expr list -> bool_expr -end - -(** Quantifier expressions *) -module Quantifier : -sig - type quantifier = Quantifier of Expr.expr - - val expr_of_quantifier : quantifier -> Expr.expr - val quantifier_of_expr : Expr.expr -> quantifier - - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. *) - module Pattern : - sig - type pattern = Pattern of AST.ast - - val ast_of_pattern : pattern -> AST.ast - val pattern_of_ast : AST.ast -> pattern - - (** The number of terms in the pattern. *) - val get_num_terms : pattern -> int - - (** The terms in the pattern. *) - val get_terms : pattern -> Expr.expr list - - (** A string representation of the pattern. *) - val to_string : pattern -> string - end - - - (** The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. *) - val get_index : Expr.expr -> int - - (** Indicates whether the quantifier is universal. *) - val is_universal : quantifier -> bool - - (** Indicates whether the quantifier is existential. *) - val is_existential : quantifier -> bool - - (** The weight of the quantifier. *) - val get_weight : quantifier -> int - - (** The number of patterns. *) - val get_num_patterns : quantifier -> int - - (** The patterns. *) - val get_patterns : quantifier -> Pattern.pattern list - - (** The number of no-patterns. *) - val get_num_no_patterns : quantifier -> int - - (** The no-patterns. *) - val get_no_patterns : quantifier -> Pattern.pattern list - - (** The number of bound variables. *) - val get_num_bound : quantifier -> int - - (** The symbols for the bound variables. *) - val get_bound_variable_names : quantifier -> Symbol.symbol list - - (** The sorts of the bound variables. *) - val get_bound_variable_sorts : quantifier -> Sort.sort list - - (** The body of the quantifier. *) - val get_body : quantifier -> Boolean.bool_expr - - (** Creates a new bound variable. *) - val mk_bound : context -> int -> Sort.sort -> Expr.expr - - (** Create a quantifier pattern. *) - val mk_pattern : context -> Expr.expr list -> Pattern.pattern - - (** Create a universal Quantifier. *) - val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a universal Quantifier. *) - val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier -end - -(** Functions to manipulate Array expressions *) -module Array_ : -sig - type array_sort = ArraySort of Sort.sort - type array_expr = ArrayExpr of Expr.expr - - val sort_of_array_sort : array_sort -> Sort.sort - val array_sort_of_sort : Sort.sort -> array_sort - val expr_of_array_expr : array_expr -> Expr.expr - - val array_expr_of_expr : Expr.expr -> array_expr - - (** Create a new array sort. *) - val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort - - (** Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an array select. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - val is_constant_array : Expr.expr -> bool - - (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. *) - val is_default_array : Expr.expr -> bool - - (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - val is_array_map : Expr.expr -> bool - - (** Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. *) - val is_as_array : Expr.expr -> bool - - (** Indicates whether the term is of an array sort. *) - val is_array : Expr.expr -> bool - - (** The domain of the array sort. *) - val get_domain : array_sort -> Sort.sort - - (** The range of the array sort. *) - val get_range : array_sort -> Sort.sort - - (** Create an array constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr - - (** Create an array constant. *) - val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr - - (** Array read. - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - {!Array_.mk_sort} - {!mk_store} *) - val mk_select : context -> array_expr -> Expr.expr -> array_expr - - (** Array update. - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - {!Array_.mk_sort} - {!mk_select} *) - val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr - - (** Create a constant array. - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - {!Array_.mk_sort} - {!mk_select} *) - val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr - - (** Maps f on the argument arrays. - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - {!Array_.mk_sort} - {!mk_select} - {!mk_store} *) - val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr - - (** Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. *) - val mk_term_array : context -> array_expr -> array_expr -end - -(** Functions to manipulate Set expressions *) -module Set : -sig - type set_sort = SetSort of Sort.sort - - val sort_of_set_sort : set_sort -> Sort.sort - - (** Create a set type. *) - val mk_sort : context -> Sort.sort -> set_sort - - (** Indicates whether the term is set union *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is set intersection *) - val is_intersect : Expr.expr -> bool - - (** Indicates whether the term is set difference *) - val is_difference : Expr.expr -> bool - - (** Indicates whether the term is set complement *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is set subset *) - val is_subset : Expr.expr -> bool - - (** Create an empty set. *) - val mk_empty : context -> Sort.sort -> Expr.expr - - (** Create the full set. *) - val mk_full : context -> Sort.sort -> Expr.expr - - (** Add an element to the set. *) - val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Remove an element from a set. *) - val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the union of a list of sets. *) - val mk_union : context -> Expr.expr list -> Expr.expr - - (** Take the intersection of a list of sets. *) - val mk_intersection : context -> Expr.expr list -> Expr.expr - - (** Take the difference between two sets. *) - val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the complement of a set. *) - val mk_complement : context -> Expr.expr -> Expr.expr - - (** Check for set membership. *) - val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Check for subsetness of sets. *) - val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr -end - -(** Functions to manipulate Finite Domain expressions *) -module FiniteDomain : -sig - type finite_domain_sort = FiniteDomainSort of Sort.sort - - val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort - val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort - - (** Create a new finite domain sort. *) - val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort - - (** Create a new finite domain sort. *) - val mk_sort_s : context -> string -> int -> finite_domain_sort - - (** Indicates whether the term is of an array sort. *) - val is_finite_domain : Expr.expr -> bool - - (** Indicates whether the term is a less than predicate over a finite domain. *) - val is_lt : Expr.expr -> bool - - (** The size of the finite domain sort. *) - val get_size : finite_domain_sort -> int -end - - -(** Functions to manipulate Relation expressions *) -module Relation : -sig - type relation_sort = RelationSort of Sort.sort - - val sort_of_relation_sort : relation_sort -> Sort.sort - val relation_sort_of_sort : Sort.sort -> relation_sort - - (** Indicates whether the term is of a relation sort. *) - val is_relation : Expr.expr -> bool - - (** Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an empty relation *) - val is_empty : Expr.expr -> bool - - (** Indicates whether the term is a test for the emptiness of a relation *) - val is_is_empty : Expr.expr -> bool - - (** Indicates whether the term is a relational join *) - val is_join : Expr.expr -> bool - - (** Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is the widening of two relations - The function takes two arguments. *) - val is_widen : Expr.expr -> bool - - (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. *) - val is_project : Expr.expr -> bool - - (** Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. *) - val is_filter : Expr.expr -> bool - - (** Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. *) - val is_negation_filter : Expr.expr -> bool - - (** Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. *) - val is_rename : Expr.expr -> bool - - (** Indicates whether the term is the complement of a relation *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind {!is_union} - to perform destructive updates to the first argument. *) - val is_clone : Expr.expr -> bool - - (** The arity of the relation sort. *) - val get_arity : relation_sort -> int - - (** The sorts of the columns of the relation sort. *) - val get_column_sorts : relation_sort -> relation_sort list -end - -(** Functions to manipulate Datatype expressions *) -module Datatype : -sig - type datatype_sort = DatatypeSort of Sort.sort - type datatype_expr = DatatypeExpr of Expr.expr - - val sort_of_datatype_sort : datatype_sort -> Sort.sort - val datatype_sort_of_sort : Sort.sort -> datatype_sort - val expr_of_datatype_expr : datatype_expr -> Expr.expr - val datatype_expr_of_expr : Expr.expr -> datatype_expr - - (** Datatype Constructors *) - module Constructor : - sig - type constructor - - (** The number of fields of the constructor. *) - val get_num_fields : constructor -> int - - (** The function declaration of the constructor. *) - val get_constructor_decl : constructor -> FuncDecl.func_decl - - (** The function declaration of the tester. *) - val get_tester_decl : constructor -> FuncDecl.func_decl - - (** The function declarations of the accessors *) - val get_accessor_decls : constructor -> FuncDecl.func_decl list - end - - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor - - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor - - (** Create a new datatype sort. *) - val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort - - (** Create a new datatype sort. *) - val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort - - (** Create mutually recursive datatypes. *) - val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list - - (** Create mutually recursive data-types. *) - val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list - - - (** The number of constructors of the datatype sort. *) - val get_num_constructors : datatype_sort -> int - - (** The constructors. *) - val get_constructors : datatype_sort -> FuncDecl.func_decl list - - (** The recognizers. *) - val get_recognizers : datatype_sort -> FuncDecl.func_decl list - - (** The constructor accessors. *) - val get_accessors : datatype_sort -> FuncDecl.func_decl list list -end - -(** Functions to manipulate Enumeration expressions *) -module Enumeration : -sig - type enum_sort = EnumSort of Sort.sort - - val sort_of_enum_sort : enum_sort -> Sort.sort - - (** Create a new enumeration sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort - - (** Create a new enumeration sort. *) - val mk_sort_s : context -> string -> string list -> enum_sort - - (** The function declarations of the constants in the enumeration. *) - val get_const_decls : enum_sort -> FuncDecl.func_decl list - - (** The test predicates for the constants in the enumeration. *) - val get_tester_decls : enum_sort -> FuncDecl.func_decl list -end - -(** Functions to manipulate List expressions *) -module List_ : -sig - type list_sort = ListSort of Sort.sort - - val sort_of_list_sort : list_sort -> Sort.sort - - (** Create a new list sort. *) - val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort - - (** Create a new list sort. *) - val mk_list_s : context -> string -> Sort.sort -> list_sort - - (** The declaration of the nil function of this list sort. *) - val get_nil_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the isNil function of this list sort. *) - val get_is_nil_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the cons function of this list sort. *) - val get_cons_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the isCons function of this list sort. *) - val get_is_cons_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the head function of this list sort. *) - val get_head_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the tail function of this list sort. *) - val get_tail_decl : list_sort -> FuncDecl.func_decl - - (** The empty list. *) - val nil : list_sort -> Expr.expr -end - -(** Functions to manipulate Tuple expressions *) -module Tuple : -sig - type tuple_sort = TupleSort of Sort.sort - - val sort_of_tuple_sort : tuple_sort -> Sort.sort - - (** Create a new tuple sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort - - (** The constructor function of the tuple. *) - val get_mk_decl : tuple_sort -> FuncDecl.func_decl - - (** The number of fields in the tuple. *) - val get_num_fields : tuple_sort -> int - - (** The field declarations. *) - val get_field_decls : tuple_sort -> FuncDecl.func_decl list -end - -(** Functions to manipulate arithmetic expressions *) -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort - val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr - - (** Integer Arithmetic *) - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort - val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort - val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr - val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr - val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr - val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num - - (** Create a new integer sort. *) - val mk_sort : context -> int_sort - - (** Retrieve the int value. *) - val get_int : int_num -> int - - (** Returns a string representation of the numeral. *) - val to_string : int_num -> string - - (** Creates an integer constant. *) - val mk_const : context -> Symbol.symbol -> int_expr - - (** Creates an integer constant. *) - val mk_const_s : context -> string -> int_expr - - (** Create an expression representing t1 mod t2. - The arguments must have int type. *) - val mk_mod : context -> int_expr -> int_expr -> int_expr - - (** Create an expression representing t1 rem t2. - The arguments must have int type. *) - val mk_rem : context -> int_expr -> int_expr -> int_expr - - (** Create an integer numeral. *) - val mk_numeral_s : context -> string -> int_num - - (** Create an integer numeral. - @return A Term with the given value and sort Integer *) - val mk_numeral_i : context -> int -> int_num - - (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. *) - val mk_int2real : context -> int_expr -> Real.real_expr - - (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - - (** Real Arithmetic *) - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - (** Create a real sort. *) - val mk_sort : context -> real_sort - - (** The numerator of a rational numeral. *) - val get_numerator : rat_num -> Integer.int_num - - (** The denominator of a rational numeral. *) - val get_denominator : rat_num -> Integer.int_num - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as indicated by the int argument.*) - val to_decimal_string : rat_num -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : rat_num -> string - - (** Creates a real constant. *) - val mk_const : context -> Symbol.symbol -> real_expr - - (** Creates a real constant. *) - val mk_const_s : context -> string -> real_expr - - (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) - val mk_numeral_nd : context -> int -> int -> rat_num - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_s : context -> string -> rat_num - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_i : context -> int -> rat_num - - (** Creates an expression that checks whether a real number is an integer. *) - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - - (** Coerce a real to an integer. - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) - val mk_real2int : context -> real_expr -> Integer.int_expr - end - - (** Algebraic Numbers *) - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr - val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num - - (** Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_upper : algebraic_num -> int -> Real.rat_num - - (** Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_lower : algebraic_num -> int -> Real.rat_num - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as the int argument provided.*) - val to_decimal_string : algebraic_num -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : algebraic_num -> string - end - - (** Indicates whether the term is of integer sort. *) - val is_int : Expr.expr -> bool - - (** Indicates whether the term is an arithmetic numeral. *) - val is_arithmetic_numeral : Expr.expr -> bool - - (** Indicates whether the term is a less-than-or-equal *) - val is_le : Expr.expr -> bool - - (** Indicates whether the term is a greater-than-or-equal *) - val is_ge : Expr.expr -> bool - - (** Indicates whether the term is a less-than *) - val is_lt : Expr.expr -> bool - - (** Indicates whether the term is a greater-than *) - val is_gt : Expr.expr -> bool - - (** Indicates whether the term is addition (binary) *) - val is_add : Expr.expr -> bool - - (** Indicates whether the term is subtraction (binary) *) - val is_sub : Expr.expr -> bool - - (** Indicates whether the term is a unary minus *) - val is_uminus : Expr.expr -> bool - - (** Indicates whether the term is multiplication (binary) *) - val is_mul : Expr.expr -> bool - - (** Indicates whether the term is division (binary) *) - val is_div : Expr.expr -> bool - - (** Indicates whether the term is integer division (binary) *) - val is_idiv : Expr.expr -> bool - - (** Indicates whether the term is remainder (binary) *) - val is_remainder : Expr.expr -> bool - - (** Indicates whether the term is modulus (binary) *) - val is_modulus : Expr.expr -> bool - - (** Indicates whether the term is a coercion of integer to real (unary) *) - val is_inttoreal : Expr.expr -> bool - - (** Indicates whether the term is a coercion of real to integer (unary) *) - val is_real_to_int : Expr.expr -> bool - - (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - val is_real_is_int : Expr.expr -> bool - - (** Indicates whether the term is of sort real. *) - val is_real : Expr.expr -> bool - - (** Indicates whether the term is an integer numeral. *) - val is_int_numeral : Expr.expr -> bool - - (** Indicates whether the term is a real numeral. *) - val is_rat_num : Expr.expr -> bool - - (** Indicates whether the term is an algebraic number *) - val is_algebraic_number : Expr.expr -> bool - - (** Create an expression representing t[0] + t[1] + .... *) - val mk_add : context -> arith_expr list -> arith_expr - - (** Create an expression representing t[0] * t[1] * .... *) - val mk_mul : context -> arith_expr list -> arith_expr - - (** Create an expression representing t[0] - t[1] - .... *) - val mk_sub : context -> arith_expr list -> arith_expr - - (** Create an expression representing -t. *) - val mk_unary_minus : context -> arith_expr -> arith_expr - - (** Create an expression representing t1 / t2. *) - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - - (** Create an expression representing t1 ^ t2. *) - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - - (** Create an expression representing t1 < t2 *) - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 <= t2 *) - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 > t2 *) - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 >= t2 *) - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end - -(** Functions to manipulate bit-vector expressions *) -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - (** Create a new bit-vector sort. *) - val mk_sort : context -> int -> bitvec_sort - - (** Indicates whether the terms is of bit-vector sort. *) - val is_bv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector numeral *) - val is_bv_numeral : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value one *) - val is_bv_bit1 : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value zero *) - val is_bv_bit0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unary minus *) - val is_bv_uminus : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector addition (binary) *) - val is_bv_add : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector subtraction (binary) *) - val is_bv_sub : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector multiplication (binary) *) - val is_bv_mul : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division (binary) *) - val is_bv_sdiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division (binary) *) - val is_bv_udiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder (binary) *) - val is_bv_SRem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - val is_bv_urem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus *) - val is_bv_smod : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division by zero *) - val is_bv_sdiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division by zero *) - val is_bv_udiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder by zero *) - val is_bv_srem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - val is_bv_urem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus by zero *) - val is_bv_smod0 : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - val is_bv_ule : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - val is_bv_sle : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - val is_bv_uge : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - val is_bv_sge : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than *) - val is_bv_ult : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than *) - val is_bv_slt : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than *) - val is_bv_ugt : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than *) - val is_bv_sgt : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise AND *) - val is_bv_and : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise OR *) - val is_bv_or : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOT *) - val is_bv_not : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XOR *) - val is_bv_xor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NAND *) - val is_bv_nand : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOR *) - val is_bv_nor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XNOR *) - val is_bv_xnor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector concatenation (binary) *) - val is_bv_concat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector sign extension *) - val is_bv_signextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector zero extension *) - val is_bv_zeroextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector extraction *) - val is_bv_extract : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector repetition *) - val is_bv_repeat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce OR *) - val is_bv_reduceor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce AND *) - val is_bv_reduceand : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector comparison *) - val is_bv_comp : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector shift left *) - val is_bv_shiftleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector logical shift right *) - val is_bv_shiftrightlogical : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector arithmetic shift left *) - val is_bv_shiftrightarithmetic : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left *) - val is_bv_rotateleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right *) - val is_bv_rotateright : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotateleftextended : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotaterightextended : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - - (** Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_int_to_bv : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_bv_to_int : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - val is_bv_carry : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - val is_bv_xor3 : Expr.expr -> bool - - (** The size of a bit-vector sort. *) - val get_size : bitvec_sort -> int - - (** Retrieve the int value. *) - val get_int : bitvec_num -> int - - (** Returns a string representation of the numeral. *) - val to_string : bitvec_num -> string - - (** Creates a bit-vector constant. *) - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - - (** Creates a bit-vector constant. *) - val mk_const_s : context -> string -> int -> bitvec_expr - - (** Bitwise negation. - The argument must have a bit-vector sort. *) - val mk_not : context -> bitvec_expr -> Expr.expr - - (** Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redand : context -> bitvec_expr -> Expr.expr - - (** Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redor : context -> bitvec_expr -> Expr.expr - - (** Bitwise conjunction. - The arguments must have a bit-vector sort. *) - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise disjunction. - The arguments must have a bit-vector sort. *) - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise XOR. - The arguments must have a bit-vector sort. *) - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise NAND. - The arguments must have a bit-vector sort. *) - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise NOR. - The arguments must have a bit-vector sort. *) - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise XNOR. - The arguments must have a bit-vector sort. *) - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Standard two's complement unary minus. - The arguments must have a bit-vector sort. *) - val mk_neg : context -> bitvec_expr -> bitvec_expr - - (** Two's complement addition. - The arguments must have the same bit-vector sort. *) - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement subtraction. - The arguments must have the same bit-vector sort. *) - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement multiplication. - The arguments must have the same bit-vector sort. *) - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned division. - - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. *) - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Signed division. - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned remainder. - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Signed remainder. - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement signed remainder (sign follows divisor). - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned less-than - - The arguments must have the same bit-vector sort. *) - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed less-than - - The arguments must have the same bit-vector sort. *) - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). *) - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bit-vector extraction. - - Extract the bits between two limits from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. *) - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector sign extension. - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. *) - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector zero extension. - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. *) - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector repetition. *) - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - - (** Shift left. - - It is equivalent to multiplication by 2^x where \c x is the value of third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling.*) - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Logical shift right - - It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Rotate Left. - Rotate bits of \c t to the left \c i times. *) - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - - (** Rotate Right. - Rotate bits of \c t to the right \c i times.*) - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - - (** Rotate Left. - Rotate bits of the second argument to the left.*) - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Rotate Right. - Rotate bits of the second argument to the right. *) - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Create an integer from the bit-vector argument - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in the argument. - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function.*) - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - - (** Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a bit-vector numeral. *) - val mk_numeral : context -> string -> int -> bitvec_num -end - -(** Functions to manipulate proof expressions *) -module Proof : -sig - (** Indicates whether the term is a Proof for the expression 'true'. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact asserted by the user. *) - val is_asserted : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - val is_goal : Expr.expr -> bool - - (** Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). *) - val is_modus_ponens : Expr.expr -> bool - - (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. *) - val is_reflexivity : Expr.expr -> bool - - (** Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. *) - val is_symmetry : Expr.expr -> bool - - (** Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) *) - val is_transitivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. *) - val is_Transitivity_star : Expr.expr -> bool - - (** Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. *) - val is_monotonicity : Expr.expr -> bool - - (** Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - val is_quant_intro : Expr.expr -> bool - - (** Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. *) - val is_distributivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i *) - val is_and_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) *) - val is_or_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) *) - val is_rewrite : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - val is_rewrite_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - val is_pull_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents *) - val is_pull_quant_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents *) - val is_push_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. *) - val is_elim_unused_vars : Expr.expr -> bool - - (** Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. *) - val is_der : Expr.expr -> bool - - (** Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) *) - val is_quant_inst : Expr.expr -> bool - - (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. *) - val is_hypothesis : Expr.expr -> bool - - (** Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. *) - val is_lemma : Expr.expr -> bool - - (** Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - val is_unit_resolution : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) *) - val is_iff_true : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) *) - val is_iff_false : Expr.expr -> bool - - (** Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. *) - val is_commutativity : Expr.expr -> bool - - (** Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). *) - val is_def_axiom : Expr.expr -> bool - - (** Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) *) - val is_def_intro : Expr.expr -> bool - - (** Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. *) - val is_apply_def : Expr.expr -> bool - - (** Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) *) - val is_iff_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. *) - val is_nnf_pos : Expr.expr -> bool - - (** Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) *) - val is_nnf_neg : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_nnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_cnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. *) - val is_skolemize : Expr.expr -> bool - - (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q *) - val is_modus_ponens_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - val is_theory_lemma : Expr.expr -> bool -end - -(** Goals - - A goal (aka problem). A goal is essentially a - of formulas, that can be solved and/or transformed using - tactics and solvers. *) -module Goal : -sig - type goal - - (** The precision of the goal. - - Goals can be transformed using over and under approximations. - An under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. *) - val get_precision : goal -> Z3enums.goal_prec - - (** Indicates whether the goal is precise. *) - val is_precise : goal -> bool - - (** Indicates whether the goal is an under-approximation. *) - val is_underapproximation : goal -> bool - - (** Indicates whether the goal is an over-approximation. *) - val is_overapproximation : goal -> bool - - (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) - val is_garbage : goal -> bool - - (** Adds the constraints to the given goal. *) - val assert_ : goal -> Boolean.bool_expr list -> unit - - (** Indicates whether the goal contains `false'. *) - val is_inconsistent : goal -> bool - - (** The depth of the goal. - This tracks how many transformations were applied to it. *) - val get_depth : goal -> int - - (** Erases all formulas from the given goal. *) - val reset : goal -> unit - - (** The number of formulas in the goal. *) - val get_size : goal -> int - - (** The formulas in the goal. *) - val get_formulas : goal -> Boolean.bool_expr list - - (** The number of formulas, subformulas and terms in the goal. *) - val get_num_exprs : goal -> int - - (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) - val is_decided_sat : goal -> bool - - (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) - val is_decided_unsat : goal -> bool - - (** Translates (copies) the Goal to another context.. *) - val translate : goal -> context -> goal - - (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - val simplify : goal -> Params.params option -> goal - - (** Creates a new Goal. - - Note that the Context must have been created with proof generation support if - the fourth argument is set to true here. *) - val mk_goal : context -> bool -> bool -> bool -> goal - - (** A string representation of the Goal. *) - val to_string : goal -> string -end - -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) -module Model : -sig - type model - - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. *) - module FuncInterp : - sig - type func_interp - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. *) - module FuncEntry : - sig - type func_entry - - (** Return the (symbolic) value of this entry. - *) - val get_value : func_entry -> Expr.expr - - (** The number of arguments of the entry. - *) - val get_num_args : func_entry -> int - - (** The arguments of the function entry. - *) - val get_args : func_entry -> Expr.expr list - - (** A string representation of the function entry. - *) - val to_string : func_entry -> string - end - - (** The number of entries in the function interpretation. *) - val get_num_entries : func_interp -> int - - (** The entries in the function interpretation *) - val get_entries : func_interp -> FuncEntry.func_entry list - - (** The (symbolic) `else' value of the function interpretation. *) - val get_else : func_interp -> Expr.expr - - (** The arity of the function interpretation *) - val get_arity : func_interp -> int - - (** A string representation of the function interpretation. *) - val to_string : func_interp -> string - end - - (** Retrieves the interpretation (the assignment) of a func_decl in the model. - An expression if the function has an interpretation in the model, null otherwise. *) - val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of an expression in the model. - An expression if the constant has an interpretation in the model, null otherwise. *) - val get_const_interp_e : model -> Expr.expr -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option - - (** The number of constant interpretations in the model. *) - val get_num_consts : model -> int - - (** The function declarations of the constants in the model. *) - val get_const_decls : model -> FuncDecl.func_decl list - - (** The number of function interpretations in the model. *) - val get_num_funcs : model -> int - - (** The function declarations of the function interpretations in the model. *) - val get_func_decls : model -> FuncDecl.func_decl list - - (** All symbols that have an interpretation in the model. *) - val get_decls : model -> FuncDecl.func_decl list - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - - (** Evaluates an expression in the current model. - - This function may fail if the argument contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - *) - val eval : model -> Expr.expr -> bool -> Expr.expr - - (** Alias for eval. *) - val evaluate : model -> Expr.expr -> bool -> Expr.expr - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - val get_num_sorts : model -> int - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - {!get_num_sorts} - {!sort_universe} *) - val get_sorts : model -> Sort.sort list - - (** The finite set of distinct values that represent the interpretation of a sort. - {!get_sorts} - @returns A list of expressions, where each is an element of the universe of the sort *) - val sort_universe : model -> Sort.sort -> AST.ast list - - (** Conversion of models to strings. - A string representation of the model. *) - val to_string : model -> string -end - -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe : -sig - type probe - - (** Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - val apply : probe -> Goal.goal -> float - - (** The number of supported Probes. *) - val get_num_probes : context -> int - - (** The names of all supported Probes. *) - val get_probe_names : context -> string list - - (** Returns a string containing a description of the probe with the given name. *) - val get_probe_description : context -> string -> string - - (** Creates a new Probe. *) - val mk_probe : context -> string -> probe - - (** Create a probe that always evaluates to a float value. *) - val const : context -> float -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than the value returned by second argument *) - val lt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than the value returned by second argument *) - val gt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than or equal the value returned by second argument *) - val le : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than or equal the value returned by second argument *) - val ge : context -> probe -> probe -> probe - - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is equal the value returned by second argument *) - val eq : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) - val and_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) - val or_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) - val not_ : context -> probe -> probe -end - -(** Tactics - - Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Tactic : -sig - type tactic - - (** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) - module ApplyResult : - sig - type apply_result - - (** The number of Subgoals. *) - val get_num_subgoals : apply_result -> int - - (** Retrieves the subgoals from the apply_result. *) - val get_subgoals : apply_result -> Goal.goal list - - (** Retrieves a subgoal from the apply_result. *) - val get_subgoal : apply_result -> int -> Goal.goal - - (** Convert a model for a subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g *) - val convert_model : apply_result -> int -> Model.model -> Model.model - - (** A string representation of the ApplyResult. *) - val to_string : apply_result -> string - end - - (** A string containing a description of parameters accepted by the tactic. *) - val get_help : tactic -> string - - (** Retrieves parameter descriptions for Tactics. *) - val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs - - (** Apply the tactic to the goal. *) - val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result - - (** The number of supported tactics. *) - val get_num_tactics : context -> int - - (** The names of all supported tactics. *) - val get_tactic_names : context -> string list - - (** Returns a string containing a description of the tactic with the given name. *) - val get_tactic_description : context -> string -> string - - (** Creates a new Tactic. *) - val mk_tactic : context -> string -> tactic - - (** Create a tactic that applies one tactic to a Goal and - then another one to every subgoal produced by the first one. *) - val and_then : context -> tactic -> tactic -> tactic list -> tactic - - (** Create a tactic that first applies one tactic to a Goal and - if it fails then returns the result of another tactic applied to the Goal. *) - val or_else : context -> tactic -> tactic -> tactic - - (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). - - If the tactic does not terminate within the timeout, then it fails. *) - val try_for : context -> tactic -> int -> tactic - - (** Create a tactic that applies one tactic to a given goal if the probe - evaluates to true. - - If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) - val when_ : context -> Probe.probe -> tactic -> tactic - - (** Create a tactic that applies a tactic to a given goal if the probe - evaluates to true and another tactic otherwise. *) - val cond : context -> Probe.probe -> tactic -> tactic -> tactic - - (** Create a tactic that keeps applying one tactic until the goal is not - modified anymore or the maximum number of iterations is reached. *) - val repeat : context -> tactic -> int -> tactic - - (** Create a tactic that just returns the given goal. *) - val skip : context -> tactic - - (** Create a tactic always fails. *) - val fail : context -> tactic - - (** Create a tactic that fails if the probe evaluates to false. *) - val fail_if : context -> Probe.probe -> tactic - - (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). *) - val fail_if_not_decided : context -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. *) - val using_params : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. - Alias for UsingParams*) - val with_ : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies the given tactics in parallel. *) - val par_or : context -> tactic list -> tactic - - (** Create a tactic that applies a tactic to a given goal and then another tactic - to every subgoal produced by the first one. The subgoals are processed in parallel. *) - val par_and_then : context -> tactic -> tactic -> tactic - - (** Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. *) - val interrupt : context -> unit -end - -(** Solvers *) -module Solver : -sig - type solver - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - - val string_of_status : status -> string - - (** Objects that track statistical information about solvers. *) - module Statistics : - sig - type statistics - - (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - *) - module Entry : - sig - type statistics_entry - - (** The key of the entry. *) - val get_key : statistics_entry -> string - - (** The int-value of the entry. *) - val get_int : statistics_entry -> int - - (** The float-value of the entry. *) - val get_float : statistics_entry -> float - - (** True if the entry is uint-valued. *) - val is_int : statistics_entry -> bool - - (** True if the entry is double-valued. *) - val is_float : statistics_entry -> bool - - (** The string representation of the the entry's value. *) - val to_string_value : statistics_entry -> string - - (** The string representation of the entry (key and value) *) - val to_string : statistics_entry -> string - end - - (** A string representation of the statistical data. *) - val to_string : statistics -> string - - (** The number of statistical data. *) - val get_size : statistics -> int - - (** The data entries. *) - val get_entries : statistics -> Entry.statistics_entry list - - (** The statistical counters. *) - val get_keys : statistics -> string list - - (** The value of a particular statistical counter. *) - val get : statistics -> string -> Entry.statistics_entry option - end - - (** A string that describes all available solver parameters. *) - val get_help : solver -> string - - (** Sets the solver parameters. *) - val set_parameters : solver -> Params.params -> unit - - (** Retrieves parameter descriptions for solver. *) - val get_param_descrs : solver -> Params.ParamDescrs.param_descrs - - (** The current number of backtracking points (scopes). - {!pop} - {!push} *) - val get_num_scopes : solver -> int - - (** Creates a backtracking point. - {!pop} *) - val push : solver -> unit - - (** Backtracks a number of backtracking points. - Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} - {!push} *) - val pop : solver -> int -> unit - - (** Resets the Solver. - This removes all assertions from the solver. *) - val reset : solver -> unit - - (** Assert a constraint (or multiple) into the solver. *) - val assert_ : solver -> Boolean.bool_expr list -> unit - - (** * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit - - (** * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit - - (** The number of assertions in the solver. *) - val get_num_assertions : solver -> int - - (** The set of asserted formulas. *) - val get_assertions : solver -> Boolean.bool_expr list - - (** Checks whether the assertions in the solver are consistent or not. - - {!Model} - {!get_unsat_core} - {!Proof} *) - val check : solver -> Boolean.bool_expr list -> status - - (** The model of the last Check. - - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. *) - val get_model : solver -> Model.model option - - (** The proof of the last Check. - - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. *) - val get_proof : solver -> Expr.expr option - - (** The unsat core of the last Check. - - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. *) - val get_unsat_core : solver -> AST.ast list - - (** A brief justification of why the last call to Check returned UNKNOWN. *) - val get_reason_unknown : solver -> string - - (** Solver statistics. *) - val get_statistics : solver -> Statistics.statistics - - (** Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. *) - val mk_solver : context -> Symbol.symbol option -> solver - - (** Creates a new (incremental) solver. - {!mk_solver} *) - val mk_solver_s : context -> string -> solver - - (** Creates a new (incremental) solver. *) - val mk_simple_solver : context -> solver - - (** Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. *) - val mk_solver_t : context -> Tactic.tactic -> solver - - (** A string representation of the solver. *) - val to_string : solver -> string -end - -(** Fixedpoint solving *) -module Fixedpoint : -sig - type fixedpoint - - (** A string that describes all available fixedpoint solver parameters. *) - val get_help : fixedpoint -> string - - (** Sets the fixedpoint solver parameters. *) - val set_params : fixedpoint -> Params.params -> unit - - (** Retrieves parameter descriptions for Fixedpoint solver. *) - val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs - - (** Assert a constraints into the fixedpoint solver. *) - val assert_ : fixedpoint -> Boolean.bool_expr list -> unit - - (** Register predicate as recursive relation. *) - val register_relation : fixedpoint -> FuncDecl.func_decl -> unit - - (** Add rule into the fixedpoint solver. *) - val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit - - (** Add table fact to the fixedpoint solver. *) - val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit - - (** Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. *) - val query : fixedpoint -> Boolean.bool_expr -> Solver.status - - (** Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status - - (** Creates a backtracking point. - {!pop} *) - val push : fixedpoint -> unit - - (** Backtrack one backtracking point. - - Note that an exception is thrown if Pop is called without a corresponding Push - {!push} *) - val pop : fixedpoint -> unit - - (** Update named rule into in the fixedpoint solver. *) - val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit - - (** Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. *) - val get_answer : fixedpoint -> Expr.expr option - - (** Retrieve explanation why fixedpoint engine returned status Unknown. *) - val get_reason_unknown : fixedpoint -> string - - (** Retrieve the number of levels explored for a given predicate. *) - val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int - - (** Retrieve the cover of a predicate. *) - val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option - - (** Add property about the predicate. - The property is added at level. *) - val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit - - (** Retrieve internal string representation of fixedpoint object. *) - val to_string : fixedpoint -> string - - (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit - - (** Convert benchmark given as set of axioms, rules and queries to a string. *) - val to_string_q : fixedpoint -> Boolean.bool_expr list -> string - - (** Retrieve set of rules added to fixedpoint context. *) - val get_rules : fixedpoint -> Boolean.bool_expr list - - (** Retrieve set of assertions added to fixedpoint context. *) - val get_assertions : fixedpoint -> Boolean.bool_expr list - - (** Create a Fixedpoint context. *) - val mk_fixedpoint : context -> fixedpoint -end - -(** Global and context options - - Note: This module contains functions that set parameters/options for context - objects as well as functions that set options that are used globally, across - contexts.*) -module Options : -sig - (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - {!get_param_value} *) - val update_param_value : context -> string -> string -> unit - - (** Get a configuration parameter. - - Returns None if the parameter value does not exist. - {!update_param_value} *) - val get_param_value : context -> string -> string option - - (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) - val set_print_mode : context -> Z3enums.ast_print_mode -> unit - - (** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) - val toggle_warning_messages : bool -> unit -end - -(** Functions for handling SMT and SMT2 expressions and files *) -module SMT : -sig - (** Convert a benchmark into an SMT-LIB formatted string. - - @return A string representation of the benchmark. *) - val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string - - (** Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays in the third and fifth argument - don't need to match the names of the sorts and declarations in the arrays in the fourth - and sixth argument. This is a useful feature since we can use arbitrary names to - reference sorts and declarations. *) - val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** Parse the given file using the SMT-LIB parser. - {!parse_smtlib_string} *) - val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_formulas : context -> int - - (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_formulas : context -> Boolean.bool_expr list - - (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_assumptions : context -> int - - (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_assumptions : context -> Boolean.bool_expr list - - (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_decls : context -> int - - (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_decls : context -> FuncDecl.func_decl list - - (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_sorts : context -> int - - (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_sorts : context -> Sort.sort list - - (** Parse the given string using the SMT-LIB2 parser. - - {!parse_smtlib_string} - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr - - (** Parse the given file using the SMT-LIB2 parser. - {!parse_smtlib2_string} *) - val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr -end - -(** Set a global (or module) parameter, which is shared by all Z3 contexts. - - When a Z3 module is initialized it will use the value of these parameters - when Z3_params objects are not provided. - The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - The character '.' is a delimiter (more later). - The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - This function can be used to set parameters for a specific Z3 module. - This can be done by using .. - For example: - (set_global_param "pp.decimal" "true") - will set the parameter "decimal" in the module "pp" to true. -*) -val set_global_param : string -> string -> unit - -(** Get a global (or module) parameter. - - Returns None if the parameter does not exist. - The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. - This function cannot be invoked simultaneously from different threads without synchronization. - The result string stored in param_value is stored in a shared location. -*) -val get_global_param : string -> string option - -(** Restore the value of all global (and module) parameters. - - This command will not affect already created objects (such as tactics and solvers) - {!set_global_param} -*) -val global_param_reset_all : unit From 3e336592a290c07b2937c84ce415776b3563240d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 4 Jun 2013 18:00:48 +0100 Subject: [PATCH 318/646] ML API: bug and build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 28 ++++++++++++++++------------ scripts/update_api.py | 5 ++++- src/api/ml/z3.ml | 27 +++++++++++++++++---------- src/api/ml/z3.mli | 6 +++--- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a30e074b0..f46339f5c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1340,26 +1340,30 @@ class MLComponent(Component): mk_dir(os.path.join(BUILD_DIR, sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): - out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) - if IS_WINDOWS: str = str.replace('/','\\') + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) + out.write(str) + for f in filter(lambda f: f.endswith('.mli'), os.listdir(self.src_dir)): + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): - out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) - if IS_WINDOWS: str = str.replace('/','\\') + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: - out.write('%s/%s.mli: %s/%s.ml %s\n' % (sub_dir,m,sub_dir,m,prev)) - out.write('\t%s -I %s -i -c %s/%s.ml > %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m,sub_dir,m)) - prev = prev + ' ' + sub_dir + '/' + m + '.mli' + fn = os.path.join(self.src_dir, ('%s.mli' % m)) + if not os.path.exists(fn): + out.write('%s.mli: %s.ml %s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) + prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = '' for m in modules: - out.write('%s/%s.cmi: %s/%s.mli\n' % (sub_dir,m,sub_dir,m)) - out.write('\t%s -I %s -c %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m)) - cmis = cmis + ' ' + sub_dir + '/' + m + '.cmi' + out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) + out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) + cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') diff --git a/scripts/update_api.py b/scripts/update_api.py index 44d871348..77a5bf7f2 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1185,7 +1185,8 @@ def mk_ml(): ip = inparams(params) op = outparams(params) if len(ip) == 0: - ml_native.write(' unit -> ') + ml_native.write(' unit -> ') + ml_i.write(' unit -> ') for p in ip: ml_native.write('%s -> ' % param2ml(p)) ml_i.write('%s -> ' % param2ml(p)) @@ -1233,6 +1234,8 @@ def mk_ml(): ml_native.write(' ') ml_native.write('a%d' % i) i = i + 1 + if len(ip) == 0: + ml_native.write('()') ml_native.write(' = \n') ml_native.write(' ') if result == VOID and len(op) == 0: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 081433f1f..8b783d25d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -34,7 +34,7 @@ struct ) let create_context settings = - let cfg = Z3native.mk_config in + let cfg = Z3native.mk_config () in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = Z3native.mk_context_rc cfg in @@ -101,12 +101,12 @@ end module Version = struct - let major = let (x, _, _, _) = Z3native.get_version in x - let minor = let (_, x, _, _) = Z3native.get_version in x - let build = let (_, _, x, _) = Z3native.get_version in x - let revision = let (_, _, _, x) = Z3native.get_version in x + let major = let (x, _, _, _) = Z3native.get_version () in x + let minor = let (_, x, _, _) = Z3native.get_version () in x + let build = let (_, _, x, _) = Z3native.get_version () in x + let revision = let (_, _, _, x) = Z3native.get_version () in x let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in + let (mj, mn, bld, rev) = Z3native.get_version () in string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ @@ -609,6 +609,10 @@ sig val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit val mk_params : context -> params val to_string : params -> string + + val update_param_value : context -> string -> string -> unit + val get_param_value : context -> string -> string option + val set_print_mode : context -> Z3enums.ast_print_mode -> unit end = struct type params = z3_native_object @@ -1099,7 +1103,7 @@ struct end -module Array = +module Z3Array = struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) @@ -1382,7 +1386,7 @@ struct end -module List = +module Z3List = struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in @@ -2038,7 +2042,7 @@ struct if not r then None else - expr_of_ptr (z3obj_gc x) v + Some(expr_of_ptr (z3obj_gc x) v) let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion @@ -2331,7 +2335,7 @@ struct if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.create_sd k (Z3native.stats_get_float_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in mk_list f n @@ -2667,3 +2671,6 @@ let global_param_reset_all = let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled + +module Array = Z3Array +module List = Z3List diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 570ff8717..3f83ef6b2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -8,7 +8,7 @@ (** General Z3 exceptions Many functions in this API may throw an exception; if they do, it is this one.*) -exception Error +exception Error of string (** Context objects. @@ -55,11 +55,11 @@ module Log : sig (** Open an interaction log file. @return True if opening the log file succeeds, false otherwise. *) - (* CMW: "open" seems to be a reserved keyword? *) + (* CMW: "open" is a reserved keyword. *) val open_ : string -> bool (** Closes the interaction log. *) - val close : unit + val close : unit -> unit (** Appends a user-provided string to the interaction log. *) val append : string -> unit From 2ee3ff518fcd1e305f4d58cccc52e69af5d21294 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 21 Oct 2013 11:22:42 +0100 Subject: [PATCH 319/646] ML bindings: list/array are now called z3array/z3list to avoid confusion. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 4 ---- src/api/ml/z3.mli | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8b783d25d..ed815d720 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2670,7 +2670,3 @@ let global_param_reset_all = let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled - - -module Array = Z3Array -module List = Z3List diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 3f83ef6b2..ff1898185 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -761,7 +761,7 @@ sig end (** Functions to manipulate Array expressions *) -module Array : +module Z3Array : sig (** Create a new array sort. *) val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort @@ -1093,7 +1093,7 @@ sig end (** Functions to manipulate List expressions *) -module List : +module Z3List : sig (** Create a new list sort. *) val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort From f7c371ac4d2228669c457ce8e9a27dc622bb3df6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 28 Oct 2013 12:17:58 +0000 Subject: [PATCH 320/646] ML API: bugfix for native function with more than 5 parameters. Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 77a5bf7f2..dd1e46c4f 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1211,9 +1211,11 @@ def mk_ml(): ml_i.write(')') ml_native.write('\n') ml_i.write('\n') - ml_native.write(' = "n_%s"\n' % ml_method_name(name)) if len(ip) > 5: - ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write(' = "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write(' "n_%s"\n' % ml_method_name(name)) + else: + ml_native.write(' = "n_%s"\n' % ml_method_name(name)) ml_native.write('\n') ml_native.write(' end\n\n') ml_i.write('\n(**/**)\n'); From 832e119b9858c60ec4538fbfb21275da1120d953 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 2 Apr 2014 19:08:59 +0100 Subject: [PATCH 321/646] ML API bugfix (Codeplex issue 102) Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 43 ++++++ src/api/ml/z3.ml | 289 +++++++++++++++++++------------------- src/api/ml/z3.mli | 3 + 3 files changed, 192 insertions(+), 143 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index c9ed1d948..0dd227784 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -196,6 +196,48 @@ let basic_tests ( ctx : context ) = Printf.printf "Exception caught, OK.\n" ) +(** + A basic example of how to use quantifiers. +**) +let quantifierExample1 ( ctx : context ) = + Printf.printf "QuantifierExample\n" ; + let is = (Integer.mk_sort ctx) in + let types = [ is; is; is ] in + let names = [ (Symbol.mk_string ctx "x_0"); + (Symbol.mk_string ctx "x_1"); + (Symbol.mk_string ctx "x_2") ] in + let vars = [ (Quantifier.mk_bound ctx 2 (List.nth types 0)); + (Quantifier.mk_bound ctx 2 (List.nth types 1)); + (Quantifier.mk_bound ctx 2 (List.nth types 2)) ] in + let xs = [ (Integer.mk_const ctx (List.nth names 0)); + (Integer.mk_const ctx (List.nth names 1)); + (Integer.mk_const ctx (List.nth names 2)) ] in + + let body_vars = (Boolean.mk_and ctx + [ (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth vars 0) ; (Integer.mk_numeral_i ctx 1)]) + (Integer.mk_numeral_i ctx 2)) ; + (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth vars 1); (Integer.mk_numeral_i ctx 2)]) + (Arithmetic.mk_add ctx [ (List.nth vars 2); (Integer.mk_numeral_i ctx 3)])) ]) in + let body_const = (Boolean.mk_and ctx + [ (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth xs 0); (Integer.mk_numeral_i ctx 1)]) + (Integer.mk_numeral_i ctx 2)) ; + (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth xs 1); (Integer.mk_numeral_i ctx 2)]) + (Arithmetic.mk_add ctx [ (List.nth xs 2); (Integer.mk_numeral_i ctx 3)])) ]) in + + let x = (Quantifier.mk_forall ctx types names body_vars (Some 1) [] [] (Some (Symbol.mk_string ctx "Q1")) (Some (Symbol.mk_string ctx "skid1"))) in + Printf.printf "Quantifier X: %s\n" (Quantifier.to_string x) ; + let y = (Quantifier.mk_forall_const ctx xs body_const (Some 1) [] [] (Some (Symbol.mk_string ctx "Q2")) (Some (Symbol.mk_string ctx "skid2"))) in + Printf.printf "Quantifier Y: %s\n" (Quantifier.to_string y) ; + if (is_true (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) + else if (is_false (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) + else if (is_const (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) let _ = try ( @@ -217,6 +259,7 @@ let _ = Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); basic_tests ctx ; + quantifierExample1 ctx ; Printf.printf "Disposing...\n"; Gc.full_major () ); diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index ed815d720..d91d3ca8d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -297,6 +297,7 @@ struct | VAR_AST -> true | _ -> false + let is_app ( x : ast ) = (get_ast_kind x) == APP_AST let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST @@ -828,22 +829,22 @@ end = struct (Z3native.mk_bool_sort (gnc x)) (Z3native.get_sort (gnc x) (gno x))) - let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -1100,6 +1101,8 @@ struct mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + + let to_string ( x : quantifier ) = (Expr.to_string (expr_of_quantifier x)) end @@ -1108,12 +1111,12 @@ struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_constant_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_default_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_array_map ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_as_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) let is_array ( x : expr ) = (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) @@ -1150,11 +1153,11 @@ struct let mk_sort ( ctx : context ) ( ty : sort ) = sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) let mk_empty ( ctx : context ) ( domain : sort ) = @@ -1203,7 +1206,7 @@ struct (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) let get_size ( x : sort ) = let (r, v) = (Z3native.get_finite_domain_sort_size (Sort.gnc x) (Sort.gno x)) in @@ -1219,19 +1222,19 @@ struct ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_join ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_widen ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_project ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_negation_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_rename ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_clone ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) let get_arity ( x : sort ) = Z3native.get_relation_arity (Sort.gnc x) (Sort.gno x) @@ -1534,37 +1537,37 @@ struct (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) let is_real ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) @@ -1616,57 +1619,57 @@ struct sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) let is_bv ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_bit1 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_sdiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_udiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_SRem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_urem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_smod ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_sdiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_udiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_srem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_urem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_smod0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_ule ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_sle ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_uge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_sge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_ult ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_slt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_ugt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_sgt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_nand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_xnor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_concat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_signextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_zeroextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_extract ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_repeat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_reduceor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_comp ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_shiftleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftrightlogical ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_rotateleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateright ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateleftextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotaterightextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_int_to_bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_bv_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_carry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_xor3 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) let get_int ( x : expr ) = let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in @@ -1778,44 +1781,44 @@ end module Proof = struct - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_asserted ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_goal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_modus_ponens ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_reflexivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_symmetry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_transitivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_Transitivity_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_monotonicity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_quant_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_distributivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_and_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_or_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_rewrite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_pull_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_push_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_elim_unused_vars ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_der ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_quant_inst ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_hypothesis ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_unit_resolution ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_iff_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_commutativity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_def_axiom ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_apply_def ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_iff_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_nnf_pos ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_neg ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_cnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_skolemize ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_modus_ponens_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_theory_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index ff1898185..5c9c56dbf 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -758,6 +758,9 @@ sig (** Create a Quantifier. *) val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** A string representation of the quantifier. *) + val to_string : quantifier -> string end (** Functions to manipulate Array expressions *) From 0da912e5578cfa56c5cc4a8d804d505794bc3fe3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 2 Apr 2014 19:18:43 +0100 Subject: [PATCH 322/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index d91d3ca8d..5f8d96d2a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -793,7 +793,7 @@ end = struct mk_list f n let update ( x : expr ) ( args : expr list ) = - if (List.length args <> (get_num_args x)) then + if ((AST.is_app (ast_of_expr x)) && (List.length args <> (get_num_args x))) then raise (Z3native.Exception "Number of arguments does not match") else expr_of_ptr (Expr.gc x) (Z3native.update_term (gnc x) (gno x) (List.length args) (expr_lton args)) From 20be39006ec2b86ebb02e46be0cc7c4dec951f18 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:32:06 +0100 Subject: [PATCH 323/646] ML API `or' is deprecated, changed to `||' Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 5f8d96d2a..c037a9263 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -748,7 +748,7 @@ end = struct Expr(z3_native_object_of_ast_ptr ctx no) else if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + if (sk == INT_SORT || sk == REAL_SORT || sk == BV_SORT) then Expr(z3_native_object_of_ast_ptr ctx no) else raise (Z3native.Exception "Unsupported numeral object") From a028f200af844393bf8c9e0a35107303b325fd5c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:33:52 +0100 Subject: [PATCH 324/646] ML example; `or' is deprecated, changed to `||' Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 0dd227784..25862b2d7 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -168,7 +168,7 @@ let basic_tests ( ctx : context ) = let inum = (get_numerator rn) in let iden = get_denominator rn in Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; - if ((Real.to_string inum) <> "42" or (Real.to_string iden) <> "43") then + if ((Real.to_string inum) <> "42" || (Real.to_string iden) <> "43") then raise (TestFailedException "") else Printf.printf "Test passed.\n" From a3d17a0e24f288b3a3fd1b0572bb5488750aa128 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:38:29 +0100 Subject: [PATCH 325/646] ML API build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index f46339f5c..8017c8c61 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1385,6 +1385,15 @@ class MLComponent(Component): out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') + # Generate META file and package installation commands + self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('\tocamlfind remove Z3\n') + out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)') + if IS_WINDOWS: + out.write(' libz3$(LIB_EXT)') + out.write('\n') + out.write('\n') def main_component(self): return is_ml_enabled() From d0588c0565b3d96fae32e3d9967092167925c8ab Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:39:53 +0100 Subject: [PATCH 326/646] ML API build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8017c8c61..41efe90f1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1821,6 +1821,8 @@ def mk_install(out): for c in get_components(): c.mk_install_deps(out) out.write(' ') + if is_ml_enabled(): + out.write('ocamlfind_install') out.write('\n') out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'bin')) out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'include')) From 3228c3ff5ca5784e948b5ceea873ea013d3e80d0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:49:05 +0100 Subject: [PATCH 327/646] ML API build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 41efe90f1..c74836a27 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -35,6 +35,7 @@ JNI_HOME=getenv("JNI_HOME", None) OCAMLC=getenv("OCAMLC", "ocamlc") OCAMLOPT=getenv("OCAMLOPT", "ocamlopt") OCAML_LIB=getenv("OCAML_LIB", None) +OCAMLFIND=getenv("OCAMLFIND", "ocamlfind") CXX_COMPILERS=['g++', 'clang++'] C_COMPILERS=['gcc', 'clang'] @@ -357,6 +358,15 @@ def check_ml(): rmf('hello.cmx') rmf('a.out') find_ml_lib() + find_ocaml_find() + +def find_ocaml_find(): + global OCAMLFIND + if is_verbose(): + print "Testing %s..." % OCAMLFIND + r = exec_cmd([OCAMLFIND, 'printconf']) + if r != 0: + OCAMLFIND='' def find_ml_lib(): global OCAML_LIB @@ -1387,13 +1397,14 @@ class MLComponent(Component): out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') - out.write('\tocamlfind remove Z3\n') - out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)') - if IS_WINDOWS: - out.write(' libz3$(LIB_EXT)') - out.write('\n') - out.write('\n') + if OCAMLFIND != '': + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('\t%s remove Z3\n' % (OCAMLFIND)) + out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + if IS_WINDOWS: + out.write(' libz3$(LIB_EXT)') + out.write('\n') + out.write('\n') def main_component(self): return is_ml_enabled() @@ -1821,7 +1832,7 @@ def mk_install(out): for c in get_components(): c.mk_install_deps(out) out.write(' ') - if is_ml_enabled(): + if is_ml_enabled() and OCAMLFIND != '': out.write('ocamlfind_install') out.write('\n') out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'bin')) From 10fe6b7759f2b117a71d4129dbe18cfdfa1397ff Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 12:55:23 +0100 Subject: [PATCH 328/646] ML API refactoring Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 72 ++++++++----------- src/api/ml/z3.mli | 180 +++++++++++++++++++++++----------------------- 2 files changed, 119 insertions(+), 133 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c037a9263..051a54696 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,5 +1,5 @@ (** - The Z3 ML/Ocaml Interface. + The Z3 ML/OCaml Interface. Copyright (C) 2012 Microsoft Corporation @author CM Wintersteiger (cwinter) 2012-12-17 @@ -698,7 +698,6 @@ sig val get_simplify_help : context -> string val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs val get_func_decl : expr -> FuncDecl.func_decl - val get_bool_value : expr -> Z3enums.lbool val get_num_args : expr -> int val get_args : expr -> expr list val update : expr -> expr list -> expr @@ -710,20 +709,7 @@ sig val is_numeral : expr -> bool val is_well_sorted : expr -> bool val get_sort : expr -> Sort.sort - val is_bool : expr -> bool val is_const : expr -> bool - val is_true : expr -> bool - val is_false : expr -> bool - val is_eq : expr -> bool - val is_distinct : expr -> bool - val is_ite : expr -> bool - val is_and : expr -> bool - val is_or : expr -> bool - val is_iff : expr -> bool - val is_xor : expr -> bool - val is_not : expr -> bool - val is_implies : expr -> bool - val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr val mk_const_f : context -> FuncDecl.func_decl -> expr @@ -782,9 +768,7 @@ end = struct let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) - - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) @@ -823,29 +807,11 @@ end = struct let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) - - let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (gnc x) - (Z3native.mk_bool_sort (gnc x)) - (Z3native.get_sort (gnc x) (gno x))) - + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -888,12 +854,6 @@ struct let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx - - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) - - let mk_distinct ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) let mk_not ( ctx : context ) ( a : expr ) = expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) @@ -917,6 +877,31 @@ struct let mk_or ( ctx : context ) ( args : expr list ) = let f x = (Expr.gno (x)) in expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) + + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + let mk_distinct ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) + + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) end @@ -1784,6 +1769,7 @@ struct let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) let is_asserted ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) let is_goal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_OEQ) let is_modus_ponens ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) let is_reflexivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) let is_symmetry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 5c9c56dbf..c554d7564 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1,5 +1,5 @@ (** - The Z3 ML/Ocaml Interface. + The Z3 ML/OCaml Interface. Copyright (C) 2012 Microsoft Corporation @author CM Wintersteiger (cwinter) 2012-12-17 @@ -488,10 +488,6 @@ sig (** The function declaration of the function that is applied in this expression. *) val get_func_decl : Expr.expr -> FuncDecl.func_decl - (** Indicates whether the expression is the true or false expression - or something else (L_UNDEF). *) - val get_bool_value : Expr.expr -> Z3enums.lbool - (** The number of arguments of the expression. *) val get_num_args : Expr.expr -> int @@ -535,11 +531,88 @@ sig (** The Sort of the term. *) val get_sort : Expr.expr -> Sort.sort - (** Indicates whether the term has Boolean sort. *) - val is_bool : Expr.expr -> bool - (** Indicates whether the term represents a constant. *) val is_const : Expr.expr -> bool + + (** Creates a new constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) + val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) + val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) + val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr + + (** Create a numeral of a given sort. + @return A Term with the given value and sort *) + val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) + val mk_numeral_int : context -> int -> Sort.sort -> expr +end + +(** Boolean expressions; Propositional logic and equality *) +module Boolean : +sig + (** Create a Boolean sort *) + val mk_sort : context -> Sort.sort + + (** Create a Boolean constant. *) + val mk_const : context -> Symbol.symbol -> Expr.expr + + (** Create a Boolean constant. *) + val mk_const_s : context -> string -> Expr.expr + + (** The true Term. *) + val mk_true : context -> Expr.expr + + (** The false Term. *) + val mk_false : context -> Expr.expr + + (** Creates a Boolean value. *) + val mk_val : context -> bool -> Expr.expr + + (** Mk an expression representing not(a). *) + val mk_not : context -> Expr.expr -> Expr.expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 iff t2. *) + val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 -> t2. *) + val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 xor t2. *) + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing the AND of args *) + val mk_and : context -> Expr.expr list -> Expr.expr + + (** Create an expression representing the OR of args *) + val mk_or : context -> Expr.expr list -> Expr.expr + + (** Creates the equality between two expr's. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Creates a distinct term. *) + val mk_distinct : context -> Expr.expr list -> Expr.expr + + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) + val get_bool_value : Expr.expr -> Z3enums.lbool + + (** Indicates whether the term has Boolean sort. *) + val is_bool : Expr.expr -> bool (** Indicates whether the term is the constant true. *) val is_true : Expr.expr -> bool @@ -573,84 +646,6 @@ sig (** Indicates whether the term is an implication *) val is_implies : Expr.expr -> bool - - (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) - val is_oeq : Expr.expr -> bool - - (** Creates a new constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - - (** Creates a new constant. *) - val mk_const_s : context -> string -> Sort.sort -> expr - - (** Creates a constant from the func_decl. *) - val mk_const_f : context -> FuncDecl.func_decl -> expr - - (** Creates a fresh constant with a name prefixed with a string. *) - val mk_fresh_const : context -> string -> Sort.sort -> expr - - (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - - (** Create a numeral of a given sort. - @return A Term with the goven value and sort *) - val mk_numeral_string : context -> string -> Sort.sort -> expr - - (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @return A Term with the given value and sort *) - val mk_numeral_int : context -> int -> Sort.sort -> expr -end - -(** Boolean expressions *) -module Boolean : -sig - (** Create a Boolean sort *) - val mk_sort : context -> Sort.sort - - (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> Expr.expr - - (** Create a Boolean constant. *) - val mk_const_s : context -> string -> Expr.expr - - (** The true Term. *) - val mk_true : context -> Expr.expr - - (** The false Term. *) - val mk_false : context -> Expr.expr - - (** Creates a Boolean value. *) - val mk_val : context -> bool -> Expr.expr - - (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr list -> Expr.expr - - (** Mk an expression representing not(a). *) - val mk_not : context -> Expr.expr -> Expr.expr - - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) - val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 iff t2. *) - val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 -> t2. *) - val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 xor t2. *) - val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing the AND of args *) - val mk_and : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing the OR of args *) - val mk_or : context -> Expr.expr list -> Expr.expr end (** Quantifier expressions *) @@ -817,7 +812,7 @@ sig The node a must have an array sort [domain -> range], and i must have the sort domain. The sort of the result is range. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -833,7 +828,7 @@ sig on all indices except for i, where it maps to v (and the select of a with respect to i may be a different value). - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr @@ -841,7 +836,7 @@ sig The resulting term is an array, such that a selecton an arbitrary index produces the value v. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr @@ -850,7 +845,7 @@ sig Eeach element of args must be of an array sort [domain_i -> range_i]. The function declaration f must have type range_1 .. range_n -> range. v must have sort range. The sort of the result is [domain_i -> range]. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr @@ -1837,6 +1832,11 @@ sig (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) val is_goal : Expr.expr -> bool + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) + val is_oeq : Expr.expr -> bool + (** Indicates whether the term is proof via modus ponens Given a proof for p and a proof for (implies p q), produces a proof for q. From 2f00968b4febd0b2128b50511340e558e026cf98 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:05:22 +0100 Subject: [PATCH 329/646] ML example doc fix Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/ml/README b/examples/ml/README index 3e1eb0d1c..7d33df743 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -12,3 +12,13 @@ or LD_LIBRARY_PATH=. ./ml_example.byte for the byte-code version. +If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), +then we can compile this example as follows: + +ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg +ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg + +Note that the resulting binaries depend on the shared z3 library, which needs to be +in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was +installed into ocamlfind, the path that should be added is +`ocamlfind printconf destdir`/Z3 From e5932efc44d5dd3e379e7f77321113909ee06a31 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:05:50 +0100 Subject: [PATCH 330/646] ML API refactoring (z3native.c -> z3native_stubs.c) Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 8 ++++---- scripts/update_api.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c74836a27..8aa582d12 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1374,10 +1374,10 @@ class MLComponent(Component): out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') diff --git a/scripts/update_api.py b/scripts/update_api.py index dd1e46c4f..0ed9b29ca 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1148,7 +1148,7 @@ def mk_ml(): ml_dir = get_component('ml').src_dir ml_nativef = os.path.join(ml_dir, 'z3native.ml') ml_nativefi = os.path.join(ml_dir, 'z3native.mli') - ml_wrapperf = os.path.join(ml_dir, 'z3native.c') + ml_wrapperf = os.path.join(ml_dir, 'z3native_stubs.c') ml_native = open(ml_nativef, 'w') ml_i = open(ml_nativefi, 'w') ml_native.write('(* Automatically generated file *)\n\n') From 4f0e8a1057069ffb3c34926faad1fe2b582052c0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:06:29 +0100 Subject: [PATCH 331/646] ML API refactoring (z3native.c -> z3native_stubs.c) Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fccf9424d..9c9707c4b 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ src/api/ml/native.c src/api/ml/z3.ml src/api/ml/enumerations.ml src/api/ml/z3native.c +src/api/ml/z3native_stubs.c src/api/ml/z3native.ml src/api/ml/z3enums.ml src/api/ml/z3.mllib From e2f0dc31f471af42edce1703719e5da32476c38a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 14:18:46 +0100 Subject: [PATCH 332/646] ML API: Added get_bit_int and get_ratio Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 +- src/api/ml/META | 7 ++++ src/api/ml/z3.ml | 101 +++++++++++++++++++++++++-------------------- src/api/ml/z3.mli | 12 ++++-- 4 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 src/api/ml/META diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8aa582d12..b19e95cee 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1534,7 +1534,7 @@ class MLExampleComponent(ExampleComponent): out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" z3.cma') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1545,7 +1545,7 @@ class MLExampleComponent(ExampleComponent): out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" z3.cmxa') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') diff --git a/src/api/ml/META b/src/api/ml/META new file mode 100644 index 000000000..d275d98be --- /dev/null +++ b/src/api/ml/META @@ -0,0 +1,7 @@ +# META file for the "z3" package: +version = "VERSION" +description = "Z3 Theorem Prover (OCaml API)" +requires = "num" +archive(byte) = "z3.cma" +archive(native) = "z3.cmxa" +linkopts = "-cclib -lz3" \ No newline at end of file diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 051a54696..dda8807c9 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1425,6 +1425,50 @@ end module Arithmetic = struct + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + + let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + let is_rat_numeral ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) module Integer = struct @@ -1435,6 +1479,12 @@ struct let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") + + let get_big_int ( x : expr ) = + if (is_int_numeral x) then + let s = to_string(x) in + (Big_int.big_int_of_string s) + else raise (Z3native.Exception "Conversion failed.") let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) @@ -1474,6 +1524,12 @@ struct let get_denominator ( x : expr ) = expr_of_ptr (Expr.gc x) (Z3native.get_denominator (Expr.gnc x) (Expr.gno x)) + let get_ratio ( x : expr ) = + if (is_rat_numeral x) then + let s = to_string(x) in + (Ratio.ratio_of_string s) + else raise (Z3native.Exception "Conversion failed.") + let to_decimal_string ( x : expr ) ( precision : int ) = Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision @@ -1518,51 +1574,6 @@ struct end end - let is_int ( x : expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - - let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - - let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - - let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - - let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - - let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - - let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - - let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - - let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - - let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - - let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - - let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - - let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - - let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - - let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - - let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - - let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) - - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - let mk_add ( ctx : context ) ( t : expr list ) = let f x = (Expr.gno x) in (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index c554d7564..4122f40f2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1149,6 +1149,9 @@ sig (** Retrieve the int value. *) val get_int : Expr.expr -> int + (** Get a big_int from an integer numeral *) + val get_big_int : Expr.expr -> Big_int.big_int + (** Returns a string representation of the numeral. *) val to_string : Expr.expr -> string @@ -1201,10 +1204,13 @@ sig val mk_sort : context -> Sort.sort (** The numerator of a rational numeral. *) - val get_numerator : Expr.expr-> Expr.expr + val get_numerator : Expr.expr -> Expr.expr (** The denominator of a rational numeral. *) - val get_denominator : Expr.expr-> Expr.expr + val get_denominator : Expr.expr -> Expr.expr + + (** Get a ratio from a real numeral *) + val get_ratio : Expr.expr -> Ratio.ratio (** Returns a string representation in decimal notation. The result has at most as many decimal places as indicated by the int argument.*) @@ -1323,7 +1329,7 @@ sig val is_int_numeral : Expr.expr -> bool (** Indicates whether the term is a real numeral. *) - val is_rat_num : Expr.expr -> bool + val is_rat_numeral : Expr.expr -> bool (** Indicates whether the term is an algebraic number *) val is_algebraic_number : Expr.expr -> bool From 6394dde85d18b350a5c52916c109582343952340 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 15:33:07 +0100 Subject: [PATCH 333/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b19e95cee..84621e396 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1375,7 +1375,7 @@ class MLComponent(Component): out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): From 1e4b14af675c30f38c950672d112b8c463a3d8cb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:10:18 +0100 Subject: [PATCH 334/646] ML API: ocamlfind installation fixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 4 ++-- scripts/mk_util.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index 7d33df743..844638552 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -15,8 +15,8 @@ for the byte-code version. If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), then we can compile this example as follows: -ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg -ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg +ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg ml_example.ml +ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml Note that the resulting binaries depend on the shared z3 library, which needs to be in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 84621e396..8577479b7 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1401,6 +1401,9 @@ class MLComponent(Component): out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + for m in modules: + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmx' % (os.path.join(sub_dir, m))) if IS_WINDOWS: out.write(' libz3$(LIB_EXT)') out.write('\n') From f72ac1afb69ea38b77333b11e2cd10d2b108eb68 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:10:29 +0100 Subject: [PATCH 335/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 0ed9b29ca..8ce652ed5 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1254,7 +1254,7 @@ def mk_ml(): ml_native.write(' a%d' % i) i = i + 1 ml_native.write(') in\n') - if len(params) > 0 and param_type(params[0]) == CONTEXT: + if name not in Unwrapped and len(params) > 0 and param_type(params[0]) == CONTEXT: ml_native.write(' let err = (error_code_of_int (ML2C.n_get_error_code a0)) in \n') ml_native.write(' if err <> OK then\n') ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (int_of_error_code err)))\n') From d8a84c9f8990470736c7b3f62e2a6b27aa846f0f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:12:55 +0100 Subject: [PATCH 336/646] ML API doc fix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.mli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 4122f40f2..8a88a91bb 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -2404,7 +2404,7 @@ sig (** The finite set of distinct values that represent the interpretation of a sort. {!get_sorts} - @returns A list of expressions, where each is an element of the universe of the sort *) + @return A list of expressions, where each is an element of the universe of the sort *) val sort_universe : model -> Sort.sort -> AST.ast list (** Conversion of models to strings. From 47997e175f10ddfbb20dd103c92261064852bfd1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:16:40 +0100 Subject: [PATCH 337/646] ML API doc fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.mli | 220 +++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 8a88a91bb..ff45fb0f2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -241,7 +241,7 @@ sig AST objects are reference counted and unwrapping an AST disables automatic reference counting, i.e., all references to the IntPtr that is returned must be handled externally and through native calls (see e.g., - Z3native.inc_ref). + [Z3native.inc_ref]). {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr @@ -251,7 +251,7 @@ sig managed objects. Note that the native ast that is passed must be a native object obtained from Z3 (e.g., through {!unwrap_ast}) and that it must have a correct reference count (see e.g., - Z3native.inc_ref). *) + [Z3native.inc_ref]). *) val wrap_ast : context -> Z3native.z3_ast -> ast end @@ -439,7 +439,7 @@ sig (** Update a mutable configuration parameter. The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -p + [z3.exe -p] Only a few configuration parameters are mutable once the context is created. An exception is thrown when trying to modify an immutable parameter. {!get_param_value} *) @@ -479,7 +479,7 @@ sig {!get_simplify_help} *) val simplify : Expr.expr -> Params.params option -> expr - (** A string describing all available parameters to Expr.Simplify. *) + (** A string describing all available parameters to [Expr.Simplify]. *) val get_simplify_help : context -> string (** Retrieves parameter descriptions for simplifier. *) @@ -498,20 +498,20 @@ sig The number of new arguments should coincide with the current number of arguments. *) val update : Expr.expr -> Expr.expr list -> expr - (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + (** Substitute every occurrence of [from[i]] in the expression with [to[i]], for [i] smaller than [num_exprs]. - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. *) + The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. + For every [i] smaller than [num_exprs], we must have that + sort of [from[i]] must be equal to sort of [to[i]]. *) val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr - (** Substitute every occurrence of from in the expression with to. + (** Substitute every occurrence of [from] in the expression with [to]. {!substitute} *) val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr (** Substitute the free variables in the expression with the expressions in the expr array - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) + For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) val substitute_vars : Expr.expr -> Expr.expr list -> expr (** Translates (copies) the term to another context. @@ -554,7 +554,7 @@ sig val mk_numeral_string : context -> string -> Sort.sort -> expr (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. @return A Term with the given value and sort *) val mk_numeral_int : context -> int -> Sort.sort -> expr end @@ -580,19 +580,19 @@ sig (** Creates a Boolean value. *) val mk_val : context -> bool -> Expr.expr - (** Mk an expression representing not(a). *) + (** Mk an expression representing [not(a)]. *) val mk_not : context -> Expr.expr -> Expr.expr - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + (** Create an expression representing an if-then-else: [ite(t1, t2, t3)]. *) val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 iff t2. *) + (** Create an expression representing [t1 iff t2]. *) val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 -> t2. *) + (** Create an expression representing [t1 -> t2]. *) val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 xor t2. *) + (** Create an expression representing [t1 xor t2]. *) val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing the AND of args *) @@ -604,7 +604,7 @@ sig (** Creates the equality between two expr's. *) val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Creates a distinct term. *) + (** Creates a [distinct] term. *) val mk_distinct : context -> Expr.expr list -> Expr.expr (** Indicates whether the expression is the true or false expression @@ -806,45 +806,45 @@ sig (** Array read. - The argument a is the array and i is the index + The argument [a] is the array and [i] is the index of the array that gets read. - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. + The node [a] must have an array sort [[domain -> range]], + and [i] must have the sort [domain]. + The sort of the result is [range]. {!Z3Array.mk_sort} {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr (** Array update. - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. + The node [a] must have an array sort [[domain -> range]], + [i] must have sort [domain], + [v] must have sort range. The sort of the result is [[domain -> range]]. The semantics of this function is given by the theory of arrays described in the SMT-LIB standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). + The result of this function is an array that is equal to [a] + (with respect to [select]) + on all indices except for [i], where it maps to [v] + (and the [select] of [a] with + respect to [i] may be a different value). {!Z3Array.mk_sort} {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create a constant array. - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. + The resulting term is an array, such that a [select]on an arbitrary index + produces the value [v]. {!Z3Array.mk_sort} {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr (** Maps f on the argument arrays. - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. + Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. + The function declaration [f] must have type [ range_1 .. range_n -> range]. + [v] must have sort range. The sort of the result is [[domain_i -> range]]. {!Z3Array.mk_sort} {!mk_select} {!mk_store} *) @@ -938,8 +938,8 @@ sig (** Indicates whether the term is an relation store Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. *) + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + correspond to the [n] columns of the relation. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an empty relation *) @@ -997,8 +997,8 @@ sig (** Indicates whether the term is a relational select Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. *) + The function takes [n+1] arguments, where the first argument is a relation, + and the remaining [n] arguments correspond to a record. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a relational clone (copy) @@ -1161,11 +1161,11 @@ sig (** Creates an integer constant. *) val mk_const_s : context -> string -> Expr.expr - (** Create an expression representing t1 mod t2. + (** Create an expression representing [t1 mod t2]. The arguments must have int type. *) val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 rem t2. + (** Create an expression representing [t1 rem t2]. The arguments must have int type. *) val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1181,8 +1181,8 @@ sig There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + You can take the floor of a real by creating an auxiliary integer Term [k] and + and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. The argument must be of integer sort. *) val mk_int2real : context -> Expr.expr -> Expr.expr @@ -1334,34 +1334,34 @@ sig (** Indicates whether the term is an algebraic number *) val is_algebraic_number : Expr.expr -> bool - (** Create an expression representing t[0] + t[1] + .... *) + (** Create an expression representing [t[0] + t[1] + ...]. *) val mk_add : context -> Expr.expr list -> Expr.expr - (** Create an expression representing t[0] * t[1] * .... *) + (** Create an expression representing [t[0] * t[1] * ...]. *) val mk_mul : context -> Expr.expr list -> Expr.expr - (** Create an expression representing t[0] - t[1] - .... *) + (** Create an expression representing [t[0] - t[1] - ...]. *) val mk_sub : context -> Expr.expr list -> Expr.expr - (** Create an expression representing -t. *) + (** Create an expression representing [-t]. *) val mk_unary_minus : context -> Expr.expr -> Expr.expr - (** Create an expression representing t1 / t2. *) + (** Create an expression representing [t1 / t2]. *) val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 ^ t2. *) + (** Create an expression representing [t1 ^ t2]. *) val mk_power : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 < t2 *) + (** Create an expression representing [t1 < t2] *) val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 <= t2 *) + (** Create an expression representing [t1 <= t2] *) val mk_le : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 > t2 *) + (** Create an expression representing [t1 > t2] *) val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 >= t2 *) + (** Create an expression representing [t1 >= t2] *) val mk_ge : context -> Expr.expr -> Expr.expr -> Expr.expr end @@ -1610,8 +1610,8 @@ sig (** Unsigned division. - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result + It is defined as the floor of [t1/t2] if \c t2 is + different from zero. If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1620,33 +1620,33 @@ sig It is defined in the following way: - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned remainder. - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. + It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed remainder. - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed remainder (sign follows divisor). - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1694,27 +1694,27 @@ sig The arguments must have a bit-vector sort. @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). *) + The result is a bit-vector of size [n1+n2], where [n1] ([n2]) + is the size of [t1] ([t2]). *) val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector extraction. Extract the bits between two limits from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. *) + size [m] to yield a new bitvector of size [n], where + [n = high - low + 1]. *) val mk_extract : context -> int -> int -> Expr.expr -> Expr.expr (** Bit-vector sign extension. Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. *) + size [m+i], where \c m is the size of the given bit-vector. *) val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector zero extension. Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the + bitvector of size [m+i], where \c m is the size of the given bit-vector. *) val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr @@ -1723,7 +1723,7 @@ sig (** Shift left. - It is equivalent to multiplication by 2^x where \c x is the value of third argument. + It is equivalent to multiplication by [2^x] where \c x is the value of third argument. NB. The semantics of shift operations varies between environments. This definition does not necessarily capture directly the semantics of the @@ -1732,7 +1732,7 @@ sig (** Logical shift right - It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. NB. The semantics of shift operations varies between environments. This definition does not necessarily capture directly the semantics of the @@ -1773,7 +1773,7 @@ sig (** Create an integer from the bit-vector argument If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where + So the result is non-negative and in the range [[0..2^N-1]], where N are the number of bits in the argument. If \c is_signed is true, \c t1 is treated as a signed bit-vector. @@ -2353,15 +2353,15 @@ sig end (** Retrieves the interpretation (the assignment) of a func_decl in the model. - An expression if the function has an interpretation in the model, null otherwise. *) + @return An expression if the function has an interpretation in the model, null otherwise. *) val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option (** Retrieves the interpretation (the assignment) of an expression in the model. - An expression if the constant has an interpretation in the model, null otherwise. *) + @return An expression if the constant has an interpretation in the model, null otherwise. *) val get_const_interp_e : model -> Expr.expr -> Expr.expr option (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + @return A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option (** The number of constant interpretations in the model. *) @@ -2383,11 +2383,11 @@ sig This function may fail if the argument contains quantifiers, is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. + In this case a [ModelEvaluationFailedException] is thrown. *) val eval : model -> Expr.expr -> bool -> Expr.expr option - (** Alias for eval. *) + (** Alias for [eval]. *) val evaluate : model -> Expr.expr -> bool -> Expr.expr option (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -2408,7 +2408,7 @@ sig val sort_universe : model -> Sort.sort -> AST.ast list (** Conversion of models to strings. - A string representation of the model. *) + @return A string representation of the model. *) val to_string : model -> string end @@ -2416,17 +2416,17 @@ end Probes are used to inspect a goal (aka problem) and collect information that may be used to decide which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. + The complete list of probes may be obtained using the procedures [Context.NumProbes] + and [Context.ProbeNames]. + It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. *) module Probe : sig type probe (** Execute the probe over the goal. - A probe always produce a float value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + @return A probe always produce a float value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float (** The number of supported Probes. *) @@ -2478,9 +2478,9 @@ end (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. + The complete list of tactics may be obtained using [Context.get_num_tactics] + and [Context.get_tactic_names]. + It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. *) module Tactic : sig @@ -2504,8 +2504,8 @@ sig val get_subgoal : apply_result -> int -> Goal.goal (** Convert a model for a subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g *) + goal [g], that the ApplyResult was obtained from. + #return A model for [g] *) val convert_model : apply_result -> int -> Model.model -> Model.model (** A string representation of the ApplyResult. *) @@ -2549,7 +2549,7 @@ sig (** Create a tactic that applies one tactic to a given goal if the probe evaluates to true. - If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) + If the probe evaluates to false, then the new tactic behaves like the [skip] tactic. *) val when_ : context -> Probe.probe -> tactic -> tactic (** Create a tactic that applies a tactic to a given goal if the probe @@ -2577,7 +2577,7 @@ sig val using_params : context -> tactic -> Params.params -> tactic (** Create a tactic that applies a tactic using the given set of parameters. - Alias for UsingParams*) + Alias for [UsingParams]*) val with_ : context -> tactic -> Params.params -> tactic (** Create a tactic that applies the given tactics in parallel. *) @@ -2718,26 +2718,26 @@ sig {!Proof} *) val check : solver -> Expr.expr list -> status - (** The model of the last Check. + (** The model of the last [Check]. - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. *) + The result is [None] if [Check] was not invoked before, + if its results was not [SATISFIABLE], or if model production is not enabled. *) val get_model : solver -> Model.model option - (** The proof of the last Check. + (** The proof of the last [Check]. - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. *) + The result is [null] if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if proof production is disabled. *) val get_proof : solver -> Expr.expr option - (** The unsat core of the last Check. + (** The unsat core of the last [Check]. - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. *) + The unsat core is a subset of [Assertions] + The result is empty if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if core production is disabled. *) val get_unsat_core : solver -> AST.ast list - (** A brief justification of why the last call to Check returned UNKNOWN. *) + (** A brief justification of why the last call to [Check] returned [UNKNOWN]. *) val get_reason_unknown : solver -> string (** Solver statistics. *) @@ -2759,7 +2759,7 @@ sig (** Creates a solver that is implemented using the given tactic. - The solver supports the commands Push and Pop, but it + The solver supports the commands [Push] and [Pop], but it will always solve each check from scratch. *) val mk_solver_t : context -> Tactic.tactic -> solver @@ -2811,7 +2811,7 @@ sig (** Backtrack one backtracking point. - Note that an exception is thrown if Pop is called without a corresponding Push + Note that an exception is thrown if Pop is called without a corresponding [Push] {!push} *) val pop : fixedpoint -> unit @@ -2875,28 +2875,28 @@ sig {!parse_smtlib_string} *) val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_formulas : context -> int - (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_formulas : context -> Expr.expr list - (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_assumptions : context -> int - (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_assumptions : context -> Expr.expr list - (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_decls : context -> int - (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_decls : context -> FuncDecl.func_decl list - (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB sorts parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_sorts : context -> int - (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The sort declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_sorts : context -> Sort.sort list (** Parse the given string using the SMT-LIB2 parser. From 2a67301c50033dd3a9e2a02bcf1ad6bbf153f7a0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 17 Apr 2014 15:06:32 +0100 Subject: [PATCH 338/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index dda8807c9..e2fa01478 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1482,7 +1482,7 @@ struct let get_big_int ( x : expr ) = if (is_int_numeral x) then - let s = to_string(x) in + let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in (Big_int.big_int_of_string s) else raise (Z3native.Exception "Conversion failed.") @@ -1526,7 +1526,7 @@ struct let get_ratio ( x : expr ) = if (is_rat_numeral x) then - let s = to_string(x) in + let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in (Ratio.ratio_of_string s) else raise (Z3native.Exception "Conversion failed.") From 4c54b6816a1e2669398172391d4c5c93612fcb3d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 22 Apr 2014 11:49:47 +0100 Subject: [PATCH 339/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index e2fa01478..dafd255f8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -119,7 +119,7 @@ let mk_list ( f : int -> 'a ) ( n : int ) = if (i >= n) then tail else - (mk_list' f (i+1) n ((f i) :: tail)) + (f i) :: (mk_list' f (i+1) n tail) in mk_list' f 0 n [] From 1c34842ca6839a3833638e58d18b5e9c1f8f8ff6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 15:15:59 +0100 Subject: [PATCH 340/646] ML API: added Expr.equal and Expr.compare Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 6 ++++++ src/api/ml/z3.mli | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index dafd255f8..3f40b288c 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -717,6 +717,8 @@ sig val mk_app : context -> FuncDecl.func_decl -> expr list -> expr val mk_numeral_string : context -> string -> Sort.sort -> expr val mk_numeral_int : context -> int -> Sort.sort -> expr + val equal : expr -> expr -> bool + val compare : expr -> expr -> int end = struct type expr = Expr of AST.ast @@ -830,6 +832,10 @@ end = struct let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + + let equal ( a : expr ) ( b : expr ) = AST.equal (ast_of_expr a) (ast_of_expr b) + + let compare a b = AST.compare (ast_of_expr a) (ast_of_expr b) end open FuncDecl diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index ff45fb0f2..84f230d95 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -554,9 +554,17 @@ sig val mk_numeral_string : context -> string -> Sort.sort -> expr (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. - @return A Term with the given value and sort *) + It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. + @return A Term with the given value and sort *) val mk_numeral_int : context -> int -> Sort.sort -> expr + + (** Comparison operator. + @return True if the two expr's are equal; false otherwise. *) + val equal : expr -> expr -> bool + + (** Object Comparison. + @return Negative if the first expr should be sorted before the second, positive if after, else zero. *) + val compare : expr -> expr -> int end (** Boolean expressions; Propositional logic and equality *) From ce94a8b2e0f5f56b2b8c469aeeaef3d4854f0aa5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 15:25:08 +0100 Subject: [PATCH 341/646] ML API: added constructors for ast_map and ast_vector Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 31 ++++++++++++++++++++++--------- src/api/ml/z3.mli | 20 ++++++++++++-------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 3f40b288c..b48681b87 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -214,7 +214,7 @@ struct struct type ast_vector = z3_native_object - let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; @@ -223,6 +223,8 @@ struct (z3obj_create res) ; res + let mk_ast_vector ( ctx : context ) = (create ctx (Z3native.mk_ast_vector (context_gno ctx))) + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) @@ -239,7 +241,7 @@ struct Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) let translate ( x : ast_vector ) ( to_ctx : context ) = - ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) let to_string ( x : ast_vector ) = Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) @@ -248,7 +250,18 @@ struct module ASTMap = struct type ast_map = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + let mk_ast_map ( ctx : context ) = (create ctx (Z3native.mk_ast_map (context_gno ctx))) + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; @@ -277,7 +290,7 @@ struct Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) let get_keys ( x : ast_map ) = - let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let av = ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in let f i = (ASTVector.get av i) in mk_list f (ASTVector.get_size av) @@ -2061,7 +2074,7 @@ struct mk_list f n let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in mk_list f n @@ -2386,11 +2399,11 @@ struct Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno c) (Expr.gno p) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) let get_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in mk_list f n @@ -2423,7 +2436,7 @@ struct Some (expr_of_ptr (z3obj_gc x) q) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in mk_list f n @@ -2545,13 +2558,13 @@ struct Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 84f230d95..4347c7431 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -107,10 +107,9 @@ sig (** A string representation of the symbol. *) val to_string : symbol -> string - (** Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. *) + (** Creates a new symbol using an integer. + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. *) val mk_int : context -> int -> symbol (** Creates a new symbol using a string. *) @@ -132,12 +131,14 @@ sig module ASTVector : sig type ast_vector + + (** Create an empty AST vector *) + val mk_ast_vector : context -> ast_vector (** The size of the vector *) val get_size : ast_vector -> int - (** - Retrieves the i-th object in the vector. + (** Retrieves the i-th object in the vector. @return An AST *) val get : ast_vector -> int -> ast @@ -162,7 +163,10 @@ sig (** Map from AST to AST *) module ASTMap : sig - type ast_map + type ast_map + + (** Create an empty mapping from AST to AST *) + val mk_ast_map : context -> ast_map (** Checks whether the map contains a key. @return True if the key in the map, false otherwise. *) @@ -2297,7 +2301,7 @@ sig (** Creates a new Goal. - Note that the Context must have been created with proof generation support if + Note that the Context must have been created with proof generation support if the fourth argument is set to true here. *) val mk_goal : context -> bool -> bool -> bool -> goal From bcbfaad3cc9d0ead2118432a7f04ae7d1c2e0e07 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 18:50:11 +0100 Subject: [PATCH 342/646] ML API bugfix. Thanks to Martin Neuhaeusser for reporting this one! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b48681b87..bdcf1a26b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2045,7 +2045,7 @@ struct let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) let get_func_decls ( x : model ) = - let n = (get_num_consts x) in + let n = (get_num_funcs x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in mk_list f n From 8bd4ea293e9f427fc118fcc90cf2d10ec4a7f8b5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 18:59:03 +0100 Subject: [PATCH 343/646] ML API fix for datatype construction (Issue #121). Thanks to Elarnon for reporting this one! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 12 ++++++++---- src/api/ml/z3.mli | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index bdcf1a26b..f34ce0ca7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -374,6 +374,10 @@ struct let sort_lton ( a : sort list ) = let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) + + let sort_option_lton ( a : sort option list ) = + let f ( e : sort option ) = match e with None -> null | Some(Sort(a)) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) let equal : sort -> sort -> bool = fun a b -> (a == b) || @@ -1257,7 +1261,7 @@ struct let _sizes = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = let n = (List.length field_names) in if n != (List.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -1269,7 +1273,7 @@ struct (Symbol.gno recognizer) n (Symbol.symbol_lton field_names) - (sort_lton sorts) + (sort_option_lton sorts) (Array.of_list sort_refs)) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; @@ -1316,11 +1320,11 @@ struct res end - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = Constructor.create ctx name recognizer field_names sorts sort_refs - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 4347c7431..1342bb4bc 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1053,12 +1053,12 @@ sig (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a new datatype sort. *) val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> Sort.sort From 662039938c7999a5cf4925943c7d8b90d825cb27 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 19:16:16 +0100 Subject: [PATCH 344/646] ML API bugfix (Issue #119). Thanks to user Elarnon for reporting this! Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 8ce652ed5..fba194bac 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1464,7 +1464,7 @@ def mk_ml(): for p in params: if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) - ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s_val, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 From d84e728f7ae460a9860d2c16b19ab26eac62a344 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 19:29:06 +0100 Subject: [PATCH 345/646] ML API bugfix for datatype module (Issue #120). Thanks to user Elarnon for reporting this! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f34ce0ca7..013101398 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -277,7 +277,7 @@ struct let find ( x : ast_map ) ( key : ast ) = ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + let insert ( x : ast_map ) ( key : ast ) ( value : ast ) = Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) let erase ( x : ast_map ) ( key : ast ) = @@ -1259,7 +1259,13 @@ struct struct type constructor = z3_native_object - let _sizes = Hashtbl.create 0 + module FieldNumTable = Hashtbl.Make(struct + type t = AST.ast + let equal x y = AST.compare x y = 0 + let hash = AST.hash + end) + + let _field_nums = FieldNumTable.create 0 let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = let n = (List.length field_names) in @@ -1283,10 +1289,10 @@ struct (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; - Hashtbl.add _sizes no n ; + FieldNumTable.add _field_nums no n ; no - let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x + let get_num_fields ( x : constructor ) = FieldNumTable.find _field_nums x let get_constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in From 2a67befe9d7195708614c2603e11cf8e6a2099bc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 14 Aug 2014 18:58:52 +0100 Subject: [PATCH 346/646] ML API: added .cmxs to the distribution. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 17 +++++++++++------ src/api/ml/META | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8577479b7..b3c21b552 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,23 +1384,28 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('\t%s ' % (OCAMLOPT)) + if DEBUG_MODE: + out.write('-g ') + out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) - out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) for m in modules: out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) diff --git a/src/api/ml/META b/src/api/ml/META index d275d98be..6238403a3 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -4,4 +4,6 @@ description = "Z3 Theorem Prover (OCaml API)" requires = "num" archive(byte) = "z3.cma" archive(native) = "z3.cmxa" +archive(byte, plugin) = "z3.cma" +archive(native, plugin) = "z3.cmxs" linkopts = "-cclib -lz3" \ No newline at end of file From 45ec0c1b991f98645f2df834e6b22f32d5e8d3a4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:02:00 +0100 Subject: [PATCH 347/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++--- src/api/ml/META | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b3c21b552..16286d62e 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,12 +1384,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('-shared -o %s %s -linkall\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1397,7 +1397,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands diff --git a/src/api/ml/META b/src/api/ml/META index 6238403a3..f1d34ba3d 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -6,4 +6,4 @@ archive(byte) = "z3.cma" archive(native) = "z3.cmxa" archive(byte, plugin) = "z3.cma" archive(native, plugin) = "z3.cmxs" -linkopts = "-cclib -lz3" \ No newline at end of file +linkopts = "-cclib -lz3 -lz3ml" \ No newline at end of file From bd9c863e6bf820e918436547fc7caebe3d423f41 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:09:01 +0100 Subject: [PATCH 348/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 16286d62e..da3dd8692 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,7 +1384,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: @@ -1397,7 +1397,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 4109d19cecd016a134baab74261336081362e958 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:18:40 +0100 Subject: [PATCH 349/646] ML API: bugfixes --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index da3dd8692..362c74834 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,12 +1384,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-shared -o %s %s -linkall\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('-shared -cclib "-L%s -lz3ml" -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir,'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1397,7 +1397,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 30a30e8dd033395bee17de5e88ac435f292ac338 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:22:40 +0100 Subject: [PATCH 350/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/META | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/META b/src/api/ml/META index f1d34ba3d..6238403a3 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -6,4 +6,4 @@ archive(byte) = "z3.cma" archive(native) = "z3.cmxa" archive(byte, plugin) = "z3.cma" archive(native, plugin) = "z3.cmxs" -linkopts = "-cclib -lz3 -lz3ml" \ No newline at end of file +linkopts = "-cclib -lz3" \ No newline at end of file From fc32a2e4735daa6a290b30767ca9fecf3ef940ef Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:32:33 +0100 Subject: [PATCH 351/646] ML API: Undoing earlier changes. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 362c74834..b3c21b552 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,12 +1384,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-shared -cclib "-L%s -lz3ml" -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir,'z3.cmxa'))) + out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1397,7 +1397,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 16ba29e991729c05c71e424178f71a46345a70e4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 19:39:13 +0000 Subject: [PATCH 352/646] ML API: added interpolation, bugfixes. Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 10 +- src/api/ml/z3.ml | 121 ++-- src/api/ml/z3.mli | 1386 +++++++++++++++++++++-------------------- 3 files changed, 806 insertions(+), 711 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index fba194bac..4669b78fc 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -334,6 +334,8 @@ def param2ml(p): return "ptr" elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: return "%s array" % type2ml(param_type(p)) + elif k == OUT_MANAGED_ARRAY: + return "%s array" % type2ml(param_type(p)); else: return type2ml(param_type(p)) @@ -1067,7 +1069,7 @@ def ml_method_name(name): return name[3:] # Remove Z3_ def is_out_param(p): - if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_MANAGED_ARRAY: return True else: return False @@ -1411,6 +1413,8 @@ def mk_ml(): type2str(param_type(param)), type2str(param_type(param)), param_array_capacity_pos(param))) + elif k == OUT_MANAGED_ARRAY: + ml_wrapper.write(' %s * _a%s = 0;\n' % (type2str(param_type(param)), i)) elif k == IN_ARRAY or k == INOUT_ARRAY: t = param_type(param) ts = type2str(t) @@ -1449,7 +1453,7 @@ def mk_ml(): else: ml_wrapper.write(', ') k = param_kind(param) - if k == OUT or k == INOUT: + if k == OUT or k == INOUT or k == OUT_MANAGED_ARRAY: ml_wrapper.write('&_a%s' % i) else: ml_wrapper.write('_a%i' % i) @@ -1465,6 +1469,8 @@ def mk_ml(): if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s_val, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) + elif param_kind(p) == OUT_MANAGED_ARRAY: + ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 013101398..2b54a1113 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -165,7 +165,7 @@ struct let symbol_lton ( a : symbol list ) = let f ( e : symbol ) = (gno e) in Array.of_list (List.map f a) - + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL @@ -213,7 +213,7 @@ struct module ASTVector = struct type ast_vector = z3_native_object - + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; @@ -224,7 +224,7 @@ struct res let mk_ast_vector ( ctx : context ) = (create ctx (Z3native.mk_ast_vector (context_gno ctx))) - + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) @@ -259,7 +259,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let mk_ast_map ( ctx : context ) = (create ctx (Z3native.mk_ast_map (context_gno ctx))) let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = @@ -330,7 +330,7 @@ struct if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - + let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then x @@ -366,7 +366,7 @@ struct | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") let ast_of_sort s = match s with Sort(x) -> x - + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -378,7 +378,7 @@ struct let sort_option_lton ( a : sort option list ) = let f ( e : sort option ) = match e with None -> null | Some(Sort(a)) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) - + let equal : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then @@ -629,7 +629,6 @@ sig val to_string : params -> string val update_param_value : context -> string -> string -> unit - val get_param_value : context -> string -> string option val set_print_mode : context -> Z3enums.ast_print_mode -> unit end = struct type params = z3_native_object @@ -688,13 +687,6 @@ end = struct let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) end @@ -826,11 +818,11 @@ end = struct let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) - + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -851,7 +843,7 @@ end = struct expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) let equal ( a : expr ) ( b : expr ) = AST.equal (ast_of_expr a) (ast_of_expr b) - + let compare a b = AST.compare (ast_of_expr a) (ast_of_expr b) end @@ -941,7 +933,7 @@ struct raise (Z3native.Exception "Invalid coercion") else Quantifier(e) - + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) @@ -949,13 +941,13 @@ struct module Pattern = struct type pattern = Pattern of ast - + let ast_of_pattern e = match e with Pattern(x) -> x let pattern_of_ast a = - (* CMW: Unchecked ok? *) + (* CMW: Unchecked ok? *) Pattern(a) - + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) @@ -1258,11 +1250,11 @@ struct module Constructor = struct type constructor = z3_native_object - + module FieldNumTable = Hashtbl.Make(struct - type t = AST.ast - let equal x y = AST.compare x y = 0 - let hash = AST.hash + type t = AST.ast + let equal x y = AST.compare x y = 0 + let hash = AST.hash end) let _field_nums = FieldNumTable.create 0 @@ -1291,7 +1283,7 @@ struct Gc.finalise f no ; FieldNumTable.add _field_nums no n ; no - + let get_num_fields ( x : constructor ) = FieldNumTable.find _field_nums x let get_constructor_decl ( x : constructor ) = @@ -1613,16 +1605,16 @@ struct let mk_sub ( ctx : context ) ( t : expr list ) = let f x = (Expr.gno x) in - (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) let mk_unary_minus ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) + (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) let mk_div ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_power ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) @@ -1893,7 +1885,7 @@ struct let get_formulas ( x : goal ) = let n = get_size x in let f i = ((expr_of_ptr (z3obj_gc x) - (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in mk_list f n let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) @@ -2065,7 +2057,7 @@ struct let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in (mk_list f n_funcs) @ (mk_list g n_consts) - + let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then @@ -2316,7 +2308,7 @@ struct mutable m_is_float : bool ; mutable m_int : int ; mutable m_float : float } - + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -2644,7 +2636,7 @@ struct mk_list f n let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - + let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in @@ -2683,6 +2675,65 @@ struct (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end +module Interpolation = +struct + let mk_interpolant ( ctx : context ) ( a : expr ) = + (expr_of_ptr ctx (Z3native.mk_interpolant (context_gno ctx) (Expr.gno a))) + + let mk_interpolation_context ( settings : ( string * string ) list ) = + let cfg = Z3native.mk_config () in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_interpolation_context cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + + let get_interpolant ( ctx : context ) ( pf : expr ) ( pat: expr ) ( p : Params.params ) = + (ASTVector.create ctx (Z3native.get_interpolant (context_gno ctx) (Expr.gno pf) (Expr.gno pat) (z3obj_gno p))) + + let compute_interpolant ( ctx : context ) ( pat : expr ) ( p : Params.params ) = + let (r, interp, model) = (Z3native.compute_interpolant (context_gno ctx) (Expr.gno pat) (z3obj_gno p)) in + match (lbool_of_int r) with + | L_TRUE -> ((ASTVector.create ctx interp), (Model.create ctx model)) + | _ -> raise (Z3native.Exception "Error computing interpolant.") + + let get_interpolation_profile ( ctx : context ) = + (Z3native.interpolation_profile (context_gno ctx)) + + let read_interpolation_problem ( ctx : context ) ( filename : string ) = + let (r, num, cnsts, parents, error, num_theory, theory) = (Z3native.read_interpolation_problem (context_gno ctx) filename) in + match r with + | 0 -> raise (Z3native.Exception "Interpolation problem could not be read.") + | _ -> + let f1 i = (expr_of_ptr ctx (Array.get cnsts i)) in + let f2 i = (Array.get parents i) in + let f3 i = (expr_of_ptr ctx (Array.get theory i)) in + ((mk_list f1 num), + (mk_list f2 num), + (mk_list f3 num_theory)) + + let check_interpolant ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( interps : Expr.expr list ) ( num_theory : int ) ( theory : Expr.expr list ) = + let (r, str) = (Z3native.check_interpolant (context_gno ctx) + num + (let f x = Expr.gno x in (Array.of_list (List.map f cnsts))) + (Array.of_list parents) + (let f x = Expr.gno x in (Array.of_list (List.map f interps))) + num_theory + (let f x = Expr.gno x in (Array.of_list (List.map f theory)))) in + match (lbool_of_int r) with + | L_UNDEF -> raise (Z3native.Exception "Interpolant could not be verified.") + | L_FALSE -> raise (Z3native.Exception "Interpolant could not be verified.") + | _ -> () + + let write_interpolation_problem ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( filename : string ) ( num_theory : int ) ( theory : Expr.expr list ) = + (Z3native.write_interpolation_problem (context_gno ctx) num (expr_lton cnsts) (Array.of_list parents) filename num_theory (expr_lton theory)) ; + () +end let set_global_param ( id : string ) ( value : string ) = (Z3native.global_param_set id value) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 1342bb4bc..b2f0939d0 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -149,11 +149,11 @@ sig val resize : ast_vector -> int -> unit (** Add an ast to the back of the vector. The size - is increased by 1. *) + is increased by 1. *) val push : ast_vector -> ast -> unit (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) + @return A new ASTVector *) val translate : ast_vector -> context -> ast_vector (** Retrieves a string representation of the vector. *) @@ -196,7 +196,7 @@ sig end (** The AST's hash code. - @return A hash code *) + @return A hash code *) val hash : ast -> int (** A unique identifier for the AST (unique among all ASTs). *) @@ -227,34 +227,34 @@ sig val to_sexpr : ast -> string (** Comparison operator. - @return True if the two ast's are from the same context - and represent the same sort; false otherwise. *) + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) val equal : ast -> ast -> bool (** Object Comparison. - @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) val compare : ast -> ast -> int (** Translates (copies) the AST to another context. - @return A copy of the AST which is associated with the other context. *) + @return A copy of the AST which is associated with the other context. *) val translate : ast -> context -> ast (** Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - [Z3native.inc_ref]). - {!wrap_ast} *) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + [Z3native.inc_ref]). + {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr (** Wraps an AST. - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., [Z3native.inc_ref]). *) val wrap_ast : context -> Z3native.z3_ast -> ast end @@ -267,8 +267,8 @@ sig val ast_of_sort : sort -> AST.ast (** Comparison operator. - @return True if the two sorts are from the same context - and represent the same sort; false otherwise. *) + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) val equal : sort -> sort -> bool (** Returns a unique identifier for the sort. *) @@ -441,33 +441,26 @@ sig val to_string : params -> string (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - [z3.exe -p] - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - {!get_param_value} *) + + The list of all configuration parameters can be obtained using the Z3 executable: + [z3.exe -p] + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) val update_param_value : context -> string -> string -> unit - - (** Get a configuration parameter. - - Returns None if the parameter value does not exist. - {!update_param_value} *) - val get_param_value : context -> string -> string option - + (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) val set_print_mode : context -> Z3enums.ast_print_mode -> unit end @@ -480,7 +473,7 @@ sig val expr_of_ast : AST.ast -> Expr.expr (** Returns a simplified version of the expression. - {!get_simplify_help} *) + {!get_simplify_help} *) val simplify : Expr.expr -> Params.params option -> expr (** A string describing all available parameters to [Expr.Simplify]. *) @@ -503,23 +496,23 @@ sig val update : Expr.expr -> Expr.expr list -> expr (** Substitute every occurrence of [from[i]] in the expression with [to[i]], for [i] smaller than [num_exprs]. - - The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. - For every [i] smaller than [num_exprs], we must have that - sort of [from[i]] must be equal to sort of [to[i]]. *) + + The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. + For every [i] smaller than [num_exprs], we must have that + sort of [from[i]] must be equal to sort of [to[i]]. *) val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr (** Substitute every occurrence of [from] in the expression with [to]. - {!substitute} *) + {!substitute} *) val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr (** Substitute the free variables in the expression with the expressions in the expr array - For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) + For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) val substitute_vars : Expr.expr -> Expr.expr list -> expr (** Translates (copies) the term to another context. - @return A copy of the term which is associated with the other context *) + @return A copy of the term which is associated with the other context *) val translate : Expr.expr -> context -> expr (** Returns a string representation of the expression. *) @@ -529,7 +522,7 @@ sig val is_numeral : Expr.expr -> bool (** Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. *) + @return True if the term is well-sorted, false otherwise. *) val is_well_sorted : Expr.expr -> bool (** The Sort of the term. *) @@ -537,26 +530,26 @@ sig (** Indicates whether the term represents a constant. *) val is_const : Expr.expr -> bool - + (** Creates a new constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - + (** Creates a new constant. *) val mk_const_s : context -> string -> Sort.sort -> expr - + (** Creates a constant from the func_decl. *) val mk_const_f : context -> FuncDecl.func_decl -> expr - + (** Creates a fresh constant with a name prefixed with a string. *) val mk_fresh_const : context -> string -> Sort.sort -> expr - + (** Create a new function application. *) val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - + (** Create a numeral of a given sort. - @return A Term with the given value and sort *) + @return A Term with the given value and sort *) val mk_numeral_string : context -> string -> Sort.sort -> expr - + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. @return A Term with the given value and sort *) @@ -692,21 +685,21 @@ sig (** The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. *) + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) val get_index : Expr.expr -> int (** Indicates whether the quantifier is universal. *) @@ -723,19 +716,19 @@ sig (** The patterns. *) val get_patterns : quantifier -> Pattern.pattern list - - (** The number of no-patterns. *) + + (** The number of no-patterns. *) val get_num_no_patterns : quantifier -> int (** The no-patterns. *) val get_no_patterns : quantifier -> Pattern.pattern list - (** The number of bound variables. *) - val get_num_bound : quantifier -> int - - (** The symbols for the bound variables. *) + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) val get_bound_variable_names : quantifier -> Symbol.symbol list - + (** The sorts of the bound variables. *) val get_bound_variable_sorts : quantifier -> Sort.sort list @@ -767,7 +760,7 @@ sig val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** A string representation of the quantifier. *) - val to_string : quantifier -> string + val to_string : quantifier -> string end (** Functions to manipulate Array expressions *) @@ -777,28 +770,28 @@ sig val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort (** Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. *) + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an array select. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. *) + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) val is_constant_array : Expr.expr -> bool (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. *) + For example default(const(v)) = v. The function is unary. *) val is_default_array : Expr.expr -> bool (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) val is_array_map : Expr.expr -> bool (** Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. *) + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) val is_as_array : Expr.expr -> bool (** Indicates whether the term is of an array sort. *) @@ -806,66 +799,66 @@ sig (** The domain of the array sort. *) val get_domain : Sort.sort -> Sort.sort - + (** The range of the array sort. *) val get_range : Sort.sort -> Sort.sort - + (** Create an array constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> Expr.expr - + (** Create an array constant. *) val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> Expr.expr - + (** Array read. - - The argument [a] is the array and [i] is the index - of the array that gets read. - - The node [a] must have an array sort [[domain -> range]], - and [i] must have the sort [domain]. - The sort of the result is [range]. - {!Z3Array.mk_sort} - {!mk_store} *) + + The argument [a] is the array and [i] is the index + of the array that gets read. + + The node [a] must have an array sort [[domain -> range]], + and [i] must have the sort [domain]. + The sort of the result is [range]. + {!Z3Array.mk_sort} + {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr (** Array update. - - The node [a] must have an array sort [[domain -> range]], - [i] must have sort [domain], - [v] must have sort range. The sort of the result is [[domain -> range]]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to [a] - (with respect to [select]) - on all indices except for [i], where it maps to [v] - (and the [select] of [a] with - respect to [i] may be a different value). - {!Z3Array.mk_sort} - {!mk_select} *) + + The node [a] must have an array sort [[domain -> range]], + [i] must have sort [domain], + [v] must have sort range. The sort of the result is [[domain -> range]]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to [a] + (with respect to [select]) + on all indices except for [i], where it maps to [v] + (and the [select] of [a] with + respect to [i] may be a different value). + {!Z3Array.mk_sort} + {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create a constant array. - - The resulting term is an array, such that a [select]on an arbitrary index - produces the value [v]. - {!Z3Array.mk_sort} - {!mk_select} *) + + The resulting term is an array, such that a [select]on an arbitrary index + produces the value [v]. + {!Z3Array.mk_sort} + {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr (** Maps f on the argument arrays. - - Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. - The function declaration [f] must have type [ range_1 .. range_n -> range]. - [v] must have sort range. The sort of the result is [[domain_i -> range]]. - {!Z3Array.mk_sort} - {!mk_select} - {!mk_store} *) + + Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. + The function declaration [f] must have type [ range_1 .. range_n -> range]. + [v] must have sort range. The sort of the result is [[domain_i -> range]]. + {!Z3Array.mk_sort} + {!mk_select} + {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr (** Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. *) + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) val mk_term_array : context -> Expr.expr -> Expr.expr end @@ -948,10 +941,10 @@ sig val is_relation : Expr.expr -> bool (** Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements - correspond to the [n] columns of the relation. *) + + Insert a record into a relation. + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + correspond to the [n] columns of the relation. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an empty relation *) @@ -964,62 +957,62 @@ sig val is_join : Expr.expr -> bool (** Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. *) + The function takes two arguments. *) val is_union : Expr.expr -> bool (** Indicates whether the term is the widening of two relations - The function takes two arguments. *) + The function takes two arguments. *) val is_widen : Expr.expr -> bool (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. *) + The function takes one argument. *) val is_project : Expr.expr -> bool (** Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. *) + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) val is_filter : Expr.expr -> bool (** Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. *) + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) val is_negation_filter : Expr.expr -> bool (** Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. *) + + The function takes one argument. + The parameters contain the renaming as a cycle. *) val is_rename : Expr.expr -> bool (** Indicates whether the term is the complement of a relation *) val is_complement : Expr.expr -> bool (** Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes [n+1] arguments, where the first argument is a relation, - and the remaining [n] arguments correspond to a record. *) + + Check if a record is an element of the relation. + The function takes [n+1] arguments, where the first argument is a relation, + and the remaining [n] arguments correspond to a record. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind {!is_union} - to perform destructive updates to the first argument. *) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) val is_clone : Expr.expr -> bool (** The arity of the relation sort. *) @@ -1039,25 +1032,25 @@ sig (** The number of fields of the constructor. *) val get_num_fields : constructor -> int - + (** The function declaration of the constructor. *) val get_constructor_decl : constructor -> FuncDecl.func_decl (** The function declaration of the tester. *) val get_tester_decl : constructor -> FuncDecl.func_decl - + (** The function declarations of the accessors *) val get_accessor_decls : constructor -> FuncDecl.func_decl list end (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a new datatype sort. *) @@ -1078,7 +1071,7 @@ sig (** The constructors. *) val get_constructors : Sort.sort -> FuncDecl.func_decl list - + (** The recognizers. *) val get_recognizers : Sort.sort -> FuncDecl.func_decl list @@ -1174,38 +1167,38 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create an expression representing [t1 mod t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing [t1 rem t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer numeral. *) val mk_numeral_s : context -> string -> Expr.expr (** Create an integer numeral. - @return A Term with the given value and sort Integer *) + @return A Term with the given value and sort Integer *) val mk_numeral_i : context -> int -> Expr.expr (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term [k] and - and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. - The argument must be of integer sort. *) + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term [k] and + and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. + The argument must be of integer sort. *) val mk_int2real : context -> Expr.expr -> Expr.expr (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) val mk_int2bv : context -> int -> Expr.expr -> Expr.expr end @@ -1238,16 +1231,16 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) + @return A Term with rational value and sort Real + {!mk_numeral_s} *) val mk_numeral_nd : context -> int -> int -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_s : context -> string -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_i : context -> int -> Expr.expr (** Creates an expression that checks whether a real number is an integer. *) @@ -1255,8 +1248,8 @@ sig (** Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) val mk_real2int : context -> Expr.expr -> Expr.expr (** Algebraic Numbers *) @@ -1522,34 +1515,34 @@ sig val is_bv_rotateright : Expr.expr -> bool (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) val is_bv_rotateleftextended : Expr.expr -> bool (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) val is_bv_rotaterightextended : Expr.expr -> bool - + (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) (** Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_int_to_bv : Expr.expr -> bool (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_bv_to_int : Expr.expr -> bool (** Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) val is_bv_carry : Expr.expr -> bool - + (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) val is_bv_xor3 : Expr.expr -> bool (** The size of a bit-vector sort. *) @@ -1557,7 +1550,7 @@ sig (** Retrieve the int value. *) val get_int : Expr.expr -> int - + (** Returns a string representation of the numeral. *) val to_string : Expr.expr -> string @@ -1568,146 +1561,145 @@ sig val mk_const_s : context -> string -> int -> Expr.expr (** Bitwise negation. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_not : context -> Expr.expr -> Expr.expr (** Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_redand : context -> Expr.expr -> Expr.expr (** Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_redor : context -> Expr.expr -> Expr.expr (** Bitwise conjunction. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_and : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise disjunction. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_or : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NAND. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_nand : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_nor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XNOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_xnor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Standard two's complement unary minus. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_neg : context -> Expr.expr -> Expr.expr (** Two's complement addition. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement subtraction. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement multiplication. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned division. - - - It is defined as the floor of [t1/t2] if \c t2 is - different from zero. If [t2] is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. *) + + It is defined as the floor of [t1/t2] if \c t2 is + different from zero. If [t2] is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed division. - - It is defined in the following way: + + It is defined in the following way: - - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. + - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. - - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. + - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned remainder. - - It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + + It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed remainder. - - It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed remainder (sign follows divisor). - - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ult : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed less-than - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_slt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ule : context -> Expr.expr -> Expr.expr -> Expr.expr - + (** Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sle : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_uge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater-than. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ugt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sgt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size [n1+n2], where [n1] ([n2]) - is the size of [t1] ([t2]). *) + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size [n1+n2], where [n1] ([n2]) + is the size of [t1] ([t2]). *) val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector extraction. @@ -1719,17 +1711,17 @@ sig (** Bit-vector sign extension. - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size [m+i], where \c m is the size of the given bit-vector. *) + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size [m+i], where \c m is the size of the given bit-vector. *) val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector zero extension. - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size [m+i], where \c m is the size of the - given bit-vector. *) + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size [m+i], where \c m is the size of the + given bit-vector. *) val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr - + (** Bit-vector repetition. *) val mk_repeat : context -> int -> Expr.expr -> Expr.expr @@ -1743,27 +1735,27 @@ sig val mk_shl : context -> Expr.expr -> Expr.expr -> Expr.expr (** Logical shift right - - It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. + + It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_lshr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_ashr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Rotate Left. @@ -1783,7 +1775,7 @@ sig val mk_ext_rotate_right : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer from the bit-vector argument - + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. So the result is non-negative and in the range [[0..2^N-1]], where N are the number of bits in the argument. @@ -1795,45 +1787,45 @@ sig val mk_bv2int : context -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_add_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_add_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sub_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sub_no_underflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sdiv_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_neg_no_overflow : context -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_mul_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + The arguments must be of bit-vector sort. *) + val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + (** Create a bit-vector numeral. *) val mk_numeral : context -> string -> int -> Expr.expr end @@ -1851,389 +1843,389 @@ sig val is_goal : Expr.expr -> bool (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) val is_oeq : Expr.expr -> bool (** Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). *) + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) val is_modus_ponens : Expr.expr -> bool (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. *) + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) val is_reflexivity : Expr.expr -> bool (** Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. *) + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) val is_symmetry : Expr.expr -> bool (** Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) *) + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) val is_transitivity : Expr.expr -> bool (** Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. *) + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) val is_Transitivity_star : Expr.expr -> bool (** Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. *) + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) val is_monotonicity : Expr.expr -> bool (** Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) val is_quant_intro : Expr.expr -> bool (** Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. *) + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) val is_distributivity : Expr.expr -> bool (** Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i *) + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) val is_and_elimination : Expr.expr -> bool (** Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) *) + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) val is_or_elimination : Expr.expr -> bool (** Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) *) + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) val is_rewrite : Expr.expr -> bool (** Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) val is_rewrite_star : Expr.expr -> bool (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) val is_pull_quant : Expr.expr -> bool (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents *) + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) val is_pull_quant_star : Expr.expr -> bool (** Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents *) + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) val is_push_quant : Expr.expr -> bool (** Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. *) + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) val is_elim_unused_vars : Expr.expr -> bool (** Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. *) + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) val is_der : Expr.expr -> bool - + (** Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) *) + + A proof of (or (not (forall (x) (P x))) (P a)) *) val is_quant_inst : Expr.expr -> bool (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. *) + Mark a hypothesis in a natural deduction style proof. *) val is_hypothesis : Expr.expr -> bool (** Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. *) + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) val is_lemma : Expr.expr -> bool (** Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) val is_unit_resolution : Expr.expr -> bool (** Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) *) + + T1: p + [iff-true T1]: (iff p true) *) val is_iff_true : Expr.expr -> bool (** Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) *) + + T1: (not p) + [iff-false T1]: (iff p false) *) val is_iff_false : Expr.expr -> bool (** Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. *) + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) val is_commutativity : Expr.expr -> bool (** Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). *) + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) val is_def_axiom : Expr.expr -> bool (** Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) *) + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) val is_def_intro : Expr.expr -> bool (** Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. *) + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) val is_apply_def : Expr.expr -> bool (** Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) *) + + T1: (iff p q) + [iff~ T1]: (~ p q) *) val is_iff_oeq : Expr.expr -> bool (** Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. *) + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) val is_nnf_pos : Expr.expr -> bool (** Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) *) + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) val is_nnf_neg : Expr.expr -> bool (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_nnf_star : Expr.expr -> bool (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_cnf_star : Expr.expr -> bool (** Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. *) + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) val is_skolemize : Expr.expr -> bool (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q *) + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) val is_modus_ponens_oeq : Expr.expr -> bool (** Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) val is_theory_lemma : Expr.expr -> bool end @@ -2265,12 +2257,12 @@ sig (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) val is_garbage : goal -> bool - (** Adds the constraints to the given goal. *) + (** Adds the constraints to the given goal. *) val add : goal -> Expr.expr list -> unit - + (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool - + (** The depth of the goal. This tracks how many transformations were applied to it. *) val get_depth : goal -> int @@ -2300,7 +2292,7 @@ sig val simplify : goal -> Params.params option -> goal (** Creates a new Goal. - + Note that the Context must have been created with proof generation support if the fourth argument is set to true here. *) val mk_goal : context -> bool -> bool -> bool -> goal @@ -2323,7 +2315,7 @@ sig module FuncInterp : sig type func_interp - + (** Function interpretations entries An Entry object represents an element in the finite map used to a function interpretation. *) @@ -2418,7 +2410,7 @@ sig {!get_sorts} @return A list of expressions, where each is an element of the universe of the sort *) val sort_universe : model -> Sort.sort -> AST.ast list - + (** Conversion of models to strings. @return A string representation of the model. *) val to_string : model -> string @@ -2437,8 +2429,8 @@ sig type probe (** Execute the probe over the goal. - @return A probe always produce a float value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + @return A probe always produce a float value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float (** The number of supported Probes. *) @@ -2546,21 +2538,21 @@ sig val mk_tactic : context -> string -> tactic (** Create a tactic that applies one tactic to a Goal and - then another one to every subgoal produced by the first one. *) + then another one to every subgoal produced by the first one. *) val and_then : context -> tactic -> tactic -> tactic list -> tactic (** Create a tactic that first applies one tactic to a Goal and - if it fails then returns the result of another tactic applied to the Goal. *) + if it fails then returns the result of another tactic applied to the Goal. *) val or_else : context -> tactic -> tactic -> tactic (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). - - If the tactic does not terminate within the timeout, then it fails. *) + + If the tactic does not terminate within the timeout, then it fails. *) val try_for : context -> tactic -> int -> tactic (** Create a tactic that applies one tactic to a given goal if the probe evaluates to true. - + If the probe evaluates to false, then the new tactic behaves like the [skip] tactic. *) val when_ : context -> Probe.probe -> tactic -> tactic @@ -2569,7 +2561,7 @@ sig val cond : context -> Probe.probe -> tactic -> tactic -> tactic (** Create a tactic that keeps applying one tactic until the goal is not - modified anymore or the maximum number of iterations is reached. *) + modified anymore or the maximum number of iterations is reached. *) val repeat : context -> tactic -> int -> tactic (** Create a tactic that just returns the given goal. *) @@ -2582,14 +2574,14 @@ sig val fail_if : context -> Probe.probe -> tactic (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). *) + or trivially unsatisfiable (i.e., contains `false'). *) val fail_if_not_decided : context -> tactic (** Create a tactic that applies a tactic using the given set of parameters. *) val using_params : context -> tactic -> Params.params -> tactic (** Create a tactic that applies a tactic using the given set of parameters. - Alias for [UsingParams]*) + Alias for [UsingParams]*) val with_ : context -> tactic -> Params.params -> tactic (** Create a tactic that applies the given tactics in parallel. *) @@ -2600,7 +2592,7 @@ sig val par_and_then : context -> tactic -> tactic -> tactic (** Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. *) + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) val interrupt : context -> unit end @@ -2618,8 +2610,8 @@ sig type statistics (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - *) + Entry is either a floating point or integer value. + *) module Entry : sig type statistics_entry @@ -2641,7 +2633,7 @@ sig (** The string representation of the the entry's value. *) val to_string_value : statistics_entry -> string - + (** The string representation of the entry (key and value) *) val to_string : statistics_entry -> string end @@ -2672,49 +2664,49 @@ sig val get_param_descrs : solver -> Params.ParamDescrs.param_descrs (** The current number of backtracking points (scopes). - {!pop} - {!push} *) + {!pop} + {!push} *) val get_num_scopes : solver -> int (** Creates a backtracking point. - {!pop} *) + {!pop} *) val push : solver -> unit (** Backtracks a number of backtracking points. - Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} - {!push} *) + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) val pop : solver -> int -> unit (** Resets the Solver. - This removes all assertions from the solver. *) + This removes all assertions from the solver. *) val reset : solver -> unit (** Assert a constraint (or multiple) into the solver. *) val add : solver -> Expr.expr list -> unit (** * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit (** * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit (** The number of assertions in the solver. *) @@ -2724,29 +2716,29 @@ sig val get_assertions : solver -> Expr.expr list (** Checks whether the assertions in the solver are consistent or not. - - {!Model} - {!get_unsat_core} - {!Proof} *) + + {!Model} + {!get_unsat_core} + {!Proof} *) val check : solver -> Expr.expr list -> status (** The model of the last [Check]. - - The result is [None] if [Check] was not invoked before, - if its results was not [SATISFIABLE], or if model production is not enabled. *) + + The result is [None] if [Check] was not invoked before, + if its results was not [SATISFIABLE], or if model production is not enabled. *) val get_model : solver -> Model.model option (** The proof of the last [Check]. - - The result is [null] if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if proof production is disabled. *) + + The result is [null] if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if proof production is disabled. *) val get_proof : solver -> Expr.expr option (** The unsat core of the last [Check]. - - The unsat core is a subset of [Assertions] - The result is empty if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if core production is disabled. *) + + The unsat core is a subset of [Assertions] + The result is empty if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if core production is disabled. *) val get_unsat_core : solver -> AST.ast list (** A brief justification of why the last call to [Check] returned [UNKNOWN]. *) @@ -2756,23 +2748,23 @@ sig val get_statistics : solver -> Statistics.statistics (** Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. *) + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) val mk_solver : context -> Symbol.symbol option -> solver (** Creates a new (incremental) solver. - {!mk_solver} *) + {!mk_solver} *) val mk_solver_s : context -> string -> solver (** Creates a new (incremental) solver. *) val mk_simple_solver : context -> solver (** Creates a solver that is implemented using the given tactic. - - The solver supports the commands [Push] and [Pop], but it - will always solve each check from scratch. *) + + The solver supports the commands [Push] and [Pop], but it + will always solve each check from scratch. *) val mk_solver_t : context -> Tactic.tactic -> solver (** A string representation of the solver. *) @@ -2806,32 +2798,32 @@ sig val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit (** Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. *) + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) val query : fixedpoint -> Expr.expr -> Solver.status (** Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. *) + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status (** Creates a backtracking point. - {!pop} *) + {!pop} *) val push : fixedpoint -> unit (** Backtrack one backtracking point. - Note that an exception is thrown if Pop is called without a corresponding [Push] - {!push} *) + Note that an exception is thrown if Pop is called without a corresponding [Push] + {!push} *) val pop : fixedpoint -> unit (** Update named rule into in the fixedpoint solver. *) val update_rule : fixedpoint -> Expr.expr -> Symbol.symbol -> unit (** Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. *) + or definitions for the recursive predicates that show unsatisfiability. *) val get_answer : fixedpoint -> Expr.expr option (** Retrieve explanation why fixedpoint engine returned status Unknown. *) @@ -2844,7 +2836,7 @@ sig val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option (** Add property about the predicate. - The property is added at level. *) + The property is added at level. *) val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit (** Retrieve internal string representation of fixedpoint object. *) @@ -2871,7 +2863,7 @@ module SMT : sig (** Convert a benchmark into an SMT-LIB formatted string. - @return A string representation of the benchmark. *) + @return A string representation of the benchmark. *) val benchmark_to_smtstring : context -> string -> string -> string -> string -> Expr.expr list -> Expr.expr -> string (** Parse the given string using the SMT-LIB parser. @@ -2884,7 +2876,7 @@ sig val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** Parse the given file using the SMT-LIB parser. - {!parse_smtlib_string} *) + {!parse_smtlib_string} *) val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** The number of SMTLIB formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) @@ -2913,15 +2905,61 @@ sig (** Parse the given string using the SMT-LIB2 parser. - {!parse_smtlib_string} - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr (** Parse the given file using the SMT-LIB2 parser. - {!parse_smtlib2_string} *) + {!parse_smtlib2_string} *) val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr end +(** Interpolation *) +module Interpolation : +sig + + (** Create an AST node marking a formula position for interpolation. + The expression must have Boolean sort. *) + val mk_interpolant : context -> Expr.expr -> Expr.expr + + (** The interpolation context is suitable for generation of interpolants. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val mk_interpolation_context : (string * string) list -> context + + (** Gets an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val get_interpolant : context -> Expr.expr -> Expr.expr -> Params.params -> AST.ASTVector.ast_vector + + (** Computes an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val compute_interpolant : context -> Expr.expr -> Params.params -> (AST.ASTVector.ast_vector * Model.model) + + (** Retrieves an interpolation profile. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val get_interpolation_profile : context -> string + + (** Read an interpolation problem from file. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val read_interpolation_problem : context -> string -> (Expr.expr list * int list * Expr.expr list) + + (** Check the correctness of an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val check_interpolant : context -> int -> Expr.expr list -> int list -> Expr.expr list -> int -> Expr.expr list -> unit + + (** Write an interpolation problem to file suitable for reading with + Z3_read_interpolation_problem. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val write_interpolation_problem : context -> int -> Expr.expr list -> int list -> string -> int -> Expr.expr list -> unit + +end + (** Set a global (or module) parameter, which is shared by all Z3 contexts. When a Z3 module is initialized it will use the value of these parameters @@ -2939,9 +2977,9 @@ end val set_global_param : string -> string -> unit (** Get a global (or module) parameter. - + Returns None if the parameter does not exist. - The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + The caller must invoke #Z3_global_param_del_value to delete the value returned at param_value. This function cannot be invoked simultaneously from different threads without synchronization. The result string stored in param_value is stored in a shared location. *) From 8b266cff529fd4412f3a879a1bf2aafadfee0fc9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 20:21:30 +0000 Subject: [PATCH 353/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b3c21b552..1f8bf9fd6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1361,6 +1361,10 @@ class MLComponent(Component): out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) + for f in filter(lambda f: f=='META', os.listdir(self.src_dir)): + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) + out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: @@ -1403,7 +1407,7 @@ class MLComponent(Component): # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs\n') + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/META\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) for m in modules: From 5f9d1af04ad9eda20b05c1e8d69adb1ad6482753 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 20:31:16 +0000 Subject: [PATCH 354/646] ML API build fix --- scripts/mk_util.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 1f8bf9fd6..6ef3df13c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1361,10 +1361,6 @@ class MLComponent(Component): out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) - for f in filter(lambda f: f=='META', os.listdir(self.src_dir)): - out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) - str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) - out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: From fcee69af4b6ea775d4acc5f2b61f5de853a99380 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 22:00:58 +0000 Subject: [PATCH 355/646] ML API build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 6ef3df13c..62078cf84 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1374,9 +1374,14 @@ class MLComponent(Component): out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3native_stubs$(OBJ_EXT): %s/z3native_stubs.c\n' % (sub_dir)); out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') + out.write('api/ml/libz3mldyn$(SO_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) From e11cc5a1f1a0f4be80ffe5b9c7e8886b2dc63837 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 13:45:49 +0000 Subject: [PATCH 356/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 98 ++++++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 62078cf84..90618edc3 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1366,58 +1366,80 @@ class MLComponent(Component): for m in modules: fn = os.path.join(self.src_dir, ('%s.mli' % m)) if not os.path.exists(fn): - out.write('%s.mli: %s.ml %s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = '' for m in modules: - out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) + out.write('%s.cmi: %s.mli%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m), cmis)) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/z3native_stubs$(OBJ_EXT): %s/z3native_stubs.c\n' % (sub_dir)); - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') - out.write('api/ml/libz3mldyn$(SO_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + + out.write('%s: %s %s\n' % + (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), + os.path.join(sub_dir, 'z3native_stubs.c'), + get_component(Z3_DLL_COMPONENT).dll_name+'$(SO_EXT)')); + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % + (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) - out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLOPT)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('\t%s ' % (OCAMLOPT)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLC)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) - out.write('\n') + # out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + # out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') + + # out.write('api/ml/libz3ml$(SO_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + # out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + + + # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + + # for mlfile in get_ml_files(self.src_dir): + # out.write(' %s' % os.path.join(sub_dir, mlfile)) + # out.write('\n') + # out.write('\t%s ' % (OCAMLOPT)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + + # out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + # out.write('\t%s ' % (OCAMLOPT)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + # for mlfile in get_ml_files(self.src_dir): + # out.write(' %s' % os.path.join(sub_dir, mlfile)) + # out.write('\n') + # out.write('\t%s ' % (OCAMLC)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + + out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) + for m in modules: + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write('%s/z3native_stubs.o\n' % (sub_dir)) + out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) + for m in modules: + out.write(' ' + m) + out.write('z3native_stubs$(OBJ_EXT) ; cd -' ) + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) + #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/META\n') + out.write('\nocamlfind_install: api/ml/z3.cmxa api/ml/META\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) - out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: + out.write(' %s.cma' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxx' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - if IS_WINDOWS: - out.write(' libz3$(LIB_EXT)') - out.write('\n') - out.write('\n') + out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3$(SO_EXT)')))) + out.write('\n\n') def main_component(self): return is_ml_enabled() From 7d577eeb71e26b488ef7437a36b80e46e370034e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 13:51:17 +0000 Subject: [PATCH 357/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 90618edc3..c4f780358 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1422,8 +1422,9 @@ class MLComponent(Component): out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: out.write(' ' + m) - out.write('z3native_stubs$(OBJ_EXT) ; cd -' ) - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) + out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) + # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) From 6e1e28dd58fbf0d60aa3b2c53c0c909c968deea6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:11:19 +0000 Subject: [PATCH 358/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c4f780358..6803e97e4 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1416,8 +1416,8 @@ class MLComponent(Component): out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) for m in modules: out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) out.write('%s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: @@ -1435,11 +1435,15 @@ class MLComponent(Component): for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'dllz3$(SO_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3')))) + if IS_WINDOWS: + out.write('.lib') + else: + out.write('.so') # .so also on OSX! out.write('\n\n') def main_component(self): From b95ada16f32436b140da15853e8e2fc75a2e54e1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:14:14 +0000 Subject: [PATCH 359/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 6803e97e4..3d10468c0 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1418,7 +1418,7 @@ class MLComponent(Component): out.write(' %s.cmi' % (os.path.join(sub_dir, m))) # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) - out.write('%s/z3native_stubs.o\n' % (sub_dir)) + out.write(' %s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: out.write(' ' + m) From c7b73c98a5cac51880ed224e8b42fcf7838a9e31 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:18:03 +0000 Subject: [PATCH 360/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3d10468c0..6fdbdd2a3 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1421,7 +1421,7 @@ class MLComponent(Component): out.write(' %s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: - out.write(' ' + m) + out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) From 5de8f880116c555cbfaef76917fac7710907ffa1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 15:03:10 +0000 Subject: [PATCH 361/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 6fdbdd2a3..c8bcd6e12 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1418,28 +1418,28 @@ class MLComponent(Component): out.write(' %s.cmi' % (os.path.join(sub_dir, m))) # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) - out.write(' %s/z3native_stubs.o\n' % (sub_dir)) - out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) + out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) + out.write('\tcd %s ; ocamlmklib -o z3ml' % (sub_dir)) for m in modules: out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('\nocamlfind_install: api/ml/z3.cmxa api/ml/META\n') + out.write('\nocamlfind_install: %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) + #out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'dllz3')))) + out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: out.write('.lib') else: From 1ce0cd3209131ee01e6ba8462f8aa21b12592905 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 15:38:15 +0000 Subject: [PATCH 362/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c8bcd6e12..c169a21f7 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1404,14 +1404,19 @@ class MLComponent(Component): # if DEBUG_MODE: # out.write('-g ') # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - # for mlfile in get_ml_files(self.src_dir): - # out.write(' %s' % os.path.join(sub_dir, mlfile)) - # out.write('\n') - # out.write('\t%s ' % (OCAMLC)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('%s: %s %s$(SO_EXT) %s' % ( + os.path.join(sub_dir, 'z3.cma'), + os.path.join(sub_dir, 'libz3ml$(LIB_EXT)'), + get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + for mlfile in get_ml_files(self.src_dir): + out.write(' %s' % os.path.join(sub_dir, mlfile)) + out.write('\n') + out.write('\t%s ' % (OCAMLC)) + if DEBUG_MODE: + out.write('-g ') + out.write('-I %s -a -o %s -linkall' % (sub_dir, os.path.join(sub_dir, 'z3.cma'))) + for m in modules: + out.write(' %s.ml' % (os.path.join(sub_dir, m))) out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) for m in modules: From f0d66388d4af4c29531978473885d7296ea49ab9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 19:22:23 +0000 Subject: [PATCH 363/646] ML API: build fixes --- scripts/mk_util.py | 96 ++++++++++++++++++---------------------------- src/api/ml/META | 10 ++--- src/api/ml/z3.ml | 2 +- 3 files changed, 43 insertions(+), 65 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c169a21f7..caad10555 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1362,19 +1362,25 @@ class MLComponent(Component): str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! - prev = '' + mls = '' + mlis = '' + cmis = '' + archives = '' + for m in modules: fn = os.path.join(self.src_dir, ('%s.mli' % m)) if not os.path.exists(fn): - out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),mlis)) out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) - prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' - cmis = '' - for m in modules: out.write('%s.cmi: %s.mli%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m), cmis)) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) + out.write('%s.cma: %s.ml %s.cmi%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),os.path.join(sub_dir,m), archives)) + out.write('\t%s -a -o %s.ml -o %s.cma\n' % (OCAMLC,os.path.join(sub_dir,m), os.path.join(sub_dir,m))) + mlis = mlis + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - + archives = archives + ' ' + os.path.join(sub_dir,m) + '.cma' + mls = mls + ' ' + os.path.join(sub_dir, m) + '.ml' + out.write('%s: %s %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), os.path.join(sub_dir, 'z3native_stubs.c'), @@ -1382,73 +1388,43 @@ class MLComponent(Component): out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) - # out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - # out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') - - # out.write('api/ml/libz3ml$(SO_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - # out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) - - - # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - - # for mlfile in get_ml_files(self.src_dir): - # out.write(' %s' % os.path.join(sub_dir, mlfile)) - # out.write('\n') - # out.write('\t%s ' % (OCAMLOPT)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - - # out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - # out.write('\t%s ' % (OCAMLOPT)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('%s: %s %s$(SO_EXT) %s' % ( - os.path.join(sub_dir, 'z3.cma'), - os.path.join(sub_dir, 'libz3ml$(LIB_EXT)'), - get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLC)) - if DEBUG_MODE: - out.write('-g ') - out.write('-I %s -a -o %s -linkall' % (sub_dir, os.path.join(sub_dir, 'z3.cma'))) - for m in modules: - out.write(' %s.ml' % (os.path.join(sub_dir, m))) - - out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) - for m in modules: - out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write('%s: %s %s %s$(SO_EXT)' % ( + os.path.join(sub_dir, "z3ml.cmxa"), + cmis, + archives, + get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tcd %s ; ocamlmklib -o z3ml' % (sub_dir)) + out.write('\tcd %s ; ocamlmklib -o z3ml -ldopt \'-L../.. -lz3\' ' % (sub_dir)) for m in modules: out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) - # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) - #out.write('\n') - # Generate META file and package installation commands + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('\nocamlfind_install: %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'META'))) + out.write('\nocamlfind_install: %s %s %s\n' % ( + get_component(Z3_DLL_COMPONENT).dll_name)+'$(SO_EXT)', + os.path.join(sub_dir, 'z3ml.cmxa'), + os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - #out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write(' %s.ml' % (os.path.join(sub_dir, m))) + out.write(' %s.mli' % (os.path.join(sub_dir, m))) + out.write(' %s$(OBJ_EXT)' % (os.path.join(sub_dir, m))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.a')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cma')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cmxa')))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: out.write('.lib') else: out.write('.so') # .so also on OSX! + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name) + '$(SO_EXT)')))) out.write('\n\n') def main_component(self): @@ -1572,25 +1548,25 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: api/ml/z3.cma ') + out.write('ml_example.byte: api/ml/z3ml.cma ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3.cma') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3ml.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example$(EXE_EXT): api/ml/z3.cmxa ml_example.byte') + out.write('ml_example$(EXE_EXT): api/ml/z3ml.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3.cmxa') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3ml.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -3035,3 +3011,5 @@ def mk_unix_dist(build_path, dist_path): if __name__ == '__main__': import doctest doctest.testmod() + + diff --git a/src/api/ml/META b/src/api/ml/META index 6238403a3..8634b53b1 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -2,8 +2,8 @@ version = "VERSION" description = "Z3 Theorem Prover (OCaml API)" requires = "num" -archive(byte) = "z3.cma" -archive(native) = "z3.cmxa" -archive(byte, plugin) = "z3.cma" -archive(native, plugin) = "z3.cmxs" -linkopts = "-cclib -lz3" \ No newline at end of file +archive(byte) = "z3ml.cma" +archive(native) = "z3ml.cmxa" +archive(byte, plugin) = "z3ml.cma" +archive(native, plugin) = "z3ml.cmxs" +linkopts = "-cclib -lz3" diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 2b54a1113..350457525 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -110,7 +110,7 @@ struct string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ - string_of_int rev ^ "." + string_of_int rev end From 6022ae68737122ab1142f851c2328946e30e43d4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 19:42:03 +0000 Subject: [PATCH 364/646] ML API: build fixes? --- scripts/mk_util.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index caad10555..99f413090 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1394,16 +1394,18 @@ class MLComponent(Component): archives, get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tcd %s ; ocamlmklib -o z3ml -ldopt \'-L../.. -lz3\' ' % (sub_dir)) + out.write('\tocamlmklib -o %s -I %s -ldopt \'-L. -lz3\' ' % ( + os.path.join(sub_dir, 'z3ml'), + sub_dir)) for m in modules: - out.write(' %s.ml' % m) - out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') + out.write(' %s' % (os.path.join(sub_dir, m+'.ml'))) + out.write(' z3native_stubs$(OBJ_EXT)\n') out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': out.write('\nocamlfind_install: %s %s %s\n' % ( - get_component(Z3_DLL_COMPONENT).dll_name)+'$(SO_EXT)', - os.path.join(sub_dir, 'z3ml.cmxa'), + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)', + os.path.join(sub_dir, 'z3ml.cmxa'), os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) @@ -1424,7 +1426,7 @@ class MLComponent(Component): out.write('.lib') else: out.write('.so') # .so also on OSX! - out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name) + '$(SO_EXT)')))) + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') out.write('\n\n') def main_component(self): From 0fee9659ab7e7df991778995baeb3bd7fbf9a8a5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 5 Dec 2014 16:40:40 +0000 Subject: [PATCH 365/646] ML API: Windows build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 99f413090..d2d9dd983 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1394,12 +1394,10 @@ class MLComponent(Component): archives, get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tocamlmklib -o %s -I %s -ldopt \'-L. -lz3\' ' % ( - os.path.join(sub_dir, 'z3ml'), - sub_dir)) + out.write('\tocamlmklib -o %s -I %s -ldopt \"-L. -lz3\" ' % (os.path.join(sub_dir, 'z3ml'), sub_dir)) for m in modules: out.write(' %s' % (os.path.join(sub_dir, m+'.ml'))) - out.write(' z3native_stubs$(OBJ_EXT)\n') + out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': @@ -1417,13 +1415,13 @@ class MLComponent(Component): out.write(' %s.ml' % (os.path.join(sub_dir, m))) out.write(' %s.mli' % (os.path.join(sub_dir, m))) out.write(' %s$(OBJ_EXT)' % (os.path.join(sub_dir, m))) - out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.a')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cma')))) out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cmxa')))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: - out.write('.lib') + out.write('.dll') else: out.write('.so') # .so also on OSX! out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') @@ -1550,7 +1548,7 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: api/ml/z3ml.cma ') + out.write('ml_example.byte: api/ml/z3ml.cmxa ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') From ae2c4d738c850cb9617179eaa567bac27ca1bd13 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:14:26 +0000 Subject: [PATCH 366/646] ML API: build fix --- src/api/ml/META | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/ml/META b/src/api/ml/META index 8634b53b1..635de613c 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -4,6 +4,8 @@ description = "Z3 Theorem Prover (OCaml API)" requires = "num" archive(byte) = "z3ml.cma" archive(native) = "z3ml.cmxa" -archive(byte, plugin) = "z3ml.cma" -archive(native, plugin) = "z3ml.cmxs" +archive(byte,plugin) = "z3ml.cma" +archive(native,plugin) = "z3ml.cmxa" +archive(byte,toploop) = "z3ml.cma" +archive(native,toploop) = "z3ml.cmxa" linkopts = "-cclib -lz3" From ccffea2bc997e955e605da6fb7c4d43497e9fcf1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:21:27 +0000 Subject: [PATCH 367/646] ML API: build fix --- examples/ml/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ml/README b/examples/ml/README index 844638552..c61716b65 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -15,7 +15,7 @@ for the byte-code version. If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), then we can compile this example as follows: -ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg ml_example.ml +ocamlfind ocamlc -o ml_example.byte -package Z3 -linkpkg ml_example.ml ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml Note that the resulting binaries depend on the shared z3 library, which needs to be From decb09bb9ecc95c1e59c2381131f10e207d779e9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:37:09 +0000 Subject: [PATCH 368/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d2d9dd983..5cfcbb4d3 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1425,6 +1425,8 @@ class MLComponent(Component): else: out.write('.so') # .so also on OSX! out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') + if IS_WINDOWS: + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') out.write('\n\n') def main_component(self): From 90cb04668447edc5414f218ab6ca42733de17c34 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 13:37:02 +0000 Subject: [PATCH 369/646] Beginnings of a new ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 11 + scripts/update_api.py | 576 +++++++++++------------------------------- src/api/ml/README | 5 +- 3 files changed, 166 insertions(+), 426 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5cfcbb4d3..7a054256d 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1428,6 +1428,13 @@ class MLComponent(Component): if IS_WINDOWS: out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') out.write('\n\n') + mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) + libfile = '%s$(LIB_EXT)' % self.lib_name + out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'z3_native.c'))) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) %s/z3_native.c\n' % self.to_src_dir) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'z3_native')) + out.write('ml: %s\n' % libfile) + out.write('\n') def main_component(self): return is_ml_enabled() @@ -1841,7 +1848,11 @@ def mk_config(): if GPROF: print('gprof: enabled') print('Python version: %s' % distutils.sysconfig.get_python_version()) +<<<<<<< HEAD print('ML API: %s' % is_ml_enabled()) +======= + print 'ML API: %s' % is_ml_enabled() +>>>>>>> Beginnings of a new ML API if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) diff --git a/scripts/update_api.py b/scripts/update_api.py index 4669b78fc..945496781 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -213,7 +213,10 @@ def type2javaw(ty): def type2ml(ty): global Type2ML - return Type2ML[ty] + if (ty >= FIRST_OBJ_ID): + return 'long' + else: + return Type2ML[ty] def _in(ty): return (IN, ty); @@ -1066,216 +1069,76 @@ def mk_bindings(): exe_c.write("}\n") def ml_method_name(name): - return name[3:] # Remove Z3_ - -def is_out_param(p): - if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_MANAGED_ARRAY: - return True - else: - return False - -def outparams(params): - op = [] - for param in params: - if is_out_param(param): - op.append(param) - return op - -def is_in_param(p): - if param_kind(p) == IN or param_kind(p) == INOUT or param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY: - return True - else: - return False - -def inparams(params): - ip = [] - for param in params: - if is_in_param(param): - ip.append(param) - return ip - -def is_array_param(p): - if param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_ARRAY: - return True - else: - return False - -def arrayparams(params): - op = [] - for param in params: - if is_array_param(param): - op.append(param) - return op - - -def ml_unwrap(t, ts, s): - if t == STRING: - return '(' + ts + ') String_val(' + s + ')' - elif t == BOOL: - return '(' + ts + ') Bool_val(' + s + ')' - elif t == INT or t == PRINT_MODE or t == ERROR_CODE: - return '(' + ts + ') Int_val(' + s + ')' - elif t == UINT: - return '(' + ts + ') Unsigned_int_val(' + s + ')' - elif t == INT64: - return '(' + ts + ') Long_val(' + s + ')' - elif t == UINT64: - return '(' + ts + ') Unsigned_long_val(' + s + ')' - elif t == DOUBLE: - return '(' + ts + ') Double_val(' + s + ')' - else: - return '* (' + ts + '*) Data_custom_val(' + s + ')' - -def ml_set_wrap(t, d, n): - if t == VOID: - return d + ' = Val_unit;' - elif t == BOOL: - return d + ' = Val_bool(' + n + ');' - elif t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: - return d + ' = Val_int(' + n + ');' - elif t == INT64 or t == UINT64: - return d + ' = Val_long(' + n + ');' - elif t == DOUBLE: - return 'Store_double_val(' + d + ', ' + n + ');' - elif t == STRING: - return d + ' = caml_copy_string((const char*) ' + n + ');' - else: - ts = type2str(t) - return d + ' = caml_alloc_custom(&default_custom_ops, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' + result = '' + name = name[3:] # Remove Z3_ + return result def mk_ml(): - global Type2Str if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'z3native.ml') - ml_nativefi = os.path.join(ml_dir, 'z3native.mli') - ml_wrapperf = os.path.join(ml_dir, 'z3native_stubs.c') + ml_nativef = os.path.join(ml_dir, 'z3_native.ml') + ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') ml_native = open(ml_nativef, 'w') - ml_i = open(ml_nativefi, 'w') - ml_native.write('(* Automatically generated file *)\n\n') - ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') - ml_i.write('(* Automatically generated file *)\n\n') - ml_i.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') - ml_i.write('(**/**)\n\n'); - ml_native.write('open Z3enums\n\n') - ml_native.write('(**/**)\n') - ml_native.write('type ptr\n') - ml_i.write('type ptr\n') - ml_native.write('and z3_symbol = ptr\n') - ml_i.write('and z3_symbol = ptr\n') - for k, v in Type2Str.iteritems(): - if is_obj(k): - ml_native.write('and %s = ptr\n' % v.lower()) - ml_i.write('and %s = ptr\n' % v.lower()) + ml_native.write('// Automatically generated file\n') ml_native.write('\n') - ml_i.write('\n') - ml_native.write('external is_null : ptr -> bool\n = "n_is_null"\n\n') - ml_native.write('external mk_null : unit -> ptr\n = "n_mk_null"\n\n') - ml_native.write('external set_internal_error_handler : ptr -> unit\n = "n_set_internal_error_handler"\n\n') - ml_native.write('exception Exception of string\n\n') - ml_i.write('val is_null : ptr -> bool\n') - ml_i.write('val mk_null : unit -> ptr\n') - ml_i.write('val set_internal_error_handler : ptr -> unit\n\n') - ml_i.write('exception Exception of string\n\n') - - # ML declarations - ml_native.write('module ML2C = struct\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external n_%s : ' % ml_method_name(name)) - ml_i.write('val %s : ' % ml_method_name(name)) - ip = inparams(params) - op = outparams(params) - if len(ip) == 0: - ml_native.write(' unit -> ') - ml_i.write(' unit -> ') - for p in ip: - ml_native.write('%s -> ' % param2ml(p)) - ml_i.write('%s -> ' % param2ml(p)) - if len(op) > 0: - ml_native.write('(') - ml_i.write('(') + ml_native.write(' external %s : (' % ml_method_name(name)) first = True - if result != VOID or len(op) == 0: - ml_native.write('%s' % type2ml(result)) - ml_i.write('%s' % type2ml(result)) - first = False - for p in op: + i = 0; + for param in params: if first: first = False else: - ml_native.write(' * ') - ml_i.write(' * ') - ml_native.write('%s' % param2ml(p)) - ml_i.write('%s' % param2ml(p)) - if len(op) > 0: - ml_native.write(')') - ml_i.write(')') - ml_native.write('\n') - ml_i.write('\n') - if len(ip) > 5: - ml_native.write(' = "n_%s_bytecode"\n' % ml_method_name(name)) - ml_native.write(' "n_%s"\n' % ml_method_name(name)) - else: - ml_native.write(' = "n_%s"\n' % ml_method_name(name)) - ml_native.write('\n') - ml_native.write(' end\n\n') - ml_i.write('\n(**/**)\n'); - - # Exception wrappers - for name, result, params in _dotnet_decls: - ip = inparams(params) - op = outparams(params) - ml_native.write(' let %s ' % ml_method_name(name)) - - first = True - i = 0; - for p in params: - if is_in_param(p): - if first: - first = False; - else: - ml_native.write(' ') - ml_native.write('a%d' % i) + ml_native.write(', ') + ml_native.write('%s a%d' % (param2ml(param), i)) i = i + 1 - if len(ip) == 0: - ml_native.write('()') - ml_native.write(' = \n') - ml_native.write(' ') - if result == VOID and len(op) == 0: - ml_native.write('let _ = ') - else: - ml_native.write('let res = ') - ml_native.write('(ML2C.n_%s' % (ml_method_name(name))) - if len(ip) == 0: - ml_native.write(' ()') - first = True - i = 0; - for p in params: - if is_in_param(p): - ml_native.write(' a%d' % i) - i = i + 1 - ml_native.write(') in\n') - if name not in Unwrapped and len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (error_code_of_int (ML2C.n_get_error_code a0)) in \n') - ml_native.write(' if err <> OK then\n') - ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (int_of_error_code err)))\n') - ml_native.write(' else\n') - if result == VOID and len(op) == 0: - ml_native.write(' ()\n') - else: - ml_native.write(' res\n') - ml_native.write('\n') - ml_native.write('(**/**)\n') - - # C interface + ml_native.write('%s)\n' % (type2ml(result))) + # ml_native.write(' = "NATIVE_%s"' % ml_method_name(name)) + # ml_native.write('\n\n') + # # Exception wrappers + # for name, result, params in _dotnet_decls: + # java_native.write(' public static %s %s(' % (type2java(result), java_method_name(name))) + # first = True + # i = 0; + # for param in params: + # if first: + # first = False + # else: + # java_native.write(', ') + # java_native.write('%s a%d' % (param2java(param), i)) + # i = i + 1 + # java_native.write(')') + # if len(params) > 0 and param_type(params[0]) == CONTEXT: + # java_native.write(' throws Z3Exception') + # java_native.write('\n') + # java_native.write(' {\n') + # java_native.write(' ') + # if result != VOID: + # java_native.write('%s res = ' % type2java(result)) + # java_native.write('INTERNAL%s(' % (java_method_name(name))) + # first = True + # i = 0; + # for param in params: + # if first: + # first = False + # else: + # java_native.write(', ') + # java_native.write('a%d' % i) + # i = i + 1 + # java_native.write(');\n') + # if len(params) > 0 and param_type(params[0]) == CONTEXT: + # java_native.write(' Z3_error_code err = Z3_error_code.fromInt(INTERNALgetErrorCode(a0));\n') + # java_native.write(' if (err != Z3_error_code.Z3_OK)\n') + # java_native.write(' throw new Z3Exception(INTERNALgetErrorMsgEx(a0, err.toInt()));\n') + # if result != VOID: + # java_native.write(' return res;\n') + # java_native.write(' }\n\n') + # java_native.write('}\n') ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') ml_wrapper.write('#include \n') - ml_wrapper.write('#include \n\n') - ml_wrapper.write('#ifdef __cplusplus\n') - ml_wrapper.write('extern "C" {\n') - ml_wrapper.write('#endif\n') + ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') @@ -1285,237 +1148,100 @@ def mk_ml(): ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') ml_wrapper.write('#endif\n') - ml_wrapper.write('#ifdef __cplusplus\n') - ml_wrapper.write('}\n') - ml_wrapper.write('#endif\n\n') - ml_wrapper.write('#include \n\n') - ml_wrapper.write('#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \\\n') - ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal1(X6) \n') - ml_wrapper.write('#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \\\n') - ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal2(X6,X7) \n') - ml_wrapper.write('#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') - ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal3(X6,X7,X8) \n') - ml_wrapper.write('\n') - ml_wrapper.write('#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \\\n') - ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam2(X6,X7) \n') - ml_wrapper.write('#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') - ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam3(X6,X7,X8) \n') - ml_wrapper.write('#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \\\n') - ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9) \n') - ml_wrapper.write('#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \\\n') - ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam2(X11,X12) \n') - ml_wrapper.write('#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \\\n') - ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam3(X11,X12,X13) \n') - ml_wrapper.write('\n\n') - ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') - ml_wrapper.write(' (char*) "default handling",\n') - ml_wrapper.write(' custom_finalize_default,\n') - ml_wrapper.write(' custom_compare_default,\n') - ml_wrapper.write(' custom_hash_default,\n') - ml_wrapper.write(' custom_serialize_default,\n') - ml_wrapper.write(' custom_deserialize_default\n') - ml_wrapper.write('};\n\n') - ml_wrapper.write('#ifdef __cplusplus\n') - ml_wrapper.write('extern "C" {\n') - ml_wrapper.write('#endif\n\n') - ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') - ml_wrapper.write(' void * t = * (void**) Data_custom_val(p);\n') - ml_wrapper.write(' return Val_bool(t == 0);\n') - ml_wrapper.write('}\n\n') - ml_wrapper.write('CAMLprim value n_mk_null( void ) {\n') - ml_wrapper.write(' CAMLparam0();\n') - ml_wrapper.write(' CAMLlocal1(result);\n') - ml_wrapper.write(' void * z3_result = 0;\n') - ml_wrapper.write(' result = caml_alloc_custom(&default_custom_ops, sizeof(void*), 0, 1);\n') - ml_wrapper.write(' memcpy( Data_custom_val(result), &z3_result, sizeof(void*));\n') - ml_wrapper.write(' CAMLreturn (result);\n') - ml_wrapper.write('}\n\n') - ml_wrapper.write('void MLErrorHandler(Z3_context c, Z3_error_code e)\n') - ml_wrapper.write('{\n') - ml_wrapper.write(' // Internal do-nothing error handler. This is required to avoid that Z3 calls exit()\n') - ml_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') - ml_wrapper.write(' // wrappers below.\n') - ml_wrapper.write('}\n\n') - ml_wrapper.write('void n_set_internal_error_handler(value a0)\n') - ml_wrapper.write('{\n') - ml_wrapper.write(' Z3_context _a0 = * (Z3_context*) Data_custom_val(a0);\n') - ml_wrapper.write(' Z3_set_error_handler(_a0, MLErrorHandler);\n') - ml_wrapper.write('}\n\n') - for name, result, params in _dotnet_decls: - ip = inparams(params) - op = outparams(params) - ap = arrayparams(params) - ret_size = len(op) - if result != VOID: - ret_size = ret_size + 1 - - # Setup frame - ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) - first = True - i = 0 - for p in params: - if is_in_param(p): - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('value a%d' % i) - i = i + 1 - ml_wrapper.write(') {\n') - ml_wrapper.write(' CAMLparam%d(' % len(ip)) - i = 0 - first = True - for p in params: - if is_in_param(p): - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('a%d' % i) - i = i + 1 - ml_wrapper.write(');\n') - i = 0 - if len(op) + len(ap) == 0: - ml_wrapper.write(' CAMLlocal1(result);\n') - else: - c = 0 - for p in params: - if is_out_param(p) or is_array_param(p): - c = c + 1 - ml_wrapper.write(' CAMLlocal%s(result, res_val' % (c+2)) - for p in params: - if is_out_param(p) or is_array_param(p): - ml_wrapper.write(', _a%s_val' % i) - i = i + 1 - ml_wrapper.write(');\n') + # for name, result, params in _dotnet_decls: + # java_wrapper.write('JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) + # i = 0; + # for param in params: + # java_wrapper.write(', ') + # java_wrapper.write('%s a%d' % (param2javaw(param), i)) + # i = i + 1 + # java_wrapper.write(') {\n') + # # preprocess arrays, strings, in/out arguments + # i = 0 + # for param in params: + # k = param_kind(param) + # if k == OUT or k == INOUT: + # java_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + # elif k == IN_ARRAY or k == INOUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) + # else: + # java_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) + # elif k == OUT_ARRAY: + # java_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), + # i, + # type2str(param_type(param)), + # param_array_capacity_pos(param), + # type2str(param_type(param)))) + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + # else: + # java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) + # elif k == IN and param_type(param) == STRING: + # java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i)) + # i = i + 1 + # # invoke procedure + # java_wrapper.write(' ') + # if result != VOID: + # java_wrapper.write('%s result = ' % type2str(result)) + # java_wrapper.write('%s(' % name) + # i = 0 + # first = True + # for param in params: + # if first: + # first = False + # else: + # java_wrapper.write(', ') + # k = param_kind(param) + # if k == OUT or k == INOUT: + # java_wrapper.write('&_a%s' % i) + # elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + # java_wrapper.write('_a%s' % i) + # elif k == IN and param_type(param) == STRING: + # java_wrapper.write('_a%s' % i) + # else: + # java_wrapper.write('(%s)a%i' % (param2str(param), i)) + # i = i + 1 + # java_wrapper.write(');\n') + # # cleanup + # i = 0 + # for param in params: + # k = param_kind(param) + # if k == OUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + # else: + # java_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) + # java_wrapper.write(' free(_a%s);\n' % i) + # elif k == IN_ARRAY or k == OUT_ARRAY: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) + # else: + # java_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) - if len(ap) != 0: - ml_wrapper.write(' unsigned _i;\n') - - # declare locals, preprocess arrays, strings, in/out arguments - i = 0 - for param in params: - k = param_kind(param) - if k == OUT_ARRAY: - ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * (_a%s));\n' % ( - type2str(param_type(param)), - i, - type2str(param_type(param)), - type2str(param_type(param)), - param_array_capacity_pos(param))) - elif k == OUT_MANAGED_ARRAY: - ml_wrapper.write(' %s * _a%s = 0;\n' % (type2str(param_type(param)), i)) - elif k == IN_ARRAY or k == INOUT_ARRAY: - t = param_type(param) - ts = type2str(t) - ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * _a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) - elif k == IN: - t = param_type(param) - ml_wrapper.write(' %s _a%s = %s;\n' % (type2str(t), i, ml_unwrap(t, type2str(t), 'a' + str(i)))) - elif k == OUT: - ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) - elif k == INOUT: - ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) - i = i + 1 - - if result != VOID: - ml_wrapper.write(' %s z3_result;\n' % type2str(result)) - - i = 0 - for param in params: - k = param_kind(param) - if k == IN_ARRAY or k == INOUT_ARRAY: - t = param_type(param) - ts = type2str(t) - ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { _a%s[_i] = %s; }\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', _i)'))) - i = i + 1 - - # invoke procedure - ml_wrapper.write(' ') - if result != VOID: - ml_wrapper.write('z3_result = ') - ml_wrapper.write('%s(' % name) - i = 0 - first = True - for param in params: - if first: - first = False - else: - ml_wrapper.write(', ') - k = param_kind(param) - if k == OUT or k == INOUT or k == OUT_MANAGED_ARRAY: - ml_wrapper.write('&_a%s' % i) - else: - ml_wrapper.write('_a%i' % i) - i = i + 1 - ml_wrapper.write(');\n') - - # convert output params - if len(op) > 0: - if result != VOID: - ml_wrapper.write(' %s\n' % ml_set_wrap(result, "res_val", "z3_result")) - i = 0; - for p in params: - if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: - ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) - ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s_val, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) - elif param_kind(p) == OUT_MANAGED_ARRAY: - ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) - elif is_out_param(p): - ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) - i = i + 1 - - # return tuples - if len(op) == 0: - ml_wrapper.write(' %s\n' % ml_set_wrap(result, "result", "z3_result")) - else: - ml_wrapper.write(' result = caml_alloc(%s, 0);\n' % ret_size) - i = j = 0 - if result != VOID: - ml_wrapper.write(' Store_field(result, 0, res_val);\n') - j = j + 1 - for p in params: - if is_out_param(p): - ml_wrapper.write(' Store_field(result, %s, _a%s_val);\n' % (j, i)) - j = j + 1; - i = i + 1 - - # local array cleanup - i = 0 - for p in params: - k = param_kind(p) - if k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: - ml_wrapper.write(' free(_a%s);\n' % i) - i = i + 1 - - # return - ml_wrapper.write(' CAMLreturn(result);\n') - ml_wrapper.write('}\n\n') - if len(ip) > 5: - ml_wrapper.write('CAMLprim value n_%s_bytecode(value * argv, int argn) {\n' % ml_method_name(name)) - ml_wrapper.write(' return n_%s(' % ml_method_name(name)) - i = 0 - while i < len(ip): - if i == 0: - ml_wrapper.write('argv[0]') - else: - ml_wrapper.write(', argv[%s]' % i) - i = i + 1 - ml_wrapper.write(');\n}\n') - ml_wrapper.write('\n\n') - ml_wrapper.write('#ifdef __cplusplus\n') - ml_wrapper.write('}\n') - ml_wrapper.write('#endif\n') + # elif k == OUT or k == INOUT: + # if param_type(param) == INT or param_type(param) == UINT: + # java_wrapper.write(' {\n') + # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') + # java_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) + # java_wrapper.write(' }\n') + # else: + # java_wrapper.write(' {\n') + # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') + # java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) + # java_wrapper.write(' }\n') + # i = i + 1 + # # return + # if result == STRING: + # java_wrapper.write(' return jenv->NewStringUTF(result);\n') + # elif result != VOID: + # java_wrapper.write(' return (%s) result;\n' % type2javaw(result)) + # java_wrapper.write('}\n') + # java_wrapper.write('#ifdef __cplusplus\n') + # java_wrapper.write('}\n') + # java_wrapper.write('#endif\n') if is_verbose(): print "Generated '%s'" % ml_nativef diff --git a/src/api/ml/README b/src/api/ml/README index beee7d864..f8984c79e 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -1,8 +1,11 @@ This directory is work in progress. We are currently working on a brand new ML API. +<<<<<<< HEAD On Windows, there are no less than four different ports of OCaml. The Z3 build system assumes that either the win32 or the win64 port is installed. This means that OCaml will use `cl' as the underlying C compiler and not the cygwin or -mingw compilers. \ No newline at end of file +mingw compilers. +======= +>>>>>>> Beginnings of a new ML API From 1579da02b0e49c079afe95df9fb7b36f32b9dc2a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 15:07:33 +0000 Subject: [PATCH 370/646] More new ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 9 ++-- scripts/mk_util.py | 25 +++++++++ scripts/update_api.py | 121 ++++++++++++++++++++++++------------------ 3 files changed, 99 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index 9c9707c4b..2ae719b85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ *~ *.pyc -*.pyo -# Ignore callgrind files -callgrind.out.* # .hpp files are automatically generated *.hpp .z3-trace @@ -45,6 +42,7 @@ bld_rel_x64/* # Auto generated files. config.log config.status +configure install_tactic.cpp mem_initializer.cpp gparams_register_modules.cpp @@ -56,8 +54,6 @@ src/api/api_log_macros.cpp src/api/dll/api_dll.def src/api/dotnet/Enumerations.cs src/api/dotnet/Native.cs -src/api/dotnet/Properties/AssemblyInfo.cs -src/api/dotnet/Microsoft.Z3.xml src/api/python/z3consts.py src/api/python/z3core.py src/ast/pattern/database.h @@ -78,3 +74,6 @@ src/api/ml/z3native_stubs.c src/api/ml/z3native.ml src/api/ml/z3enums.ml src/api/ml/z3.mllib +src/api/ml/z3_native.c +src/api/ml/z3_native.ml +src/api/ml/z3_enums.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 7a054256d..d019e24e9 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2431,6 +2431,8 @@ def mk_bindings(api_files): mk_z3consts_ml(api_files) _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3py_to_build() + if is_ml_enabled(): + mk_z3consts_ml(api_files) # Extract enumeration types from API files, and add python definitions. def mk_z3consts_py(api_files): @@ -2718,6 +2720,7 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) +<<<<<<< HEAD efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') efile.write('(** The enumeration types of Z3. *)\n\n') @@ -2799,6 +2802,13 @@ def mk_z3consts_ml(api_files): efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') efile.write('(** The enumeration types of Z3. *)\n\n') +======= + efile = open('%s.ml' % os.path.join(gendir, "z3_enums"), 'w') + efile.write('(* Automatically generated file *)\n\n') + # efile.write('module z3_enums = struct\n\n'); + + +>>>>>>> More new ML API for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2844,6 +2854,7 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: +<<<<<<< HEAD efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ for k, i in decls.iteritems(): @@ -2854,6 +2865,13 @@ def mk_z3consts_ml(api_files): efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ efile.write('\n') +======= + efile.write('\n(* %s *)\n' % name) + efile.write('type %s =\n' % name[3:]) # strip Z3_ + efile.write + for k, i in decls.iteritems(): + efile.write(' | %s \n' % k[3:]) # strip Z3_ +>>>>>>> More new ML API mode = SEARCHING else: if words[2] != '': @@ -2864,8 +2882,15 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 +<<<<<<< HEAD if VERBOSE: print "Generated '%s/z3enums.mli'" % ('%s' % gendir) +======= + efile.write('\n') + # efile.write'end\n'); + if VERBOSE: + print "Generated '%s/z3_enums.ml'" % ('%s' % gendir) +>>>>>>> More new ML API def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 945496781..c1bb22a44 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -157,9 +157,9 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} # Mapping to ML types -Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', - STRING : 'string', STRING_PTR : 'char**', - BOOL : 'bool', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } +Type2ML = { VOID : 'unit', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', + STRING : 'string', STRING_PTR : 'char**', + BOOL : 'lbool', SYMBOL : 'symbol', PRINT_MODE : 'ast_print_mode', ERROR_CODE : 'error_code' } next_type_id = FIRST_OBJ_ID @@ -1069,9 +1069,7 @@ def mk_bindings(): exe_c.write("}\n") def ml_method_name(name): - result = '' - name = name[3:] # Remove Z3_ - return result + return name[3:] # Remove Z3_ def mk_ml(): if not is_ml_enabled(): @@ -1080,10 +1078,57 @@ def mk_ml(): ml_nativef = os.path.join(ml_dir, 'z3_native.ml') ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') ml_native = open(ml_nativef, 'w') - ml_native.write('// Automatically generated file\n') + ml_native.write('(* Automatically generated file *)\n') ml_native.write('\n') + ml_native.write('module Z3 = struct\n\n') + ml_native.write('type context\n') + ml_native.write('and symbol\n') + ml_native.write('and ast\n') + ml_native.write('and sort = private ast\n') + ml_native.write('and func_decl = private ast\n') + ml_native.write('and app = private ast\n') + ml_native.write('and pattern = private ast\n') + ml_native.write('and params\n') + ml_native.write('and param_descrs\n') + ml_native.write('and model\n') + ml_native.write('and func_interp\n') + ml_native.write('and func_entry\n') + ml_native.write('and fixedpoint\n') + ml_native.write('and ast_vector\n') + ml_native.write('and ast_map\n') + ml_native.write('and goal\n') + ml_native.write('and tactic\n') + ml_native.write('and probe\n') + ml_native.write('and apply_result\n') + ml_native.write('and solver\n') + ml_native.write('and stats\n') + ml_native.write('\n') + ml_native.write(' exception Z3Exception of string\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external %s : (' % ml_method_name(name)) + ml_native.write(' external native_%s : ' % ml_method_name(name)) + i = 0; + for param in params: + ml_native.write('%s -> ' % param2ml(param)) + i = i + 1 + ml_native.write('%s\n' % (type2ml(result))) + ml_native.write(' = "Native_Z3_%s"\n\n' % ml_method_name(name)) + # Exception wrappers + for name, result, params in _dotnet_decls: + ml_native.write(' let %s ' % ml_method_name(name)) + first = True + i = 0; + for param in params: + if first: + first = False; + else: + ml_native.write(' ') + ml_native.write('a%d' % i) + i = i + 1 + ml_native.write(' = \n') + ml_native.write(' ') + if result != VOID: + ml_native.write('let res = ') + ml_native.write('n_%s(' % (ml_method_name(name))) first = True i = 0; for param in params: @@ -1091,50 +1136,24 @@ def mk_ml(): first = False else: ml_native.write(', ') - ml_native.write('%s a%d' % (param2ml(param), i)) + ml_native.write('a%d' % i) i = i + 1 - ml_native.write('%s)\n' % (type2ml(result))) - # ml_native.write(' = "NATIVE_%s"' % ml_method_name(name)) - # ml_native.write('\n\n') - # # Exception wrappers - # for name, result, params in _dotnet_decls: - # java_native.write(' public static %s %s(' % (type2java(result), java_method_name(name))) - # first = True - # i = 0; - # for param in params: - # if first: - # first = False - # else: - # java_native.write(', ') - # java_native.write('%s a%d' % (param2java(param), i)) - # i = i + 1 - # java_native.write(')') - # if len(params) > 0 and param_type(params[0]) == CONTEXT: - # java_native.write(' throws Z3Exception') - # java_native.write('\n') - # java_native.write(' {\n') - # java_native.write(' ') - # if result != VOID: - # java_native.write('%s res = ' % type2java(result)) - # java_native.write('INTERNAL%s(' % (java_method_name(name))) - # first = True - # i = 0; - # for param in params: - # if first: - # first = False - # else: - # java_native.write(', ') - # java_native.write('a%d' % i) - # i = i + 1 - # java_native.write(');\n') - # if len(params) > 0 and param_type(params[0]) == CONTEXT: - # java_native.write(' Z3_error_code err = Z3_error_code.fromInt(INTERNALgetErrorCode(a0));\n') - # java_native.write(' if (err != Z3_error_code.Z3_OK)\n') - # java_native.write(' throw new Z3Exception(INTERNALgetErrorMsgEx(a0, err.toInt()));\n') - # if result != VOID: - # java_native.write(' return res;\n') - # java_native.write(' }\n\n') - # java_native.write('}\n') + ml_native.write(')') + if result != VOID: + ml_native.write(' in\n') + else: + ml_native.write(';\n') + if len(params) > 0 and param_type(params[0]) == CONTEXT: + ml_native.write(' let err = error_code.fromInt(n_get_error_code(a0)) in \n') + ml_native.write(' if err <> Z3_enums.OK then\n') + ml_native.write(' raise (z3_exception n_get_error_msg_ex(a0, err.toInt()))\n') + ml_native.write(' else\n') + if result == VOID: + ml_native.write(' ()\n') + else: + ml_native.write(' res\n') + ml_native.write('\n') + ml_native.write('\nend\n') ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') ml_wrapper.write('#include \n') From a40433aae85d0b181c355c9861cf95b163c9d422 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 16:35:39 +0000 Subject: [PATCH 371/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 3 + scripts/mk_util.py | 6 +- scripts/update_api.py | 211 +++++++++++++++++++++++------------------- src/api/ml/Makefile | 10 -- 4 files changed, 120 insertions(+), 110 deletions(-) delete mode 100644 src/api/ml/Makefile diff --git a/.gitignore b/.gitignore index 2ae719b85..a3fa5e919 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,7 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java + *.bak doc/api doc/code @@ -76,4 +77,6 @@ src/api/ml/z3enums.ml src/api/ml/z3.mllib src/api/ml/z3_native.c src/api/ml/z3_native.ml +src/api/ml/native.c +src/api/ml/Z3.ml src/api/ml/z3_enums.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d019e24e9..d324e5206 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1430,9 +1430,9 @@ class MLComponent(Component): out.write('\n\n') mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) libfile = '%s$(LIB_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'z3_native.c'))) - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) %s/z3_native.c\n' % self.to_src_dir) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'z3_native')) + out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) out.write('ml: %s\n' % libfile) out.write('\n') diff --git a/scripts/update_api.py b/scripts/update_api.py index c1bb22a44..72fd32702 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1075,12 +1075,12 @@ def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'z3_native.ml') - ml_wrapperf = os.path.join(ml_dir, 'z3_native.c') + ml_nativef = os.path.join(ml_dir, 'Z3.ml') + ml_wrapperf = os.path.join(ml_dir, 'native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n') ml_native.write('\n') - ml_native.write('module Z3 = struct\n\n') + ml_native.write('module Z3Native = struct\n\n') ml_native.write('type context\n') ml_native.write('and symbol\n') ml_native.write('and ast\n') @@ -1166,101 +1166,118 @@ def mk_ml(): ml_wrapper.write('#ifdef Custom_tag\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') - ml_wrapper.write('#endif\n') - # for name, result, params in _dotnet_decls: - # java_wrapper.write('JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) - # i = 0; - # for param in params: - # java_wrapper.write(', ') - # java_wrapper.write('%s a%d' % (param2javaw(param), i)) - # i = i + 1 - # java_wrapper.write(') {\n') - # # preprocess arrays, strings, in/out arguments - # i = 0 - # for param in params: - # k = param_kind(param) - # if k == OUT or k == INOUT: - # java_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) - # elif k == IN_ARRAY or k == INOUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) - # else: - # java_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) - # elif k == OUT_ARRAY: - # java_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), - # i, - # type2str(param_type(param)), - # param_array_capacity_pos(param), - # type2str(param_type(param)))) - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - # else: - # java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) - # elif k == IN and param_type(param) == STRING: - # java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i)) - # i = i + 1 - # # invoke procedure - # java_wrapper.write(' ') - # if result != VOID: - # java_wrapper.write('%s result = ' % type2str(result)) - # java_wrapper.write('%s(' % name) - # i = 0 - # first = True - # for param in params: - # if first: - # first = False - # else: - # java_wrapper.write(', ') - # k = param_kind(param) - # if k == OUT or k == INOUT: - # java_wrapper.write('&_a%s' % i) - # elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: - # java_wrapper.write('_a%s' % i) - # elif k == IN and param_type(param) == STRING: - # java_wrapper.write('_a%s' % i) - # else: - # java_wrapper.write('(%s)a%i' % (param2str(param), i)) - # i = i + 1 - # java_wrapper.write(');\n') - # # cleanup - # i = 0 - # for param in params: - # k = param_kind(param) - # if k == OUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - # else: - # java_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) - # java_wrapper.write(' free(_a%s);\n' % i) - # elif k == IN_ARRAY or k == OUT_ARRAY: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) - # else: - # java_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) + ml_wrapper.write('#endif\n\n') + ml_wrapper.write('#include \n\n') + for name, result, params in _dotnet_decls: + #return type = type2ml(result) + ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) + first = True + i = 0 + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('value a%d' % i) + # param type = param2ml(param) + i = i + 1 + ml_wrapper.write(') {\n') + ml_wrapper.write(' CAMLparam%d(' % len(params)) + i = 0 + first = True + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('a%d' % i) + i = i + 1 + ml_wrapper.write(');\n') + # preprocess arrays, strings, in/out arguments + i = 0 + for param in params: + k = param_kind(param) + if k == OUT or k == INOUT: + ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + elif k == IN_ARRAY or k == INOUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) + else: + ml_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) + elif k == OUT_ARRAY: + ml_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), + i, + type2str(param_type(param)), + param_array_capacity_pos(param), + type2str(param_type(param)))) + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + else: + ml_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) + elif k == IN and param_type(param) == STRING: + ml_wrapper.write(' Z3_string _a%s = (Z3_string) String_val(a%s);\n' % (i, i)) + i = i + 1 + # invoke procedure + ml_wrapper.write(' ') + if result != VOID: + ml_wrapper.write('%s result = ' % type2str(result)) + ml_wrapper.write('%s(' % name) + i = 0 + first = True + for param in params: + if first: + first = False + else: + ml_wrapper.write(', ') + k = param_kind(param) + if k == OUT or k == INOUT: + ml_wrapper.write('&_a%s' % i) + elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + ml_wrapper.write('_a%s' % i) + elif k == IN and param_type(param) == STRING: + ml_wrapper.write('_a%s' % i) + else: + ml_wrapper.write('(%s)a%i' % (param2str(param), i)) + i = i + 1 + ml_wrapper.write(');\n') + # cleanup + i = 0 + for param in params: + k = param_kind(param) + if k == OUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) + else: + ml_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) + ml_wrapper.write(' free(_a%s);\n' % i) + elif k == IN_ARRAY or k == OUT_ARRAY: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) + else: + ml_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) - # elif k == OUT or k == INOUT: - # if param_type(param) == INT or param_type(param) == UINT: - # java_wrapper.write(' {\n') - # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') - # java_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) - # java_wrapper.write(' }\n') - # else: - # java_wrapper.write(' {\n') - # java_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - # java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') - # java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) - # java_wrapper.write(' }\n') - # i = i + 1 - # # return - # if result == STRING: - # java_wrapper.write(' return jenv->NewStringUTF(result);\n') - # elif result != VOID: - # java_wrapper.write(' return (%s) result;\n' % type2javaw(result)) - # java_wrapper.write('}\n') - # java_wrapper.write('#ifdef __cplusplus\n') - # java_wrapper.write('}\n') - # java_wrapper.write('#endif\n') + elif k == OUT or k == INOUT: + if param_type(param) == INT or param_type(param) == UINT: + ml_wrapper.write(' {\n') + ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') + ml_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) + ml_wrapper.write(' }\n') + else: + ml_wrapper.write(' {\n') + ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) + ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') + ml_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) + ml_wrapper.write(' }\n') + i = i + 1 + # return + if result == STRING: + ml_wrapper.write(' return caml_copy_string(result);\n') + elif result == VOID: + ml_wrapper.write(' CAMLreturn(Val_unit);\n') + elif result != VOID: + ml_wrapper.write(' return (value) result;\n') + ml_wrapper.write('}\n\n') if is_verbose(): print "Generated '%s'" % ml_nativef diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile deleted file mode 100644 index 96fd0a55d..000000000 --- a/src/api/ml/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# This is a temporary support file for emacs annotations. -# It does not compile the Z3 ML API; this will be built -# in the top-level build directory. - -all: - ocamlbuild -cflag -annot z3.cmxa - -doc: *.ml - mkdir -p doc - ocamldoc -html -d doc -I _build -sort *.mli -hide Z3 From dcd6f1f69736ace570ead5e544b670dfa0a1b42c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 11 Dec 2012 21:39:52 +0000 Subject: [PATCH 372/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 4 +-- scripts/mk_util.py | 44 ++++++++++++++++++++++++++++++--- scripts/update_api.py | 57 ++++++++++++++++++++++++------------------- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index a3fa5e919..a1a8b7f6b 100644 --- a/.gitignore +++ b/.gitignore @@ -78,5 +78,5 @@ src/api/ml/z3.mllib src/api/ml/z3_native.c src/api/ml/z3_native.ml src/api/ml/native.c -src/api/ml/Z3.ml -src/api/ml/z3_enums.ml +src/api/ml/z3.ml +src/api/ml/enumerations.ml diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d324e5206..bd6495d1b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1428,9 +1428,17 @@ class MLComponent(Component): if IS_WINDOWS: out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') out.write('\n\n') - mk_dir(os.path.join(BUILD_DIR, 'api', 'ml')) + bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') + mk_dir(bld_dir) libfile = '%s$(LIB_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s\n' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + for mlfile in get_ml_files(self.src_dir): + out.write('%si: %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) + out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) + out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) + out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) + for mlfile in get_ml_files(self.src_dir): + out.write(' %si' % os.path.join('api','ml', mlfile)) + out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) out.write('ml: %s\n' % libfile) @@ -2720,6 +2728,7 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) +<<<<<<< HEAD <<<<<<< HEAD efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') @@ -2809,6 +2818,11 @@ def mk_z3consts_ml(api_files): >>>>>>> More new ML API +======= + efile = open('%s.ml' % os.path.join(gendir, "enumerations"), 'w') + efile.write('(* Automatically generated file *)\n\n') + efile.write('module Enumerations = struct\n') +>>>>>>> More ML API for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2854,6 +2868,7 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: +<<<<<<< HEAD <<<<<<< HEAD efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ @@ -2867,11 +2882,28 @@ def mk_z3consts_ml(api_files): efile.write('\n') ======= efile.write('\n(* %s *)\n' % name) +======= +>>>>>>> More ML API efile.write('type %s =\n' % name[3:]) # strip Z3_ - efile.write for k, i in decls.iteritems(): +<<<<<<< HEAD efile.write(' | %s \n' % k[3:]) # strip Z3_ >>>>>>> More new ML API +======= + efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write('\n') + efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in decls.iteritems(): + efile.write(' | %s -> %d\n' % (k[3:], i)) + efile.write('\n') + efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in decls.iteritems(): + efile.write(' | %d -> %s\n' % (i, k[3:])) + # use Z3.Exception? + efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') +>>>>>>> More ML API mode = SEARCHING else: if words[2] != '': @@ -2882,6 +2914,7 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 +<<<<<<< HEAD <<<<<<< HEAD if VERBOSE: print "Generated '%s/z3enums.mli'" % ('%s' % gendir) @@ -2891,6 +2924,11 @@ def mk_z3consts_ml(api_files): if VERBOSE: print "Generated '%s/z3_enums.ml'" % ('%s' % gendir) >>>>>>> More new ML API +======= + efile.write('end\n') + if VERBOSE: + print "Generated '%s/enumerations.ml'" % ('%s' % gendir) +>>>>>>> More ML API def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 72fd32702..971e6eab1 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -157,9 +157,9 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} # Mapping to ML types -Type2ML = { VOID : 'unit', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', - STRING : 'string', STRING_PTR : 'char**', - BOOL : 'lbool', SYMBOL : 'symbol', PRINT_MODE : 'ast_print_mode', ERROR_CODE : 'error_code' } +Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', + STRING : 'string', STRING_PTR : 'char**', + BOOL : 'int', SYMBOL : 'symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -214,7 +214,7 @@ def type2javaw(ty): def type2ml(ty): global Type2ML if (ty >= FIRST_OBJ_ID): - return 'long' + return 'int' else: return Type2ML[ty] @@ -331,6 +331,8 @@ def param2ml(p): if k == OUT: if param_type(p) == INT or param_type(p) == UINT or param_type(p) == INT64 or param_type(p) == UINT64: return "int" + elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: + return "int" elif param_type(p) == STRING: return "string" else: @@ -1075,12 +1077,12 @@ def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'Z3.ml') + ml_nativef = os.path.join(ml_dir, 'z3.ml') ml_wrapperf = os.path.join(ml_dir, 'native.c') ml_native = open(ml_nativef, 'w') - ml_native.write('(* Automatically generated file *)\n') - ml_native.write('\n') - ml_native.write('module Z3Native = struct\n\n') + ml_native.write('(* Automatically generated file *)\n\n') + ml_native.write('open Enumerations\n\n') + ml_native.write('module Z3 = struct\n\n') ml_native.write('type context\n') ml_native.write('and symbol\n') ml_native.write('and ast\n') @@ -1103,15 +1105,17 @@ def mk_ml(): ml_native.write('and solver\n') ml_native.write('and stats\n') ml_native.write('\n') - ml_native.write(' exception Z3Exception of string\n\n') + ml_native.write(' exception Exception of string\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external native_%s : ' % ml_method_name(name)) + ml_native.write(' external n_%s : ' % ml_method_name(name)) i = 0; for param in params: ml_native.write('%s -> ' % param2ml(param)) i = i + 1 + if len(params) == 0: + ml_native.write(' unit -> ') ml_native.write('%s\n' % (type2ml(result))) - ml_native.write(' = "Native_Z3_%s"\n\n' % ml_method_name(name)) + ml_native.write(' = "n_%s"\n\n' % ml_method_name(name)) # Exception wrappers for name, result, params in _dotnet_decls: ml_native.write(' let %s ' % ml_method_name(name)) @@ -1128,25 +1132,28 @@ def mk_ml(): ml_native.write(' ') if result != VOID: ml_native.write('let res = ') - ml_native.write('n_%s(' % (ml_method_name(name))) - first = True - i = 0; - for param in params: - if first: - first = False - else: - ml_native.write(', ') - ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(')') + if len(params) == 0: + ml_native.write('n_%s()' % (ml_method_name(name))) + else: + ml_native.write('(n_%s ' % (ml_method_name(name))) + first = True + i = 0; + for param in params: + if first: + first = False + else: + ml_native.write(' ') + ml_native.write('a%d' % i) + i = i + 1 + ml_native.write(')') if result != VOID: ml_native.write(' in\n') else: ml_native.write(';\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = error_code.fromInt(n_get_error_code(a0)) in \n') - ml_native.write(' if err <> Z3_enums.OK then\n') - ml_native.write(' raise (z3_exception n_get_error_msg_ex(a0, err.toInt()))\n') + ml_native.write(' let err = (Enumerations.int2error_code (n_get_error_code a0)) in \n') + ml_native.write(' if err <> Enumerations.OK then\n') + ml_native.write(' raise (Exception (n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') From c4f07c7fd179313ff57b73b7336e64bc39854aa3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:34:36 +0000 Subject: [PATCH 373/646] New native ML API layer. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 36 ++-- scripts/update_api.py | 400 +++++++++++++++++++++++++++--------------- 2 files changed, 289 insertions(+), 147 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index bd6495d1b..33129f555 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1428,20 +1428,30 @@ class MLComponent(Component): if IS_WINDOWS: out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') out.write('\n\n') + deffile = open('%s.mllib' % os.path.join(self.src_dir, "z3"), 'w') + for mlfile in get_ml_files(self.src_dir): + deffile.write('%s\n' % (string.upper(mlfile[0]) + mlfile[1:-3])) + deffile.close() bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') mk_dir(bld_dir) - libfile = '%s$(LIB_EXT)' % self.lib_name + libfile = '%s$(SO_EXT)' % self.lib_name + # for mlfile in get_ml_files(self.src_dir): + # out.write('%si: libz3$(SO_EXT) %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) + # out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) + # out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) + out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) for mlfile in get_ml_files(self.src_dir): - out.write('%si: %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) - out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) - out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) - out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'native.c'))) - for mlfile in get_ml_files(self.src_dir): - out.write(' %si' % os.path.join('api','ml', mlfile)) + out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3_native$(OBJ_EXT) -I%s %s/native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3ml$(LIB_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % os.path.join('api', 'ml', 'native')) - out.write('ml: %s\n' % libfile) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + out.write('z3.cmxa: %s\n' % libfile) + out.write('\tcd %s && ocamlbuild -lflags -cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cmxa && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) + out.write('\tcp api/ml/z3.cmxa .\n') + out.write('z3.cma: %s\n' % libfile) + out.write('\tcd %s && ocamlbuild -lflags -custom,-cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) + out.write('\tcp api/ml/z3.cma .\n') + out.write('ml: z3.cmxa z3.cma\n') out.write('\n') def main_component(self): @@ -2728,6 +2738,7 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') @@ -2823,6 +2834,11 @@ def mk_z3consts_ml(api_files): efile.write('(* Automatically generated file *)\n\n') efile.write('module Enumerations = struct\n') >>>>>>> More ML API +======= + efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') + efile.write('(* Automatically generated file *)\n\n') + efile.write('module Z3enums = struct\n') +>>>>>>> New native ML API layer. for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) diff --git a/scripts/update_api.py b/scripts/update_api.py index 971e6eab1..f142c8ec1 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1073,98 +1073,145 @@ def mk_bindings(): def ml_method_name(name): return name[3:] # Remove Z3_ +def is_out_param(p): + if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + return True + else: + return False + +def outparams(params): + op = [] + for param in params: + if is_out_param(param): + op.append(param) + return op + +def is_in_param(p): + if param_kind(p) == IN or param_kind(p) == INOUT or param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY: + return True + else: + return False + +def inparams(params): + ip = [] + for param in params: + if is_in_param(param): + ip.append(param) + return ip + +def is_array_param(p): + if param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_ARRAY: + return True + else: + return False + def mk_ml(): if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir - ml_nativef = os.path.join(ml_dir, 'z3.ml') - ml_wrapperf = os.path.join(ml_dir, 'native.c') + ml_nativef = os.path.join(ml_dir, 'z3native.ml') + ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') - ml_native.write('open Enumerations\n\n') - ml_native.write('module Z3 = struct\n\n') - ml_native.write('type context\n') - ml_native.write('and symbol\n') - ml_native.write('and ast\n') - ml_native.write('and sort = private ast\n') - ml_native.write('and func_decl = private ast\n') - ml_native.write('and app = private ast\n') - ml_native.write('and pattern = private ast\n') - ml_native.write('and params\n') - ml_native.write('and param_descrs\n') - ml_native.write('and model\n') - ml_native.write('and func_interp\n') - ml_native.write('and func_entry\n') - ml_native.write('and fixedpoint\n') - ml_native.write('and ast_vector\n') - ml_native.write('and ast_map\n') - ml_native.write('and goal\n') - ml_native.write('and tactic\n') - ml_native.write('and probe\n') - ml_native.write('and apply_result\n') - ml_native.write('and solver\n') - ml_native.write('and stats\n') - ml_native.write('\n') + ml_native.write('open Z3enums\n\n') + ml_native.write('module Z3native = struct\n\n') + ml_native.write(' type context\n') + ml_native.write(' and symbol\n') + ml_native.write(' and ast\n') + ml_native.write(' and sort = private ast\n') + ml_native.write(' and func_decl = private ast\n') + ml_native.write(' and app = private ast\n') + ml_native.write(' and pattern = private ast\n') + ml_native.write(' and params\n') + ml_native.write(' and param_descrs\n') + ml_native.write(' and model\n') + ml_native.write(' and func_interp\n') + ml_native.write(' and func_entry\n') + ml_native.write(' and fixedpoint\n') + ml_native.write(' and ast_vector\n') + ml_native.write(' and ast_map\n') + ml_native.write(' and goal\n') + ml_native.write(' and tactic\n') + ml_native.write(' and probe\n') + ml_native.write(' and apply_result\n') + ml_native.write(' and solver\n') + ml_native.write(' and stats\n\n') ml_native.write(' exception Exception of string\n\n') + + # ML declarations + ml_native.write(' module ML2C = struct\n\n') for name, result, params in _dotnet_decls: - ml_native.write(' external n_%s : ' % ml_method_name(name)) - i = 0; - for param in params: - ml_native.write('%s -> ' % param2ml(param)) - i = i + 1 - if len(params) == 0: + ml_native.write(' external n_%s : ' % ml_method_name(name)) + ip = inparams(params) + op = outparams(params) + if len(ip) == 0: ml_native.write(' unit -> ') - ml_native.write('%s\n' % (type2ml(result))) - ml_native.write(' = "n_%s"\n\n' % ml_method_name(name)) + for p in ip: + ml_native.write('%s -> ' % param2ml(p)) + if len(op) > 0: + ml_native.write('(') + ml_native.write('%s' % type2ml(result)) + for p in op: + ml_native.write(' * %s' % param2ml(p)) + if len(op) > 0: + ml_native.write(')') + ml_native.write('\n') + ml_native.write(' = "n_%s"\n' % ml_method_name(name)) + if len(ip) > 5: + ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write('\n') + ml_native.write(' end\n\n') + # Exception wrappers for name, result, params in _dotnet_decls: - ml_native.write(' let %s ' % ml_method_name(name)) + ip = inparams(params) + op = outparams(params) + ml_native.write(' let %s ' % ml_method_name(name)) first = True i = 0; - for param in params: - if first: - first = False; - else: - ml_native.write(' ') - ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(' = \n') - ml_native.write(' ') - if result != VOID: - ml_native.write('let res = ') - if len(params) == 0: - ml_native.write('n_%s()' % (ml_method_name(name))) - else: - ml_native.write('(n_%s ' % (ml_method_name(name))) - first = True - i = 0; - for param in params: + for p in params: + if is_in_param(p): if first: - first = False + first = False; else: ml_native.write(' ') ml_native.write('a%d' % i) - i = i + 1 - ml_native.write(')') - if result != VOID: - ml_native.write(' in\n') + i = i + 1 + ml_native.write(' = \n') + ml_native.write(' ') + if result == VOID: + ml_native.write('let _ = ') else: - ml_native.write(';\n') + ml_native.write('let res = ') + ml_native.write('(ML2C.n_%s' % (ml_method_name(name))) + first = True + i = 0; + for p in params: + if is_in_param(p): + ml_native.write(' a%d' % i) + i = i + 1 + ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (Enumerations.int2error_code (n_get_error_code a0)) in \n') - ml_native.write(' if err <> Enumerations.OK then\n') - ml_native.write(' raise (Exception (n_get_error_msg_ex a0 (error_code2int err)))\n') + ml_native.write(' let err = (Z3enums.int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' if err <> Z3enums.OK then\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (Z3enums.error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') else: ml_native.write(' res\n') ml_native.write('\n') - ml_native.write('\nend\n') + + ml_native.write('end\n') + + # C interface ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') ml_wrapper.write('#include \n') - ml_wrapper.write('#include \n') + ml_wrapper.write('#include \n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('extern "C" {\n') + ml_wrapper.write('#endif\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') @@ -1173,61 +1220,119 @@ def mk_ml(): ml_wrapper.write('#ifdef Custom_tag\n') ml_wrapper.write('#include \n') ml_wrapper.write('#include \n') + ml_wrapper.write('#endif\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('}\n') ml_wrapper.write('#endif\n\n') ml_wrapper.write('#include \n\n') + ml_wrapper.write('#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal1(X6); \n') + ml_wrapper.write('#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal2(X6,X7); \n') + ml_wrapper.write('#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') + ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLlocal3(X6,X7,X8); \n') + ml_wrapper.write('\n') + ml_wrapper.write('#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam2(X6,X7); \n') + ml_wrapper.write('#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam3(X6,X7,X8); \n') + ml_wrapper.write('#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9); \n') + ml_wrapper.write('#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') + ml_wrapper.write(' CAMLxparam2(X11,X12); \n') + ml_wrapper.write('#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \\\n') + ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') + ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') + ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') + ml_wrapper.write('\n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('extern "C" {\n') + ml_wrapper.write('#endif\n\n') for name, result, params in _dotnet_decls: - #return type = type2ml(result) + ip = inparams(params) + op = outparams(params) + ret_size = len(op) + if result != VOID: + ret_size = ret_size + 1 + + # Setup frame + n_locals = 0 + for p in params: + if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): + n_locals = n_locals + 1 ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) first = True i = 0 - for param in params: - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('value a%d' % i) - # param type = param2ml(param) + for p in params: + if is_in_param(p): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('value a%d' % i) i = i + 1 ml_wrapper.write(') {\n') - ml_wrapper.write(' CAMLparam%d(' % len(params)) + ml_wrapper.write(' CAMLparam%d(' % len(ip)) i = 0 first = True - for param in params: - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('a%d' % i) + for p in params: + if is_in_param(p): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('a%d' % i) i = i + 1 ml_wrapper.write(');\n') + i = 0 + first = True + if result != VOID: + n_locals = n_locals + 1 + if ret_size > 1: + n_locals = n_locals + 1 + if n_locals > 0: + ml_wrapper.write(' CAMLlocal%s(' % (n_locals)) + if ret_size > 1: + if result != VOID: + ml_wrapper.write('result, ') + ml_wrapper.write('result_tuple') + first = False + elif result != VOID: + ml_wrapper.write('result') + first = False + for p in params: + if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): + if first: + first = False + else: + ml_wrapper.write(', ') + ml_wrapper.write('_a%s' % i) + i = i + 1 + ml_wrapper.write(');\n') + # preprocess arrays, strings, in/out arguments i = 0 for param in params: - k = param_kind(param) - if k == OUT or k == INOUT: - ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) - elif k == IN_ARRAY or k == INOUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' %s * _a%s = (%s*) jenv->GetIntArrayElements(a%s, NULL);\n' % (type2str(param_type(param)), i, type2str(param_type(param)), i)) - else: - ml_wrapper.write(' GETLONGAELEMS(%s, a%s, _a%s);\n' % (type2str(param_type(param)), i, i)) - elif k == OUT_ARRAY: - ml_wrapper.write(' %s * _a%s = (%s *) malloc(((unsigned)a%s) * sizeof(%s));\n' % (type2str(param_type(param)), - i, - type2str(param_type(param)), - param_array_capacity_pos(param), - type2str(param_type(param)))) - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - else: - ml_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) - elif k == IN and param_type(param) == STRING: - ml_wrapper.write(' Z3_string _a%s = (Z3_string) String_val(a%s);\n' % (i, i)) + if param_kind(param) == OUT_ARRAY: + ml_wrapper.write(' _a%s = (long) malloc(sizeof(%s) * ((long)a%s));\n' % (i, + type2str(param_type(param)), + param_array_capacity_pos(param))) + elif param_kind(param) == IN and param_type(param) == STRING: + ml_wrapper.write(' _a%s = (value) String_val(a%s);\n' % (i, i)) i = i + 1 + # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('%s result = ' % type2str(result)) + ml_wrapper.write('result = (value) ') ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1238,53 +1343,74 @@ def mk_ml(): ml_wrapper.write(', ') k = param_kind(param) if k == OUT or k == INOUT: - ml_wrapper.write('&_a%s' % i) - elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: - ml_wrapper.write('_a%s' % i) + ml_wrapper.write('(%s)&_a%s' % (param2str(param), i)) + elif k == INOUT_ARRAY or k == IN_ARRAY: + ml_wrapper.write('(%s*)a%s' % (type2str(param_type(param)), i)) + elif k == OUT_ARRAY: + ml_wrapper.write('(%s*)_a%s' % (type2str(param_type(param)), i)) elif k == IN and param_type(param) == STRING: - ml_wrapper.write('_a%s' % i) + ml_wrapper.write('(Z3_string) _a%s' % i) else: ml_wrapper.write('(%s)a%i' % (param2str(param), i)) i = i + 1 ml_wrapper.write(');\n') - # cleanup - i = 0 - for param in params: - k = param_kind(param) - if k == OUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->SetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) - else: - ml_wrapper.write(' SETLONGAREGION(a%s, 0, a%s, _a%s);\n' % (i, param_array_capacity_pos(param), i)) - ml_wrapper.write(' free(_a%s);\n' % i) - elif k == IN_ARRAY or k == OUT_ARRAY: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' jenv->ReleaseIntArrayElements(a%s, (jint*)_a%s, JNI_ABORT);\n' % (i, i)) - else: - ml_wrapper.write(' RELEASELONGAELEMS(a%s, _a%s);\n' % (i, i)) - elif k == OUT or k == INOUT: - if param_type(param) == INT or param_type(param) == UINT: - ml_wrapper.write(' {\n') - ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "I");\n') - ml_wrapper.write(' jenv->SetIntField(a%s, fid, (jint) _a%s);\n' % (i, i)) - ml_wrapper.write(' }\n') + # return tuples + if len(op) > 0: + ml_wrapper.write(' result_tuple = caml_alloc(%s, 0);\n' % ret_size) + i = j = 0 + if result != VOID: + if result == STRING: + ml_wrapper.write(' Store_field(result_tuple, 0, caml_copy_string(result));\n') else: - ml_wrapper.write(' {\n') - ml_wrapper.write(' jclass mc = jenv->GetObjectClass(a%s);\n' % i) - ml_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') - ml_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) - ml_wrapper.write(' }\n') + ml_wrapper.write(' Store_field(result_tuple, 0, result);\n') + j = j + 1 + for p in params: + if param_kind(p) == OUT_ARRAY or param_kind(p) == OUT: + ml_wrapper.write(' Store_field(result_tuple, %s, _a%s);\n' % (j, i)) + j = j + 1; + elif is_out_param(p): + if param_type(p) == STRING: + ml_wrapper.write(' Store_field(result_tuple, %s, caml_copy_string((const char *)_a%s));\n' % (j, i)) + else: + ml_wrapper.write(' Store_field(result_tuple, %s, a%s);\n' % (j, i)) + j = j + 1; + i = i + 1 + + # local array cleanup + i = 0 + for p in params: + if param_kind(p) == OUT_ARRAY: + ml_wrapper.write(' free((long*)_a%s);\n' % i) i = i + 1 + # return - if result == STRING: - ml_wrapper.write(' return caml_copy_string(result);\n') - elif result == VOID: - ml_wrapper.write(' CAMLreturn(Val_unit);\n') - elif result != VOID: - ml_wrapper.write(' return (value) result;\n') + if len(op) > 0: + ml_wrapper.write(' CAMLreturn(result_tuple);\n') + else: + if result == STRING: + ml_wrapper.write(' CAMLreturn(caml_copy_string((const char*) result));\n') + elif result == VOID: + ml_wrapper.write(' CAMLreturn(Val_unit);\n') + elif result != VOID: + ml_wrapper.write(' CAMLreturn(result);\n') + ml_wrapper.write('}\n\n') + if len(ip) > 5: + ml_wrapper.write('CAMLprim value n_%s_bytecode(value * argv, int argn) {\n' % ml_method_name(name)) + ml_wrapper.write(' return n_%s(' % ml_method_name(name)) + i = 0 + while i < len(ip): + if i == 0: + ml_wrapper.write('argv[0]') + else: + ml_wrapper.write(', argv[%s]' % i) + i = i + 1 + ml_wrapper.write(');\n}\n') + ml_wrapper.write('\n\n') + ml_wrapper.write('#ifdef __cplusplus\n') + ml_wrapper.write('}\n') + ml_wrapper.write('#endif\n') if is_verbose(): print "Generated '%s'" % ml_nativef From 1ef9013c8ed4020847bdbccdf17828c3b4338d85 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:37:32 +0000 Subject: [PATCH 374/646] More new ML API. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2751 +--------------------------------------------- 1 file changed, 5 insertions(+), 2746 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 350457525..5251a8767 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,2752 +1,11 @@ -(** - The Z3 ML/OCaml Interface. - - Copyright (C) 2012 Microsoft Corporation - @author CM Wintersteiger (cwinter) 2012-12-17 +(* + Author: CM Wintersteiger + (C) Microsoft Research, 2012 *) open Z3enums +open Z3native -exception Error = Z3native.Exception - -(* Some helpers. *) -let null = Z3native.mk_null() -let is_null o = (Z3native.is_null o) - -(* Internal types *) -type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } -type context = z3_native_context - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - -(** Internal stuff *) -module Internal = -struct - let dispose_context ctx = - if ctx.m_n_obj_cnt == 0 then ( - (Z3native.del_context ctx.m_n_ctx) - ) else ( - Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; - ) - - let create_context settings = - let cfg = Z3native.mk_config () in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - Z3native.set_internal_error_handler v ; - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> dispose_context o in - Gc.finalise f res; - res - - let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) - let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) - let context_gno ctx = ctx.m_n_ctx - - - let z3obj_gc o = o.m_ctx - let z3obj_gnc o = (context_gno o.m_ctx) - - let z3obj_gno o = o.m_n_obj - let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - - let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - - let z3obj_create o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - - let z3obj_nil_ref x y = () - - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> - let res : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res -end - -open Internal - -module Log = -struct - let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - let close = Z3native.close_log - let append s = Z3native.append_log s -end - - -module Version = -struct - let major = let (x, _, _, _) = Z3native.get_version () in x - let minor = let (_, x, _, _) = Z3native.get_version () in x - let build = let (_, _, x, _) = Z3native.get_version () in x - let revision = let (_, _, _, x) = Z3native.get_version () in x - let to_string = - let (mj, mn, bld, rev) = Z3native.get_version () in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev -end - - -let mk_list ( f : int -> 'a ) ( n : int ) = - let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = - if (i >= n) then - tail - else - (f i) :: (mk_list' f (i+1) n tail) - in - mk_list' f 0 n [] - -let list_of_array ( x : _ array ) = - let f i = (Array.get x i) in - mk_list f (Array.length x) - -let mk_context ( cfg : ( string * string ) list ) = - create_context cfg - - -module Symbol = -struct - type symbol = z3_native_object - - let create_i ( ctx : context ) ( no : Z3native.ptr ) = - let res : symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create_s ( ctx : context ) ( no : Z3native.ptr ) = - let res : symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> (create_i ctx no) - | STRING_SYMBOL -> (create_s ctx no) - - let gc ( x : symbol ) = (z3obj_gc x) - let gnc ( x : symbol ) = (z3obj_gnc x) - let gno ( x : symbol ) = (z3obj_gno x) - - let symbol_lton ( a : symbol list ) = - let f ( e : symbol ) = (gno e) in - Array.of_list (List.map f a) - - let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) - let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL - let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - let get_int (o : symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - let get_string (o : symbol ) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) - let to_string ( o : symbol ) = - match (kind o) with - | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) - | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) - - let mk_int ( ctx : context ) ( i : int ) = - (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) - - let mk_string ( ctx : context ) ( s : string ) = - (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - - let mk_ints ( ctx : context ) ( names : int list ) = - let f elem = mk_int ( ctx : context ) elem in - (List.map f names) - - let mk_strings ( ctx : context ) ( names : string list ) = - let f elem = mk_string ( ctx : context ) elem in - (List.map f names) -end - - -module AST = -struct - type ast = z3_native_object - - let context_of_ast ( x : ast ) = (z3obj_gc x) - let nc_of_ast ( x : ast ) = (z3obj_gnc x) - let ptr_of_ast ( x : ast ) = (z3obj_gno x) - - let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST - | SORT_AST - | QUANTIFIER_AST - | APP_AST - | NUMERAL_AST - | VAR_AST -> z3_native_object_of_ast_ptr ctx no - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") - - module ASTVector = - struct - type ast_vector = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_vector = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_vector_inc_ref ; - dec_ref = Z3native.ast_vector_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let mk_ast_vector ( ctx : context ) = (create ctx (Z3native.mk_ast_vector (context_gno ctx))) - - let get_size ( x : ast_vector ) = - Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) - - let get ( x : ast_vector ) ( i : int ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) - - let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) - - let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size - - let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) - - let translate ( x : ast_vector ) ( to_ctx : context ) = - create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) - end - - module ASTMap = - struct - type ast_map = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_map = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_map_inc_ref ; - dec_ref = Z3native.ast_map_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let mk_ast_map ( ctx : context ) = (create ctx (Z3native.mk_ast_map (context_gno ctx))) - - let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_map = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_map_inc_ref ; - dec_ref = Z3native.ast_map_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let contains ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let find ( x : ast_map ) ( key : ast ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - - let insert ( x : ast_map ) ( key : ast ) ( value : ast ) = - Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) - - let erase ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let reset ( x : ast_map ) = - Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : ast_map ) = - Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) - - let get_keys ( x : ast_map ) = - let av = ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in - let f i = (ASTVector.get av i) in - mk_list f (ASTVector.get_size av) - - let to_string ( x : ast_map ) = - Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let hash ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) - let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) - let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) - - let is_expr ( x : ast ) = - match get_ast_kind ( x : ast ) with - | APP_AST - | NUMERAL_AST - | QUANTIFIER_AST - | VAR_AST -> true - | _ -> false - - let is_app ( x : ast ) = (get_ast_kind x) == APP_AST - let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST - let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST - let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST - let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST - - let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - - - let equal ( a : ast ) ( b : ast ) = (a == b) || - if (z3obj_gnc a) != (z3obj_gnc b) then - false - else - Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) - - let compare a b = - if (get_id a) < (get_id b) then -1 else - if (get_id a) > (get_id b) then 1 else - 0 - - let translate ( x : ast ) ( to_ctx : context ) = - if (z3obj_gnc x) == (context_gno to_ctx) then - x - else - ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let unwrap_ast ( x : ast ) = (z3obj_gno x) - let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr -end - -open AST - - -module Sort = -struct - type sort = Sort of AST.ast - - let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> - let q = (z3_native_object_of_ast_ptr ctx no) in - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then - raise (Z3native.Exception "Invalid coercion") - else - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - - let ast_of_sort s = match s with Sort(x) -> x - - let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) - let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) - let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - - let sort_lton ( a : sort list ) = - let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let sort_option_lton ( a : sort option list ) = - let f ( e : sort option ) = match e with None -> null | Some(Sort(a)) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let equal : sort -> sort -> bool = fun a b -> - (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) - - - let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) - let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) - let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) - let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) - - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; - (z3obj_create res) ; - Sort(res) - - let mk_uninterpreted_s ( ctx : context ) ( s : string ) = - mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) -end - -open Sort - - -module rec FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - val func_decl_of_ptr : context -> Z3native.ptr -> func_decl - val gc : func_decl -> context - val gnc : func_decl -> Z3native.ptr - val gno : func_decl -> Z3native.ptr - module Parameter : - sig - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - val get_kind : parameter -> Z3enums.parameter_kind - val get_int : parameter -> int - val get_float : parameter -> float - val get_symbol : parameter -> Symbol.symbol - val get_sort : parameter -> Sort.sort - val get_ast : parameter -> AST.ast - val get_func_decl : parameter -> func_decl - val get_rational : parameter -> string - end - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - val equal : func_decl -> func_decl -> bool - val to_string : func_decl -> string - val get_id : func_decl -> int - val get_arity : func_decl -> int - val get_domain_size : func_decl -> int - val get_domain : func_decl -> Sort.sort list - val get_range : func_decl -> Sort.sort - val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_name : func_decl -> Symbol.symbol - val get_num_parameters : func_decl -> int - val get_parameters : func_decl -> Parameter.parameter list - val apply : func_decl -> Expr.expr list -> Expr.expr -end = struct - type func_decl = FuncDecl of AST.ast - - let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - FuncDecl(z3_native_object_of_ast_ptr ctx no) - - let ast_of_func_decl f = match f with FuncDecl(x) -> x - - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) - let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) - let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - - module Parameter = - struct - type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - let get_kind ( x : parameter ) = - (match x with - | P_Int(_) -> PARAMETER_INT - | P_Dbl(_) -> PARAMETER_DOUBLE - | P_Sym(_) -> PARAMETER_SYMBOL - | P_Srt(_) -> PARAMETER_SORT - | P_Ast(_) -> PARAMETER_AST - | P_Fdl(_) -> PARAMETER_FUNC_DECL - | P_Rat(_) -> PARAMETER_RATIONAL) - - let get_int ( x : parameter ) = - match x with - | P_Int(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an int") - - let get_float ( x : parameter ) = - match x with - | P_Dbl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a float") - - let get_symbol ( x : parameter ) = - match x with - | P_Sym(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a symbol") - - let get_sort ( x : parameter ) = - match x with - | P_Srt(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a sort") - - let get_ast ( x : parameter ) = - match x with - | P_Ast(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an ast") - - let get_func_decl ( x : parameter ) = - match x with - | P_Fdl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a func_decl") - - let get_rational ( x : parameter ) = - match x with - | P_Rat(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a rational string") - end - - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - create_ndr ctx name domain range - - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = - mk_func_decl ctx (Symbol.mk_string ctx name) domain range - - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - create_pdr ctx prefix domain range - - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_ndr ctx name [] range - - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = - create_ndr ctx (Symbol.mk_string ctx name) [] range - - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = - create_pdr ctx prefix [] range - - - let equal ( a : func_decl ) ( b : func_decl ) = (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) - - let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) - - let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) - - let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) - - let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) - - let get_domain ( x : func_decl ) = - let n = (get_domain_size x) in - let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in - mk_list f n - - let get_range ( x : func_decl ) = - sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) - - let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) - - let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) - - let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) - - let get_parameters ( x : func_decl ) = - let n = (get_num_parameters x) in - let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) - ) in - mk_list f n - - let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args -end - - -and Params : -sig - type params = z3_native_object - module ParamDescrs : - sig - type param_descrs - val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - val get_names : param_descrs -> Symbol.symbol list - val get_size : param_descrs -> int - val to_string : param_descrs -> string - end - val add_bool : params -> Symbol.symbol -> bool -> unit - val add_int : params -> Symbol.symbol -> int -> unit - val add_float : params -> Symbol.symbol -> float -> unit - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - val mk_params : context -> params - val to_string : params -> string - - val update_param_value : context -> string -> string -> unit - val set_print_mode : context -> Z3enums.ast_print_mode -> unit -end = struct - type params = z3_native_object - - module ParamDescrs = - struct - type param_descrs = z3_native_object - - let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : param_descrs = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.param_descrs_inc_ref ; - dec_ref = Z3native.param_descrs_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let validate ( x : param_descrs ) ( p : params ) = - Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) - - let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) - - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in - let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = - Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = - Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_float ( x : params ) ( name : Symbol.symbol ) ( value : float ) = - Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = - Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - - let mk_params ( ctx : context ) = - let res : params = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.params_inc_ref ; - dec_ref = Z3native.params_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; - (z3obj_create res) ; - res - - let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) - - let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value (context_gno ctx) id value - - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) -end - -(** General expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - val expr_of_ptr : context -> Z3native.ptr -> expr - val gc : expr -> context - val gnc : expr -> Z3native.ptr - val gno : expr -> Z3native.ptr - val expr_lton : expr list -> Z3native.ptr array - val ast_of_expr : expr -> AST.ast - val expr_of_ast : AST.ast -> expr - val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr - val simplify : expr -> Params.params option -> expr - val get_simplify_help : context -> string - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - val get_func_decl : expr -> FuncDecl.func_decl - val get_num_args : expr -> int - val get_args : expr -> expr list - val update : expr -> expr list -> expr - val substitute : expr -> expr list -> expr list -> expr - val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr list -> expr - val translate : expr -> context -> expr - val to_string : expr -> string - val is_numeral : expr -> bool - val is_well_sorted : expr -> bool - val get_sort : expr -> Sort.sort - val is_const : expr -> bool - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - val mk_const_s : context -> string -> Sort.sort -> expr - val mk_const_f : context -> FuncDecl.func_decl -> expr - val mk_fresh_const : context -> string -> Sort.sort -> expr - val mk_app : context -> FuncDecl.func_decl -> expr list -> expr - val mk_numeral_string : context -> string -> Sort.sort -> expr - val mk_numeral_int : context -> int -> Sort.sort -> expr - val equal : expr -> expr -> bool - val compare : expr -> expr -> int -end = struct - type expr = Expr of AST.ast - - let gc e = match e with Expr(a) -> (z3obj_gc a) - let gnc e = match e with Expr(a) -> (z3obj_gnc a) - let gno e = match e with Expr(a) -> (z3obj_gno a) - - let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then - Expr(z3_native_object_of_ast_ptr ctx no) - else - let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) no) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT || sk == REAL_SORT || sk == BV_SORT) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - raise (Z3native.Exception "Unsupported numeral object") - else - Expr(z3_native_object_of_ast_ptr ctx no) - - let expr_of_ast a = - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Expr(a) - - let ast_of_expr e = match e with Expr(a) -> a - - let expr_lton ( a : expr list ) = - let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> - match f with FuncDecl.FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in - expr_of_ptr ctx o - - let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (gnc x) (gno x)) - | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) - - let get_simplify_help ( ctx : context ) = - Z3native.simplify_get_help (context_gno ctx) - - let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) - - let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) - - let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in - mk_list f n - - let update ( x : expr ) ( args : expr list ) = - if ((AST.is_app (ast_of_expr x)) && (List.length args <> (get_num_args x))) then - raise (Z3native.Exception "Number of arguments does not match") - else - expr_of_ptr (Expr.gc x) (Z3native.update_term (gnc x) (gno x) (List.length args) (expr_lton args)) - - let substitute ( x : expr ) from to_ = - if (List.length from) <> (List.length to_) then - raise (Z3native.Exception "Argument sizes do not match") - else - expr_of_ptr (Expr.gc x) (Z3native.substitute (gnc x) (gno x) (List.length from) (expr_lton from) (expr_lton to_)) - - let substitute_one ( x : expr ) from to_ = - substitute ( x : expr ) [ from ] [ to_ ] - - let substitute_vars ( x : expr ) to_ = - expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (gnc x) (gno x) (List.length to_) (expr_lton to_)) - - let translate ( x : expr ) to_ctx = - if (Expr.gc x) == to_ctx then - x - else - expr_of_ptr to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) - - let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) - - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) - - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) - - let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) - - let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && - (get_num_args x) == 0 && - (FuncDecl.get_domain_size (get_func_decl x)) == 0 - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) - - let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) range - - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] - - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args - - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) - - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) - - let equal ( a : expr ) ( b : expr ) = AST.equal (ast_of_expr a) (ast_of_expr b) - - let compare a b = AST.compare (ast_of_expr a) (ast_of_expr b) -end - -open FuncDecl -open Expr - -module Boolean = -struct - let mk_sort ( ctx : context ) = - (sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - (Expr.mk_const ctx name (mk_sort ctx)) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_true ( ctx : context ) = - expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) - - let mk_false ( ctx : context ) = - expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) - - let mk_val ( ctx : context ) ( value : bool ) = - if value then mk_true ctx else mk_false ctx - - let mk_not ( ctx : context ) ( a : expr ) = - expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - - let mk_ite ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( t3 : expr ) = - expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - - let mk_iff ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - - let mk_implies ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - - let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - - let mk_and ( ctx : context ) ( args : expr list ) = - let f x = (Expr.gno (x)) in - expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - - let mk_or ( ctx : context ) ( args : expr list ) = - let f x = (Expr.gno (x)) in - expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) - - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) - - let mk_distinct ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) - - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) - - let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (gnc x) - (Z3native.mk_bool_sort (gnc x)) - (Z3native.get_sort (gnc x) (gno x))) - - let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) -end - - -module Quantifier = -struct - type quantifier = Quantifier of expr - - let expr_of_quantifier e = match e with Quantifier(x) -> x - - let quantifier_of_expr e = - match e with Expr.Expr(a) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.QUANTIFIER_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Quantifier(e) - - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - - module Pattern = - struct - type pattern = Pattern of ast - - let ast_of_pattern e = match e with Pattern(x) -> x - - let pattern_of_ast a = - (* CMW: Unchecked ok? *) - Pattern(a) - - let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) - let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) - let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - mk_list f n - - let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) - end - - let get_index ( x : expr ) = - if not (AST.is_var (match x with Expr.Expr(a) -> a)) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value (Expr.gnc x) (Expr.gno x) - - let is_universal ( x : quantifier ) = - Z3native.is_quantifier_forall (gnc x) (gno x) - - let is_existential ( x : quantifier ) = not (is_universal x) - - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) - - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) - - let get_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) - - let get_no_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) - - let get_bound_variable_names ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in - mk_list f n - - let get_bound_variable_sorts ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in - mk_list f n - - let get_body ( x : quantifier ) = - expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) - - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - - let mk_pattern ( ctx : context ) ( terms : expr list ) = - if (List.length terms) == 0 then - raise (Z3native.Exception "Cannot create a pattern from zero terms") - else - Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) - - let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - else - (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id - else - mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id - - let to_string ( x : quantifier ) = (Expr.to_string (expr_of_quantifier x)) -end - - -module Z3Array = -struct - let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - - let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - let is_constant_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - let is_default_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - let is_array_map ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - let is_as_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) - let is_array ( x : expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) - - let get_domain ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_domain (Sort.gnc x) (Sort.gno x)) - let get_range ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_range (Sort.gnc x) (Sort.gno x)) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - (Expr.mk_const ctx name (mk_sort ctx domain range)) - - let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) domain range - - let mk_select ( ctx : context ) ( a : expr ) ( i : expr ) = - expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (Expr.gno a) (Expr.gno i)) - - let mk_store ( ctx : context ) ( a : expr ) ( i : expr ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (Expr.gno a) (Expr.gno i) (Expr.gno v)) - - let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) - - let mk_map ( ctx : context ) ( f : func_decl ) ( args : expr list ) = - let m x = (Expr.gno x) in - expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) - - let mk_term_array ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (Expr.gno arg)) -end - - -module Set = -struct - let mk_sort ( ctx : context ) ( ty : sort ) = - sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - - let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - let is_intersect ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - let is_difference ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - let is_subset ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) - - - let mk_empty ( ctx : context ) ( domain : sort ) = - (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) - - let mk_full ( ctx : context ) ( domain : sort ) = - expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) - - let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_union ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_intersection ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) - - let mk_complement ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) - - let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) - - let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) +module Z3 = struct end - - -module FiniteDomain = -struct - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) - - let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_sort ctx (Symbol.mk_string ctx name) size - - let is_finite_domain ( x : expr ) = - let nc = (Expr.gnc x) in - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) - - let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - - let get_size ( x : sort ) = - let (r, v) = (Z3native.get_finite_domain_sort_size (Sort.gnc x) (Sort.gno x)) in - if r then v - else raise (Z3native.Exception "Conversion failed.") -end - - -module Relation = -struct - let is_relation ( x : expr ) = - let nc = (Expr.gnc x) in - ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) - - let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - let is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - let is_is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - let is_join ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - let is_widen ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - let is_project ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - let is_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - let is_negation_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - let is_rename ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - let is_clone ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - - let get_arity ( x : sort ) = Z3native.get_relation_arity (Sort.gnc x) (Sort.gno x) - - let get_column_sorts ( x : sort ) = - let n = get_arity x in - let f i = (sort_of_ptr (Sort.gc x) (Z3native.get_relation_column (Sort.gnc x) (Sort.gno x) i)) in - mk_list f n -end - - -module Datatype = -struct - module Constructor = - struct - type constructor = z3_native_object - - module FieldNumTable = Hashtbl.Make(struct - type t = AST.ast - let equal x y = AST.compare x y = 0 - let hash = AST.hash - end) - - let _field_nums = FieldNumTable.create 0 - - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = - let n = (List.length field_names) in - if n != (List.length sorts) then - raise (Z3native.Exception "Number of field names does not match number of sorts") - else - if n != (List.length sort_refs) then - raise (Z3native.Exception "Number of field names does not match number of sort refs") - else - let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) - (Symbol.gno recognizer) - n - (Symbol.symbol_lton field_names) - (sort_option_lton sorts) - (Array.of_list sort_refs)) in - let no : constructor = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - (z3obj_sno no ctx ptr) ; - (z3obj_create no) ; - let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f no ; - FieldNumTable.add _field_nums no n ; - no - - let get_num_fields ( x : constructor ) = FieldNumTable.find _field_nums x - - let get_constructor_decl ( x : constructor ) = - let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) a - - let get_tester_decl ( x : constructor ) = - let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) b - - let get_accessor_decls ( x : constructor ) = - let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in - mk_list f (Array.length c) - - end - - module ConstructorList = - struct - type constructor_list = z3_native_object - - let create ( ctx : context ) ( c : Constructor.constructor list ) = - let res : constructor_list = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - let f x =(z3obj_gno x) in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; - (z3obj_create res) ; - let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f res; - res - end - - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = - Constructor.create ctx name recognizer field_names sorts sort_refs - - - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = - mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = - let f x = (z3obj_gno x) in - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in - sort_of_ptr ctx x - - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = - mk_sort ctx (Symbol.mk_string ctx name) constructors - - let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = - let n = (List.length names) in - let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in - let cla = (Array.of_list (List.map f c)) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in - let g i = (sort_of_ptr ctx (Array.get r i)) in - mk_list g (Array.length r) - - let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = - mk_sorts ctx - ( - let f e = (Symbol.mk_string ctx e) in - List.map f names - ) - c - - let get_num_constructors ( x : sort ) = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) - - let get_constructors ( x : sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in - mk_list f n - - let get_recognizers ( x : sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i) in - mk_list f n - - let get_accessors ( x : sort ) = - let n = (get_num_constructors x) in - let f i = ( - let fd = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in - let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) i j) in - mk_list g ds - ) in - mk_list f n -end - - -module Enumeration = -struct - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = - let (a, _, _) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in - sort_of_ptr ctx a - - let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = - mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - - let get_const_decls ( x : sort ) = - let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in - let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i)) in - mk_list f n - - let get_tester_decls ( x : sort ) = - let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in - let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i)) in - mk_list f n - -end - - -module Z3List = -struct - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = - let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - sort_of_ptr ctx r - - let mk_list_s ( ctx : context ) (name : string) elem_sort = - mk_sort ctx (Symbol.mk_string ctx name) elem_sort - - let get_nil_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 0) - - let get_is_nil_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 0) - - let get_cons_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 1) - - let get_is_cons_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 1) - - let get_head_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 0) - - let get_tail_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 1) - - let nil ( x : sort ) = expr_of_func_app (Sort.gc x) (get_nil_decl x) [] -end - - -module Tuple = -struct - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = - let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in - sort_of_ptr ctx r - - let get_mk_decl ( x : sort ) = - func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_mk_decl (Sort.gnc x) (Sort.gno x)) - - let get_num_fields ( x : sort ) = Z3native.get_tuple_sort_num_fields (Sort.gnc x) (Sort.gno x) - - let get_field_decls ( x : sort ) = - let n = get_num_fields x in - let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_field_decl (Sort.gnc x) (Sort.gno x) i) in - mk_list f n -end - - -module Arithmetic = -struct - let is_int ( x : expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - - let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - - let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - - let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - - let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - - let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - - let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - - let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - - let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - - let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - - let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - - let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - - let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - - let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - - let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - - let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - - let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) - - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - - let is_rat_numeral ( x : expr ) = (Expr.is_numeral x) && (is_real x) - - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - - module Integer = - struct - let mk_sort ( ctx : context ) = - sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - - let get_int ( x : expr ) = - let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - - let get_big_int ( x : expr ) = - if (is_int_numeral x) then - let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in - (Big_int.big_int_of_string s) - else raise (Z3native.Exception "Conversion failed.") - - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - Expr.mk_const ctx name (mk_sort ctx) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_mod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - - let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - - let mk_int2real ( ctx : context ) ( t : expr ) = - (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (Expr.gno t))) - - let mk_int2bv ( ctx : context ) ( n : int ) ( t : expr ) = - (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (Expr.gno t))) - end - - module Real = - struct - let mk_sort ( ctx : context ) = - sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - - let get_numerator ( x : expr ) = - expr_of_ptr (Expr.gc x) (Z3native.get_numerator (Expr.gnc x) (Expr.gno x)) - - let get_denominator ( x : expr ) = - expr_of_ptr (Expr.gc x) (Z3native.get_denominator (Expr.gnc x) (Expr.gno x)) - - let get_ratio ( x : expr ) = - if (is_rat_numeral x) then - let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in - (Ratio.ratio_of_string s) - else raise (Z3native.Exception "Conversion failed.") - - let to_decimal_string ( x : expr ) ( precision : int ) = - Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - Expr.mk_const ctx name (mk_sort ctx) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = - if (den == 0) then - raise (Z3native.Exception "Denominator is zero") - else - expr_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - - let mk_is_integer ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (Expr.gno t))) - - let mk_real2int ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (Expr.gno t))) - - module AlgebraicNumber = - struct - let to_upper ( x : expr ) ( precision : int ) = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) - - let to_lower ( x : expr ) precision = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) - - let to_decimal_string ( x : expr ) ( precision : int ) = - Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - end - end - - let mk_add ( ctx : context ) ( t : expr list ) = - let f x = (Expr.gno x) in - (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_mul ( ctx : context ) ( t : expr list ) = - let f x = (Expr.gno x) in - (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_sub ( ctx : context ) ( t : expr list ) = - let f x = (Expr.gno x) in - (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_unary_minus ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) - - let mk_div ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - - let mk_power ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - - let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - - let mk_le ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - - let mk_gt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - - let mk_ge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) -end - - -module BitVector = -struct - let mk_sort ( ctx : context ) size = - sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) - let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) - let is_bv_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - let is_bv_bit1 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - let is_bv_bit0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - let is_bv_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - let is_bv_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - let is_bv_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - let is_bv_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - let is_bv_sdiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - let is_bv_udiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - let is_bv_SRem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - let is_bv_urem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - let is_bv_smod ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - let is_bv_sdiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - let is_bv_udiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - let is_bv_srem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - let is_bv_urem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - let is_bv_smod0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - let is_bv_ule ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - let is_bv_sle ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - let is_bv_uge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - let is_bv_sge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - let is_bv_ult ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - let is_bv_slt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - let is_bv_ugt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - let is_bv_sgt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - let is_bv_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - let is_bv_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - let is_bv_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - let is_bv_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - let is_bv_nand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - let is_bv_nor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - let is_bv_xnor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - let is_bv_concat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - let is_bv_signextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - let is_bv_zeroextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - let is_bv_extract ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - let is_bv_repeat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - let is_bv_reduceor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - let is_bv_reduceand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - let is_bv_comp ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - let is_bv_shiftleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - let is_bv_shiftrightlogical ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - let is_bv_shiftrightarithmetic ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - let is_bv_rotateleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - let is_bv_rotateright ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - let is_bv_rotateleftextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - let is_bv_rotaterightextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - let is_bv_carry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - let is_bv_xor3 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) - let get_int ( x : expr ) = - let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - Expr.mk_const ctx name (mk_sort ctx size) - let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_const ctx (Symbol.mk_string ctx name) size - let mk_not ( ctx : context ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (Expr.gno t)) - let mk_redand ( ctx : context ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (Expr.gno t)) - let mk_redor ( ctx : context ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (Expr.gno t)) - let mk_and ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_or ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_nand ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_nor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_xnor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_neg ( ctx : context ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (Expr.gno t)) - let mk_add ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_sub ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_mul ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_udiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_sdiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_urem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_srem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_smod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_ult ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_slt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_ule ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_sle ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_uge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_sge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_ugt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_sgt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_concat ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (Expr.gno t)) - let mk_sign_ext ( ctx : context ) ( i : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (Expr.gno t)) - let mk_zero_ext ( ctx : context ) ( i : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (Expr.gno t)) - let mk_repeat ( ctx : context ) ( i : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (Expr.gno t)) - let mk_shl ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_lshr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_ashr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_rotate_left ( ctx : context ) ( i : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (Expr.gno t)) - let mk_rotate_right ( ctx : context ) ( i : int ) ( t : expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (Expr.gno t)) - let mk_ext_rotate_left ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_ext_rotate_right ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_bv2int ( ctx : context ) ( t : expr ) ( signed : bool ) = - expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (Expr.gno t) signed) - let mk_add_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = - (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) - let mk_add_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_sub_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_sub_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = - (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) - let mk_sdiv_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_neg_no_overflow ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (Expr.gno t))) - let mk_mul_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = - (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) - let mk_mul_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx size))) -end - - -module Proof = -struct - let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - let is_asserted ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - let is_goal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_OEQ) - let is_modus_ponens ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - let is_reflexivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - let is_symmetry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - let is_transitivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - let is_Transitivity_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - let is_monotonicity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - let is_quant_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - let is_distributivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - let is_and_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - let is_or_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - let is_rewrite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - let is_rewrite_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - let is_pull_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - let is_pull_quant_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - let is_push_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - let is_elim_unused_vars ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - let is_der ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - let is_quant_inst ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - let is_hypothesis ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - let is_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - let is_unit_resolution ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - let is_iff_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - let is_iff_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - let is_commutativity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - let is_def_axiom ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - let is_def_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - let is_apply_def ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - let is_iff_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - let is_nnf_pos ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - let is_nnf_neg ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - let is_nnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - let is_cnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - let is_skolemize ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - let is_modus_ponens_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - let is_theory_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) -end - - -module Goal = -struct - type goal = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : goal = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.goal_inc_ref ; - dec_ref = Z3native.goal_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_precision ( x : goal ) = - goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) - - let is_precise ( x : goal ) = - (get_precision x) == GOAL_PRECISE - - let is_underapproximation ( x : goal ) = - (get_precision x) == GOAL_UNDER - - let is_overapproximation ( x : goal ) = - (get_precision x) == GOAL_OVER - - let is_garbage ( x : goal ) = - (get_precision x) == GOAL_UNDER_OVER - - let add ( x : goal ) ( constraints : expr list ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e) in - ignore (List.map f constraints) ; - () - - let is_inconsistent ( x : goal ) = - Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) - - let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) - - let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) - - let get_formulas ( x : goal ) = - let n = get_size x in - let f i = ((expr_of_ptr (z3obj_gc x) - (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in - mk_list f n - - let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) - - let is_decided_sat ( x : goal ) = - Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) - - let is_decided_unsat ( x : goal ) = - Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) - - let translate ( x : goal ) ( to_ctx : context ) = - create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let simplify ( x : goal ) ( p : Params.params option ) = - let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in - Z3native.tactic_inc_ref (z3obj_gnc x) tn ; - let arn = match p with - | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) - | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) - in - Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; - let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in - let res = if sg == 0 then - raise (Z3native.Exception "No subgoals") - else - Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in - Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; - Z3native.tactic_dec_ref (z3obj_gnc x) tn ; - create (z3obj_gc x) res - - let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) - - let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Model = -struct - type model = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : model = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.model_inc_ref ; - dec_ref = Z3native.model_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncInterp = - struct - type func_interp = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_interp = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_interp_inc_ref ; - dec_ref = Z3native.func_interp_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncEntry = - struct - type func_entry = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_entry = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_entry_inc_ref ; - dec_ref = Z3native.func_entry_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_value ( x : func_entry ) = - expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) - - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) - - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) - - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) - - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (List.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null np) then - None - else - Some (expr_of_ptr (z3obj_gc x) np) - - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if not (Z3native.is_as_array (z3obj_gnc x) n) then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in - if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) - - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) - - let get_func_decls ( x : model ) = - let n = (get_num_funcs x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - (mk_list f n_funcs) @ (mk_list g n_consts) - - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in - if not r then - None - else - Some(expr_of_ptr (z3obj_gc x) v) - - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) - - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - mk_list f n - - let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Probe = -struct - type probe = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : probe = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.probe_inc_ref ; - dec_ref = Z3native.probe_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - let apply ( x : probe ) ( g : Goal.goal ) = - Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) - - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes (context_gno ctx) - - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name (context_gno ctx) i) in - mk_list f n - - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr (context_gno ctx) name - - let mk_probe ( ctx : context ) ( name : string ) = - (create ctx (Z3native.mk_probe (context_gno ctx) name)) - - let const ( ctx : context ) ( v : float ) = - (create ctx (Z3native.probe_const (context_gno ctx) v)) - - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let not_ ( ctx : context ) ( p : probe ) = - (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) -end - - -module Tactic = -struct - type tactic = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : tactic = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.tactic_inc_ref ; - dec_ref = Z3native.tactic_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module ApplyResult = - struct - type apply_result = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : apply_result = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.apply_result_inc_ref ; - dec_ref = Z3native.apply_result_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) - - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_subgoal ( x : apply_result ) ( i : int ) = - Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) - - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) - - let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) - - let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = - match p with - | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) - | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) - - let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) - - let get_tactic_names ( ctx : context ) = - let n = (get_num_tactics ctx ) in - let f i = (Z3native.get_tactic_name (context_gno ctx) i) in - mk_list f n - - let get_tactic_description ( ctx : context ) ( name : string ) = - Z3native.tactic_get_descr (context_gno ctx) name - - let mk_tactic ( ctx : context ) ( name : string ) = - create ctx (Z3native.mk_tactic (context_gno ctx) name) - - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = - let f p c = (match p with - | None -> (Some (z3obj_gno c)) - | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in - match (List.fold_left f None ts) with - | None -> - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - | Some(x) -> - let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) - - let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) - - let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) - - let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) - - let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) - - let skip ( ctx : context ) = - create ctx (Z3native.tactic_skip (context_gno ctx)) - - let fail ( ctx : context ) = - create ctx (Z3native.tactic_fail (context_gno ctx)) - - let fail_if ( ctx : context ) ( p : Probe.probe ) = - create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) - - let fail_if_not_decided ( ctx : context ) = - create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) - - let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) - - let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - using_params ctx t p - - let par_or ( ctx : context ) ( t : tactic list ) = - let f e = (z3obj_gno e) in - create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) - - let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let interrupt ( ctx : context ) = - Z3native.interrupt (context_gno ctx) -end - - -module Solver = -struct - type solver = z3_native_object - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : solver = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.solver_inc_ref ; - dec_ref = Z3native.solver_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let string_of_status ( s : status) = match s with - | UNSATISFIABLE -> "unsatisfiable" - | SATISFIABLE -> "satisfiable" - | _ -> "unknown" - - module Statistics = - struct - type statistics = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : statistics = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.stats_inc_ref ; - dec_ref = Z3native.stats_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - module Entry = - struct - type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } - - let create_si k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = true ; - m_is_float = false ; - m_int = v ; - m_float = 0.0 - } in - res - - let create_sd k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = false ; - m_is_float = true ; - m_int = 0 ; - m_float = v - } in - res - - - let get_key (x : statistics_entry) = x.m_key - let get_int (x : statistics_entry) = x.m_int - let get_float (x : statistics_entry) = x.m_float - let is_int (x : statistics_entry) = x.m_is_int - let is_float (x : statistics_entry) = x.m_is_float - let to_string_value (x : statistics_entry) = - if (is_int x) then - string_of_int (get_int x) - else if (is_float x) then - string_of_float (get_float x) - else - raise (Z3native.Exception "Unknown statistical entry type") - let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) - end - - let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : statistics ) = - let n = (get_size x ) in - let f i = ( - let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in - if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) - else - (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) - ) in - mk_list f n - - let get_keys ( x : statistics ) = - let n = (get_size x) in - let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get ( x : statistics ) ( key : string ) = - let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in - List.fold_left f None (get_entries x) - end - - let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_parameters ( x : solver ) ( p : Params.params )= - Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : solver ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) - - let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n - - let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - - let add ( x : solver ) ( constraints : expr list ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in - ignore (List.map f constraints) - - let assert_and_track_l ( x : solver ) ( cs : expr list ) ( ps : expr list ) = - if ((List.length cs) != (List.length ps)) then - raise (Z3native.Exception "Argument size mismatch") - else - let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno a) (Expr.gno b)) in - ignore (List.iter2 f cs ps) - - let assert_and_track ( x : solver ) ( c : expr ) ( p : expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno c) (Expr.gno p) - - let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVector.get_size a) - - let get_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size a) in - let f i = (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in - mk_list f n - - let check ( x : solver ) ( assumptions : expr list ) = - let r = - if ((List.length assumptions) == 0) then - lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) - else - let f x = (Expr.gno x) in - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) - in - match r with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN - - let get_model ( x : solver ) = - let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (Model.create (z3obj_gc x) q) - - let get_proof ( x : solver ) = - let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size cn) in - let f i = (AST.ASTVector.get cn i) in - mk_list f n - - let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_statistics ( x : solver ) = - (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) - - let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = - match logic with - | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) - - let mk_solver_s ( ctx : context ) ( logic : string ) = - mk_solver ctx (Some (Symbol.mk_string ctx logic)) - - let mk_simple_solver ( ctx : context ) = - (create ctx (Z3native.mk_simple_solver (context_gno ctx))) - - let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = - (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) - - let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Fixedpoint = -struct - type fixedpoint = z3_native_object - - let create ( ctx : context ) = - let res : fixedpoint = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.fixedpoint_inc_ref ; - dec_ref = Z3native.fixedpoint_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; - (z3obj_create res) ; - res - - - let get_help ( x : fixedpoint ) = - Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_params ( x : fixedpoint ) ( p : Params.params )= - Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let add ( x : fixedpoint ) ( constraints : expr list ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in - ignore (List.map f constraints) ; - () - - let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - - let add_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol option ) = - match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno y) - - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) - - let query ( x : fixedpoint ) ( query : expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Expr.gno query))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let query_r ( x : fixedpoint ) ( relations : func_decl list ) = - let f x = ptr_of_ast (ast_of_func_decl x) in - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let push ( x : fixedpoint ) = - Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : fixedpoint ) = - Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - - let update_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno name) - - let get_answer ( x : fixedpoint ) = - let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_reason_unknown ( x : fixedpoint ) = - Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) - - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) - - let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - - let to_string_q ( x : fixedpoint ) ( queries : expr list ) = - let f x = Expr.gno x in - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) - - let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let mk_fixedpoint ( ctx : context ) = create ctx -end - - -module SMT = -struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : expr list ) ( formula : expr ) = - Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (List.length assumptions) (let f x = Expr.gno (x) in (Array.of_list (List.map f assumptions))) - (Expr.gno formula) - - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_file (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) - - let get_smtlib_formulas ( ctx : context ) = - let n = (get_num_smtlib_formulas ctx ) in - let f i =(expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) - - let get_smtlib_assumptions ( ctx : context ) = - let n = (get_num_smtlib_assumptions ctx ) in - let f i = (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) - - let get_smtlib_decls ( ctx : context ) = - let n = (get_num_smtlib_decls ctx) in - let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in - mk_list f n - - let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - - let get_smtlib_sorts ( ctx : context ) = - let n = (get_num_smtlib_sorts ctx) in - let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in - mk_list f n - - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) -end - -module Interpolation = -struct - let mk_interpolant ( ctx : context ) ( a : expr ) = - (expr_of_ptr ctx (Z3native.mk_interpolant (context_gno ctx) (Expr.gno a))) - - let mk_interpolation_context ( settings : ( string * string ) list ) = - let cfg = Z3native.mk_config () in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_interpolation_context cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - Z3native.set_internal_error_handler v ; - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> dispose_context o in - Gc.finalise f res; - res - - let get_interpolant ( ctx : context ) ( pf : expr ) ( pat: expr ) ( p : Params.params ) = - (ASTVector.create ctx (Z3native.get_interpolant (context_gno ctx) (Expr.gno pf) (Expr.gno pat) (z3obj_gno p))) - - let compute_interpolant ( ctx : context ) ( pat : expr ) ( p : Params.params ) = - let (r, interp, model) = (Z3native.compute_interpolant (context_gno ctx) (Expr.gno pat) (z3obj_gno p)) in - match (lbool_of_int r) with - | L_TRUE -> ((ASTVector.create ctx interp), (Model.create ctx model)) - | _ -> raise (Z3native.Exception "Error computing interpolant.") - - let get_interpolation_profile ( ctx : context ) = - (Z3native.interpolation_profile (context_gno ctx)) - - let read_interpolation_problem ( ctx : context ) ( filename : string ) = - let (r, num, cnsts, parents, error, num_theory, theory) = (Z3native.read_interpolation_problem (context_gno ctx) filename) in - match r with - | 0 -> raise (Z3native.Exception "Interpolation problem could not be read.") - | _ -> - let f1 i = (expr_of_ptr ctx (Array.get cnsts i)) in - let f2 i = (Array.get parents i) in - let f3 i = (expr_of_ptr ctx (Array.get theory i)) in - ((mk_list f1 num), - (mk_list f2 num), - (mk_list f3 num_theory)) - - let check_interpolant ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( interps : Expr.expr list ) ( num_theory : int ) ( theory : Expr.expr list ) = - let (r, str) = (Z3native.check_interpolant (context_gno ctx) - num - (let f x = Expr.gno x in (Array.of_list (List.map f cnsts))) - (Array.of_list parents) - (let f x = Expr.gno x in (Array.of_list (List.map f interps))) - num_theory - (let f x = Expr.gno x in (Array.of_list (List.map f theory)))) in - match (lbool_of_int r) with - | L_UNDEF -> raise (Z3native.Exception "Interpolant could not be verified.") - | L_FALSE -> raise (Z3native.Exception "Interpolant could not be verified.") - | _ -> () - - let write_interpolation_problem ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( filename : string ) ( num_theory : int ) ( theory : Expr.expr list ) = - (Z3native.write_interpolation_problem (context_gno ctx) num (expr_lton cnsts) (Array.of_list parents) filename num_theory (expr_lton theory)) ; - () -end - -let set_global_param ( id : string ) ( value : string ) = - (Z3native.global_param_set id value) - -let get_global_param ( id : string ) = - let (r, v) = (Z3native.global_param_get id) in - if not r then - None - else - Some v - -let global_param_reset_all = - Z3native.global_param_reset_all - -let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages enabled From e2ac8c73d9ad7ac7fa59f9a15ff70da94c6fc2fb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 04:37:46 +0000 Subject: [PATCH 375/646] ML API temp files added to .gitignore Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index a1a8b7f6b..648013ca1 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,6 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java - *.bak doc/api doc/code From d2d4bf7f835c65d58aa5f56b11bb36e0a5b5bee8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 08:06:10 +0000 Subject: [PATCH 376/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 45 ------------------------- scripts/update_api.py | 45 +++++++------------------ src/api/ml/z3.ml | 78 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 81 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 33129f555..2c525861c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1866,11 +1866,7 @@ def mk_config(): if GPROF: print('gprof: enabled') print('Python version: %s' % distutils.sysconfig.get_python_version()) -<<<<<<< HEAD print('ML API: %s' % is_ml_enabled()) -======= - print 'ML API: %s' % is_ml_enabled() ->>>>>>> Beginnings of a new ML API if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) @@ -2738,9 +2734,6 @@ def mk_z3consts_ml(api_files): if not os.path.exists(gendir): os.mkdir(gendir) -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') efile.write('(** The enumeration types of Z3. *)\n\n') @@ -2822,23 +2815,7 @@ def mk_z3consts_ml(api_files): efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') efile.write('(** The enumeration types of Z3. *)\n\n') -======= - efile = open('%s.ml' % os.path.join(gendir, "z3_enums"), 'w') - efile.write('(* Automatically generated file *)\n\n') - # efile.write('module z3_enums = struct\n\n'); - - ->>>>>>> More new ML API -======= - efile = open('%s.ml' % os.path.join(gendir, "enumerations"), 'w') - efile.write('(* Automatically generated file *)\n\n') - efile.write('module Enumerations = struct\n') ->>>>>>> More ML API -======= - efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') - efile.write('(* Automatically generated file *)\n\n') efile.write('module Z3enums = struct\n') ->>>>>>> New native ML API layer. for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) @@ -2884,8 +2861,6 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: -<<<<<<< HEAD -<<<<<<< HEAD efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ for k, i in decls.iteritems(): @@ -2896,17 +2871,10 @@ def mk_z3consts_ml(api_files): efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ efile.write('\n') -======= efile.write('\n(* %s *)\n' % name) -======= ->>>>>>> More ML API efile.write('type %s =\n' % name[3:]) # strip Z3_ for k, i in decls.iteritems(): -<<<<<<< HEAD efile.write(' | %s \n' % k[3:]) # strip Z3_ ->>>>>>> More new ML API -======= - efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') @@ -2919,7 +2887,6 @@ def mk_z3consts_ml(api_files): efile.write(' | %d -> %s\n' % (i, k[3:])) # use Z3.Exception? efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') ->>>>>>> More ML API mode = SEARCHING else: if words[2] != '': @@ -2930,21 +2897,9 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 -<<<<<<< HEAD -<<<<<<< HEAD - if VERBOSE: - print "Generated '%s/z3enums.mli'" % ('%s' % gendir) -======= - efile.write('\n') - # efile.write'end\n'); - if VERBOSE: - print "Generated '%s/z3_enums.ml'" % ('%s' % gendir) ->>>>>>> More new ML API -======= efile.write('end\n') if VERBOSE: print "Generated '%s/enumerations.ml'" % ('%s' % gendir) ->>>>>>> More ML API def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index f142c8ec1..a586ad6e3 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -159,7 +159,7 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I # Mapping to ML types Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', STRING : 'string', STRING_PTR : 'char**', - BOOL : 'int', SYMBOL : 'symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } + BOOL : 'int', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -213,10 +213,7 @@ def type2javaw(ty): def type2ml(ty): global Type2ML - if (ty >= FIRST_OBJ_ID): - return 'int' - else: - return Type2ML[ty] + return Type2ML[ty] def _in(ty): return (IN, ty); @@ -1106,6 +1103,7 @@ def is_array_param(p): return False def mk_ml(): + global Type2Str if not is_ml_enabled(): return ml_dir = get_component('ml').src_dir @@ -1114,29 +1112,12 @@ def mk_ml(): ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') ml_native.write('open Z3enums\n\n') - ml_native.write('module Z3native = struct\n\n') - ml_native.write(' type context\n') - ml_native.write(' and symbol\n') - ml_native.write(' and ast\n') - ml_native.write(' and sort = private ast\n') - ml_native.write(' and func_decl = private ast\n') - ml_native.write(' and app = private ast\n') - ml_native.write(' and pattern = private ast\n') - ml_native.write(' and params\n') - ml_native.write(' and param_descrs\n') - ml_native.write(' and model\n') - ml_native.write(' and func_interp\n') - ml_native.write(' and func_entry\n') - ml_native.write(' and fixedpoint\n') - ml_native.write(' and ast_vector\n') - ml_native.write(' and ast_map\n') - ml_native.write(' and goal\n') - ml_native.write(' and tactic\n') - ml_native.write(' and probe\n') - ml_native.write(' and apply_result\n') - ml_native.write(' and solver\n') - ml_native.write(' and stats\n\n') - ml_native.write(' exception Exception of string\n\n') + ml_native.write('type ptr\n') + ml_native.write('and z3_symbol = ptr\n') + for k, v in Type2Str.iteritems(): + if is_obj(k): + ml_native.write('and %s = ptr\n' % v.lower()) + ml_native.write('\nexception Exception of string\n\n') # ML declarations ml_native.write(' module ML2C = struct\n\n') @@ -1192,9 +1173,9 @@ def mk_ml(): i = i + 1 ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (Z3enums.int2error_code (ML2C.n_get_error_code a0)) in \n') - ml_native.write(' if err <> Z3enums.OK then\n') - ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (Z3enums.error_code2int err)))\n') + ml_native.write(' let err = (int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' if err <> OK then\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') if result == VOID: ml_native.write(' ()\n') @@ -1202,8 +1183,6 @@ def mk_ml(): ml_native.write(' res\n') ml_native.write('\n') - ml_native.write('end\n') - # C interface ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 5251a8767..a6a388aa7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,11 +1,83 @@ (* Author: CM Wintersteiger (C) Microsoft Research, 2012 -*) + *) open Z3enums open Z3native -module Z3 = struct +class context = + object (self) + val m_n_ctx : Z3native.z3_context option = None + val mutable m_refCount : int = 0 + initializer Gc.finalise (fun self -> self#dispose ()) self + method dispose () = + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with + | Some(x) -> (del_context x) + | None -> () + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 + method add_one_ctx_obj = m_refCount <- m_refCount + 1 + end + +class virtual z3object ctx_init obj_init = + object (self) + val mutable m_ctx : context option = ctx_init + val mutable m_n_obj : Z3native.ptr option = obj_init + + initializer + (match m_n_obj with + | Some (x) -> self#incref x; + (match m_ctx with + | Some(x) -> x#add_one_ctx_obj + | None -> () + ) + | None -> () + ); + Gc.finalise (fun self -> self#dispose ()) self + + method virtual incref : Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> unit + + (* + Disposes of the underlying native Z3 object. + *) + method dispose () = + Printf.printf "Disposing %d \n" (Oo.id self) ; + (match m_n_obj with + | Some (x) -> self#decref x; m_n_obj <- None + | None -> () + ); + (match m_ctx with + | Some (x) -> x#sub_one_ctx_obj + | None -> () + ); + m_ctx <- None + + + method get_native_object = m_n_obj + + method set_native_object x = + (match x with + | Some(x) -> self#incref x + | None -> () + ); + (match m_n_obj with + | Some(x) -> self#decref x + | None -> () + ); + m_n_obj <- x + + method get_context = m_ctx + + method array_to_native a = + let f e = e#get_native_object in + (Array.map f a) + + method array_length a = + match a with + | Some(x) -> (Array.length x) + | None -> 0 + + end -end From f7b3529f0166facc8b94b6becbe97b56e4abc54d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 16:33:51 +0000 Subject: [PATCH 377/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- examples/ml/MLExample.ml | 12 ++++++++ scripts/mk_util.py | 9 +++++- src/api/ml/README | 3 -- src/api/ml/z3.ml | 59 ++++++++++++++++++++++++++++++++-------- 4 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 examples/ml/MLExample.ml diff --git a/examples/ml/MLExample.ml b/examples/ml/MLExample.ml new file mode 100644 index 000000000..8cc248206 --- /dev/null +++ b/examples/ml/MLExample.ml @@ -0,0 +1,12 @@ +(* + Copyright (C) 2012 Microsoft Corporation + Author: CM Wintersteiger (cwinter) 2012-12-17 + *) + + open Z3 + + let _ = ignore(Log.open_ "z3.log") ; +let cfg = Some [("model", "true"); ("proof", "false")] in +let ctx = (new context cfg) in +ctx#dispose +;; diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 2c525861c..40828f8c3 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1597,7 +1597,14 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('_ex_%s: ml_example.byte ml_example$(EXE_EXT)\n\n' % self.name) + out.write('_ex_%s: z3.cmxa' % self.name) + deps = '' + for mlfile in get_ml_files(self.ex_dir): + out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) + if IS_WINDOWS: + deps = deps.replace('/', '\\') + out.write('%s\n' % deps) + out.write('\tcd %s && ocamlbuild -build-dir ../../%s -lib z3 MLExample.native && cd -\n\n' % (self.to_src_dir, BUILD_DIR)) class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): diff --git a/src/api/ml/README b/src/api/ml/README index f8984c79e..36f903925 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -1,11 +1,8 @@ This directory is work in progress. We are currently working on a brand new ML API. -<<<<<<< HEAD On Windows, there are no less than four different ports of OCaml. The Z3 build system assumes that either the win32 or the win64 port is installed. This means that OCaml will use `cl' as the underlying C compiler and not the cygwin or mingw compilers. -======= ->>>>>>> Beginnings of a new ML API diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index a6a388aa7..0329402dd 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,27 +1,60 @@ (* - Author: CM Wintersteiger - (C) Microsoft Research, 2012 + Copyright (C) 2012 Microsoft Corporation + Author: CM Wintersteiger (cwinter) 2012-12-17 *) open Z3enums open Z3native -class context = +module Log = + struct + let m_is_open = false +(* CMW: "open" seems to be an invalid function name*) + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) + end + +class virtual idisposable = + object + method virtual dispose : unit + end + +class context settings = object (self) - val m_n_ctx : Z3native.z3_context option = None + inherit idisposable + val mutable m_n_ctx : Z3native.z3_context option = None val mutable m_refCount : int = 0 - initializer Gc.finalise (fun self -> self#dispose ()) self - method dispose () = - Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with - | Some(x) -> (del_context x) - | None -> () + + initializer + let cfg = mk_config() in + (match settings with + | Some(x) -> + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f x) + | _ -> () + ) ; + m_n_ctx <- Some (mk_context_rc cfg) ; + del_config(cfg) ; + Gc.finalise (fun self -> self#dispose) self + + method dispose : unit = + if m_refCount == 0 then ( + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with + | Some(x) -> (del_context x) + | None -> () + ) else ( + (* re-queue for finalization? *) + ) + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 end class virtual z3object ctx_init obj_init = object (self) + inherit idisposable val mutable m_ctx : context option = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init @@ -34,7 +67,7 @@ class virtual z3object ctx_init obj_init = ) | None -> () ); - Gc.finalise (fun self -> self#dispose ()) self + Gc.finalise (fun self -> self#dispose) self method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit @@ -42,7 +75,7 @@ class virtual z3object ctx_init obj_init = (* Disposes of the underlying native Z3 object. *) - method dispose () = + method dispose = Printf.printf "Disposing %d \n" (Oo.id self) ; (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None @@ -70,6 +103,7 @@ class virtual z3object ctx_init obj_init = method get_context = m_ctx +(* method array_to_native a = let f e = e#get_native_object in (Array.map f a) @@ -78,6 +112,7 @@ class virtual z3object ctx_init obj_init = match a with | Some(x) -> (Array.length x) | None -> 0 +*) end From f614f6824e63948123354c6d93597a069478b7d0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 17:26:28 +0000 Subject: [PATCH 378/646] More ML API Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 158 +++++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0329402dd..a7d59de9f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,118 +1,118 @@ (* Copyright (C) 2012 Microsoft Corporation Author: CM Wintersteiger (cwinter) 2012-12-17 - *) +*) open Z3enums open Z3native module Log = - struct - let m_is_open = false -(* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) - end - +struct + let m_is_open = false + (* CMW: "open" seems to be an invalid function name*) + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) +end + class virtual idisposable = - object - method virtual dispose : unit - end +object + method virtual dispose : unit +end class context settings = - object (self) - inherit idisposable - val mutable m_n_ctx : Z3native.z3_context option = None - val mutable m_refCount : int = 0 - - initializer - let cfg = mk_config() in - (match settings with - | Some(x) -> - let f e = (set_param_value cfg (fst e) (snd e)) in - (List.iter f x) - | _ -> () - ) ; - m_n_ctx <- Some (mk_context_rc cfg) ; - del_config(cfg) ; - Gc.finalise (fun self -> self#dispose) self - - method dispose : unit = - if m_refCount == 0 then ( - Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with +object (self) + inherit idisposable + val mutable m_n_ctx : Z3native.z3_context option = None + val mutable m_refCount : int = 0 + + initializer + let cfg = mk_config() in + (match settings with + | Some(x) -> + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f x) + | _ -> () + ) ; + m_n_ctx <- Some (mk_context_rc cfg) ; + del_config(cfg) ; + Gc.finalise (fun self -> self#dispose) self + + method dispose : unit = + if m_refCount == 0 then ( + Printf.printf "Disposing %d \n" (Oo.id self) ; + match m_n_ctx with | Some(x) -> (del_context x) | None -> () - ) else ( - (* re-queue for finalization? *) - ) + ) else ( + (* re-queue for finalization? *) + ) - method sub_one_ctx_obj = m_refCount <- m_refCount - 1 - method add_one_ctx_obj = m_refCount <- m_refCount + 1 - end + method sub_one_ctx_obj = m_refCount <- m_refCount - 1 + method add_one_ctx_obj = m_refCount <- m_refCount + 1 +end class virtual z3object ctx_init obj_init = - object (self) - inherit idisposable - val mutable m_ctx : context option = ctx_init - val mutable m_n_obj : Z3native.ptr option = obj_init - - initializer - (match m_n_obj with +object (self) + inherit idisposable + val mutable m_ctx : context option = ctx_init + val mutable m_n_obj : Z3native.ptr option = obj_init + + initializer + (match m_n_obj with | Some (x) -> self#incref x; - (match m_ctx with + (match m_ctx with | Some(x) -> x#add_one_ctx_obj | None -> () - ) + ) | None -> () - ); - Gc.finalise (fun self -> self#dispose) self + ); + Gc.finalise (fun self -> self#dispose) self - method virtual incref : Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> unit - - (* - Disposes of the underlying native Z3 object. - *) - method dispose = - Printf.printf "Disposing %d \n" (Oo.id self) ; - (match m_n_obj with + method virtual incref : Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> unit + + (* + Disposes of the underlying native Z3 object. + *) + method dispose = + Printf.printf "Disposing %d \n" (Oo.id self) ; + (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None | None -> () - ); - (match m_ctx with + ); + (match m_ctx with | Some (x) -> x#sub_one_ctx_obj | None -> () - ); - m_ctx <- None + ); + m_ctx <- None - method get_native_object = m_n_obj + method get_native_object = m_n_obj - method set_native_object x = - (match x with + method set_native_object x = + (match x with | Some(x) -> self#incref x | None -> () - ); - (match m_n_obj with + ); + (match m_n_obj with | Some(x) -> self#decref x | None -> () - ); - m_n_obj <- x + ); + m_n_obj <- x - method get_context = m_ctx + method get_context = m_ctx -(* + (* method array_to_native a = - let f e = e#get_native_object in - (Array.map f a) + let f e = e#get_native_object in + (Array.map f a) method array_length a = - match a with - | Some(x) -> (Array.length x) - | None -> 0 -*) + match a with + | Some(x) -> (Array.length x) + | None -> 0 + *) - end +end From c9cca119c5d89296da457b80d8c1fd0300e98aa1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 20:18:53 +0000 Subject: [PATCH 379/646] File renamed Signed-off-by: Christoph M. Wintersteiger --- examples/ml/{MLExample.ml => mlexample.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/ml/{MLExample.ml => mlexample.ml} (100%) diff --git a/examples/ml/MLExample.ml b/examples/ml/mlexample.ml similarity index 100% rename from examples/ml/MLExample.ml rename to examples/ml/mlexample.ml From 0e98d267219e5ad3459030a772c418e9f762b5d7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 22:25:16 +0000 Subject: [PATCH 380/646] ML API and example compilation. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 10 -- examples/ml/ml_example.ml | 272 +------------------------------------- examples/ml/mlexample.ml | 12 -- scripts/mk_util.py | 33 +---- src/api/ml/z3.ml | 2 +- 5 files changed, 15 insertions(+), 314 deletions(-) delete mode 100644 examples/ml/mlexample.ml diff --git a/examples/ml/README b/examples/ml/README index c61716b65..3e1eb0d1c 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -12,13 +12,3 @@ or LD_LIBRARY_PATH=. ./ml_example.byte for the byte-code version. -If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), -then we can compile this example as follows: - -ocamlfind ocamlc -o ml_example.byte -package Z3 -linkpkg ml_example.ml -ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml - -Note that the resulting binaries depend on the shared z3 library, which needs to be -in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was -installed into ocamlfind, the path that should be added is -`ocamlfind printconf destdir`/Z3 diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 25862b2d7..9c704e4d0 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,269 +4,11 @@ *) open Z3 -open Z3.Symbol -open Z3.Sort -open Z3.Expr -open Z3.Boolean -open Z3.FuncDecl -open Z3.Goal -open Z3.Tactic -open Z3.Tactic.ApplyResult -open Z3.Probe -open Z3.Solver -open Z3.Arithmetic -open Z3.Arithmetic.Integer -open Z3.Arithmetic.Real -open Z3.BitVector - -exception TestFailedException of string - -(** - Model Converter test -*) -let model_converter_test ( ctx : context ) = - Printf.printf "ModelConverterTest\n"; - let xr = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Real.mk_sort ctx)) in - let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in - let g4 = (mk_goal ctx true false false ) in - (Goal.add g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; - (Goal.add g4 [ (mk_eq ctx - yr - (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1) ])) ]) ; - (Goal.add g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; - ( - let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in - if ((get_num_subgoals ar) == 1 && - ((is_decided_sat (get_subgoal ar 0)) || - (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") []) g4 None) in - if ((get_num_subgoals ar) == 1 && - ((is_decided_sat (get_subgoal ar 0)) || - (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ; - let solver = (mk_solver ctx None) in - let f e = (Solver.add solver [ e ]) in - ignore (List.map f (get_formulas (get_subgoal ar 0))) ; - let q = (check solver []) in - if q != SATISFIABLE then - raise (TestFailedException "") - else - let m = (get_model solver) in - match m with - | None -> raise (TestFailedException "") - | Some (m) -> - Printf.printf "Solver says: %s\n" (string_of_status q) ; - Printf.printf "Model: \n%s\n" (Model.to_string m) ; - Printf.printf "Converted Model: \n%s\n" (Model.to_string (convert_model ar 0 m)) - ) - -(** - Some basic tests. -*) -let basic_tests ( ctx : context ) = - Printf.printf "BasicTests\n" ; -(* let qi = (mk_int ctx 1) in *) - let fname = (mk_string ctx "f") in - let x = (mk_string ctx "x") in - let y = (mk_string ctx "y") in - let bs = (Boolean.mk_sort ctx) in - let domain = [ bs; bs ] in - let f = (FuncDecl.mk_func_decl ctx fname domain bs) in - let fapp = (mk_app ctx f - [ (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) ]) in - let fargs2 = [ (mk_fresh_const ctx "cp" bs) ] in - let domain2 = [ bs ] in - let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in - let trivial_eq = (mk_eq ctx fapp fapp) in - let nontrivial_eq = (mk_eq ctx fapp fapp2) in - let g = (mk_goal ctx true false false) in - (Goal.add g [ trivial_eq ]) ; - (Goal.add g [ nontrivial_eq ]) ; - Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; - ( - let solver = (mk_solver ctx None) in - (List.iter (fun a -> (Solver.add solver [ a ])) (get_formulas g)) ; - if (check solver []) != SATISFIABLE then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in - if ((get_num_subgoals ar) == 1 && - ((is_decided_sat (get_subgoal ar 0)) || - (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - (Goal.add g [ (mk_eq ctx - (mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) - (mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) - ; - ( - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let g2 = (mk_goal ctx true true false) in - let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let g2 = (mk_goal ctx true true false) in - (Goal.add g2 [ (Boolean.mk_false ctx) ]) ; - let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ); - ( - let g3 = (mk_goal ctx true true false) in - let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Integer.mk_sort ctx)) in - let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Integer.mk_sort ctx)) in - (Goal.add g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; - (Goal.add g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; - let constr = (mk_eq ctx xc yc) in - (Goal.add g3 [ constr ] ) ; - let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ) ; - model_converter_test ctx ; - (* Real num/den test. *) - let rn = Real.mk_numeral_nd ctx 42 43 in - let inum = (get_numerator rn) in - let iden = get_denominator rn in - Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; - if ((Real.to_string inum) <> "42" || (Real.to_string iden) <> "43") then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ; - if ((to_decimal_string rn 3) <> "0.976?") then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" - ; - if (to_decimal_string (Real.mk_numeral_s ctx "-1231231232/234234333") 5 <> "-5.25640?") then - raise (TestFailedException "") - else if (to_decimal_string (Real.mk_numeral_s ctx "-123123234234234234231232/234234333") 5 <> "-525641278361333.28170?") then - raise (TestFailedException "") - else if (to_decimal_string (Real.mk_numeral_s ctx "-234234333") 5 <> "-234234333") then - raise (TestFailedException "") - else if (to_decimal_string (Real.mk_numeral_s ctx "234234333/2") 5 <> "117117166.5") then - raise (TestFailedException "") - ; - (* Error handling test. *) - try ( - let i = Integer.mk_numeral_s ctx "1/2" in - raise (TestFailedException "") (* unreachable *) - ) - with Z3native.Exception(_) -> ( - Printf.printf "Exception caught, OK.\n" - ) - -(** - A basic example of how to use quantifiers. -**) -let quantifierExample1 ( ctx : context ) = - Printf.printf "QuantifierExample\n" ; - let is = (Integer.mk_sort ctx) in - let types = [ is; is; is ] in - let names = [ (Symbol.mk_string ctx "x_0"); - (Symbol.mk_string ctx "x_1"); - (Symbol.mk_string ctx "x_2") ] in - let vars = [ (Quantifier.mk_bound ctx 2 (List.nth types 0)); - (Quantifier.mk_bound ctx 2 (List.nth types 1)); - (Quantifier.mk_bound ctx 2 (List.nth types 2)) ] in - let xs = [ (Integer.mk_const ctx (List.nth names 0)); - (Integer.mk_const ctx (List.nth names 1)); - (Integer.mk_const ctx (List.nth names 2)) ] in - - let body_vars = (Boolean.mk_and ctx - [ (mk_eq ctx - (Arithmetic.mk_add ctx [ (List.nth vars 0) ; (Integer.mk_numeral_i ctx 1)]) - (Integer.mk_numeral_i ctx 2)) ; - (mk_eq ctx - (Arithmetic.mk_add ctx [ (List.nth vars 1); (Integer.mk_numeral_i ctx 2)]) - (Arithmetic.mk_add ctx [ (List.nth vars 2); (Integer.mk_numeral_i ctx 3)])) ]) in - let body_const = (Boolean.mk_and ctx - [ (mk_eq ctx - (Arithmetic.mk_add ctx [ (List.nth xs 0); (Integer.mk_numeral_i ctx 1)]) - (Integer.mk_numeral_i ctx 2)) ; - (mk_eq ctx - (Arithmetic.mk_add ctx [ (List.nth xs 1); (Integer.mk_numeral_i ctx 2)]) - (Arithmetic.mk_add ctx [ (List.nth xs 2); (Integer.mk_numeral_i ctx 3)])) ]) in - - let x = (Quantifier.mk_forall ctx types names body_vars (Some 1) [] [] (Some (Symbol.mk_string ctx "Q1")) (Some (Symbol.mk_string ctx "skid1"))) in - Printf.printf "Quantifier X: %s\n" (Quantifier.to_string x) ; - let y = (Quantifier.mk_forall_const ctx xs body_const (Some 1) [] [] (Some (Symbol.mk_string ctx "Q2")) (Some (Symbol.mk_string ctx "skid2"))) in - Printf.printf "Quantifier Y: %s\n" (Quantifier.to_string y) ; - if (is_true (Quantifier.expr_of_quantifier x)) then - raise (TestFailedException "") (* unreachable *) - else if (is_false (Quantifier.expr_of_quantifier x)) then - raise (TestFailedException "") (* unreachable *) - else if (is_const (Quantifier.expr_of_quantifier x)) then - raise (TestFailedException "") (* unreachable *) - -let _ = - try ( - if not (Log.open_ "z3.log") then - raise (TestFailedException "Log couldn't be opened.") - else - ( - Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = [("model", "true"); ("proof", "false")] in - let ctx = (mk_context cfg) in - let is = (Symbol.mk_int ctx 42) in - let ss = (Symbol.mk_string ctx "mySymbol") in - let bs = (Boolean.mk_sort ctx) in - let ints = (Integer.mk_sort ctx) in - let rs = (Real.mk_sort ctx) in - Printf.printf "int symbol: %s\n" (Symbol.to_string is); - Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string bs); - Printf.printf "int sort: %s\n" (Sort.to_string ints); - Printf.printf "real sort: %s\n" (Sort.to_string rs); - basic_tests ctx ; - quantifierExample1 ctx ; - Printf.printf "Disposing...\n"; - Gc.full_major () - ); - Printf.printf "Exiting.\n" ; - exit 0 - ) with Z3native.Exception(msg) -> ( - Printf.printf "Z3 EXCEPTION: %s\n" msg ; - exit 1 - ) + +let _ = ignore(Log.open_ "z3.log") ; + let cfg = Some [("model", "true"); ("proof", "false")] in + let ctx = (new context cfg) in + Printf.printf "Disposing...\n"; + ctx#dispose ; + Printf.printf "Exiting.\n"; ;; diff --git a/examples/ml/mlexample.ml b/examples/ml/mlexample.ml deleted file mode 100644 index 8cc248206..000000000 --- a/examples/ml/mlexample.ml +++ /dev/null @@ -1,12 +0,0 @@ -(* - Copyright (C) 2012 Microsoft Corporation - Author: CM Wintersteiger (cwinter) 2012-12-17 - *) - - open Z3 - - let _ = ignore(Log.open_ "z3.log") ; -let cfg = Some [("model", "true"); ("proof", "false")] in -let ctx = (new context cfg) in -ctx#dispose -;; diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 40828f8c3..38af3893f 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1435,10 +1435,6 @@ class MLComponent(Component): bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') mk_dir(bld_dir) libfile = '%s$(SO_EXT)' % self.lib_name - # for mlfile in get_ml_files(self.src_dir): - # out.write('%si: libz3$(SO_EXT) %s\n' % (os.path.join('api', 'ml', mlfile),os.path.join(self.to_src_dir, mlfile))) - # out.write('\tocamlopt -I %s -i %s > %si\n' % (os.path.join('api', 'ml'), os.path.join(self.to_src_dir, mlfile), os.path.join('api', 'ml', mlfile))) - # out.write('\tocamlopt -I %s -c %si \n' % (os.path.join('api', 'ml'), os.path.join('api','ml', mlfile))) out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) @@ -1446,11 +1442,9 @@ class MLComponent(Component): out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -lflags -cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cmxa && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) - out.write('\tcp api/ml/z3.cmxa .\n') + out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -lflags -custom,-cclib,../../../%s/libz3ml.so,-cclib,../../../%s/libz3.so -build-dir ../../../%s/api/ml z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR,BUILD_DIR,BUILD_DIR)) - out.write('\tcp api/ml/z3.cma .\n') + out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -custom,-cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3native$(OBJ_EXT) z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('ml: z3.cmxa z3.cma\n') out.write('\n') @@ -1575,36 +1569,23 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: api/ml/z3ml.cmxa ') + out.write('ml_example.byte: z3.cma ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\t%s ' % OCAMLC) - if DEBUG_MODE: - out.write('-g ') - out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3ml.cma') + out.write('\tocamlc -g -o ml_example.byte -I . z3.cma -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example$(EXE_EXT): api/ml/z3ml.cmxa ml_example.byte') + out.write('ml_example($EXE_EXT): z3.cmxa ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\t%s ' % OCAMLOPT) - if DEBUG_MODE: - out.write('-g ') - out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3ml.cmxa') + out.write('\tocamlopt -g -o ml_example -I . z3.cmxa -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('_ex_%s: z3.cmxa' % self.name) - deps = '' - for mlfile in get_ml_files(self.ex_dir): - out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) - if IS_WINDOWS: - deps = deps.replace('/', '\\') - out.write('%s\n' % deps) - out.write('\tcd %s && ocamlbuild -build-dir ../../%s -lib z3 MLExample.native && cd -\n\n' % (self.to_src_dir, BUILD_DIR)) + out.write('_ex_%s: ml_example.byte ml_example($EXE_EXT)\n\n' % self.name) class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index a7d59de9f..68edd9b42 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -76,7 +76,7 @@ object (self) Disposes of the underlying native Z3 object. *) method dispose = - Printf.printf "Disposing %d \n" (Oo.id self) ; + Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with | Some (x) -> self#decref x; m_n_obj <- None | None -> () From 50560ba791c23f89ad40178e4930f7fec24155d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 19 Dec 2012 23:31:42 +0000 Subject: [PATCH 381/646] more ML API Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 94 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 68edd9b42..9812bd790 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -23,48 +23,42 @@ end class context settings = object (self) inherit idisposable - val mutable m_n_ctx : Z3native.z3_context option = None + + val mutable m_n_ctx : Z3native.z3_context = + let cfg = mk_config() in + let f e = (set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = mk_context_rc cfg in + del_config(cfg) ; + v + val mutable m_refCount : int = 0 - initializer - let cfg = mk_config() in - (match settings with - | Some(x) -> - let f e = (set_param_value cfg (fst e) (snd e)) in - (List.iter f x) - | _ -> () - ) ; - m_n_ctx <- Some (mk_context_rc cfg) ; - del_config(cfg) ; - Gc.finalise (fun self -> self#dispose) self + initializer Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing %d \n" (Oo.id self) ; - match m_n_ctx with - | Some(x) -> (del_context x) - | None -> () + (del_context m_n_ctx) ) else ( (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 + method get_native = m_n_ctx end class virtual z3object ctx_init obj_init = object (self) inherit idisposable - val mutable m_ctx : context option = ctx_init + val mutable m_ctx : context = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init initializer (match m_n_obj with | Some (x) -> self#incref x; - (match m_ctx with - | Some(x) -> x#add_one_ctx_obj - | None -> () - ) + m_ctx#add_one_ctx_obj | None -> () ); Gc.finalise (fun self -> self#dispose) self @@ -78,15 +72,9 @@ object (self) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with - | Some (x) -> self#decref x; m_n_obj <- None + | Some (x) -> self#decref x; m_n_obj <- None; m_ctx#sub_one_ctx_obj | None -> () ); - (match m_ctx with - | Some (x) -> x#sub_one_ctx_obj - | None -> () - ); - m_ctx <- None - method get_native_object = m_n_obj @@ -102,6 +90,7 @@ object (self) m_n_obj <- x method get_context = m_ctx + method get_native_context = m_ctx#get_native (* method array_to_native a = @@ -113,6 +102,57 @@ object (self) | Some(x) -> (Array.length x) | None -> 0 *) +end + +class symbol ctx_init obj_init = +object (self) + inherit z3object ctx_init obj_init + + method incref o = () + method decref o = () + + method kind = match m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") + + method is_int_symbol = match m_n_obj with + | Some(x) -> self#kind == INT_SYMBOL + | _ -> false + + method is_string_symbol = match m_n_obj with + | Some(x) -> self#kind == STRING_SYMBOL + | _ -> false + + method to_string = match m_n_obj with + | Some(x) -> + ( + match self#kind with + | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) + ) + | None -> "" + + method create ctx obj = + match obj with + | Some(x) -> ( + match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with + | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) + | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) + ) + | None -> raise (Exception "Can't create null objects") end +and intsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init + + method get_int = match m_n_obj with + | Some(x) -> (get_symbol_int m_ctx#get_native x) + | None -> 0 +end + +and stringsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end From 1685e3dd6fbf3341aadc1d6b9bfa72722b65e061 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 04:10:38 +0000 Subject: [PATCH 382/646] ML API bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 20 +++++-- scripts/update_api.py | 22 ++++--- src/api/ml/z3.ml | 121 +++++++++++++++++++++++--------------- 3 files changed, 99 insertions(+), 64 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 9c704e4d0..c79b3cdaa 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,11 +4,19 @@ *) open Z3 - -let _ = ignore(Log.open_ "z3.log") ; - let cfg = Some [("model", "true"); ("proof", "false")] in - let ctx = (new context cfg) in - Printf.printf "Disposing...\n"; - ctx#dispose ; + +exception ExampleException of string + +let _ = + if not (Log.open_ "z3.log") then + raise (ExampleException "Log couldn't be opened.") + else + ( + Printf.printf "Running Z3 version %s\n" Version.to_string ; + let cfg = [("model", "true"); ("proof", "false")] in + let ctx = (new context cfg) in + Printf.printf "Disposing...\n"; + ctx#dispose (* can do, but we'd rather let it go out of scope *) ; + ); Printf.printf "Exiting.\n"; ;; diff --git a/scripts/update_api.py b/scripts/update_api.py index a586ad6e3..25adce2af 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1,4 +1,3 @@ - ############################################ # Copyright (c) 2012 Microsoft Corporation # @@ -328,16 +327,12 @@ def param2ml(p): if k == OUT: if param_type(p) == INT or param_type(p) == UINT or param_type(p) == INT64 or param_type(p) == UINT64: return "int" - elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: - return "int" elif param_type(p) == STRING: return "string" else: return "ptr" elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: return "%s array" % type2ml(param_type(p)) - elif k == OUT_MANAGED_ARRAY: - return "%s array" % type2ml(param_type(p)); else: return type2ml(param_type(p)) @@ -1131,9 +1126,16 @@ def mk_ml(): ml_native.write('%s -> ' % param2ml(p)) if len(op) > 0: ml_native.write('(') - ml_native.write('%s' % type2ml(result)) + first = True + if result != VOID or len(op) == 0: + ml_native.write('%s' % type2ml(result)) + first = False for p in op: - ml_native.write(' * %s' % param2ml(p)) + if first: + first = False + else: + ml_native.write(' * ') + ml_native.write('%s' % param2ml(p)) if len(op) > 0: ml_native.write(')') ml_native.write('\n') @@ -1160,11 +1162,13 @@ def mk_ml(): i = i + 1 ml_native.write(' = \n') ml_native.write(' ') - if result == VOID: + if result == VOID and len(op) == 0: ml_native.write('let _ = ') else: ml_native.write('let res = ') ml_native.write('(ML2C.n_%s' % (ml_method_name(name))) + if len(ip) == 0: + ml_native.write(' ()') first = True i = 0; for p in params: @@ -1177,7 +1181,7 @@ def mk_ml(): ml_native.write(' if err <> OK then\n') ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') ml_native.write(' else\n') - if result == VOID: + if result == VOID and len(op) == 0: ml_native.write(' ()\n') else: ml_native.write(' res\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 9812bd790..31bb7e5fc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -9,12 +9,27 @@ open Z3native module Log = struct let m_is_open = false - (* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) + (* CMW: "open" seems to be an invalid function name*) + let open_ fn = let rv = (open_log fn) in + Printf.printf "ol returned %d\n" rv ; + ((int2lbool rv) == L_TRUE) + let close = close_log + let append s = append_log s end - + +module Version = +struct + let major = let (x, _, _, _) = get_version in x + let minor = let (_, x, _, _) = get_version in x + let build = let (_, _, x, _) = get_version in x + let revision = let (_, _, _, x) = get_version in x + let to_string = + string_of_int major ^ "." ^ + string_of_int minor ^ "." ^ + string_of_int build ^ "." ^ + string_of_int revision ^ "." +end + class virtual idisposable = object method virtual dispose : unit @@ -25,7 +40,7 @@ object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config() in + let cfg = mk_config in let f e = (set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = mk_context_rc cfg in @@ -34,14 +49,15 @@ object (self) val mutable m_refCount : int = 0 - initializer Gc.finalise (fun self -> self#dispose) self + initializer + Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing %d \n" (Oo.id self) ; (del_context m_n_ctx) ) else ( - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 @@ -66,9 +82,9 @@ object (self) method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) + (* + Disposes of the underlying native Z3 object. + *) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with @@ -92,16 +108,17 @@ object (self) method get_context = m_ctx method get_native_context = m_ctx#get_native - (* - method array_to_native a = +(* + method array_to_native a = let f e = e#get_native_object in (Array.map f a) - method array_length a = + method array_length a = match a with - | Some(x) -> (Array.length x) - | None -> 0 - *) + | Some(x) -> (Array.length x) + | None -> 0 +*) + end class symbol ctx_init obj_init = @@ -110,49 +127,55 @@ object (self) method incref o = () method decref o = () +end - method kind = match m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) - | _ -> raise (Exception "Underlying object lost") +class int_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_int_symbol = match m_n_obj with - | Some(x) -> self#kind == INT_SYMBOL - | _ -> false +class string_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_string_symbol = match m_n_obj with - | Some(x) -> self#kind == STRING_SYMBOL - | _ -> false - - method to_string = match m_n_obj with - | Some(x) -> - ( - match self#kind with - | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) - ) - | None -> "" - - method create ctx obj = +module Symbol = +struct + let create ctx obj = match obj with | Some(x) -> ( match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) - | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) + | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) + | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) ) | None -> raise (Exception "Can't create null objects") -end + let kind o = match o#m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") -and intsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let is_int_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == INT_SYMBOL + | _ -> false - method get_int = match m_n_obj with - | Some(x) -> (get_symbol_int m_ctx#get_native x) + let is_string_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == STRING_SYMBOL + | _ -> false + + let get_int o = match o#m_n_obj with + | Some(x) -> (get_symbol_int o#get_native_context x) | None -> 0 -end -and stringsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let get_string o = match o#m_n_obj with + | Some(x) -> (get_symbol_string o#get_native_context x) + | None -> "" + + let to_string o = match o#m_n_obj with + | Some(x) -> + ( + match (kind o) with + | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) + ) + | None -> "" end From 18a57267d1cf13d59dabcff027db7c4801ec4012 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 04:12:41 +0000 Subject: [PATCH 383/646] added temporary Makefile for ML annotations. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/api/ml/Makefile diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile new file mode 100644 index 000000000..f97a2dc30 --- /dev/null +++ b/src/api/ml/Makefile @@ -0,0 +1,6 @@ +# This is a temporary support file for emacs annotations. +# It does not compile the Z3 ML API; this will be built +# in the top-level build directory. + +all: + ocamlbuild -cflag -annot z3.cmxa \ No newline at end of file From cfa099007a2c93628ab5fae0acdf32224d1dc483 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 20 Dec 2012 20:51:18 +0000 Subject: [PATCH 384/646] ML build system checks Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 +- src/api/ml/z3.ml | 127 +++++++++++++++++++-------------------------- 2 files changed, 55 insertions(+), 77 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 38af3893f..a0f123609 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1439,7 +1439,7 @@ class MLComponent(Component): for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, self.to_src_dir)) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) @@ -1577,7 +1577,7 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example($EXE_EXT): z3.cmxa ') + out.write('ml_example($EXE_EXT): z3.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') @@ -2434,6 +2434,7 @@ def mk_bindings(api_files): _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3py_to_build() if is_ml_enabled(): + check_ml() mk_z3consts_ml(api_files) # Extract enumeration types from API files, and add python definitions. diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 31bb7e5fc..4f847bc48 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -10,26 +10,11 @@ module Log = struct let m_is_open = false (* CMW: "open" seems to be an invalid function name*) - let open_ fn = let rv = (open_log fn) in - Printf.printf "ol returned %d\n" rv ; - ((int2lbool rv) == L_TRUE) - let close = close_log - let append s = append_log s + let open_ fn = int2lbool(open_log fn) == L_TRUE + let close = (close_log) + let append s = (append_log s) end - -module Version = -struct - let major = let (x, _, _, _) = get_version in x - let minor = let (_, x, _, _) = get_version in x - let build = let (_, _, x, _) = get_version in x - let revision = let (_, _, _, x) = get_version in x - let to_string = - string_of_int major ^ "." ^ - string_of_int minor ^ "." ^ - string_of_int build ^ "." ^ - string_of_int revision ^ "." -end - + class virtual idisposable = object method virtual dispose : unit @@ -40,7 +25,7 @@ object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config in + let cfg = mk_config() in let f e = (set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = mk_context_rc cfg in @@ -49,15 +34,14 @@ object (self) val mutable m_refCount : int = 0 - initializer - Gc.finalise (fun self -> self#dispose) self + initializer Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing %d \n" (Oo.id self) ; (del_context m_n_ctx) ) else ( - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 @@ -82,9 +66,9 @@ object (self) method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) + (* + Disposes of the underlying native Z3 object. + *) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with @@ -108,17 +92,16 @@ object (self) method get_context = m_ctx method get_native_context = m_ctx#get_native -(* - method array_to_native a = + (* + method array_to_native a = let f e = e#get_native_object in (Array.map f a) - method array_length a = + method array_length a = match a with - | Some(x) -> (Array.length x) - | None -> 0 -*) - + | Some(x) -> (Array.length x) + | None -> 0 + *) end class symbol ctx_init obj_init = @@ -127,55 +110,49 @@ object (self) method incref o = () method decref o = () -end -class int_symbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init -end + method kind = match m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") -class string_symbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init -end + method is_int_symbol = match m_n_obj with + | Some(x) -> self#kind == INT_SYMBOL + | _ -> false -module Symbol = -struct - let create ctx obj = + method is_string_symbol = match m_n_obj with + | Some(x) -> self#kind == STRING_SYMBOL + | _ -> false + + method to_string = match m_n_obj with + | Some(x) -> + ( + match self#kind with + | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) + ) + | None -> "" + + method create ctx obj = match obj with | Some(x) -> ( match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) - | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) + | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) + | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) ) | None -> raise (Exception "Can't create null objects") - let kind o = match o#m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) - | _ -> raise (Exception "Underlying object lost") - - let is_int_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == INT_SYMBOL - | _ -> false - - let is_string_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == STRING_SYMBOL - | _ -> false - - let get_int o = match o#m_n_obj with - | Some(x) -> (get_symbol_int o#get_native_context x) - | None -> 0 - - let get_string o = match o#m_n_obj with - | Some(x) -> (get_symbol_string o#get_native_context x) - | None -> "" - - let to_string o = match o#m_n_obj with - | Some(x) -> - ( - match (kind o) with - | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) - ) - | None -> "" +end + +and intsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init + + method get_int = match m_n_obj with + | Some(x) -> (get_symbol_int m_ctx#get_native x) + | None -> 0 +end + +and stringsymbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init end From d8ed9be98e9224b9abfc37d90b1ea7879b35a3f0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Dec 2012 03:02:12 +0000 Subject: [PATCH 385/646] ML native layer bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- scripts/update_api.py | 165 +++++++++++++++++++++++++----------------- src/api/ml/z3.ml | 120 +++++++++++++++++------------- 3 files changed, 171 insertions(+), 116 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a0f123609..e44c120cb 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2888,7 +2888,7 @@ def mk_z3consts_ml(api_files): linenum = linenum + 1 efile.write('end\n') if VERBOSE: - print "Generated '%s/enumerations.ml'" % ('%s' % gendir) + print "Generated '%s/z3enums.ml'" % ('%s' % gendir) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 25adce2af..d0ef2ec86 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1,3 +1,4 @@ + ############################################ # Copyright (c) 2012 Microsoft Corporation # @@ -1097,6 +1098,45 @@ def is_array_param(p): else: return False +def arrayparams(params): + op = [] + for param in params: + if is_array_param(param): + op.append(param) + return op + + +def ml_unwrap(t): + if t == STRING: + return 'String_val' + elif t == BOOL or t == INT or PRINT_MODE or ERROR_CODE: + return 'Int_val' + elif t == UINT: + return 'Unsigned_int_val' + elif t == INT64: + return 'Long_val' + elif t == UINT64: + return 'Unsigned_long_val' + elif t == DOUBLE: + return 'Double_val' + else: + return 'Data_custom_val' + +def ml_set_wrap(t, d, n): + if t == VOID: + return d + ' = Val_unit;' + elif t == BOOL or t == INT or t == UINT or PRINT_MODE or ERROR_CODE: + return d + ' = Val_int(' + n + ');' + elif t == INT64 or t == UINT64: + return d + ' = Val_long(' + n + ');' + elif t == DOUBLE: + return 'Store_double_val(' + d + ', ' + n + ');' + elif t == STRING: + return d + ' = caml_copy_string((const char*) ' + n + ');' + else: + ts = type2str(t) + return d + ' = caml_alloc_custom(0, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' + def mk_ml(): global Type2Str if not is_ml_enabled(): @@ -1242,15 +1282,12 @@ def mk_ml(): for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) + ap = arrayparams(params) ret_size = len(op) if result != VOID: ret_size = ret_size + 1 # Setup frame - n_locals = 0 - for p in params: - if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): - n_locals = n_locals + 1 ml_wrapper.write('CAMLprim value n_%s(' % ml_method_name(name)) first = True i = 0 @@ -1276,46 +1313,50 @@ def mk_ml(): i = i + 1 ml_wrapper.write(');\n') i = 0 - first = True - if result != VOID: - n_locals = n_locals + 1 - if ret_size > 1: - n_locals = n_locals + 1 - if n_locals > 0: - ml_wrapper.write(' CAMLlocal%s(' % (n_locals)) - if ret_size > 1: - if result != VOID: - ml_wrapper.write('result, ') - ml_wrapper.write('result_tuple') - first = False - elif result != VOID: - ml_wrapper.write('result') - first = False + if len(op) + len(ap) == 0: + ml_wrapper.write(' CAMLlocal1(result);\n') + else: + c = 0 for p in params: - if is_out_param(p) or (is_in_param(p) and param_type(p) == STRING): - if first: - first = False - else: - ml_wrapper.write(', ') - ml_wrapper.write('_a%s' % i) + if is_out_param(p) or is_array_param(p): + c = c + 1 + ml_wrapper.write(' CAMLlocal%s(result, res_val' % (c+2)) + for p in params: + if is_out_param(p) or is_array_param(p): + ml_wrapper.write(', _a%s_val' % i) i = i + 1 ml_wrapper.write(');\n') # preprocess arrays, strings, in/out arguments i = 0 for param in params: - if param_kind(param) == OUT_ARRAY: - ml_wrapper.write(' _a%s = (long) malloc(sizeof(%s) * ((long)a%s));\n' % (i, - type2str(param_type(param)), - param_array_capacity_pos(param))) - elif param_kind(param) == IN and param_type(param) == STRING: - ml_wrapper.write(' _a%s = (value) String_val(a%s);\n' % (i, i)) + k = param_kind(param) + if k == OUT_ARRAY: + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * (_a%s));\n' % ( + type2str(param_type(param)), + i, + type2str(param_type(param)), + type2str(param_type(param)), + param_array_capacity_pos(param))) + elif k == IN_ARRAY or k == INOUT_ARRAY: + t = param_type(param) + ts = type2str(t) + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) + ml_wrapper.write(' for (unsigned i = 0; i < a%s; i++) _a%s[i] = (%s) %s(Field(a%s, i));\n' % (param_array_capacity_pos(param), i, ts, ml_unwrap(t), i)) + elif k == IN: + t = param_type(param) + ml_wrapper.write(' %s _a%s = (%s) %s(a%s);\n' % (type2str(t), i, type2str(t), ml_unwrap(t), i)) + elif k == OUT: + ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) + elif k == INOUT: + ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) + i = i + 1 # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('result = (value) ') + ml_wrapper.write('%s z3_result = ' % type2str(result)) ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1326,58 +1367,50 @@ def mk_ml(): ml_wrapper.write(', ') k = param_kind(param) if k == OUT or k == INOUT: - ml_wrapper.write('(%s)&_a%s' % (param2str(param), i)) - elif k == INOUT_ARRAY or k == IN_ARRAY: - ml_wrapper.write('(%s*)a%s' % (type2str(param_type(param)), i)) - elif k == OUT_ARRAY: - ml_wrapper.write('(%s*)_a%s' % (type2str(param_type(param)), i)) - elif k == IN and param_type(param) == STRING: - ml_wrapper.write('(Z3_string) _a%s' % i) + ml_wrapper.write('&_a%s' % i) else: - ml_wrapper.write('(%s)a%i' % (param2str(param), i)) + ml_wrapper.write('_a%i' % i) i = i + 1 ml_wrapper.write(');\n') - # return tuples + # convert output params if len(op) > 0: - ml_wrapper.write(' result_tuple = caml_alloc(%s, 0);\n' % ret_size) + if result != VOID: + ml_wrapper.write(' %s\n' % ml_set_wrap(result, "res_val", "z3_result")) + i = 0; + for p in params: + if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) + ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) { value t; %s Store_field(_a%s, i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[i]'), i)) + elif is_out_param(p): + ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) + i = i + 1 + + # return tuples + if len(op) == 0: + ml_wrapper.write(' %s\n' % ml_set_wrap(result, "result", "z3_result")) + else: + ml_wrapper.write(' result = caml_alloc(%s, 0);\n' % ret_size) i = j = 0 if result != VOID: - if result == STRING: - ml_wrapper.write(' Store_field(result_tuple, 0, caml_copy_string(result));\n') - else: - ml_wrapper.write(' Store_field(result_tuple, 0, result);\n') + ml_wrapper.write(' Store_field(result, 0, res_val);\n') j = j + 1 for p in params: - if param_kind(p) == OUT_ARRAY or param_kind(p) == OUT: - ml_wrapper.write(' Store_field(result_tuple, %s, _a%s);\n' % (j, i)) - j = j + 1; - elif is_out_param(p): - if param_type(p) == STRING: - ml_wrapper.write(' Store_field(result_tuple, %s, caml_copy_string((const char *)_a%s));\n' % (j, i)) - else: - ml_wrapper.write(' Store_field(result_tuple, %s, a%s);\n' % (j, i)) + if is_out_param(p): + ml_wrapper.write(' Store_field(result, %s, _a%s_val);\n' % (j, i)) j = j + 1; i = i + 1 # local array cleanup i = 0 for p in params: - if param_kind(p) == OUT_ARRAY: - ml_wrapper.write(' free((long*)_a%s);\n' % i) + k = param_kind(p) + if k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: + ml_wrapper.write(' free(_a%s);\n' % i) i = i + 1 # return - if len(op) > 0: - ml_wrapper.write(' CAMLreturn(result_tuple);\n') - else: - if result == STRING: - ml_wrapper.write(' CAMLreturn(caml_copy_string((const char*) result));\n') - elif result == VOID: - ml_wrapper.write(' CAMLreturn(Val_unit);\n') - elif result != VOID: - ml_wrapper.write(' CAMLreturn(result);\n') - + ml_wrapper.write(' CAMLreturn(result);\n') ml_wrapper.write('}\n\n') if len(ip) > 5: ml_wrapper.write('CAMLprim value n_%s_bytecode(value * argv, int argn) {\n' % ml_method_name(name)) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4f847bc48..d1ba2b746 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -10,11 +10,25 @@ module Log = struct let m_is_open = false (* CMW: "open" seems to be an invalid function name*) - let open_ fn = int2lbool(open_log fn) == L_TRUE - let close = (close_log) - let append s = (append_log s) + let open_ fn = ((int2lbool (open_log fn)) == L_TRUE) + let close = close_log + let append s = append_log s end - + +module Version = +struct + let major = let (x, _, _, _) = get_version in x + let minor = let (_, x, _, _) = get_version in x + let build = let (_, _, x, _) = get_version in x + let revision = let (_, _, _, x) = get_version in x + let to_string = + let (mj, mn, bld, rev) = get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + class virtual idisposable = object method virtual dispose : unit @@ -25,7 +39,7 @@ object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config() in + let cfg = mk_config in let f e = (set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = mk_context_rc cfg in @@ -34,14 +48,15 @@ object (self) val mutable m_refCount : int = 0 - initializer Gc.finalise (fun self -> self#dispose) self + initializer + Gc.finalise (fun self -> self#dispose) self method dispose : unit = if m_refCount == 0 then ( - Printf.printf "Disposing %d \n" (Oo.id self) ; + Printf.printf "Disposing context %d \n" (Oo.id self) ; (del_context m_n_ctx) ) else ( - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 @@ -66,9 +81,9 @@ object (self) method virtual incref : Z3native.ptr -> unit method virtual decref : Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) + (* + Disposes of the underlying native Z3 object. + *) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with @@ -92,16 +107,17 @@ object (self) method get_context = m_ctx method get_native_context = m_ctx#get_native - (* - method array_to_native a = +(* + method array_to_native a = let f e = e#get_native_object in (Array.map f a) - method array_length a = + method array_length a = match a with - | Some(x) -> (Array.length x) - | None -> 0 - *) + | Some(x) -> (Array.length x) + | None -> 0 +*) + end class symbol ctx_init obj_init = @@ -110,49 +126,55 @@ object (self) method incref o = () method decref o = () +end - method kind = match m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind self#get_native_context x)) - | _ -> raise (Exception "Underlying object lost") +class int_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_int_symbol = match m_n_obj with - | Some(x) -> self#kind == INT_SYMBOL - | _ -> false +class string_symbol ctx_init obj_init = +object(self) + inherit symbol ctx_init obj_init +end - method is_string_symbol = match m_n_obj with - | Some(x) -> self#kind == STRING_SYMBOL - | _ -> false - - method to_string = match m_n_obj with - | Some(x) -> - ( - match self#kind with - | INT_SYMBOL -> (string_of_int (get_symbol_int self#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string self#get_native_context x) - ) - | None -> "" - - method create ctx obj = +module Symbol = +struct + let create ctx obj = match obj with | Some(x) -> ( match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new intsymbol ctx obj :> symbol) - | STRING_SYMBOL -> (new stringsymbol ctx obj :> symbol) + | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) + | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) ) | None -> raise (Exception "Can't create null objects") -end + let kind o = match o#m_n_obj with + | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) + | _ -> raise (Exception "Underlying object lost") -and intsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let is_int_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == INT_SYMBOL + | _ -> false - method get_int = match m_n_obj with - | Some(x) -> (get_symbol_int m_ctx#get_native x) + let is_string_symbol o = match o#m_n_obj with + | Some(x) -> x#kind == STRING_SYMBOL + | _ -> false + + let get_int o = match o#m_n_obj with + | Some(x) -> (get_symbol_int o#get_native_context x) | None -> 0 -end -and stringsymbol ctx_init obj_init = -object(self) - inherit symbol ctx_init obj_init + let get_string o = match o#m_n_obj with + | Some(x) -> (get_symbol_string o#get_native_context x) + | None -> "" + + let to_string o = match o#m_n_obj with + | Some(x) -> + ( + match (kind o) with + | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) + | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) + ) + | None -> "" end From 7ae90f0b20ef3dc24e0f220f9f30db1ca870dd0c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 21 Dec 2012 07:18:46 +0000 Subject: [PATCH 386/646] More ML API: Fixes in native layer. Added symbols. Prepared code for automatic documentation. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 5 ++ scripts/mk_util.py | 89 +------------------- scripts/update_api.py | 37 ++++++--- src/api/ml/z3.ml | 168 ++++++++++++++++++++++++++------------ 4 files changed, 148 insertions(+), 151 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index c79b3cdaa..7046a92b0 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,6 +4,7 @@ *) open Z3 +open Z3.Context exception ExampleException of string @@ -15,6 +16,10 @@ let _ = Printf.printf "Running Z3 version %s\n" Version.to_string ; let cfg = [("model", "true"); ("proof", "false")] in let ctx = (new context cfg) in + let is = (mk_symbol_int ctx 42) in + let ss = (mk_symbol_string ctx "mySymbol") in + Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); + Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); Printf.printf "Disposing...\n"; ctx#dispose (* can do, but we'd rather let it go out of scope *) ; ); diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e44c120cb..5ca0d2299 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2777,99 +2777,12 @@ def mk_z3consts_ml(api_files): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) - efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ - efile.write(' match x with\n') - for k, i in decls.iteritems(): - efile.write(' | %s -> %d\n' % (k[3:], i)) - efile.write('\n') - efile.write('(** Convert int to %s*)\n' % name[3:]) - efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ - efile.write(' match x with\n') - for k, i in decls.iteritems(): - efile.write(' | %d -> %s\n' % (i, k[3:])) - # use Z3.Exception? - efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') - mode = SEARCHING - else: - if words[2] != '': - if len(words[2]) > 1 and words[2][1] == 'x': - idx = int(words[2], 16) - else: - idx = int(words[2]) - decls[words[1]] = idx - idx = idx + 1 - linenum = linenum + 1 - if VERBOSE: - print "Generated '%s/z3enums.ml'" % ('%s' % gendir) - efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') - efile.write('(* Automatically generated file *)\n\n') - efile.write('(** The enumeration types of Z3. *)\n\n') - efile.write('module Z3enums = struct\n') - for api_file in api_files: - api_file_c = ml.find_file(api_file, ml.name) - api_file = os.path.join(api_file_c.src_dir, api_file) - - api = open(api_file, 'r') - - SEARCHING = 0 - FOUND_ENUM = 1 - IN_ENUM = 2 - - mode = SEARCHING - decls = {} - idx = 0 - - linenum = 1 - for line in api: - m1 = blank_pat.match(line) - m2 = comment_pat.match(line) - if m1 or m2: - # skip blank lines and comments - linenum = linenum + 1 - elif mode == SEARCHING: - m = typedef_pat.match(line) - if m: - mode = FOUND_ENUM - m = typedef2_pat.match(line) - if m: - mode = IN_ENUM - decls = {} - idx = 0 - elif mode == FOUND_ENUM: - m = openbrace_pat.match(line) - if m: - mode = IN_ENUM - decls = {} - idx = 0 - else: - assert False, "Invalid %s, line: %s" % (api_file, linenum) - else: - assert mode == IN_ENUM - words = re.split('[^\-a-zA-Z0-9_]+', line) - m = closebrace_pat.match(line) - if m: - name = words[1] - if name not in DeprecatedEnums: - efile.write('(** %s *)\n' % name[3:]) - efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in decls.iteritems(): - efile.write(' | %s \n' % k[3:]) # strip Z3_ - efile.write('\n') - efile.write('(** Convert %s to int*)\n' % name[3:]) - efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_ - efile.write('(** Convert int to %s*)\n' % name[3:]) - efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ - efile.write('\n') - efile.write('\n(* %s *)\n' % name) - efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in decls.iteritems(): - efile.write(' | %s \n' % k[3:]) # strip Z3_ - efile.write('\n') efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') + efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): diff --git a/scripts/update_api.py b/scripts/update_api.py index d0ef2ec86..c8cd05c7e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1106,26 +1106,26 @@ def arrayparams(params): return op -def ml_unwrap(t): +def ml_unwrap(t, ts, s): if t == STRING: - return 'String_val' - elif t == BOOL or t == INT or PRINT_MODE or ERROR_CODE: - return 'Int_val' + return '(' + ts + ') String_val(' + s + ')' + elif t == BOOL or t == INT or t == PRINT_MODE or t == ERROR_CODE: + return '(' + ts + ') Int_val(' + s + ')' elif t == UINT: - return 'Unsigned_int_val' + return '(' + ts + ') Unsigned_int_val(' + s + ')' elif t == INT64: - return 'Long_val' + return '(' + ts + ') Long_val(' + s + ')' elif t == UINT64: - return 'Unsigned_long_val' + return '(' + ts + ') Unsigned_long_val(' + s + ')' elif t == DOUBLE: - return 'Double_val' + return '(' + ts + ') Double_val(' + s + ')' else: - return 'Data_custom_val' + return '* (' + ts + '*) Data_custom_val(' + s + ')' def ml_set_wrap(t, d, n): if t == VOID: return d + ' = Val_unit;' - elif t == BOOL or t == INT or t == UINT or PRINT_MODE or ERROR_CODE: + elif t == BOOL or t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: return d + ' = Val_int(' + n + ');' elif t == INT64 or t == UINT64: return d + ' = Val_long(' + n + ');' @@ -1135,7 +1135,7 @@ def ml_set_wrap(t, d, n): return d + ' = caml_copy_string((const char*) ' + n + ');' else: ts = type2str(t) - return d + ' = caml_alloc_custom(0, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' + return d + ' = caml_alloc_custom(&default_custom_ops, sizeof(' + ts + '), 0, 1); memcpy( Data_custom_val(' + d + '), &' + n + ', sizeof(' + ts + '));' def mk_ml(): global Type2Str @@ -1146,7 +1146,9 @@ def mk_ml(): ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') + ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_native.write('open Z3enums\n\n') + ml_native.write('(**/**)\n') ml_native.write('type ptr\n') ml_native.write('and z3_symbol = ptr\n') for k, v in Type2Str.iteritems(): @@ -1226,6 +1228,7 @@ def mk_ml(): else: ml_native.write(' res\n') ml_native.write('\n') + ml_native.write('(**/**)\n') # C interface ml_wrapper = open(ml_wrapperf, 'w') @@ -1276,6 +1279,14 @@ def mk_ml(): ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') ml_wrapper.write('\n\n') + ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') + ml_wrapper.write(' identifier: "default handling",\n') + ml_wrapper.write(' finalize: custom_finalize_default,\n') + ml_wrapper.write(' compare: custom_compare_default,\n') + ml_wrapper.write(' hash: custom_hash_default,\n') + ml_wrapper.write(' serialize: custom_serialize_default,\n') + ml_wrapper.write(' deserialize: custom_deserialize_default\n') + ml_wrapper.write('};\n\n') ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') @@ -1342,10 +1353,10 @@ def mk_ml(): t = param_type(param) ts = type2str(t) ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) - ml_wrapper.write(' for (unsigned i = 0; i < a%s; i++) _a%s[i] = (%s) %s(Field(a%s, i));\n' % (param_array_capacity_pos(param), i, ts, ml_unwrap(t), i)) + ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) _a%s[i] = %s;\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', i)'))) elif k == IN: t = param_type(param) - ml_wrapper.write(' %s _a%s = (%s) %s(a%s);\n' % (type2str(t), i, type2str(t), ml_unwrap(t), i)) + ml_wrapper.write(' %s _a%s = %s;\n' % (type2str(t), i, ml_unwrap(t, type2str(t), 'a' + str(i)))) elif k == OUT: ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) elif k == INOUT: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index d1ba2b746..321b17c82 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,33 +1,17 @@ -(* +(** + The Z3 ML/Ocaml Interface. + Copyright (C) 2012 Microsoft Corporation - Author: CM Wintersteiger (cwinter) 2012-12-17 + @author CM Wintersteiger (cwinter) 2012-12-17 *) open Z3enums open Z3native -module Log = -struct - let m_is_open = false - (* CMW: "open" seems to be an invalid function name*) - let open_ fn = ((int2lbool (open_log fn)) == L_TRUE) - let close = close_log - let append s = append_log s -end +(**/**) -module Version = -struct - let major = let (x, _, _, _) = get_version in x - let minor = let (_, x, _, _) = get_version in x - let build = let (_, _, x, _) = get_version in x - let revision = let (_, _, _, x) = get_version in x - let to_string = - let (mj, mn, bld, rev) = get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end +(* Object definitions. These are internal and should be interacted + with only via the corresponding functions from modules. *) class virtual idisposable = object @@ -61,7 +45,7 @@ object (self) method sub_one_ctx_obj = m_refCount <- m_refCount - 1 method add_one_ctx_obj = m_refCount <- m_refCount + 1 - method get_native = m_n_ctx + method gno = m_n_ctx end class virtual z3object ctx_init obj_init = @@ -91,9 +75,9 @@ object (self) | None -> () ); - method get_native_object = m_n_obj + method gno = m_n_obj - method set_native_object x = + method sno x = (match x with | Some(x) -> self#incref x | None -> () @@ -105,11 +89,11 @@ object (self) m_n_obj <- x method get_context = m_ctx - method get_native_context = m_ctx#get_native + method gnc = m_ctx#gno (* method array_to_native a = - let f e = e#get_native_object in + let f e = e#gno in (Array.map f a) method array_length a = @@ -120,61 +104,145 @@ object (self) end -class symbol ctx_init obj_init = +class symbol ctx obj = object (self) - inherit z3object ctx_init obj_init + inherit z3object ctx obj method incref o = () method decref o = () end -class int_symbol ctx_init obj_init = +class int_symbol ctx = object(self) - inherit symbol ctx_init obj_init + inherit symbol ctx None + method cnstr_obj obj = (self#sno obj) ; self + method cnstr_int i = (self#sno (Some (mk_int_symbol ctx#gno i))) ; self end -class string_symbol ctx_init obj_init = +class string_symbol ctx = object(self) - inherit symbol ctx_init obj_init + inherit symbol ctx None + method cnstr_obj obj = (self#sno obj) ; self + method cnstr_string name = (self#sno (Some (mk_string_symbol ctx#gno name))) ; self end +(**/**) + +(** Interaction logging for Z3. + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log = +struct + (** Open an interaction log file. + @param filename the name of the file to open. + @return True if opening the log file succeeds, false otherwise. + *) + (* CMW: "open" seems to be a reserved keyword? *) + let open_ filename = ((int2lbool (open_log filename)) == L_TRUE) + + (** Closes the interaction log. *) + let close = close_log + + (** Appends a user-provided string to the interaction log. + @param s the string to append*) + let append s = append_log s +end + +(** Version information. *) +module Version = +struct + (** The major version. *) + let major = let (x, _, _, _) = get_version in x + + (** The minor version. *) + let minor = let (_, x, _, _) = get_version in x + + (** The build version. *) + let build = let (_, _, x, _) = get_version in x + + (** The revision. *) + let revision = let (_, _, _, x) = get_version in x + + (** A string representation of the version information. *) + let to_string = + let (mj, mn, bld, rev) = get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + +(** Symbols are used to name several term and type constructors. *) module Symbol = struct +(**/**) let create ctx obj = match obj with | Some(x) -> ( - match (int2symbol_kind (get_symbol_kind ctx#get_native x)) with - | INT_SYMBOL -> (new int_symbol ctx obj :> symbol) - | STRING_SYMBOL -> (new string_symbol ctx obj :> symbol) + match (int2symbol_kind (get_symbol_kind ctx#gno x)) with + | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj obj) :> symbol) + | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj obj) :> symbol) ) | None -> raise (Exception "Can't create null objects") +(**/**) - let kind o = match o#m_n_obj with - | Some(x) -> (int2symbol_kind (get_symbol_kind o#get_native_context x)) + (** The kind of the symbol (int or string) *) + let kind (o : symbol) = match o#gno with + | Some(x) -> (int2symbol_kind (get_symbol_kind o#gnc x)) | _ -> raise (Exception "Underlying object lost") - let is_int_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == INT_SYMBOL + (** Indicates whether the symbol is of Int kind *) + let is_int_symbol (o : symbol) = match o#gno with + | Some(x) -> (kind o) == INT_SYMBOL | _ -> false - let is_string_symbol o = match o#m_n_obj with - | Some(x) -> x#kind == STRING_SYMBOL + (** Indicates whether the symbol is of string kind. *) + let is_string_symbol (o : symbol) = match o#gno with + | Some(x) -> (kind o) == STRING_SYMBOL | _ -> false - let get_int o = match o#m_n_obj with - | Some(x) -> (get_symbol_int o#get_native_context x) + (** The int value of the symbol. *) + let get_int (o : int_symbol) = match o#gno with + | Some(x) -> (get_symbol_int o#gnc x) | None -> 0 - let get_string o = match o#m_n_obj with - | Some(x) -> (get_symbol_string o#get_native_context x) + (** The string value of the symbol. *) + let get_string (o : string_symbol) = match o#gno with + | Some(x) -> (get_symbol_string o#gnc x) | None -> "" - let to_string o = match o#m_n_obj with + (** A string representation of the symbol. *) + let to_string (o : symbol) = match o#gno with | Some(x) -> ( match (kind o) with - | INT_SYMBOL -> (string_of_int (get_symbol_int o#get_native_context x)) - | STRING_SYMBOL -> (get_symbol_string o#get_native_context x) + | INT_SYMBOL -> (string_of_int (get_symbol_int o#gnc x)) + | STRING_SYMBOL -> (get_symbol_string o#gnc x) ) | None -> "" end + +(** The main interaction with Z3 happens via the Context. *) +module Context = +struct + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_symbol_int ctx i = + (new int_symbol ctx)#cnstr_int i + + (** Creates a new symbol using a string. *) + let mk_symbol_string ctx s = + (new string_symbol ctx)#cnstr_string s + + (** + Create an array of symbols. + *) + let mk_symbols ctx names = + let f elem = mk_symbol_string ctx elem in + (Array.map f names) + +end From a2ad7d91bc29b8cec52a2fceed1aa5d655966bf4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 00:51:07 +0000 Subject: [PATCH 387/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 6 +- src/api/ml/z3.ml | 5746 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 5659 insertions(+), 93 deletions(-) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index f97a2dc30..4d4a6c08f 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -3,4 +3,8 @@ # in the top-level build directory. all: - ocamlbuild -cflag -annot z3.cmxa \ No newline at end of file + ocamlbuild -cflag -annot z3.cmxa + +doc: *.ml + mkdir -p doc + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml *.ml -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 321b17c82..2100f371e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -6,7 +6,6 @@ *) open Z3enums -open Z3native (**/**) @@ -18,27 +17,28 @@ object method virtual dispose : unit end +(** Context objects *) class context settings = object (self) inherit idisposable val mutable m_n_ctx : Z3native.z3_context = - let cfg = mk_config in - let f e = (set_param_value cfg (fst e) (snd e)) in + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; - let v = mk_context_rc cfg in - del_config(cfg) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; v val mutable m_refCount : int = 0 initializer Gc.finalise (fun self -> self#dispose) self - + method dispose : unit = if m_refCount == 0 then ( Printf.printf "Disposing context %d \n" (Oo.id self) ; - (del_context m_n_ctx) + (Z3native.del_context m_n_ctx) ) else ( (* re-queue for finalization? *) ) @@ -48,6 +48,8 @@ object (self) method gno = m_n_ctx end + +(** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) inherit idisposable @@ -56,14 +58,14 @@ object (self) initializer (match m_n_obj with - | Some (x) -> self#incref x; + | Some (x) -> self#incref m_ctx#gno x; m_ctx#add_one_ctx_obj | None -> () ); Gc.finalise (fun self -> self#dispose) self - method virtual incref : Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> unit + method virtual incref : Z3native.ptr -> Z3native.ptr -> unit + method virtual decref : Z3native.ptr -> Z3native.ptr -> unit (* Disposes of the underlying native Z3 object. @@ -71,61 +73,415 @@ object (self) method dispose = Printf.printf "Disposing z3object %d \n" (Oo.id self) ; (match m_n_obj with - | Some (x) -> self#decref x; m_n_obj <- None; m_ctx#sub_one_ctx_obj + | Some (x) -> self#decref m_ctx#gno x; m_n_obj <- None; m_ctx#sub_one_ctx_obj | None -> () ); - method gno = m_n_obj + method gno = match m_n_obj with + | Some(x) -> x + | None -> raise (Z3native.Exception "Z3 object lost") - method sno x = - (match x with - | Some(x) -> self#incref x - | None -> () - ); + method sno nc o = + self#incref nc o ; (match m_n_obj with - | Some(x) -> self#decref x + | Some(x) -> self#decref nc x | None -> () ); - m_n_obj <- x + m_n_obj <- Some o - method get_context = m_ctx + method gc = m_ctx method gnc = m_ctx#gno - -(* - method array_to_native a = - let f e = e#gno in - (Array.map f a) - - method array_length a = - match a with - | Some(x) -> (Array.length x) - | None -> 0 -*) - end -class symbol ctx obj = + +(** Parameter set objects *) +class params ctx obj = object (self) - inherit z3object ctx obj - - method incref o = () - method decref o = () + inherit z3object ctx obj as super + method incref ctx o = Z3native.params_inc_ref ctx o + method decref ctx o = Z3native.params_dec_ref ctx o end + +(** Symbol objects *) +class symbol ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method incref ctx o = () + method decref ctx o = () +end + +let symbolaton (a : symbol array) = + let f (e : symbol) = e#gno in + Array.map f a + +(** Int symbol objects *) class int_symbol ctx = object(self) - inherit symbol ctx None - method cnstr_obj obj = (self#sno obj) ; self - method cnstr_int i = (self#sno (Some (mk_int_symbol ctx#gno i))) ; self + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_int i = (self#sno ctx#gno (Z3native.mk_int_symbol ctx#gno i)) ; self end +(** String symbol objects *) class string_symbol ctx = object(self) - inherit symbol ctx None - method cnstr_obj obj = (self#sno obj) ; self - method cnstr_string name = (self#sno (Some (mk_string_symbol ctx#gno name))) ; self + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_string name = (self#sno ctx#gno (Z3native.mk_string_symbol ctx#gno name)) ; self end +let create_symbol ctx no = + match (int2symbol_kind (Z3native.get_symbol_kind ctx#gno no)) with + | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) + | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) + +(** AST objects *) +class ast ctx = +object (self) + inherit z3object ctx None as super (* CMW: derive from icomparable? *) + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + + method incref nc o = Z3native.inc_ref nc o + method decref nc o = Z3native.dec_ref nc o +end + +let astaton (a : ast array) = + let f (e : ast) = e#gno in + Array.map f a + +(** Sort objects *) +class sort ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Arithmetic sort objects, i.e., Int or Real. *) +class arith_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Array sorts objects *) +class array_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx#gno (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self +end + +(** Bit-vector sort objects *) +class bitvec_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Boolean sort objects *) +class bool_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Datatype sort objects *) +class datatype_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_sc (name : symbol) constructors = (self#sno ctx#gno (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self +end + +(** Enum sort objects *) +class enum_sort ctx = +object (self) + inherit sort ctx as super + val mutable _constdecls = None + val mutable _testerdecls = None + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ss (name : symbol) (enum_names : symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + _constdecls <- Some a ; + _testerdecls <- Some b ; + (self#sno ctx#gno r) ; + self + + method const_decls = match _constdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing const decls") + + method tester_decls = match _testerdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tester decls") +end + +(** Int sort objects *) +class int_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Real sort objects *) +class real_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Uninterpreted sort objects *) +class uninterpreted_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_s (s : symbol) = (self #sno ctx#gno (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self +end + +(** Finite domain sort objects *) +class finite_domain_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx#gno (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self +end + +(** Relation sort objects *) +class relation_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** List sort objects *) +class list_sort ctx = +object (self) + inherit sort ctx as super + val mutable _nildecl = None + val mutable _is_nildecl = None + val mutable _consdecl = None + val mutable _is_consdecl = None + val mutable _headdecl = None + val mutable _taildecl = None + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ss (name : symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + _nildecl <- Some a ; + _is_nildecl <- Some b ; + _consdecl <- Some c ; + _is_consdecl <- Some d ; + _headdecl <- Some e ; + _taildecl <- Some f ; + (self#sno ctx#gno r) ; + self + + method nil_decl = match _nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing nil decl") + + method is_nil_decl = match _is_nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_nil decls") + + method cons_decl = match _consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing cons decls") + + method is_cons_decl = match _is_consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_cons decls") + + method head_decl = match _headdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing head decls") + + method tail_decl = match _taildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tail decls") + +end + +(** Set sort objects *) +class set_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_s (s : sort) = (self#sno ctx#gno s#gno) ; self +end + +(** Tuple sort objects *) +class tuple_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = + let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + (self#sno ctx#gno x) ; + self +end + +let create_sort ctx obj = + match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) + | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) + | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) + | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) + | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) + | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) + | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) + | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) + | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + +(** Function declaration objects *) +class func_decl ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + + method incref nc o = super#incref nc o + method decref nc o = super#decref nc o +end + +class parameter = +object (self) + val mutable m_kind : parameter_kind = PARAMETER_INT; + val mutable m_i : int = 0 + val mutable m_d : float = 0.0 + val mutable m_sym : symbol option = None + val mutable m_srt : sort option = None + val mutable m_ast : ast option = None + val mutable m_fd : func_decl option = None + val mutable m_r : string = "" + + method cnstr_int i = m_kind <- PARAMETER_INT; m_i <- i + method cnstr_double d = m_kind <- PARAMETER_DOUBLE; m_d <- d + method cnstr_symbol sym = m_kind <- PARAMETER_SYMBOL; m_sym <- sym + method cnstr_sort srt = m_kind <- PARAMETER_SORT; m_srt <- srt + method cnstr_ast ast = m_kind <- PARAMETER_AST; m_ast <- ast + method cnstr_func_decl fd = m_kind <- PARAMETER_FUNC_DECL; m_fd <- fd + method cnstr_rational r = m_kind <- PARAMETER_RATIONAL; m_r <- r + + method kind = m_kind + method int = m_i + method double = m_d + method symbol = match m_sym with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter symbol") + method sort = match m_srt with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter sort") + method ast = match m_ast with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter ast") + method func_decl = match m_fd with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing parameter func_decl") + method rational = m_r +end + +(** Expression objects *) +class expr ctx = +object(self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +let expraton (a : expr array) = + let f (e : expr) = e#gno in + Array.map f a + +(** Boolean expression objects *) +class bool_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Arithmetic expression objects (int/real) *) +class arith_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Int expression objects *) +class int_expr ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Real expression objects *) +class real_expr ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Bit-vector expression objects *) +class bitvec_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Array expression objects *) +class array_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Datatype expression objects *) +class datatype_expr ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Integer numeral expression objects *) +class int_num ctx = +object (self) + inherit int_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Rational numeral expression objects *) +class rat_num ctx = +object (self) + inherit real_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Bit-vector numeral expression objects *) +class bitvec_num ctx = +object (self) + inherit bitvec_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + +(** Algebraic numeral expression objects *) +class algebraic_num ctx = +object (self) + inherit arith_expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + + +(** Quantifier objects *) +class quantifier ctx = +object (self) + inherit expr ctx as super + method cnstr_obj obj = (self#sno ctx#gno obj) ; self +end + + + (**/**) (** Interaction logging for Z3. @@ -138,34 +494,34 @@ struct @return True if opening the log file succeeds, false otherwise. *) (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((int2lbool (open_log filename)) == L_TRUE) + let open_ filename = ((int2lbool (Z3native.open_log filename)) == L_TRUE) (** Closes the interaction log. *) - let close = close_log + let close = Z3native.close_log (** Appends a user-provided string to the interaction log. @param s the string to append*) - let append s = append_log s + let append s = Z3native.append_log s end (** Version information. *) module Version = struct (** The major version. *) - let major = let (x, _, _, _) = get_version in x + let major = let (x, _, _, _) = Z3native.get_version in x (** The minor version. *) - let minor = let (_, x, _, _) = get_version in x + let minor = let (_, x, _, _) = Z3native.get_version in x (** The build version. *) - let build = let (_, _, x, _) = get_version in x + let build = let (_, _, x, _) = Z3native.get_version in x (** The revision. *) - let revision = let (_, _, _, x) = get_version in x + let revision = let (_, _, _, x) = Z3native.get_version in x (** A string representation of the version information. *) let to_string = - let (mj, mn, bld, rev) = get_version in + let (mj, mn, bld, rev) = Z3native.get_version in string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ @@ -174,75 +530,5281 @@ end (** Symbols are used to name several term and type constructors. *) module Symbol = -struct -(**/**) - let create ctx obj = - match obj with - | Some(x) -> ( - match (int2symbol_kind (get_symbol_kind ctx#gno x)) with - | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj obj) :> symbol) - | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj obj) :> symbol) - ) - | None -> raise (Exception "Can't create null objects") -(**/**) - +struct (** The kind of the symbol (int or string) *) - let kind (o : symbol) = match o#gno with - | Some(x) -> (int2symbol_kind (get_symbol_kind o#gnc x)) - | _ -> raise (Exception "Underlying object lost") + let kind (o : symbol) = (int2symbol_kind (Z3native.get_symbol_kind o#gnc o#gno)) (** Indicates whether the symbol is of Int kind *) - let is_int_symbol (o : symbol) = match o#gno with - | Some(x) -> (kind o) == INT_SYMBOL - | _ -> false + let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL (** Indicates whether the symbol is of string kind. *) - let is_string_symbol (o : symbol) = match o#gno with - | Some(x) -> (kind o) == STRING_SYMBOL - | _ -> false + let is_string_symbol (o : symbol) = (kind o) == STRING_SYMBOL (** The int value of the symbol. *) - let get_int (o : int_symbol) = match o#gno with - | Some(x) -> (get_symbol_int o#gnc x) - | None -> 0 + let get_int (o : int_symbol) = Z3native.get_symbol_int o#gnc o#gno (** The string value of the symbol. *) - let get_string (o : string_symbol) = match o#gno with - | Some(x) -> (get_symbol_string o#gnc x) - | None -> "" + let get_string (o : string_symbol) = Z3native.get_symbol_string o#gnc o#gno (** A string representation of the symbol. *) - let to_string (o : symbol) = match o#gno with - | Some(x) -> - ( - match (kind o) with - | INT_SYMBOL -> (string_of_int (get_symbol_int o#gnc x)) - | STRING_SYMBOL -> (get_symbol_string o#gnc x) - ) - | None -> "" + let to_string (o : symbol) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) + | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) end -(** The main interaction with Z3 happens via the Context. *) + +(** + The Sort module implements type information for ASTs. +*) +module Sort = +struct + (** + Comparison operator. + @param a A sort + @param b A sort + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) (a : sort) (b : sort) = (a == b) || + if a#gnc != b#gnc then + false + else + ((int2lbool (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + + (** + Returns a unique identifier for the sort. + *) + let get_id (x : sort) = Z3native.get_sort_id x#gnc x#gno + + (** + The kind of the sort. + *) + let get_sort_kind (x : sort) = (int2sort_kind (Z3native.get_sort_kind x#gnc x#gno)) + + (** + The name of the sort + *) + let get_name (x : sort) = (create_symbol x#gc (Z3native.get_sort_name x#gnc x#gno)) + + (** + A string representation of the sort. + *) + let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno +end + +(** Array sorts *) +module ArraySort = +struct + (** The domain of the array sort. *) + let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + + (** The range of the array sort. *) + let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) +end + +(** Bit-vector sorts *) +module BitVectorSort = +struct + (** The size of the bit-vector sort. *) + let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno +end + +(** Finite domain sorts. *) +module FiniteDomainSort = +struct + (** The size of the finite domain sort. *) + let get_size (x : finite_domain_sort) = + let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") +end + +(** Relation sorts. *) +module RelationSort = +struct + (** The arity of the relation sort. *) + let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + + (** The sorts of the columns of the relation sort. *) + let get_column_sorts (x : relation_sort) = + let n = get_arity x in + let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + Array.init n f + +end + +(**/**) +let create_expr ctx obj = + if int2ast_kind (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + (((new quantifier ctx)#cnstr_obj obj) :> expr) + else + let s = Z3native.get_sort ctx#gno obj in + let sk = (int2sort_kind (Z3native.get_sort_kind ctx#gno s)) in + if (int2lbool (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + (((new algebraic_num ctx)#cnstr_obj obj) :> expr) + else + if ((int2lbool (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + match sk with + | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) + | REAL_SORT -> (((new rat_num ctx)#cnstr_obj obj) :> expr) + | BV_SORT -> (((new bitvec_num ctx)#cnstr_obj obj) :> expr) + | _ -> raise (Z3native.Exception "Unsupported numeral object") + else + match sk with + | BOOL_SORT -> (((new bool_expr ctx)#cnstr_obj obj) :> expr) + | INT_SORT -> (((new int_expr ctx)#cnstr_obj obj) :> expr) + | REAL_SORT -> (((new real_expr ctx)#cnstr_obj obj) :> expr) + | BV_SORT -> (((new bitvec_expr ctx)#cnstr_obj obj) :> expr) + | ARRAY_SORT -> (((new array_expr ctx)#cnstr_obj obj) :> expr) + | DATATYPE_SORT -> (((new datatype_expr ctx)#cnstr_obj obj) :> expr) + | _ -> (new expr ctx)#cnstr_obj obj + +let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = + let o = Z3native.mk_app ctx#gno f#gno (Array.length args) (astaton args) in + create_expr ctx o + +let create_ast ctx no = + match (int2ast_kind (Z3native.get_ast_kind ctx#gno no)) with + | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) + | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) + | SORT_AST -> ((create_sort ctx no) :> ast) + | APP_AST + | NUMERAL_AST + | VAR_AST -> ((create_expr ctx no) :> ast) + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") +(**/**) + +(** Function declarations. *) +module FuncDecl = +struct +(** Parameters of Func_Decls *) + module Parameter = + struct + (** + The kind of the parameter. + *) + let get_kind (x : parameter) = x#kind + + (**The int value of the parameter.*) + let get_int (x : parameter) = + if (x#kind != PARAMETER_INT) then + raise (Z3native.Exception "parameter is not an int") + else + x#int + + (**The double value of the parameter.*) + let get_double (x : parameter) = + if (x#kind != PARAMETER_DOUBLE) then + raise (Z3native.Exception "parameter is not a double") + else + x#double + + (**The Symbol value of the parameter.*) + let get_symbol (x : parameter) = + if (x#kind != PARAMETER_SYMBOL) then + raise (Z3native.Exception "parameter is not a symbol") + else + x#symbol + + (**The Sort value of the parameter.*) + let get_sort (x : parameter) = + if (x#kind != PARAMETER_SORT) then + raise (Z3native.Exception "parameter is not a sort") + else + x#sort + + (**The AST value of the parameter.*) + let get_ast (x : parameter) = + if (x#kind != PARAMETER_AST) then + raise (Z3native.Exception "parameter is not an ast") + else + x#ast + + (**The FunctionDeclaration value of the parameter.*) + let get_ast (x : parameter) = + if (x#kind != PARAMETER_FUNC_DECL) then + raise (Z3native.Exception "parameter is not an function declaration") + else + x#func_decl + + (**The rational string value of the parameter.*) + let get_rational (x : parameter) = + if (x#kind != PARAMETER_RATIONAL) then + raise (Z3native.Exception "parameter is not a ratinoal string") + else + x#rational + end + + (** + Comparison operator. + @param a A func_decl + @param b A func_decl + @return True if and are from the same context + and represent the same func_decl; false otherwise. + *) + let ( = ) (a : func_decl) (b : func_decl) = (a == b) || + if a#gnc == a#gnc then + false + else + ((int2lbool (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + (** + A string representations of the function declaration. + *) + let to_string (x : func_decl) = Z3native.func_decl_to_string x#gnc x#gno + + (** + Returns a unique identifier for the function declaration. + *) + let get_id (x : func_decl) = Z3native.get_func_decl_id x#gnc x#gno + + (** + The arity of the function declaration + *) + let get_arity (x : func_decl) = Z3native.get_arity x#gnc x#gno + + (** + The size of the domain of the function declaration + + *) + let get_domain_size (x : func_decl) = Z3native.get_domain_size x#gnc x#gno + + (** + The domain of the function declaration + *) + let get_domain (x : func_decl) = + let n = (get_domain_size x) in + let f i = create_sort x#gc (Z3native.get_domain x#gnc x#gno i) in + Array.init n f + + (** + The range of the function declaration + *) + let get_range (x : func_decl) = + create_sort x#gc (Z3native.get_range x#gnc x#gno) + + (** + The kind of the function declaration. + *) + let get_decl_kind (x : func_decl) = (int2decl_kind (Z3native.get_decl_kind x#gnc x#gno)) + + (** + The name of the function declaration + *) + let get_name (x : func_decl) = (create_symbol x#gc (Z3native.get_decl_name x#gnc x#gno)) + + (** + The number of parameters of the function declaration + *) + let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) + + (** + The parameters of the function declaration + *) + let get_parameters (x : func_decl) = + let n = (get_num_parameters x) in + let f i = ( + match (int2parameter_kind (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with + | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) + | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) + | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SORT -> (new parameter)#cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) + | PARAMETER_AST -> (new parameter)#cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) + | PARAMETER_FUNC_DECL -> (new parameter)#cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) + | PARAMETER_RATIONAL -> (new parameter)#cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) + ) in + Array.init n f + + (** + Create expression that applies function to arguments. + + *) + let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args + +end + +(** Datatype sorts *) +module DatatypeSort = +struct + (** The number of constructors of the datatype sort. *) + let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + + (** The range of the array sort. *) + let get_constructors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + Array.init n f + + (** The recognizers. *) + let get_recognizers (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + Array.init n f + + (** The constructor accessors. *) + let get_accessors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = ( + let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in + let ds = (Z3native.get_domain_size fd#gnc fd#gno) in + let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + Array.init ds g + ) in + Array.init n f +end + +(** Enumeration sorts. *) +module EnumSort = +struct + (** The function declarations of the constants in the enumeration. *) + let get_const_decls (x : enum_sort) = + let f e = ((new func_decl x#gc)#cnstr_obj e) in + Array.map f x#const_decls + + (** The test predicates for the constants in the enumeration. *) + let get_tester_decls (x : enum_sort) = + let f e = ((new func_decl x#gc)#cnstr_obj e) in + Array.map f x#tester_decls +end + +(** List sorts. *) +module ListSort = +struct + (** The declaration of the nil function of this list sort. *) + let get_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#nil_decl + + (** The declaration of the isNil function of this list sort. *) + let get_is_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_nil_decl + + (** The declaration of the cons function of this list sort. *) + let get_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#cons_decl + + (** The declaration of the isCons function of this list sort. *) + let get_is_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_cons_decl + + (** The declaration of the head function of this list sort.*) + let get_head_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#head_decl + + (** The declaration of the tail function of this list sort. *) + let get_tail_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#tail_decl + + (** The empty list. *) + let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] +end + +module TupleSort = +struct + (** The constructor function of the tuple.*) + let get_mk_decl (x : tuple_sort) = + (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + + (** The number of fields in the tuple. *) + let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + + (** The field declarations. *) + let get_field_decls (x : tuple_sort) = + let n = get_num_fields x in + let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + Array.init n f +end + +(** The abstract syntax tree (AST) module. *) +module AST = +struct + (** + The AST's hash code. + @return A hash code + *) + let get_hash_code ( x : ast) = Z3native.get_ast_hash x#gnc x#gno + + (** + A unique identifier for the AST (unique among all ASTs). + *) + let get_id ( x : ast) = Z3native.get_ast_id x#gnc x#gno + + (** + The kind of the AST. + *) + let get_ast_kind ( x : ast) = (int2ast_kind (Z3native.get_ast_kind x#gnc x#gno)) + + (** + Indicates whether the AST is an Expr + *) + let is_expr ( x : ast) = + match get_ast_kind ( x : ast) with + | APP_AST + | NUMERAL_AST + | QUANTIFIER_AST + | VAR_AST -> true + | _ -> false + + (** + Indicates whether the AST is a BoundVariable + *) + let is_var ( x : ast) = (get_ast_kind x) == VAR_AST + + (** + Indicates whether the AST is a Quantifier + *) + let is_quantifier ( x : ast) = (get_ast_kind x) == QUANTIFIER_AST + + + (** + Indicates whether the AST is a Sort + *) + let is_sort ( x : ast) = (get_ast_kind x) == SORT_AST + + (** + Indicates whether the AST is a FunctionDeclaration + *) + let is_func_decl ( x : ast) = (get_ast_kind x) == FUNC_DECL_AST + + (** + A string representation of the AST. + *) + let to_string ( x : ast) = Z3native.ast_to_string x#gnc x#gno + + (** + A string representation of the AST in s-expression notation. + *) + let to_sexpr ( x : ast) = Z3native.ast_to_string x#gnc x#gno + + (** + Comparison operator. + @param a An AST + @param b An AST + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) (a : expr) (b : expr) = (a == b) || + if a#gnc == b#gnc then + false + else + ((int2lbool (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + + (** + Object Comparison. + @param other Another ast + @return Negative if the object should be sorted before , positive if after else zero. + *) + let compare a b = + if (get_id a) < (get_id b) then -1 else + if (get_id a) > (get_id b) then 1 else + 0 + + (** Operator < *) + let ( < ) (a : ast) (b : ast) = (compare a b) + + (** + Translates (copies) the AST to the Context . + @param ctx A context + @return A copy of the AST which is associated with + *) + let translate ( x : ast) to_ctx = + if x#gc == to_ctx then + x + else + (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) +end + +(** + Parameter sets + + A Params objects represents a configuration in the form of Symbol/value pairs. +*) +module Params = +struct + (** + Adds a parameter setting. + *) + let add_bool (p : params) (name : symbol) (value : bool) = + Z3native.params_set_bool p#gnc p#gno name#gno (lbool2int (if value then L_TRUE else L_FALSE)) + + (** + Adds a parameter setting. + *) + let add_int (p : params) (name : symbol) (value : int) = + Z3native.params_set_uint p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_double (p : params) (name : symbol) (value : float) = + Z3native.params_set_double p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol (p : params) (name : symbol) (value : symbol) = + Z3native.params_set_symbol p#gnc p#gno name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool (p : params) (name : string) (value : bool) = + add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_int (p : params) (name : string) (value : int) = + add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_double (p : params) (name : string) (value : float) = + add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol (p : params) (name : string) (value : symbol) = + add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + A string representation of the parameter set. + *) + let to_string (p : params) = Z3native.params_to_string p#gnc p#gno +end + +(** Expressions (terms) *) +module Expr = +struct + (** + Returns a simplified version of the expression. + A set of parameters to configure the simplifier + + *) + let simplify ( x : expr ) ( p : params option ) = match p with + | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) + | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) + + (** + The function declaration of the function that is applied in this expression. + *) + let get_func_decl ( x : expr ) = (new func_decl x#gc)#cnstr_obj (Z3native.get_app_decl x#gnc x#gno) + + (** + Indicates whether the expression is the true or false expression + or something else (Z3_L_UNDEF). + *) + let get_bool_value ( x : expr ) = int2lbool (Z3native.get_bool_value x#gnc x#gno) + + (** + The number of arguments of the expression. + *) + let get_num_args ( x : expr ) = Z3native.get_app_num_args x#gnc x#gno + + (** + The arguments of the expression. + *) + let get_args ( x : expr ) = let n = (get_num_args x) in + let f i = create_expr x#gc (Z3native.get_app_arg x#gnc x#gno i) in + Array.init n f + + (** + Update the arguments of the expression using the arguments + The number of new arguments should coincide with the current number of arguments. + *) + let update ( x : expr ) args = + if (Array.length args <> (get_num_args x)) then + raise (Z3native.Exception "Number of arguments does not match") + else + x#sno x#gnc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + + (** + Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. + + *) + let substitute ( x : expr ) from to_ = + if (Array.length from) <> (Array.length to_) then + raise (Z3native.Exception "Argument sizes do not match") + else + create_expr x#gc (Z3native.substitute x#gnc x#gno (Array.length from) (expraton from) (expraton to_)) + + (** + Substitute every occurrence of from in the expression with to. + + *) + let substitute_one ( x : expr ) from to_ = + substitute ( x : expr ) [| from |] [| to_ |] + + (** + Substitute the free variables in the expression with the expressions in + + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. + + *) + let substitute_vars ( x : expr ) to_ = + create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) + + + (** + Translates (copies) the term to the Context . + A context + A copy of the term which is associated with + *) + let translate ( x : expr ) to_ctx = + if x#gc == to_ctx then + x + else + create_expr to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno) + + (** + Returns a string representation of the expression. + *) + let to_string ( x : expr ) = Z3native.ast_to_string x#gnc x#gno + + (** + Indicates whether the term is a numeral + *) + let is_numeral ( x : expr ) = int2lbool (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + + (** + Indicates whether the term is well-sorted. + True if the term is well-sorted, false otherwise. + *) + let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + + (** + The Sort of the term. + *) + let get_sort ( x : expr ) = create_sort x#gc (Z3native.get_sort x#gnc x#gno) + + (** + Indicates whether the term has Boolean sort. + *) + let is_bool ( x : expr ) = (AST.is_expr x) && + (int2lbool (Z3native.is_eq_sort x#gnc + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno))) == L_TRUE + + (** + Indicates whether the term is of integer sort. + *) + let is_int ( x : expr ) = + ((int2lbool (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + + (** + Indicates whether the term is of sort real. + *) + let is_real ( x : expr ) = + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + + (** + Indicates whether the term is of an array sort. + *) + let is_array ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + + (** + Indicates whether the term represents a constant. + *) + let is_const ( x : expr ) = (AST.is_expr x) && + (get_num_args x) == 0 && + FuncDecl.get_domain_size(get_func_decl x) == 0 + + (** + Indicates whether the term is an integer numeral. + *) + let is_int_numeral ( x : expr ) = (is_numeral x) && (is_int x) + + (** + Indicates whether the term is a real numeral. + *) + let is_rat_num ( x : expr ) = (is_numeral x) && (is_real x) + + (** + Indicates whether the term is an algebraic number + *) + let is_algebraic_number ( x : expr ) = int2lbool(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + + (** + Indicates whether the term is the constant true. + *) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + + (** + Indicates whether the term is the constant false. + *) + let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + + (** + Indicates whether the term is an equality predicate. + *) + let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + + (** + Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). + *) + let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + + (** + Indicates whether the term is a ternary if-then-else term + *) + let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + + (** + Indicates whether the term is an n-ary conjunction + *) + let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + + (** + Indicates whether the term is an n-ary disjunction + *) + let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + + (** + Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) + *) + let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + + (** + Indicates whether the term is an exclusive or + *) + let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + + (** + Indicates whether the term is a negation + *) + let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + + (** + Indicates whether the term is an implication + *) + let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + + (** + Indicates whether the term is an arithmetic numeral. + *) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ANUM) + + (** + Indicates whether the term is a less-than-or-equal + *) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LE) + + (** + Indicates whether the term is a greater-than-or-equal + *) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GE) + + (** + Indicates whether the term is a less-than + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LT) + + (** + Indicates whether the term is a greater-than + *) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GT) + + (** + Indicates whether the term is addition (binary) + *) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ADD) + + (** + Indicates whether the term is subtraction (binary) + *) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SUB) + + (** + Indicates whether the term is a unary minus + *) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UMINUS) + + (** + Indicates whether the term is multiplication (binary) + *) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MUL) + + (** + Indicates whether the term is division (binary) + *) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DIV) + + (** + Indicates whether the term is integer division (binary) + *) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IDIV) + + (** + Indicates whether the term is remainder (binary) + *) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REM) + + (** + Indicates whether the term is modulus (binary) + *) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MOD) + + (** + Indicates whether the term is a coercion of integer to real (unary) + *) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_REAL) + + (** + Indicates whether the term is a coercion of real to integer (unary) + *) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_INT) + + (** + Indicates whether the term is a check that tests whether a real is integral (unary) + *) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IS_INT) + + (** + Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. + *) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_STORE) + + (** + Indicates whether the term is an array select. + *) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SELECT) + + (** + Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. + *) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONST_ARRAY) + + (** + Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. + *) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_DEFAULT) + + (** + Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + *) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_MAP) + + (** + Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. + *) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AS_ARRAY) + + (** + Indicates whether the term is set union + *) + let is_set_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_UNION) + + (** + Indicates whether the term is set intersection + *) + let is_set_intersect ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_INTERSECT) + + (** + Indicates whether the term is set difference + *) + let is_set_difference ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_DIFFERENCE) + + (** + Indicates whether the term is set complement + *) + let is_set_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_COMPLEMENT) + + (** + Indicates whether the term is set subset + *) + let is_set_subset ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_SUBSET) + + (** + Indicates whether the terms is of bit-vector sort. + *) + let is_bv ( x : expr ) = + ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + + (** + Indicates whether the term is a bit-vector numeral + *) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNUM) + + (** + Indicates whether the term is a one-bit bit-vector with value one + *) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT1) + + (** + Indicates whether the term is a one-bit bit-vector with value zero + *) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT0) + + (** + Indicates whether the term is a bit-vector unary minus + *) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNEG) + + (** + Indicates whether the term is a bit-vector addition (binary) + *) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BADD) + + (** + Indicates whether the term is a bit-vector subtraction (binary) + *) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSUB) + + (** + Indicates whether the term is a bit-vector multiplication (binary) + *) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BMUL) + + (** + Indicates whether the term is a bit-vector signed division (binary) + *) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV) + + (** + Indicates whether the term is a bit-vector unsigned division (binary) + *) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV) + + (** + Indicates whether the term is a bit-vector signed remainder (binary) + *) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM) + + (** + Indicates whether the term is a bit-vector unsigned remainder (binary) + *) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM) + + (** + Indicates whether the term is a bit-vector signed modulus + *) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD) + + (** + Indicates whether the term is a bit-vector signed division by zero + *) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV0) + + (** + Indicates whether the term is a bit-vector unsigned division by zero + *) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV0) + + (** + Indicates whether the term is a bit-vector signed remainder by zero + *) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM0) + + (** + Indicates whether the term is a bit-vector unsigned remainder by zero + *) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM0) + + (** + Indicates whether the term is a bit-vector signed modulus by zero + *) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD0) + + (** + Indicates whether the term is an unsigned bit-vector less-than-or-equal + *) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULEQ) + + (** + Indicates whether the term is a signed bit-vector less-than-or-equal + *) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLEQ) + + (** + Indicates whether the term is an unsigned bit-vector greater-than-or-equal + *) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGEQ) + + (** + Indicates whether the term is a signed bit-vector greater-than-or-equal + *) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGEQ) + + (** + Indicates whether the term is an unsigned bit-vector less-than + *) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULT) + + (** + Indicates whether the term is a signed bit-vector less-than + *) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLT) + + (** + Indicates whether the term is an unsigned bit-vector greater-than + *) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGT) + + (** + Indicates whether the term is a signed bit-vector greater-than + *) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGT) + + (** + Indicates whether the term is a bit-wise AND + *) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BAND) + + (** + Indicates whether the term is a bit-wise OR + *) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BOR) + + (** + Indicates whether the term is a bit-wise NOT + *) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOT) + + (** + Indicates whether the term is a bit-wise XOR + *) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXOR) + + (** + Indicates whether the term is a bit-wise NAND + *) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNAND) + + (** + Indicates whether the term is a bit-wise NOR + *) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOR) + + (** + Indicates whether the term is a bit-wise XNOR + *) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXNOR) + + (** + Indicates whether the term is a bit-vector concatenation (binary) + *) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONCAT) + + (** + Indicates whether the term is a bit-vector sign extension + *) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SIGN_EXT) + + (** + Indicates whether the term is a bit-vector zero extension + *) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ZERO_EXT) + + (** + Indicates whether the term is a bit-vector extraction + *) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXTRACT) + + (** + Indicates whether the term is a bit-vector repetition + *) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REPEAT) + + (** + Indicates whether the term is a bit-vector reduce OR + *) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDOR) + + (** + Indicates whether the term is a bit-vector reduce AND + *) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDAND) + + (** + Indicates whether the term is a bit-vector comparison + *) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BCOMP) + + (** + Indicates whether the term is a bit-vector shift left + *) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSHL) + + (** + Indicates whether the term is a bit-vector logical shift right + *) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BLSHR) + + (** + Indicates whether the term is a bit-vector arithmetic shift left + *) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BASHR) + + (** + Indicates whether the term is a bit-vector rotate left + *) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_LEFT) + + (** + Indicates whether the term is a bit-vector rotate right + *) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_RIGHT) + + (** + Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. + *) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_LEFT) + + (** + Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. + *) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_RIGHT) + + (** + Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. + *) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_INT2BV) + + (** + Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. + *) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BV2INT) + + (** + Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + *) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CARRY) + + (** + Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + *) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR3) + + (** + Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. + *) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + + (** + Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + *) + + (** + Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. + *) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + + (** + Indicates whether the term is a Proof for the expression 'true'. + *) + let is_proof_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRUE) + + (** + Indicates whether the term is a proof for a fact asserted by the user. + *) + let is_proof_asserted ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ASSERTED) + + (** + Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. + *) + let is_proof_goal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_GOAL) + + (** + Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). + *) + let is_proof_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS) + + (** + Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. + *) + let is_proof_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REFLEXIVITY) + + (** + Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. + + *) + let is_proof_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SYMMETRY) + + (** + Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) + + *) + let is_proof_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY) + + (** + Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. + + *) + let is_proof_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + + + (** + Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. + + *) + let is_proof_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MONOTONICITY) + + (** + Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) + + *) + let is_proof_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INTRO) + + (** + Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. + + *) + let is_proof_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DISTRIBUTIVITY) + + (** + Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i + + *) + let is_proof_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_AND_ELIM) + + (** + Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) + + *) + let is_proof_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NOT_OR_ELIM) + + (** + Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) + + *) + let is_proof_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE) + + (** + Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) + + *) + let is_proof_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE_STAR) + + (** + Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. + + *) + let is_proof_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT) + + (** + Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents + + *) + let is_proof_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT_STAR) + + (** + Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents + + *) + let is_proof_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PUSH_QUANT) + + (** + Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. + + *) + let is_proof_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + + (** + Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. + + *) + let is_proof_der ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DER) + + (** + Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) + + *) + let is_proof_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INST) + + (** + Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. + *) + let is_proof_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_HYPOTHESIS) + + (** + Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. + + *) + let is_proof_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_LEMMA) + + (** + Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') + + *) + let is_proof_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_UNIT_RESOLUTION) + + (** + Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) + + *) + let is_proof_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_TRUE) + + (** + Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) + + *) + let is_proof_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_FALSE) + + (** + Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. + + *) + let is_proof_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + + (** + Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). + + *) + let is_proof_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_AXIOM) + + (** + Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) + + *) + let is_proof_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_INTRO) + + (** + Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. + + *) + let is_proof_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_APPLY_DEF) + + (** + Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) + + *) + let is_proof_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_OEQ) + + (** + Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. + + *) + let is_proof_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_POS) + + (** + Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) + + *) + let is_proof_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_NEG) + + (** + Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. + + *) + let is_proof_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_STAR) + + (** + Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. + + *) + let is_proof_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_CNF_STAR) + + (** + Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. + + *) + let is_proof_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SKOLEMIZE) + + (** + Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q + + *) + let is_proof_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + + (** + Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. + + *) + let is_proof_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TH_LEMMA) + + (** + Indicates whether the term is of a relation sort. + *) + let is_Relation ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + + (** + Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. + + *) + let is_relation_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_STORE) + + (** + Indicates whether the term is an empty relation + *) + let is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_EMPTY) + + (** + Indicates whether the term is a test for the emptiness of a relation + *) + let is_is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_IS_EMPTY) + + (** + Indicates whether the term is a relational join + *) + let is_relational_join ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_JOIN) + + (** + Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. + *) + let is_relation_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_UNION) + + (** + Indicates whether the term is the widening of two relations + The function takes two arguments. + *) + let is_relation_widen ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_WIDEN) + + (** + Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. + *) + let is_relation_project ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_PROJECT) + + (** + Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. + + *) + let is_relation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_FILTER) + + (** + Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. + + *) + let is_relation_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_NEGATION_FILTER) + + (** + Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. + + *) + let is_relation_rename ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_RENAME) + + (** + Indicates whether the term is the complement of a relation + *) + let is_relation_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_COMPLEMENT) + + (** + Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. + + *) + let is_relation_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_SELECT) + + (** + Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind + to perform destructive updates to the first argument. + + *) + let is_relation_clone ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_CLONE) + + (** + Indicates whether the term is of an array sort. + *) + let is_finite_domain ( x : expr ) = + ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + + (** + Indicates whether the term is a less than predicate over a finite domain. + *) + let is_finite_domain_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FD_LT) + + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno +end + +(* Integer Numerals *) +module IntNum = +struct + (** Retrieve the int value. *) + let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Rational Numerals *) +module RatNum = +struct + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) (precision : int) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Bit-vector numerals *) +module BitVecNum = +struct + (** Retrieve the int value. *) + let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** Algebraic numbers *) +module AlgebraicNum = +struct + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + + the precision of the result + A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + + + A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno +end + +(** The main interaction with Z3 happens via the Context module. *) module Context = struct + + (* SYMBOLS *) + (** Creates a new symbol using an integer. Not all integers can be passed to this function. The legal range of unsigned integers is 0 to 2^30-1. *) - let mk_symbol_int ctx i = + let mk_symbol_int ( ctx : context ) i = (new int_symbol ctx)#cnstr_int i - + (** Creates a new symbol using a string. *) - let mk_symbol_string ctx s = + let mk_symbol_string ( ctx : context ) s = (new string_symbol ctx)#cnstr_string s (** Create an array of symbols. *) - let mk_symbols ctx names = - let f elem = mk_symbol_string ctx elem in + let mk_symbols_int ( ctx : context ) names = + let f elem = mk_symbol_int ( ctx : context ) elem in + (Array.map f names) + + (** + Create an array of symbols. + *) + let mk_symbols_string ( ctx : context ) names = + let f elem = mk_symbol_string ( ctx : context ) elem in (Array.map f names) + + (* SORTS *) + + (** + Create a new Boolean sort. + *) + let mk_bool_sort ( ctx : context ) = + (new bool_sort ctx) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_sort ( ctx : context ) (s : symbol) = + (new uninterpreted_sort ctx)#cnstr_s s + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_sort_s ( ctx : context ) (s : string) = + mk_uninterpreted_sort ctx ((mk_symbol_string ( ctx : context ) s) :> symbol) + + (** + Create a new integer sort. + *) + let mk_int_sort ( ctx : context ) = + (new int_sort ctx) + + (** + Create a real sort. + *) + let mk_real_sort ( ctx : context ) = + (new real_sort ctx) + + (** + Create a new bit-vector sort. + *) + let mk_bitvec_sort ( ctx : context ) size = + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) + + (** + Create a new array sort. + *) + let mk_array_sort ( ctx : context ) domain range = + (new array_sort ctx)#cnstr_dr domain range + + (** + Create a new tuple sort. + *) + let mk_tuple_sort ( ctx : context ) name field_names field_sorts = + (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts + + (** + Create a new enumeration sort. + *) + let mk_enum_sort ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss name enum_names + + (** + Create a new enumeration sort. + *) + let mk_enum_sort_s ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss + ((mk_symbol_string ( ctx : context ) name) :> symbol) + (let f e = (e :> symbol) in + (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) + ) + + (** + Create a new list sort. + *) + let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = + (new list_sort ctx)#cnstr_ss name elem_sort + + (** + Create a new list sort. + *) + let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = + mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort + + + (** + Create a new finite domain sort. + *) + let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = + (new finite_domain_sort ctx)#cnstr_si name size + + (** + Create a new finite domain sort. + *) + let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = + (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size + +(** + +(* DATATYPES *) +(** + Create a datatype constructor. +*) + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + public Constructor MkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) + { + + + + + return new Constructor(this, name, recognizer, fieldNames, sorts, sortRefs); + } + +(** + Create a datatype constructor. +*) + @param name + @param recognizer + @param fieldNames + @param sorts + @param sortRefs + @return + public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) + { + + + return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs); + } + +(** + Create a new datatype sort. +*) + let mk_Datatype_Sort(Symbol name, Constructor[] constructors) + { + + + + + + + CheckContextMatch(name); + CheckContextMatch(constructors); + return new DatatypeSort(this, name, constructors); + } + +(** + Create a new datatype sort. +*) + let mk_Datatype_Sort(string name, Constructor[] constructors) + { + + + + + CheckContextMatch(constructors); + return new DatatypeSort(this, MkSymbol(name), constructors); + } + +(** + Create mutually recursive datatypes. +*) + @param names names of datatype sorts + @param c list of constructors, one list per sort. + let mk_Datatype_Sorts(Symbol[] names, Constructor[][] c) + { + + + + + + + + CheckContextMatch(names); + uint n = (uint)names.Length; + ConstructorList[] cla = new ConstructorList[n]; + IntPtr[] n_constr = new IntPtr[n]; + for (uint i = 0; i < n; i++) + { + Constructor[] constructor = c[i]; + + CheckContextMatch(constructor); + cla[i] = new ConstructorList(this, constructor); + n_constr[i] = cla[i].x#gno; + } + IntPtr[] n_res = new IntPtr[n]; + Z3native.mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); + DatatypeSort[] res = new DatatypeSort[n]; + for (uint i = 0; i < n; i++) + res[i] = new DatatypeSort(this, n_res[i]); + return res; + } + +(** + Create mutually recursive data-types. +*) + @param names + @param c + @return + let mk_Datatype_Sorts(string[] names, Constructor[][] c) + { + + + + + + + + return MkDatatypeSorts(MkSymbols(names), c); + } + + + + +(* FUNCTION DECLARATIONS *) +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(Symbol name, Sort[] domain, Sort range) + { + + + + + + CheckContextMatch(name); + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, name, domain, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(Symbol name, Sort domain, Sort range) + { + + + + + + CheckContextMatch(name); + CheckContextMatch(domain); + CheckContextMatch(range); + Sort[] q = new Sort[] { domain }; + return new Func_Decl(this, name, q, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(string name, Sort[] domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, MkSymbol(name), domain, range); + } + +(** + Creates a new function declaration. +*) + public Func_Decl MkFunc_Decl(string name, Sort domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + Sort[] q = new Sort[] { domain }; + return new Func_Decl(this, MkSymbol(name), q, range); + } + +(** + Creates a fresh function declaration with a name prefixed with . +*) + + + let mk_Fresh_Func_Decl(string prefix, Sort[] domain, Sort range) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(range); + return new Func_Decl(this, prefix, domain, range); + } + +(** + Creates a new constant function declaration. +*) + let mk_Const_Decl(Symbol name, Sort range) + { + + + + + CheckContextMatch(name); + CheckContextMatch(range); + return new Func_Decl(this, name, null, range); + } + +(** + Creates a new constant function declaration. +*) + let mk_Const_Decl(string name, Sort range) + { + + + + CheckContextMatch(range); + return new Func_Decl(this, MkSymbol(name), null, range); + } + +(** + Creates a fresh constant function declaration with a name prefixed with . +*) + + + let mk_Fresh_ConstDecl(string prefix, Sort range) + { + + + + CheckContextMatch(range); + return new Func_Decl(this, prefix, null, range); + } + + +(* BOUND VARIABLES *) +(** + Creates a new bound variable. +*) + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + public Expr MkBound(uint index, Sort ty) + { + + + + return Expr.Create(this, Z3native.mk_bound(nCtx, index, ty.x#gno)); + } + + +(* QUANTIFIER PATTERNS *) +(** + Create a quantifier pattern. +*) + public Pattern MkPattern(params Expr[] terms) + { + + if (terms.Length == 0) + throw new Z3Exception("Cannot create a pattern from zero terms"); + + + + + + IntPtr[] termsNative = AST.ArrayToNative(terms); + return new Pattern(this, Z3native.mk_pattern(nCtx, (uint)terms.Length, termsNative)); + } + + +(* CONSTANTS *) +(** + Creates a new Constant of sort and named . +*) + public Expr MkConst(Symbol name, Sort range) + { + + + + + CheckContextMatch(name); + CheckContextMatch(range); + + return Expr.Create(this, Z3native.mk_const(nCtx, name.x#gno, range.x#gno)); + } + +(** + Creates a new Constant of sort and named . +*) + public Expr MkConst(string name, Sort range) + { + + + + return MkConst(MkSymbol(name), range); + } + +(** + Creates a fresh Constant of sort and a + name prefixed with . +*) + let mk_Fresh_Const(string prefix, Sort range) + { + + + + CheckContextMatch(range); + return Expr.Create(this, Z3native.mk_fresh_const(nCtx, prefix, range.x#gno)); + } + +(** + Creates a fresh constant from the Func_Decl . +*) + @param f A decl of a 0-arity function + public Expr MkConst(Func_Decl f) + { + + + + return MkApp(f); + } + +(** + Create a Boolean constant. +*) + let mk_Bool_Const(Symbol name) + { + + + + return (BoolExpr)MkConst(name, BoolSort); + } + +(** + Create a Boolean constant. +*) + let mk_Bool_Const(string name) + { + + + return (BoolExpr)MkConst(MkSymbol(name), BoolSort); + } + +(** + Creates an integer constant. +*) + let mk_Int_Const(Symbol name) + { + + + + return (IntExpr)MkConst(name, IntSort); + } + +(** + Creates an integer constant. +*) + let mk_Int_Const(string name) + { + + + + return (IntExpr)MkConst(name, IntSort); + } + +(** + Creates a real constant. +*) + let mk_Real_Const(Symbol name) + { + + + + return (RealExpr)MkConst(name, RealSort); + } + +(** + Creates a real constant. +*) + let mk_Real_Const(string name) + { + + + return (RealExpr)MkConst(name, RealSort); + } + +(** + Creates a bit-vector constant. +*) + let mk_B_VConst(Symbol name, uint size) + { + + + + return (BitVecExpr)MkConst(name, MkBitVecSort(size)); + } + +(** + Creates a bit-vector constant. +*) + let mk_B_VConst(string name, uint size) + { + + + return (BitVecExpr)MkConst(name, MkBitVecSort(size)); + } + + +(* TERMS *) +(** + Create a new function application. +*) + public Expr MkApp(Func_Decl f, params Expr[] args) + { + + + + + CheckContextMatch(f); + CheckContextMatch(args); + return Expr.Create(this, f, args); + } + +(* PROPOSITIONAL *) +(** + The true Term. +*) + public BoolExpr MkTrue ( ctx : context ) = + { + + + return new BoolExpr(this, Z3native.mk_true(nCtx)); + } + +(** + The false Term. +*) + public BoolExpr MkFalse ( ctx : context ) = + { + + + return new BoolExpr(this, Z3native.mk_false(nCtx)); + } + +(** + Creates a Boolean value. +*) + public BoolExpr MkBool(bool value) + { + + + return value ? MkTrue ( ctx : context ) = : MkFalse ( ctx : context ) =; + } + +(** + Creates the equality = . +*) + public BoolExpr MkEq(Expr x, Expr y) + { + + + + + CheckContextMatch(x); + CheckContextMatch(y); + return new BoolExpr(this, Z3native.mk_eq(nCtx, x.x#gno, y.x#gno)); + } + +(** + Creates a distinct term. +*) + public BoolExpr MkDistinct(params Expr[] args) + { + + + + + + CheckContextMatch(args); + return new BoolExpr(this, Z3native.mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Mk an expression representing not(a). +*) + public BoolExpr MkNot(BoolExpr a) + { + + + + CheckContextMatch(a); + return new BoolExpr(this, Z3native.mk_not(nCtx, a.x#gno)); + } + +(** + Create an expression representing an if-then-else: ite(t1, t2, t3). +*) + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + let mk_I_TE(BoolExpr t1, Expr t2, Expr t3) + { + + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + CheckContextMatch(t3); + return Expr.Create(this, Z3native.mk_ite(nCtx, t1.x#gno, t2.x#gno, t3.x#gno)); + } + +(** + Create an expression representing t1 iff t2. +*) + public BoolExpr MkIff(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_iff(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 -> t2. +*) + public BoolExpr MkImplies(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_implies(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 xor t2. +*) + public BoolExpr MkXor(BoolExpr t1, BoolExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_xor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t[0] and t[1] and .... +*) + public BoolExpr MkAnd(params BoolExpr[] t) + { + + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] or t[1] or .... +*) + public BoolExpr MkOr(params BoolExpr[] t) + { + + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + + +(* ARITHMETIC *) +(** + Create an expression representing t[0] + t[1] + .... +*) + public ArithExpr MkAdd(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] * t[1] * .... +*) + public ArithExpr MkMul(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing t[0] - t[1] - .... +*) + public ArithExpr MkSub(params ArithExpr[] t) + { + + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); + } + +(** + Create an expression representing -t. +*) + let mk_Unary_Minus(ArithExpr t) + { + + + + CheckContextMatch(t); + return (ArithExpr)Expr.Create(this, Z3native.mk_unary_minus(nCtx, t.x#gno)); + } + +(** + Create an expression representing t1 / t2. +*) + public ArithExpr MkDiv(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return (ArithExpr)Expr.Create(this, Z3native.mk_div(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 mod t2. +*) + The arguments must have int type. + public IntExpr MkMod(IntExpr t1, IntExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new IntExpr(this, Z3native.mk_mod(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 rem t2. +*) + The arguments must have int type. + public IntExpr MkRem(IntExpr t1, IntExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new IntExpr(this, Z3native.mk_rem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 ^ t2. +*) + public ArithExpr MkPower(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return (ArithExpr)Expr.Create(this, Z3native.mk_power(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 < t2 +*) + public BoolExpr MkLt(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_lt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 <= t2 +*) + public BoolExpr MkLe(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_le(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 > t2 +*) + public BoolExpr MkGt(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_gt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an expression representing t1 >= t2 +*) + public BoolExpr MkGe(ArithExpr t1, ArithExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_ge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Coerce an integer to a real. +*) + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + + public RealExpr MkInt2Real(IntExpr t) + { + + + + CheckContextMatch(t); + return new RealExpr(this, Z3native.mk_int2real(nCtx, t.x#gno)); + } + +(** + Coerce a real to an integer. +*) + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + + public IntExpr MkReal2Int(RealExpr t) + { + + + + CheckContextMatch(t); + return new IntExpr(this, Z3native.mk_real2int(nCtx, t.x#gno)); + } + +(** + Creates an expression that checks whether a real number is an integer. +*) + let mk_Is_Integer(RealExpr t) + { + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_is_int(nCtx, t.x#gno)); + } + + +(* BIT-VECTORS *) +(** + Bitwise negation. +*) + The argument must have a bit-vector sort. + let mk_B_VNot(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvnot(nCtx, t.x#gno)); + } + +(** + Take conjunction of bits in a vector, return vector of length 1. +*) + The argument must have a bit-vector sort. + let mk_B_VRedAND(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvredand(nCtx, t.x#gno)); + } + +(** + Take disjunction of bits in a vector, return vector of length 1. +*) + The argument must have a bit-vector sort. + let mk_B_VRedOR(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvredor(nCtx, t.x#gno)); + } + +(** + Bitwise conjunction. +*) + The arguments must have a bit-vector sort. + let mk_B_VAND(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvand(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise disjunction. +*) + The arguments must have a bit-vector sort. + let mk_B_VOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise XOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VXOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvxor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise NAND. +*) + The arguments must have a bit-vector sort. + let mk_B_VNAND(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvnand(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise NOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VNOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvnor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bitwise XNOR. +*) + The arguments must have a bit-vector sort. + let mk_B_VXNOR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvxnor(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Standard two's complement unary minus. +*) + The arguments must have a bit-vector sort. + let mk_B_VNeg(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_bvneg(nCtx, t.x#gno)); + } + +(** + Two's complement addition. +*) + The arguments must have the same bit-vector sort. + let mk_B_VAdd(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvadd(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement subtraction. +*) + The arguments must have the same bit-vector sort. + let mk_B_VSub(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsub(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement multiplication. +*) + The arguments must have the same bit-vector sort. + let mk_B_VMul(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvmul(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned division. +*) + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VUDiv(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvudiv(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Signed division. +*) + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSDiv(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsdiv(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned remainder. +*) + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VURem(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvurem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Signed remainder. +*) + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSRem(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsrem(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed remainder (sign follows divisor). +*) + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + + let mk_B_VSMod(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvsmod(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned less-than +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VULT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvult(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed less-than +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSLT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvslt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned less-than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VULE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvule(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed less-than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSLE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsle(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned greater than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VUGE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvuge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed greater than or equal to. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSGE(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsge(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Unsigned greater-than. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VUGT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvugt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Two's complement signed greater-than. +*) + + The arguments must have the same bit-vector sort. + + let mk_B_VSGT(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsgt(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bit-vector concatenation. +*) + + The arguments must have a bit-vector sort. + + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). + + public BitVecExpr MkConcat(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_concat(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Bit-vector extraction. +*) + + Extract the bits down to from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. + The argument must have a bit-vector sort. + + public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_extract(nCtx, high, low, t.x#gno)); + } + +(** + Bit-vector sign extension. +*) + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. + The argument must have a bit-vector sort. + + let mk_Sign_Ext(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_sign_ext(nCtx, i, t.x#gno)); + } + +(** + Bit-vector zero extension. +*) + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. + The argument must have a bit-vector sort. + + let mk_Zero_Ext(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_zero_ext(nCtx, i, t.x#gno)); + } + +(** + Bit-vector repetition. +*) + + The argument must have a bit-vector sort. + + public BitVecExpr MkRepeat(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_repeat(nCtx, i, t.x#gno)); + } + +(** + Shift left. +*) + + It is equivalent to multiplication by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VSHL(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvshl(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Logical shift right +*) + + It is equivalent to unsigned division by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VLSHR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvlshr(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Arithmetic shift right +*) + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + + let mk_B_VASHR(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_bvashr(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Rotate Left. +*) + + Rotate bits of \c t to the left \c i times. + The argument must have a bit-vector sort. + + let mk_B_VRotateLeft(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_rotate_left(nCtx, i, t.x#gno)); + } + +(** + Rotate Right. +*) + + Rotate bits of \c t to the right \c i times. + The argument must have a bit-vector sort. + + let mk_B_VRotateRight(uint i, BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_rotate_right(nCtx, i, t.x#gno)); + } + +(** + Rotate Left. +*) + + Rotate bits of to the left times. + The arguments must have the same bit-vector sort. + + let mk_B_VRotateLeft(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_ext_rotate_left(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Rotate Right. +*) + + Rotate bits of to the right times. + The arguments must have the same bit-vector sort. + + let mk_B_VRotateRight(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BitVecExpr(this, Z3native.mk_ext_rotate_right(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create an bit bit-vector from the integer argument . +*) + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + + public BitVecExpr MkInt2BV(uint n, IntExpr t) + { + + + + CheckContextMatch(t); + return new BitVecExpr(this, Z3native.mk_int2bv(nCtx, n, t.x#gno)); + } + +(** + Create an integer from the bit-vector argument . +*) + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in . + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of bit-vector sort. + + let mk_B_V2Int(BitVecExpr t, bool signed) + { + + + + CheckContextMatch(t); + return new IntExpr(this, Z3native.mk_bv2int(nCtx, t.x#gno, (signed) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise addition does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VAddNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvadd_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise addition does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvadd_no_underflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise subtraction does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSubNoOverflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsub_no_overflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise subtraction does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsub_no_underflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise signed division does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvsdiv_no_overflow(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise negation does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VNegNoOverflow(BitVecExpr t) + { + + + + CheckContextMatch(t); + return new BoolExpr(this, Z3native.mk_bvneg_no_overflow(nCtx, t.x#gno)); + } + +(** + Create a predicate that checks that the bit-wise multiplication does not overflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VMulNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvmul_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); + } + +(** + Create a predicate that checks that the bit-wise multiplication does not underflow. +*) + + The arguments must be of bit-vector sort. + + let mk_B_VMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new BoolExpr(this, Z3native.mk_bvmul_no_underflow(nCtx, t1.x#gno, t2.x#gno)); + } + + +(* ARRAYS *) +(** + Create an array constant. +*) + let mk_Array_Const(Symbol name, Sort domain, Sort range) + { + + + + + + return (ArrayExpr)MkConst(name, MkArraySort(domain, range)); + } + +(** + Create an array constant. +*) + let mk_Array_Const(string name, Sort domain, Sort range) + { + + + + + return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range)); + } + +(** + Array read. +*) + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + + + + public Expr MkSelect(ArrayExpr a, Expr i) + { + + + + + CheckContextMatch(a); + CheckContextMatch(i); + return Expr.Create(this, Z3native.mk_select(nCtx, a.x#gno, i.x#gno)); + } + +(** + Array update. +*) + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + + + + public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v) + { + + + + + + CheckContextMatch(a); + CheckContextMatch(i); + CheckContextMatch(v); + return new ArrayExpr(this, Z3native.mk_store(nCtx, a.x#gno, i.x#gno, v.x#gno)); + } + +(** + Create a constant array. +*) + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + + + + let mk_Const_Array(Sort domain, Expr v) + { + + + + + CheckContextMatch(domain); + CheckContextMatch(v); + return new ArrayExpr(this, Z3native.mk_const_array(nCtx, domain.x#gno, v.x#gno)); + } + +(** + Maps f on the argument arrays. +*) + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + + + + + public ArrayExpr MkMap(Func_Decl f, params ArrayExpr[] args) + { + + + + + CheckContextMatch(f); + CheckContextMatch(args); + return (ArrayExpr)Expr.Create(this, Z3native.mk_map(nCtx, f.x#gno, AST.ArrayLength(args), AST.ArrayToNative(args))); + } + +(** + Access the array default value. +*) + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. + + let mk_Term_Array(ArrayExpr array) + { + + + + CheckContextMatch(array); + return Expr.Create(this, Z3native.mk_array_default(nCtx, array.x#gno)); + } + + +(* SETS *) +(** + Create a set type. +*) + let mk_Set_Sort(Sort ty) + { + + + + CheckContextMatch(ty); + return new SetSort(this, ty); + } + +(** + Create an empty set. +*) + let mk_Empty_Set(Sort domain) + { + + + + CheckContextMatch(domain); + return Expr.Create(this, Z3native.mk_empty_set(nCtx, domain.x#gno)); + } + +(** + Create the full set. +*) + let mk_Full_Set(Sort domain) + { + + + + CheckContextMatch(domain); + return Expr.Create(this, Z3native.mk_full_set(nCtx, domain.x#gno)); + } + +(** + Add an element to the set. +*) + let mk_Set_Add(Expr set, Expr element) + { + + + + + CheckContextMatch(set); + CheckContextMatch(element); + return Expr.Create(this, Z3native.mk_set_add(nCtx, set.x#gno, element.x#gno)); + } + + +(** + Remove an element from a set. +*) + let mk_Set_Del(Expr set, Expr element) + { + + + + + CheckContextMatch(set); + CheckContextMatch(element); + return Expr.Create(this, Z3native.mk_set_del(nCtx, set.x#gno, element.x#gno)); + } + +(** + Take the union of a list of sets. +*) + let mk_Set_Union(params Expr[] args) + { + + + + CheckContextMatch(args); + return Expr.Create(this, Z3native.mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Take the intersection of a list of sets. +*) + let mk_Set_Intersection(params Expr[] args) + { + + + + + CheckContextMatch(args); + return Expr.Create(this, Z3native.mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); + } + +(** + Take the difference between two sets. +*) + let mk_Set_Difference(Expr arg1, Expr arg2) + { + + + + + CheckContextMatch(arg1); + CheckContextMatch(arg2); + return Expr.Create(this, Z3native.mk_set_difference(nCtx, arg1.x#gno, arg2.x#gno)); + } + +(** + Take the complement of a set. +*) + let mk_Set_Complement(Expr arg) + { + + + + CheckContextMatch(arg); + return Expr.Create(this, Z3native.mk_set_complement(nCtx, arg.x#gno)); + } + +(** + Check for set membership. +*) + let mk_Set_Membership(Expr elem, Expr set) + { + + + + + CheckContextMatch(elem); + CheckContextMatch(set); + return Expr.Create(this, Z3native.mk_set_member(nCtx, elem.x#gno, set.x#gno)); + } + +(** + Check for subsetness of sets. +*) + let mk_Set_Subset(Expr arg1, Expr arg2) + { + + + + + CheckContextMatch(arg1); + CheckContextMatch(arg2); + return Expr.Create(this, Z3native.mk_set_subset(nCtx, arg1.x#gno, arg2.x#gno)); + } + + +(* NUMERALS *) + +(* GENERAL NUMERALS *) +(** + Create a Term of a given sort. +*) + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + public Expr MkNumeral(string v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_numeral(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(int v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_int(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(uint v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_unsigned_int(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(long v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_int64(nCtx, v, ty.x#gno)); + } + +(** + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. +*) + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(ulong v, Sort ty) + { + + + + CheckContextMatch(ty); + return Expr.Create(this, Z3native.mk_unsigned_int64(nCtx, v, ty.x#gno)); + } + + +(* REALS *) +(** + Create a real from a fraction. +*) + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + public RatNum MkReal(int num, int den) + { + if (den == 0) + throw new Z3Exception("Denominator is zero"); + + + + + return new RatNum(this, Z3native.mk_real(nCtx, num, den)); + } + +(** + Create a real numeral. +*) + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + public RatNum MkReal(string v) + { + + + return new RatNum(this, Z3native.mk_numeral(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(int v) + { + + + return new RatNum(this, Z3native.mk_int(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(uint v) + { + + + return new RatNum(this, Z3native.mk_unsigned_int(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(long v) + { + + + return new RatNum(this, Z3native.mk_int64(nCtx, v, RealSort.x#gno)); + } + +(** + Create a real numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(ulong v) + { + + + return new RatNum(this, Z3native.mk_unsigned_int64(nCtx, v, RealSort.x#gno)); + } + + +(* INTEGERS *) +(** + Create an integer numeral. +*) + @param v A string representing the Term value in decimal notation. + public IntNum MkInt(string v) + { + + + return new IntNum(this, Z3native.mk_numeral(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(int v) + { + + + return new IntNum(this, Z3native.mk_int(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(uint v) + { + + + return new IntNum(this, Z3native.mk_unsigned_int(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(long v) + { + + + return new IntNum(this, Z3native.mk_int64(nCtx, v, IntSort.x#gno)); + } + +(** + Create an integer numeral. +*) + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(ulong v) + { + + + return new IntNum(this, Z3native.mk_unsigned_int64(nCtx, v, IntSort.x#gno)); + } + + +(* BIT-VECTORS *) +(** + Create a bit-vector numeral. +*) + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + let mk_B_V(string v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(int v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(uint v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(long v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + +(** + Create a bit-vector numeral. +*) + @param v value of the numeral. + @param size the size of the bit-vector + let mk_B_V(ulong v, uint size) + { + + + return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); + } + + + // Numerals + +(* QUANTIFIERS *) +(** + Create a universal Quantifier. +*) + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. + + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + + return new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a universal Quantifier. +*) + public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + return new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + +(** + Create an existential Quantifier. +*) + + public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + return new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + +(** + Create an existential Quantifier. +*) + public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + return new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a Quantifier. +*) + public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + + + + + if (universal) + return MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + return MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + +(** + Create a Quantifier. +*) + public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + { + + + + + + + + if (universal) + return MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + } + + + + // Expr + +(* OPTIONS *) + +(** + Selects the format used for pretty-printing expressions. +*) + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + + + + + + public Z3_ast_print_mode PrintMode + { + set { Z3native.set_ast_print_mode(nCtx, (uint)value); } + } + + +(* SMT Files & Strings *) +(** + Convert a benchmark into an SMT-LIB formatted string. +*) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) + { + + + + + return Z3native.benchmark_to_smtlib_string(nCtx, name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula.x#gno); + } + +(** + Parse the given string using the SMT-LIB parser. +*) + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. + + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string(nCtx, str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); + } + +(** + Parse the given file using the SMT-LIB parser. +*) + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file(nCtx, fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); + } + +(** + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBFormulas { get { return Z3native.get_smtlib_num_formulas(nCtx)) + +(** + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public BoolExpr[] SMTLIBFormulas + { + get + { + + + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_formula(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBAssumptions { get { return Z3native.get_smtlib_num_assumptions(nCtx)) + +(** + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public BoolExpr[] SMTLIBAssumptions + { + get + { + + + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_assumption(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBDecls { get { return Z3native.get_smtlib_num_decls(nCtx)) + +(** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public Func_Decl[] SMTLIBDecls + { + get + { + + + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl(nCtx, i)); + return res; + } + } + +(** + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public uint NumSMTLIBSorts { get { return Z3native.get_smtlib_num_sorts(nCtx)) + +(** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. +*) + public Sort[] SMTLIBSorts + { + get + { + + + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort(nCtx, i)); + return res; + } + } + +(** + Parse the given string using the SMT-LIB2 parser. +*) + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + public BoolExpr ParseSMTLIB2String(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_string(nCtx, str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); + } + +(** + Parse the given file using the SMT-LIB2 parser. +*) + + public BoolExpr ParseSMTLIB2File(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + { + + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_file(nCtx, fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); + } + + +(* GOALS *) +(** + Creates a new Goal. +*) + + Note that the Context must have been created with proof generation support if + is set to true here. + + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) + { + + + return new Goal(this, models, unsatCores, proofs); + } + + +(* PARAMETERSETS *) +(** + Creates a new ParameterSet. +*) + public Params MkParams ( ctx : context ) = + { + + + return new Params(this); + } + + +(* TACTICS *) +(** + The number of supported tactics. +*) + public uint NumTactics + { + get { return Z3native.get_num_tactics(nCtx); } + } + +(** + The names of all supported tactics. +*) + public string[] TacticNames + { + get + { + + + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name(nCtx, i); + return res; + } + } + +(** + Returns a string containing a description of the tactic with the given name. +*) + public string TacticDescription(string name) + { + + + return Z3native.tactic_get_descr(nCtx, name); + } + +(** + Creates a new Tactic. +*) + public Tactic MkTactic(string name) + { + + + return new Tactic(this, name); + } + +(** + Create a tactic that applies to a Goal and + then to every subgoal produced by . +*) + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + { + + + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + CheckContextMatch(ts); + + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) + { + last = ts[ts.Length - 1].x#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then(nCtx, ts[i].x#gno, last); + } + if (last != IntPtr.Zero) + { + last = Z3native.tactic_and_then(nCtx, t2.x#gno, last); + return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, last)); + } + else + return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that applies to a Goal and + then to every subgoal produced by . +*) + + Shorthand for AndThen. + + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) + { + + + + + + return AndThen(t1, t2, ts); + } + +(** + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. +*) + public Tactic OrElse(Tactic t1, Tactic t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_or_else(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that applies to a goal for milliseconds. +*) + + If does not terminate within milliseconds, then it fails. + + public Tactic TryFor(Tactic t, uint ms) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_try_for(nCtx, t.x#gno, ms)); + } + +(** + Create a tactic that applies to a given goal if the probe + evaluates to true. +*) + + If evaluates to false, then the new tactic behaves like the skip tactic. + + public Tactic When(Probe p, Tactic t) + { + + + + + CheckContextMatch(t); + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_when(nCtx, p.x#gno, t.x#gno)); + } + +(** + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. +*) + public Tactic Cond(Probe p, Tactic t1, Tactic t2) + { + + + + + + CheckContextMatch(p); + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_cond(nCtx, p.x#gno, t1.x#gno, t2.x#gno)); + } + +(** + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. +*) + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_repeat(nCtx, t.x#gno, max)); + } + +(** + Create a tactic that just returns the given goal. +*) + public Tactic Skip ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_skip(nCtx)); + } + +(** + Create a tactic always fails. +*) + public Tactic Fail ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_fail(nCtx)); + } + +(** + Create a tactic that fails if the probe evaluates to false. +*) + public Tactic FailIf(Probe p) + { + + + + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_fail_if(nCtx, p.x#gno)); + } + +(** + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). +*) + public Tactic FailIfNotDecided ( ctx : context ) = + { + + + return new Tactic(this, Z3native.tactic_fail_if_not_decided(nCtx)); + } + +(** + Create a tactic that applies using the given set of parameters . +*) + public Tactic UsingParams(Tactic t, Params p) + { + + + + + CheckContextMatch(t); + CheckContextMatch(p); + return new Tactic(this, Z3native.tactic_using_params(nCtx, t.x#gno, p.x#gno)); + } + +(** + Create a tactic that applies using the given set of parameters . +*) + Alias for UsingParams + public Tactic With(Tactic t, Params p) + { + + + + + return UsingParams(t, p); + } + +(** + Create a tactic that applies the given tactics in parallel. +*) + public Tactic ParOr(params Tactic[] t) + { + + + + CheckContextMatch(t); + return new Tactic(this, Z3native.tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); + } + +(** + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. +*) + public Tactic ParAndThen(Tactic t1, Tactic t2) + { + + + + + CheckContextMatch(t1); + CheckContextMatch(t2); + return new Tactic(this, Z3native.tactic_par_and_then(nCtx, t1.x#gno, t2.x#gno)); + } + +(** + Interrupt the execution of a Z3 procedure. +*) + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = + { + Z3native.interrupt(nCtx); + } + + +(* PROBES *) +(** + The number of supported Probes. +*) + public uint NumProbes + { + get { return Z3native.get_num_probes(nCtx); } + } + +(** + The names of all supported Probes. +*) + public string[] ProbeNames + { + get + { + + + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name(nCtx, i); + return res; + } + } + +(** + Returns a string containing a description of the probe with the given name. +*) + public string ProbeDescription(string name) + { + + + return Z3native.probe_get_descr(nCtx, name); + } + +(** + Creates a new Probe. +*) + public Probe MkProbe(string name) + { + + + return new Probe(this, name); + } + +(** + Create a probe that always evaluates to . +*) + public Probe Const(double val) + { + + + return new Probe(this, Z3native.probe_const(nCtx, val)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by +*) + public Probe Lt(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_lt(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by +*) + public Probe Gt(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_gt(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by +*) + public Probe Le(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_le(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by +*) + public Probe Ge(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_ge(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by +*) + public Probe Eq(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_eq(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + and evaluate to "true". +*) + public Probe And(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_and(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + or evaluate to "true". +*) + public Probe Or(Probe p1, Probe p2) + { + + + + + CheckContextMatch(p1); + CheckContextMatch(p2); + return new Probe(this, Z3native.probe_or(nCtx, p1.x#gno, p2.x#gno)); + } + +(** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". +*) + public Probe Not(Probe p) + { + + + + CheckContextMatch(p); + return new Probe(this, Z3native.probe_not(nCtx, p.x#gno)); + } + + +(* SOLVERS *) +(** + Creates a new (incremental) solver. +*) + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. + + public Solver MkSolver(Symbol logic = null) + { + + + if (logic == null) + return new Solver(this, Z3native.mk_solver(nCtx)); + else + return new Solver(this, Z3native.mk_solver_for_logic(nCtx, logic.x#gno)); + } + +(** + Creates a new (incremental) solver. +*) + + public Solver MkSolver(string logic) + { + + + return MkSolver(MkSymbol(logic)); + } + +(** + Creates a new (incremental) solver. +*) + let mk_Simple_Solver ( ctx : context ) = + { + + + return new Solver(this, Z3native.mk_simple_solver(nCtx)); + } + +(** + Creates a solver that is implemented using the given tactic. +*) + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. + + public Solver MkSolver(Tactic t) + { + + + + return new Solver(this, Z3native.mk_solver_from_tactic(nCtx, t.x#gno)); + } + + +(* FIXEDPOINTS *) +(** + Create a Fixedpoint context. +*) + public Fixedpoint MkFixedpoint ( ctx : context ) = + { + + + return new Fixedpoint(this); + } + + + +(* MISCELLANEOUS *) +(** + Wraps an AST. +*) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) + { + + return AST.Create(this, nativeObject); + } + +(** + Unwraps an AST. +*) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) + { + return a.x#gno; + } + +(** + Return a string describing all available parameters to Expr.Simplify. +*) + public string SimplifyHelp ( ctx : context ) = + { + + + return Z3native.simplify_get_help(nCtx); + } + +(** + Retrieves parameter descriptions for simplifier. +*) + public ParamDescrs SimplifyParameterDescriptions + { + get { return new ParamDescrs(this, Z3native.simplify_get_param_descrs(nCtx)); } + } + +(** + Enable/disable printing of warning messages to the console. +*) + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) + { + Z3native.toggle_warning_messages((enabled) ? 1 : 0); + } + + +(* ERROR HANDLING *) + //(** + //A delegate which is executed when an error is raised. + //*) + // + //Note that it is possible for memory leaks to occur if error handlers + //throw exceptions. + // + //public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); + + //(** + //The OnError event. + //*) + //public event ErrorHandler OnError = null; + + +(* PARAMETERS *) +(** + Update a mutable configuration parameter. +*) + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + + + public void UpdateParamValue(string id, string value) + { + Z3native.update_param_value(nCtx, id, value); + } + +(** + Get a configuration parameter. +*) + + Returns null if the parameter value does not exist. + + + public string GetParamValue(string id) + { + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value(nCtx, id, out res); + if (r == (int)Z3_lbool.Z3_L_FALSE) + return null; + else + return Marshal.PtrToStringAnsi(res); + } + + + +(* INTERNAL *) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get { return m_ctx) + + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + { + // Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + } + + internal void InitContext ( ctx : context ) = + { + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); // keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); + } +*) end From c28f0e7c8ac61db34bdb96493d3df1913bc2a5d4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 01:45:10 +0000 Subject: [PATCH 388/646] ML API bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 ++- scripts/update_api.py | 2 +- src/api/ml/z3.ml | 136 ++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 66 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 7046a92b0..f414e9d1a 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -18,10 +18,16 @@ let _ = let ctx = (new context cfg) in let is = (mk_symbol_int ctx 42) in let ss = (mk_symbol_string ctx "mySymbol") in + let bs = (mk_bool_sort ctx) in + let ints = (mk_int_sort ctx) in + let rs = (mk_real_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); Printf.printf "Disposing...\n"; - ctx#dispose (* can do, but we'd rather let it go out of scope *) ; + Gc.full_major () ); Printf.printf "Exiting.\n"; ;; diff --git a/scripts/update_api.py b/scripts/update_api.py index c8cd05c7e..c3f2abce6 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1280,7 +1280,7 @@ def mk_ml(): ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') ml_wrapper.write('\n\n') ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') - ml_wrapper.write(' identifier: "default handling",\n') + ml_wrapper.write(' identifier: (char*) "default handling",\n') ml_wrapper.write(' finalize: custom_finalize_default,\n') ml_wrapper.write(' compare: custom_compare_default,\n') ml_wrapper.write(' hash: custom_hash_default,\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 2100f371e..3a0e9208e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -30,21 +30,25 @@ object (self) Z3native.del_config(cfg) ; v - val mutable m_refCount : int = 0 + val mutable m_obj_cnt : int = 0 initializer - Gc.finalise (fun self -> self#dispose) self + (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v method dispose : unit = - if m_refCount == 0 then ( - Printf.printf "Disposing context %d \n" (Oo.id self) ; + if m_obj_cnt == 0 then ( + (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) (Z3native.del_context m_n_ctx) ) else ( + Printf.printf "NOT DISPOSING context %d because it still has %d objects alive\n" (Oo.id self) m_obj_cnt; (* re-queue for finalization? *) ) - method sub_one_ctx_obj = m_refCount <- m_refCount - 1 - method add_one_ctx_obj = m_refCount <- m_refCount + 1 + method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 + method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx end @@ -62,18 +66,21 @@ object (self) m_ctx#add_one_ctx_obj | None -> () ); - Gc.finalise (fun self -> self#dispose) self + (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v method virtual incref : Z3native.ptr -> Z3native.ptr -> unit method virtual decref : Z3native.ptr -> Z3native.ptr -> unit - (* - Disposes of the underlying native Z3 object. - *) method dispose = - Printf.printf "Disposing z3object %d \n" (Oo.id self) ; + (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) (match m_n_obj with - | Some (x) -> self#decref m_ctx#gno x; m_n_obj <- None; m_ctx#sub_one_ctx_obj + | Some (x) -> + self#decref m_ctx#gno x; + m_ctx#sub_one_ctx_obj ; + m_n_obj <- None; | None -> () ); @@ -81,10 +88,11 @@ object (self) | Some(x) -> x | None -> raise (Z3native.Exception "Z3 object lost") - method sno nc o = - self#incref nc o ; + method sno (ctx : context) o = + m_ctx#add_one_ctx_obj ; + self#incref ctx#gno o ; (match m_n_obj with - | Some(x) -> self#decref nc x + | Some(x) -> self#decref ctx#gno x ; m_ctx#sub_one_ctx_obj | None -> () ); m_n_obj <- Some o @@ -107,7 +115,7 @@ end class symbol ctx = object (self) inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method incref ctx o = () method decref ctx o = () end @@ -120,16 +128,16 @@ let symbolaton (a : symbol array) = class int_symbol ctx = object(self) inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_int i = (self#sno ctx#gno (Z3native.mk_int_symbol ctx#gno i)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol ctx#gno i)) ; self end (** String symbol objects *) class string_symbol ctx = object(self) inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_string name = (self#sno ctx#gno (Z3native.mk_string_symbol ctx#gno name)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol ctx#gno name)) ; self end let create_symbol ctx no = @@ -141,7 +149,7 @@ let create_symbol ctx no = class ast ctx = object (self) inherit z3object ctx None as super (* CMW: derive from icomparable? *) - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = Z3native.inc_ref nc o method decref nc o = Z3native.dec_ref nc o @@ -155,44 +163,44 @@ let astaton (a : ast array) = class sort ctx = object (self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Arithmetic sort objects, i.e., Int or Real. *) class arith_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Array sorts objects *) class array_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx#gno (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self end (** Bit-vector sort objects *) class bitvec_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Boolean sort objects *) class bool_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Datatype sort objects *) class datatype_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_sc (name : symbol) constructors = (self#sno ctx#gno (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_sc (name : symbol) constructors = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self end (** Enum sort objects *) @@ -201,12 +209,12 @@ object (self) inherit sort ctx as super val mutable _constdecls = None val mutable _testerdecls = None - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in _constdecls <- Some a ; _testerdecls <- Some b ; - (self#sno ctx#gno r) ; + (self#sno ctx r) ; self method const_decls = match _constdecls with @@ -222,37 +230,37 @@ end class int_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Real sort objects *) class real_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Uninterpreted sort objects *) class uninterpreted_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx#gno (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self end (** Finite domain sort objects *) class finite_domain_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx#gno (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self end (** Relation sort objects *) class relation_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** List sort objects *) @@ -265,7 +273,7 @@ object (self) val mutable _is_consdecl = None val mutable _headdecl = None val mutable _taildecl = None - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in _nildecl <- Some a ; @@ -274,7 +282,7 @@ object (self) _is_consdecl <- Some d ; _headdecl <- Some e ; _taildecl <- Some f ; - (self#sno ctx#gno r) ; + (self#sno ctx r) ; self method nil_decl = match _nildecl with @@ -307,18 +315,18 @@ end class set_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_s (s : sort) = (self#sno ctx#gno s#gno) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_s (s : sort) = (self#sno ctx s#gno) ; self end (** Tuple sort objects *) class tuple_sort ctx = object (self) inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in - (self#sno ctx#gno x) ; + (self#sno ctx x) ; self end @@ -339,9 +347,9 @@ let create_sort ctx obj = class func_decl ctx = object (self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx#gno (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o method decref nc o = super#decref nc o @@ -388,7 +396,7 @@ end class expr ctx = object(self) inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end let expraton (a : expr array) = @@ -399,77 +407,77 @@ let expraton (a : expr array) = class bool_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Arithmetic expression objects (int/real) *) class arith_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Int expression objects *) class int_expr ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Real expression objects *) class real_expr ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Bit-vector expression objects *) class bitvec_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Array expression objects *) class array_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Datatype expression objects *) class datatype_expr ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Integer numeral expression objects *) class int_num ctx = object (self) inherit int_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Rational numeral expression objects *) class rat_num ctx = object (self) inherit real_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Bit-vector numeral expression objects *) class bitvec_num ctx = object (self) inherit bitvec_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end (** Algebraic numeral expression objects *) class algebraic_num ctx = object (self) inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end @@ -477,7 +485,7 @@ end class quantifier ctx = object (self) inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx#gno obj) ; self + method cnstr_obj obj = (self#sno ctx obj) ; self end @@ -1112,7 +1120,7 @@ struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - x#sno x#gnc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + x#sno x#gc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -2483,7 +2491,7 @@ struct Create a new Boolean sort. *) let mk_bool_sort ( ctx : context ) = - (new bool_sort ctx) + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) (** Create a new uninterpreted sort. @@ -2501,13 +2509,13 @@ struct Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx) + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx) + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) (** Create a new bit-vector sort. From 2a6c74bc13e57459effcb46c0bcebc88bb7582b3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 03:57:18 +0000 Subject: [PATCH 389/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 572 ++++++++++++++++++++++++++++++----------------- 1 file changed, 364 insertions(+), 208 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 3a0e9208e..116d7a230 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -33,11 +33,11 @@ object (self) val mutable m_obj_cnt : int = 0 initializer - (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v - + (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) + let f = fun o -> o#dispose in + let v = self in + Gc.finalise f v + method dispose : unit = if m_obj_cnt == 0 then ( (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) @@ -110,7 +110,6 @@ object (self) method decref ctx o = Z3native.params_dec_ref ctx o end - (** Symbol objects *) class symbol ctx = object (self) @@ -166,6 +165,10 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +let sortaton (a : sort array) = + let f (e : sort) = e#gno in + Array.map f a + (** Arithmetic sort objects, i.e., Int or Real. *) class arith_sort ctx = object (self) @@ -195,20 +198,12 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** Datatype sort objects *) -class datatype_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) constructors = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (astaton constructors)))) ; self -end - (** Enum sort objects *) class enum_sort ctx = object (self) inherit sort ctx as super - val mutable _constdecls = None - val mutable _testerdecls = None + val mutable _constdecls : Z3native.ptr array option = None + val mutable _testerdecls : Z3native.ptr array option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in @@ -267,12 +262,12 @@ end class list_sort ctx = object (self) inherit sort ctx as super - val mutable _nildecl = None - val mutable _is_nildecl = None - val mutable _consdecl = None - val mutable _is_consdecl = None - val mutable _headdecl = None - val mutable _taildecl = None + val mutable _nildecl : Z3native.ptr option = None + val mutable _is_nildecl : Z3native.ptr option = None + val mutable _consdecl : Z3native.ptr option = None + val mutable _is_consdecl : Z3native.ptr option = None + val mutable _headdecl : Z3native.ptr option = None + val mutable _taildecl : Z3native.ptr option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in @@ -291,23 +286,23 @@ object (self) method is_nil_decl = match _is_nildecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decls") + | None -> raise (Z3native.Exception "Missing is_nil decl") method cons_decl = match _consdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decls") + | None -> raise (Z3native.Exception "Missing cons decl") method is_cons_decl = match _is_consdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decls") + | None -> raise (Z3native.Exception "Missing is_cons decl") method head_decl = match _headdecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decls") + | None -> raise (Z3native.Exception "Missing head decl") method tail_decl = match _taildecl with | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decls") + | None -> raise (Z3native.Exception "Missing tail decl") end @@ -330,18 +325,6 @@ object (self) self end -let create_sort ctx obj = - match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with - | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) - | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) - | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) - | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) - | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) - | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) - | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) - | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) - | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") (** Function declaration objects *) class func_decl ctx = @@ -392,6 +375,126 @@ object (self) method rational = m_r end + +(** Constructor objects *) +class constructor ctx = +object (self) + inherit z3object ctx None as super + val mutable m_n : int = 0 + val mutable m_tester_decl : func_decl option = None + val mutable m_constructor_decl : func_decl option = None + val mutable m_accessor_decls : func_decl array option = None + method incref ctx o = () + method decref ctx o = () + initializer + let f = fun o -> Z3native.del_constructor o#gnc o#gno in + let v = self in + Gc.finalise f v + + method cnstr_ssssi (name : symbol) (recognizer : symbol) (field_names : symbol array) (sorts : sort array) (sort_refs : int array) = + m_n <- (Array.length field_names) ; + if m_n != (Array.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if m_n != (Array.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let o = (Z3native.mk_constructor ctx#gno name#gno recognizer#gno m_n (symbolaton field_names) + (sortaton sorts) + sort_refs) in + self#sno ctx o ; + self + + method private init = + match m_tester_decl with + | None -> + let (a, b, c) = (Z3native.query_constructor self#gnc self#gno m_n) in + m_constructor_decl <- Some ((new func_decl ctx)#cnstr_obj a) ; + m_tester_decl <- Some ((new func_decl ctx)#cnstr_obj b) ; + m_accessor_decls <- Some (let f e = ((new func_decl ctx)#cnstr_obj e) in Array.map f c) ; + () + | _ -> () + + method get_n = m_n + + method tester_decl = match m_tester_decl with + | Some(x) -> x + | None -> self#init ; self#tester_decl + + method constructor_decl = match m_constructor_decl with + | Some(x) -> x + | None -> self#init ; self#constructor_decl + + method accessor_decls = match m_accessor_decls with + | Some(x) -> x + | None -> self#init ; self#accessor_decls +end + +let constructoraton (a : constructor array) = + let f (e : constructor) = e#gno in + Array.map f a + +(** Constructor list objects *) +class constructor_list ctx = +object (self) + inherit z3object ctx None + method incref ctx o = () + method decref ctx o = () + initializer + let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in + let v = self in + Gc.finalise f v + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ca ( c : constructor array ) = + self#sno ctx (Z3native.mk_constructor_list ctx#gno (Array.length c) (constructoraton c)) ; + self +end + +let constructor_listaton (a : constructor_list array) = + let f (e : constructor_list) = e#gno in + Array.map f a + +(** Datatype sort objects *) +class datatype_sort ctx = +object (self) + inherit sort ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (constructoraton constructors)))) ; self +end + +let create_sort ctx obj = + match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) + | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) + | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) + | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) + | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) + | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) + | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) + | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) + | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + +(** AST vector objects *) +class ast_vector ctx = +object (self) + inherit z3object ctx None + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref ctx o = Z3native.ast_vector_inc_ref ctx o + method decref ctx o = Z3native.ast_vector_dec_ref ctx o +end + + +(** AST map objects *) +class ast_map ctx = +object (self) + inherit z3object ctx None + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref ctx o = Z3native.ast_map_inc_ref ctx o + method decref ctx o = Z3native.ast_map_dec_ref ctx o +end + + (** Expression objects *) class expr ctx = object(self) @@ -492,7 +595,8 @@ end (**/**) -(** Interaction logging for Z3. +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) module Log = @@ -512,7 +616,7 @@ struct let append s = Z3native.append_log s end -(** Version information. *) +(** Version information *) module Version = struct (** The major version. *) @@ -536,7 +640,7 @@ struct string_of_int rev ^ "." end -(** Symbols are used to name several term and type constructors. *) +(** Symbols are used to name several term and type constructors *) module Symbol = struct (** The kind of the symbol (int or string) *) @@ -562,9 +666,7 @@ struct end -(** - The Sort module implements type information for ASTs. -*) +(** The Sort module implements type information for ASTs *) module Sort = struct (** @@ -612,13 +714,13 @@ struct end (** Bit-vector sorts *) -module BitVectorSort = +module BitVecSort = struct (** The size of the bit-vector sort. *) let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno end -(** Finite domain sorts. *) +(** Finite domain sorts *) module FiniteDomainSort = struct (** The size of the finite domain sort. *) @@ -628,7 +730,7 @@ struct else raise (Z3native.Exception "Conversion failed.") end -(** Relation sorts. *) +(** Relation sorts *) module RelationSort = struct (** The arity of the relation sort. *) @@ -684,60 +786,60 @@ let create_ast ctx no = | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") (**/**) -(** Function declarations. *) +(** Function declarations *) module FuncDecl = struct -(** Parameters of Func_Decls *) + (** Parameters of Func_Decls *) module Parameter = struct - (** - The kind of the parameter. - *) + (** + The kind of the parameter. + *) let get_kind (x : parameter) = x#kind - (**The int value of the parameter.*) + (**The int value of the parameter.*) let get_int (x : parameter) = if (x#kind != PARAMETER_INT) then raise (Z3native.Exception "parameter is not an int") else x#int - (**The double value of the parameter.*) + (**The double value of the parameter.*) let get_double (x : parameter) = if (x#kind != PARAMETER_DOUBLE) then raise (Z3native.Exception "parameter is not a double") else x#double - (**The Symbol value of the parameter.*) + (**The Symbol value of the parameter.*) let get_symbol (x : parameter) = if (x#kind != PARAMETER_SYMBOL) then raise (Z3native.Exception "parameter is not a symbol") else x#symbol - (**The Sort value of the parameter.*) + (**The Sort value of the parameter.*) let get_sort (x : parameter) = if (x#kind != PARAMETER_SORT) then raise (Z3native.Exception "parameter is not a sort") else x#sort - (**The AST value of the parameter.*) + (**The AST value of the parameter.*) let get_ast (x : parameter) = if (x#kind != PARAMETER_AST) then raise (Z3native.Exception "parameter is not an ast") else x#ast - (**The FunctionDeclaration value of the parameter.*) + (**The FunctionDeclaration value of the parameter.*) let get_ast (x : parameter) = if (x#kind != PARAMETER_FUNC_DECL) then raise (Z3native.Exception "parameter is not an function declaration") else x#func_decl - (**The rational string value of the parameter.*) + (**The rational string value of the parameter.*) let get_rational (x : parameter) = if (x#kind != PARAMETER_RATIONAL) then raise (Z3native.Exception "parameter is not a ratinoal string") @@ -826,7 +928,7 @@ struct (** Create expression that applies function to arguments. - + @param args The arguments *) let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args @@ -862,7 +964,7 @@ struct Array.init n f end -(** Enumeration sorts. *) +(** Enumeration sorts *) module EnumSort = struct (** The function declarations of the constants in the enumeration. *) @@ -876,7 +978,7 @@ struct Array.map f x#tester_decls end -(** List sorts. *) +(** List sorts *) module ListSort = struct (** The declaration of the nil function of this list sort. *) @@ -901,6 +1003,7 @@ struct let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] end +(** Tuple sorts *) module TupleSort = struct (** The constructor function of the tuple.*) @@ -917,7 +1020,7 @@ struct Array.init n f end -(** The abstract syntax tree (AST) module. *) +(** The abstract syntax tree (AST) module *) module AST = struct (** @@ -1077,12 +1180,107 @@ struct let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end +(** Vectors of ASTs *) +module ASTVector = +struct + (** The size of the vector *) + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size x#gnc x#gno + + (** + Retrieves the i-th object in the vector. + @param i Index + @return An AST + *) + let get ( x : ast_vector ) ( i : int ) = + create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + + (** Sets the i-th object in the vector. *) + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set x#gnc x#gno i value#gno + + (** Resize the vector to . + @param newSize The new size of the vector. *) + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize x#gnc x#gno new_size + + (** + Add the AST to the back of the vector. The size + is increased by 1. + @param a An AST + *) + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push x#gnc x#gno a#gno + + (** + Translates all ASTs in the vector to . + @param to_ctx A context + @return A new ASTVector + *) + let translate ( x : ast_vector ) ( to_ctx : context ) = + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + + (** Retrieves a string representation of the vector. *) + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string x#gnc x#gno +end + +(** Map from AST to AST *) +module ASTMap = +struct + (** Checks whether the map contains the key . + @param k An AST + @return True if is a key in the map, false otherwise. *) + let contains ( m : ast_map ) ( key : ast ) = + (int2lbool (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + + (** Finds the value associated with the key . + + This function signs an error when is not a key in the map. + + @param k An AST + *) + let find ( m : ast_map ) ( key : ast ) = + create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + + (** + Stores or replaces a new key/value pair in the map. + @param k The key AST + @param v The value AST + *) + let insert ( m : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + + (** + Erases the key from the map. + @param k An AST + *) + let erase ( m : ast_map ) ( key : ast ) = + Z3native.ast_map_erase m#gnc m#gno key#gno + + (** Removes all keys from the map. *) + let reset ( m : ast_map ) = + Z3native.ast_map_reset m#gnc m#gno + + (** The size of the map *) + let get_size ( m : ast_map ) = + Z3native.ast_map_size m#gnc m#gno + + (** The keys stored in the map. *) + let get_keys ( m : ast_map ) = + (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + + (** Retrieves a string representation of the map.*) + let to_strnig ( m : ast_map ) = + Z3native.ast_map_to_string m#gnc m#gno +end + (** Expressions (terms) *) module Expr = struct (** Returns a simplified version of the expression. - A set of parameters to configure the simplifier + @param p A set of parameters to configure the simplifier *) let simplify ( x : expr ) ( p : params option ) = match p with @@ -1155,8 +1353,8 @@ struct (** Translates (copies) the term to the Context . - A context - A copy of the term which is associated with + @param ctx A context + @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = if x#gc == to_ctx then @@ -1176,7 +1374,7 @@ struct (** Indicates whether the term is well-sorted. - True if the term is well-sorted, false otherwise. + @return True if the term is well-sorted, false otherwise. *) let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE @@ -2372,13 +2570,13 @@ struct Z3native.get_index_value x#gnc x#gno end -(* Integer Numerals *) +(** Integer Numerals *) module IntNum = struct (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -2410,9 +2608,9 @@ module BitVecNum = struct (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") - + if int2lbool(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno end @@ -2424,9 +2622,8 @@ struct Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^. - - the precision of the result - A numeral Expr of sort Real + @param precision the precision of the result + @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) @@ -2435,9 +2632,8 @@ struct Return a lower bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^. - - - A numeral Expr of sort Real + @param precision the precision of the result + @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) @@ -2450,8 +2646,24 @@ struct (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno end + +(** Constructors are used for datatype sorts *) +module Constructor = +struct + (** The number of fields of the constructor. *) + let get_num_fields ( x : constructor ) = x#get_n + + (** The function declaration of the constructor. *) + let get_constructor_decl ( x : constructor ) = x#constructor_decl + + (** The function declaration of the tester. *) + let get_tester_decl ( x : constructor ) = x#tester_decl + + (** The function declarations of the accessors *) + let get_accessor_decls ( x : constructor ) = x#accessor_decls +end -(** The main interaction with Z3 happens via the Context module. *) +(** The main interaction with Z3 happens via the Context module *) module Context = struct @@ -2551,151 +2763,95 @@ struct (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) ) - (** - Create a new list sort. - *) + (** + Create a new list sort. + *) let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort + (new list_sort ctx)#cnstr_ss name elem_sort - (** - Create a new list sort. - *) + (** + Create a new list sort. + *) let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort - (** - Create a new finite domain sort. - *) + (** + Create a new finite domain sort. + *) let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = (new finite_domain_sort ctx)#cnstr_si name size - (** - Create a new finite domain sort. - *) + (** + Create a new finite domain sort. + *) let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size -(** - -(* DATATYPES *) -(** - Create a datatype constructor. -*) - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - public Constructor MkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) - { + (* DATATYPES *) + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + mk_constructor ctx ((mk_symbol_string ctx name) :> symbol) recognizer field_names sorts sort_refs - return new Constructor(this, name, recognizer, fieldNames, sorts, sortRefs); - } + (** + Create a new datatype sort. + *) + let mk_datatype_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + (new datatype_sort ctx)#cnstr_sc name constructors + + (** + Create a new datatype sort. + *) + let mk_datatype_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + mk_datatype_sort ctx ((mk_symbol_string ctx name) :> symbol) constructors + + (** + Create mutually recursive datatypes. + @param names names of datatype sorts + @param c list of constructors, one list per sort. + *) + let mk_datatype_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let n = (Array.length names) in + let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let cla = (Array.map f c) in + let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + (Array.map g r) + + (** Create mutually recursive data-types. *) + let mk_datatype_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + mk_datatype_sorts ctx + ( + let f e = ((mk_symbol_string ctx e) :> symbol) in + Array.map f names + ) + c (** - Create a datatype constructor. -*) - @param name - @param recognizer - @param fieldNames - @param sorts - @param sortRefs - @return - public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) - { - - - return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs); - } - -(** - Create a new datatype sort. -*) - let mk_Datatype_Sort(Symbol name, Constructor[] constructors) - { - - - - - - - CheckContextMatch(name); - CheckContextMatch(constructors); - return new DatatypeSort(this, name, constructors); - } - -(** - Create a new datatype sort. -*) - let mk_Datatype_Sort(string name, Constructor[] constructors) - { - - - - - CheckContextMatch(constructors); - return new DatatypeSort(this, MkSymbol(name), constructors); - } - -(** - Create mutually recursive datatypes. -*) - @param names names of datatype sorts - @param c list of constructors, one list per sort. - let mk_Datatype_Sorts(Symbol[] names, Constructor[][] c) - { - - - - - - - - CheckContextMatch(names); - uint n = (uint)names.Length; - ConstructorList[] cla = new ConstructorList[n]; - IntPtr[] n_constr = new IntPtr[n]; - for (uint i = 0; i < n; i++) - { - Constructor[] constructor = c[i]; - - CheckContextMatch(constructor); - cla[i] = new ConstructorList(this, constructor); - n_constr[i] = cla[i].x#gno; - } - IntPtr[] n_res = new IntPtr[n]; - Z3native.mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); - DatatypeSort[] res = new DatatypeSort[n]; - for (uint i = 0; i < n; i++) - res[i] = new DatatypeSort(this, n_res[i]); - return res; - } - -(** - Create mutually recursive data-types. -*) - @param names - @param c - @return - let mk_Datatype_Sorts(string[] names, Constructor[][] c) - { - - - - - - - - return MkDatatypeSorts(MkSymbols(names), c); - } - - (* FUNCTION DECLARATIONS *) From 954d92a5135aa8996ef4db5b02756e8d956aca72 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 22 Dec 2012 21:06:13 +0000 Subject: [PATCH 390/646] More new ML API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 +- scripts/update_api.py | 11 +- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 1025 +++++++++++++++++++++++++++++++++++------ 4 files changed, 901 insertions(+), 141 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5ca0d2299..849644a18 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2777,13 +2777,13 @@ def mk_z3consts_ml(api_files): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) - efile.write('let %s2int x : int =\n' % (name[3:])) # strip Z3_ + efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') efile.write('(** Convert int to %s*)\n' % name[3:]) - efile.write('let int2%s x : %s =\n' % (name[3:],name[3:])) # strip Z3_ + efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') for k, i in decls.iteritems(): efile.write(' | %d -> %s\n' % (i, k[3:])) diff --git a/scripts/update_api.py b/scripts/update_api.py index c3f2abce6..27f7dd507 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1154,7 +1154,9 @@ def mk_ml(): for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) - ml_native.write('\nexception Exception of string\n\n') + ml_native.write('\nexternal is_null : ptr -> bool\n') + ml_native.write(' = "n_is_null"\n\n') + ml_native.write('exception Exception of string\n\n') # ML declarations ml_native.write(' module ML2C = struct\n\n') @@ -1219,9 +1221,9 @@ def mk_ml(): i = i + 1 ml_native.write(') in\n') if len(params) > 0 and param_type(params[0]) == CONTEXT: - ml_native.write(' let err = (int2error_code (ML2C.n_get_error_code a0)) in \n') + ml_native.write(' let err = (error_code_of_int (ML2C.n_get_error_code a0)) in \n') ml_native.write(' if err <> OK then\n') - ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (error_code2int err)))\n') + ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (int_of_error_code err)))\n') ml_native.write(' else\n') if result == VOID and len(op) == 0: ml_native.write(' ()\n') @@ -1290,6 +1292,9 @@ def mk_ml(): ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') + ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') + ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index 4d4a6c08f..ad5442327 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml *.ml -hide Z3 + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.ml -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 116d7a230..c22ef869b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -9,9 +9,6 @@ open Z3enums (**/**) -(* Object definitions. These are internal and should be interacted - with only via the corresponding functions from modules. *) - class virtual idisposable = object method virtual dispose : unit @@ -106,8 +103,8 @@ end class params ctx obj = object (self) inherit z3object ctx obj as super - method incref ctx o = Z3native.params_inc_ref ctx o - method decref ctx o = Z3native.params_dec_ref ctx o + method incref nc o = Z3native.params_inc_ref nc o + method decref nc o = Z3native.params_dec_ref nc o end (** Symbol objects *) @@ -115,8 +112,8 @@ class symbol ctx = object (self) inherit z3object ctx None as super method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () end let symbolaton (a : symbol array) = @@ -140,7 +137,7 @@ object(self) end let create_symbol ctx no = - match (int2symbol_kind (Z3native.get_symbol_kind ctx#gno no)) with + match (symbol_kind_of_int (Z3native.get_symbol_kind ctx#gno no)) with | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) @@ -198,29 +195,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** Enum sort objects *) -class enum_sort ctx = -object (self) - inherit sort ctx as super - val mutable _constdecls : Z3native.ptr array option = None - val mutable _testerdecls : Z3native.ptr array option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in - _constdecls <- Some a ; - _testerdecls <- Some b ; - (self#sno ctx r) ; - self - - method const_decls = match _constdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing const decls") - - method tester_decls = match _testerdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tester decls") -end - (** Int sort objects *) class int_sort ctx = object (self) @@ -258,54 +232,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end -(** List sort objects *) -class list_sort ctx = -object (self) - inherit sort ctx as super - val mutable _nildecl : Z3native.ptr option = None - val mutable _is_nildecl : Z3native.ptr option = None - val mutable _consdecl : Z3native.ptr option = None - val mutable _is_consdecl : Z3native.ptr option = None - val mutable _headdecl : Z3native.ptr option = None - val mutable _taildecl : Z3native.ptr option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in - _nildecl <- Some a ; - _is_nildecl <- Some b ; - _consdecl <- Some c ; - _is_consdecl <- Some d ; - _headdecl <- Some e ; - _taildecl <- Some f ; - (self#sno ctx r) ; - self - - method nil_decl = match _nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing nil decl") - - method is_nil_decl = match _is_nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decl") - - method cons_decl = match _consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decl") - - method is_cons_decl = match _is_consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decl") - - method head_decl = match _headdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decl") - - method tail_decl = match _taildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decl") - -end - (** Set sort objects *) class set_sort ctx = object (self) @@ -376,6 +302,76 @@ object (self) end +(** Enum sort objects *) +class enum_sort ctx = +object (self) + inherit sort ctx as super + val mutable _constdecls : func_decl array option = None + val mutable _testerdecls : func_decl array option = None + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ss (name : symbol) (enum_names : symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; + _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; + (self#sno ctx r) ; + self + + method const_decls = match _constdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing const decls") + + method tester_decls = match _testerdecls with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tester decls") +end + +(** List sort objects *) +class list_sort ctx = +object (self) + inherit sort ctx as super + val mutable _nildecl : func_decl option = None + val mutable _is_nildecl : func_decl option = None + val mutable _consdecl : func_decl option = None + val mutable _is_consdecl : func_decl option = None + val mutable _headdecl : func_decl option = None + val mutable _taildecl : func_decl option = None + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_ss (name : symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; + _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; + _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; + _is_consdecl <- Some ((new func_decl ctx)#cnstr_obj d) ; + _headdecl <- Some ((new func_decl ctx)#cnstr_obj e) ; + _taildecl <- Some ((new func_decl ctx)#cnstr_obj f) ; + (self#sno ctx r) ; + self + + method nil_decl = match _nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing nil decl") + + method is_nil_decl = match _is_nildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_nil decl") + + method cons_decl = match _consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing cons decl") + + method is_cons_decl = match _is_consdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing is_cons decl") + + method head_decl = match _headdecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing head decl") + + method tail_decl = match _taildecl with + | Some(x) -> x + | None -> raise (Z3native.Exception "Missing tail decl") +end + (** Constructor objects *) class constructor ctx = object (self) @@ -384,8 +380,8 @@ object (self) val mutable m_tester_decl : func_decl option = None val mutable m_constructor_decl : func_decl option = None val mutable m_accessor_decls : func_decl array option = None - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () initializer let f = fun o -> Z3native.del_constructor o#gnc o#gno in let v = self in @@ -438,8 +434,8 @@ let constructoraton (a : constructor array) = class constructor_list ctx = object (self) inherit z3object ctx None - method incref ctx o = () - method decref ctx o = () + method incref nc o = () + method decref nc o = () initializer let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in let v = self in @@ -463,7 +459,7 @@ object (self) end let create_sort ctx obj = - match (int2sort_kind (Z3native.get_sort_kind ctx#gno obj)) with + match (sort_kind_of_int (Z3native.get_sort_kind ctx#gno obj)) with | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) @@ -480,8 +476,8 @@ class ast_vector ctx = object (self) inherit z3object ctx None method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = Z3native.ast_vector_inc_ref ctx o - method decref ctx o = Z3native.ast_vector_dec_ref ctx o + method incref nc o = Z3native.ast_vector_inc_ref nc o + method decref nc o = Z3native.ast_vector_dec_ref nc o end @@ -490,8 +486,8 @@ class ast_map ctx = object (self) inherit z3object ctx None method cnstr_obj obj = (self#sno ctx obj) ; self - method incref ctx o = Z3native.ast_map_inc_ref ctx o - method decref ctx o = Z3native.ast_map_dec_ref ctx o + method incref nc o = Z3native.ast_map_inc_ref nc o + method decref nc o = Z3native.ast_map_dec_ref nc o end @@ -583,7 +579,6 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end - (** Quantifier objects *) class quantifier ctx = object (self) @@ -591,10 +586,127 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +(** Parameter description objects *) +class param_descrs ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.param_descrs_inc_ref nc o + method decref nc o = Z3native.param_descrs_dec_ref nc o +end +(** Goal objects *) +class goal ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.goal_inc_ref nc o + method decref nc o = Z3native.goal_dec_ref nc o +end + +(** Tactic objects *) +class tactic ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.tactic_inc_ref nc o + method decref nc o = Z3native.tactic_dec_ref nc o +end + +(** Function interpretation entry objects *) +class func_entry ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.func_entry_inc_ref nc o + method decref nc o = Z3native.func_entry_dec_ref nc o +end + +(** Function interpretation objects *) +class func_interp ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.func_interp_inc_ref nc o + method decref nc o = Z3native.func_interp_dec_ref nc o +end + +(** Model objects *) +class model ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.model_inc_ref nc o + method decref nc o = Z3native.model_dec_ref nc o +end + +(** Tactic application result objects *) +class apply_result ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.apply_result_inc_ref nc o + method decref nc o = Z3native.apply_result_dec_ref nc o +end + +(** Probe objects *) +class probe ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.probe_inc_ref nc o + method decref nc o = Z3native.probe_dec_ref nc o +end + +(** Statistical value objects *) +class statistics_entry = +object (self) + val mutable m_key : string = "" + val mutable m_is_int = false + val mutable m_is_float = false + val mutable m_int = 0 + val mutable m_float = 0.0 + + method cnstr_si k v = + m_key <- k; + m_is_int <- true; + m_int <- v; + self + + method cnstr_sd k v = + m_key <- k; + m_is_float <- true; + m_float <- v; + self + + method key = m_key + method int = m_int + method float = m_float + method is_int = m_is_int + method is_float = m_is_float +end + +(** Statistics objects *) +class statistics ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.stats_inc_ref nc o + method decref nc o = Z3native.stats_dec_ref nc o +end + +(** Solver objects *) +class solver ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.solver_inc_ref nc o + method decref nc o = Z3native.solver_dec_ref nc o +end (**/**) + (** Interaction logging for Z3 Note that this is a global, static log and if multiple Context @@ -606,7 +718,7 @@ struct @return True if opening the log file succeeds, false otherwise. *) (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((int2lbool (Z3native.open_log filename)) == L_TRUE) + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) (** Closes the interaction log. *) let close = Z3native.close_log @@ -644,7 +756,7 @@ end module Symbol = struct (** The kind of the symbol (int or string) *) - let kind (o : symbol) = (int2symbol_kind (Z3native.get_symbol_kind o#gnc o#gno)) + let kind (o : symbol) = (symbol_kind_of_int (Z3native.get_symbol_kind o#gnc o#gno)) (** Indicates whether the symbol is of Int kind *) let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL @@ -680,7 +792,7 @@ struct if a#gnc != b#gnc then false else - ((int2lbool (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) (** Returns a unique identifier for the sort. @@ -690,7 +802,7 @@ struct (** The kind of the sort. *) - let get_sort_kind (x : sort) = (int2sort_kind (Z3native.get_sort_kind x#gnc x#gno)) + let get_sort_kind (x : sort) = (sort_kind_of_int (Z3native.get_sort_kind x#gnc x#gno)) (** The name of the sort @@ -726,7 +838,7 @@ struct (** The size of the finite domain sort. *) let get_size (x : finite_domain_sort) = let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") end @@ -746,15 +858,15 @@ end (**/**) let create_expr ctx obj = - if int2ast_kind (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then (((new quantifier ctx)#cnstr_obj obj) :> expr) else let s = Z3native.get_sort ctx#gno obj in - let sk = (int2sort_kind (Z3native.get_sort_kind ctx#gno s)) in - if (int2lbool (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in + if (lbool_of_int (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if ((int2lbool (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + if ((lbool_of_int (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -776,7 +888,7 @@ let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = create_expr ctx o let create_ast ctx no = - match (int2ast_kind (Z3native.get_ast_kind ctx#gno no)) with + match (ast_kind_of_int (Z3native.get_ast_kind ctx#gno no)) with | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) | SORT_AST -> ((create_sort ctx no) :> ast) @@ -858,7 +970,7 @@ struct if a#gnc == a#gnc then false else - ((int2lbool (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) (** A string representations of the function declaration. *) @@ -897,7 +1009,7 @@ struct (** The kind of the function declaration. *) - let get_decl_kind (x : func_decl) = (int2decl_kind (Z3native.get_decl_kind x#gnc x#gno)) + let get_decl_kind (x : func_decl) = (decl_kind_of_int (Z3native.get_decl_kind x#gnc x#gno)) (** The name of the function declaration @@ -915,7 +1027,7 @@ struct let get_parameters (x : func_decl) = let n = (get_num_parameters x) in let f i = ( - match (int2parameter_kind (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with + match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) @@ -968,36 +1080,32 @@ end module EnumSort = struct (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = - let f e = ((new func_decl x#gc)#cnstr_obj e) in - Array.map f x#const_decls + let get_const_decls (x : enum_sort) = x#const_decls (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = - let f e = ((new func_decl x#gc)#cnstr_obj e) in - Array.map f x#tester_decls + let get_tester_decls (x : enum_sort) = x#tester_decls end (** List sorts *) module ListSort = struct (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#nil_decl + let get_nil_decl (x : list_sort) = x#nil_decl (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_nil_decl + let get_is_nil_decl (x : list_sort) = x#is_nil_decl (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#cons_decl + let get_cons_decl (x : list_sort) = x#cons_decl (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#is_cons_decl + let get_is_cons_decl (x : list_sort) = x#is_cons_decl (** The declaration of the head function of this list sort.*) - let get_head_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#head_decl + let get_head_decl (x : list_sort) = x#head_decl (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = (new func_decl x#gc)#cnstr_obj x#tail_decl + let get_tail_decl (x : list_sort) = x#tail_decl (** The empty list. *) let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] @@ -1037,7 +1145,7 @@ struct (** The kind of the AST. *) - let get_ast_kind ( x : ast) = (int2ast_kind (Z3native.get_ast_kind x#gnc x#gno)) + let get_ast_kind ( x : ast) = (ast_kind_of_int (Z3native.get_ast_kind x#gnc x#gno)) (** Indicates whether the AST is an Expr @@ -1092,7 +1200,7 @@ struct if a#gnc == b#gnc then false else - ((int2lbool (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + ((lbool_of_int (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) (** Object Comparison. @@ -1130,7 +1238,7 @@ struct Adds a parameter setting. *) let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (lbool2int (if value then L_TRUE else L_FALSE)) + Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) (** Adds a parameter setting. @@ -1232,7 +1340,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( m : ast_map ) ( key : ast ) = - (int2lbool (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE (** Finds the value associated with the key . @@ -1296,7 +1404,7 @@ struct Indicates whether the expression is the true or false expression or something else (Z3_L_UNDEF). *) - let get_bool_value ( x : expr ) = int2lbool (Z3native.get_bool_value x#gnc x#gno) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) (** The number of arguments of the expression. @@ -1370,13 +1478,13 @@ struct (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = int2lbool (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + let is_numeral ( x : expr ) = lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = int2lbool (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + let is_well_sorted ( x : expr ) = lbool_of_int (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE (** The Sort of the term. @@ -1387,7 +1495,7 @@ struct Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (AST.is_expr x) && - (int2lbool (Z3native.is_eq_sort x#gnc + (lbool_of_int (Z3native.is_eq_sort x#gnc (Z3native.mk_bool_sort x#gnc) (Z3native.get_sort x#gnc x#gno))) == L_TRUE @@ -1395,21 +1503,21 @@ struct Indicates whether the term is of integer sort. *) let is_int ( x : expr ) = - ((int2lbool (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) (** Indicates whether the term is of sort real. *) let is_real ( x : expr ) = - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) (** Indicates whether the term is of an array sort. *) let is_array ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) (** Indicates whether the term represents a constant. @@ -1431,7 +1539,7 @@ struct (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = int2lbool(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE (** Indicates whether the term is the constant true. @@ -1634,7 +1742,7 @@ struct Indicates whether the terms is of bit-vector sort. *) let is_bv ( x : expr ) = - ((int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral @@ -2422,8 +2530,8 @@ struct Indicates whether the term is of a relation sort. *) let is_Relation ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) (** Indicates whether the term is an relation store @@ -2536,8 +2644,8 @@ struct Indicates whether the term is of an array sort. *) let is_finite_domain ( x : expr ) = - ((int2lbool (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (int2sort_kind (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. @@ -2575,7 +2683,7 @@ module IntNum = struct (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) @@ -2608,7 +2716,7 @@ module BitVecNum = struct (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if int2lbool(r) == L_TRUE then v + if lbool_of_int(r) == L_TRUE then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) @@ -2662,7 +2770,654 @@ struct (** The function declarations of the accessors *) let get_accessor_decls ( x : constructor ) = x#accessor_decls end + + +(** ParamDescrs describe sets of parameters.*) +module ParamDescrs = +struct + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno + +end + +(** Goals + + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) +module Goal = +struct + + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. + *) + let get_precision ( x : goal ) = + goal_prec_of_int (Z3native.goal_precision x#gnc x#gno) + + (** Indicates whether the goal is precise. *) + let is_precise ( x : goal ) = + (get_precision x) == GOAL_PRECISE + + (** Indicates whether the goal is an under-approximation. *) + let is_underapproximation ( x : goal ) = + (get_precision x) == GOAL_UNDER + + (** Indicates whether the goal is an over-approximation. *) + let is_overapproximation ( x : goal ) = + (get_precision x) == GOAL_OVER + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) + let is_garbage ( x : goal ) = + (get_precision x) == GOAL_UNDER_OVER + + (** Adds the constraints to the given goal. *) + (* CMW: assert seems to be a keyword. *) + let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let f e = Z3native.goal_assert x#gnc x#gno e#gno in + Array.map f constraints + + (** Indicates whether the goal contains `false'. *) + let is_inconsistent ( x : goal ) = + (lbool_of_int (Z3native.goal_inconsistent x#gnc x#gno)) == L_TRUE + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) + let get_depth ( x : goal ) = Z3native.goal_depth x#gnc x#gno + + (** Erases all formulas from the given goal. *) + let reset ( x : goal ) = Z3native.goal_reset x#gnc x#gno + + (** The number of formulas in the goal. *) + let get_size ( x : goal ) = Z3native.goal_size x#gnc x#gno + + (** The formulas in the goal. *) + let get_formulas ( x : goal ) = + let n = get_size x in + let f i = (new bool_expr x#gc)#cnstr_obj (Z3native.goal_formula x#gnc x#gno i) in + Array.init n f + + (** The number of formulas, subformulas and terms in the goal. *) + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs x#gnc x#gno + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) + let is_decided_sat ( x : goal ) = + (lbool_of_int (Z3native.goal_is_decided_sat x#gnc x#gno)) == L_TRUE + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) + let is_decided_unsat ( x : goal ) = + (lbool_of_int (Z3native.goal_is_decided_unsat x#gnc x#gno)) == L_TRUE + + (** Translates (copies) the Goal to the target Context . *) + let translate ( x : goal ) ( to_ctx : context ) = + (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno to_ctx#gno) + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) + let simplify ( x : goal ) ( p : params option ) = + let tn = Z3native.mk_tactic x#gnc "simplify" in + Z3native.tactic_inc_ref x#gnc tn ; + let arn = match p with + | None -> Z3native.tactic_apply x#gnc tn x#gno + | Some(pn) -> Z3native.tactic_apply_ex x#gnc tn x#gno pn#gno + in + Z3native.apply_result_inc_ref x#gnc arn ; + let sg = Z3native.apply_result_get_num_subgoals x#gnc arn in + let res = if sg == 0 then + raise (Z3native.Exception "No subgoals") + else + Z3native.apply_result_get_subgoal x#gnc arn 0 in + Z3native.apply_result_dec_ref x#gnc arn ; + Z3native.tactic_dec_ref x#gnc tn ; + (new goal x#gc)#cnstr_obj res + + (** A string representation of the Goal. *) + let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno +end + + +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Tactic = +struct + (** A string containing a description of parameters accepted by the tactic. *) + let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno + + + (** Retrieves parameter descriptions for Tactics. *) + let get_param_descrs ( x : tactic ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.tactic_get_param_descrs x#gnc x#gno) + + (** Apply the tactic to the goal. *) + let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + match p with + | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) + | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) + + (** Creates a solver that is implemented using the given tactic. + *) + let get_solver ( x : tactic ) = + (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) + +end + + +(** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. +*) +module FuncInterp = +struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") +end + +(** Models. + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr x#gc np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl x#gnc n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in + if (lbool_of_int r) == L_FALSE then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr x#gc v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in + let n = (ASTVector.get_size n_univ) in + let f i = (ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno +end + +(** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) +module ApplyResult = +struct + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals x#gnc x#gno + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in + Array.init n f + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno +end + +(** Objects that track statistical information about solvers. *) +module Statistics = +struct + + (** + Statistical data is organized into pairs of [Key, Entry], where every + Entry is either a DoubleEntry or a UIntEntry + *) + module Entry = + struct + (** The key of the entry. *) + let get_key (x : statistics_entry) = x#key + + (** The int-value of the entry. *) + let get_int (x : statistics_entry) = x#int + + (** The float-value of the entry. *) + let get_float (x : statistics_entry) = x#float + + (** True if the entry is uint-valued. *) + let is_int (x : statistics_entry) = x#is_int + + (** True if the entry is double-valued. *) + let is_float (x : statistics_entry) = x#is_float + + (** The string representation of the the entry's value. *) + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + + (** The string representation of the entry (key and value) *) + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + (** A string representation of the statistical data. *) + let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + + (** The number of statistical data. *) + let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + + (** The data entries. *) + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key x#gnc x#gno i in + if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + else + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ) in + Array.init n f + + (** + The statistical counters. + *) + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key x#gnc x#gno i) in + Array.init n f + + (** + The value of a particular statistical counter. + *) + let get ( x : statistics ) ( key : string ) = + let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + Array.fold_left f None (get_entries x) + +end + +(** Solvers *) +module Solver = +struct + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + (** + A string that describes all available solver parameters. + *) + let get_help ( x : solver ) = Z3native.solver_get_help x#gnc x#gno + + (** + Sets the solver parameters. + *) + let set_parameters ( x : solver ) ( value : params )= + Z3native.solver_set_params x#gnc x#gno value#gno + + (** + Retrieves parameter descriptions for solver. + *) + let get_param_descrs ( x : solver ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.solver_get_param_descrs x#gnc x#gno) + + (** + The current number of backtracking points (scopes). + + + *) + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes x#gnc x#gno + + (** + Creates a backtracking point. + + *) + let push ( x : solver ) = Z3native.solver_push x#gnc x#gno + + (** + Backtracks backtracking points. + Note that an exception is thrown if is not smaller than NumScopes + + *) + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n + + (** + Resets the Solver. + This removes all assertions from the solver. + *) + let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno + + (** + Assert a constraint (or multiple) into the solver. + *) + let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in + Array.map f constraints + + (** + The number of assertions in the solver. + *) + let get_num_assertions ( x : solver ) = + let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + (ASTVector.get_size a) + + + (** + The set of asserted formulas. + *) + let get_assertions ( x : solver ) = + let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let n = (ASTVector.get_size a) in + let f i = ((new bool_expr x#gc)#cnstr_obj (ASTVector.get a i)#gno) in + Array.init n f + + (** + Checks whether the assertions in the solver are consistent or not. + + + + + + *) + let check ( x : solver ) ( assumptions : bool_expr array option) = + let r = + match assumptions with + | None -> lbool_of_int (Z3native.solver_check x#gnc x#gno) + | Some (ass) -> lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length ass) (astaton ass)) + in + match r with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN + + (** + The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. + + *) + let get_model ( x : solver ) = + let q = Z3native.solver_get_model x#gnc x#gno in + if (Z3native.is_null q) then + None + else + Some ((new model x#gc)#cnstr_obj q) + + (** + The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. + + *) + let get_proof ( x : solver ) = + let q = Z3native.solver_get_proof x#gnc x#gno in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. + + *) + let get_unsat_core ( x : solver ) = + let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in + let n = (ASTVector.get_size cn) in + let f i = (ASTVector.get cn i) in + Array.init n f + + (** + A brief justification of why the last call to Check returned UNKNOWN. + *) + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown x#gnc x#gno + + + (** + Solver statistics. + *) + let get_statistics ( x : solver ) = + (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + + (** + A string representation of the solver. + *) + let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno +end + +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = +struct + (** + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. + *) + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply x#gnc x#gno g#gno +end + + (** The main interaction with Z3 happens via the Context module *) module Context = struct From f1ecf3ae0bec626e0bc9861ed94beb146f288424 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 23 Dec 2012 02:20:24 +0000 Subject: [PATCH 391/646] New ML API savepoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 6488 +++++++++++++++++++--------------------------- 1 file changed, 2629 insertions(+), 3859 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c22ef869b..5f67e11e2 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -586,6 +586,13 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +(** Quantifier pattern objects *) +class pattern ctx = +object (self) + inherit ast ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self +end + (** Parameter description objects *) class param_descrs ctx = object (self) @@ -775,6 +782,33 @@ struct match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) + + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_int ( ctx : context ) i = + (new int_symbol ctx)#cnstr_int i + + (** Creates a new symbol using a string. *) + let mk_string ( ctx : context ) s = + (new string_symbol ctx)#cnstr_string s + + (** + Create an array of symbols. + *) + let mk_ints ( ctx : context ) ( names : int array ) = + let f elem = mk_int ( ctx : context ) elem in + (Array.map f names) + + (** + Create an array of symbols. + *) + let mk_strings ( ctx : context ) ( names : string array ) = + let f elem = mk_string ( ctx : context ) elem in + (Array.map f names) end @@ -813,49 +847,26 @@ struct A string representation of the sort. *) let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno + + (** + Create a new Boolean sort. + *) + let mk_bool ( ctx : context ) = + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted ( ctx : context ) (s : symbol) = + (new uninterpreted_sort ctx)#cnstr_s s + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_s ( ctx : context ) (s : string) = + mk_uninterpreted ctx ((Symbol.mk_string ( ctx : context ) s) :> symbol) end -(** Array sorts *) -module ArraySort = -struct - (** The domain of the array sort. *) - let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) - - (** The range of the array sort. *) - let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) -end - -(** Bit-vector sorts *) -module BitVecSort = -struct - (** The size of the bit-vector sort. *) - let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno -end - -(** Finite domain sorts *) -module FiniteDomainSort = -struct - (** The size of the finite domain sort. *) - let get_size (x : finite_domain_sort) = - let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") -end - -(** Relation sorts *) -module RelationSort = -struct - (** The arity of the relation sort. *) - let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno - - (** The sorts of the columns of the relation sort. *) - let get_column_sorts (x : relation_sort) = - let n = get_arity x in - let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in - Array.init n f - -end - (**/**) let create_expr ctx obj = if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then @@ -957,6 +968,48 @@ struct raise (Z3native.Exception "parameter is not a ratinoal string") else x#rational + + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name domain range + + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = + mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix domain range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name [||] range + + + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix [||] range + end (** @@ -1046,91 +1099,103 @@ struct end -(** Datatype sorts *) -module DatatypeSort = -struct - (** The number of constructors of the datatype sort. *) - let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno - - (** The range of the array sort. *) - let get_constructors (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in - Array.init n f - - (** The recognizers. *) - let get_recognizers (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in - Array.init n f - - (** The constructor accessors. *) - let get_accessors (x : datatype_sort) = - let n = (get_num_constructors x) in - let f i = ( - let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in - let ds = (Z3native.get_domain_size fd#gnc fd#gno) in - let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in - Array.init ds g - ) in - Array.init n f -end - -(** Enumeration sorts *) -module EnumSort = -struct - (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = x#const_decls - - (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = x#tester_decls -end - -(** List sorts *) -module ListSort = -struct - (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = x#nil_decl - - (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = x#is_nil_decl - - (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = x#cons_decl - - (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = x#is_cons_decl - - (** The declaration of the head function of this list sort.*) - let get_head_decl (x : list_sort) = x#head_decl - - (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = x#tail_decl - - (** The empty list. *) - let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] -end - -(** Tuple sorts *) -module TupleSort = -struct - (** The constructor function of the tuple.*) - let get_mk_decl (x : tuple_sort) = - (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) - - (** The number of fields in the tuple. *) - let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno - - (** The field declarations. *) - let get_field_decls (x : tuple_sort) = - let n = get_num_fields x in - let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in - Array.init n f -end - (** The abstract syntax tree (AST) module *) module AST = struct + (** Vectors of ASTs *) + module ASTVector = + struct + (** The size of the vector *) + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size x#gnc x#gno + + (** + Retrieves the i-th object in the vector. + @param i Index + @return An AST + *) + let get ( x : ast_vector ) ( i : int ) = + create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + + (** Sets the i-th object in the vector. *) + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set x#gnc x#gno i value#gno + + (** Resize the vector to . + @param newSize The new size of the vector. *) + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize x#gnc x#gno new_size + + (** + Add the AST to the back of the vector. The size + is increased by 1. + @param a An AST + *) + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push x#gnc x#gno a#gno + + (** + Translates all ASTs in the vector to . + @param to_ctx A context + @return A new ASTVector + *) + let translate ( x : ast_vector ) ( to_ctx : context ) = + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + + (** Retrieves a string representation of the vector. *) + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string x#gnc x#gno + end + + (** Map from AST to AST *) + module ASTMap = + struct + (** Checks whether the map contains the key . + @param k An AST + @return True if is a key in the map, false otherwise. *) + let contains ( m : ast_map ) ( key : ast ) = + (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + + (** Finds the value associated with the key . + + This function signs an error when is not a key in the map. + @param k An AST + *) + let find ( m : ast_map ) ( key : ast ) = + create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + + (** + Stores or replaces a new key/value pair in the map. + @param k The key AST + @param v The value AST + *) + let insert ( m : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + + (** + Erases the key from the map. + @param k An AST + *) + let erase ( m : ast_map ) ( key : ast ) = + Z3native.ast_map_erase m#gnc m#gno key#gno + + (** Removes all keys from the map. *) + let reset ( m : ast_map ) = + Z3native.ast_map_reset m#gnc m#gno + + (** The size of the map *) + let get_size ( m : ast_map ) = + Z3native.ast_map_size m#gnc m#gno + + (** The keys stored in the map. *) + let get_keys ( m : ast_map ) = + (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + + (** Retrieves a string representation of the map.*) + let to_strnig ( m : ast_map ) = + Z3native.ast_map_to_string m#gnc m#gno + end + (** The AST's hash code. @return A hash code @@ -1159,7 +1224,7 @@ struct | _ -> false (** - Indicates whether the AST is a BoundVariable + Indicates whether the AST is a bound variable *) let is_var ( x : ast) = (get_ast_kind x) == VAR_AST @@ -1227,163 +1292,7 @@ struct (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) end -(** - Parameter sets - - A Params objects represents a configuration in the form of Symbol/value pairs. -*) -module Params = -struct - (** - Adds a parameter setting. - *) - let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) - - (** - Adds a parameter setting. - *) - let add_int (p : params) (name : symbol) (value : int) = - Z3native.params_set_uint p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_double (p : params) (name : symbol) (value : float) = - Z3native.params_set_double p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_symbol (p : params) (name : symbol) (value : symbol) = - Z3native.params_set_symbol p#gnc p#gno name#gno value#gno - - (** - Adds a parameter setting. - *) - let add_s_bool (p : params) (name : string) (value : bool) = - add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_int (p : params) (name : string) (value : int) = - add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_double (p : params) (name : string) (value : float) = - add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_symbol (p : params) (name : string) (value : symbol) = - add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - A string representation of the parameter set. - *) - let to_string (p : params) = Z3native.params_to_string p#gnc p#gno -end - -(** Vectors of ASTs *) -module ASTVector = -struct - (** The size of the vector *) - let get_size ( x : ast_vector ) = - Z3native.ast_vector_size x#gnc x#gno - - (** - Retrieves the i-th object in the vector. - @param i Index - @return An AST - *) - let get ( x : ast_vector ) ( i : int ) = - create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) - - (** Sets the i-th object in the vector. *) - let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set x#gnc x#gno i value#gno - - (** Resize the vector to . - @param newSize The new size of the vector. *) - let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize x#gnc x#gno new_size - - (** - Add the AST to the back of the vector. The size - is increased by 1. - @param a An AST - *) - let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push x#gnc x#gno a#gno - - (** - Translates all ASTs in the vector to . - @param to_ctx A context - @return A new ASTVector - *) - let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) - - (** Retrieves a string representation of the vector. *) - let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string x#gnc x#gno -end - -(** Map from AST to AST *) -module ASTMap = -struct - (** Checks whether the map contains the key . - @param k An AST - @return True if is a key in the map, false otherwise. *) - let contains ( m : ast_map ) ( key : ast ) = - (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE - - (** Finds the value associated with the key . - - This function signs an error when is not a key in the map. - - @param k An AST - *) - let find ( m : ast_map ) ( key : ast ) = - create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) - - (** - Stores or replaces a new key/value pair in the map. - @param k The key AST - @param v The value AST - *) - let insert ( m : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert m#gnc m#gno key#gno value#gno - - (** - Erases the key from the map. - @param k An AST - *) - let erase ( m : ast_map ) ( key : ast ) = - Z3native.ast_map_erase m#gnc m#gno key#gno - - (** Removes all keys from the map. *) - let reset ( m : ast_map ) = - Z3native.ast_map_reset m#gnc m#gno - - (** The size of the map *) - let get_size ( m : ast_map ) = - Z3native.ast_map_size m#gnc m#gno - - (** The keys stored in the map. *) - let get_keys ( m : ast_map ) = - (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) - - (** Retrieves a string representation of the map.*) - let to_strnig ( m : ast_map ) = - Z3native.ast_map_to_string m#gnc m#gno -end - -(** Expressions (terms) *) +(** General expressions (terms), including Boolean logic *) module Expr = struct (** @@ -1402,7 +1311,7 @@ struct (** Indicates whether the expression is the true or false expression - or something else (Z3_L_UNDEF). + or something else (L_UNDEF). *) let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) @@ -1434,7 +1343,6 @@ struct The result is the new expression. The arrays from and to must have size num_exprs. For every i smaller than num_exprs, we must have that sort of from[i] must be equal to sort of to[i]. - *) let substitute ( x : expr ) from to_ = if (Array.length from) <> (Array.length to_) then @@ -1453,7 +1361,6 @@ struct Substitute the free variables in the expression with the expressions in For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. - *) let substitute_vars ( x : expr ) to_ = create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) @@ -1496,28 +1403,8 @@ struct *) let is_bool ( x : expr ) = (AST.is_expr x) && (lbool_of_int (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno))) == L_TRUE - - (** - Indicates whether the term is of integer sort. - *) - let is_int ( x : expr ) = - ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) - - (** - Indicates whether the term is of sort real. - *) - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) - - (** - Indicates whether the term is of an array sort. - *) - let is_array ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno))) == L_TRUE (** Indicates whether the term represents a constant. @@ -1526,21 +1413,6 @@ struct (get_num_args x) == 0 && FuncDecl.get_domain_size(get_func_decl x) == 0 - (** - Indicates whether the term is an integer numeral. - *) - let is_int_numeral ( x : expr ) = (is_numeral x) && (is_int x) - - (** - Indicates whether the term is a real numeral. - *) - let is_rat_num ( x : expr ) = (is_numeral x) && (is_real x) - - (** - Indicates whether the term is an algebraic number - *) - let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE - (** Indicates whether the term is the constant true. *) @@ -1597,146 +1469,1189 @@ struct let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) (** - Indicates whether the term is an arithmetic numeral. + Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ANUM) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) (** - Indicates whether the term is a less-than-or-equal + Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LE) (** - Indicates whether the term is a greater-than-or-equal + Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GE) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) (** - Indicates whether the term is a less-than + Creates a new Constant of sort and named . *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LT) + let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + create_expr ctx (Z3native.mk_const ctx#gno name#gno range#gno) + (** - Indicates whether the term is a greater-than + Creates a new Constant of sort and named . *) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_GT) + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) range + (** - Indicates whether the term is addition (binary) + Creates a constant from the func_decl . + @param f An expression of a 0-arity function *) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ADD) + let mk_const_f ( ctx : context ) ( f : func_decl ) = + create_expr_fa ctx f [||] (** - Indicates whether the term is subtraction (binary) + Creates a fresh constant of sort and a + name prefixed with . *) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SUB) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = + create_expr ctx (Z3native.mk_fresh_const ctx#gno prefix range#gno) (** - Indicates whether the term is a unary minus - *) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UMINUS) + Create a Boolean constant. + *) + let mk_bool_const ( ctx : context ) ( name : symbol ) = + ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) + + (** + Create a Boolean constant. + *) + let mk_bool_const_s ( ctx : context ) ( name : string ) = + mk_bool_const ctx ((Symbol.mk_string ctx name) :> symbol) (** - Indicates whether the term is multiplication (binary) + Create a new function application. *) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MUL) + let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = + create_expr_fa ctx f args (** - Indicates whether the term is division (binary) - *) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DIV) + The true Term. + *) + let mk_true ( ctx : context ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_true ctx#gno) (** - Indicates whether the term is integer division (binary) - *) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IDIV) + The false Term. + *) + let mk_false ( ctx : context ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_false ctx#gno) (** - Indicates whether the term is remainder (binary) - *) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REM) + Creates a Boolean value. + *) + let mk_bool ( ctx : context ) ( value : bool) = + if value then mk_true ctx else mk_false ctx (** - Indicates whether the term is modulus (binary) + Creates the equality = . *) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_MOD) + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq ctx#gno x#gno y#gno) (** - Indicates whether the term is a coercion of integer to real (unary) + Creates a distinct term. *) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_REAL) + let mk_distinct ( ctx : context ) ( args : expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct ctx#gno (Array.length args) (astaton args)) + + (** + Mk an expression representing not(a). + *) + let mk_not ( ctx : context ) ( a : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_not ctx#gno a#gno) + + (** + Create an expression representing an if-then-else: ite(t1, t2, t3). + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + *) + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + create_expr ctx (Z3native.mk_ite ctx#gno t1#gno t2#gno t3#gno) + + (** + Create an expression representing t1 iff t2. + *) + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff ctx#gno t1#gno t2#gno) (** - Indicates whether the term is a coercion of real to integer (unary) + Create an expression representing t1 -> t2. *) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TO_INT) + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies ctx#gno t1#gno t2#gno) (** - Indicates whether the term is a check that tests whether a real is integral (unary) + Create an expression representing t1 xor t2. *) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IS_INT) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor ctx#gno t1#gno t2#gno) + + (** + Create an expression representing the AND of args + *) + let mk_and ( ctx : context ) ( args : bool_expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_and ctx#gno (Array.length args) (astaton args)) + + (** + Create an expression representing the OR of args + *) + let mk_or ( ctx : context ) ( args : bool_expr array ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) +end + +(** Functions to manipulate Array expressions *) +module Arrays = +struct + (** + Create a new array sort. + *) + let mk_sort ( ctx : context ) domain range = + (new array_sort ctx)#cnstr_dr domain range (** Indicates whether the term is an array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. + Array store takes at least 3 arguments. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. + For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the - function passed as parameter. + function passed as parameter. *) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + (** + Indicates whether the term is of an array sort. + *) + let is_array ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + + (** The domain of the array sort. *) + let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + + (** The range of the array sort. *) + let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) + + + (** + Create an array constant. + *) + let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) + + (** + Create an array constant. + *) + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) domain range + + (** + Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + + + *) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + ((create_expr ctx (Z3native.mk_select ctx#gno a#gno i#gno)) :> array_expr) + + (** + Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + + + *) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = + (new array_expr ctx)#cnstr_obj (Z3native.mk_store ctx#gno a#gno i#gno v#gno) + + (** + Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + + + *) + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array ctx#gno domain#gno v#gno) + + (** + Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + + + + *) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + ((create_expr ctx (Z3native.mk_map ctx#gno f#gno (Array.length args) (astaton args))) :> array_expr) + + (** + Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. + *) + let mk_term_array ( ctx : context ) ( arg : array_expr ) = + ((create_expr ctx (Z3native.mk_array_default ctx#gno arg#gno)) :> array_expr) +end + +(** Functions to manipulate Set expressions *) +module Sets = +struct (** Indicates whether the term is set union *) - let is_set_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_set_intersect ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_set_difference ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_set_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_set_subset ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + +(** + Create a set type. +*) +let mk_sort ( ctx : context ) ( ty : sort) = + (new set_sort ctx)#cnstr_s ty + +(** + Create an empty set. +*) +let mk_empty ( ctx : context ) ( domain : sort ) = + (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + + (** + Create the full set. + *) +let mk_full ( ctx : context ) ( domain : sort ) = + create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + +(** + Add an element to the set. +*) +let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + + (** + Remove an element from a set. + *) +let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + + (** + Take the union of a list of sets. + *) +let mk_union ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + +(** + Take the intersection of a list of sets. +*) +let mk_intersection ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + +(** + Take the difference between two sets. +*) +let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + +(** + Take the complement of a set. +*) +let mk_complement ( ctx : context ) ( arg : expr ) = + create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + +(** + Check for set membership. +*) +let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + + (** + Check for subsetness of sets. + *) +let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + +end + +(** Functions to manipulate Finite Domain expressions *) +module FiniteDomains = +struct + (** + Create a new finite domain sort. + *) + let mk_sort ( ctx : context ) ( name : symbol ) size = + (new finite_domain_sort ctx)#cnstr_si name size + + (** + Create a new finite domain sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) size = + (new finite_domain_sort ctx)#cnstr_si ((Symbol.mk_string ctx name) :> symbol) size + + + (** + Indicates whether the term is of an array sort. + *) + let is_finite_domain ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + + (** + Indicates whether the term is a less than predicate over a finite domain. + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + + (** The size of the finite domain sort. *) + let get_size (x : finite_domain_sort) = + let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") +end + +(** Functions to manipulate Relation expressions *) +module Relations = +struct + (** + Indicates whether the term is of a relation sort. + *) + let is_relation ( x : expr ) = + ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + + (** + Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. + *) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + + (** + Indicates whether the term is an empty relation + *) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + + (** + Indicates whether the term is a test for the emptiness of a relation + *) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + + (** + Indicates whether the term is a relational join + *) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + + (** + Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. + *) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + + (** + Indicates whether the term is the widening of two relations + The function takes two arguments. + *) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + + (** + Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. + *) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + + (** + Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. + *) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + + (** + Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. + *) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + + (** + Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. + *) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + + (** + Indicates whether the term is the complement of a relation + *) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + + (** + Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. + *) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + + (** + Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind + to perform destructive updates to the first argument. + *) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + + (** The arity of the relation sort. *) + let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + + (** The sorts of the columns of the relation sort. *) + let get_column_sorts (x : relation_sort) = + let n = get_arity x in + let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + Array.init n f + +end + +(** Quantifier expressions *) +module Quantifiers = +struct + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Pattern = + struct + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms x#gnc x#gno + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + end + + (** + Indicates whether the quantifier is universal. + *) + let is_universal ( x : quantifier ) = + lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + + (** + Indicates whether the quantifier is existential. + *) + let is_existential ( x : quantifier ) = not (is_universal x) + + (** + The weight of the quantifier. + *) + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + + (** + The number of patterns. + *) + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + + (** + The patterns. + *) + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of no-patterns. + *) + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + + (** + The no-patterns. + *) + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of bound variables. + *) + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + + (** + The symbols for the bound variables. + *) + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + Array.init n f + + (** + The sorts of the bound variables. + *) + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + Array.init n f + + (** + The body of the quantifier. + *) + let get_body ( x : quantifier ) = + (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + + (** + Creates a new bound variable. + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + *) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + + (** + Create a quantifier pattern. + *) + let mk_pattern ( ctx : context ) ( terms : expr array ) = + if (Array.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) +end + +(** Functions to manipulate Datatype expressions *) +module Datatypes = +struct + (** Constructors *) + module Constructor = + struct + (** The number of fields of the constructor. *) + let get_num_fields ( x : constructor ) = x#get_n + + (** The function declaration of the constructor. *) + let get_constructor_decl ( x : constructor ) = x#constructor_decl + + (** The function declaration of the tester. *) + let get_tester_decl ( x : constructor ) = x#tester_decl + + (** The function declarations of the accessors *) + let get_accessor_decls ( x : constructor ) = x#accessor_decls + end + + (* DATATYPES *) + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + + + (** + Create a datatype constructor. + @param name constructor name + @param recognizer name of recognizer function. + @param fieldNames names of the constructor fields. + @param sorts field sorts, 0 if the field sort refers to a recursive sort. + @param sortRefs reference to datatype sort that is an argument to the constructor; + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. + *) + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + mk_constructor ctx ((Symbol.mk_string ctx name) :> symbol) recognizer field_names sorts sort_refs + + + (** + Create a new datatype sort. + *) + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + (new datatype_sort ctx)#cnstr_sc name constructors + + (** + Create a new datatype sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) constructors + + (** + Create mutually recursive datatypes. + @param names names of datatype sorts + @param c list of constructors, one list per sort. + *) + let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let n = (Array.length names) in + let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let cla = (Array.map f c) in + let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + (Array.map g r) + + (** Create mutually recursive data-types. *) + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + mk_sorts ctx + ( + let f e = ((Symbol.mk_string ctx e) :> symbol) in + Array.map f names + ) + c + + (** The number of constructors of the datatype sort. *) + let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + + (** The range of the array sort. *) + let get_constructors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + Array.init n f + + (** The recognizers. *) + let get_recognizers (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + Array.init n f + + (** The constructor accessors. *) + let get_accessors (x : datatype_sort) = + let n = (get_num_constructors x) in + let f i = ( + let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in + let ds = (Z3native.get_domain_size fd#gnc fd#gno) in + let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + Array.init ds g + ) in + Array.init n f +end + +(** Functions to manipulate Enumeration expressions *) +module Enumerations = +struct + (** + Create a new enumeration sort. + *) + let mk_sort ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss name enum_names + + (** + Create a new enumeration sort. + *) + let mk_sort_s ( ctx : context ) name enum_names = + (new enum_sort ctx)#cnstr_ss + ((Symbol.mk_string ( ctx : context ) name) :> symbol) + (let f e = (e :> symbol) in + (Array.map f (Symbol.mk_strings ( ctx : context ) enum_names)) + ) + + (** The function declarations of the constants in the enumeration. *) + let get_const_decls (x : enum_sort) = x#const_decls + + (** The test predicates for the constants in the enumeration. *) + let get_tester_decls (x : enum_sort) = x#tester_decls +end + +(** Functions to manipulate List expressions *) +module Lists = +struct + (** + Create a new list sort. + *) + let mk_sort ( ctx : context ) (name : symbol) elem_sort = + (new list_sort ctx)#cnstr_ss name elem_sort + + (** + Create a new list sort. + *) + let mk_list_s ( ctx : context ) (name : string) elem_sort = + mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) elem_sort + + + (** The declaration of the nil function of this list sort. *) + let get_nil_decl (x : list_sort) = x#nil_decl + + (** The declaration of the isNil function of this list sort. *) + let get_is_nil_decl (x : list_sort) = x#is_nil_decl + + (** The declaration of the cons function of this list sort. *) + let get_cons_decl (x : list_sort) = x#cons_decl + + (** The declaration of the isCons function of this list sort. *) + let get_is_cons_decl (x : list_sort) = x#is_cons_decl + + (** The declaration of the head function of this list sort. *) + let get_head_decl (x : list_sort) = x#head_decl + + (** The declaration of the tail function of this list sort. *) + let get_tail_decl (x : list_sort) = x#tail_decl + + (** The empty list. *) + let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] +end + +(** Functions to manipulate Tuple expressions *) +module Tuples = +struct + (** + Create a new tuple sort. + *) + let mk_sort ( ctx : context ) name field_names field_sorts = + (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts + + (** The constructor function of the tuple. *) + let get_mk_decl (x : tuple_sort) = + (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + + (** The number of fields in the tuple. *) + let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + + (** The field declarations. *) + let get_field_decls (x : tuple_sort) = + let n = get_num_fields x in + let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + Array.init n f +end + +(** Functions to manipulate arithmetic expressions *) +module Arithmetic = +struct + (** + Create a new integer sort. + *) + let mk_int_sort ( ctx : context ) = + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) + + (** + Create a real sort. + *) + let mk_real_sort ( ctx : context ) = + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) + + (** + Indicates whether the term is of integer sort. + *) + let is_int ( x : expr ) = + ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + + (** + Indicates whether the term is an arithmetic numeral. + *) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + (** + Indicates whether the term is a less-than-or-equal + *) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + (** + Indicates whether the term is a greater-than-or-equal + *) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + (** + Indicates whether the term is a less-than + *) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + (** + Indicates whether the term is a greater-than + *) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + (** + Indicates whether the term is addition (binary) + *) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + (** + Indicates whether the term is subtraction (binary) + *) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + (** + Indicates whether the term is a unary minus + *) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + (** + Indicates whether the term is multiplication (binary) + *) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + (** + Indicates whether the term is division (binary) + *) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + (** + Indicates whether the term is integer division (binary) + *) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + (** + Indicates whether the term is remainder (binary) + *) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + (** + Indicates whether the term is modulus (binary) + *) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + (** + Indicates whether the term is a coercion of integer to real (unary) + *) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + (** + Indicates whether the term is a coercion of real to integer (unary) + *) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + (** + Indicates whether the term is a check that tests whether a real is integral (unary) + *) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + (** + Indicates whether the term is of sort real. + *) + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + + (** + Indicates whether the term is an integer numeral. + *) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + (** + Indicates whether the term is a real numeral. + *) + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + (** + Indicates whether the term is an algebraic number + *) + let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + + (** Retrieve the int value. *) + let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) (precision : int) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno + + (** + Creates an integer constant. + *) + let mk_int_const ( ctx : context ) ( name : symbol ) = + ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) + + (** + Creates an integer constant. + *) + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx ((Symbol.mk_string ctx name) :> symbol) + + (** + Creates a real constant. + *) + let mk_real_const ( ctx : context ) ( name : symbol ) = + ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) + + (** + Creates a real constant. + *) + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx ((Symbol.mk_string ctx name) :> symbol) + + (** + Create an expression representing t[0] + t[1] + .... + *) + let mk_add ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_add ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing t[0] * t[1] * .... + *) + let mk_mul ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_mul ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing t[0] - t[1] - .... + *) + let mk_sub ( ctx : context ) ( t : arith_expr array ) = + (create_expr ctx (Z3native.mk_sub ctx#gno (Array.length t) (astaton t)) :> arith_expr) + + (** + Create an expression representing -t. + *) + let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = + (create_expr ctx (Z3native.mk_unary_minus ctx#gno t#gno) :> arith_expr) + + (** + Create an expression representing t1 / t2. + *) + let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + (create_expr ctx (Z3native.mk_div ctx#gno t1#gno t2#gno) :> arith_expr) + + (** + Create an expression representing t1 mod t2. + The arguments must have int type. + *) + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_mod ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 rem t2. + The arguments must have int type. + *) + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_rem ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 ^ t2. + *) + let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (create_expr ctx (Z3native.mk_power ctx#gno t1#gno t2#gno) :> arith_expr) + + (** + Create an expression representing t1 < t2 + *) + let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 <= t2 + *) + let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_le ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 > t2 + *) + let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt ctx#gno t1#gno t2#gno) + + (** + Create an expression representing t1 >= t2 + *) + let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge ctx#gno t1#gno t2#gno) + + (** + Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + *) + let mk_int2real ( ctx : context ) ( t : int_expr ) = + (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real ctx#gno t#gno) + + (** + Coerce a real to an integer. + + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + *) + let mk_real2int ( ctx : context ) ( t : real_expr ) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int ctx#gno t#gno) + + (** + Creates an expression that checks whether a real number is an integer. + *) + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int ctx#gno t#gno) + + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno +end + + +(** Functions to manipulate bit-vector expressions *) +module BitVectors = +struct + (** + Create a new bit-vector sort. + *) + let mk_sort ( ctx : context ) size = + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) (** Indicates whether the terms is of bit-vector sort. @@ -1747,300 +2662,750 @@ struct (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BADD) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ULT) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SLT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BAND) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BOR) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOT) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. + rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. + rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + + (** The size of a bit-vector sort. *) + let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno + + (** Retrieve the int value. *) + let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if lbool_of_int(r) == L_TRUE then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno (** - Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. + Creates a bit-vector constant. *) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = + ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) (** - Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + Creates a bit-vector constant. *) + let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_const ctx ((Symbol.mk_string ctx name) :> symbol) size (** - Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. + Bitwise negation. + The argument must have a bit-vector sort. *) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + let mk_not ( ctx : context ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot ctx#gno t#gno) + (** + Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. + *) + let mk_redand ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand ctx#gno t#gno) + + (** + Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. + *) + let mk_redor ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor ctx#gno t#gno) + + (** + Bitwise conjunction. + The arguments must have a bit-vector sort. + *) + let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand ctx#gno t1#gno t2#gno) + + (** + Bitwise disjunction. + The arguments must have a bit-vector sort. + *) + let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor ctx#gno t1#gno t2#gno) + + (** + Bitwise XOR. + The arguments must have a bit-vector sort. + *) + let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor ctx#gno t1#gno t2#gno) + + (** + Bitwise NAND. + The arguments must have a bit-vector sort. + *) + let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand ctx#gno t1#gno t2#gno) + + (** + Bitwise NOR. + The arguments must have a bit-vector sort. + *) + let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor ctx#gno t1#gno t2#gno) + + (** + Bitwise XNOR. + The arguments must have a bit-vector sort. + *) + let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor ctx#gno t1#gno t2#gno) + + (** + Standard two's complement unary minus. + The arguments must have a bit-vector sort. + *) + let mk_neg ( ctx : context ) ( t : bitvec_expr) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg ctx#gno t#gno) + + (** + Two's complement addition. + The arguments must have the same bit-vector sort. + *) + let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd ctx#gno t1#gno t2#gno) + + (** + Two's complement subtraction. + The arguments must have the same bit-vector sort. + *) + let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub ctx#gno t1#gno t2#gno) + + (** + Two's complement multiplication. + The arguments must have the same bit-vector sort. + *) + let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul ctx#gno t1#gno t2#gno) + + (** + Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv ctx#gno t1#gno t2#gno) + + (** + Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv ctx#gno t1#gno t2#gno) + + (** + Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem ctx#gno t1#gno t2#gno) + + (** + Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem ctx#gno t1#gno t2#gno) + + (** + Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. + *) + let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod ctx#gno t1#gno t2#gno) + + (** + Unsigned less-than + + The arguments must have the same bit-vector sort. + *) + let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult ctx#gno t1#gno t2#gno) + + (** + Two's complement signed less-than + + The arguments must have the same bit-vector sort. + *) + let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt ctx#gno t1#gno t2#gno) + + (** + Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule ctx#gno t1#gno t2#gno) + + (** + Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle ctx#gno t1#gno t2#gno) + + (** + Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge ctx#gno t1#gno t2#gno) + + (** + Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. + *) + let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge ctx#gno t1#gno t2#gno) + + (** + Unsigned greater-than. + + The arguments must have the same bit-vector sort. + *) + let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt ctx#gno t1#gno t2#gno) + + (** + Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. + *) + let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt ctx#gno t1#gno t2#gno) + + (** + Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). + *) + let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat ctx#gno t1#gno t2#gno) + + (** + Bit-vector extraction. + + Extract the bits down to from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. + The argument must have a bit-vector sort. + *) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract ctx#gno high low t#gno) + + (** + Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. + The argument must have a bit-vector sort. + *) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext ctx#gno i t#gno) + + (** + Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. + The argument must have a bit-vector sort. + *) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext ctx#gno i t#gno) + + (** + Bit-vector repetition. + + The argument must have a bit-vector sort. + *) + let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat ctx#gno i t#gno) + + (** + Shift left. + + + It is equivalent to multiplication by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl ctx#gno t1#gno t2#gno) + + (** + Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of . + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr ctx#gno t1#gno t2#gno) + + (** + Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. + *) + let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr ctx#gno t1#gno t2#gno) + + (** + Rotate Left. + + Rotate bits of \c t to the left \c i times. + The argument must have a bit-vector sort. + *) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left ctx#gno i t#gno) + + (** + Rotate Right. + + Rotate bits of \c t to the right \c i times. + The argument must have a bit-vector sort. + *) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right ctx#gno i t#gno) + + (** + Rotate Left. + + Rotate bits of to the left times. + The arguments must have the same bit-vector sort. + *) + let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left ctx#gno t1#gno t2#gno) + + (** + Rotate Right. + + + Rotate bits of to the right times. + The arguments must have the same bit-vector sort. + *) + let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right ctx#gno t1#gno t2#gno) + + (** + Create an bit bit-vector from the integer argument . + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + *) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv ctx#gno n t#gno) + + (** + Create an integer from the bit-vector argument . + + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in . + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of bit-vector sort. + *) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow ctx#gno t1#gno t2#gno) + + (** + Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow ctx#gno t#gno) + + (** + Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. + *) + let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + + (** + Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. + *) + let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) + +end + +(** Functions to manipulate Proof objects *) +module Proofs = +struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_proof_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRUE) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_proof_asserted ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_proof_goal ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -2049,18 +3414,18 @@ struct T1: p T2: (implies p q) [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). + The second antecedents may also be a proof for (iff p q). *) - let is_proof_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. The only reflexive relations that are used are equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. + That is, R is either '~', '=' or 'iff'. *) - let is_proof_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -2069,9 +3434,8 @@ struct T1: (R t s) [symmetry T1]: (R s t) T1 is the antecedent of this proof object. - *) - let is_proof_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -2081,9 +3445,8 @@ struct T1: (R t s) T2: (R s u) [trans T1 T2]: (R t u) - *) - let is_proof_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -2102,9 +3465,8 @@ struct using the antecedents, symmetry and transitivity. That is, if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. - *) - let is_proof_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -2116,9 +3478,8 @@ struct [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. - *) - let is_proof_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -2126,9 +3487,8 @@ struct Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - *) - let is_proof_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -2144,9 +3504,8 @@ struct This proof object has no antecedents. Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. - *) - let is_proof_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -2154,9 +3513,8 @@ struct Given a proof for (and l_1 ... l_n), produces a proof for l_i T1: (and l_1 ... l_n) [and-elim T1]: l_i - *) - let is_proof_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -2164,9 +3522,8 @@ struct Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) - *) - let is_proof_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -2183,9 +3540,8 @@ struct (= (+ ( x : expr ) 0) x) (= (+ ( x : expr ) 1 2) (+ 3 x)) (iff (or ( x : expr ) false) x) - *) - let is_proof_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -2199,17 +3555,15 @@ struct - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - *) - let is_proof_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - *) - let is_proof_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -2217,9 +3571,8 @@ struct A proof for (iff P Q) where Q is in prenex normal form. This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents - *) - let is_proof_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -2230,9 +3583,9 @@ struct ... (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) This proof object has no antecedents - *) - let is_proof_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_PUSH_QUANT) + + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -2242,9 +3595,9 @@ struct It is used to justify the elimination of unused variables. This proof object has no antecedents. - *) - let is_proof_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution @@ -2256,23 +3609,22 @@ struct This proof object has no antecedents. Several variables can be eliminated simultaneously. - *) - let is_proof_der ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DER) + + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) - *) - let is_proof_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. + Mark a hypothesis in a natural deduction style proof. *) - let is_proof_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -2283,9 +3635,8 @@ struct This proof object has one antecedent: a hypothetical proof for false. It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. - *) - let is_proof_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -2295,27 +3646,24 @@ struct ... T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - *) - let is_proof_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true T1: p [iff-true T1]: (iff p true) - *) - let is_proof_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false T1: (not p) [iff-false T1]: (iff p false) - *) - let is_proof_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -2326,9 +3674,8 @@ struct This proof object has no antecedents. Remark: if f is bool, then = is iff. - *) - let is_proof_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -2362,9 +3709,8 @@ struct You can recover the propositional tautologies by unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). - *) - let is_proof_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -2385,9 +3731,8 @@ struct Otherwise: [def-intro]: (= n e) - *) - let is_proof_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -2395,18 +3740,16 @@ struct [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is a proof that n is a name for F. - *) - let is_proof_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq T1: (iff p q) [iff~ T1]: (~ p q) - *) - let is_proof_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -2432,9 +3775,8 @@ struct for NNF_POS are 'implies', 'iff', 'xor', 'ite'. NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. - *) - let is_proof_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -2457,9 +3799,8 @@ struct T4: s_2 ~ r_2' [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) - *) - let is_proof_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -2469,9 +3810,8 @@ struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) - let is_proof_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -2479,9 +3819,8 @@ struct A proof for (~ P Q) where Q is in conjunctive normal form. This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) - let is_proof_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step @@ -2492,9 +3831,8 @@ struct [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) This proof object has no antecedents. - *) - let is_proof_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -2503,9 +3841,8 @@ struct T1: p T2: (~ p q) [mp~ T1 T2]: q - *) - let is_proof_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -2520,259 +3857,74 @@ struct - farkas - followed by rational coefficients. Multiply the coefficients to the inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - *) - let is_proof_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_PR_TH_LEMMA) - - (** - Indicates whether the term is of a relation sort. - *) - let is_Relation ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) - - (** - Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. - - *) - let is_relation_store ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_STORE) - - (** - Indicates whether the term is an empty relation - *) - let is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_EMPTY) - - (** - Indicates whether the term is a test for the emptiness of a relation - *) - let is_is_empty_relation ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_IS_EMPTY) - - (** - Indicates whether the term is a relational join - *) - let is_relational_join ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_JOIN) - - (** - Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. - *) - let is_relation_union ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_UNION) - - (** - Indicates whether the term is the widening of two relations - The function takes two arguments. - *) - let is_relation_widen ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_WIDEN) - - (** - Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. - *) - let is_relation_project ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_PROJECT) - - (** - Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. - - *) - let is_relation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_FILTER) - - (** - Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. - - *) - let is_relation_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_NEGATION_FILTER) - - (** - Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. - - *) - let is_relation_rename ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_RENAME) - - (** - Indicates whether the term is the complement of a relation - *) - let is_relation_complement ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_COMPLEMENT) - - (** - Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. - - *) - let is_relation_select ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_SELECT) - - (** - Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind - to perform destructive updates to the first argument. - - *) - let is_relation_clone ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_RA_CLONE) - - (** - Indicates whether the term is of an array sort. - *) - let is_finite_domain ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) - - (** - Indicates whether the term is a less than predicate over a finite domain. - *) - let is_finite_domain_lt ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FD_LT) - - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - - *) - let get_index ( x : expr ) = - if not (AST.is_var x) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value x#gnc x#gno + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** Integer Numerals *) -module IntNum = -struct - (** Retrieve the int value. *) - let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") +(** + Parameter sets (of Solvers, Tactics, ...) - (** Returns a string representation of the numeral. *) - let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Rational Numerals *) -module RatNum = -struct - - (** The numerator of a rational numeral. *) - let get_numerator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) - - (** The denominator of a rational numeral. *) - let get_denominator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : rat_num ) (precision : int) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** Returns a string representation of the numeral. *) - let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Bit-vector numerals *) -module BitVecNum = -struct - (** Retrieve the int value. *) - let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno -end - -(** Algebraic numbers *) -module AlgebraicNum = + A Params objects represents a configuration in the form of symbol/value pairs. +*) +module Params = struct (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real + Adds a parameter setting. *) - let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) - - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + let add_bool (p : params) (name : symbol) (value : bool) = + Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision + (** + Adds a parameter setting. + *) + let add_int (p : params) (name : symbol) (value : int) = + Z3native.params_set_uint p#gnc p#gno name#gno value - (** Returns a string representation of the numeral. *) - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno + (** + Adds a parameter setting. + *) + let add_double (p : params) (name : symbol) (value : float) = + Z3native.params_set_double p#gnc p#gno name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol (p : params) (name : symbol) (value : symbol) = + Z3native.params_set_symbol p#gnc p#gno name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool (p : params) (name : string) (value : bool) = + add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_int (p : params) (name : string) (value : int) = + add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_double (p : params) (name : string) (value : float) = + add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol (p : params) (name : string) (value : symbol) = + add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + + (** + A string representation of the parameter set. + *) + let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end -(** Constructors are used for datatype sorts *) -module Constructor = -struct - (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = x#get_n - - (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = x#constructor_decl - - (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = x#tester_decl - - (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = x#accessor_decls -end - - -(** ParamDescrs describe sets of parameters.*) +(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) module ParamDescrs = struct @@ -2917,102 +4069,100 @@ struct | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) - (** Creates a solver that is implemented using the given tactic. + (** creates a solver that is implemented using the given tactic. *) let get_solver ( x : tactic ) = (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) end - -(** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. -*) -module FuncInterp = -struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") -end - -(** Models. +(** Models A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) @@ -3093,7 +4243,7 @@ struct This function may fail if contains quantifiers, is partial (MODEL_PARTIAL enabled), or if is not well-sorted. In this case a ModelEvaluationFailedException is thrown. - + An expression When this flag is enabled, a model value will be assigned to any constant @@ -3120,7 +4270,6 @@ struct Z3 also provides an intepretation for uninterpreted sorts used in a formula. The interpretation for a sort is a finite set of distinct values. We say this finite set is the "universe" of the sort. - *) @@ -3137,8 +4286,8 @@ struct *) let sort_universe ( x : model ) ( s : sort ) = let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (ASTVector.get_size n_univ) in - let f i = (ASTVector.get n_univ i) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -3174,84 +4323,85 @@ struct let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno end -(** Objects that track statistical information about solvers. *) -module Statistics = -struct - - (** - Statistical data is organized into pairs of [Key, Entry], where every - Entry is either a DoubleEntry or a UIntEntry - *) - module Entry = - struct - (** The key of the entry. *) - let get_key (x : statistics_entry) = x#key - - (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x#int - - (** The float-value of the entry. *) - let get_float (x : statistics_entry) = x#float - - (** True if the entry is uint-valued. *) - let is_int (x : statistics_entry) = x#is_int - - (** True if the entry is double-valued. *) - let is_float (x : statistics_entry) = x#is_float - - (** The string representation of the the entry's value. *) - let to_string_value (x : statistics_entry) = - if (is_int x) then - string_of_int (get_int x) - else if (is_float x) then - string_of_float (get_float x) - else - raise (Z3native.Exception "Unknown statistical entry type") - - (** The string representation of the entry (key and value) *) - let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) - end - - (** A string representation of the statistical data. *) - let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno - - (** The number of statistical data. *) - let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno - - (** The data entries. *) - let get_entries ( x : statistics ) = - let n = (get_size x ) in - let f i = ( - let k = Z3native.stats_get_key x#gnc x#gno i in - if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) - else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) - ) in - Array.init n f - - (** - The statistical counters. - *) - let get_keys ( x : statistics ) = - let n = (get_size x) in - let f i = (Z3native.stats_get_key x#gnc x#gno i) in - Array.init n f - - (** - The value of a particular statistical counter. - *) - let get ( x : statistics ) ( key : string ) = - let f p c = (if (Entry.get_key c) = key then (Some c) else p) in - Array.fold_left f None (get_entries x) - -end - (** Solvers *) module Solver = struct type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + (** Objects that track statistical information about solvers. *) + module Statistics = + struct + + (** + Statistical data is organized into pairs of [Key, Entry], where every + Entry is either a DoubleEntry or a UIntEntry + *) + module Entry = + struct + (** The key of the entry. *) + let get_key (x : statistics_entry) = x#key + + (** The int-value of the entry. *) + let get_int (x : statistics_entry) = x#int + + (** The float-value of the entry. *) + let get_float (x : statistics_entry) = x#float + + (** True if the entry is uint-valued. *) + let is_int (x : statistics_entry) = x#is_int + + (** True if the entry is double-valued. *) + let is_float (x : statistics_entry) = x#is_float + + (** The string representation of the the entry's value. *) + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + + (** The string representation of the entry (key and value) *) + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + (** A string representation of the statistical data. *) + let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + + (** The number of statistical data. *) + let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + + (** The data entries. *) + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key x#gnc x#gno i in + if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + else + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ) in + Array.init n f + + (** + The statistical counters. + *) + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key x#gnc x#gno i) in + Array.init n f + + (** + The value of a particular statistical counter. + *) + let get ( x : statistics ) ( key : string ) = + let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + Array.fold_left f None (get_entries x) + + end + + (** A string that describes all available solver parameters. *) @@ -3284,14 +4434,14 @@ struct (** Backtracks backtracking points. - Note that an exception is thrown if is not smaller than NumScopes + Note that an exception is thrown if is not smaller than NumScopes *) let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n (** Resets the Solver. - This removes all assertions from the solver. + This removes all assertions from the solver. *) let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno @@ -3307,7 +4457,7 @@ struct *) let get_num_assertions ( x : solver ) = let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in - (ASTVector.get_size a) + (AST.ASTVector.get_size a) (** @@ -3315,8 +4465,8 @@ struct *) let get_assertions ( x : solver ) = let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in - let n = (ASTVector.get_size a) in - let f i = ((new bool_expr x#gc)#cnstr_obj (ASTVector.get a i)#gno) in + let n = (AST.ASTVector.get_size a) in + let f i = ((new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -3325,7 +4475,6 @@ struct - *) let check ( x : solver ) ( assumptions : bool_expr array option) = let r = @@ -3343,7 +4492,6 @@ struct The result is None if Check was not invoked before, if its results was not SATISFIABLE, or if model production is not enabled. - *) let get_model ( x : solver ) = let q = Z3native.solver_get_model x#gnc x#gno in @@ -3357,7 +4505,6 @@ struct The result is null if Check was not invoked before, if its results was not UNSATISFIABLE, or if proof production is disabled. - *) let get_proof ( x : solver ) = let q = Z3native.solver_get_proof x#gnc x#gno in @@ -3372,12 +4519,11 @@ struct The unsat core is a subset of Assertions The result is empty if Check was not invoked before, if its results was not UNSATISFIABLE, or if core production is disabled. - *) let get_unsat_core ( x : solver ) = let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in - let n = (ASTVector.get_size cn) in - let f i = (ASTVector.get cn i) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in Array.init n f (** @@ -3418,3312 +4564,936 @@ struct end -(** The main interaction with Z3 happens via the Context module *) -module Context = -struct +(* STUFF FROM THE CONTEXT *) - (* SYMBOLS *) - - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) - let mk_symbol_int ( ctx : context ) i = - (new int_symbol ctx)#cnstr_int i - - (** Creates a new symbol using a string. *) - let mk_symbol_string ( ctx : context ) s = - (new string_symbol ctx)#cnstr_string s - - (** - Create an array of symbols. - *) - let mk_symbols_int ( ctx : context ) names = - let f elem = mk_symbol_int ( ctx : context ) elem in - (Array.map f names) - - (** - Create an array of symbols. - *) - let mk_symbols_string ( ctx : context ) names = - let f elem = mk_symbol_string ( ctx : context ) elem in - (Array.map f names) - - - (* SORTS *) - - (** - Create a new Boolean sort. - *) - let mk_bool_sort ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_sort ( ctx : context ) (s : symbol) = - (new uninterpreted_sort ctx)#cnstr_s s - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_sort_s ( ctx : context ) (s : string) = - mk_uninterpreted_sort ctx ((mk_symbol_string ( ctx : context ) s) :> symbol) - - (** - Create a new integer sort. - *) - let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) - - (** - Create a real sort. - *) - let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) - - (** - Create a new bit-vector sort. - *) - let mk_bitvec_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) - - (** - Create a new array sort. - *) - let mk_array_sort ( ctx : context ) domain range = - (new array_sort ctx)#cnstr_dr domain range - - (** - Create a new tuple sort. - *) - let mk_tuple_sort ( ctx : context ) name field_names field_sorts = - (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts - - (** - Create a new enumeration sort. - *) - let mk_enum_sort ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss name enum_names - - (** - Create a new enumeration sort. - *) - let mk_enum_sort_s ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss - ((mk_symbol_string ( ctx : context ) name) :> symbol) - (let f e = (e :> symbol) in - (Array.map f (mk_symbols_string ( ctx : context ) enum_names)) - ) - - (** - Create a new list sort. - *) - let mk_list_sort ( ctx : context ) (name : symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort - - (** - Create a new list sort. - *) - let mk_list_sort_s ( ctx : context ) (name : string) elem_sort = - mk_list_sort ctx ((mk_symbol_string ctx name) :> symbol) elem_sort - - - (** - Create a new finite domain sort. - *) - let mk_finite_domain_sort ( ctx : context ) ( name : symbol ) size = - (new finite_domain_sort ctx)#cnstr_si name size - - (** - Create a new finite domain sort. - *) - let mk_finite_domain_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si ((mk_symbol_string ctx name) :> symbol) size - - (* DATATYPES *) - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs - - - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - mk_constructor ctx ((mk_symbol_string ctx name) :> symbol) recognizer field_names sorts sort_refs - - - (** - Create a new datatype sort. - *) - let mk_datatype_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = - (new datatype_sort ctx)#cnstr_sc name constructors - - (** - Create a new datatype sort. - *) - let mk_datatype_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = - mk_datatype_sort ctx ((mk_symbol_string ctx name) :> symbol) constructors - - (** - Create mutually recursive datatypes. - @param names names of datatype sorts - @param c list of constructors, one list per sort. - *) - let mk_datatype_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = - let n = (Array.length names) in - let f e = ( (new constructor_list ctx)#cnstr_ca e ) in - let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in - let g e = ( (new datatype_sort ctx)#cnstr_obj e) in - (Array.map g r) - - (** Create mutually recursive data-types. *) - let mk_datatype_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = - mk_datatype_sorts ctx - ( - let f e = ((mk_symbol_string ctx e) :> symbol) in - Array.map f names - ) - c - -(** - - -(* FUNCTION DECLARATIONS *) -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(Symbol name, Sort[] domain, Sort range) - { - - - - - - CheckContextMatch(name); - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, name, domain, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(Symbol name, Sort domain, Sort range) - { - - - - - - CheckContextMatch(name); - CheckContextMatch(domain); - CheckContextMatch(range); - Sort[] q = new Sort[] { domain }; - return new Func_Decl(this, name, q, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(string name, Sort[] domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, MkSymbol(name), domain, range); - } - -(** - Creates a new function declaration. -*) - public Func_Decl MkFunc_Decl(string name, Sort domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - Sort[] q = new Sort[] { domain }; - return new Func_Decl(this, MkSymbol(name), q, range); - } - -(** - Creates a fresh function declaration with a name prefixed with . -*) - - - let mk_Fresh_Func_Decl(string prefix, Sort[] domain, Sort range) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(range); - return new Func_Decl(this, prefix, domain, range); - } - -(** - Creates a new constant function declaration. -*) - let mk_Const_Decl(Symbol name, Sort range) - { - - - - - CheckContextMatch(name); - CheckContextMatch(range); - return new Func_Decl(this, name, null, range); - } - -(** - Creates a new constant function declaration. -*) - let mk_Const_Decl(string name, Sort range) - { - - - - CheckContextMatch(range); - return new Func_Decl(this, MkSymbol(name), null, range); - } - -(** - Creates a fresh constant function declaration with a name prefixed with . -*) - - - let mk_Fresh_ConstDecl(string prefix, Sort range) - { - - - - CheckContextMatch(range); - return new Func_Decl(this, prefix, null, range); - } - - -(* BOUND VARIABLES *) -(** - Creates a new bound variable. -*) - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - public Expr MkBound(uint index, Sort ty) - { - - - - return Expr.Create(this, Z3native.mk_bound(nCtx, index, ty.x#gno)); - } - - -(* QUANTIFIER PATTERNS *) -(** - Create a quantifier pattern. -*) - public Pattern MkPattern(params Expr[] terms) - { - - if (terms.Length == 0) - throw new Z3Exception("Cannot create a pattern from zero terms"); - - - - - - IntPtr[] termsNative = AST.ArrayToNative(terms); - return new Pattern(this, Z3native.mk_pattern(nCtx, (uint)terms.Length, termsNative)); - } - - -(* CONSTANTS *) -(** - Creates a new Constant of sort and named . -*) - public Expr MkConst(Symbol name, Sort range) - { - - - - - CheckContextMatch(name); - CheckContextMatch(range); - - return Expr.Create(this, Z3native.mk_const(nCtx, name.x#gno, range.x#gno)); - } - -(** - Creates a new Constant of sort and named . -*) - public Expr MkConst(string name, Sort range) - { - - - - return MkConst(MkSymbol(name), range); - } - -(** - Creates a fresh Constant of sort and a - name prefixed with . -*) - let mk_Fresh_Const(string prefix, Sort range) - { - - - - CheckContextMatch(range); - return Expr.Create(this, Z3native.mk_fresh_const(nCtx, prefix, range.x#gno)); - } - -(** - Creates a fresh constant from the Func_Decl . -*) - @param f A decl of a 0-arity function - public Expr MkConst(Func_Decl f) - { - - - - return MkApp(f); - } - -(** - Create a Boolean constant. -*) - let mk_Bool_Const(Symbol name) - { - - - - return (BoolExpr)MkConst(name, BoolSort); - } - -(** - Create a Boolean constant. -*) - let mk_Bool_Const(string name) - { - - - return (BoolExpr)MkConst(MkSymbol(name), BoolSort); - } - -(** - Creates an integer constant. -*) - let mk_Int_Const(Symbol name) - { - - - - return (IntExpr)MkConst(name, IntSort); - } - -(** - Creates an integer constant. -*) - let mk_Int_Const(string name) - { - - - - return (IntExpr)MkConst(name, IntSort); - } - -(** - Creates a real constant. -*) - let mk_Real_Const(Symbol name) - { - - - - return (RealExpr)MkConst(name, RealSort); - } - -(** - Creates a real constant. -*) - let mk_Real_Const(string name) - { - - - return (RealExpr)MkConst(name, RealSort); - } - -(** - Creates a bit-vector constant. -*) - let mk_B_VConst(Symbol name, uint size) - { - - - - return (BitVecExpr)MkConst(name, MkBitVecSort(size)); - } - -(** - Creates a bit-vector constant. -*) - let mk_B_VConst(string name, uint size) - { - - - return (BitVecExpr)MkConst(name, MkBitVecSort(size)); - } - - -(* TERMS *) -(** - Create a new function application. -*) - public Expr MkApp(Func_Decl f, params Expr[] args) - { - - - - - CheckContextMatch(f); - CheckContextMatch(args); - return Expr.Create(this, f, args); - } - -(* PROPOSITIONAL *) -(** - The true Term. -*) - public BoolExpr MkTrue ( ctx : context ) = - { - - - return new BoolExpr(this, Z3native.mk_true(nCtx)); - } - -(** - The false Term. -*) - public BoolExpr MkFalse ( ctx : context ) = - { - - - return new BoolExpr(this, Z3native.mk_false(nCtx)); - } - -(** - Creates a Boolean value. -*) - public BoolExpr MkBool(bool value) - { - - - return value ? MkTrue ( ctx : context ) = : MkFalse ( ctx : context ) =; - } - -(** - Creates the equality = . -*) - public BoolExpr MkEq(Expr x, Expr y) - { - - - - - CheckContextMatch(x); - CheckContextMatch(y); - return new BoolExpr(this, Z3native.mk_eq(nCtx, x.x#gno, y.x#gno)); - } - -(** - Creates a distinct term. -*) - public BoolExpr MkDistinct(params Expr[] args) - { - - - - - - CheckContextMatch(args); - return new BoolExpr(this, Z3native.mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Mk an expression representing not(a). -*) - public BoolExpr MkNot(BoolExpr a) - { - - - - CheckContextMatch(a); - return new BoolExpr(this, Z3native.mk_not(nCtx, a.x#gno)); - } - -(** - Create an expression representing an if-then-else: ite(t1, t2, t3). -*) - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - let mk_I_TE(BoolExpr t1, Expr t2, Expr t3) - { - - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - CheckContextMatch(t3); - return Expr.Create(this, Z3native.mk_ite(nCtx, t1.x#gno, t2.x#gno, t3.x#gno)); - } - -(** - Create an expression representing t1 iff t2. -*) - public BoolExpr MkIff(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_iff(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 -> t2. -*) - public BoolExpr MkImplies(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_implies(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 xor t2. -*) - public BoolExpr MkXor(BoolExpr t1, BoolExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_xor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t[0] and t[1] and .... -*) - public BoolExpr MkAnd(params BoolExpr[] t) - { - - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] or t[1] or .... -*) - public BoolExpr MkOr(params BoolExpr[] t) - { - - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - - -(* ARITHMETIC *) -(** - Create an expression representing t[0] + t[1] + .... -*) - public ArithExpr MkAdd(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] * t[1] * .... -*) - public ArithExpr MkMul(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_mul(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing t[0] - t[1] - .... -*) - public ArithExpr MkSub(params ArithExpr[] t) - { - - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); - } - -(** - Create an expression representing -t. -*) - let mk_Unary_Minus(ArithExpr t) - { - - - - CheckContextMatch(t); - return (ArithExpr)Expr.Create(this, Z3native.mk_unary_minus(nCtx, t.x#gno)); - } - -(** - Create an expression representing t1 / t2. -*) - public ArithExpr MkDiv(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return (ArithExpr)Expr.Create(this, Z3native.mk_div(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 mod t2. -*) - The arguments must have int type. - public IntExpr MkMod(IntExpr t1, IntExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new IntExpr(this, Z3native.mk_mod(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 rem t2. -*) - The arguments must have int type. - public IntExpr MkRem(IntExpr t1, IntExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new IntExpr(this, Z3native.mk_rem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 ^ t2. -*) - public ArithExpr MkPower(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return (ArithExpr)Expr.Create(this, Z3native.mk_power(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 < t2 -*) - public BoolExpr MkLt(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_lt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 <= t2 -*) - public BoolExpr MkLe(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_le(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 > t2 -*) - public BoolExpr MkGt(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_gt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an expression representing t1 >= t2 -*) - public BoolExpr MkGe(ArithExpr t1, ArithExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_ge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Coerce an integer to a real. -*) - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - - public RealExpr MkInt2Real(IntExpr t) - { - - - - CheckContextMatch(t); - return new RealExpr(this, Z3native.mk_int2real(nCtx, t.x#gno)); - } - -(** - Coerce a real to an integer. -*) - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - - public IntExpr MkReal2Int(RealExpr t) - { - - - - CheckContextMatch(t); - return new IntExpr(this, Z3native.mk_real2int(nCtx, t.x#gno)); - } - -(** - Creates an expression that checks whether a real number is an integer. -*) - let mk_Is_Integer(RealExpr t) - { - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_is_int(nCtx, t.x#gno)); - } - - -(* BIT-VECTORS *) -(** - Bitwise negation. -*) - The argument must have a bit-vector sort. - let mk_B_VNot(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvnot(nCtx, t.x#gno)); - } - -(** - Take conjunction of bits in a vector, return vector of length 1. -*) - The argument must have a bit-vector sort. - let mk_B_VRedAND(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvredand(nCtx, t.x#gno)); - } - -(** - Take disjunction of bits in a vector, return vector of length 1. -*) - The argument must have a bit-vector sort. - let mk_B_VRedOR(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvredor(nCtx, t.x#gno)); - } - -(** - Bitwise conjunction. -*) - The arguments must have a bit-vector sort. - let mk_B_VAND(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvand(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise disjunction. -*) - The arguments must have a bit-vector sort. - let mk_B_VOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise XOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VXOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvxor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise NAND. -*) - The arguments must have a bit-vector sort. - let mk_B_VNAND(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvnand(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise NOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VNOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvnor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bitwise XNOR. -*) - The arguments must have a bit-vector sort. - let mk_B_VXNOR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvxnor(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Standard two's complement unary minus. -*) - The arguments must have a bit-vector sort. - let mk_B_VNeg(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_bvneg(nCtx, t.x#gno)); - } - -(** - Two's complement addition. -*) - The arguments must have the same bit-vector sort. - let mk_B_VAdd(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvadd(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement subtraction. -*) - The arguments must have the same bit-vector sort. - let mk_B_VSub(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsub(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement multiplication. -*) - The arguments must have the same bit-vector sort. - let mk_B_VMul(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvmul(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned division. -*) - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VUDiv(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvudiv(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Signed division. -*) - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSDiv(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsdiv(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned remainder. -*) - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VURem(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvurem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Signed remainder. -*) - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSRem(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsrem(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed remainder (sign follows divisor). -*) - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - - let mk_B_VSMod(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvsmod(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned less-than -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VULT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvult(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed less-than -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSLT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvslt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned less-than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VULE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvule(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed less-than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSLE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsle(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned greater than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VUGE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvuge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed greater than or equal to. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSGE(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsge(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Unsigned greater-than. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VUGT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvugt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Two's complement signed greater-than. -*) - - The arguments must have the same bit-vector sort. - - let mk_B_VSGT(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsgt(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bit-vector concatenation. -*) - - The arguments must have a bit-vector sort. - - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). - - public BitVecExpr MkConcat(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_concat(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Bit-vector extraction. -*) - - Extract the bits down to from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. - The argument must have a bit-vector sort. - - public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_extract(nCtx, high, low, t.x#gno)); - } - -(** - Bit-vector sign extension. -*) - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. - The argument must have a bit-vector sort. - - let mk_Sign_Ext(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_sign_ext(nCtx, i, t.x#gno)); - } - -(** - Bit-vector zero extension. -*) - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. - The argument must have a bit-vector sort. - - let mk_Zero_Ext(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_zero_ext(nCtx, i, t.x#gno)); - } - -(** - Bit-vector repetition. -*) - - The argument must have a bit-vector sort. - - public BitVecExpr MkRepeat(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_repeat(nCtx, i, t.x#gno)); - } - -(** - Shift left. -*) - - It is equivalent to multiplication by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VSHL(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvshl(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Logical shift right -*) - - It is equivalent to unsigned division by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VLSHR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvlshr(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Arithmetic shift right -*) - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - - let mk_B_VASHR(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_bvashr(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Rotate Left. -*) - - Rotate bits of \c t to the left \c i times. - The argument must have a bit-vector sort. - - let mk_B_VRotateLeft(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_rotate_left(nCtx, i, t.x#gno)); - } - -(** - Rotate Right. -*) - - Rotate bits of \c t to the right \c i times. - The argument must have a bit-vector sort. - - let mk_B_VRotateRight(uint i, BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_rotate_right(nCtx, i, t.x#gno)); - } - -(** - Rotate Left. -*) - - Rotate bits of to the left times. - The arguments must have the same bit-vector sort. - - let mk_B_VRotateLeft(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_ext_rotate_left(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Rotate Right. -*) - - Rotate bits of to the right times. - The arguments must have the same bit-vector sort. - - let mk_B_VRotateRight(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BitVecExpr(this, Z3native.mk_ext_rotate_right(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create an bit bit-vector from the integer argument . -*) - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - - public BitVecExpr MkInt2BV(uint n, IntExpr t) - { - - - - CheckContextMatch(t); - return new BitVecExpr(this, Z3native.mk_int2bv(nCtx, n, t.x#gno)); - } - -(** - Create an integer from the bit-vector argument . -*) - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in . - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of bit-vector sort. - - let mk_B_V2Int(BitVecExpr t, bool signed) - { - - - - CheckContextMatch(t); - return new IntExpr(this, Z3native.mk_bv2int(nCtx, t.x#gno, (signed) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise addition does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VAddNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvadd_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise addition does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvadd_no_underflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise subtraction does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSubNoOverflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsub_no_overflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise subtraction does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsub_no_underflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise signed division does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvsdiv_no_overflow(nCtx, t1.x#gno, t2.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise negation does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VNegNoOverflow(BitVecExpr t) - { - - - - CheckContextMatch(t); - return new BoolExpr(this, Z3native.mk_bvneg_no_overflow(nCtx, t.x#gno)); - } - -(** - Create a predicate that checks that the bit-wise multiplication does not overflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VMulNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvmul_no_overflow(nCtx, t1.x#gno, t2.x#gno, (isSigned) ? 1 : 0)); - } - -(** - Create a predicate that checks that the bit-wise multiplication does not underflow. -*) - - The arguments must be of bit-vector sort. - - let mk_B_VMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) - { - - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new BoolExpr(this, Z3native.mk_bvmul_no_underflow(nCtx, t1.x#gno, t2.x#gno)); - } - - -(* ARRAYS *) -(** - Create an array constant. -*) - let mk_Array_Const(Symbol name, Sort domain, Sort range) - { - - - - - - return (ArrayExpr)MkConst(name, MkArraySort(domain, range)); - } - -(** - Create an array constant. -*) - let mk_Array_Const(string name, Sort domain, Sort range) - { - - - - - return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range)); - } - -(** - Array read. -*) - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - - - - public Expr MkSelect(ArrayExpr a, Expr i) - { - - - - - CheckContextMatch(a); - CheckContextMatch(i); - return Expr.Create(this, Z3native.mk_select(nCtx, a.x#gno, i.x#gno)); - } - -(** - Array update. -*) - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - - - - public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v) - { - - - - - - CheckContextMatch(a); - CheckContextMatch(i); - CheckContextMatch(v); - return new ArrayExpr(this, Z3native.mk_store(nCtx, a.x#gno, i.x#gno, v.x#gno)); - } - -(** - Create a constant array. -*) - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - - - - let mk_Const_Array(Sort domain, Expr v) - { - - - - - CheckContextMatch(domain); - CheckContextMatch(v); - return new ArrayExpr(this, Z3native.mk_const_array(nCtx, domain.x#gno, v.x#gno)); - } - -(** - Maps f on the argument arrays. -*) - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - - - - - public ArrayExpr MkMap(Func_Decl f, params ArrayExpr[] args) - { - - - - - CheckContextMatch(f); - CheckContextMatch(args); - return (ArrayExpr)Expr.Create(this, Z3native.mk_map(nCtx, f.x#gno, AST.ArrayLength(args), AST.ArrayToNative(args))); - } - -(** - Access the array default value. -*) - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - - let mk_Term_Array(ArrayExpr array) - { - - - - CheckContextMatch(array); - return Expr.Create(this, Z3native.mk_array_default(nCtx, array.x#gno)); - } - - -(* SETS *) -(** - Create a set type. -*) - let mk_Set_Sort(Sort ty) - { - - - - CheckContextMatch(ty); - return new SetSort(this, ty); - } - -(** - Create an empty set. -*) - let mk_Empty_Set(Sort domain) - { - - - - CheckContextMatch(domain); - return Expr.Create(this, Z3native.mk_empty_set(nCtx, domain.x#gno)); - } - -(** - Create the full set. -*) - let mk_Full_Set(Sort domain) - { - - - - CheckContextMatch(domain); - return Expr.Create(this, Z3native.mk_full_set(nCtx, domain.x#gno)); - } - -(** - Add an element to the set. -*) - let mk_Set_Add(Expr set, Expr element) - { - - - - - CheckContextMatch(set); - CheckContextMatch(element); - return Expr.Create(this, Z3native.mk_set_add(nCtx, set.x#gno, element.x#gno)); - } - - -(** - Remove an element from a set. -*) - let mk_Set_Del(Expr set, Expr element) - { - - - - - CheckContextMatch(set); - CheckContextMatch(element); - return Expr.Create(this, Z3native.mk_set_del(nCtx, set.x#gno, element.x#gno)); - } - -(** - Take the union of a list of sets. -*) - let mk_Set_Union(params Expr[] args) - { - - - - CheckContextMatch(args); - return Expr.Create(this, Z3native.mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Take the intersection of a list of sets. -*) - let mk_Set_Intersection(params Expr[] args) - { - - - - - CheckContextMatch(args); - return Expr.Create(this, Z3native.mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); - } - -(** - Take the difference between two sets. -*) - let mk_Set_Difference(Expr arg1, Expr arg2) - { - - - - - CheckContextMatch(arg1); - CheckContextMatch(arg2); - return Expr.Create(this, Z3native.mk_set_difference(nCtx, arg1.x#gno, arg2.x#gno)); - } - -(** - Take the complement of a set. -*) - let mk_Set_Complement(Expr arg) - { - - - - CheckContextMatch(arg); - return Expr.Create(this, Z3native.mk_set_complement(nCtx, arg.x#gno)); - } - -(** - Check for set membership. -*) - let mk_Set_Membership(Expr elem, Expr set) - { - - - - - CheckContextMatch(elem); - CheckContextMatch(set); - return Expr.Create(this, Z3native.mk_set_member(nCtx, elem.x#gno, set.x#gno)); - } - -(** - Check for subsetness of sets. -*) - let mk_Set_Subset(Expr arg1, Expr arg2) - { - - - - - CheckContextMatch(arg1); - CheckContextMatch(arg2); - return Expr.Create(this, Z3native.mk_set_subset(nCtx, arg1.x#gno, arg2.x#gno)); - } - +(** (* NUMERALS *) (* GENERAL NUMERALS *) (** - Create a Term of a given sort. + Create a Term of a given sort. *) - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - public Expr MkNumeral(string v, Sort ty) - { + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + public Expr MkNumeral(string v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_numeral(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_numeral ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(int v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(int v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_int(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_int ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(uint v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(uint v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_unsigned_int(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_unsigned_int ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(long v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(long v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_int64(nCtx, v, ty.x#gno)); - } + create_expr ctx (Z3native.mk_int64 ctx#gno v, ty#gno) (** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. *) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(ulong v, Sort ty) - { + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + public Expr MkNumeral(ulong v, Sort ty) - - - CheckContextMatch(ty); - return Expr.Create(this, Z3native.mk_unsigned_int64(nCtx, v, ty.x#gno)); - } - + create_expr ctx (Z3native.mk_unsigned_int64 ctx#gno v, ty#gno) (* REALS *) (** - Create a real from a fraction. + Create a real from a fraction. *) - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - public RatNum MkReal(int num, int den) - { - if (den == 0) - throw new Z3Exception("Denominator is zero"); + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + public RatNum MkReal(int num, int den) + if (den == 0) + throw new Z3Exception("Denominator is zero"); - - - return new RatNum(this, Z3native.mk_real(nCtx, num, den)); - } + new RatNum(this, Z3native.mk_real ctx#gno num, den) (** - Create a real numeral. + Create a real numeral. *) - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - public RatNum MkReal(string v) - { + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + public RatNum MkReal(string v) - - return new RatNum(this, Z3native.mk_numeral(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_numeral ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(int v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(int v) - - return new RatNum(this, Z3native.mk_int(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_int ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(uint v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(uint v) - - return new RatNum(this, Z3native.mk_unsigned_int(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_unsigned_int ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(long v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(long v) - - return new RatNum(this, Z3native.mk_int64(nCtx, v, RealSort.x#gno)); - } + new RatNum(this, Z3native.mk_int64 ctx#gno v, RealSort#gno) (** - Create a real numeral. + Create a real numeral. *) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(ulong v) - { + @param v value of the numeral. + @return A Term with value and sort Real + public RatNum MkReal(ulong v) - - return new RatNum(this, Z3native.mk_unsigned_int64(nCtx, v, RealSort.x#gno)); - } - + new RatNum(this, Z3native.mk_unsigned_int64 ctx#gno v, RealSort#gno) (* INTEGERS *) (** - Create an integer numeral. + Create an integer numeral. *) - @param v A string representing the Term value in decimal notation. - public IntNum MkInt(string v) - { + @param v A string representing the Term value in decimal notation. + public IntNum MkInt(string v) - - return new IntNum(this, Z3native.mk_numeral(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_numeral ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(int v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(int v) - - return new IntNum(this, Z3native.mk_int(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_int ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(uint v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(uint v) - - return new IntNum(this, Z3native.mk_unsigned_int(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_unsigned_int ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(long v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(long v) - - return new IntNum(this, Z3native.mk_int64(nCtx, v, IntSort.x#gno)); - } + new IntNum(this, Z3native.mk_int64 ctx#gno v, IntSort#gno) (** - Create an integer numeral. + Create an integer numeral. *) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(ulong v) - { + @param v value of the numeral. + @return A Term with value and sort Integer + public IntNum MkInt(ulong v) - - return new IntNum(this, Z3native.mk_unsigned_int64(nCtx, v, IntSort.x#gno)); - } - + new IntNum(this, Z3native.mk_unsigned_int64 ctx#gno v, IntSort#gno) (* BIT-VECTORS *) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - let mk_B_V(string v, uint size) - { + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) string v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(int v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) int v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(uint v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) uint v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(long v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) long v, uint size) - - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } + (BitVecNum)MkNumeral(v, MkBitVecSort(size) (** - Create a bit-vector numeral. + Create a bit-vector numeral. *) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_B_V(ulong v, uint size) - { + @param v value of the numeral. + @param size the size of the bit-vector + let mk_bv_ ( ctx : context ) ulong v, uint size) + (BitVecNum)MkNumeral(v, MkBitVecSort(size) - return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); - } - - - // Numerals + // Numerals (* QUANTIFIERS *) (** - Create a universal Quantifier. + Create a universal Quantifier. + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. *) - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. - - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - - - - - - return new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a universal Quantifier. + Create a universal Quantifier. *) - public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - - - - - - return new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create an existential Quantifier. + Create an existential Quantifier. *) - - public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + + public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - - - - - - - - - return new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create an existential Quantifier. + Create an existential Quantifier. *) - public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - return new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a Quantifier. + Create a Quantifier. *) - public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { - - - - - - - - - - - - if (universal) - return MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - return MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - } + public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + if (universal) + MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); (** - Create a Quantifier. + Create a Quantifier. *) - public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - { + public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) + if (universal) + MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); + else + MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - - - - - - if (universal) - return MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - } - - - - // Expr + // Expr (* OPTIONS *) (** - Selects the format used for pretty-printing expressions. + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. *) - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. - - - - - - public Z3_ast_print_mode PrintMode - { - set { Z3native.set_ast_print_mode(nCtx, (uint)value); } - } - + + + + + public Z3_ast_print_mode PrintMode + + set { Z3native.set_ast_print_mode ctx#gno (uint)value); } (* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Convert a benchmark into an SMT-LIB formatted string. *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) - { + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) - - - - return Z3native.benchmark_to_smtlib_string(nCtx, name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula.x#gno); - } + Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula#gno); (** - Parse the given string using the SMT-LIB parser. + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. - - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string(nCtx, str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); - } + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - Parse the given file using the SMT-LIB parser. + Parse the given file using the SMT-LIB parser. *) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file(nCtx, fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)); - } + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBFormulas { get { return Z3native.get_smtlib_num_formulas(nCtx)) + public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public BoolExpr[] SMTLIBFormulas - { - get - { + let[] SMTLIBFormulas + get + + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) + res; - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_formula(nCtx, i)); - return res; - } - } (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBAssumptions { get { return Z3native.get_smtlib_num_assumptions(nCtx)) + public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public BoolExpr[] SMTLIBAssumptions - { - get - { + let[] SMTLIBAssumptions + get + + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) + res; - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)Expr.Create(this, Z3native.get_smtlib_assumption(nCtx, i)); - return res; - } - } (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBDecls { get { return Z3native.get_smtlib_num_decls(nCtx)) + public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Func_Decl[] SMTLIBDecls - { - get - { + public Func_Decl[] SMTLIBDecls + get + + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) + res; - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl(nCtx, i)); - return res; - } - } (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBSorts { get { return Z3native.get_smtlib_num_sorts(nCtx)) + public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Sort[] SMTLIBSorts - { - get - { + public Sort[] SMTLIBSorts + get + + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) + res; - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort(nCtx, i)); - return res; - } - } (** - Parse the given string using the SMT-LIB2 parser. + Parse the given string using the SMT-LIB2 parser. *) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - public BoolExpr ParseSMTLIB2String(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_string(nCtx, str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); - } + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (** - Parse the given file using the SMT-LIB2 parser. + Parse the given file using the SMT-LIB2 parser. *) - - public BoolExpr ParseSMTLIB2File(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - { + + let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - return (BoolExpr)Expr.Create(this, Z3native.parse_smtlib2_file(nCtx, fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); - } - + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (* GOALS *) (** - Creates a new Goal. + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. *) - - Note that the Context must have been created with proof generation support if - is set to true here. - - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - { + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - - return new Goal(this, models, unsatCores, proofs); - } - + new Goal(this, models, unsatCores, proofs); (* PARAMETERSETS *) (** - Creates a new ParameterSet. + Creates a new ParameterSet. *) - public Params MkParams ( ctx : context ) = - { + public Params MkParams ( ctx : context ) = - - return new Params(this); - } - + new Params(this); (* TACTICS *) (** - The number of supported tactics. + The number of supported tactics. *) - public uint NumTactics - { - get { return Z3native.get_num_tactics(nCtx); } - } + public uint NumTactics + + get {Z3native.get_num_tactics ctx#gno); } (** - The names of all supported tactics. + The names of all supported tactics. *) - public string[] TacticNames - { - get - { + public string[] TacticNames + get + + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name ctx#gno i); + res; - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name(nCtx, i); - return res; - } - } (** - Returns a string containing a description of the tactic with the given name. + Returns a string containing a description of the tactic with the given name. *) - public string TacticDescription(string name) - { + public string TacticDescription(string name) - - return Z3native.tactic_get_descr(nCtx, name); - } + Z3native.tactic_get_descr ctx#gno name); (** - Creates a new Tactic. + Creates a new Tactic. *) - public Tactic MkTactic(string name) - { + public Tactic MkTactic(string name) - - return new Tactic(this, name); - } + new Tactic(this, name); (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . *) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - { + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) + last = ts[ts.Length - 1]#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); + if (last != IntPtr.Zero) + last = Z3native.tactic_and_then ctx#gno t2#gno last); + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) - - CheckContextMatch(t1); - CheckContextMatch(t2); - CheckContextMatch(ts); - - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) - { - last = ts[ts.Length - 1].x#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then(nCtx, ts[i].x#gno, last); - } - if (last != IntPtr.Zero) - { - last = Z3native.tactic_and_then(nCtx, t2.x#gno, last); - return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, last)); - } - else - return new Tactic(this, Z3native.tactic_and_then(nCtx, t1.x#gno, t2.x#gno)); - } + else + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . + + Shorthand for AndThen. *) - - Shorthand for AndThen. - - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - { + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - - - - - return AndThen(t1, t2, ts); - } + AndThen(t1, t2, ts); (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. *) - public Tactic OrElse(Tactic t1, Tactic t2) - { + public Tactic OrElse(Tactic t1, Tactic t2) - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_or_else(nCtx, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a goal for milliseconds. + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. *) - - If does not terminate within milliseconds, then it fails. - - public Tactic TryFor(Tactic t, uint ms) - { + public Tactic TryFor(Tactic t, uint ms) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_try_for(nCtx, t.x#gno, ms)); - } + new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) (** - Create a tactic that applies to a given goal if the probe - evaluates to true. + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. *) - - If evaluates to false, then the new tactic behaves like the skip tactic. - - public Tactic When(Probe p, Tactic t) - { + public Tactic When(Probe p, Tactic t) - - - - CheckContextMatch(t); - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_when(nCtx, p.x#gno, t.x#gno)); - } + new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. *) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) - { + public Tactic Cond(Probe p, Tactic t1, Tactic t2) - - - - - CheckContextMatch(p); - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_cond(nCtx, p.x#gno, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. *) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - { + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_repeat(nCtx, t.x#gno, max)); - } + new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) (** - Create a tactic that just returns the given goal. + Create a tactic that just returns the given goal. *) - public Tactic Skip ( ctx : context ) = - { + public Tactic Skip ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_skip(nCtx)); - } + new Tactic(this, Z3native.tactic_skip ctx#gno) (** - Create a tactic always fails. + Create a tactic always fails. *) - public Tactic Fail ( ctx : context ) = - { + public Tactic Fail ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_fail(nCtx)); - } + new Tactic(this, Z3native.tactic_fail ctx#gno) (** - Create a tactic that fails if the probe evaluates to false. + Create a tactic that fails if the probe evaluates to false. *) - public Tactic FailIf(Probe p) - { + public Tactic FailIf(Probe p) - - - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_fail_if(nCtx, p.x#gno)); - } + new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) - public Tactic FailIfNotDecided ( ctx : context ) = - { + public Tactic FailIfNotDecided ( ctx : context ) = - - return new Tactic(this, Z3native.tactic_fail_if_not_decided(nCtx)); - } + new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) (** - Create a tactic that applies using the given set of parameters . + Create a tactic that applies using the given set of parameters . *) - public Tactic UsingParams(Tactic t, Params p) - { + public Tactic UsingParams(Tactic t, Params p) - - - - CheckContextMatch(t); - CheckContextMatch(p); - return new Tactic(this, Z3native.tactic_using_params(nCtx, t.x#gno, p.x#gno)); - } + new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) (** - Create a tactic that applies using the given set of parameters . -*) - Alias for UsingParams - public Tactic With(Tactic t, Params p) - { + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + public Tactic With(Tactic t, Params p) - - - - return UsingParams(t, p); - } + UsingParams(t, p); (** - Create a tactic that applies the given tactics in parallel. + Create a tactic that applies the given tactics in parallel. *) - public Tactic ParOr(params Tactic[] t) - { + public Tactic ParOr(params Tactic[] t) - - - CheckContextMatch(t); - return new Tactic(this, Z3native.tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); - } + new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. *) - public Tactic ParAndThen(Tactic t1, Tactic t2) - { + public Tactic ParAndThen(Tactic t1, Tactic t2) - - - - CheckContextMatch(t1); - CheckContextMatch(t2); - return new Tactic(this, Z3native.tactic_par_and_then(nCtx, t1.x#gno, t2.x#gno)); - } + new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) (** - Interrupt the execution of a Z3 procedure. + Interrupt the execution of a Z3 procedure. *) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = - { - Z3native.interrupt(nCtx); - } - + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = + + Z3native.interrupt ctx#gno); (* PROBES *) (** - The number of supported Probes. + The number of supported Probes. *) - public uint NumProbes - { - get { return Z3native.get_num_probes(nCtx); } - } + public uint NumProbes + + get {Z3native.get_num_probes ctx#gno); } (** - The names of all supported Probes. + The names of all supported Probes. *) - public string[] ProbeNames - { - get - { + public string[] ProbeNames + get + + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name ctx#gno i); + res; - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name(nCtx, i); - return res; - } - } (** - Returns a string containing a description of the probe with the given name. + Returns a string containing a description of the probe with the given name. *) - public string ProbeDescription(string name) - { + public string ProbeDescription(string name) - - return Z3native.probe_get_descr(nCtx, name); - } + Z3native.probe_get_descr ctx#gno name); (** - Creates a new Probe. + Creates a new Probe. *) - public Probe MkProbe(string name) - { + public Probe MkProbe(string name) - - return new Probe(this, name); - } + new Probe(this, name); (** - Create a probe that always evaluates to . + Create a probe that always evaluates to . *) - public Probe Const(double val) - { + public Probe Const(double val) - - return new Probe(this, Z3native.probe_const(nCtx, val)); - } + new Probe(this, Z3native.probe_const ctx#gno val) (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - public Probe Lt(Probe p1, Probe p2) - { + public Probe Lt(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_lt(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by *) - public Probe Gt(Probe p1, Probe p2) - { + public Probe Gt(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_gt(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by *) - public Probe Le(Probe p1, Probe p2) - { + public Probe Le(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_le(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by *) - public Probe Ge(Probe p1, Probe p2) - { + public Probe Ge(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_ge(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by *) - public Probe Eq(Probe p1, Probe p2) - { + public Probe Eq(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_eq(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". + Create a probe that evaluates to "true" when the value + and evaluate to "true". *) - public Probe And(Probe p1, Probe p2) - { + public Probe And(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_and(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". + Create a probe that evaluates to "true" when the value + or evaluate to "true". *) - public Probe Or(Probe p1, Probe p2) - { + public Probe Or(Probe p1, Probe p2) - - - - CheckContextMatch(p1); - CheckContextMatch(p2); - return new Probe(this, Z3native.probe_or(nCtx, p1.x#gno, p2.x#gno)); - } + new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". + Create a probe that evaluates to "true" when the value + does not evaluate to "true". *) - public Probe Not(Probe p) - { + public Probe Not(Probe p) - - - CheckContextMatch(p); - return new Probe(this, Z3native.probe_not(nCtx, p.x#gno)); - } - + new Probe(this, Z3native.probe_not ctx#gno p#gno) (* SOLVERS *) (** - Creates a new (incremental) solver. -*) - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. - - public Solver MkSolver(Symbol logic = null) - { + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. +*) + public Solver MkSolver(Symbol logic = null) - - if (logic == null) - return new Solver(this, Z3native.mk_solver(nCtx)); - else - return new Solver(this, Z3native.mk_solver_for_logic(nCtx, logic.x#gno)); - } + if (logic == null) + new Solver(this, Z3native.mk_solver ctx#gno) + else + new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - - public Solver MkSolver(string logic) - { + + public Solver MkSolver(string logic) - - return MkSolver(MkSymbol(logic)); - } + MkSolver(MkSymbol(logic) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - let mk_Simple_Solver ( ctx : context ) = - { + let mk_Simple_Solver ( ctx : context ) ctx : context ) = - - return new Solver(this, Z3native.mk_simple_solver(nCtx)); - } + new Solver(this, Z3native.mk_simple_solver ctx#gno) (** - Creates a solver that is implemented using the given tactic. + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. - - public Solver MkSolver(Tactic t) - { + public Solver MkSolver(Tactic t) - - - return new Solver(this, Z3native.mk_solver_from_tactic(nCtx, t.x#gno)); - } - + new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) (* FIXEDPOINTS *) (** - Create a Fixedpoint context. + Create a Fixedpoint context. *) - public Fixedpoint MkFixedpoint ( ctx : context ) = - { - - - return new Fixedpoint(this); - } - + public Fixedpoint MkFixedpoint ( ctx : context ) = + new Fixedpoint(this); (* MISCELLANEOUS *) (** - Wraps an AST. + Wraps an AST. *) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) - { + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) - return AST.Create(this, nativeObject); - } + AST.Create(this, nativeObject); (** - Unwraps an AST. + Unwraps an AST. *) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) - { - return a.x#gno; - } + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) + + a#gno; (** - Return a string describing all available parameters to Expr.Simplify. + a string describing all available parameters to Expr.Simplify. *) - public string SimplifyHelp ( ctx : context ) = - { + public string SimplifyHelp ( ctx : context ) = - - return Z3native.simplify_get_help(nCtx); - } + Z3native.simplify_get_help ctx#gno); (** - Retrieves parameter descriptions for simplifier. + Retrieves parameter descriptions for simplifier. *) - public ParamDescrs SimplifyParameterDescriptions - { - get { return new ParamDescrs(this, Z3native.simplify_get_param_descrs(nCtx)); } - } + public ParamDescrs SimplifyParameterDescriptions + + get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } (** - Enable/disable printing of warning messages to the console. + Enable/disable printing of warning messages to the console. *) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) - { - Z3native.toggle_warning_messages((enabled) ? 1 : 0); - } - + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) + + Z3native.toggle_warning_messages((enabled) ? 1 : 0); (* ERROR HANDLING *) - //(** - //A delegate which is executed when an error is raised. - //*) - // - //Note that it is possible for memory leaks to occur if error handlers - //throw exceptions. - // - //public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); +(** + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. +*) + public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); - //(** - //The OnError event. - //*) - //public event ErrorHandler OnError = null; - +(** + The OnError event. +*) + public event ErrorHandler OnError = null; (* PARAMETERS *) (** - Update a mutable configuration parameter. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - - - public void UpdateParamValue(string id, string value) - { - Z3native.update_param_value(nCtx, id, value); - } + + public void UpdateParamValue(string id, string value) + + Z3native.update_param_value ctx#gno id, value); (** - Get a configuration parameter. + Get a configuration parameter. + + Returns null if the parameter value does not exist. + *) - - Returns null if the parameter value does not exist. - - - public string GetParamValue(string id) - { - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value(nCtx, id, out res); - if (r == (int)Z3_lbool.Z3_L_FALSE) - return null; - else - return Marshal.PtrToStringAnsi(res); - } + public string GetParamValue(string id) - + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value ctx#gno id, out res); + if (r == (int)Z3_lbool.L_FALSE) + null; + else + Marshal.PtrToStringAnsi(res); (* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get { return m_ctx) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get {m_ctx) - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) - { - // Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - } + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + + internal void InitContext ( ctx : context ) = + + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); - internal void InitContext ( ctx : context ) = - { - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); // keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); - } *) -end + From 49a4e77a6df433ea91cc23bfc77063335459841e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 23 Dec 2012 04:00:34 +0000 Subject: [PATCH 392/646] More new ML API. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 +- scripts/update_api.py | 13 +- src/api/ml/z3.ml | 1644 ++++++++++++++++++------------------- 3 files changed, 807 insertions(+), 858 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index f414e9d1a..dde9f944a 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,7 +4,7 @@ *) open Z3 -open Z3.Context +open Z3.Arithmetic exception ExampleException of string @@ -16,9 +16,9 @@ let _ = Printf.printf "Running Z3 version %s\n" Version.to_string ; let cfg = [("model", "true"); ("proof", "false")] in let ctx = (new context cfg) in - let is = (mk_symbol_int ctx 42) in - let ss = (mk_symbol_string ctx "mySymbol") in - let bs = (mk_bool_sort ctx) in + let is = (Symbol.mk_int ctx 42) in + let ss = (Symbol.mk_string ctx "mySymbol") in + let bs = (Sort.mk_bool ctx) in let ints = (mk_int_sort ctx) in let rs = (mk_real_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); diff --git a/scripts/update_api.py b/scripts/update_api.py index 27f7dd507..acaa9478e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1154,8 +1154,11 @@ def mk_ml(): for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) - ml_native.write('\nexternal is_null : ptr -> bool\n') + ml_native.write('\n') + ml_native.write('external is_null : ptr -> bool\n') ml_native.write(' = "n_is_null"\n\n') + ml_native.write('external mk_null : unit -> ptr\n') + ml_native.write(' = "n_mk_null"\n\n') ml_native.write('exception Exception of string\n\n') # ML declarations @@ -1295,6 +1298,14 @@ def mk_ml(): ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') ml_wrapper.write('}\n\n') + ml_wrapper.write('CAMLprim value n_mk_null( void ) {\n') + ml_wrapper.write(' CAMLparam0();\n') + ml_wrapper.write(' CAMLlocal1(result);\n') + ml_wrapper.write(' void * z3_result = 0;\n') + ml_wrapper.write(' result = caml_alloc_custom(&default_custom_ops, sizeof(void*), 0, 1);\n') + ml_wrapper.write(' memcpy( Data_custom_val(result), &z3_result, sizeof(void*));\n') + ml_wrapper.write(' CAMLreturn (result);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 5f67e11e2..f6454b797 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -593,6 +593,10 @@ object (self) method cnstr_obj obj = (self#sno ctx obj) ; self end +let patternaton (a : pattern array) = + let f (e : pattern) = e#gno in + Array.map f a + (** Parameter description objects *) class param_descrs ctx = object (self) @@ -1607,6 +1611,306 @@ struct *) let mk_or ( ctx : context ) ( args : bool_expr array ) = (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) + + (** + Create a numeral of a given sort. + @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. + @return A Term with value and sort + *) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + create_expr ctx (Z3native.mk_numeral ctx#gno v ty#gno) + + (** + Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @param v Value of the numeral + @param ty Sort of the numeral + @return A Term with value and type + *) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_int ctx#gno v ty#gno) +end + +(** Quantifier expressions *) +module Quantifiers = +struct + (** + The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. + *) + let get_index ( x : expr ) = + if not (AST.is_var x) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value x#gnc x#gno + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Pattern = + struct + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms x#gnc x#gno + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + end + + (** + Indicates whether the quantifier is universal. + *) + let is_universal ( x : quantifier ) = + lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + + (** + Indicates whether the quantifier is existential. + *) + let is_existential ( x : quantifier ) = not (is_universal x) + + (** + The weight of the quantifier. + *) + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + + (** + The number of patterns. + *) + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + + (** + The patterns. + *) + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of no-patterns. + *) + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + + (** + The no-patterns. + *) + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + Array.init n f + + (** + The number of bound variables. + *) + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + + (** + The symbols for the bound variables. + *) + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + Array.init n f + + (** + The sorts of the bound variables. + *) + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + Array.init n f + + (** + The body of the quantifier. + *) + let get_body ( x : quantifier ) = + (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + + (** + Creates a new bound variable. + @param index The de-Bruijn index of the variable + @param ty The sort of the variable + *) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + + (** + Create a quantifier pattern. + *) + let mk_pattern ( ctx : context ) ( terms : expr array ) = + if (Array.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) + + (** + Create a universal Quantifier. + + Creates a forall formula, where is the weight, + is an array of patterns, is an array + with the sorts of the bound variables, is an array with the + 'names' of the bound variables, and is the body of the + quantifier. Quantifiers are associated with weights indicating + the importance of using the quantifier during instantiation. + + @param sorts the sorts of the bound variables. + @param names names of the bound variables + @param body the body of the quantifier. + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + @param patterns array containing the patterns created using MkPattern. + @param noPatterns array containing the anti-patterns created using MkPattern. + @param quantifierID optional symbol to track quantifier. + @param skolemID optional symbol to track skolem constants. + *) + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (Array.length sorts) != (Array.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + + (** + Create a universal Quantifier. + *) + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_TRUE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + (** + Create an existential Quantifier. + + *) + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (Array.length sorts) != (Array.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length sorts) (astaton sorts) + (astaton names) + body#gno) + + (** + Create an existential Quantifier. + *) + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (nopatterns == None && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + else + let null = Z3native.mk_null() in + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_FALSE) + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> x#gno) + (match skolem_id with | None -> null | Some(x) -> x#gno) + (Array.length bound_constants) (expraton bound_constants) + (match patterns with | None -> 0 | Some(x) -> (Array.length x)) + (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) + (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + body#gno) + + (** + Create a Quantifier. + *) + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (universal) then + (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + else + (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + + + (** + Create a Quantifier. + *) + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if (universal) then + mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + else + mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id end (** Functions to manipulate Array expressions *) @@ -1777,71 +2081,71 @@ struct *) let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) -(** - Create a set type. -*) -let mk_sort ( ctx : context ) ( ty : sort) = - (new set_sort ctx)#cnstr_s ty + (** + Create a set type. + *) + let mk_sort ( ctx : context ) ( ty : sort) = + (new set_sort ctx)#cnstr_s ty -(** - Create an empty set. -*) -let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) - - (** - Create the full set. - *) -let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + (** + Create an empty set. + *) + let mk_empty ( ctx : context ) ( domain : sort ) = + (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + + (** + Create the full set. + *) + let mk_full ( ctx : context ) ( domain : sort ) = + create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) -(** - Add an element to the set. -*) -let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) - - (** - Remove an element from a set. - *) -let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) - - (** - Take the union of a list of sets. - *) -let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) - -(** - Take the intersection of a list of sets. -*) -let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + (** + Add an element to the set. + *) + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + + (** + Remove an element from a set. + *) + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + + (** + Take the union of a list of sets. + *) + let mk_union ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + + (** + Take the intersection of a list of sets. + *) + let mk_intersection ( ctx : context ) ( args : expr array ) = + create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) -(** - Take the difference between two sets. -*) -let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + (** + Take the difference between two sets. + *) + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) -(** - Take the complement of a set. -*) -let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + (** + Take the complement of a set. + *) + let mk_complement ( ctx : context ) ( arg : expr ) = + create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) -(** - Check for set membership. -*) -let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + (** + Check for set membership. + *) + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) - (** - Check for subsetness of sets. - *) -let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + (** + Check for subsetness of sets. + *) + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = + create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) end @@ -2001,148 +2305,6 @@ struct Array.init n f end - -(** Quantifier expressions *) -module Quantifiers = -struct - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - *) - let get_index ( x : expr ) = - if not (AST.is_var x) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value x#gnc x#gno - - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) - module Pattern = - struct - (** - The number of terms in the pattern. - *) - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms x#gnc x#gno - - (** - The terms in the pattern. - *) - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the pattern. - *) - let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno - end - - (** - Indicates whether the quantifier is universal. - *) - let is_universal ( x : quantifier ) = - lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE - - (** - Indicates whether the quantifier is existential. - *) - let is_existential ( x : quantifier ) = not (is_universal x) - - (** - The weight of the quantifier. - *) - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno - - (** - The number of patterns. - *) - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno - - (** - The patterns. - *) - let get_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in - Array.init n f - - (** - The number of no-patterns. - *) - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno - - (** - The no-patterns. - *) - let get_no_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in - Array.init n f - - (** - The number of bound variables. - *) - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno - - (** - The symbols for the bound variables. - *) - let get_bound_variable_names ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in - Array.init n f - - (** - The sorts of the bound variables. - *) - let get_bound_variable_sorts ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in - Array.init n f - - (** - The body of the quantifier. - *) - let get_body ( x : quantifier ) = - (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) - - (** - Creates a new bound variable. - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) - - (** - Create a quantifier pattern. - *) - let mk_pattern ( ctx : context ) ( terms : expr array ) = - if (Array.length terms) == 0 then - raise (Z3native.Exception "Cannot create a pattern from zero terms") - else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) -end (** Functions to manipulate Datatype expressions *) module Datatypes = @@ -2638,7 +2800,54 @@ struct The result has at most decimal places.*) let to_decimal_string ( x : algebraic_num ) ( precision : int ) = Z3native.get_numeral_decimal_string x#gnc x#gno precision + + (** + Create a real from a fraction. + + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + *) + let mk_real_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + (new rat_num ctx)#cnstr_obj (Z3native.mk_real ctx#gno num den) + + (** + Create a real numeral. + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + *) + let mk_real_numeral_s ( ctx : context ) ( v : string ) = + (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_real_sort ctx)#gno) + + (** + Create a real numeral. + + @param v value of the numeral. + @return A Term with value and sort Real + *) + let mk_real_numeral_i ( ctx : context ) ( v : int ) = + (new rat_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_real_sort ctx)#gno) + + (** + Create an integer numeral. + @param v A string representing the Term value in decimal notation. + *) + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + (new int_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_int_sort ctx)#gno) + + (** + Create an integer numeral. + @param v value of the numeral. + @return A Term with value and sort Integer + *) + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + (new int_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_int_sort ctx)#gno) + (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno end @@ -3386,10 +3595,18 @@ struct *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) - + + (** + Create a bit-vector numeral. + + @param v A string representing the value in decimal notation. + @param size the size of the bit-vector + *) + let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = + (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_sort ctx size)#gno) end -(** Functions to manipulate Proof objects *) +(** Functions to manipulate proof expressions *) module Proofs = struct (** @@ -4567,933 +4784,654 @@ end (* STUFF FROM THE CONTEXT *) (** - -(* NUMERALS *) - -(* GENERAL NUMERALS *) -(** - Create a Term of a given sort. -*) - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - public Expr MkNumeral(string v, Sort ty) - - create_expr ctx (Z3native.mk_numeral ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(int v, Sort ty) - - create_expr ctx (Z3native.mk_int ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(uint v, Sort ty) - - create_expr ctx (Z3native.mk_unsigned_int ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(long v, Sort ty) - - create_expr ctx (Z3native.mk_int64 ctx#gno v, ty#gno) - -(** - Create a Term of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. -*) - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - public Expr MkNumeral(ulong v, Sort ty) - - create_expr ctx (Z3native.mk_unsigned_int64 ctx#gno v, ty#gno) - -(* REALS *) -(** - Create a real from a fraction. -*) - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - public RatNum MkReal(int num, int den) - - if (den == 0) - throw new Z3Exception("Denominator is zero"); - - new RatNum(this, Z3native.mk_real ctx#gno num, den) - -(** - Create a real numeral. -*) - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - public RatNum MkReal(string v) - - new RatNum(this, Z3native.mk_numeral ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(int v) - - new RatNum(this, Z3native.mk_int ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(uint v) - - new RatNum(this, Z3native.mk_unsigned_int ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(long v) - - new RatNum(this, Z3native.mk_int64 ctx#gno v, RealSort#gno) - -(** - Create a real numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Real - public RatNum MkReal(ulong v) - - new RatNum(this, Z3native.mk_unsigned_int64 ctx#gno v, RealSort#gno) - -(* INTEGERS *) -(** - Create an integer numeral. -*) - @param v A string representing the Term value in decimal notation. - public IntNum MkInt(string v) - - new IntNum(this, Z3native.mk_numeral ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(int v) - - new IntNum(this, Z3native.mk_int ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(uint v) - - new IntNum(this, Z3native.mk_unsigned_int ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(long v) - - new IntNum(this, Z3native.mk_int64 ctx#gno v, IntSort#gno) - -(** - Create an integer numeral. -*) - @param v value of the numeral. - @return A Term with value and sort Integer - public IntNum MkInt(ulong v) - - new IntNum(this, Z3native.mk_unsigned_int64 ctx#gno v, IntSort#gno) - -(* BIT-VECTORS *) -(** - Create a bit-vector numeral. -*) - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) string v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) int v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) uint v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) long v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - -(** - Create a bit-vector numeral. -*) - @param v value of the numeral. - @param size the size of the bit-vector - let mk_bv_ ( ctx : context ) ulong v, uint size) - - (BitVecNum)MkNumeral(v, MkBitVecSort(size) - - // Numerals - -(* QUANTIFIERS *) -(** - Create a universal Quantifier. - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. -*) - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a universal Quantifier. -*) - public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create an existential Quantifier. -*) - - public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create an existential Quantifier. -*) - public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a Quantifier. -*) - public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - if (universal) - MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); - -(** - Create a Quantifier. -*) - public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) - - if (universal) - MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - else - MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); - - // Expr - (* OPTIONS *) (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the Z3_PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. *) - - - - - public Z3_ast_print_mode PrintMode + + + + + public Z3_ast_print_mode PrintMode - set { Z3native.set_ast_print_mode ctx#gno (uint)value); } + set { Z3native.set_ast_print_mode ctx#gno (uint)value); } (* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Convert a benchmark into an SMT-LIB formatted string. *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + public string BenchmarkToSMTString(string name, string logic, string status, string attributes, + BoolExpr[] assumptions, BoolExpr formula) - Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula#gno); + Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, + (uint)assumptions.Length, AST.ArrayToNative(assumptions), + formula#gno); (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - Parse the given file using the SMT-LIB parser. + Parse the given file using the SMT-LIB parser. *) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + Z3native.parse_smtlib_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) + public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let[] SMTLIBFormulas + let[] SMTLIBFormulas - get + get - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) - res; + uint n = NumSMTLIBFormulas; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) + res; (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) + public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let[] SMTLIBAssumptions + let[] SMTLIBAssumptions - get + get - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) - res; + uint n = NumSMTLIBAssumptions; + BoolExpr[] res = new BoolExpr[n]; + for (uint i = 0; i < n; i++) + res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) + res; (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) + public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Func_Decl[] SMTLIBDecls + public Func_Decl[] SMTLIBDecls - get + get - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) - res; + uint n = NumSMTLIBDecls; + Func_Decl[] res = new Func_Decl[n]; + for (uint i = 0; i < n; i++) + res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) + res; (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) + public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - public Sort[] SMTLIBSorts + public Sort[] SMTLIBSorts - get + get - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) - res; + uint n = NumSMTLIBSorts; + Sort[] res = new Sort[n]; + for (uint i = 0; i < n; i++) + res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) + res; (** - Parse the given string using the SMT-LIB2 parser. + Parse the given string using the SMT-LIB2 parser. *) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (** - Parse the given file using the SMT-LIB2 parser. + Parse the given file using the SMT-LIB2 parser. *) - - let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + + let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) + uint csn = Symbol.ArrayLength(sortNames); + uint cs = Sort.ArrayLength(sorts); + uint cdn = Symbol.ArrayLength(declNames); + uint cd = AST.ArrayLength(decls); + if (csn != cs || cdn != cd) + throw new Z3Exception("Argument size mismatch"); + (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, + AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), + AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) (* GOALS *) (** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. *) - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) + @param models Indicates whether model generation should be enabled. + @param unsatCores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - new Goal(this, models, unsatCores, proofs); + new Goal(this, models, unsatCores, proofs); (* PARAMETERSETS *) (** - Creates a new ParameterSet. + Creates a new ParameterSet. *) - public Params MkParams ( ctx : context ) = + public Params MkParams ( ctx : context ) = - new Params(this); + new Params(this); (* TACTICS *) (** - The number of supported tactics. + The number of supported tactics. *) - public uint NumTactics + public uint NumTactics - get {Z3native.get_num_tactics ctx#gno); } + get {Z3native.get_num_tactics ctx#gno); } (** - The names of all supported tactics. + The names of all supported tactics. *) - public string[] TacticNames + public string[] TacticNames - get + get - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name ctx#gno i); - res; + uint n = NumTactics; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_tactic_name ctx#gno i); + res; (** - Returns a string containing a description of the tactic with the given name. + Returns a string containing a description of the tactic with the given name. *) - public string TacticDescription(string name) + public string TacticDescription(string name) - Z3native.tactic_get_descr ctx#gno name); + Z3native.tactic_get_descr ctx#gno name); (** - Creates a new Tactic. + Creates a new Tactic. *) - public Tactic MkTactic(string name) + public Tactic MkTactic(string name) - new Tactic(this, name); + new Tactic(this, name); (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . + Create a tactic that applies to a Goal and + then to every subgoal produced by . *) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) + public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) + IntPtr last = IntPtr.Zero; + if (ts != null && ts.Length > 0) - last = ts[ts.Length - 1]#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); + last = ts[ts.Length - 1]#gno; + for (int i = ts.Length - 2; i >= 0; i--) + last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); - if (last != IntPtr.Zero) + if (last != IntPtr.Zero) - last = Z3native.tactic_and_then ctx#gno t2#gno last); - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) + last = Z3native.tactic_and_then ctx#gno t2#gno last); + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) - else - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + else + new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - - Shorthand for AndThen. + Create a tactic that applies to a Goal and + then to every subgoal produced by . + + Shorthand for AndThen. *) - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) + public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - AndThen(t1, t2, ts); + AndThen(t1, t2, ts); (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. *) - public Tactic OrElse(Tactic t1, Tactic t2) + public Tactic OrElse(Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) (** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. *) - public Tactic TryFor(Tactic t, uint ms) + public Tactic TryFor(Tactic t, uint ms) - new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) + new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) (** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. *) - public Tactic When(Probe p, Tactic t) + public Tactic When(Probe p, Tactic t) - new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) + new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. *) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) + public Tactic Cond(Probe p, Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. *) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) + public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) + new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) (** - Create a tactic that just returns the given goal. + Create a tactic that just returns the given goal. *) - public Tactic Skip ( ctx : context ) = + public Tactic Skip ( ctx : context ) = - new Tactic(this, Z3native.tactic_skip ctx#gno) + new Tactic(this, Z3native.tactic_skip ctx#gno) (** - Create a tactic always fails. + Create a tactic always fails. *) - public Tactic Fail ( ctx : context ) = + public Tactic Fail ( ctx : context ) = - new Tactic(this, Z3native.tactic_fail ctx#gno) + new Tactic(this, Z3native.tactic_fail ctx#gno) (** - Create a tactic that fails if the probe evaluates to false. + Create a tactic that fails if the probe evaluates to false. *) - public Tactic FailIf(Probe p) + public Tactic FailIf(Probe p) - new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) + new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) - public Tactic FailIfNotDecided ( ctx : context ) = + public Tactic FailIfNotDecided ( ctx : context ) = - new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) + new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) (** - Create a tactic that applies using the given set of parameters . + Create a tactic that applies using the given set of parameters . *) - public Tactic UsingParams(Tactic t, Params p) + public Tactic UsingParams(Tactic t, Params p) - new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) + new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) (** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - public Tactic With(Tactic t, Params p) + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + public Tactic With(Tactic t, Params p) - UsingParams(t, p); + UsingParams(t, p); (** - Create a tactic that applies the given tactics in parallel. + Create a tactic that applies the given tactics in parallel. *) - public Tactic ParOr(params Tactic[] t) + public Tactic ParOr(params Tactic[] t) - new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) + new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. *) - public Tactic ParAndThen(Tactic t1, Tactic t2) + public Tactic ParAndThen(Tactic t1, Tactic t2) - new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) (** - Interrupt the execution of a Z3 procedure. + Interrupt the execution of a Z3 procedure. *) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = + This procedure can be used to interrupt: solvers, simplifiers and tactics. + public void Interrupt ( ctx : context ) = - Z3native.interrupt ctx#gno); + Z3native.interrupt ctx#gno); (* PROBES *) (** - The number of supported Probes. + The number of supported Probes. *) - public uint NumProbes + public uint NumProbes - get {Z3native.get_num_probes ctx#gno); } + get {Z3native.get_num_probes ctx#gno); } (** - The names of all supported Probes. + The names of all supported Probes. *) - public string[] ProbeNames + public string[] ProbeNames - get + get - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name ctx#gno i); - res; + uint n = NumProbes; + string[] res = new string[n]; + for (uint i = 0; i < n; i++) + res[i] = Z3native.get_probe_name ctx#gno i); + res; (** - Returns a string containing a description of the probe with the given name. + Returns a string containing a description of the probe with the given name. *) - public string ProbeDescription(string name) + public string ProbeDescription(string name) - Z3native.probe_get_descr ctx#gno name); + Z3native.probe_get_descr ctx#gno name); (** - Creates a new Probe. + Creates a new Probe. *) - public Probe MkProbe(string name) + public Probe MkProbe(string name) - new Probe(this, name); + new Probe(this, name); (** - Create a probe that always evaluates to . + Create a probe that always evaluates to . *) - public Probe Const(double val) + public Probe Const(double val) - new Probe(this, Z3native.probe_const ctx#gno val) + new Probe(this, Z3native.probe_const ctx#gno val) (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - public Probe Lt(Probe p1, Probe p2) + public Probe Lt(Probe p1, Probe p2) - new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by *) - public Probe Gt(Probe p1, Probe p2) + public Probe Gt(Probe p1, Probe p2) - new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by *) - public Probe Le(Probe p1, Probe p2) + public Probe Le(Probe p1, Probe p2) - new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by *) - public Probe Ge(Probe p1, Probe p2) + public Probe Ge(Probe p1, Probe p2) - new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by *) - public Probe Eq(Probe p1, Probe p2) + public Probe Eq(Probe p1, Probe p2) - new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". + Create a probe that evaluates to "true" when the value + and evaluate to "true". *) - public Probe And(Probe p1, Probe p2) + public Probe And(Probe p1, Probe p2) - new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". + Create a probe that evaluates to "true" when the value + or evaluate to "true". *) - public Probe Or(Probe p1, Probe p2) + public Probe Or(Probe p1, Probe p2) - new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) + new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". + Create a probe that evaluates to "true" when the value + does not evaluate to "true". *) - public Probe Not(Probe p) + public Probe Not(Probe p) - new Probe(this, Z3native.probe_not ctx#gno p#gno) + new Probe(this, Z3native.probe_not ctx#gno p#gno) (* SOLVERS *) (** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) - public Solver MkSolver(Symbol logic = null) + public Solver MkSolver(Symbol logic = null) - if (logic == null) - new Solver(this, Z3native.mk_solver ctx#gno) - else - new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) + if (logic == null) + new Solver(this, Z3native.mk_solver ctx#gno) + else + new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - - public Solver MkSolver(string logic) + + public Solver MkSolver(string logic) - MkSolver(MkSymbol(logic) + MkSolver(MkSymbol(logic) (** - Creates a new (incremental) solver. + Creates a new (incremental) solver. *) - let mk_Simple_Solver ( ctx : context ) ctx : context ) = + let mk_Simple_Solver( ctx : context ) ctx : context ) = - new Solver(this, Z3native.mk_simple_solver ctx#gno) + new Solver(this, Z3native.mk_simple_solver ctx#gno) (** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) - public Solver MkSolver(Tactic t) + public Solver MkSolver(Tactic t) - new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) + new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) (* FIXEDPOINTS *) (** - Create a Fixedpoint context. + Create a Fixedpoint context. *) - public Fixedpoint MkFixedpoint ( ctx : context ) = + public Fixedpoint MkFixedpoint ( ctx : context ) = - new Fixedpoint(this); + new Fixedpoint(this); (* MISCELLANEOUS *) (** - Wraps an AST. + Wraps an AST. *) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + public AST WrapAST(IntPtr nativeObject) - AST.Create(this, nativeObject); + AST.Create(this, nativeObject); (** - Unwraps an AST. + Unwraps an AST. *) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + public IntPtr UnwrapAST(AST a) - a#gno; + a#gno; (** - a string describing all available parameters to Expr.Simplify. + a string describing all available parameters to Expr.Simplify. *) - public string SimplifyHelp ( ctx : context ) = + public string SimplifyHelp ( ctx : context ) = - Z3native.simplify_get_help ctx#gno); + Z3native.simplify_get_help ctx#gno); (** - Retrieves parameter descriptions for simplifier. + Retrieves parameter descriptions for simplifier. *) - public ParamDescrs SimplifyParameterDescriptions + public ParamDescrs SimplifyParameterDescriptions - get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } + get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } (** - Enable/disable printing of warning messages to the console. + Enable/disable printing of warning messages to the console. *) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) + Note that this function is static and effects the behaviour of + all contexts globally. + public static void ToggleWarningMessages(bool enabled) - Z3native.toggle_warning_messages((enabled) ? 1 : 0); + Z3native.toggle_warning_messages((enabled) ? 1 : 0); (* ERROR HANDLING *) (** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. *) - public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); + public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); (** - The OnError event. + The OnError event. *) - public event ErrorHandler OnError = null; + public event ErrorHandler OnError = null; (* PARAMETERS *) (** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) - - public void UpdateParamValue(string id, string value) + + public void UpdateParamValue(string id, string value) - Z3native.update_param_value ctx#gno id, value); + Z3native.update_param_value ctx#gno id, value); (** - Get a configuration parameter. - - Returns null if the parameter value does not exist. - + Get a configuration parameter. + + Returns null if the parameter value does not exist. + *) - public string GetParamValue(string id) + public string GetParamValue(string id) - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value ctx#gno id, out res); - if (r == (int)Z3_lbool.L_FALSE) - null; - else - Marshal.PtrToStringAnsi(res); + IntPtr res = IntPtr.Zero; + int r = Z3native.get_param_value ctx#gno id, out res); + if (r == (int)Z3_lbool.L_FALSE) + null; + else + Marshal.PtrToStringAnsi(res); (* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get {m_ctx) + internal IntPtr m_ctx = IntPtr.Zero; + internal Z3native.error_handler m_n_err_handler = null; + internal IntPtr nCtx { get {m_ctx) - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) + internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - internal void InitContext ( ctx : context ) = + internal void InitContext ( ctx : context ) = - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); *) - From 77679dc1f508833b3acc034b24a750ae0c2db956 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 02:47:41 +0000 Subject: [PATCH 393/646] More new ML API; Status: everything is there except for error handling. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 1498 +++++++++++++++++++++++++--------------------- 1 file changed, 809 insertions(+), 689 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f6454b797..088bfbd6f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,33 +7,52 @@ open Z3enums -(**/**) +(** Context objects. -class virtual idisposable = -object - method virtual dispose : unit -end +Most interactions with Z3 are interpreted in some context; most users will only +require one such object, but power users may require more than one. To start using +Z3, do -(** Context objects *) + + let ctx = (new context [||]) in + (...) + + +where [||] is a (possibly empty) list of pairs of strings, which can +be used to set options on the context, e.g., like so: + + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (new context cfg) in + (...) + + +*) class context settings = +(**/**) object (self) - inherit idisposable - val mutable m_n_ctx : Z3native.z3_context = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = Z3native.mk_context_rc cfg in Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; v +(* CMW: Install error handler here! + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); +*) + val mutable m_obj_cnt : int = 0 initializer (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) let f = fun o -> o#dispose in let v = self in - Gc.finalise f v + Gc.finalise f v; method dispose : unit = if m_obj_cnt == 0 then ( @@ -47,13 +66,14 @@ object (self) method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx +(**/**) end +(**/**) (** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) - inherit idisposable val mutable m_ctx : context = ctx_init val mutable m_n_obj : Z3native.ptr option = obj_init @@ -100,9 +120,10 @@ end (** Parameter set objects *) -class params ctx obj = +class params ctx = object (self) - inherit z3object ctx obj as super + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = Z3native.params_inc_ref nc o method decref nc o = Z3native.params_dec_ref nc o end @@ -264,6 +285,10 @@ object (self) method decref nc o = super#decref nc o end +let func_declaton (a : func_decl array) = + let f (e : func_decl) = e#gno in + Array.map f a + class parameter = object (self) val mutable m_kind : parameter_kind = PARAMETER_INT; @@ -624,6 +649,10 @@ object (self) method decref nc o = Z3native.tactic_dec_ref nc o end +let tacticaton (a : tactic array) = + let f (e : tactic) = e#gno in + Array.map f a + (** Function interpretation entry objects *) class func_entry ctx = object (self) @@ -715,6 +744,15 @@ object (self) method decref nc o = Z3native.solver_dec_ref nc o end +(** Fixedpoint objects *) +class fixedpoint ctx = +object (self) + inherit z3object ctx None as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method incref nc o = Z3native.fixedpoint_inc_ref nc o + method decref nc o = Z3native.fixedpoint_dec_ref nc o +end + (**/**) @@ -1294,6 +1332,33 @@ struct x else (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) + +(** + Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. +*) + let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = + create_ast ctx ptr + +(** + Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. +*) + let unwrap_ast ( a : ast ) = a#gno end (** General expressions (terms), including Boolean logic *) @@ -1308,6 +1373,18 @@ struct | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) +(** + a string describing all available parameters to Expr.Simplify. +*) + let get_simplify_help ( ctx : context ) = + Z3native.simplify_get_help ctx#gno + +(** + Retrieves parameter descriptions for simplifier. +*) + let get_simplify_parameter_descrs ( ctx : context ) = + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs ctx#gno) + (** The function declaration of the function that is applied in this expression. *) @@ -4087,6 +4164,30 @@ end *) module Params = struct +(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) +module ParamDescrs = +struct + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno +end + (** Adds a parameter setting. *) @@ -4135,37 +4236,18 @@ struct let add_s_symbol (p : params) (name : string) (value : symbol) = add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value + (** + Creates a new parameter set + *) + let mk_params ( ctx : context ) = + (new params ctx)#cnstr_obj (Z3native.mk_params ctx#gno) + (** A string representation of the parameter set. *) let to_string (p : params) = Z3native.params_to_string p#gnc p#gno end -(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) -module ParamDescrs = -struct - - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) - - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f - - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno - -end - (** Goals A goal (aka problem). A goal is essentially a @@ -4258,6 +4340,22 @@ struct Z3native.tactic_dec_ref x#gnc tn ; (new goal x#gc)#cnstr_obj res + + (** + Creates a new Goal. + + Note that the Context must have been created with proof generation support if + is set to true here. + @param models Indicates whether model generation should be enabled. + @param unsat_cores Indicates whether unsat core generation should be enabled. + @param proofs Indicates whether proof generation should be enabled. + *) + let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = + (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno + (int_of_lbool (if models then L_TRUE else L_FALSE)) + (int_of_lbool (if unsat_cores then L_TRUE else L_FALSE)) + (int_of_lbool (if proofs then L_TRUE else L_FALSE))) + (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno end @@ -4272,6 +4370,33 @@ end *) module Tactic = struct +(** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) +module ApplyResult = +struct + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals x#gnc x#gno + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in + Array.init n f + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno +end + (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno @@ -4291,6 +4416,147 @@ struct let get_solver ( x : tactic ) = (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) + (** + The number of supported tactics. + *) + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics ctx#gno + + (** + The names of all supported tactics. + *) + let get_tactic_names ( ctx : context ) = + let n = (get_num_tactics ctx ) in + let f i = (Z3native.get_tactic_name ctx#gno i) in + Array.init n f + + + (** + Returns a string containing a description of the tactic with the given name. + *) + let get_tactic_description ( ctx : context ) ( name : string ) = + Z3native.tactic_get_descr ctx#gno name + + (** + Creates a new Tactic. + *) + let mk_tactic ( ctx : context ) ( name : string ) = + (new tactic ctx)#cnstr_obj (Z3native.mk_tactic ctx#gno name) + + (** + Create a tactic that applies to a Goal and + then to every subgoal produced by . + *) + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array option ) = + match + match ts with + | None -> None + | Some(rts) -> ( + let f p c = (match p with + | None -> (Some c#gno) + | Some(x) -> (Some (Z3native.tactic_and_then ctx#gno c#gno x))) in + Array.fold_left f None rts) + with + | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + | Some(x) -> + let o = (Z3native.tactic_and_then ctx#gno t2#gno x) in + (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno o) + + (** + Create a tactic that first applies to a Goal and + if it fails then returns the result of applied to the Goal. + *) + let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + + (** + Create a tactic that applies to a goal for milliseconds. + + If does not terminate within milliseconds, then it fails. + *) + let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for ctx#gno t#gno ms) + + (** + Create a tactic that applies to a given goal if the probe + evaluates to true. + + If evaluates to false, then the new tactic behaves like the skip tactic. + *) + (* CMW: when is a keyword *) + let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_when ctx#gno p#gno t#gno) + + (** + Create a tactic that applies to a given goal if the probe + evaluates to true and otherwise. + *) + let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + + (** + Create a tactic that keeps applying until the goal is not + modified anymore or the maximum number of iterations is reached. + *) + let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat ctx#gno t#gno max) + + (** + Create a tactic that just returns the given goal. + *) + let skip ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_skip ctx#gno) + + (** + Create a tactic always fails. + *) + let fail ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail ctx#gno) + + (** + Create a tactic that fails if the probe evaluates to false. + *) + let fail_if ( ctx : context ) ( p : probe ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if ctx#gno p#gno) + + (** + Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). + *) + let fail_if_not_decided ( ctx : context ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided ctx#gno) + + (** + Create a tactic that applies using the given set of parameters . + *) + let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params ctx#gno t#gno p#gno) + + (** + Create a tactic that applies using the given set of parameters . + Alias for UsingParams*) + (* CMW: with is a keyword *) + let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + using_params ctx t p + + (** + Create a tactic that applies the given tactics in parallel. + *) + let par_or ( ctx : context ) ( t : tactic array ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or ctx#gno (Array.length t) (tacticaton t)) + + (** + Create a tactic that applies to a given goal and then + to every subgoal produced by . The subgoals are processed in parallel. + *) + let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + + (** + Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. + *) + let interrupt ( ctx : context ) = + Z3native.interrupt ctx#gno end (** Models @@ -4337,7 +4603,7 @@ struct let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]") + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end (** @@ -4513,33 +4779,6 @@ struct let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno end -(** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) -module ApplyResult = -struct - (** The number of Subgoals. *) - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals x#gnc x#gno - - (** Retrieves the subgoals from the apply_result. *) - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in - Array.init n f - - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = - (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) - - (** A string representation of the ApplyResult. *) - let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno -end - (** Solvers *) module Solver = struct @@ -4615,10 +4854,8 @@ struct let get ( x : statistics ) ( key : string ) = let f p c = (if (Entry.get_key c) = key then (Some c) else p) in Array.fold_left f None (get_entries x) - end - (** A string that describes all available solver parameters. *) @@ -4755,12 +4992,222 @@ struct let get_statistics ( x : solver ) = (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + (** + Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. + *) + let mk_solver ( ctx : context ) ( logic : symbol option) = + match logic with + | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver ctx#gno) + | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic ctx#gno x#gno) + + (** + Creates a new (incremental) solver. + + *) + let mk_solver_s ( ctx : context ) ( logic : string ) = + mk_solver ctx (Some ((Symbol.mk_string ctx logic) :> symbol)) + + (** + Creates a new (incremental) solver. + *) + let mk_simple_solver ( ctx : context ) = + (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver ctx#gno) + + (** + Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. + *) + let mk_solver_t ( ctx : context ) ( t : tactic ) = + (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic ctx#gno t#gno) + (** A string representation of the solver. *) let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno end +(** Fixedpoint solving *) +module Fixedpoints = +struct + (** + A string that describes all available fixedpoint solver parameters. + *) + let get_help ( x : fixedpoint ) = + Z3native.fixedpoint_get_help x#gnc x#gno + + (** + Sets the fixedpoint solver parameters. + *) + let set_params ( x : fixedpoint ) ( p : params )= + Z3native.fixedpoint_set_params x#gnc x#gno p#gno + + (** + Retrieves parameter descriptions for Fixedpoint solver. + *) + let get_param_descrs ( x : fixedpoint ) = + (new param_descrs x#gc)#cnstr_obj (Z3native.fixedpoint_get_param_descrs x#gnc x#gno) + + (** + Assert a constraints into the fixedpoint solver. + *) + let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in + Array.map f constraints + + (** + Register predicate as recursive relation. + *) + let register_relation ( x : fixedpoint ) ( f : func_decl ) = + Z3native.fixedpoint_register_relation x#gnc x#gno f#gno + + (** + Add rule into the fixedpoint solver. + *) + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + match name with + | None -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno (Z3native.mk_null()) + | Some(y) -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno y#gno + + (** + Add table fact to the fixedpoint solver. + *) + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = + Z3native.fixedpoint_add_fact x#gnc x#gno pred#gno (Array.length args) args + + (** + Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. + *) + let query ( x : fixedpoint ) ( query : bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query x#gnc x#gno query#gno)) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + (** + Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. + *) + let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + match (lbool_of_int (Z3native.fixedpoint_query_relations x#gnc x#gno (Array.length relations) (func_declaton relations))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + (** + Creates a backtracking point. + + *) + let push ( x : fixedpoint ) = + Z3native.fixedpoint_push x#gnc x#gno + + (** + Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + + *) + let pop ( x : fixedpoint ) = + Z3native.fixedpoint_pop x#gnc x#gno + + (** + Update named rule into in the fixedpoint solver. + *) + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + Z3native.fixedpoint_update_rule x#gnc x#gno rule#gno name#gno + + (** + Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. + *) + let get_answer ( x : fixedpoint ) = + let q = (Z3native.fixedpoint_get_answer x#gnc x#gno) in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + Retrieve explanation why fixedpoint engine returned status Unknown. + *) + let get_reason_unknown ( x : fixedpoint ) = + Z3native.fixedpoint_get_reason_unknown x#gnc x#gno + + (** + Retrieve the number of levels explored for a given predicate. + *) + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = + Z3native.fixedpoint_get_num_levels x#gnc x#gno predicate#gno + + (** + Retrieve the cover of a predicate. + *) + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta x#gnc x#gno level predicate#gno) in + if (Z3native.is_null q) then + None + else + Some (create_expr x#gc q) + + (** + Add property about the predicate. + The property is added at level. + *) + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover x#gnc x#gno level predicate#gno, property#gno + + (** + Retrieve internal string representation of fixedpoint object. + *) + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string x#gnc x#gno 0 [||] + + (** + Instrument the Datalog engine on which table representation to use for recursive predicate. + *) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + Z3native.fixedpoint_set_predicate_representation x#gnc x#gno f#gno (Array.length kinds) (symbolaton kinds) + + (** + Convert benchmark given as set of axioms, rules and queries to a string. + *) + let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = + Z3native.fixedpoint_to_string x#gnc x#gno (Array.length queries) (astaton queries) + + (** + Retrieve set of rules added to fixedpoint context. + *) + let get_rules ( x : fixedpoint ) = + let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_rules x#gnc x#gno)) in + let n = (AST.ASTVector.get_size v) in + let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + Array.init n f + + (** + Retrieve set of assertions added to fixedpoint context. + *) + let get_assertions ( x : fixedpoint ) = + let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_assertions x#gnc x#gno)) in + let n = (AST.ASTVector.get_size v) in + let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + Array.init n f + + (** + Create a Fixedpoint context. + *) + let mk_fixedpoint ( ctx : context ) = + (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) +end + (** Probes Probes are used to inspect a goal (aka problem) and collect information that may be used to decide @@ -4778,660 +5225,333 @@ struct *) let apply ( x : probe ) (g : goal) = Z3native.probe_apply x#gnc x#gno g#gno + + (** + The number of supported Probes. + *) + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes ctx#gno + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name ctx#gno i) in + Array.init n f + + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr ctx#gno name + + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + + (** + Create a probe that always evaluates to . + *) + let const ( ctx : context ) ( v : float ) = + (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by + *) + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) end - -(* STUFF FROM THE CONTEXT *) - -(** -(* OPTIONS *) +(** Global and context options + + Note: This module contains functions that set parameters/options for context + objects as well as functions that set options that are used globally, across + contexts.*) +module Options = +struct (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the Z3_PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + *) - - - - - public Z3_ast_print_mode PrintMode + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value ctx#gno id value - set { Z3native.set_ast_print_mode ctx#gno (uint)value); } - -(* SMT Files & Strings *) (** - Convert a benchmark into an SMT-LIB formatted string. + Get a configuration parameter. + + Returns None if the parameter value does not exist. + *) - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - public string BenchmarkToSMTString(string name, string logic, string status, string attributes, - BoolExpr[] assumptions, BoolExpr formula) + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value ctx#gno id) in + if ((lbool_of_int r) == L_FALSE) then + None + else + Some v - Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes, - (uint)assumptions.Length, AST.ArrayToNative(assumptions), - formula#gno); + (** + Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + + + + + *) + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode ctx#gno (int_of_ast_print_mode value) (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. + Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) - public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) + let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages (int_of_lbool (if enabled then L_TRUE else L_FALSE)) +end - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) +(** Functions for handling SMT and SMT2 expressions and files *) +module SMT = +struct + (** + Convert a benchmark into an SMT-LIB formatted string. -(** - Parse the given file using the SMT-LIB parser. -*) - - public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - Z3native.parse_smtlib_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls) - -(** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno)) - -(** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - let[] SMTLIBFormulas - - get - - uint n = NumSMTLIBFormulas; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i) - res; - - -(** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno)) - -(** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - let[] SMTLIBAssumptions - - get - - uint n = NumSMTLIBAssumptions; - BoolExpr[] res = new BoolExpr[n]; - for (uint i = 0; i < n; i++) - res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i) - res; - - -(** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno)) - -(** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public Func_Decl[] SMTLIBDecls - - get - - uint n = NumSMTLIBDecls; - Func_Decl[] res = new Func_Decl[n]; - for (uint i = 0; i < n; i++) - res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i) - res; - - -(** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno)) - -(** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. -*) - public Sort[] SMTLIBSorts - - get - - uint n = NumSMTLIBSorts; - Sort[] res = new Sort[n]; - for (uint i = 0; i < n; i++) - res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i) - res; - - -(** - Parse the given string using the SMT-LIB2 parser. -*) - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) - -(** - Parse the given file using the SMT-LIB2 parser. -*) - - let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null) - - uint csn = Symbol.ArrayLength(sortNames); - uint cs = Sort.ArrayLength(sorts); - uint cdn = Symbol.ArrayLength(declNames); - uint cd = AST.ArrayLength(decls); - if (csn != cs || cdn != cd) - throw new Z3Exception("Argument size mismatch"); - (BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName, - AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), - AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)) - -(* GOALS *) -(** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. -*) - @param models Indicates whether model generation should be enabled. - @param unsatCores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) - - new Goal(this, models, unsatCores, proofs); - -(* PARAMETERSETS *) -(** - Creates a new ParameterSet. -*) - public Params MkParams ( ctx : context ) = - - new Params(this); - -(* TACTICS *) -(** - The number of supported tactics. -*) - public uint NumTactics - - get {Z3native.get_num_tactics ctx#gno); } - -(** - The names of all supported tactics. -*) - public string[] TacticNames - - get - - uint n = NumTactics; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_tactic_name ctx#gno i); - res; - - -(** - Returns a string containing a description of the tactic with the given name. -*) - public string TacticDescription(string name) - - Z3native.tactic_get_descr ctx#gno name); - -(** - Creates a new Tactic. -*) - public Tactic MkTactic(string name) - - new Tactic(this, name); - -(** - Create a tactic that applies to a Goal and - then to every subgoal produced by . -*) - public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) - - IntPtr last = IntPtr.Zero; - if (ts != null && ts.Length > 0) - - last = ts[ts.Length - 1]#gno; - for (int i = ts.Length - 2; i >= 0; i--) - last = Z3native.tactic_and_then ctx#gno ts[i]#gno last); - - if (last != IntPtr.Zero) - - last = Z3native.tactic_and_then ctx#gno t2#gno last); - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last) + @param name Name of the benchmark. The argument is optional. + @param logic The benchmark logic. + @param status The status string (sat, unsat, or unknown) + @param attributes Other attributes, such as source, difficulty or category. + @param assumptions Auxiliary assumptions. + @param formula Formula to be checked for consistency in conjunction with assumptions. + @return A string representation of the benchmark. + *) + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + Z3native.benchmark_to_smtlib_string ctx#gno name logic status attributes + (Array.length assumptions) (astaton assumptions) + formula#gno + (** + Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays and + don't need to match the names of the sorts and declarations in the arrays + and . This is a useful feature since we can use arbitrary names to + reference sorts and declarations. + *) + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno) - -(** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - - Shorthand for AndThen. -*) - public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) - - AndThen(t1, t2, ts); - -(** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. -*) - public Tactic OrElse(Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno) - -(** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. -*) - public Tactic TryFor(Tactic t, uint ms) - - new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms) - -(** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. -*) - public Tactic When(Probe p, Tactic t) - - new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno) - -(** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. -*) - public Tactic Cond(Probe p, Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) - -(** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. -*) - public Tactic Repeat(Tactic t, uint max = uint.MaxValue) - - new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max) - -(** - Create a tactic that just returns the given goal. -*) - public Tactic Skip ( ctx : context ) = - - new Tactic(this, Z3native.tactic_skip ctx#gno) - -(** - Create a tactic always fails. -*) - public Tactic Fail ( ctx : context ) = - - new Tactic(this, Z3native.tactic_fail ctx#gno) - -(** - Create a tactic that fails if the probe evaluates to false. -*) - public Tactic FailIf(Probe p) - - new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno) - -(** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). -*) - public Tactic FailIfNotDecided ( ctx : context ) = - - new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno) - -(** - Create a tactic that applies using the given set of parameters . -*) - public Tactic UsingParams(Tactic t, Params p) - - new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno) - -(** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - public Tactic With(Tactic t, Params p) - - UsingParams(t, p); - -(** - Create a tactic that applies the given tactics in parallel. -*) - public Tactic ParOr(params Tactic[] t) - - new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t)) - -(** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. -*) - public Tactic ParAndThen(Tactic t1, Tactic t2) - - new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) - -(** - Interrupt the execution of a Z3 procedure. -*) - This procedure can be used to interrupt: solvers, simplifiers and tactics. - public void Interrupt ( ctx : context ) = - - Z3native.interrupt ctx#gno); - -(* PROBES *) -(** - The number of supported Probes. -*) - public uint NumProbes - - get {Z3native.get_num_probes ctx#gno); } - -(** - The names of all supported Probes. -*) - public string[] ProbeNames - - get - - uint n = NumProbes; - string[] res = new string[n]; - for (uint i = 0; i < n; i++) - res[i] = Z3native.get_probe_name ctx#gno i); - res; - - -(** - Returns a string containing a description of the probe with the given name. -*) - public string ProbeDescription(string name) - - Z3native.probe_get_descr ctx#gno name); - -(** - Creates a new Probe. -*) - public Probe MkProbe(string name) - - new Probe(this, name); - -(** - Create a probe that always evaluates to . -*) - public Probe Const(double val) - - new Probe(this, Z3native.probe_const ctx#gno val) - -(** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by -*) - public Probe Lt(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by -*) - public Probe Gt(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by -*) - public Probe Le(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by -*) - public Probe Ge(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by -*) - public Probe Eq(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - and evaluate to "true". -*) - public Probe And(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - or evaluate to "true". -*) - public Probe Or(Probe p1, Probe p2) - - new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno) - -(** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". -*) - public Probe Not(Probe p) - - new Probe(this, Z3native.probe_not ctx#gno p#gno) - -(* SOLVERS *) -(** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. -*) - public Solver MkSolver(Symbol logic = null) - - if (logic == null) - new Solver(this, Z3native.mk_solver ctx#gno) + Z3native.parse_smtlib_string ctx#gno str + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + + (** + Parse the given file using the SMT-LIB parser. + + *) + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno) + Z3native.parse_smtlib_file ctx#gno file_name + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (** + The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas ctx#gno -(** - Creates a new (incremental) solver. -*) - - public Solver MkSolver(string logic) + (** + The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_formulas ( ctx : context ) = + let n = (get_num_smtlib_formulas ctx ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_formula ctx#gno i)) :> bool_expr) in + Array.init n f - MkSolver(MkSymbol(logic) -(** - Creates a new (incremental) solver. -*) - let mk_Simple_Solver( ctx : context ) ctx : context ) = + (** + The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions ctx#gno - new Solver(this, Z3native.mk_simple_solver ctx#gno) + (** + The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_assumptions ( ctx : context ) = + let n = (get_num_smtlib_assumptions ctx ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i)) :> bool_expr ) in + Array.init n f -(** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. -*) - public Solver MkSolver(Tactic t) + (** + The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls ctx#gno - new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno) + (** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_decls ( ctx : context ) = + let n = (get_num_smtlib_decls ctx) in + let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl ctx#gno i) in + Array.init n f -(* FIXEDPOINTS *) -(** - Create a Fixedpoint context. -*) - public Fixedpoint MkFixedpoint ( ctx : context ) = + (** + The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts ctx#gno - new Fixedpoint(this); + (** + The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. + *) + let get_smtlib_sorts ( ctx : context ) = + let n = (get_num_smtlib_sorts ctx) in + let f i = (create_sort ctx (Z3native.get_smtlib_sort ctx#gno i)) in + Array.init n f -(* MISCELLANEOUS *) -(** - Wraps an AST. -*) - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - public AST WrapAST(IntPtr nativeObject) + (** + Parse the given string using the SMT-LIB2 parser. - AST.Create(this, nativeObject); - -(** - Unwraps an AST. -*) - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - public IntPtr UnwrapAST(AST a) - - a#gno; - -(** - a string describing all available parameters to Expr.Simplify. -*) - public string SimplifyHelp ( ctx : context ) = - - Z3native.simplify_get_help ctx#gno); - -(** - Retrieves parameter descriptions for simplifier. -*) - public ParamDescrs SimplifyParameterDescriptions - - get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); } - -(** - Enable/disable printing of warning messages to the console. -*) - Note that this function is static and effects the behaviour of - all contexts globally. - public static void ToggleWarningMessages(bool enabled) - - Z3native.toggle_warning_messages((enabled) ? 1 : 0); - -(* ERROR HANDLING *) -(** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. -*) - public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); - -(** - The OnError event. -*) - public event ErrorHandler OnError = null; - -(* PARAMETERS *) -(** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. -*) - - public void UpdateParamValue(string id, string value) - - Z3native.update_param_value ctx#gno id, value); - -(** - Get a configuration parameter. - - Returns null if the parameter value does not exist. - -*) - public string GetParamValue(string id) - - IntPtr res = IntPtr.Zero; - int r = Z3native.get_param_value ctx#gno id, out res); - if (r == (int)Z3_lbool.L_FALSE) - null; + + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. + *) + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") else - Marshal.PtrToStringAnsi(res); + Z3native.parse_smtlib2_string ctx#gno str + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) -(* INTERNAL *) - internal IntPtr m_ctx = IntPtr.Zero; - internal Z3native.error_handler m_n_err_handler = null; - internal IntPtr nCtx { get {m_ctx) + (** + Parse the given file using the SMT-LIB2 parser. + + *) + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = + let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in + let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in + let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in + let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib2_string ctx#gno file_name + cs + (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match sorts with | None -> [||] | Some(x) -> (astaton x)) + cd + (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) + (match decls with | None -> [||] | Some(x) -> (func_declaton x)) +end - internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) +(* - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. +(** + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. +*) + public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - internal void InitContext ( ctx : context ) = + internal Z3native.error_handler m_n_err_handler = null; - PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) + + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. *) From c2ff90720e6a7c08e096c096cdcc4cd7feb4b5b3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 03:00:39 +0000 Subject: [PATCH 394/646] ML API: mk_context added. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 4 +- src/api/ml/z3.ml | 687 +++++++++++++++++++------------------- 2 files changed, 349 insertions(+), 342 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index dde9f944a..32c9458f5 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,8 +14,8 @@ let _ = else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = [("model", "true"); ("proof", "false")] in - let ctx = (new context cfg) in + let cfg = (Some [("model", "true"); ("proof", "false")]) in + let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in let bs = (Sort.mk_bool ctx) in diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 088bfbd6f..fee6f9fe0 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,29 +7,9 @@ open Z3enums -(** Context objects. - -Most interactions with Z3 are interpreted in some context; most users will only -require one such object, but power users may require more than one. To start using -Z3, do - - - let ctx = (new context [||]) in - (...) - - -where [||] is a (possibly empty) list of pairs of strings, which can -be used to set options on the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (new context cfg) in - (...) - - -*) -class context settings = (**/**) + +class context settings = object (self) val mutable m_n_ctx : Z3native.z3_context = let cfg = Z3native.mk_config in @@ -66,11 +46,37 @@ object (self) method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 method gno = m_n_ctx -(**/**) end (**/**) +(** Create a context object. + +Most interactions with Z3 are interpreted in some context; many users will only +require one such object, but power users may require more than one. To start using +Z3, do + + + let ctx = (mk_context None) in + (...) + + +where a list of pairs of strings may be passed to set options on +the context, e.g., like so: + + + let cfg = (Some [("model", "true"); ("...", "...")]) in + let ctx = (mk_context cfg) in + (...) + +*) +let mk_context ( cfg : ( string * string ) list option ) = + match cfg with + | None -> new context [] + | Some(x) -> new context x + +(**/**) + (** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) @@ -4559,224 +4565,114 @@ end Z3native.interrupt ctx#gno end -(** Models +(** Probes - A Model contains interpretations (assignments) of constants and functions. *) -module Model = + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = struct - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) - module FuncInterp = - struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null np) then - None - else - Some (create_expr x#gc np) - - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl x#gnc n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno - - (** The function declarations of the constants in the model. *) - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.init n f - - - (** The number of function interpretations in the model. *) - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno - - (** The function declarations of the function interpretations in the model. *) - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - Array.init n f - - (** All symbols that have an interpretation in the model. *) - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in - if (lbool_of_int r) == L_FALSE then - raise (ModelEvaluationFailedException "evaluation failed") - else - create_expr x#gc v + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply x#gnc x#gno g#gno - (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - + (** + The number of supported Probes. *) - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes ctx#gno + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name ctx#gno i) in Array.init n f + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr ctx#gno name - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + + (** + Create a probe that always evaluates to . *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - Array.init n f - - (** Conversion of models to strings. - A string representation of the model. + let const ( ctx : context ) ( v : float ) = + (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by *) - let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) end (** Solvers *) @@ -5032,6 +4928,227 @@ struct let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno end + +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr x#gc np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl x#gnc n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in + let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in + if (lbool_of_int r) == L_FALSE then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr x#gc v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno +end + (** Fixedpoint solving *) module Fixedpoints = struct @@ -5208,116 +5325,6 @@ struct (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe = -struct - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply x#gnc x#gno g#gno - - (** - The number of supported Probes. - *) - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes ctx#gno - - (** - The names of all supported Probes. - *) - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name ctx#gno i) in - Array.init n f - - (** - Returns a string containing a description of the probe with the given name. - *) - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr ctx#gno name - - (** - Creates a new Probe. - *) - let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) - - (** - Create a probe that always evaluates to . - *) - let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) - let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) -end - (** Global and context options Note: This module contains functions that set parameters/options for context From 25498345e54f30d7f7b3095b41e3707eeb3217b2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Dec 2012 15:16:16 +0000 Subject: [PATCH 395/646] New ML API bugfixes and first example. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 122 ++++++++++++++++++++++++++++++++++++++ scripts/update_api.py | 10 +++- src/api/ml/z3.ml | 112 +++++++++++++++++----------------- 3 files changed, 186 insertions(+), 58 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 32c9458f5..945c9a494 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -4,10 +4,131 @@ *) open Z3 +open Z3.Symbol +open Z3.Sort +open Z3.Expr +open Z3.FuncDecl +open Z3.Goal +open Z3.Tactic +open Z3.Probe +open Z3.Solver open Z3.Arithmetic exception ExampleException of string + +(** + Some basic tests. +*) +let basic_tests ( ctx : context ) = + Printf.printf "BasicTests\n" ; + let qi = (mk_int ctx 1) in + let fname = ((mk_string ctx "f") :> symbol) in + let x = ((mk_string ctx "x") :> symbol) in + let y = ((mk_string ctx "y") :> symbol) in + let bs = (Sort.mk_bool ctx) in + let domain = [| bs; bs |] in + let f = (FuncDecl.mk_func_decl ctx fname domain bs) in + let fapp = (mk_app ctx f + [| (mk_const ctx x bs); (mk_const ctx y bs) |]) in + let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in + let domain2 = [| bs |] in + let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in + let trivial_eq = (mk_eq ctx fapp fapp) in + let nontrivial_eq = (mk_eq ctx fapp fapp2) in + let g = (mk_goal ctx true false false) in + (Goal.assert_ g [| trivial_eq |]) ; + (Goal.assert_ g [| nontrivial_eq |]) ; + Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; + let solver = (mk_solver ctx None) in + (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; + if (check solver None) != SATISFIABLE then + raise (ExampleException "") + else + Printf.printf "Test passed.\n" ; + () + +(* + ApplyResult ar = ApplyTactic(ctx, ctx.MkTactic("simplify"), g); + if (ar.NumSubgoals == 1 && (ar.Subgoals[0].IsDecidedSat || ar.Subgoals[0].IsDecidedUnsat)) + throw new TestFailedException(); + + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) + throw new TestFailedException(); + + g.Assert(ctx.MkEq(ctx.MkNumeral(1, ctx.MkBitVecSort(32)), + ctx.MkNumeral(2, ctx.MkBitVecSort(32)))); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + + Goal g2 = ctx.MkGoal(true, true); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) + throw new TestFailedException(); + + g2 = ctx.MkGoal(true, true); + g2.Assert(ctx.MkFalse()); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + Goal g3 = ctx.MkGoal(true, true); + Expr xc = ctx.MkConst(ctx.MkSymbol("x"), ctx.IntSort); + Expr yc = ctx.MkConst(ctx.MkSymbol("y"), ctx.IntSort); + g3.Assert(ctx.MkEq(xc, ctx.MkNumeral(1, ctx.IntSort))); + g3.Assert(ctx.MkEq(yc, ctx.MkNumeral(2, ctx.IntSort))); + BoolExpr constr = ctx.MkEq(xc, yc); + g3.Assert(constr); + ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g3); + if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) + throw new TestFailedException(); + + ModelConverterTest(ctx); + + // Real num/den test. + RatNum rn = ctx.MkReal(42, 43); + Expr inum = rn.Numerator; + Expr iden = rn.Denominator; + Console.WriteLine("Numerator: " + inum + " Denominator: " + iden); + if (inum.ToString() != "42" || iden.ToString() != "43") + throw new TestFailedException(); + + if (rn.ToDecimalString(3) != "0.976?") + throw new TestFailedException(); + + BigIntCheck(ctx, ctx.MkReal("-1231231232/234234333")); + BigIntCheck(ctx, ctx.MkReal("-123123234234234234231232/234234333")); + BigIntCheck(ctx, ctx.MkReal("-234234333")); + BigIntCheck(ctx, ctx.MkReal("234234333/2")); + + + string bn = "1234567890987654321"; + + if (ctx.MkInt(bn).BigInteger.ToString() != bn) + throw new TestFailedException(); + + if (ctx.MkBV(bn, 128).BigInteger.ToString() != bn) + throw new TestFailedException(); + + if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn) + throw new TestFailedException(); + + // Error handling test. + try + { + IntExpr i = ctx.MkInt("1/2"); + throw new TestFailedException(); // unreachable + } + catch (Z3Exception) + { + } + } +*) + + let _ = if not (Log.open_ "z3.log") then raise (ExampleException "Log couldn't be opened.") @@ -27,6 +148,7 @@ let _ = Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); Printf.printf "Disposing...\n"; + basic_tests ctx ; Gc.full_major () ); Printf.printf "Exiting.\n"; diff --git a/scripts/update_api.py b/scripts/update_api.py index acaa9478e..5d95a12f8 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -159,7 +159,7 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I # Mapping to ML types Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', STRING : 'string', STRING_PTR : 'char**', - BOOL : 'int', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } + BOOL : 'bool', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID @@ -1109,7 +1109,9 @@ def arrayparams(params): def ml_unwrap(t, ts, s): if t == STRING: return '(' + ts + ') String_val(' + s + ')' - elif t == BOOL or t == INT or t == PRINT_MODE or t == ERROR_CODE: + elif t == BOOL: + return '(' + ts + ') Bool_val(' + s + ')' + elif t == INT or t == PRINT_MODE or t == ERROR_CODE: return '(' + ts + ') Int_val(' + s + ')' elif t == UINT: return '(' + ts + ') Unsigned_int_val(' + s + ')' @@ -1125,7 +1127,9 @@ def ml_unwrap(t, ts, s): def ml_set_wrap(t, d, n): if t == VOID: return d + ' = Val_unit;' - elif t == BOOL or t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: + elif t == BOOL: + return d + ' = Val_bool(' + n + ');' + elif t == INT or t == UINT or t == PRINT_MODE or t == ERROR_CODE: return d + ' = Val_int(' + n + ');' elif t == INT64 or t == UINT64: return d + ' = Val_long(' + n + ');' diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index fee6f9fe0..b4d58711c 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -874,7 +874,7 @@ struct if a#gnc != b#gnc then false else - ((lbool_of_int (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_sort a#gnc a#gno b#gno) (** Returns a unique identifier for the sort. @@ -922,10 +922,10 @@ let create_expr ctx obj = else let s = Z3native.get_sort ctx#gno obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in - if (lbool_of_int (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then + if (Z3native.is_algebraic_number ctx#gno obj) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if ((lbool_of_int (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) && + if (Z3native.is_numeral_ast ctx#gno obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -1016,6 +1016,7 @@ struct raise (Z3native.Exception "parameter is not a ratinoal string") else x#rational + end (** Creates a new function declaration. @@ -1058,7 +1059,6 @@ struct let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = (new func_decl ctx)#cnstr_pdr prefix [||] range - end (** Comparison operator. @@ -1071,7 +1071,7 @@ struct if a#gnc == a#gnc then false else - ((lbool_of_int (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_func_decl a#gnc a#gno b#gno) (** A string representations of the function declaration. *) @@ -1202,7 +1202,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( m : ast_map ) ( key : ast ) = - (lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE + (Z3native.ast_map_contains m#gnc m#gno key#gno) (** Finds the value associated with the key . @@ -1313,7 +1313,7 @@ struct if a#gnc == b#gnc then false else - ((lbool_of_int (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE) + (Z3native.is_eq_ast a#gnc a#gno b#gno) (** Object Comparison. @@ -1472,13 +1472,13 @@ struct (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast x#gnc x#gno) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = lbool_of_int (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted x#gnc x#gno (** The Sort of the term. @@ -1489,9 +1489,9 @@ struct Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (AST.is_expr x) && - (lbool_of_int (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno))) == L_TRUE + (Z3native.is_eq_sort x#gnc + (Z3native.mk_bool_sort x#gnc) + (Z3native.get_sort x#gnc x#gno)) (** Indicates whether the term represents a constant. @@ -1774,7 +1774,7 @@ struct Indicates whether the quantifier is universal. *) let is_universal ( x : quantifier ) = - lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE + Z3native.is_quantifier_forall x#gnc x#gno (** Indicates whether the quantifier is existential. @@ -1879,7 +1879,7 @@ struct if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) (match patterns with | None -> [||] | Some(x) -> (patternaton x)) @@ -1888,7 +1888,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1905,7 +1905,7 @@ struct *) let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) @@ -1913,7 +1913,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_TRUE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1931,7 +1931,7 @@ struct if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) (match patterns with | None -> [||] | Some(x) -> (patternaton x)) @@ -1940,7 +1940,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -1957,7 +1957,7 @@ struct *) let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) (match patterns with | None -> 0 | Some(x) -> (Array.length x)) @@ -1965,7 +1965,7 @@ struct body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_FALSE) + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) @@ -2046,7 +2046,7 @@ struct Indicates whether the term is of an array sort. *) let is_array ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (Z3native.is_app x#gnc x#gno) && ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) (** The domain of the array sort. *) @@ -2252,7 +2252,7 @@ struct Indicates whether the term is of an array sort. *) let is_finite_domain ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && + (Z3native.is_app x#gnc x#gno) && (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) (** @@ -2263,7 +2263,7 @@ struct (** The size of the finite domain sort. *) let get_size (x : finite_domain_sort) = let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v + if r then v else raise (Z3native.Exception "Conversion failed.") end @@ -2274,8 +2274,8 @@ struct Indicates whether the term is of a relation sort. *) let is_relation ( x : expr ) = - ((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT) + ((Z3native.is_app x#gnc x#gno) && + (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2604,7 +2604,7 @@ struct Indicates whether the term is of integer sort. *) let is_int ( x : expr ) = - ((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) && + (Z3native.is_numeral_ast x#gnc x#gno) && ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) (** @@ -2706,12 +2706,13 @@ struct (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number x#gnc x#gno (** Retrieve the int value. *) - let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if r then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3219,9 +3220,10 @@ struct let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno (** Retrieve the int value. *) - let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if lbool_of_int(r) == L_TRUE then v - else raise (Z3native.Exception "Conversion failed.") + let get_int ( x : bitvec_num ) = + let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + if r then v + else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3613,7 +3615,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3621,7 +3623,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3645,7 +3647,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3669,7 +3671,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE))) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -4198,7 +4200,7 @@ end Adds a parameter setting. *) let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE)) + Z3native.params_set_bool p#gnc p#gno name#gno value (** Adds a parameter setting. @@ -4291,11 +4293,12 @@ struct (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : bool_expr array ) = let f e = Z3native.goal_assert x#gnc x#gno e#gno in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = - (lbool_of_int (Z3native.goal_inconsistent x#gnc x#gno)) == L_TRUE + Z3native.goal_inconsistent x#gnc x#gno (** The depth of the goal. This tracks how many transformations were applied to it. *) @@ -4318,11 +4321,11 @@ struct (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = - (lbool_of_int (Z3native.goal_is_decided_sat x#gnc x#gno)) == L_TRUE + Z3native.goal_is_decided_sat x#gnc x#gno (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = - (lbool_of_int (Z3native.goal_is_decided_unsat x#gnc x#gno)) == L_TRUE + Z3native.goal_is_decided_unsat x#gnc x#gno (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = @@ -4357,10 +4360,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno - (int_of_lbool (if models then L_TRUE else L_FALSE)) - (int_of_lbool (if unsat_cores then L_TRUE else L_FALSE)) - (int_of_lbool (if proofs then L_TRUE else L_FALSE))) + (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno @@ -4729,7 +4729,7 @@ struct let n = (get_size x ) in let f i = ( let k = Z3native.stats_get_key x#gnc x#gno i in - if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then + if (Z3native.stats_is_uint x#gnc x#gno i) then ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) else ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) @@ -4800,7 +4800,8 @@ struct *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** The number of assertions in the solver. @@ -5049,7 +5050,7 @@ struct else match sk with | ARRAY_SORT -> - if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then + if not (Z3native.is_as_array x#gnc n) then raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl x#gnc n in @@ -5105,8 +5106,8 @@ struct The evaluation of in the model. *) let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in - if (lbool_of_int r) == L_FALSE then + let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno completion) in + if not r then raise (ModelEvaluationFailedException "evaluation failed") else create_expr x#gc v @@ -5175,7 +5176,8 @@ struct *) let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in - Array.map f constraints + ignore (Array.map f constraints) ; + () (** Register predicate as recursive relation. @@ -5353,7 +5355,7 @@ struct *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value ctx#gno id) in - if ((lbool_of_int r) == L_FALSE) then + if not r then None else Some v @@ -5383,7 +5385,7 @@ struct all contexts globally. *) let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages (int_of_lbool (if enabled then L_TRUE else L_FALSE)) + Z3native.toggle_warning_messages enabled end (** Functions for handling SMT and SMT2 expressions and files *) From c03d5277bc179a561083151549177f33fe087823 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 26 Dec 2012 16:54:45 +0000 Subject: [PATCH 396/646] more ML Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 58 +++++++++++++++++++++------------------ src/api/ml/z3.ml | 4 +++ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 945c9a494..7fcd2e9f7 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -10,11 +10,12 @@ open Z3.Expr open Z3.FuncDecl open Z3.Goal open Z3.Tactic +open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic -exception ExampleException of string +exception TestFailedException of string (** @@ -43,32 +44,37 @@ let basic_tests ( ctx : context ) = let solver = (mk_solver ctx None) in (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; if (check solver None) != SATISFIABLE then - raise (ExampleException "") + raise (TestFailedException "") else Printf.printf "Test passed.\n" ; - () - -(* - ApplyResult ar = ApplyTactic(ctx, ctx.MkTactic("simplify"), g); - if (ar.NumSubgoals == 1 && (ar.Subgoals[0].IsDecidedSat || ar.Subgoals[0].IsDecidedUnsat)) - throw new TestFailedException(); - - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) - throw new TestFailedException(); - - g.Assert(ctx.MkEq(ctx.MkNumeral(1, ctx.MkBitVecSort(32)), - ctx.MkNumeral(2, ctx.MkBitVecSort(32)))); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - - Goal g2 = ctx.MkGoal(true, true); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedSat) - throw new TestFailedException(); - + () ; + let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + let g2 = (mk_goal ctx true true false) in + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + () +(* g2 = ctx.MkGoal(true, true); g2.Assert(ctx.MkFalse()); ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); @@ -131,7 +137,7 @@ let basic_tests ( ctx : context ) = let _ = if not (Log.open_ "z3.log") then - raise (ExampleException "Log couldn't be opened.") + raise (TestFailedException "Log couldn't be opened.") else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b4d58711c..8806a70ee 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -4391,6 +4391,10 @@ struct let n = (get_num_subgoals x) in let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in Array.init n f + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoal ( x : apply_result ) ( i : int ) = + (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. From e2f6b10e3200bef881e0e3dcd2d84c8ab5570d37 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 27 Dec 2012 15:51:42 +0000 Subject: [PATCH 397/646] ML API bugfixes More ML examples Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 165 ++++++++++++++++++++++++++------------ src/api/ml/z3.ml | 5 ++ 2 files changed, 119 insertions(+), 51 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 7fcd2e9f7..0e8122ae0 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -17,6 +17,50 @@ open Z3.Arithmetic exception TestFailedException of string +(** + Model Converter test +*) +let model_converter_test ( ctx : context ) = + Printf.printf "ModelConverterTest\n"; + let xr = ((mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let yr = ((mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let g4 = (mk_goal ctx true false false ) in + (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; + (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; + (Goal.assert_ g4 [| (mk_gt ctx yr (mk_real_numeral_nd ctx 1 1)) |]) ; + ( + let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") None) g4 None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + let solver = (mk_solver ctx None) in + let f e = (Solver.assert_ solver [| e |]) in + ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; + let q = (check solver None) in + if q != SATISFIABLE then + raise (TestFailedException "") + else + let m = (get_model solver) in + match m with + | None -> raise (TestFailedException "") + | Some (m) -> + Printf.printf "Solver says: %s\n" (string_of_status q) ; + Printf.printf "Model: \n%s\n" (Model.to_string m) ; + Printf.printf "Converted Model: \n%s\n" (Model.to_string (convert_model ar 0 m)) + ) (** Some basic tests. @@ -41,59 +85,78 @@ let basic_tests ( ctx : context ) = (Goal.assert_ g [| trivial_eq |]) ; (Goal.assert_ g [| nontrivial_eq |]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; - let solver = (mk_solver ctx None) in - (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver None) != SATISFIABLE then - raise (TestFailedException "") - else - Printf.printf "Test passed.\n" ; - () ; - let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in - if ((get_num_subgoals ar) == 1 && - ((is_decided_sat (get_subgoal ar 0)) || - (is_decided_unsat (get_subgoal ar 0)))) then + ( + let solver = (mk_solver ctx None) in + (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; + if (check solver None) != SATISFIABLE then raise (TestFailedException "") else - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) - (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) - ; - let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_unsat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - let g2 = (mk_goal ctx true true false) in - let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in - if ((get_num_subgoals ar) == 1 && - (not (is_decided_sat (get_subgoal ar 0)))) then - raise (TestFailedException "") - else - () -(* - g2 = ctx.MkGoal(true, true); - g2.Assert(ctx.MkFalse()); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g2); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - Goal g3 = ctx.MkGoal(true, true); - Expr xc = ctx.MkConst(ctx.MkSymbol("x"), ctx.IntSort); - Expr yc = ctx.MkConst(ctx.MkSymbol("y"), ctx.IntSort); - g3.Assert(ctx.MkEq(xc, ctx.MkNumeral(1, ctx.IntSort))); - g3.Assert(ctx.MkEq(yc, ctx.MkNumeral(2, ctx.IntSort))); - BoolExpr constr = ctx.MkEq(xc, yc); - g3.Assert(constr); - ar = ApplyTactic(ctx, ctx.MkTactic("smt"), g3); - if (ar.NumSubgoals != 1 || !ar.Subgoals[0].IsDecidedUnsat) - throw new TestFailedException(); - - ModelConverterTest(ctx); - + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in + if ((get_num_subgoals ar) == 1 && + ((is_decided_sat (get_subgoal ar 0)) || + (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + ; + ( + let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g2 = (mk_goal ctx true true false) in + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_sat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g2 = (mk_goal ctx true true false) in + (Goal.assert_ g2 [| (mk_false ctx) |]) ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); + ( + let g3 = (mk_goal ctx true true false) in + let xc = (mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_int_sort ctx)) in + let yc = (mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_int_sort ctx)) in + (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; + (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; + let constr = (mk_eq ctx xc yc) in + (Goal.assert_ g3 [| constr |] ) ; + let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in + if ((get_num_subgoals ar) == 1 && + (not (is_decided_unsat (get_subgoal ar 0)))) then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ) ; + model_converter_test ctx +(* // Real num/den test. RatNum rn = ctx.MkReal(42, 43); Expr inum = rn.Numerator; diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8806a70ee..c0711b4eb 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -4684,6 +4684,11 @@ module Solver = struct type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let string_of_status ( s : status) = match s with + | UNSATISFIABLE -> "unsatisfiable" + | SATISFIABLE -> "satisfiable" + | _ -> "unknown" + (** Objects that track statistical information about solvers. *) module Statistics = struct From 7eb95bf6c20943f9324e52b1671d11ebfb6537b5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 15:32:25 +0000 Subject: [PATCH 398/646] ML API: made native layer ANSI-C compliant to avoid compilation issues. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 +++- scripts/update_api.py | 55 ++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 849644a18..020653272 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1440,7 +1440,10 @@ class MLComponent(Component): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + if WINDOWS: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) + else: + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) out.write('z3.cmxa: %s\n' % libfile) out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) out.write('z3.cma: %s\n' % libfile) diff --git a/scripts/update_api.py b/scripts/update_api.py index 5d95a12f8..1986f4a7e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1262,39 +1262,39 @@ def mk_ml(): ml_wrapper.write('#include \n\n') ml_wrapper.write('#define CAMLlocal6(X1,X2,X3,X4,X5,X6) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal1(X6); \n') + ml_wrapper.write(' CAMLlocal1(X6) \n') ml_wrapper.write('#define CAMLlocal7(X1,X2,X3,X4,X5,X6,X7) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal2(X6,X7); \n') + ml_wrapper.write(' CAMLlocal2(X6,X7) \n') ml_wrapper.write('#define CAMLlocal8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') ml_wrapper.write(' CAMLlocal5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLlocal3(X6,X7,X8); \n') + ml_wrapper.write(' CAMLlocal3(X6,X7,X8) \n') ml_wrapper.write('\n') ml_wrapper.write('#define CAMLparam7(X1,X2,X3,X4,X5,X6,X7) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam2(X6,X7); \n') + ml_wrapper.write(' CAMLxparam2(X6,X7) \n') ml_wrapper.write('#define CAMLparam8(X1,X2,X3,X4,X5,X6,X7,X8) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam3(X6,X7,X8); \n') + ml_wrapper.write(' CAMLxparam3(X6,X7,X8) \n') ml_wrapper.write('#define CAMLparam9(X1,X2,X3,X4,X5,X6,X7,X8,X9) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') - ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9); \n') + ml_wrapper.write(' CAMLxparam4(X6,X7,X8,X9) \n') ml_wrapper.write('#define CAMLparam12(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam2(X11,X12); \n') + ml_wrapper.write(' CAMLxparam2(X11,X12) \n') ml_wrapper.write('#define CAMLparam13(X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13) \\\n') ml_wrapper.write(' CAMLparam5(X1,X2,X3,X4,X5); \\\n') ml_wrapper.write(' CAMLxparam5(X6,X7,X8,X9,X10); \\\n') - ml_wrapper.write(' CAMLxparam3(X11,X12,X13); \n') + ml_wrapper.write(' CAMLxparam3(X11,X12,X13) \n') ml_wrapper.write('\n\n') ml_wrapper.write('static struct custom_operations default_custom_ops = {\n') - ml_wrapper.write(' identifier: (char*) "default handling",\n') - ml_wrapper.write(' finalize: custom_finalize_default,\n') - ml_wrapper.write(' compare: custom_compare_default,\n') - ml_wrapper.write(' hash: custom_hash_default,\n') - ml_wrapper.write(' serialize: custom_serialize_default,\n') - ml_wrapper.write(' deserialize: custom_deserialize_default\n') + ml_wrapper.write(' (char*) "default handling",\n') + ml_wrapper.write(' custom_finalize_default,\n') + ml_wrapper.write(' custom_compare_default,\n') + ml_wrapper.write(' custom_hash_default,\n') + ml_wrapper.write(' custom_serialize_default,\n') + ml_wrapper.write(' custom_deserialize_default\n') ml_wrapper.write('};\n\n') ml_wrapper.write('#ifdef __cplusplus\n') ml_wrapper.write('extern "C" {\n') @@ -1358,7 +1358,10 @@ def mk_ml(): i = i + 1 ml_wrapper.write(');\n') - # preprocess arrays, strings, in/out arguments + if len(ap) != 0: + ml_wrapper.write(' unsigned _i;\n') + + # declare locals, preprocess arrays, strings, in/out arguments i = 0 for param in params: k = param_kind(param) @@ -1372,22 +1375,32 @@ def mk_ml(): elif k == IN_ARRAY or k == INOUT_ARRAY: t = param_type(param) ts = type2str(t) - ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) - ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) _a%s[i] = %s;\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', i)'))) + ml_wrapper.write(' %s * _a%s = (%s*) malloc(sizeof(%s) * _a%s);\n' % (ts, i, ts, ts, param_array_capacity_pos(param))) elif k == IN: t = param_type(param) ml_wrapper.write(' %s _a%s = %s;\n' % (type2str(t), i, ml_unwrap(t, type2str(t), 'a' + str(i)))) elif k == OUT: ml_wrapper.write(' %s _a%s;\n' % (type2str(param_type(param)), i)) elif k == INOUT: - ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) - + ml_wrapper.write(' %s _a%s = a%s;\n' % (type2str(param_type(param)), i, i)) + i = i + 1 + + if result != VOID: + ml_wrapper.write(' %s z3_result;\n' % type2str(result)) + + i = 0 + for param in params: + k = param_kind(param) + if k == IN_ARRAY or k == INOUT_ARRAY: + t = param_type(param) + ts = type2str(t) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { _a%s[_i] = %s; }\n' % (param_array_capacity_pos(param), i, ml_unwrap(t, ts, 'Field(a' + str(i) + ', _i)'))) i = i + 1 # invoke procedure ml_wrapper.write(' ') if result != VOID: - ml_wrapper.write('%s z3_result = ' % type2str(result)) + ml_wrapper.write('z3_result = ') ml_wrapper.write('%s(' % name) i = 0 first = True @@ -1412,7 +1425,7 @@ def mk_ml(): for p in params: if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) - ml_wrapper.write(' for (unsigned i = 0; i < _a%s; i++) { value t; %s Store_field(_a%s, i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[i]'), i)) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 From 3e8c1e3a29494a6b893f5015ba2dccce9477a2d5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 18:56:19 +0000 Subject: [PATCH 399/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 020653272..9bb0e0efe 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1440,7 +1440,7 @@ class MLComponent(Component): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - if WINDOWS: + if IS_WINDOWS: out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) else: out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) From 4a606dbe600d09fb8b9db059583a865edea4b5be Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 7 Jan 2013 22:44:55 +0000 Subject: [PATCH 400/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 9bb0e0efe..9dcf43813 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1439,7 +1439,7 @@ class MLComponent(Component): for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I%s -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) + out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I"%s" -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) if IS_WINDOWS: out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) else: From 49dd2e4a07a48ce106c86cb0b6fefee804bc47ee Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 20:56:49 +0000 Subject: [PATCH 401/646] ML API: build system changes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 48 +++++++++++++++++++++++++++++++++++----------- src/api/ml/README | 2 +- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 9dcf43813..4c39ff13b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1342,6 +1342,7 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): +<<<<<<< HEAD CP_CMD = "cp" if IS_WINDOWS: CP_CMD = "copy" @@ -1436,18 +1437,31 @@ class MLComponent(Component): mk_dir(bld_dir) libfile = '%s$(SO_EXT)' % self.lib_name out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) +======= + src_dir = self.to_src_dir + sub_dir = os.path.join('api', 'ml') + mk_dir(os.path.join(BUILD_DIR, sub_dir)) + for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): + shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): + shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + out.write('z3.cmxa:') + for mlfile in get_ml_files(self.src_dir): + out.write(' %s' % os.path.join(src_dir, mlfile)) + out.write('\n') + out.write('\tpushd %s && %s ' % (sub_dir, OCAMLOPT)) + if DEBUG_MODE: + out.write('-g ') + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cmxa -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) + out.write('z3.cma:') +>>>>>>> ML API: build system changes for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT) -I"%s" -I%s %s/z3native.c\n' % (get_component(API_COMPONENT).to_src_dir, OCAML_LIB, self.to_src_dir)) - if IS_WINDOWS: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) - else: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % (libfile, os.path.join('api', 'ml', 'z3native'))) - out.write('z3.cmxa: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3.cmxa z3native$(OBJ_EXT) && cd -\n' % (self.to_src_dir,BUILD_DIR)) - out.write('z3.cma: %s\n' % libfile) - out.write('\tcd %s && ocamlbuild -cflags \'-g\' -lflags -custom,-cclib,-L../..,-cclib,-lz3,-cclib,-lz3ml,-linkall -build-dir ../../../%s/api/ml z3native$(OBJ_EXT) z3.cma && cd -\n' % (self.to_src_dir,BUILD_DIR)) + out.write('\tpushd %s && %s ' % (sub_dir, OCAMLC)) + if DEBUG_MODE: + out.write('-g ') + out.write('-custom -ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cma -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) out.write('ml: z3.cmxa z3.cma\n') out.write('\n') @@ -1576,7 +1590,10 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\tocamlc -g -o ml_example.byte -I . z3.cma -I api/ml') + out.write('\t%s ' % OCAMLC) + if DEBUG_MODE: + out.write('-g ') + out.write('-custom -o ml_example.byte -I . z3.cma -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1584,7 +1601,10 @@ class MLExampleComponent(ExampleComponent): for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') - out.write('\tocamlopt -g -o ml_example -I . z3.cmxa -I api/ml') + out.write('\t%s ' % OCAMLOPT) + if DEBUG_MODE: + out.write('-g ') + out.write('-o ml_example($EXE_EXT) -I . z3.cmxa -I api/ml') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1862,9 +1882,15 @@ def mk_config(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) if is_ml_enabled(): +<<<<<<< HEAD print('Ocaml Compiler: %s' % OCAMLC) print('Ocaml Native: %s' % OCAMLOPT) print('Ocaml Library: %s' % OCAML_LIB) +======= + print('OCaml Compiler: %s' % OCAMLC) + print('OCaml Native: %s' % OCAMLOPT) + print('OCaml Library: %s' % OCAML_LIB) +>>>>>>> ML API: build system changes def mk_install(out): out.write('install: ') diff --git a/src/api/ml/README b/src/api/ml/README index 36f903925..beee7d864 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -5,4 +5,4 @@ We are currently working on a brand new ML API. On Windows, there are no less than four different ports of OCaml. The Z3 build system assumes that either the win32 or the win64 port is installed. This means that OCaml will use `cl' as the underlying C compiler and not the cygwin or -mingw compilers. +mingw compilers. \ No newline at end of file From 09292437db25600e12a590ea6151784005843f3c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 21:02:44 +0000 Subject: [PATCH 402/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4c39ff13b..503c3dadd 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -357,6 +357,7 @@ def check_ml(): rmf('hello.cmo') rmf('hello.cmx') rmf('a.out') + t.__del__() find_ml_lib() find_ocaml_find() From f94fa8544476845742078bad95b1627cdec6f0bb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 8 Jan 2013 21:22:45 +0000 Subject: [PATCH 403/646] ML API: build system fix --- scripts/mk_util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 503c3dadd..4c39ff13b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -357,7 +357,6 @@ def check_ml(): rmf('hello.cmo') rmf('hello.cmx') rmf('a.out') - t.__del__() find_ml_lib() find_ocaml_find() From f0e61ee52342dccf32039b44186afb4c77ac71f3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 10 Jan 2013 17:25:55 +0000 Subject: [PATCH 404/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 128 ++++++--------------------------------------- 1 file changed, 15 insertions(+), 113 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4c39ff13b..c7b48b891 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1342,102 +1342,6 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): -<<<<<<< HEAD - CP_CMD = "cp" - if IS_WINDOWS: - CP_CMD = "copy" - src_dir = self.to_src_dir - sub_dir = os.path.join('api', 'ml') - mk_dir(os.path.join(BUILD_DIR, sub_dir)) - api_src = get_component(API_COMPONENT).to_src_dir - for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): - out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) - str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) - out.write(str) - for f in filter(lambda f: f.endswith('.mli'), os.listdir(self.src_dir)): - out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) - str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) - out.write(str) - for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): - out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) - str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) - out.write(str) - modules = ["z3enums", "z3native", "z3"] # dependencies in this order! - mls = '' - mlis = '' - cmis = '' - archives = '' - - for m in modules: - fn = os.path.join(self.src_dir, ('%s.mli' % m)) - if not os.path.exists(fn): - out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),mlis)) - out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) - out.write('%s.cmi: %s.mli%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m), cmis)) - out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) - out.write('%s.cma: %s.ml %s.cmi%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),os.path.join(sub_dir,m), archives)) - out.write('\t%s -a -o %s.ml -o %s.cma\n' % (OCAMLC,os.path.join(sub_dir,m), os.path.join(sub_dir,m))) - mlis = mlis + ' ' + os.path.join(sub_dir, m) + '.mli' - cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - archives = archives + ' ' + os.path.join(sub_dir,m) + '.cma' - mls = mls + ' ' + os.path.join(sub_dir, m) + '.ml' - - out.write('%s: %s %s\n' % - (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), - os.path.join(sub_dir, 'z3native_stubs.c'), - get_component(Z3_DLL_COMPONENT).dll_name+'$(SO_EXT)')); - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % - (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) - - out.write('%s: %s %s %s$(SO_EXT)' % ( - os.path.join(sub_dir, "z3ml.cmxa"), - cmis, - archives, - get_component(Z3_DLL_COMPONENT).dll_name)) - out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tocamlmklib -o %s -I %s -ldopt \"-L. -lz3\" ' % (os.path.join(sub_dir, 'z3ml'), sub_dir)) - for m in modules: - out.write(' %s' % (os.path.join(sub_dir, m+'.ml'))) - out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) - self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) - if OCAMLFIND != '': - out.write('\nocamlfind_install: %s %s %s\n' % ( - get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)', - os.path.join(sub_dir, 'z3ml.cmxa'), - os.path.join(sub_dir, 'META'))) - out.write('\t%s remove Z3\n' % (OCAMLFIND)) - out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) - for m in modules: - out.write(' %s.cma' % (os.path.join(sub_dir, m))) - out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - out.write(' %s.cmo' % (os.path.join(sub_dir, m))) - out.write(' %s.ml' % (os.path.join(sub_dir, m))) - out.write(' %s.mli' % (os.path.join(sub_dir, m))) - out.write(' %s$(OBJ_EXT)' % (os.path.join(sub_dir, m))) - out.write(' %s' % ((os.path.join(sub_dir, 'z3ml$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cma')))) - out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cmxa')))) - out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) - if IS_WINDOWS: - out.write('.dll') - else: - out.write('.so') # .so also on OSX! - out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') - if IS_WINDOWS: - out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') - out.write('\n\n') - deffile = open('%s.mllib' % os.path.join(self.src_dir, "z3"), 'w') - for mlfile in get_ml_files(self.src_dir): - deffile.write('%s\n' % (string.upper(mlfile[0]) + mlfile[1:-3])) - deffile.close() - bld_dir = os.path.join(BUILD_DIR, 'api', 'ml') - mk_dir(bld_dir) - libfile = '%s$(SO_EXT)' % self.lib_name - out.write('%s: libz3$(SO_EXT) %s' % (libfile, os.path.join(self.to_src_dir, 'z3native.c'))) -======= src_dir = self.to_src_dir sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) @@ -1445,24 +1349,28 @@ class MLComponent(Component): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - out.write('z3.cmxa:') + out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s api/ml/z3native.c $(CXX_OUTFLAG) api/ml/z3native$(OBJ_EXT)\n' % get_component(API_COMPONENT).to_src_dir) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG) libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') - out.write('\tpushd %s && %s ' % (sub_dir, OCAMLOPT)) + out.write('\tcd %s && %s ' % (sub_dir, OCAMLOPT)) if DEBUG_MODE: out.write('-g ') out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cmxa -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) out.write('z3.cma:') ->>>>>>> ML API: build system changes + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cmxa -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('api/ml/z3.cma: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\tpushd %s && %s ' % (sub_dir, OCAMLC)) + out.write('\tcd %s && %s ' % (sub_dir, OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-custom -ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cma -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) - out.write('ml: z3.cmxa z3.cma\n') + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cma -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') def main_component(self): @@ -1586,29 +1494,29 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: z3.cma ') + out.write('ml_example.byte: api/ml/z3.cma ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I . z3.cma -I api/ml') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" z3.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example($EXE_EXT): z3.cmxa ml_example.byte') + out.write('ml_example$(EXE_EXT): api/ml/z3.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example($EXE_EXT) -I . z3.cmxa -I api/ml') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" z3.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('_ex_%s: ml_example.byte ml_example($EXE_EXT)\n\n' % self.name) + out.write('_ex_%s: ml_example.byte ml_example$(EXE_EXT)\n\n' % self.name) class PythonExampleComponent(ExampleComponent): def __init__(self, name, path): @@ -1882,15 +1790,9 @@ def mk_config(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) if is_ml_enabled(): -<<<<<<< HEAD print('Ocaml Compiler: %s' % OCAMLC) print('Ocaml Native: %s' % OCAMLOPT) print('Ocaml Library: %s' % OCAML_LIB) -======= - print('OCaml Compiler: %s' % OCAMLC) - print('OCaml Native: %s' % OCAMLOPT) - print('OCaml Library: %s' % OCAML_LIB) ->>>>>>> ML API: build system changes def mk_install(out): out.write('install: ') From e57dbbb56dcdc951e3c8460f4882f1a7d46e7e48 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 10 Jan 2013 18:39:43 +0000 Subject: [PATCH 405/646] ML API: build system fixes --- scripts/mk_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index c7b48b891..befd78be6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1350,8 +1350,8 @@ class MLComponent(Component): for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s api/ml/z3native.c $(CXX_OUTFLAG) api/ml/z3native$(OBJ_EXT)\n' % get_component(API_COMPONENT).to_src_dir) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG) libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s api/ml/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, get_component(API_COMPONENT).to_src_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) From 1e2b546b037ce87675580e860dcfe183305d35eb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 11 Jan 2013 14:33:28 +0000 Subject: [PATCH 406/646] ML API: changed context from object to normal type. Removed optional array parameters. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 8 +- src/api/ml/z3.ml | 661 ++++++++++++++++++-------------------- 2 files changed, 323 insertions(+), 346 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 0e8122ae0..129f73d4d 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -38,7 +38,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ); ( - let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") None) g4 None) in + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") [||]) g4 None) in if ((get_num_subgoals ar) == 1 && ((is_decided_sat (get_subgoal ar 0)) || (is_decided_unsat (get_subgoal ar 0)))) then @@ -49,7 +49,7 @@ let model_converter_test ( ctx : context ) = let solver = (mk_solver ctx None) in let f e = (Solver.assert_ solver [| e |]) in ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; - let q = (check solver None) in + let q = (check solver [||]) in if q != SATISFIABLE then raise (TestFailedException "") else @@ -88,7 +88,7 @@ let basic_tests ( ctx : context ) = ( let solver = (mk_solver ctx None) in (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver None) != SATISFIABLE then + if (check solver [||]) != SATISFIABLE then raise (TestFailedException "") else Printf.printf "Test passed.\n" @@ -204,7 +204,7 @@ let _ = else ( Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = (Some [("model", "true"); ("proof", "false")]) in + let cfg = [("model", "true"); ("proof", "false")] in let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c0711b4eb..c91d909bc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,46 +7,39 @@ open Z3enums +type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } + (**/**) +let context_dispose ctx = + if ctx.m_n_obj_cnt == 0 then ( + (* Printf.printf "Disposing context \n" ; *) + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; + (* re-queue for finalization? *) + ) -class context settings = -object (self) - val mutable m_n_ctx : Z3native.z3_context = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - v - +let context_init settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + (* Printf.printf "Installing finalizer on context \n" ; *) + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> context_dispose o in + Gc.finalise f res; + res (* CMW: Install error handler here! m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. Z3native.set_error_handler(m_ctx, m_n_err_handler); GC.SuppressFinalize(this); *) - val mutable m_obj_cnt : int = 0 - - initializer - (* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v; - - method dispose : unit = - if m_obj_cnt == 0 then ( - (* Printf.printf "Disposing context %d \n" (Oo.id self) ; *) - (Z3native.del_context m_n_ctx) - ) else ( - Printf.printf "NOT DISPOSING context %d because it still has %d objects alive\n" (Oo.id self) m_obj_cnt; - (* re-queue for finalization? *) - ) - - method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1 - method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1 - method gno = m_n_ctx -end +let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) +let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) +let context_gno ctx = ctx.m_n_ctx (**/**) @@ -70,10 +63,8 @@ the context, e.g., like so: (...) *) -let mk_context ( cfg : ( string * string ) list option ) = - match cfg with - | None -> new context [] - | Some(x) -> new context x +let mk_context ( cfg : ( string * string ) list ) = + context_init cfg (**/**) @@ -85,8 +76,8 @@ object (self) initializer (match m_n_obj with - | Some (x) -> self#incref m_ctx#gno x; - m_ctx#add_one_ctx_obj + | Some (x) -> self#incref (context_gno m_ctx) x; + (context_add1 m_ctx) | None -> () ); (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) @@ -101,8 +92,8 @@ object (self) (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) (match m_n_obj with | Some (x) -> - self#decref m_ctx#gno x; - m_ctx#sub_one_ctx_obj ; + self#decref (context_gno m_ctx) x; + (context_sub1 m_ctx) ; m_n_obj <- None; | None -> () ); @@ -112,16 +103,16 @@ object (self) | None -> raise (Z3native.Exception "Z3 object lost") method sno (ctx : context) o = - m_ctx#add_one_ctx_obj ; - self#incref ctx#gno o ; + (context_add1 m_ctx) ; + self#incref (context_gno ctx) o ; (match m_n_obj with - | Some(x) -> self#decref ctx#gno x ; m_ctx#sub_one_ctx_obj + | Some(x) -> self#decref (context_gno ctx) x ; (context_sub1 m_ctx) | None -> () ); m_n_obj <- Some o method gc = m_ctx - method gnc = m_ctx#gno + method gnc = (context_gno m_ctx) end @@ -134,37 +125,38 @@ object (self) method decref nc o = Z3native.params_dec_ref nc o end + (** Symbol objects *) -class symbol ctx = +class symbol ctx = object (self) - inherit z3object ctx None as super + inherit z3object ctx None as super method cnstr_obj obj = (self#sno ctx obj) ; self method incref nc o = () method decref nc o = () end +(** Int symbol objects *) +class int_symbol ctx = +object(self) + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol (context_gno ctx) i)) ; self +end + +(** String symbol objects *) +class string_symbol ctx = +object(self) + inherit symbol ctx as super + method cnstr_obj obj = (self#sno ctx obj) ; self + method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol (context_gno ctx) name)) ; self +end + let symbolaton (a : symbol array) = let f (e : symbol) = e#gno in Array.map f a -(** Int symbol objects *) -class int_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol ctx#gno i)) ; self -end - -(** String symbol objects *) -class string_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol ctx#gno name)) ; self -end - let create_symbol ctx no = - match (symbol_kind_of_int (Z3native.get_symbol_kind ctx#gno no)) with + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) @@ -205,7 +197,7 @@ class array_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self + method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort (context_gno ctx) domain#gno range#gno)) ; self end (** Bit-vector sort objects *) @@ -241,7 +233,7 @@ class uninterpreted_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self + method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) s#gno)) ; self end (** Finite domain sort objects *) @@ -249,7 +241,7 @@ class finite_domain_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self + method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) s#gno sz)) ; self end (** Relation sort objects *) @@ -273,7 +265,7 @@ object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in (self#sno ctx x) ; self end @@ -284,8 +276,8 @@ class func_decl ctx = object (self) inherit ast ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o method decref nc o = super#decref nc o @@ -341,7 +333,7 @@ object (self) val mutable _testerdecls : func_decl array option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in + let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) name#gno (Array.length enum_names) (symbolaton enum_names)) in _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; (self#sno ctx r) ; @@ -368,7 +360,7 @@ object (self) val mutable _taildecl : func_decl option = None method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) name#gno elem_sort#gno) in _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; @@ -426,7 +418,7 @@ object (self) if m_n != (Array.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else - let o = (Z3native.mk_constructor ctx#gno name#gno recognizer#gno m_n (symbolaton field_names) + let o = (Z3native.mk_constructor (context_gno ctx) name#gno recognizer#gno m_n (symbolaton field_names) (sortaton sorts) sort_refs) in self#sno ctx o ; @@ -473,7 +465,7 @@ object (self) Gc.finalise f v method cnstr_obj obj = (self#sno ctx obj) ; self method cnstr_ca ( c : constructor array ) = - self#sno ctx (Z3native.mk_constructor_list ctx#gno (Array.length c) (constructoraton c)) ; + self#sno ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (constructoraton c)) ; self end @@ -486,11 +478,11 @@ class datatype_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (constructoraton constructors)))) ; self + method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) name#gno (Array.length constructors) (constructoraton constructors)))) ; self end let create_sort ctx obj = - match (sort_kind_of_int (Z3native.get_sort_kind ctx#gno obj)) with + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) obj)) with | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) @@ -900,7 +892,7 @@ struct Create a new Boolean sort. *) let mk_bool ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno) + (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort (context_gno ctx)) (** Create a new uninterpreted sort. @@ -917,15 +909,15 @@ end (**/**) let create_expr ctx obj = - if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then (((new quantifier ctx)#cnstr_obj obj) :> expr) else - let s = Z3native.get_sort ctx#gno obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in - if (Z3native.is_algebraic_number ctx#gno obj) then + let s = Z3native.get_sort (context_gno ctx) obj in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) obj) then (((new algebraic_num ctx)#cnstr_obj obj) :> expr) else - if (Z3native.is_numeral_ast ctx#gno obj) && + if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) @@ -943,11 +935,11 @@ let create_expr ctx obj = | _ -> (new expr ctx)#cnstr_obj obj let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = - let o = Z3native.mk_app ctx#gno f#gno (Array.length args) (astaton args) in + let o = Z3native.mk_app (context_gno ctx) f#gno (Array.length args) (astaton args) in create_expr ctx o let create_ast ctx no = - match (ast_kind_of_int (Z3native.get_ast_kind ctx#gno no)) with + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) | SORT_AST -> ((create_sort ctx no) :> ast) @@ -1188,7 +1180,7 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno) + (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = @@ -1337,7 +1329,7 @@ struct if x#gc == to_ctx then x else - (create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)) + (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) (** Wraps an AST. @@ -1383,13 +1375,13 @@ struct a string describing all available parameters to Expr.Simplify. *) let get_simplify_help ( ctx : context ) = - Z3native.simplify_get_help ctx#gno + Z3native.simplify_get_help (context_gno ctx) (** Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs ctx#gno) + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -1462,7 +1454,7 @@ struct if x#gc == to_ctx then x else - create_expr to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno) + create_expr to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx)) (** Returns a string representation of the expression. @@ -1578,7 +1570,7 @@ struct Creates a new Constant of sort and named . *) let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const ctx#gno name#gno range#gno) + create_expr ctx (Z3native.mk_const (context_gno ctx) name#gno range#gno) (** @@ -1600,7 +1592,7 @@ struct name prefixed with . *) let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = - create_expr ctx (Z3native.mk_fresh_const ctx#gno prefix range#gno) + create_expr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix range#gno) (** Create a Boolean constant. @@ -1624,13 +1616,13 @@ struct The true Term. *) let mk_true ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_true ctx#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_false ctx#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1642,19 +1634,19 @@ struct Creates the equality = . *) let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq ctx#gno x#gno y#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq (context_gno ctx) x#gno y#gno) (** Creates a distinct term. *) let mk_distinct ( ctx : context ) ( args : expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct (context_gno ctx) (Array.length args) (astaton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_not ctx#gno a#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_not (context_gno ctx) a#gno) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1663,37 +1655,37 @@ struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite ctx#gno t1#gno t2#gno t3#gno) + create_expr ctx (Z3native.mk_ite (context_gno ctx) t1#gno t2#gno t3#gno) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor (context_gno ctx) t1#gno t2#gno) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_and ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_and (context_gno ctx) (Array.length args) (astaton args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args)) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_or (context_gno ctx) (Array.length args) (astaton args)) (** Create a numeral of a given sort. @@ -1702,7 +1694,7 @@ struct @return A Term with value and sort *) let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - create_expr ctx (Z3native.mk_numeral ctx#gno v ty#gno) + create_expr ctx (Z3native.mk_numeral (context_gno ctx) v ty#gno) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1712,7 +1704,7 @@ struct @return A Term with value and type *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_int ctx#gno v ty#gno) + create_expr ctx (Z3native.mk_int (context_gno ctx) v ty#gno) end (** Quantifier expressions *) @@ -1845,7 +1837,7 @@ struct @param ty The sort of the variable *) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno) + create_expr ctx (Z3native.mk_bound (context_gno ctx) index ty#gno) (** Create a quantifier pattern. @@ -1854,7 +1846,7 @@ struct if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms)) + (new pattern ctx)#cnstr_obj (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (astaton terms)) (** Create a universal Quantifier. @@ -1875,27 +1867,24 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno true + else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno true + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) @@ -1903,51 +1892,45 @@ struct (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = - if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno true + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno true + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) body#gno) (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno false + else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno false + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) (astaton names) body#gno) @@ -1955,31 +1938,28 @@ struct (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = - if (nopatterns == None && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno false + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) body#gno) else let null = Z3native.mk_null() in - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno false + (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) (match skolem_id with | None -> null | Some(x) -> x#gno) (Array.length bound_constants) (expraton bound_constants) - (match patterns with | None -> 0 | Some(x) -> (Array.length x)) - (match patterns with | None -> [||] | Some(x) -> (patternaton x)) - (match nopatterns with | None -> 0 | Some(x) -> (Array.length x)) - (match nopatterns with | None -> [||] | Some(x) -> (patternaton x)) + (Array.length patterns) (patternaton patterns) + (Array.length nopatterns) (patternaton nopatterns) body#gno) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1989,7 +1969,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2081,7 +2061,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - ((create_expr ctx (Z3native.mk_select ctx#gno a#gno i#gno)) :> array_expr) + ((create_expr ctx (Z3native.mk_select (context_gno ctx) a#gno i#gno)) :> array_expr) (** Array update. @@ -2100,7 +2080,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_store ctx#gno a#gno i#gno v#gno) + (new array_expr ctx)#cnstr_obj (Z3native.mk_store (context_gno ctx) a#gno i#gno v#gno) (** Create a constant array. @@ -2111,7 +2091,7 @@ struct *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array ctx#gno domain#gno v#gno) + (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array (context_gno ctx) domain#gno v#gno) (** Maps f on the argument arrays. @@ -2124,7 +2104,7 @@ struct *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = - ((create_expr ctx (Z3native.mk_map ctx#gno f#gno (Array.length args) (astaton args))) :> array_expr) + ((create_expr ctx (Z3native.mk_map (context_gno ctx) f#gno (Array.length args) (astaton args))) :> array_expr) (** Access the array default value. @@ -2133,7 +2113,7 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - ((create_expr ctx (Z3native.mk_array_default ctx#gno arg#gno)) :> array_expr) + ((create_expr ctx (Z3native.mk_array_default (context_gno ctx) arg#gno)) :> array_expr) end (** Functions to manipulate Set expressions *) @@ -2174,61 +2154,61 @@ struct Create an empty set. *) let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno)) + (create_expr ctx (Z3native.mk_empty_set (context_gno ctx) domain#gno)) (** Create the full set. *) let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno) + create_expr ctx (Z3native.mk_full_set (context_gno ctx) domain#gno) (** Add an element to the set. *) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno) + create_expr ctx (Z3native.mk_set_add (context_gno ctx) set#gno element#gno) (** Remove an element from a set. *) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno) + create_expr ctx (Z3native.mk_set_del (context_gno ctx) set#gno element#gno) (** Take the union of a list of sets. *) let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args)) + create_expr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (astaton args)) (** Take the intersection of a list of sets. *) let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args)) + create_expr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (astaton args)) (** Take the difference between two sets. *) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno) + create_expr ctx (Z3native.mk_set_difference (context_gno ctx) arg1#gno arg2#gno) (** Take the complement of a set. *) let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno) + create_expr ctx (Z3native.mk_set_complement (context_gno ctx) arg#gno) (** Check for set membership. *) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno) + create_expr ctx (Z3native.mk_set_member (context_gno ctx) elem#gno set#gno) (** Check for subsetness of sets. *) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno) + create_expr ctx (Z3native.mk_set_subset (context_gno ctx) arg1#gno arg2#gno) end @@ -2458,7 +2438,7 @@ struct let n = (Array.length names) in let f e = ( (new constructor_list ctx)#cnstr_ca e ) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (symbolaton names) (constructor_listaton cla)) in let g e = ( (new datatype_sort ctx)#cnstr_obj e) in (Array.map g r) @@ -2592,13 +2572,13 @@ struct Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno) + (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort (context_gno ctx)) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno) + (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort (context_gno ctx)) (** Indicates whether the term is of integer sort. @@ -2761,75 +2741,75 @@ struct Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub ctx#gno (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - (create_expr ctx (Z3native.mk_unary_minus ctx#gno t#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) t#gno) :> arith_expr) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - (create_expr ctx (Z3native.mk_div ctx#gno t1#gno t2#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_div (context_gno ctx) t1#gno t2#gno) :> arith_expr) (** Create an expression representing t1 mod t2. The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_mod ctx#gno t1#gno t2#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_mod (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_rem ctx#gno t1#gno t2#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_rem (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 ^ t2. *) let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (create_expr ctx (Z3native.mk_power ctx#gno t1#gno t2#gno) :> arith_expr) + (create_expr ctx (Z3native.mk_power (context_gno ctx) t1#gno t2#gno) :> arith_expr) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_le ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_le (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt (context_gno ctx) t1#gno t2#gno) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge (context_gno ctx) t1#gno t2#gno) (** Coerce an integer to a real. @@ -2842,7 +2822,7 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real ctx#gno t#gno) + (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real (context_gno ctx) t#gno) (** Coerce a real to an integer. @@ -2852,13 +2832,13 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int ctx#gno t#gno) + (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int (context_gno ctx) t#gno) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int ctx#gno t#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int (context_gno ctx) t#gno) (** Return a upper bound for a given real algebraic number. @@ -2898,7 +2878,7 @@ struct raise (Z3native.Exception "Denominator is zero") else - (new rat_num ctx)#cnstr_obj (Z3native.mk_real ctx#gno num den) + (new rat_num ctx)#cnstr_obj (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2906,7 +2886,7 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_real_sort ctx)#gno) + (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create a real numeral. @@ -2915,14 +2895,14 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_real_sort ctx)#gno) + (new rat_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_int_sort ctx)#gno) + (new int_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) (** Create an integer numeral. @@ -2930,7 +2910,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_int_sort ctx)#gno) + (new int_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -2944,7 +2924,7 @@ struct Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size) + (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3245,91 +3225,91 @@ struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg ctx#gno t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) (** Unsigned division. @@ -3341,7 +3321,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) (** Signed division. @@ -3356,7 +3336,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) (** Unsigned remainder. @@ -3366,7 +3346,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) (** Signed remainder. @@ -3378,7 +3358,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) (** Two's complement signed remainder (sign follows divisor). @@ -3387,7 +3367,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than @@ -3395,7 +3375,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult (context_gno ctx) t1#gno t2#gno) (** Two's complement signed less-than @@ -3403,7 +3383,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than or equal to. @@ -3411,7 +3391,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule (context_gno ctx) t1#gno t2#gno) (** Two's complement signed less-than or equal to. @@ -3419,7 +3399,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle (context_gno ctx) t1#gno t2#gno) (** Unsigned greater than or equal to. @@ -3427,7 +3407,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge (context_gno ctx) t1#gno t2#gno) (** Two's complement signed greater than or equal to. @@ -3435,7 +3415,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge (context_gno ctx) t1#gno t2#gno) (** Unsigned greater-than. @@ -3443,7 +3423,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt (context_gno ctx) t1#gno t2#gno) (** Two's complement signed greater-than. @@ -3451,7 +3431,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt (context_gno ctx) t1#gno t2#gno) (** Bit-vector concatenation. @@ -3462,7 +3442,7 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat (context_gno ctx) t1#gno t2#gno) (** Bit-vector extraction. @@ -3473,7 +3453,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract ctx#gno high low t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) (** Bit-vector sign extension. @@ -3483,7 +3463,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext (context_gno ctx) i t#gno) (** Bit-vector zero extension. @@ -3494,7 +3474,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext (context_gno ctx) i t#gno) (** Bit-vector repetition. @@ -3502,7 +3482,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat (context_gno ctx) i t#gno) (** Shift left. @@ -3517,7 +3497,7 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl (context_gno ctx) t1#gno t2#gno) (** Logical shift right @@ -3531,7 +3511,7 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr (context_gno ctx) t1#gno t2#gno) (** Arithmetic shift right @@ -3547,7 +3527,7 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr (context_gno ctx) t1#gno t2#gno) (** Rotate Left. @@ -3556,7 +3536,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left (context_gno ctx) i t#gno) (** Rotate Right. @@ -3565,7 +3545,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right ctx#gno i t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right (context_gno ctx) i t#gno) (** Rotate Left. @@ -3574,7 +3554,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left (context_gno ctx) t1#gno t2#gno) (** Rotate Right. @@ -3584,7 +3564,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right ctx#gno t1#gno t2#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right (context_gno ctx) t1#gno t2#gno) (** Create an bit bit-vector from the integer argument . @@ -3597,7 +3577,7 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv ctx#gno n t#gno) + (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv (context_gno ctx) n t#gno) (** Create an integer from the bit-vector argument . @@ -3615,7 +3595,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno signed) + (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3623,7 +3603,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3631,7 +3611,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3639,7 +3619,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3647,7 +3627,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3655,7 +3635,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) t1#gno t2#gno) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3663,7 +3643,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow ctx#gno t#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow (context_gno ctx) t#gno) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3671,7 +3651,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno signed) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow (context_gno ctx) t1#gno t2#gno signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3679,7 +3659,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno) + (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow (context_gno ctx) t1#gno t2#gno) (** Create a bit-vector numeral. @@ -3688,7 +3668,7 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_sort ctx size)#gno) + (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) end (** Functions to manipulate proof expressions *) @@ -4248,7 +4228,7 @@ end Creates a new parameter set *) let mk_params ( ctx : context ) = - (new params ctx)#cnstr_obj (Z3native.mk_params ctx#gno) + (new params ctx)#cnstr_obj (Z3native.mk_params (context_gno ctx)) (** A string representation of the parameter set. @@ -4329,7 +4309,7 @@ struct (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno to_ctx#gno) + (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : params option ) = @@ -4360,7 +4340,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal ctx#gno models unsat_cores proofs) + (new goal ctx)#cnstr_obj (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno @@ -4429,14 +4409,14 @@ end (** The number of supported tactics. *) - let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics ctx#gno + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) (** The names of all supported tactics. *) let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in - let f i = (Z3native.get_tactic_name ctx#gno i) in + let f i = (Z3native.get_tactic_name (context_gno ctx) i) in Array.init n f @@ -4444,39 +4424,34 @@ end Returns a string containing a description of the tactic with the given name. *) let get_tactic_description ( ctx : context ) ( name : string ) = - Z3native.tactic_get_descr ctx#gno name + Z3native.tactic_get_descr (context_gno ctx) name (** Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - (new tactic ctx)#cnstr_obj (Z3native.mk_tactic ctx#gno name) + (new tactic ctx)#cnstr_obj (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and then to every subgoal produced by . *) - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array option ) = - match - match ts with - | None -> None - | Some(rts) -> ( - let f p c = (match p with - | None -> (Some c#gno) - | Some(x) -> (Some (Z3native.tactic_and_then ctx#gno c#gno x))) in - Array.fold_left f None rts) - with - | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno t2#gno) + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = + let f p c = (match p with + | None -> (Some c#gno) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) c#gno x))) in + match (Array.fold_left f None ts) with + | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno t2#gno) | Some(x) -> - let o = (Z3native.tactic_and_then ctx#gno t2#gno x) in - (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then ctx#gno t1#gno o) + let o = (Z3native.tactic_and_then (context_gno ctx) t2#gno x) in + (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else ctx#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else (context_gno ctx) t1#gno t2#gno) (** Create a tactic that applies to a goal for milliseconds. @@ -4484,7 +4459,7 @@ end If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for ctx#gno t#gno ms) + (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for (context_gno ctx) t#gno ms) (** Create a tactic that applies to a given goal if the probe @@ -4494,52 +4469,52 @@ end *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when ctx#gno p#gno t#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) p#gno t#gno) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) p#gno t1#gno t2#gno) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat ctx#gno t#gno max) + (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat (context_gno ctx) t#gno max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_skip ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if ctx#gno p#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) p#gno) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided ctx#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params ctx#gno t#gno p#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params (context_gno ctx) t#gno p#gno) (** Create a tactic that applies using the given set of parameters . @@ -4552,21 +4527,21 @@ end Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or ctx#gno (Array.length t) (tacticaton t)) + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (tacticaton t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno) + (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then (context_gno ctx) t1#gno t2#gno) (** Interrupt the execution of a Z3 procedure. This procedure can be used to interrupt: solvers, simplifiers and tactics. *) let interrupt ( ctx : context ) = - Z3native.interrupt ctx#gno + Z3native.interrupt (context_gno ctx) end (** Probes @@ -4591,68 +4566,68 @@ struct The number of supported Probes. *) let get_num_probes ( ctx : context ) = - Z3native.get_num_probes ctx#gno + Z3native.get_num_probes (context_gno ctx) (** The names of all supported Probes. *) let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name ctx#gno i) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in Array.init n f (** Returns a string containing a description of the probe with the given name. *) let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr ctx#gno name + Z3native.probe_get_descr (context_gno ctx) name (** Creates a new Probe. *) let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe ctx#gno name) + (new probe ctx)#cnstr_obj (Z3native.mk_probe (context_gno ctx) name) (** Create a probe that always evaluates to . *) let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const ctx#gno v) + (new probe ctx)#cnstr_obj (Z3native.probe_const (context_gno ctx) v) (** Create a probe that evaluates to "true" when the value returned by is less than the value returned by *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_lt (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is greater than the value returned by *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_gt (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is less than or equal the value returned by *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_le (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is greater than or equal the value returned by *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_ge (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value returned by is equal to the value returned by *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_eq (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4660,7 +4635,7 @@ struct *) (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_and (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4668,7 +4643,7 @@ struct *) (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or ctx#gno p1#gno p2#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_or (context_gno ctx) p1#gno p2#gno) (** Create a probe that evaluates to "true" when the value @@ -4676,7 +4651,7 @@ struct *) (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not ctx#gno p#gno) + (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) end (** Solvers *) @@ -4836,11 +4811,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array option) = + let check ( x : solver ) ( assumptions : bool_expr array) = let r = - match assumptions with - | None -> lbool_of_int (Z3native.solver_check x#gnc x#gno) - | Some (ass) -> lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length ass) (astaton ass)) + if ((Array.length assumptions) == 0) then + lbool_of_int (Z3native.solver_check x#gnc x#gno) + else + lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length assumptions) (astaton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -4907,8 +4883,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver ctx#gno) - | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic ctx#gno x#gno) + | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver (context_gno ctx)) + | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic (context_gno ctx) x#gno) (** Creates a new (incremental) solver. @@ -4921,7 +4897,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver ctx#gno) + (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver (context_gno ctx)) (** Creates a solver that is implemented using the given tactic. @@ -4930,7 +4906,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic ctx#gno t#gno) + (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno) (** A string representation of the solver. @@ -5333,7 +5309,7 @@ struct Create a Fixedpoint context. *) let mk_fixedpoint ( ctx : context ) = - (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint ctx#gno) + (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint (context_gno ctx)) end (** Global and context options @@ -5354,7 +5330,7 @@ struct *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value ctx#gno id value + Z3native.update_param_value (context_gno ctx) id value (** Get a configuration parameter. @@ -5363,7 +5339,7 @@ struct *) let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value ctx#gno id) in + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then None else @@ -5385,7 +5361,7 @@ struct *) let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode ctx#gno (int_of_ast_print_mode value) + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) (** Enable/disable printing of warning messages to the console. @@ -5412,7 +5388,7 @@ struct @return A string representation of the benchmark. *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = - Z3native.benchmark_to_smtlib_string ctx#gno name logic status attributes + Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes (Array.length assumptions) (astaton assumptions) formula#gno @@ -5425,92 +5401,93 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib_string ctx#gno str + Z3native.parse_smtlib_string (context_gno ctx) str cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib_file ctx#gno file_name + Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas ctx#gno + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_formula ctx#gno i)) :> bool_expr) in + let f i = ((create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) :> bool_expr) in Array.init n f (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions ctx#gno + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i)) :> bool_expr ) in + let f i = ((create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) :> bool_expr ) in Array.init n f (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls ctx#gno + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl ctx#gno i) in + let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts ctx#gno + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (create_sort ctx (Z3native.get_smtlib_sort ctx#gno i)) in + let f i = (create_sort ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5519,41 +5496,41 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string ctx#gno str + Z3native.parse_smtlib2_string (context_gno ctx) str cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array option ) ( sorts : sort array option ) ( decl_names : symbol array option ) ( decls : func_decl array option ) = - let csn = (match sort_names with | None -> 0 | Some(x) -> Array.length x) in - let cs = (match sorts with | None -> 0 | Some(x) -> Array.length x) in - let cdn = (match decl_names with | None -> 0 | Some(x) -> Array.length x) in - let cd = (match decls with | None -> 0 | Some(x) -> Array.length x) in + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let csn = (Array.length sort_names) in + let cs = (Array.length sorts) in + let cdn = (Array.length decl_names) in + let cd = (Array.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string ctx#gno file_name + Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (match sort_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match sorts with | None -> [||] | Some(x) -> (astaton x)) + (symbolaton sort_names) + (astaton sorts) cd - (match decl_names with | None -> [||] | Some(x) -> (symbolaton x)) - (match decls with | None -> [||] | Some(x) -> (func_declaton x)) + (symbolaton decl_names) + (func_declaton decls) end (* From 6257c56901179e6560e57a4483a41d1f6f51c820 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 00:01:50 +0000 Subject: [PATCH 407/646] ML API: bugfixes; starting to replace objects with normal types. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 3 +- scripts/update_api.py | 3 +- src/api/ml/z3.ml | 711 ++++++++++++++++++++------------------ 3 files changed, 382 insertions(+), 335 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 129f73d4d..97985a7bc 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,6 +14,7 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic +open Z3.Fixedpoints exception TestFailedException of string @@ -216,8 +217,8 @@ let _ = Printf.printf "bool sort: %s\n" (Sort.to_string bs); Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); - Printf.printf "Disposing...\n"; basic_tests ctx ; + Printf.printf "Disposing...\n"; Gc.full_major () ); Printf.printf "Exiting.\n"; diff --git a/scripts/update_api.py b/scripts/update_api.py index 1986f4a7e..c730a325e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1300,7 +1300,8 @@ def mk_ml(): ml_wrapper.write('extern "C" {\n') ml_wrapper.write('#endif\n\n') ml_wrapper.write('CAMLprim value n_is_null(value p) {\n') - ml_wrapper.write(' return Val_bool(Data_custom_val(p) == 0);\n') + ml_wrapper.write(' void * t = * (void**) Data_custom_val(p);\n') + ml_wrapper.write(' return Val_bool(t == 0);\n') ml_wrapper.write('}\n\n') ml_wrapper.write('CAMLprim value n_mk_null( void ) {\n') ml_wrapper.write(' CAMLparam0();\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c91d909bc..1e8ffe92e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,9 +7,13 @@ open Z3enums -type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } + +(**/**) + +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) -(**/**) let context_dispose ctx = if ctx.m_n_obj_cnt == 0 then ( (* Printf.printf "Disposing context \n" ; *) @@ -19,7 +23,7 @@ let context_dispose ctx = (* re-queue for finalization? *) ) -let context_init settings = +let context_cnstr settings = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; @@ -50,7 +54,7 @@ require one such object, but power users may require more than one. To start usi Z3, do - let ctx = (mk_context None) in + let ctx = (mk_context []) in (...) @@ -58,17 +62,18 @@ where a list of pairs of strings may be passed to set options on the context, e.g., like so: - let cfg = (Some [("model", "true"); ("...", "...")]) in + let cfg = [("model", "true"); ("...", "...")] in let ctx = (mk_context cfg) in (...) *) let mk_context ( cfg : ( string * string ) list ) = - context_init cfg + context_cnstr cfg + + +(* type z3object = { m_ctx : context; m_n_obj : Z3native.ptr option; } *) (**/**) - -(** Z3 objects *) class virtual z3object ctx_init obj_init = object (self) val mutable m_ctx : context = ctx_init @@ -669,15 +674,6 @@ object (self) method decref nc o = Z3native.func_interp_dec_ref nc o end -(** Model objects *) -class model ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.model_inc_ref nc o - method decref nc o = Z3native.model_dec_ref nc o -end - (** Tactic application result objects *) class apply_result ctx = object (self) @@ -724,32 +720,38 @@ object (self) method is_float = m_is_float end -(** Statistics objects *) -class statistics ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.stats_inc_ref nc o - method decref nc o = Z3native.stats_dec_ref nc o -end -(** Solver objects *) -class solver ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.solver_inc_ref nc o - method decref nc o = Z3native.solver_dec_ref nc o -end +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } -(** Fixedpoint objects *) -class fixedpoint ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.fixedpoint_inc_ref nc o - method decref nc o = Z3native.fixedpoint_dec_ref nc o -end +let z3obj_gc o = o.m_ctx +let z3obj_gnc o = (context_gno o.m_ctx) + +let z3obj_gno o = o.m_n_obj +let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + +let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + +let z3obj_cnstr o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o (**/**) @@ -1878,7 +1880,6 @@ struct (astaton names) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1900,7 +1901,6 @@ struct (Array.length patterns) (patternaton patterns) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1924,7 +1924,6 @@ struct (astaton names) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -1946,7 +1945,6 @@ struct (Array.length patterns) (patternaton patterns) body#gno) else - let null = Z3native.mk_null() in (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> x#gno) @@ -4347,6 +4345,240 @@ struct end +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model = +struct + type model = z3_native_object + + (**/**) + let model_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : model = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. + *) + module FuncInterp = + struct + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. + *) + module FuncEntry = + struct + (** + Return the (symbolic) value of this entry. + *) + let get_value ( x : func_entry ) = + create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + + (** + The number of arguments of the entry. + *) + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + + (** + The arguments of the function entry. + *) + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + Array.init n f + + (** + A string representation of the function entry. + *) + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + (** + The number of entries in the function interpretation. + *) + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + + (** + The entries in the function interpretation + *) + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + Array.init n f + + (** + The (symbolic) `else' value of the function interpretation. + *) + let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + + (** + The arity of the function interpretation + *) + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + + (** + A string representation of the function interpretation. + *) + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (Array.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + (** Retrieves the interpretation (the assignment) of in the model. + A function declaration of zero arity + An expression if the function has an interpretation in the model, null otherwise. *) + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + if (Z3native.is_null np) then + None + else + Some (create_expr (z3obj_gc x) np) + + (** Retrieves the interpretation (the assignment) of in the model. + A Constant + An expression if the constant has an interpretation in the model, null otherwise. + *) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + (** Retrieves the interpretation (the assignment) of a non-constant in the model. + A function declaration of non-zero arity + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range f#gnc f#gno))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if not (Z3native.is_as_array (z3obj_gnc x) n) then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in + get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in + if (Z3native.is_null n) then None else Some ((new func_interp (z3obj_gc x))#cnstr_obj n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) + + (** The function declarations of the constants in the model. *) + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + + (** The number of function interpretations in the model. *) + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) + + (** The function declarations of the function interpretations in the model. *) + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** All symbols that have an interpretation in the model. *) + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + Array.append (Array.init n_funcs f) (Array.init n_consts g) + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** + Evaluates the expression in the current model. + + + This function may fail if contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + + An expression + + When this flag is enabled, a model value will be assigned to any constant + or function that does not have an interpretation in the model. + + The evaluation of in the model. + *) + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) t#gno completion) in + if not r then + raise (ModelEvaluationFailedException "evaluation failed") + else + create_expr (z3obj_gc x) v + + (** Alias for eval. *) + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + + + *) + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (create_sort (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + Array.init n f + + + (** The finite set of distinct values that represent the interpretation for sort . + + An uninterpreted sort + An array of expressions, where each is an element of the universe of + *) + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + Array.init n f + + (** Conversion of models to strings. + A string representation of the model. + *) + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) +end + + (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. @@ -4380,8 +4612,8 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = - (new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno) + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.model_cnstr x#gc (Z3native.apply_result_convert_model x#gnc x#gno i (z3obj_gno m)) (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno @@ -4401,11 +4633,6 @@ end | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) - (** creates a solver that is implemented using the given tactic. - *) - let get_solver ( x : tactic ) = - (new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno) - (** The number of supported tactics. *) @@ -4654,9 +4881,23 @@ struct (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) end + (** Solvers *) module Solver = struct + type solver = z3_native_object + +(**/**) + let solver_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : solver = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.solver_inc_ref ; + dec_ref = Z3native.solver_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res +(**/**) + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE let string_of_status ( s : status) = match s with @@ -4667,6 +4908,18 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = struct + type statistics = z3_native_object + + (**/**) + let statistics_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : statistics = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.stats_inc_ref ; + dec_ref = Z3native.stats_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** Statistical data is organized into pairs of [Key, Entry], where every @@ -4703,20 +4956,20 @@ struct end (** A string representation of the statistical data. *) - let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno + let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) (** The number of statistical data. *) - let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno + let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) (** The data entries. *) let get_entries ( x : statistics ) = let n = (get_size x ) in let f i = ( - let k = Z3native.stats_get_key x#gnc x#gno i in - if (Z3native.stats_is_uint x#gnc x#gno i) then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i)) + let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in + if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then + ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i)) + ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -4725,7 +4978,7 @@ struct *) let get_keys ( x : statistics ) = let n = (get_size x) in - let f i = (Z3native.stats_get_key x#gnc x#gno i) in + let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** @@ -4739,51 +4992,51 @@ struct (** A string that describes all available solver parameters. *) - let get_help ( x : solver ) = Z3native.solver_get_help x#gnc x#gno + let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) (** Sets the solver parameters. *) let set_parameters ( x : solver ) ( value : params )= - Z3native.solver_set_params x#gnc x#gno value#gno + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) value#gno (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.solver_get_param_descrs x#gnc x#gno) + (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). *) - let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes x#gnc x#gno + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) (** Creates a backtracking point. *) - let push ( x : solver ) = Z3native.solver_push x#gnc x#gno + let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) (** Backtracks backtracking points. Note that an exception is thrown if is not smaller than NumScopes *) - let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n (** Resets the Solver. This removes all assertions from the solver. *) - let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno + let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) (** Assert a constraint (or multiple) into the solver. *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = - let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in ignore (Array.map f constraints) ; () @@ -4791,7 +5044,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -4799,9 +5052,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in + let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get a i)#gno) in + let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -4814,9 +5067,9 @@ struct let check ( x : solver ) ( assumptions : bool_expr array) = let r = if ((Array.length assumptions) == 0) then - lbool_of_int (Z3native.solver_check x#gnc x#gno) + lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length assumptions) (astaton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (astaton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -4830,11 +5083,11 @@ struct if its results was not SATISFIABLE, or if model production is not enabled. *) let get_model ( x : solver ) = - let q = Z3native.solver_get_model x#gnc x#gno in + let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then None else - Some ((new model x#gc)#cnstr_obj q) + Some (Model.model_cnstr (z3obj_gc x) q) (** The proof of the last Check. @@ -4843,11 +5096,11 @@ struct if its results was not UNSATISFIABLE, or if proof production is disabled. *) let get_proof ( x : solver ) = - let q = Z3native.solver_get_proof x#gnc x#gno in + let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** The unsat core of the last Check. @@ -4857,7 +5110,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in + let cn = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -4865,14 +5118,14 @@ struct (** A brief justification of why the last call to Check returned UNKNOWN. *) - let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown x#gnc x#gno + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) (** Solver statistics. *) let get_statistics ( x : solver ) = - (new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno) + (Statistics.statistics_cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -4883,8 +5136,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (new solver ctx)#cnstr_obj (Z3native.mk_solver (context_gno ctx)) - | Some (x) -> (new solver ctx)#cnstr_obj (Z3native.mk_solver_for_logic (context_gno ctx) x#gno) + | None -> (solver_cnstr ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (solver_cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) (** Creates a new (incremental) solver. @@ -4897,7 +5150,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (new solver ctx)#cnstr_obj (Z3native.mk_simple_solver (context_gno ctx)) + (solver_cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -4906,261 +5159,54 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (new solver ctx)#cnstr_obj (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno) + (solver_cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) (** A string representation of the solver. *) - let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno + let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) -module Model = -struct - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) - module FuncInterp = - struct - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) - module FuncEntry = - struct - (** - Return the (symbolic) value of this entry. - *) - let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) - - (** - The number of arguments of the entry. - *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno - - (** - The arguments of the function entry. - *) - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in - Array.init n f - - (** - A string representation of the function entry. - *) - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - (** - The number of entries in the function interpretation. - *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno - - (** - The entries in the function interpretation - *) - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in - Array.init n f - - (** - The (symbolic) `else' value of the function interpretation. - *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) - - (** - The arity of the function interpretation - *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno - - (** - A string representation of the function interpretation. - *) - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (Array.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null np) then - None - else - Some (create_expr x#gc np) - - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if not (Z3native.is_as_array x#gnc n) then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl x#gnc n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno - - (** The function declarations of the constants in the model. *) - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.init n f - - - (** The number of function interpretations in the model. *) - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno - - (** The function declarations of the function interpretations in the model. *) - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - Array.init n f - - (** All symbols that have an interpretation in the model. *) - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in - let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. - *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno completion) in - if not r then - raise (ModelEvaluationFailedException "evaluation failed") - else - create_expr x#gc v - - (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - - *) - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in - Array.init n f - - - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of - *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - Array.init n f - - (** Conversion of models to strings. - A string representation of the model. - *) - let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno -end - (** Fixedpoint solving *) module Fixedpoints = struct + type fixedpoint = z3_native_object + +(**/**) + let fixedpoint_cnstr ( ctx : context ) = + let res : fixedpoint = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.fixedpoint_inc_ref ; + dec_ref = Z3native.fixedpoint_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; + (z3obj_cnstr res) ; + res +(**/**) + (** A string that describes all available fixedpoint solver parameters. *) let get_help ( x : fixedpoint ) = - Z3native.fixedpoint_get_help x#gnc x#gno + Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) (** Sets the fixedpoint solver parameters. *) let set_params ( x : fixedpoint ) ( p : params )= - Z3native.fixedpoint_set_params x#gnc x#gno p#gno + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) p#gno (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.fixedpoint_get_param_descrs x#gnc x#gno) + (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. *) let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = - let f e = (Z3native.fixedpoint_assert x#gnc x#gno e#gno) in + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in ignore (Array.map f constraints) ; () @@ -5168,21 +5214,21 @@ struct Register predicate as recursive relation. *) let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation x#gnc x#gno f#gno + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) f#gno (** Add rule into the fixedpoint solver. *) let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno (Z3native.mk_null()) - | Some(y) -> Z3native.fixedpoint_add_rule x#gnc x#gno rule#gno y#gno + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno y#gno (** Add table fact to the fixedpoint solver. *) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact x#gnc x#gno pred#gno (Array.length args) args + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) pred#gno (Array.length args) args (** Query the fixedpoint solver. @@ -5191,7 +5237,7 @@ struct The query is unsatisfiable if there are no derivations satisfying the query variables. *) let query ( x : fixedpoint ) ( query : bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query x#gnc x#gno query#gno)) with + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) query#gno)) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5203,7 +5249,7 @@ struct The query is unsatisfiable if there are no derivations satisfying any of the relations. *) let query_r ( x : fixedpoint ) ( relations : func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations x#gnc x#gno (Array.length relations) (func_declaton relations))) with + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (func_declaton relations))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5213,7 +5259,7 @@ struct *) let push ( x : fixedpoint ) = - Z3native.fixedpoint_push x#gnc x#gno + Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) (** Backtrack one backtracking point. @@ -5222,94 +5268,93 @@ struct *) let pop ( x : fixedpoint ) = - Z3native.fixedpoint_pop x#gnc x#gno + Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) (** Update named rule into in the fixedpoint solver. *) let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = - Z3native.fixedpoint_update_rule x#gnc x#gno rule#gno name#gno + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno name#gno (** Retrieve satisfying instance or instances of solver, or definitions for the recursive predicates that show unsatisfiability. *) let get_answer ( x : fixedpoint ) = - let q = (Z3native.fixedpoint_get_answer x#gnc x#gno) in + let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. *) let get_reason_unknown ( x : fixedpoint ) = - Z3native.fixedpoint_get_reason_unknown x#gnc x#gno + Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) (** Retrieve the number of levels explored for a given predicate. *) let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels x#gnc x#gno predicate#gno + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) predicate#gno (** Retrieve the cover of a predicate. *) let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta x#gnc x#gno level predicate#gno) in + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level predicate#gno) in if (Z3native.is_null q) then None else - Some (create_expr x#gc q) + Some (create_expr (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover x#gnc x#gno level predicate#gno, property#gno + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level predicate#gno property#gno (** Retrieve internal string representation of fixedpoint object. *) - let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string x#gnc x#gno 0 [||] + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = - Z3native.fixedpoint_set_predicate_representation x#gnc x#gno f#gno (Array.length kinds) (symbolaton kinds) + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (symbolaton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string x#gnc x#gno (Array.length queries) (astaton queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (astaton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_rules x#gnc x#gno)) in + let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = ((new ast_vector x#gc)#cnstr_obj (Z3native.fixedpoint_get_assertions x#gnc x#gno)) in + let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = - (new fixedpoint ctx)#cnstr_obj (Z3native.mk_fixedpoint (context_gno ctx)) + let mk_fixedpoint ( ctx : context ) = fixedpoint_cnstr ctx end (** Global and context options From 3347d7ca8c74c21fef3218fb486abfb66810fcd2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 01:15:23 +0000 Subject: [PATCH 408/646] ML API: moved more objects into normal types. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 1 - src/api/ml/z3.ml | 766 +++++++++++++++++++------------------- 2 files changed, 392 insertions(+), 375 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 97985a7bc..38b5fe642 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -14,7 +14,6 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic -open Z3.Fixedpoints exception TestFailedException of string diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 1e8ffe92e..545c7c227 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -20,7 +20,7 @@ let context_dispose ctx = (Z3native.del_context ctx.m_n_ctx) ) else ( Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) + (* re-queue for finalization? *) ) let context_cnstr settings = @@ -38,7 +38,7 @@ let context_cnstr settings = (* CMW: Install error handler here! m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); + GC.SuppressFinalize(this); *) let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) @@ -49,23 +49,23 @@ let context_gno ctx = ctx.m_n_ctx (** Create a context object. -Most interactions with Z3 are interpreted in some context; many users will only -require one such object, but power users may require more than one. To start using -Z3, do + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do - + let ctx = (mk_context []) in (...) - + -where a list of pairs of strings may be passed to set options on -the context, e.g., like so: + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: - + let cfg = [("model", "true"); ("...", "...")] in let ctx = (mk_context cfg) in (...) - + *) let mk_context ( cfg : ( string * string ) list ) = context_cnstr cfg @@ -656,70 +656,6 @@ let tacticaton (a : tactic array) = let f (e : tactic) = e#gno in Array.map f a -(** Function interpretation entry objects *) -class func_entry ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.func_entry_inc_ref nc o - method decref nc o = Z3native.func_entry_dec_ref nc o -end - -(** Function interpretation objects *) -class func_interp ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.func_interp_inc_ref nc o - method decref nc o = Z3native.func_interp_dec_ref nc o -end - -(** Tactic application result objects *) -class apply_result ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.apply_result_inc_ref nc o - method decref nc o = Z3native.apply_result_dec_ref nc o -end - -(** Probe objects *) -class probe ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.probe_inc_ref nc o - method decref nc o = Z3native.probe_dec_ref nc o -end - -(** Statistical value objects *) -class statistics_entry = -object (self) - val mutable m_key : string = "" - val mutable m_is_int = false - val mutable m_is_float = false - val mutable m_int = 0 - val mutable m_float = 0.0 - - method cnstr_si k v = - m_key <- k; - m_is_int <- true; - m_int <- v; - self - - method cnstr_sd k v = - m_key <- k; - m_is_float <- true; - m_float <- v; - self - - method key = m_key - method int = m_int - method float = m_float - method is_int = m_is_int - method is_float = m_is_float -end - type z3_native_object = { m_ctx : context ; @@ -1012,46 +948,46 @@ struct x#rational end - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name domain range + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name domain range - (** - Creates a new function declaration. - *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = + mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range - (** - Creates a fresh function declaration with a name prefixed with . - - - *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix domain range + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix domain range - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name [||] range + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr name [||] range - (** - Creates a new constant function declaration. - *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = + (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix [||] range + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = + (new func_decl ctx)#cnstr_pdr prefix [||] range (** @@ -1333,31 +1269,31 @@ struct else (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) -(** - Wraps an AST. + (** + Wraps an AST. - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. -*) + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create_ast ctx ptr + create_ast ctx ptr -(** - Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. -*) + (** + Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + *) let unwrap_ast ( a : ast ) = a#gno end @@ -1373,17 +1309,17 @@ struct | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) -(** - a string describing all available parameters to Expr.Simplify. -*) + (** + a string describing all available parameters to Expr.Simplify. + *) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) -(** - Retrieves parameter descriptions for simplifier. -*) - let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) + (** + Retrieves parameter descriptions for simplifier. + *) + let get_simplify_parameter_descrs ( ctx : context ) = + (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -2691,7 +2627,7 @@ struct let (r, v) = Z3native.get_numeral_int x#gnc x#gno in if r then v else raise (Z3native.Exception "Conversion failed.") - + (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3202,7 +3138,7 @@ struct let (r, v) = Z3native.get_numeral_int x#gnc x#gno in if r then v else raise (Z3native.Exception "Conversion failed.") - + (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -4150,29 +4086,29 @@ end *) module Params = struct -(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) -module ParamDescrs = -struct + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs = + struct - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size x#gnc x#gno in + let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno -end + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno + end (** Adds a parameter setting. @@ -4353,11 +4289,11 @@ struct type model = z3_native_object (**/**) - let model_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.model_inc_ref ; - dec_ref = Z3native.model_dec_ref } in + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res @@ -4370,6 +4306,18 @@ struct *) module FuncInterp = struct + type func_interp = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_interp = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_interp_inc_ref ; + dec_ref = Z3native.func_interp_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** Function interpretations entries @@ -4377,23 +4325,36 @@ struct *) module FuncEntry = struct + type func_entry = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_entry = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_entry_inc_ref ; + dec_ref = Z3native.func_entry_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno) + create_expr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. *) - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) (** The arguments of the function entry. *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in + let f i = (create_expr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4408,25 +4369,25 @@ struct (** The number of entries in the function interpretation. *) - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) (** The entries in the function interpretation *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in - let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in + let f i = (FuncEntry.cnstr (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno) + let get_else ( x : func_interp ) = create_expr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation *) - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) (** A string representation of the function interpretation. @@ -4486,7 +4447,7 @@ struct | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in - if (Z3native.is_null n) then None else Some ((new func_interp (z3obj_gc x))#cnstr_obj n) + if (Z3native.is_null n) then None else Some (FuncInterp.cnstr (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) @@ -4579,6 +4540,130 @@ struct end +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe = +struct + type probe = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : probe = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.probe_inc_ref ; + dec_ref = Z3native.probe_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** + Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. + *) + let apply ( x : probe ) (g : goal) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) g#gno + + (** + The number of supported Probes. + *) + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes (context_gno ctx) + + (** + The names of all supported Probes. + *) + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in + Array.init n f + + (** + Returns a string containing a description of the probe with the given name. + *) + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr (context_gno ctx) name + + (** + Creates a new Probe. + *) + let mk_probe ( ctx : context ) ( name : string ) = + (cnstr ctx (Z3native.mk_probe (context_gno ctx) name)) + + (** + Create a probe that always evaluates to . + *) + let const ( ctx : context ) ( v : float ) = + (cnstr ctx (Z3native.probe_const (context_gno ctx) v)) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than the value returned by + *) + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than the value returned by + *) + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is less than or equal the value returned by + *) + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is greater than or equal the value returned by + *) + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value returned by + is equal to the value returned by + *) + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + and evaluate to "true". + *) + (* CMW: and is a keyword *) + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + or evaluate to "true". + *) + (* CMW: or is a keyword *) + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (cnstr ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + (** + Create a probe that evaluates to "true" when the value + does not evaluate to "true". + *) + (* CMW: is not a keyword? *) + let not_ ( ctx : context ) ( p : probe ) = + (cnstr ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) +end + + (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. @@ -4588,36 +4673,49 @@ end *) module Tactic = struct -(** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) -module ApplyResult = -struct - (** The number of Subgoals. *) - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals x#gnc x#gno + (** Tactic application results - (** Retrieves the subgoals from the apply_result. *) - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in - Array.init n f - - (** Retrieves the subgoals from the apply_result. *) - let get_subgoal ( x : apply_result ) ( i : int ) = - (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) - - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.model_cnstr x#gc (Z3native.apply_result_convert_model x#gnc x#gno i (z3obj_gno m)) - - (** A string representation of the ApplyResult. *) - let to_string ( x : apply_result ) = Z3native.apply_result_to_string x#gnc x#gno -end + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) + module ApplyResult = + struct + type apply_result = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : apply_result = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.apply_result_inc_ref ; + dec_ref = Z3native.apply_result_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** The number of Subgoals. *) + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** Retrieves the subgoals from the apply_result. *) + let get_subgoal ( x : apply_result ) ( i : int ) = + (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + + (** Convert a model for the subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g + *) + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.cnstr (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + + (** A string representation of the ApplyResult. *) + let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) + end (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno @@ -4630,8 +4728,8 @@ end (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : goal ) ( p : params option ) = match p with - | None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno) - | Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno) + | None -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply x#gnc x#gno g#gno)) + | Some (pn) -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno)) (** The number of supported tactics. @@ -4695,15 +4793,15 @@ end If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) p#gno t#gno) + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) t#gno) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) p#gno t1#gno t2#gno) + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) t1#gno t2#gno) (** Create a tactic that keeps applying until the goal is not @@ -4727,8 +4825,8 @@ end (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) p#gno) + let fail_if ( ctx : context ) ( p : Probe.probe ) = + (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) @@ -4771,124 +4869,14 @@ end Z3native.interrupt (context_gno ctx) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe = -struct - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply x#gnc x#gno g#gno - - (** - The number of supported Probes. - *) - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes (context_gno ctx) - - (** - The names of all supported Probes. - *) - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name (context_gno ctx) i) in - Array.init n f - - (** - Returns a string containing a description of the probe with the given name. - *) - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr (context_gno ctx) name - - (** - Creates a new Probe. - *) - let mk_probe ( ctx : context ) ( name : string ) = - (new probe ctx)#cnstr_obj (Z3native.mk_probe (context_gno ctx) name) - - (** - Create a probe that always evaluates to . - *) - let const ( ctx : context ) ( v : float ) = - (new probe ctx)#cnstr_obj (Z3native.probe_const (context_gno ctx) v) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_lt (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_gt (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_le (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_ge (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_eq (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_and (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_or (context_gno ctx) p1#gno p2#gno) - - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) - let not_ ( ctx : context ) ( p : probe ) = - (new probe ctx)#cnstr_obj (Z3native.probe_not (context_gno ctx) p#gno) -end - (** Solvers *) module Solver = struct type solver = z3_native_object -(**/**) - let solver_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.solver_inc_ref ; @@ -4896,7 +4884,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res -(**/**) + (**/**) type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE @@ -4911,7 +4899,7 @@ struct type statistics = z3_native_object (**/**) - let statistics_cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.stats_inc_ref ; @@ -4919,28 +4907,58 @@ struct (z3obj_sno res ctx no) ; (z3obj_cnstr res) ; res - (**/**) + (**/**) (** - Statistical data is organized into pairs of [Key, Entry], where every - Entry is either a DoubleEntry or a UIntEntry + Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) module Entry = struct + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + + (**/**) + let cnstr_si k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = true ; + m_is_float = false ; + m_int = v ; + m_float = 0.0 + } in + res + + let cnstr_sd k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = false ; + m_is_float = true ; + m_int = 0 ; + m_float = v + } in + res + (**/**) + (** The key of the entry. *) - let get_key (x : statistics_entry) = x#key + let get_key (x : statistics_entry) = x.m_key (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x#int + let get_int (x : statistics_entry) = x.m_int (** The float-value of the entry. *) - let get_float (x : statistics_entry) = x#float + let get_float (x : statistics_entry) = x.m_float (** True if the entry is uint-valued. *) - let is_int (x : statistics_entry) = x#is_int + let is_int (x : statistics_entry) = x.m_is_int (** True if the entry is double-valued. *) - let is_float (x : statistics_entry) = x#is_float + let is_float (x : statistics_entry) = x.m_is_float (** The string representation of the the entry's value. *) let to_string_value (x : statistics_entry) = @@ -4967,9 +4985,9 @@ struct let f i = ( let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - ((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - ((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -5087,7 +5105,7 @@ struct if (Z3native.is_null q) then None else - Some (Model.model_cnstr (z3obj_gc x) q) + Some (Model.cnstr (z3obj_gc x) q) (** The proof of the last Check. @@ -5125,7 +5143,7 @@ struct Solver statistics. *) let get_statistics ( x : solver ) = - (Statistics.statistics_cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + (Statistics.cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -5136,8 +5154,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : symbol option) = match logic with - | None -> (solver_cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (solver_cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) + | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) (** Creates a new (incremental) solver. @@ -5150,7 +5168,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (solver_cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) + (cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -5159,7 +5177,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : tactic ) = - (solver_cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) + (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) (** A string representation of the solver. @@ -5169,12 +5187,12 @@ end (** Fixedpoint solving *) -module Fixedpoints = +module Fixedpoint = struct type fixedpoint = z3_native_object -(**/**) - let fixedpoint_cnstr ( ctx : context ) = + (**/**) + let cnstr ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.fixedpoint_inc_ref ; @@ -5182,7 +5200,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_cnstr res) ; res -(**/**) + (**/**) (** A string that describes all available fixedpoint solver parameters. @@ -5320,7 +5338,7 @@ struct Retrieve internal string representation of fixedpoint object. *) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) @@ -5354,7 +5372,7 @@ struct (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = fixedpoint_cnstr ctx + let mk_fixedpoint ( ctx : context ) = cnstr ctx end (** Global and context options @@ -5365,24 +5383,24 @@ end module Options = struct -(** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - -*) + (** + Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + + *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value -(** - Get a configuration parameter. - - Returns None if the parameter value does not exist. - -*) + (** + Get a configuration parameter. + + Returns None if the parameter value does not exist. + + *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then @@ -5408,12 +5426,12 @@ struct let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) -(** - Enable/disable printing of warning messages to the console. + (** + Enable/disable printing of warning messages to the console. - Note that this function is static and effects the behaviour of - all contexts globally. -*) + Note that this function is static and effects the behaviour of + all contexts globally. + *) let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled end @@ -5581,17 +5599,17 @@ end (* (** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. + A delegate which is executed when an error is raised. + + Note that it is possible for memory leaks to occur if error handlers + throw exceptions. *) - public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); + public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - internal Z3native.error_handler m_n_err_handler = null; + internal Z3native.error_handler m_n_err_handler = null; - internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) + internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. + Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. *) From 1b3e1d1a6c6e18c53cdf8ec893bb52b544a04e8d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 12 Jan 2013 23:18:05 +0000 Subject: [PATCH 409/646] ML API: moved more objects into normal types. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 734 ++++++++++++++++++++++++++--------------------- 1 file changed, 412 insertions(+), 322 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 545c7c227..8c0f24c4b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,13 +7,30 @@ open Z3enums -type context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } - -(**/**) - +(**/**) +(* Some helpers. *) + let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) +let mk_list ( f : int -> 'a ) ( n : int ) = + let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = + if (i >= n) then + tail + else + (mk_list' f (i+1) n ((f i) :: tail)) + in + mk_list' f 0 n [] +(**/**) + + +(**/**) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +(**/**) +type context = z3_native_context + +(**/**) + let context_dispose ctx = if ctx.m_n_obj_cnt == 0 then ( (* Printf.printf "Disposing context \n" ; *) @@ -71,8 +88,6 @@ let mk_context ( cfg : ( string * string ) list ) = context_cnstr cfg -(* type z3object = { m_ctx : context; m_n_obj : Z3native.ptr option; } *) - (**/**) class virtual z3object ctx_init obj_init = object (self) @@ -120,17 +135,6 @@ object (self) method gnc = (context_gno m_ctx) end - -(** Parameter set objects *) -class params ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.params_inc_ref nc o - method decref nc o = Z3native.params_dec_ref nc o -end - - (** Symbol objects *) class symbol ctx = object (self) @@ -292,44 +296,6 @@ let func_declaton (a : func_decl array) = let f (e : func_decl) = e#gno in Array.map f a -class parameter = -object (self) - val mutable m_kind : parameter_kind = PARAMETER_INT; - val mutable m_i : int = 0 - val mutable m_d : float = 0.0 - val mutable m_sym : symbol option = None - val mutable m_srt : sort option = None - val mutable m_ast : ast option = None - val mutable m_fd : func_decl option = None - val mutable m_r : string = "" - - method cnstr_int i = m_kind <- PARAMETER_INT; m_i <- i - method cnstr_double d = m_kind <- PARAMETER_DOUBLE; m_d <- d - method cnstr_symbol sym = m_kind <- PARAMETER_SYMBOL; m_sym <- sym - method cnstr_sort srt = m_kind <- PARAMETER_SORT; m_srt <- srt - method cnstr_ast ast = m_kind <- PARAMETER_AST; m_ast <- ast - method cnstr_func_decl fd = m_kind <- PARAMETER_FUNC_DECL; m_fd <- fd - method cnstr_rational r = m_kind <- PARAMETER_RATIONAL; m_r <- r - - method kind = m_kind - method int = m_i - method double = m_d - method symbol = match m_sym with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter symbol") - method sort = match m_srt with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter sort") - method ast = match m_ast with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter ast") - method func_decl = match m_fd with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing parameter func_decl") - method rational = m_r -end - - (** Enum sort objects *) class enum_sort ctx = object (self) @@ -499,26 +465,6 @@ let create_sort ctx obj = | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") -(** AST vector objects *) -class ast_vector ctx = -object (self) - inherit z3object ctx None - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.ast_vector_inc_ref nc o - method decref nc o = Z3native.ast_vector_dec_ref nc o -end - - -(** AST map objects *) -class ast_map ctx = -object (self) - inherit z3object ctx None - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.ast_map_inc_ref nc o - method decref nc o = Z3native.ast_map_dec_ref nc o -end - - (** Expression objects *) class expr ctx = object(self) @@ -625,37 +571,6 @@ let patternaton (a : pattern array) = let f (e : pattern) = e#gno in Array.map f a -(** Parameter description objects *) -class param_descrs ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.param_descrs_inc_ref nc o - method decref nc o = Z3native.param_descrs_dec_ref nc o -end - -(** Goal objects *) -class goal ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.goal_inc_ref nc o - method decref nc o = Z3native.goal_dec_ref nc o -end - -(** Tactic objects *) -class tactic ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = Z3native.tactic_inc_ref nc o - method decref nc o = Z3native.tactic_dec_ref nc o -end - -let tacticaton (a : tactic array) = - let f (e : tactic) = e#gno in - Array.map f a - type z3_native_object = { m_ctx : context ; @@ -689,6 +604,10 @@ let z3obj_cnstr o = let f = fun o -> (z3obj_dispose o) in Gc.finalise f o +let array_to_native a = + let f e = (z3obj_gno e) in + Array.map f a + (**/**) @@ -890,62 +809,153 @@ let create_ast ctx no = (** Function declarations *) module FuncDecl = struct + (** Parameters of Func_Decls *) module Parameter = struct + type parameter = { + m_kind : parameter_kind ; + m_i : int ; + m_d : float ; + m_sym : symbol option ; + m_srt : sort option ; + m_ast : ast option ; + m_fd : func_decl option ; + m_r : string ; + } + + (**/**) + let cnstr_int i = { + m_kind = PARAMETER_INT ; + m_i = i ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_double d = { + m_kind = PARAMETER_DOUBLE ; + m_i = 0 ; + m_d = d ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_symbol sym = { + m_kind = PARAMETER_SYMBOL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = sym ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_sort srt = { + m_kind = PARAMETER_SORT ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = srt ; + m_ast = None ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_ast ast = { + m_kind = PARAMETER_AST ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = ast ; + m_fd = None ; + m_r = "" ; + } + + let cnstr_func_decl fd ={ + m_kind = PARAMETER_FUNC_DECL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = fd ; + m_r = "" ; + } + + let cnstr_rational r = { + m_kind = PARAMETER_RATIONAL ; + m_i = 0 ; + m_d = 0.0 ; + m_sym = None ; + m_srt = None ; + m_ast = None ; + m_fd = None ; + m_r = r ; + } + (**/**) + (** The kind of the parameter. *) - let get_kind (x : parameter) = x#kind + let get_kind ( x : parameter ) = x.m_kind (**The int value of the parameter.*) - let get_int (x : parameter) = - if (x#kind != PARAMETER_INT) then + let get_int ( x : parameter ) = + if ((get_kind x) != PARAMETER_INT) then raise (Z3native.Exception "parameter is not an int") else - x#int + x.m_i (**The double value of the parameter.*) - let get_double (x : parameter) = - if (x#kind != PARAMETER_DOUBLE) then + let get_double ( x : parameter ) = + if ((get_kind x) != PARAMETER_DOUBLE) then raise (Z3native.Exception "parameter is not a double") else - x#double + x.m_d (**The Symbol value of the parameter.*) - let get_symbol (x : parameter) = - if (x#kind != PARAMETER_SYMBOL) then + let get_symbol ( x : parameter ) = + if ((get_kind x) != PARAMETER_SYMBOL) then raise (Z3native.Exception "parameter is not a symbol") else - x#symbol + x.m_sym (**The Sort value of the parameter.*) - let get_sort (x : parameter) = - if (x#kind != PARAMETER_SORT) then + let get_sort ( x : parameter ) = + if ((get_kind x) != PARAMETER_SORT) then raise (Z3native.Exception "parameter is not a sort") else - x#sort + x.m_srt (**The AST value of the parameter.*) - let get_ast (x : parameter) = - if (x#kind != PARAMETER_AST) then + let get_ast ( x : parameter ) = + if ((get_kind x) != PARAMETER_AST) then raise (Z3native.Exception "parameter is not an ast") else - x#ast + x.m_ast (**The FunctionDeclaration value of the parameter.*) - let get_ast (x : parameter) = - if (x#kind != PARAMETER_FUNC_DECL) then + let get_ast ( x : parameter ) = + if ((get_kind x) != PARAMETER_FUNC_DECL) then raise (Z3native.Exception "parameter is not an function declaration") else - x#func_decl + x.m_fd (**The rational string value of the parameter.*) - let get_rational (x : parameter) = - if (x#kind != PARAMETER_RATIONAL) then + let get_rational ( x : parameter ) = + if ((get_kind x) != PARAMETER_RATIONAL) then raise (Z3native.Exception "parameter is not a ratinoal string") else - x#rational + x.m_r end (** @@ -1051,7 +1061,7 @@ struct The number of parameters of the function declaration *) let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) - + (** The parameters of the function declaration *) @@ -1059,15 +1069,15 @@ struct let n = (get_num_parameters x) in let f i = ( match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with - | PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) - | PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) - | PARAMETER_SORT -> (new parameter)#cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) - | PARAMETER_AST -> (new parameter)#cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) - | PARAMETER_FUNC_DECL -> (new parameter)#cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) - | PARAMETER_RATIONAL -> (new parameter)#cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) + | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) + | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) + | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) + | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) + | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) + | PARAMETER_RATIONAL -> Parameter.cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) ) in - Array.init n f + mk_list f n (** Create expression that applies function to arguments. @@ -1083,9 +1093,22 @@ struct (** Vectors of ASTs *) module ASTVector = struct + type ast_vector = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_vector = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_vector_inc_ref ; + dec_ref = Z3native.ast_vector_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** The size of the vector *) let get_size ( x : ast_vector ) = - Z3native.ast_vector_size x#gnc x#gno + Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) (** Retrieves the i-th object in the vector. @@ -1093,16 +1116,16 @@ struct @return An AST *) let get ( x : ast_vector ) ( i : int ) = - create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i) + create_ast (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set x#gnc x#gno i value#gno + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i value#gno (** Resize the vector to . @param newSize The new size of the vector. *) let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize x#gnc x#gno new_size + Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size (** Add the AST to the back of the vector. The size @@ -1110,7 +1133,7 @@ struct @param a An AST *) let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push x#gnc x#gno a#gno + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) a#gno (** Translates all ASTs in the vector to . @@ -1118,60 +1141,73 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - (new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno (context_gno to_ctx)) + cnstr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string x#gnc x#gno + Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) end (** Map from AST to AST *) module ASTMap = struct + type ast_map = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Checks whether the map contains the key . @param k An AST @return True if is a key in the map, false otherwise. *) - let contains ( m : ast_map ) ( key : ast ) = - (Z3native.ast_map_contains m#gnc m#gno key#gno) + let contains ( x : ast_map ) ( key : ast ) = + (Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) key#gno) (** Finds the value associated with the key . This function signs an error when is not a key in the map. @param k An AST *) - let find ( m : ast_map ) ( key : ast ) = - create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno) + let find ( x : ast_map ) ( key : ast ) = + create_ast (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) key#gno) (** Stores or replaces a new key/value pair in the map. @param k The key AST @param v The value AST *) - let insert ( m : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert m#gnc m#gno key#gno value#gno + let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) key#gno value#gno (** Erases the key from the map. @param k An AST *) - let erase ( m : ast_map ) ( key : ast ) = - Z3native.ast_map_erase m#gnc m#gno key#gno + let erase ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) key#gno (** Removes all keys from the map. *) - let reset ( m : ast_map ) = - Z3native.ast_map_reset m#gnc m#gno + let reset ( x : ast_map ) = + Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) (** The size of the map *) - let get_size ( m : ast_map ) = - Z3native.ast_map_size m#gnc m#gno + let get_size ( x : ast_map ) = + Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) (** The keys stored in the map. *) - let get_keys ( m : ast_map ) = - (new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno) + let get_keys ( x : ast_map ) = + ASTVector.cnstr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) - let to_strnig ( m : ast_map ) = - Z3native.ast_map_to_string m#gnc m#gno + let to_string ( x : ast_map ) = + Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end (** @@ -1297,6 +1333,125 @@ struct let unwrap_ast ( a : ast ) = a#gno end + +(** + Parameter sets (of Solvers, Tactics, ...) + + A Params objects represents a configuration in the form of symbol/value pairs. +*) +module Params = +struct + type params = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs = + struct + type param_descrs = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : param_descrs = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.param_descrs_inc_ref ; + dec_ref = Z3native.param_descrs_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + + (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params ) = + Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) + + (** Retrieve kind of parameter. *) + let get_kind ( x : param_descrs ) ( name : symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) name#gno)) + + (** Retrieve all names of parameters. *) + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in + let f i = create_symbol (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + Array.init n f + + (** The size of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) + + (** Retrieves a string representation of the ParamDescrs. *) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) + end + + (** + Adds a parameter setting. + *) + let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_int ( x : params ) (name : symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_double ( x : params ) ( name : symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) name#gno value + + (** + Adds a parameter setting. + *) + let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) name#gno value#gno + + (** + Adds a parameter setting. + *) + let add_s_bool ( x : params ) ( name : string) ( value : bool ) = + add_bool x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_int ( x : params) ( name : string ) ( value : int ) = + add_int x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_double ( x : params ) ( name : string ) ( value : float ) = + add_double x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Adds a parameter setting. + *) + let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = + add_symbol x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + + (** + Creates a new parameter set + *) + let mk_params ( ctx : context ) = + cnstr ctx (Z3native.mk_params (context_gno ctx)) + + (** + A string representation of the parameter set. + *) + let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) +end + + (** General expressions (terms), including Boolean logic *) module Expr = struct @@ -1305,9 +1460,9 @@ struct @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : params option ) = match p with + let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) - | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno) + | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1319,7 +1474,7 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - (new param_descrs ctx)#cnstr_obj (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.cnstr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. @@ -4079,96 +4234,6 @@ struct let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** - Parameter sets (of Solvers, Tactics, ...) - - A Params objects represents a configuration in the form of symbol/value pairs. -*) -module Params = -struct - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs = - struct - - (** Validate a set of parameters. *) - let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno - - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno)) - - (** Retrieve all names of parameters. *) - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size x#gnc x#gno in - let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in - Array.init n f - - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno - - (** Retrieves a string representation of the ParamDescrs. *) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno - end - - (** - Adds a parameter setting. - *) - let add_bool (p : params) (name : symbol) (value : bool) = - Z3native.params_set_bool p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_int (p : params) (name : symbol) (value : int) = - Z3native.params_set_uint p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_double (p : params) (name : symbol) (value : float) = - Z3native.params_set_double p#gnc p#gno name#gno value - - (** - Adds a parameter setting. - *) - let add_symbol (p : params) (name : symbol) (value : symbol) = - Z3native.params_set_symbol p#gnc p#gno name#gno value#gno - - (** - Adds a parameter setting. - *) - let add_s_bool (p : params) (name : string) (value : bool) = - add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_int (p : params) (name : string) (value : int) = - add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_double (p : params) (name : string) (value : float) = - add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Adds a parameter setting. - *) - let add_s_symbol (p : params) (name : string) (value : symbol) = - add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value - - (** - Creates a new parameter set - *) - let mk_params ( ctx : context ) = - (new params ctx)#cnstr_obj (Z3native.mk_params (context_gno ctx)) - - (** - A string representation of the parameter set. - *) - let to_string (p : params) = Z3native.params_to_string p#gnc p#gno -end (** Goals @@ -4177,6 +4242,18 @@ end tactics and solvers. *) module Goal = struct + type goal = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : goal = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.goal_inc_ref ; + dec_ref = Z3native.goal_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) (** The precision of the goal. @@ -4185,7 +4262,7 @@ struct An over approximation is applied when the objective is to find a proof for a given goal. *) let get_precision ( x : goal ) = - goal_prec_of_int (Z3native.goal_precision x#gnc x#gno) + goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) (** Indicates whether the goal is precise. *) let is_precise ( x : goal ) = @@ -4206,62 +4283,62 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : bool_expr array ) = - let f e = Z3native.goal_assert x#gnc x#gno e#gno in + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) e#gno in ignore (Array.map f constraints) ; () (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = - Z3native.goal_inconsistent x#gnc x#gno + Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) (** The depth of the goal. This tracks how many transformations were applied to it. *) - let get_depth ( x : goal ) = Z3native.goal_depth x#gnc x#gno + let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) (** Erases all formulas from the given goal. *) - let reset ( x : goal ) = Z3native.goal_reset x#gnc x#gno + let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) (** The number of formulas in the goal. *) - let get_size ( x : goal ) = Z3native.goal_size x#gnc x#gno + let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr x#gc)#cnstr_obj (Z3native.goal_formula x#gnc x#gno i) in + let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) - let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs x#gnc x#gno + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = - Z3native.goal_is_decided_sat x#gnc x#gno + Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = - Z3native.goal_is_decided_unsat x#gnc x#gno + Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - (new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno (context_gno to_ctx)) + cnstr to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : params option ) = - let tn = Z3native.mk_tactic x#gnc "simplify" in - Z3native.tactic_inc_ref x#gnc tn ; + let simplify ( x : goal ) ( p : Params.params option ) = + let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in + Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with - | None -> Z3native.tactic_apply x#gnc tn x#gno - | Some(pn) -> Z3native.tactic_apply_ex x#gnc tn x#gno pn#gno + | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) + | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) in - Z3native.apply_result_inc_ref x#gnc arn ; - let sg = Z3native.apply_result_get_num_subgoals x#gnc arn in + Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; + let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in let res = if sg == 0 then raise (Z3native.Exception "No subgoals") else - Z3native.apply_result_get_subgoal x#gnc arn 0 in - Z3native.apply_result_dec_ref x#gnc arn ; - Z3native.tactic_dec_ref x#gnc tn ; - (new goal x#gc)#cnstr_obj res + Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in + Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; + Z3native.tactic_dec_ref (z3obj_gnc x) tn ; + cnstr (z3obj_gc x) res (** @@ -4274,10 +4351,10 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - (new goal ctx)#cnstr_obj (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + cnstr ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) - let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno + let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) end @@ -4326,7 +4403,7 @@ struct module FuncEntry = struct type func_entry = z3_native_object - + (**/**) let cnstr ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; @@ -4528,7 +4605,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n_univ = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4568,8 +4645,8 @@ struct A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : goal) = - Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) g#gno + let apply ( x : probe ) (g : Goal.goal) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** The number of supported Probes. @@ -4673,6 +4750,19 @@ end *) module Tactic = struct + type tactic = z3_native_object + + (**/**) + let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let res : tactic = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.tactic_inc_ref ; + dec_ref = Z3native.tactic_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + (**/**) + (** Tactic application results ApplyResult objects represent the result of an application of a @@ -4699,12 +4789,12 @@ struct (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in - let f i = (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = - (new goal (z3obj_gc x))#cnstr_obj (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. @@ -4718,18 +4808,17 @@ struct end (** A string containing a description of parameters accepted by the tactic. *) - let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno - + let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - (new param_descrs x#gc)#cnstr_obj (Z3native.tactic_get_param_descrs x#gnc x#gno) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with - | None -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply x#gnc x#gno g#gno)) - | Some (pn) -> (ApplyResult.cnstr x#gc (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno)) + | None -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) (** The number of supported tactics. @@ -4755,7 +4844,7 @@ struct Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - (new tactic ctx)#cnstr_obj (Z3native.mk_tactic (context_gno ctx) name) + cnstr ctx (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and @@ -4763,20 +4852,21 @@ struct *) let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = let f p c = (match p with - | None -> (Some c#gno) - | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) c#gno x))) in + | None -> (Some (z3obj_gno c)) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in match (Array.fold_left f None ts) with - | None -> (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno t2#gno) + | None -> + cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> - let o = (Z3native.tactic_and_then (context_gno ctx) t2#gno x) in - (new tactic ctx)#cnstr_obj (Z3native.tactic_and_then (context_gno ctx) t1#gno o) + let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in + cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_or_else (context_gno ctx) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that applies to a goal for milliseconds. @@ -4784,7 +4874,7 @@ struct If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_try_for (context_gno ctx) t#gno ms) + cnstr ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) (** Create a tactic that applies to a given goal if the probe @@ -4794,72 +4884,72 @@ struct *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) t#gno) + cnstr ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_repeat (context_gno ctx) t#gno max) + cnstr ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_skip (context_gno ctx)) + cnstr ctx (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail (context_gno ctx)) + cnstr ctx (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : Probe.probe ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + cnstr ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + cnstr ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_using_params (context_gno ctx) t#gno p#gno) + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + cnstr ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p (** Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (tacticaton t)) + cnstr ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - (new tactic ctx)#cnstr_obj (Z3native.tactic_par_and_then (context_gno ctx) t1#gno t2#gno) + cnstr ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Interrupt the execution of a Z3 procedure. @@ -5015,14 +5105,14 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( value : params )= - Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) value#gno + let set_parameters ( x : solver ) ( p : Params.params )= + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5062,7 +5152,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5070,7 +5160,7 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in Array.init n f @@ -5128,7 +5218,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = (new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5176,8 +5266,8 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : tactic ) = - (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) t#gno)) + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** A string representation of the solver. @@ -5211,14 +5301,14 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : params )= - Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) p#gno + let set_params ( x : fixedpoint ) ( p : Params.params )= + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - (new param_descrs (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. @@ -5355,7 +5445,7 @@ struct Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f @@ -5364,7 +5454,7 @@ struct Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = ((new ast_vector (z3obj_gc x))#cnstr_obj (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in Array.init n f From 8d1413bcc82a52034599f7136f6ddcd342b49b8a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 13 Jan 2013 00:02:38 +0000 Subject: [PATCH 410/646] ML API: Symbols are now normal types with visible hierarchy. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 468 ++++++++++++++++++++++++----------------------- 1 file changed, 241 insertions(+), 227 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8c0f24c4b..378988d59 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -135,39 +135,145 @@ object (self) method gnc = (context_gno m_ctx) end -(** Symbol objects *) -class symbol ctx = -object (self) - inherit z3object ctx None as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method incref nc o = () - method decref nc o = () -end -(** Int symbol objects *) -class int_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol (context_gno ctx) i)) ; self -end -(** String symbol objects *) -class string_symbol ctx = -object(self) - inherit symbol ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol (context_gno ctx) name)) ; self -end +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } -let symbolaton (a : symbol array) = - let f (e : symbol) = e#gno in +let z3obj_gc o = o.m_ctx +let z3obj_gnc o = (context_gno o.m_ctx) + +let z3obj_gno o = o.m_n_obj +let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + +let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + +let z3obj_cnstr o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + +let z3obj_nil_ref x y = () + +let array_to_native a = + let f e = (z3obj_gno e) in Array.map f a +(**/**) -let create_symbol ctx no = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol) - | STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol) + +(** Symbols are used to name several term and type constructors *) +module Symbol = +struct + (** Int symbol objects *) + type int_symbol = z3_native_object + + (** String symbol objects *) + and string_symbol = z3_native_object + + and symbol = + | IntSymbol of int_symbol + | StringSymbol of string_symbol + + (**/**) + let cnstr_i ( ctx : context ) ( no : Z3native.ptr ) = + let res : int_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + let cnstr_s ( ctx : context ) ( no : Z3native.ptr ) = + let res : string_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_cnstr res) ; + res + + let gnc ( x : symbol ) = + match x with + | IntSymbol(n) -> (z3obj_gnc n) + | StringSymbol(n) -> (z3obj_gnc n) + + let gno ( x : symbol ) = + match x with + | IntSymbol(n) -> (z3obj_gno n) + | StringSymbol(n) -> (z3obj_gno n) + + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> IntSymbol (cnstr_i ctx no) + | STRING_SYMBOL -> StringSymbol (cnstr_s ctx no) + + let aton a = + let f e = (gno e) in + Array.map f a + (**/**) + + (** The kind of the symbol (int or string) *) + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) + + (** Indicates whether the symbol is of Int kind *) + let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL + + (** Indicates whether the symbol is of string kind. *) + let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL + + (** The int value of the symbol. *) + let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + + (** The string value of the symbol. *) + let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + + (** A string representation of the symbol. *) + let to_string ( o : symbol ) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) + | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) + + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) + let mk_int ( ctx : context ) ( i : int ) = + IntSymbol (cnstr_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + + (** Creates a new symbol using a string. *) + let mk_string ( ctx : context ) ( s : string ) = + StringSymbol (cnstr_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + + (** Create an array of symbols. *) + let mk_ints ( ctx : context ) ( names : int array ) = + let f elem = mk_int ( ctx : context ) elem in + (Array.map f names) + + (** Create an array of symbols. *) + let mk_strings ( ctx : context ) ( names : string array ) = + let f elem = mk_string ( ctx : context ) elem in + (Array.map f names) +end + +(**/**) (** AST objects *) class ast ctx = @@ -242,7 +348,7 @@ class uninterpreted_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) s#gno)) ; self + method cnstr_s (s : Symbol.symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; self end (** Finite domain sort objects *) @@ -250,7 +356,7 @@ class finite_domain_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) s#gno sz)) ; self + method cnstr_si (s : Symbol.symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno s) sz)) ; self end (** Relation sort objects *) @@ -273,8 +379,8 @@ class tuple_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in + method cnstr_siss (name : Symbol.symbol) (num_fields: int) (field_names : Symbol.symbol array) (field_sorts : sort array) = + let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) num_fields (Symbol.aton field_names) (astaton field_sorts)) in (self#sno ctx x) ; self end @@ -285,7 +391,7 @@ class func_decl ctx = object (self) inherit ast ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) name#gno (Array.length domain) (astaton domain) range#gno)) ; self + method cnstr_ndr (name : Symbol.symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (astaton domain) range#gno)) ; self method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self method incref nc o = super#incref nc o @@ -303,8 +409,8 @@ object (self) val mutable _constdecls : func_decl array option = None val mutable _testerdecls : func_decl array option = None method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (enum_names : symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) name#gno (Array.length enum_names) (symbolaton enum_names)) in + method cnstr_ss (name : Symbol.symbol) (enum_names : Symbol.symbol array) = + let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; (self#sno ctx r) ; @@ -330,8 +436,8 @@ object (self) val mutable _headdecl : func_decl option = None val mutable _taildecl : func_decl option = None method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) name#gno elem_sort#gno) in + method cnstr_ss (name : Symbol.symbol) (elem_sort : sort) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) elem_sort#gno) in _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; @@ -381,7 +487,7 @@ object (self) let v = self in Gc.finalise f v - method cnstr_ssssi (name : symbol) (recognizer : symbol) (field_names : symbol array) (sorts : sort array) (sort_refs : int array) = + method cnstr_ssssi (name : Symbol.symbol) (recognizer : Symbol.symbol) (field_names : Symbol.symbol array) (sorts : sort array) (sort_refs : int array) = m_n <- (Array.length field_names) ; if m_n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -389,7 +495,7 @@ object (self) if m_n != (Array.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else - let o = (Z3native.mk_constructor (context_gno ctx) name#gno recognizer#gno m_n (symbolaton field_names) + let o = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) m_n (Symbol.aton field_names) (sortaton sorts) sort_refs) in self#sno ctx o ; @@ -449,7 +555,7 @@ class datatype_sort ctx = object (self) inherit sort ctx as super method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) name#gno (Array.length constructors) (constructoraton constructors)))) ; self + method cnstr_sc (name : Symbol.symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (constructoraton constructors)))) ; self end let create_sort ctx obj = @@ -571,43 +677,6 @@ let patternaton (a : pattern array) = let f (e : pattern) = e#gno in Array.map f a - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - -let z3obj_gc o = o.m_ctx -let z3obj_gnc o = (context_gno o.m_ctx) - -let z3obj_gno o = o.m_n_obj -let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - -let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - -let z3obj_cnstr o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - -let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a - (**/**) @@ -656,58 +725,6 @@ struct string_of_int rev ^ "." end -(** Symbols are used to name several term and type constructors *) -module Symbol = -struct - (** The kind of the symbol (int or string) *) - let kind (o : symbol) = (symbol_kind_of_int (Z3native.get_symbol_kind o#gnc o#gno)) - - (** Indicates whether the symbol is of Int kind *) - let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL - - (** Indicates whether the symbol is of string kind. *) - let is_string_symbol (o : symbol) = (kind o) == STRING_SYMBOL - - (** The int value of the symbol. *) - let get_int (o : int_symbol) = Z3native.get_symbol_int o#gnc o#gno - - (** The string value of the symbol. *) - let get_string (o : string_symbol) = Z3native.get_symbol_string o#gnc o#gno - - (** A string representation of the symbol. *) - let to_string (o : symbol) = - match (kind o) with - | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno)) - | STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno) - - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) - let mk_int ( ctx : context ) i = - (new int_symbol ctx)#cnstr_int i - - (** Creates a new symbol using a string. *) - let mk_string ( ctx : context ) s = - (new string_symbol ctx)#cnstr_string s - - (** - Create an array of symbols. - *) - let mk_ints ( ctx : context ) ( names : int array ) = - let f elem = mk_int ( ctx : context ) elem in - (Array.map f names) - - (** - Create an array of symbols. - *) - let mk_strings ( ctx : context ) ( names : string array ) = - let f elem = mk_string ( ctx : context ) elem in - (Array.map f names) -end - (** The Sort module implements type information for ASTs *) module Sort = @@ -738,7 +755,7 @@ struct (** The name of the sort *) - let get_name (x : sort) = (create_symbol x#gc (Z3native.get_sort_name x#gnc x#gno)) + let get_name (x : sort) = (Symbol.create x#gc (Z3native.get_sort_name x#gnc x#gno)) (** A string representation of the sort. @@ -754,14 +771,14 @@ struct (** Create a new uninterpreted sort. *) - let mk_uninterpreted ( ctx : context ) (s : symbol) = + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = (new uninterpreted_sort ctx)#cnstr_s s (** Create a new uninterpreted sort. *) - let mk_uninterpreted_s ( ctx : context ) (s : string) = - mk_uninterpreted ctx ((Symbol.mk_string ( ctx : context ) s) :> symbol) + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) end (**/**) @@ -817,7 +834,7 @@ struct m_kind : parameter_kind ; m_i : int ; m_d : float ; - m_sym : symbol option ; + m_sym : Symbol.symbol option ; m_srt : sort option ; m_ast : ast option ; m_fd : func_decl option ; @@ -961,14 +978,14 @@ struct (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort) = (new func_decl ctx)#cnstr_ndr name domain range (** Creates a new function declaration. *) let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range + mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** Creates a fresh function declaration with a name prefixed with . @@ -981,7 +998,7 @@ struct (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort) = (new func_decl ctx)#cnstr_ndr name [||] range @@ -989,7 +1006,7 @@ struct Creates a new constant function declaration. *) let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range + (new func_decl ctx)#cnstr_ndr (Symbol.mk_string ctx name) [||] range (** Creates a fresh constant function declaration with a name prefixed with . @@ -1055,7 +1072,7 @@ struct (** The name of the function declaration *) - let get_name (x : func_decl) = (create_symbol x#gc (Z3native.get_decl_name x#gnc x#gno)) + let get_name (x : func_decl) = (Symbol.create x#gc (Z3native.get_decl_name x#gnc x#gno)) (** The number of parameters of the function declaration @@ -1071,7 +1088,7 @@ struct match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) + | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (Symbol.create x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) @@ -1375,13 +1392,13 @@ struct Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) name#gno)) + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) (** Retrieve all names of parameters. *) let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in - let f i = create_symbol (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The size of the ParamDescrs. *) @@ -1394,50 +1411,50 @@ struct (** Adds a parameter setting. *) - let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = - Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_int ( x : params ) (name : symbol ) ( value : int ) = - Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_double ( x : params ) ( name : symbol ) ( value : float ) = - Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) name#gno value + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = - Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) name#gno value#gno + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) (** Adds a parameter setting. *) - let add_s_bool ( x : params ) ( name : string) ( value : bool ) = - add_bool x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = + add_bool x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + add_int x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + add_double x (Symbol.mk_string (z3obj_gc x) name) value (** Adds a parameter setting. *) - let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = - add_symbol x ((new symbol (z3obj_gc x))#cnstr_obj (Z3native.mk_string_symbol (z3obj_gnc x) name)) value + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + add_symbol x (Symbol.mk_string (z3obj_gc x) name) value (** Creates a new parameter set @@ -1662,15 +1679,15 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const (context_gno ctx) name#gno range#gno) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_expr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) range#gno) (** Creates a new Constant of sort and named . *) let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) range + mk_const ctx (Symbol.mk_string ctx name)range (** @@ -1690,14 +1707,14 @@ struct (** Create a Boolean constant. *) - let mk_bool_const ( ctx : context ) ( name : symbol ) = + let mk_bool_const ( ctx : context ) ( name : Symbol.symbol ) = ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) (** Create a Boolean constant. *) let mk_bool_const_s ( ctx : context ) ( name : string ) = - mk_bool_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_bool_const ctx (Symbol.mk_string ctx name) (** Create a new function application. @@ -1907,7 +1924,7 @@ struct *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + let f i = (Symbol.create x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in Array.init n f (** @@ -1960,7 +1977,7 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1968,23 +1985,23 @@ struct (match weight with | None -> 1 | Some(x) -> x) (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1994,8 +2011,8 @@ struct else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expraton bound_constants) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) @@ -2004,7 +2021,7 @@ struct Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -2012,23 +2029,23 @@ struct (match weight with | None -> 1 | Some(x) -> x) (Array.length patterns) (patternaton patterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) (Array.length sorts) (astaton sorts) - (astaton names) + (Symbol.aton names) body#gno) (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -2038,8 +2055,8 @@ struct else (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> x#gno) - (match skolem_id with | None -> null | Some(x) -> x#gno) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expraton bound_constants) (Array.length patterns) (patternaton patterns) (Array.length nopatterns) (patternaton nopatterns) @@ -2048,7 +2065,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -2058,7 +2075,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2128,14 +2145,14 @@ struct (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) (** Create an array constant. *) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) domain range + mk_const ctx (Symbol.mk_string ctx name) domain range (** Array read. @@ -2307,14 +2324,14 @@ struct (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) size = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) size = (new finite_domain_sort ctx)#cnstr_si name size (** Create a new finite domain sort. *) let mk_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si ((Symbol.mk_string ctx name) :> symbol) size + (new finite_domain_sort ctx)#cnstr_si (Symbol.mk_string ctx name) size (** @@ -2488,7 +2505,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array) = (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs @@ -2502,32 +2519,32 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - mk_constructor ctx ((Symbol.mk_string ctx name) :> symbol) recognizer field_names sorts sort_refs + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : constructor array) = (new datatype_sort ctx)#cnstr_sc name constructors (** Create a new datatype sort. *) let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = - mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) constructors + mk_sort ctx (Symbol.mk_string ctx name) constructors (** Create mutually recursive datatypes. @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : constructor array array ) = let n = (Array.length names) in let f e = ( (new constructor_list ctx)#cnstr_ca e ) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (symbolaton names) (constructor_listaton cla)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (constructor_listaton cla)) in let g e = ( (new datatype_sort ctx)#cnstr_obj e) in (Array.map g r) @@ -2535,7 +2552,7 @@ struct let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = mk_sorts ctx ( - let f e = ((Symbol.mk_string ctx e) :> symbol) in + let f e = (Symbol.mk_string ctx e) in Array.map f names ) c @@ -2581,10 +2598,8 @@ struct *) let mk_sort_s ( ctx : context ) name enum_names = (new enum_sort ctx)#cnstr_ss - ((Symbol.mk_string ( ctx : context ) name) :> symbol) - (let f e = (e :> symbol) in - (Array.map f (Symbol.mk_strings ( ctx : context ) enum_names)) - ) + (Symbol.mk_string ctx name) + (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) let get_const_decls (x : enum_sort) = x#const_decls @@ -2599,15 +2614,14 @@ struct (** Create a new list sort. *) - let mk_sort ( ctx : context ) (name : symbol) elem_sort = + let mk_sort ( ctx : context ) (name : Symbol.symbol) elem_sort = (new list_sort ctx)#cnstr_ss name elem_sort (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = - mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) elem_sort - + mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) let get_nil_decl (x : list_sort) = x#nil_decl @@ -2805,26 +2819,26 @@ struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : symbol ) = + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) (** Creates an integer constant. *) let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_int_const ctx (Symbol.mk_string ctx name) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : symbol ) = + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) (** Creates a real constant. *) let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx ((Symbol.mk_string ctx name) :> symbol) + mk_real_const ctx (Symbol.mk_string ctx name) (** Create an expression representing t[0] + t[1] + .... @@ -3300,14 +3314,14 @@ struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) (** Creates a bit-vector constant. *) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_const ctx ((Symbol.mk_string ctx name) :> symbol) size + mk_const ctx (Symbol.mk_string ctx name) size (** Bitwise negation. @@ -5242,17 +5256,17 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : symbol option) = + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) x#gno)) + | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) (** Creates a new (incremental) solver. *) let mk_solver_s ( ctx : context ) ( logic : string ) = - mk_solver ctx (Some ((Symbol.mk_string ctx logic) :> symbol)) + mk_solver ctx (Some (Symbol.mk_string ctx logic)) (** Creates a new (incremental) solver. @@ -5327,10 +5341,10 @@ struct (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno y#gno + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno y) (** Add table fact to the fixedpoint solver. @@ -5381,8 +5395,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno name#gno + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5432,8 +5446,8 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (symbolaton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (Symbol.aton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. @@ -5554,7 +5568,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5564,17 +5578,17 @@ struct else Z3native.parse_smtlib_string (context_gno ctx) str cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5584,10 +5598,10 @@ struct else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** @@ -5649,7 +5663,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5659,17 +5673,17 @@ struct else Z3native.parse_smtlib2_string (context_gno ctx) str cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5679,10 +5693,10 @@ struct else Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (symbolaton sort_names) + (Symbol.aton sort_names) (astaton sorts) cd - (symbolaton decl_names) + (Symbol.aton decl_names) (func_declaton decls) end From 9ed926498f424871e8dd8ab06f0d3d4d2f166b8c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Jan 2013 11:37:39 +0000 Subject: [PATCH 411/646] ML API: updated example Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 38b5fe642..3b13a2462 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -22,8 +22,8 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = ((mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_real_sort ctx )) :> arith_expr) in - let yr = ((mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_real_sort ctx )) :> arith_expr) in + let xr = ((mk_const ctx (Symbol.mk_string ctx "x") (mk_real_sort ctx )) :> arith_expr) in + let yr = ((mk_const ctx (Symbol.mk_string ctx "y") (mk_real_sort ctx )) :> arith_expr) in let g4 = (mk_goal ctx true false false ) in (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; @@ -68,9 +68,9 @@ let model_converter_test ( ctx : context ) = let basic_tests ( ctx : context ) = Printf.printf "BasicTests\n" ; let qi = (mk_int ctx 1) in - let fname = ((mk_string ctx "f") :> symbol) in - let x = ((mk_string ctx "x") :> symbol) in - let y = ((mk_string ctx "y") :> symbol) in + let fname = (mk_string ctx "f") in + let x = (mk_string ctx "x") in + let y = (mk_string ctx "y") in let bs = (Sort.mk_bool ctx) in let domain = [| bs; bs |] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in @@ -142,8 +142,8 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (mk_const ctx ((Symbol.mk_string ctx "x") :> symbol) (mk_int_sort ctx)) in - let yc = (mk_const ctx ((Symbol.mk_string ctx "y") :> symbol) (mk_int_sort ctx)) in + let xc = (mk_const ctx (Symbol.mk_string ctx "x") (mk_int_sort ctx)) in + let yc = (mk_const ctx (Symbol.mk_string ctx "y") (mk_int_sort ctx)) in (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; let constr = (mk_eq ctx xc yc) in @@ -211,8 +211,8 @@ let _ = let bs = (Sort.mk_bool ctx) in let ints = (mk_int_sort ctx) in let rs = (mk_real_sort ctx) in - Printf.printf "int symbol: %s\n" (Symbol.to_string (is :> symbol)); - Printf.printf "string symbol: %s\n" (Symbol.to_string (ss :> symbol)); + Printf.printf "int symbol: %s\n" (Symbol.to_string is); + Printf.printf "string symbol: %s\n" (Symbol.to_string ss); Printf.printf "bool sort: %s\n" (Sort.to_string bs); Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); From b895d4c8269343216022d0f9bc7103c4f9ce75b2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Jan 2013 17:51:16 +0000 Subject: [PATCH 412/646] ML API: added functions for global parameter management. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 378988d59..0dfb173c4 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -5700,6 +5700,53 @@ struct (func_declaton decls) end + +(* Global functions *) + +(** + * Set a global (or module) parameter, which is shared by all Z3 contexts. + * + * When a Z3 module is initialized it will use the value of these parameters + * when Z3_params objects are not provided. + * The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + * The character '.' is a delimiter (more later). + * The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + * Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + * This function can be used to set parameters for a specific Z3 module. + * This can be done by using .. + * For example: + * (set_global_param "pp.decimal" "true") + * will set the parameter "decimal" in the module "pp" to true. +*) +let set_global_param ( id : string ) ( value : string ) = + (Z3native.global_param_set id value) + +(** + * Get a global (or module) parameter. + * + * Returns None if the parameter does not exist. + * The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + * This function cannot be invoked simultaneously from different threads without synchronization. + * The result string stored in param_value is stored in a shared location. +*) +let get_global_param ( id : string ) = + let (r, v) = (Z3native.global_param_get id) in + if not r then + None + else + Some v + +(** + * Restore the value of all global (and module) parameters. + * + * This command will not affect already created objects (such as tactics and solvers) + * +*) +let global_param_reset_all = + Z3native.global_param_reset_all + + + (* (** From 3a0af6d15fc7591594cb0aeed5a3eb9e1f2b6a40 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 17 Jan 2013 19:47:51 +0000 Subject: [PATCH 413/646] ML API: Added Solver.assert_and_track Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0dfb173c4..f5c3e3d82 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -5159,8 +5159,42 @@ struct *) let assert_ ( x : solver ) ( constraints : bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in - ignore (Array.map f constraints) ; - () + ignore (Array.map f constraints) + + (** + * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + *) + let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + if ((Array.length cs) != (Array.length ps)) then + raise (Z3native.Exception "Argument size mismatch") + else + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) e#gno (Array.get ps i)#gno) in + ignore (Array.iteri f cs) + + (** + * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + *) + let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) c#gno p#gno (** The number of assertions in the solver. From 364954e25a0c1495570bbf9c319d501d751d8555 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 31 Jan 2013 12:51:31 +0000 Subject: [PATCH 414/646] ML build Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index befd78be6..1d3412c30 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1345,31 +1345,30 @@ class MLComponent(Component): src_dir = self.to_src_dir sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) + api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - out.write('libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s api/ml/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, get_component(API_COMPONENT).to_src_dir)) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') - out.write('\tcd %s && %s ' % (sub_dir, OCAMLOPT)) + out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3" z3native.c z3enums.ml z3native.ml z3.ml -a -o ../../z3.cmxa -linkall && popd\n' % get_component(API_COMPONENT).to_src_dir) - out.write('z3.cma:') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cmxa -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) - out.write('api/ml/z3.cma: libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') - out.write('\tcd %s && %s ' % (sub_dir, OCAMLC)) + out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" z3enums.ml z3native.ml z3.ml -a -o z3.cma -linkall && cd ../..\n' % get_component(API_COMPONENT).to_src_dir) + out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') From 313ccfbe8de02d0ed61b9330012f6b43ffb2b327 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Feb 2013 21:18:25 +0000 Subject: [PATCH 415/646] Checkpoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2989 ++++++++++++++++++++++++---------------------- 1 file changed, 1544 insertions(+), 1445 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f5c3e3d82..0e47912ae 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,6 +7,51 @@ open Z3enums +(** Interaction logging for Z3 + + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log = +struct + (** Open an interaction log file. + @param filename the name of the file to open. + @return True if opening the log file succeeds, false otherwise. + *) + (* CMW: "open" seems to be a reserved keyword? *) + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) + + (** Closes the interaction log. *) + let close = Z3native.close_log + + (** Appends a user-provided string to the interaction log. + @param s the string to append*) + let append s = Z3native.append_log s +end + +(** Version information *) +module Version = +struct + (** The major version. *) + let major = let (x, _, _, _) = Z3native.get_version in x + + (** The minor version. *) + let minor = let (_, x, _, _) = Z3native.get_version in x + + (** The build version. *) + let build = let (_, _, x, _) = Z3native.get_version in x + + (** The revision. *) + let revision = let (_, _, _, x) = Z3native.get_version in x + + (** A string representation of the version information. *) + let to_string = + let (mj, mn, bld, rev) = Z3native.get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + (**/**) (* Some helpers. *) @@ -40,7 +85,7 @@ let context_dispose ctx = (* re-queue for finalization? *) ) -let context_cnstr settings = +let context_create settings = let cfg = Z3native.mk_config in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; @@ -85,7 +130,7 @@ let context_gno ctx = ctx.m_n_ctx *) let mk_context ( cfg : ( string * string ) list ) = - context_cnstr cfg + context_create cfg (**/**) @@ -165,7 +210,7 @@ let z3obj_dispose o = ) ; o.m_n_obj <- null -let z3obj_cnstr o = +let z3obj_create o = let f = fun o -> (z3obj_dispose o) in Gc.finalise f o @@ -184,44 +229,51 @@ struct type int_symbol = z3_native_object (** String symbol objects *) - and string_symbol = z3_native_object + type string_symbol = z3_native_object - and symbol = - | IntSymbol of int_symbol - | StringSymbol of string_symbol + (** Symbol Objects *) + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol (**/**) - let cnstr_i ( ctx : context ) ( no : Z3native.ptr ) = + let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res - let cnstr_s ( ctx : context ) ( no : Z3native.ptr ) = + + let create_s ( ctx : context ) ( no : Z3native.ptr ) = let res : string_symbol = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res + + let gc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gc n) + | S_Str(n) -> (z3obj_gc n) let gnc ( x : symbol ) = match x with - | IntSymbol(n) -> (z3obj_gnc n) - | StringSymbol(n) -> (z3obj_gnc n) + | S_Int(n) -> (z3obj_gnc n) + | S_Str(n) -> (z3obj_gnc n) let gno ( x : symbol ) = match x with - | IntSymbol(n) -> (z3obj_gno n) - | StringSymbol(n) -> (z3obj_gno n) + | S_Int(n) -> (z3obj_gno n) + | S_Str(n) -> (z3obj_gno n) let create ( ctx : context ) ( no : Z3native.ptr ) = match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> IntSymbol (cnstr_i ctx no) - | STRING_SYMBOL -> StringSymbol (cnstr_s ctx no) + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) let aton a = let f e = (gno e) in @@ -256,11 +308,11 @@ struct The legal range of unsigned integers is 0 to 2^30-1. *) let mk_int ( ctx : context ) ( i : int ) = - IntSymbol (cnstr_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) (** Creates a new symbol using a string. *) let mk_string ( ctx : context ) ( s : string ) = - StringSymbol (cnstr_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) (** Create an array of symbols. *) let mk_ints ( ctx : context ) ( names : int array ) = @@ -273,853 +325,47 @@ struct (Array.map f names) end -(**/**) - -(** AST objects *) -class ast ctx = -object (self) - inherit z3object ctx None as super (* CMW: derive from icomparable? *) - method cnstr_obj obj = (self#sno ctx obj) ; self - - method incref nc o = Z3native.inc_ref nc o - method decref nc o = Z3native.dec_ref nc o -end - -let astaton (a : ast array) = - let f (e : ast) = e#gno in - Array.map f a - -(** Sort objects *) -class sort ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let sortaton (a : sort array) = - let f (e : sort) = e#gno in - Array.map f a - -(** Arithmetic sort objects, i.e., Int or Real. *) -class arith_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Array sorts objects *) -class array_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort (context_gno ctx) domain#gno range#gno)) ; self -end - -(** Bit-vector sort objects *) -class bitvec_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Boolean sort objects *) -class bool_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Int sort objects *) -class int_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Real sort objects *) -class real_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Uninterpreted sort objects *) -class uninterpreted_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : Symbol.symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; self -end - -(** Finite domain sort objects *) -class finite_domain_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_si (s : Symbol.symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno s) sz)) ; self -end - -(** Relation sort objects *) -class relation_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Set sort objects *) -class set_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_s (s : sort) = (self#sno ctx s#gno) ; self -end - -(** Tuple sort objects *) -class tuple_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_siss (name : Symbol.symbol) (num_fields: int) (field_names : Symbol.symbol array) (field_sorts : sort array) = - let (x,_,_) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) num_fields (Symbol.aton field_names) (astaton field_sorts)) in - (self#sno ctx x) ; - self -end - - -(** Function declaration objects *) -class func_decl ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ndr (name : Symbol.symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (astaton domain) range#gno)) ; self - method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (astaton domain) range#gno)) ; self - - method incref nc o = super#incref nc o - method decref nc o = super#decref nc o -end - -let func_declaton (a : func_decl array) = - let f (e : func_decl) = e#gno in - Array.map f a - -(** Enum sort objects *) -class enum_sort ctx = -object (self) - inherit sort ctx as super - val mutable _constdecls : func_decl array option = None - val mutable _testerdecls : func_decl array option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : Symbol.symbol) (enum_names : Symbol.symbol array) = - let (r, a, b) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in - _constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ; - _testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ; - (self#sno ctx r) ; - self - - method const_decls = match _constdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing const decls") - - method tester_decls = match _testerdecls with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tester decls") -end - -(** List sort objects *) -class list_sort ctx = -object (self) - inherit sort ctx as super - val mutable _nildecl : func_decl option = None - val mutable _is_nildecl : func_decl option = None - val mutable _consdecl : func_decl option = None - val mutable _is_consdecl : func_decl option = None - val mutable _headdecl : func_decl option = None - val mutable _taildecl : func_decl option = None - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ss (name : Symbol.symbol) (elem_sort : sort) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) elem_sort#gno) in - _nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ; - _is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ; - _consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ; - _is_consdecl <- Some ((new func_decl ctx)#cnstr_obj d) ; - _headdecl <- Some ((new func_decl ctx)#cnstr_obj e) ; - _taildecl <- Some ((new func_decl ctx)#cnstr_obj f) ; - (self#sno ctx r) ; - self - - method nil_decl = match _nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing nil decl") - - method is_nil_decl = match _is_nildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_nil decl") - - method cons_decl = match _consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing cons decl") - - method is_cons_decl = match _is_consdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing is_cons decl") - - method head_decl = match _headdecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing head decl") - - method tail_decl = match _taildecl with - | Some(x) -> x - | None -> raise (Z3native.Exception "Missing tail decl") -end - -(** Constructor objects *) -class constructor ctx = -object (self) - inherit z3object ctx None as super - val mutable m_n : int = 0 - val mutable m_tester_decl : func_decl option = None - val mutable m_constructor_decl : func_decl option = None - val mutable m_accessor_decls : func_decl array option = None - method incref nc o = () - method decref nc o = () - initializer - let f = fun o -> Z3native.del_constructor o#gnc o#gno in - let v = self in - Gc.finalise f v - - method cnstr_ssssi (name : Symbol.symbol) (recognizer : Symbol.symbol) (field_names : Symbol.symbol array) (sorts : sort array) (sort_refs : int array) = - m_n <- (Array.length field_names) ; - if m_n != (Array.length sorts) then - raise (Z3native.Exception "Number of field names does not match number of sorts") - else - if m_n != (Array.length sort_refs) then - raise (Z3native.Exception "Number of field names does not match number of sort refs") - else - let o = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) m_n (Symbol.aton field_names) - (sortaton sorts) - sort_refs) in - self#sno ctx o ; - self - - method private init = - match m_tester_decl with - | None -> - let (a, b, c) = (Z3native.query_constructor self#gnc self#gno m_n) in - m_constructor_decl <- Some ((new func_decl ctx)#cnstr_obj a) ; - m_tester_decl <- Some ((new func_decl ctx)#cnstr_obj b) ; - m_accessor_decls <- Some (let f e = ((new func_decl ctx)#cnstr_obj e) in Array.map f c) ; - () - | _ -> () - - method get_n = m_n - - method tester_decl = match m_tester_decl with - | Some(x) -> x - | None -> self#init ; self#tester_decl - - method constructor_decl = match m_constructor_decl with - | Some(x) -> x - | None -> self#init ; self#constructor_decl - - method accessor_decls = match m_accessor_decls with - | Some(x) -> x - | None -> self#init ; self#accessor_decls -end - -let constructoraton (a : constructor array) = - let f (e : constructor) = e#gno in - Array.map f a - -(** Constructor list objects *) -class constructor_list ctx = -object (self) - inherit z3object ctx None - method incref nc o = () - method decref nc o = () - initializer - let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in - let v = self in - Gc.finalise f v - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_ca ( c : constructor array ) = - self#sno ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (constructoraton c)) ; - self -end - -let constructor_listaton (a : constructor_list array) = - let f (e : constructor_list) = e#gno in - Array.map f a - -(** Datatype sort objects *) -class datatype_sort ctx = -object (self) - inherit sort ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self - method cnstr_sc (name : Symbol.symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (constructoraton constructors)))) ; self -end - -let create_sort ctx obj = - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) obj)) with - | ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort) - | BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort) - | BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort) - | DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort) - | INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort) - | REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort) - | UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort) - | FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort) - | RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - -(** Expression objects *) -class expr ctx = -object(self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let expraton (a : expr array) = - let f (e : expr) = e#gno in - Array.map f a - -(** Boolean expression objects *) -class bool_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Arithmetic expression objects (int/real) *) -class arith_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Int expression objects *) -class int_expr ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Real expression objects *) -class real_expr ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Bit-vector expression objects *) -class bitvec_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Array expression objects *) -class array_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Datatype expression objects *) -class datatype_expr ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Integer numeral expression objects *) -class int_num ctx = -object (self) - inherit int_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Rational numeral expression objects *) -class rat_num ctx = -object (self) - inherit real_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Bit-vector numeral expression objects *) -class bitvec_num ctx = -object (self) - inherit bitvec_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Algebraic numeral expression objects *) -class algebraic_num ctx = -object (self) - inherit arith_expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Quantifier objects *) -class quantifier ctx = -object (self) - inherit expr ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -(** Quantifier pattern objects *) -class pattern ctx = -object (self) - inherit ast ctx as super - method cnstr_obj obj = (self#sno ctx obj) ; self -end - -let patternaton (a : pattern array) = - let f (e : pattern) = e#gno in - Array.map f a - -(**/**) - - -(** Interaction logging for Z3 - - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) -module Log = -struct - (** Open an interaction log file. - @param filename the name of the file to open. - @return True if opening the log file succeeds, false otherwise. - *) - (* CMW: "open" seems to be a reserved keyword? *) - let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - - (** Closes the interaction log. *) - let close = Z3native.close_log - - (** Appends a user-provided string to the interaction log. - @param s the string to append*) - let append s = Z3native.append_log s -end - -(** Version information *) -module Version = -struct - (** The major version. *) - let major = let (x, _, _, _) = Z3native.get_version in x - - (** The minor version. *) - let minor = let (_, x, _, _) = Z3native.get_version in x - - (** The build version. *) - let build = let (_, _, x, _) = Z3native.get_version in x - - (** The revision. *) - let revision = let (_, _, _, x) = Z3native.get_version in x - - (** A string representation of the version information. *) - let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end - - -(** The Sort module implements type information for ASTs *) -module Sort = -struct - (** - Comparison operator. - @param a A sort - @param b A sort - @return True if and are from the same context - and represent the same sort; false otherwise. - *) - let ( = ) (a : sort) (b : sort) = (a == b) || - if a#gnc != b#gnc then - false - else - (Z3native.is_eq_sort a#gnc a#gno b#gno) - - (** - Returns a unique identifier for the sort. - *) - let get_id (x : sort) = Z3native.get_sort_id x#gnc x#gno - - (** - The kind of the sort. - *) - let get_sort_kind (x : sort) = (sort_kind_of_int (Z3native.get_sort_kind x#gnc x#gno)) - - (** - The name of the sort - *) - let get_name (x : sort) = (Symbol.create x#gc (Z3native.get_sort_name x#gnc x#gno)) - - (** - A string representation of the sort. - *) - let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno - - (** - Create a new Boolean sort. - *) - let mk_bool ( ctx : context ) = - (new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort (context_gno ctx)) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = - (new uninterpreted_sort ctx)#cnstr_s s - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted_s ( ctx : context ) ( s : string ) = - mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) -end - -(**/**) -let create_expr ctx obj = - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then - (((new quantifier ctx)#cnstr_obj obj) :> expr) - else - let s = Z3native.get_sort (context_gno ctx) obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (((new algebraic_num ctx)#cnstr_obj obj) :> expr) - else - if (Z3native.is_numeral_ast (context_gno ctx) obj) && - (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - match sk with - | INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr) - | REAL_SORT -> (((new rat_num ctx)#cnstr_obj obj) :> expr) - | BV_SORT -> (((new bitvec_num ctx)#cnstr_obj obj) :> expr) - | _ -> raise (Z3native.Exception "Unsupported numeral object") - else - match sk with - | BOOL_SORT -> (((new bool_expr ctx)#cnstr_obj obj) :> expr) - | INT_SORT -> (((new int_expr ctx)#cnstr_obj obj) :> expr) - | REAL_SORT -> (((new real_expr ctx)#cnstr_obj obj) :> expr) - | BV_SORT -> (((new bitvec_expr ctx)#cnstr_obj obj) :> expr) - | ARRAY_SORT -> (((new array_expr ctx)#cnstr_obj obj) :> expr) - | DATATYPE_SORT -> (((new datatype_expr ctx)#cnstr_obj obj) :> expr) - | _ -> (new expr ctx)#cnstr_obj obj - -let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) = - let o = Z3native.mk_app (context_gno ctx) f#gno (Array.length args) (astaton args) in - create_expr ctx o - -let create_ast ctx no = - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast) - | QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast) - | SORT_AST -> ((create_sort ctx no) :> ast) - | APP_AST - | NUMERAL_AST - | VAR_AST -> ((create_expr ctx no) :> ast) - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") -(**/**) - -(** Function declarations *) -module FuncDecl = -struct - - (** Parameters of Func_Decls *) - module Parameter = - struct - type parameter = { - m_kind : parameter_kind ; - m_i : int ; - m_d : float ; - m_sym : Symbol.symbol option ; - m_srt : sort option ; - m_ast : ast option ; - m_fd : func_decl option ; - m_r : string ; - } - - (**/**) - let cnstr_int i = { - m_kind = PARAMETER_INT ; - m_i = i ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_double d = { - m_kind = PARAMETER_DOUBLE ; - m_i = 0 ; - m_d = d ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_symbol sym = { - m_kind = PARAMETER_SYMBOL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = sym ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_sort srt = { - m_kind = PARAMETER_SORT ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = srt ; - m_ast = None ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_ast ast = { - m_kind = PARAMETER_AST ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = ast ; - m_fd = None ; - m_r = "" ; - } - - let cnstr_func_decl fd ={ - m_kind = PARAMETER_FUNC_DECL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = fd ; - m_r = "" ; - } - - let cnstr_rational r = { - m_kind = PARAMETER_RATIONAL ; - m_i = 0 ; - m_d = 0.0 ; - m_sym = None ; - m_srt = None ; - m_ast = None ; - m_fd = None ; - m_r = r ; - } - (**/**) - - (** - The kind of the parameter. - *) - let get_kind ( x : parameter ) = x.m_kind - - (**The int value of the parameter.*) - let get_int ( x : parameter ) = - if ((get_kind x) != PARAMETER_INT) then - raise (Z3native.Exception "parameter is not an int") - else - x.m_i - - (**The double value of the parameter.*) - let get_double ( x : parameter ) = - if ((get_kind x) != PARAMETER_DOUBLE) then - raise (Z3native.Exception "parameter is not a double") - else - x.m_d - - (**The Symbol value of the parameter.*) - let get_symbol ( x : parameter ) = - if ((get_kind x) != PARAMETER_SYMBOL) then - raise (Z3native.Exception "parameter is not a symbol") - else - x.m_sym - - (**The Sort value of the parameter.*) - let get_sort ( x : parameter ) = - if ((get_kind x) != PARAMETER_SORT) then - raise (Z3native.Exception "parameter is not a sort") - else - x.m_srt - - (**The AST value of the parameter.*) - let get_ast ( x : parameter ) = - if ((get_kind x) != PARAMETER_AST) then - raise (Z3native.Exception "parameter is not an ast") - else - x.m_ast - - (**The FunctionDeclaration value of the parameter.*) - let get_ast ( x : parameter ) = - if ((get_kind x) != PARAMETER_FUNC_DECL) then - raise (Z3native.Exception "parameter is not an function declaration") - else - x.m_fd - - (**The rational string value of the parameter.*) - let get_rational ( x : parameter ) = - if ((get_kind x) != PARAMETER_RATIONAL) then - raise (Z3native.Exception "parameter is not a ratinoal string") - else - x.m_r - end - - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name domain range - - (** - Creates a new function declaration. - *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) = - mk_func_decl ctx (Symbol.mk_string ctx name) domain range - - (** - Creates a fresh function declaration with a name prefixed with . - - - *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix domain range - - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr name [||] range - - - (** - Creates a new constant function declaration. - *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) = - (new func_decl ctx)#cnstr_ndr (Symbol.mk_string ctx name) [||] range - - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) = - (new func_decl ctx)#cnstr_pdr prefix [||] range - - - (** - Comparison operator. - @param a A func_decl - @param b A func_decl - @return True if and are from the same context - and represent the same func_decl; false otherwise. - *) - let ( = ) (a : func_decl) (b : func_decl) = (a == b) || - if a#gnc == a#gnc then - false - else - (Z3native.is_eq_func_decl a#gnc a#gno b#gno) - (** - A string representations of the function declaration. - *) - let to_string (x : func_decl) = Z3native.func_decl_to_string x#gnc x#gno - - (** - Returns a unique identifier for the function declaration. - *) - let get_id (x : func_decl) = Z3native.get_func_decl_id x#gnc x#gno - - (** - The arity of the function declaration - *) - let get_arity (x : func_decl) = Z3native.get_arity x#gnc x#gno - - (** - The size of the domain of the function declaration - - *) - let get_domain_size (x : func_decl) = Z3native.get_domain_size x#gnc x#gno - - (** - The domain of the function declaration - *) - let get_domain (x : func_decl) = - let n = (get_domain_size x) in - let f i = create_sort x#gc (Z3native.get_domain x#gnc x#gno i) in - Array.init n f - - (** - The range of the function declaration - *) - let get_range (x : func_decl) = - create_sort x#gc (Z3native.get_range x#gnc x#gno) - - (** - The kind of the function declaration. - *) - let get_decl_kind (x : func_decl) = (decl_kind_of_int (Z3native.get_decl_kind x#gnc x#gno)) - - (** - The name of the function declaration - *) - let get_name (x : func_decl) = (Symbol.create x#gc (Z3native.get_decl_name x#gnc x#gno)) - - (** - The number of parameters of the function declaration - *) - let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno) - - (** - The parameters of the function declaration - *) - let get_parameters (x : func_decl) = - let n = (get_num_parameters x) in - let f i = ( - match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with - | PARAMETER_INT -> Parameter.cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i) - | PARAMETER_DOUBLE -> Parameter.cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i) - | PARAMETER_SYMBOL-> Parameter.cnstr_symbol (Some (Symbol.create x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i))) - | PARAMETER_SORT -> Parameter.cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i))) - | PARAMETER_AST -> Parameter.cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i))) - | PARAMETER_FUNC_DECL -> Parameter.cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i))) - | PARAMETER_RATIONAL -> Parameter.cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i) - ) in - mk_list f n - - (** - Create expression that applies function to arguments. - @param args The arguments - *) - let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args - -end (** The abstract syntax tree (AST) module *) -module AST = -struct +module rec AST : +sig + type ast = z3_native_object + + val create : context -> Z3native.ptr -> ast + val aton : ast array -> Z3native.ptr array + + val is_expr : ast -> bool + val is_var : ast -> bool +end = struct + type ast = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let aton (a : ast array) = + let f (e : ast) = (z3obj_gno e) in + Array.map f a + + (** Vectors of ASTs *) module ASTVector = struct type ast_vector = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; dec_ref = Z3native.ast_vector_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1133,11 +379,11 @@ struct @return An AST *) let get ( x : ast_vector ) ( i : int ) = - create_ast (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + create (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i value#gno + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) (** Resize the vector to . @param newSize The new size of the vector. *) @@ -1150,7 +396,7 @@ struct @param a An AST *) let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) a#gno + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) (** Translates all ASTs in the vector to . @@ -1158,7 +404,7 @@ struct @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = - cnstr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = @@ -1171,13 +417,13 @@ struct type ast_map = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_map_inc_ref ; dec_ref = Z3native.ast_map_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1185,7 +431,7 @@ struct @param k An AST @return True if is a key in the map, false otherwise. *) let contains ( x : ast_map ) ( key : ast ) = - (Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) key#gno) + Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (** Finds the value associated with the key . @@ -1193,7 +439,7 @@ struct @param k An AST *) let find ( x : ast_map ) ( key : ast ) = - create_ast (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) key#gno) + create (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) (** Stores or replaces a new key/value pair in the map. @@ -1201,14 +447,14 @@ struct @param v The value AST *) let insert ( x : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) key#gno value#gno + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) (** Erases the key from the map. @param k An AST *) let erase ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) key#gno + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (** Removes all keys from the map. *) let reset ( x : ast_map ) = @@ -1220,7 +466,7 @@ struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.cnstr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -1231,23 +477,23 @@ struct The AST's hash code. @return A hash code *) - let get_hash_code ( x : ast) = Z3native.get_ast_hash x#gnc x#gno + let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) (** A unique identifier for the AST (unique among all ASTs). *) - let get_id ( x : ast) = Z3native.get_ast_id x#gnc x#gno + let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) (** The kind of the AST. *) - let get_ast_kind ( x : ast) = (ast_kind_of_int (Z3native.get_ast_kind x#gnc x#gno)) + let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) (** Indicates whether the AST is an Expr *) - let is_expr ( x : ast) = - match get_ast_kind ( x : ast) with + let is_expr ( x : ast ) = + match get_ast_kind ( x : ast ) with | APP_AST | NUMERAL_AST | QUANTIFIER_AST @@ -1257,33 +503,33 @@ struct (** Indicates whether the AST is a bound variable *) - let is_var ( x : ast) = (get_ast_kind x) == VAR_AST + let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST (** Indicates whether the AST is a Quantifier *) - let is_quantifier ( x : ast) = (get_ast_kind x) == QUANTIFIER_AST + let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST (** Indicates whether the AST is a Sort *) - let is_sort ( x : ast) = (get_ast_kind x) == SORT_AST + let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST (** Indicates whether the AST is a FunctionDeclaration *) - let is_func_decl ( x : ast) = (get_ast_kind x) == FUNC_DECL_AST + let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST (** A string representation of the AST. *) - let to_string ( x : ast) = Z3native.ast_to_string x#gnc x#gno + let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) (** A string representation of the AST in s-expression notation. *) - let to_sexpr ( x : ast) = Z3native.ast_to_string x#gnc x#gno + let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) (** Comparison operator. @@ -1292,11 +538,11 @@ struct @return True if and are from the same context and represent the same sort; false otherwise. *) - let ( = ) (a : expr) (b : expr) = (a == b) || - if a#gnc == b#gnc then + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + if (z3obj_gnc a) != (z3obj_gnc b) then false else - (Z3native.is_eq_ast a#gnc a#gno b#gno) + Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) (** Object Comparison. @@ -1316,11 +562,11 @@ struct @param ctx A context @return A copy of the AST which is associated with *) - let translate ( x : ast) to_ctx = - if x#gc == to_ctx then + let translate ( x : ast ) ( to_ctx : context ) = + if (z3obj_gnc x) == (context_gno to_ctx) then x else - (create_ast to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx))) + create to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Wraps an AST. @@ -1334,7 +580,7 @@ struct @param nativeObject The native pointer to wrap. *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create_ast ctx ptr + create ctx ptr (** Unwraps an AST. @@ -1347,43 +593,413 @@ struct @param a The AST to unwrap. *) - let unwrap_ast ( a : ast ) = a#gno + let unwrap_ast ( x : ast ) = (z3obj_gno x) + + (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST -> (match (FuncDecl.create ctx no) with FuncDecl.FuncDecl(x) -> x) + | SORT_AST -> (match (Sort.create ctx no) with Sort.Sort(x) -> x) + | QUANTIFIER_AST -> (match (Quantifiers.create ctx no) with Quantifiers.Quantifier(Expr.Expr(x)) -> x) + | APP_AST + | NUMERAL_AST + | VAR_AST -> (match (Expr.create ctx no) with Expr.Expr(x) -> x) + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") +(**/**) end +(** The Sort module implements type information for ASTs *) +and Sort : +sig + type sort = Sort of AST.ast + type bitvec_sort = BitvecSort of sort + type uninterpreted_sort = UninterpretedSort of sort + + val create : context -> Z3native.ptr -> sort + val gno : sort -> Z3native.ptr + val gnc : sort -> Z3native.ptr + val aton : sort array -> Z3native.ptr array +end = struct + type sort = Sort of AST.ast + type bitvec_sort = BitvecSort of sort + type uninterpreted_sort = UninterpretedSort of sort + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) + let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) + let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let aton : sort array -> Z3native.ptr array = fun a -> + let f e = (gno e) in + Array.map f a + + let create : context -> Z3native.ptr -> sort = fun ctx no -> + let q : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno q ctx no) ; + (z3obj_create q) ; + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + + (** + Comparison operator. + @param a A sort + @param b A sort + @return True if and are from the same context + and represent the same sort; false otherwise. + *) + let ( = ) : sort -> sort -> bool = fun a b -> + (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) + + (** + Returns a unique identifier for the sort. + *) + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) + + (** + The kind of the sort. + *) + let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) + + (** + The name of the sort + *) + let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) + + (** + A string representation of the sort. + *) + let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; + (z3obj_create res) ; + UninterpretedSort(Sort(res)) + + (** + Create a new uninterpreted sort. + *) + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) +end + + +(** Function declarations *) +and FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + + val create : context -> Z3native.ptr -> func_decl + val gno : func_decl -> Z3native.ptr + val gnc : func_decl -> Z3native.ptr + + val get_domain_size : func_decl -> int + val get_decl_kind : func_decl -> Z3enums.decl_kind +end = struct + open Sort + + type func_decl = FuncDecl of AST.ast + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) + let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) + + let aton (a : func_decl array) = + let f (e : func_decl) = (gno e) in + Array.map f a + + (** Parameters of Func_Decls *) + module Parameter = + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) + let get_kind ( x : parameter ) = + (match x with + | P_Int(_) -> PARAMETER_INT + | P_Dbl(_) -> PARAMETER_DOUBLE + | P_Sym(_) -> PARAMETER_SYMBOL + | P_Srt(_) -> PARAMETER_SORT + | P_Ast(_) -> PARAMETER_AST + | P_Fdl(_) -> PARAMETER_FUNC_DECL + | P_Rat(_) -> PARAMETER_RATIONAL) + + (**The int value of the parameter.*) + let get_int ( x : parameter ) = + match x with + | P_Int(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an int") + + (**The double value of the parameter.*) + let get_float ( x : parameter ) = + match x with + | P_Dbl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a double") + + (**The Symbol value of the parameter.*) + let get_symbol ( x : parameter ) = + match x with + | P_Sym(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a symbol") + + (**The Sort value of the parameter.*) + let get_sort ( x : parameter ) = + match x with + | P_Srt(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a sort") + + (**The AST value of the parameter.*) + let get_ast ( x : parameter ) = + match x with + | P_Ast(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an ast") + + (**The FunctionDeclaration value of the parameter.*) + let get_func_decl ( x : parameter ) = + match x with + | P_Fdl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a func_decl") + + (**The rational string value of the parameter.*) + let get_func_decl ( x : parameter ) = + match x with + | P_Rat(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a rational string") + end + + open Parameter + + (** + Creates a new function declaration. + *) + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + create_ndr ctx name domain range + + (** + Creates a new function declaration. + *) + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + mk_func_decl ctx (Symbol.mk_string ctx name) domain range + + (** + Creates a fresh function declaration with a name prefixed with . + + + *) + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + create_pdr ctx prefix domain range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_ndr ctx name [||] range + + (** + Creates a new constant function declaration. + *) + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + create_ndr ctx (Symbol.mk_string ctx name) [||] range + + (** + Creates a fresh constant function declaration with a name prefixed with . + + + *) + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + create_pdr ctx prefix [||] range + + + (** + Comparison operator. + @param a A func_decl + @param b A func_decl + @return True if and are from the same context + and represent the same func_decl; false otherwise. + *) + let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) + + (** + A string representations of the function declaration. + *) + let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) + + (** + Returns a unique identifier for the function declaration. + *) + let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) + + (** + The arity of the function declaration + *) + let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) + + (** + The size of the domain of the function declaration + + *) + let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) + + (** + The domain of the function declaration + *) + let get_domain ( x : func_decl ) = + let n = (get_domain_size x) in + let f i = Sort.create (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + Array.init n f + + (** + The range of the function declaration + *) + let get_range ( x : func_decl ) = + Sort.create (gc x) (Z3native.get_range (gnc x) (gno x)) + + (** + The kind of the function declaration. + *) + let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) + + (** + The name of the function declaration + *) + let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) + + (** + The number of parameters of the function declaration + *) + let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) + + (** + The parameters of the function declaration + *) + let get_parameters ( x : func_decl ) = + let n = (get_num_parameters x) in + let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with + | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + ) in + mk_list f n + + (** + Create expression that applies function to arguments. + @param args The arguments + *) + let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.create_fa (gc x) x args +end + (** Parameter sets (of Solvers, Tactics, ...) A Params objects represents a configuration in the form of symbol/value pairs. *) -module Params = -struct +and Params : +sig + type params = z3_native_object + + val create : context -> Z3native.ptr -> params + + module ParamDescrs : sig + type param_descrs = z3_native_object + + val create : context -> Z3native.ptr -> param_descrs + end +end = struct type params = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.params_inc_ref ; dec_ref = Z3native.params_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs = - struct + module ParamDescrs : + sig + type param_descrs = z3_native_object + + val create : context -> Z3native.ptr -> param_descrs + end = struct type param_descrs = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.param_descrs_inc_ref ; dec_ref = Z3native.param_descrs_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -1449,7 +1065,6 @@ struct *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = add_double x (Symbol.mk_string (z3obj_gc x) name) value - (** Adds a parameter setting. *) @@ -1460,7 +1075,7 @@ struct Creates a new parameter set *) let mk_params ( ctx : context ) = - cnstr ctx (Z3native.mk_params (context_gno ctx)) + create ctx (Z3native.mk_params (context_gno ctx)) (** A string representation of the parameter set. @@ -1468,18 +1083,69 @@ struct let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end - (** General expressions (terms), including Boolean logic *) -module Expr = -struct +and Expr : +sig + type expr = Expr of AST.ast + + val create : context -> Z3native.ptr -> expr + val create_fa : context -> FuncDecl.func_decl -> expr array -> expr + val gc : expr -> context + val gno : expr -> Z3native.ptr + val gnc : expr -> Z3native.ptr + val aton : expr array -> Z3native.ptr array + + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val get_func_decl : expr -> FuncDecl.func_decl +end = struct + type expr = Expr of AST.ast + + let create ( ctx : context ) ( obj : Z3native.ptr ) = + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then + (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) + else + let s = Z3native.get_sort (context_gno ctx) obj in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) obj) then + (match (Arithmetic.create_algebraic_num ctx obj) with Arithmetic.AlgebraicNum(Arithmetic.Expr(e)) -> e) + else + if (Z3native.is_numeral_ast (context_gno ctx) obj) && + (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + match sk with + | INT_SORT -> (match (Arithmetic.create_int_num ctx obj) with Arithmetic.IntNum(Arithmetic.IntExpr(Arithmetic.Expr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.create_rat_num ctx obj) with Arithmetic.RatNum(Arithmetic.RealExpr(Arithmetic.Expr(e))) -> e) + | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) + | _ -> raise (Z3native.Exception "Unsupported numeral object") + else + match sk with + | BOOL_SORT -> (match (Booleans.create ctx obj) with Booleans.BoolExpr(e) -> e) + | INT_SORT -> (match (Arithmetic.create_int_expr ctx obj) with Arithmetic.IntExpr(Arithmetic.Expr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.create_real_expr ctx obj) with Arithmetic.RealExpr(Arithmetic.Expr(e)) -> e) + | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) + | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) + | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) + | _ -> Expr(AST.create ctx obj) + + let aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (z3obj_gno a) in + Array.map f a + + let create_fa ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = + let o = Z3native.mk_app (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args) in + Expr.create ctx o + + let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) + let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) + let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> create_expr x#gc (Z3native.simplify x#gnc x#gno) - | Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno (z3obj_gno pp)) + | None -> Expr.create (gc x) (Z3native.simplify (gnc x) (gno x)) + | Some pp -> Expr.create (gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1491,29 +1157,29 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.cnstr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.create ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = (new func_decl x#gc)#cnstr_obj (Z3native.get_app_decl x#gnc x#gno) + let get_func_decl ( x : expr ) = FuncDecl.create (gc x) (Z3native.get_app_decl (gnc x) (gno x)) (** Indicates whether the expression is the true or false expression or something else (L_UNDEF). *) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) (** The number of arguments of the expression. *) - let get_num_args ( x : expr ) = Z3native.get_app_num_args x#gnc x#gno + let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) (** The arguments of the expression. *) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = create_expr x#gc (Z3native.get_app_arg x#gnc x#gno i) in + let f i = create (gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in Array.init n f (** @@ -1524,7 +1190,7 @@ struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - x#sno x#gc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args)) + create (gc x) (Z3native.update_term (gnc x) (gno x) (Array.length args) (aton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -1537,7 +1203,7 @@ struct if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - create_expr x#gc (Z3native.substitute x#gnc x#gno (Array.length from) (expraton from) (expraton to_)) + create (gc x) (Z3native.substitute (gnc x) (gno x) (Array.length from) (aton from) (aton to_)) (** Substitute every occurrence of from in the expression with to. @@ -1552,7 +1218,7 @@ struct For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) let substitute_vars ( x : expr ) to_ = - create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_)) + create (gc x) (Z3native.substitute_vars (gnc x) (gno x) (Array.length to_) (aton to_)) (** @@ -1561,46 +1227,46 @@ struct @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = - if x#gc == to_ctx then + if (gc x) == to_ctx then x else - create_expr to_ctx (Z3native.translate x#gnc x#gno (context_gno to_ctx)) + create to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) (** Returns a string representation of the expression. *) - let to_string ( x : expr ) = Z3native.ast_to_string x#gnc x#gno + let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast x#gnc x#gno) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted x#gnc x#gno + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) (** The Sort of the term. *) - let get_sort ( x : expr ) = create_sort x#gc (Z3native.get_sort x#gnc x#gno) + let get_sort ( x : expr ) = Sort.create (gc x) (Z3native.get_sort (gnc x) (gno x)) (** Indicates whether the term has Boolean sort. *) - let is_bool ( x : expr ) = (AST.is_expr x) && - (Z3native.is_eq_sort x#gnc - (Z3native.mk_bool_sort x#gnc) - (Z3native.get_sort x#gnc x#gno)) - + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) + (** Indicates whether the term represents a constant. *) - let is_const ( x : expr ) = (AST.is_expr x) && + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && - FuncDecl.get_domain_size(get_func_decl x) == 0 + (FuncDecl.get_domain_size (get_func_decl x)) == 0 (** Indicates whether the term is the constant true. @@ -1679,123 +1345,36 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_expr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) range#gno) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = + create ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) (** Creates a new Constant of sort and named . *) - let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name)range + let mk_const_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + mk_const ctx (Symbol.mk_string ctx name) range (** Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : func_decl ) = - create_expr_fa ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = + create_fa ctx f [||] (** Creates a fresh constant of sort and a name prefixed with . *) - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) = - create_expr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix range#gno) - - (** - Create a Boolean constant. - *) - let mk_bool_const ( ctx : context ) ( name : Symbol.symbol ) = - ((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr) - - (** - Create a Boolean constant. - *) - let mk_bool_const_s ( ctx : context ) ( name : string ) = - mk_bool_const ctx (Symbol.mk_string ctx name) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = + create ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = - create_expr_fa ctx f args - - (** - The true Term. - *) - let mk_true ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_true (context_gno ctx)) - - (** - The false Term. - *) - let mk_false ( ctx : context ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_false (context_gno ctx)) - - (** - Creates a Boolean value. - *) - let mk_bool ( ctx : context ) ( value : bool) = - if value then mk_true ctx else mk_false ctx - - (** - Creates the equality = . - *) - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_eq (context_gno ctx) x#gno y#gno) - - (** - Creates a distinct term. - *) - let mk_distinct ( ctx : context ) ( args : expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct (context_gno ctx) (Array.length args) (astaton args)) - - (** - Mk an expression representing not(a). - *) - let mk_not ( ctx : context ) ( a : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_not (context_gno ctx) a#gno) - - (** - Create an expression representing an if-then-else: ite(t1, t2, t3). - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - *) - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite (context_gno ctx) t1#gno t2#gno t3#gno) - - (** - Create an expression representing t1 iff t2. - *) - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_iff (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing t1 -> t2. - *) - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_implies (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing t1 xor t2. - *) - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_xor (context_gno ctx) t1#gno t2#gno) - - (** - Create an expression representing the AND of args - *) - let mk_and ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_and (context_gno ctx) (Array.length args) (astaton args)) - - (** - Create an expression representing the OR of args - *) - let mk_or ( ctx : context ) ( args : bool_expr array ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_or (context_gno ctx) (Array.length args) (astaton args)) + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = + create_fa ctx f args (** Create a numeral of a given sort. @@ -1803,8 +1382,8 @@ struct @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. @return A Term with value and sort *) - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - create_expr ctx (Z3native.mk_numeral (context_gno ctx) v ty#gno) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : Sort.sort ) = + create ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1813,13 +1392,147 @@ struct @param ty Sort of the numeral @return A Term with value and type *) - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_int (context_gno ctx) v ty#gno) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = + create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + + let aton (a : expr array) = + let f (e : expr) = (gno e) in + Array.map f a +end + +(** Boolean expressions *) +and Booleans : +sig + type bool_expr = BoolExpr of Expr.expr + type bool_sort = BoolSort of Sort.sort + + val create : context -> Z3native.ptr -> bool_expr + val aton : bool_expr array -> Z3native.ptr array +end = struct + type bool_expr = BoolExpr of Expr.expr + type bool_sort = BoolSort of Sort.sort + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.create ctx no) in + BoolExpr(Expr.Expr(a)) + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) + + let aton ( a : bool_expr array ) = + let f (e : bool_expr) = (gno e) in + Array.map f a + + let mk_sort ( ctx : context ) = + BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) + + (** + Create a Boolean constant. + *) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let s = (match (mk_sort ctx) with BoolSort(q) -> q) in + BoolExpr(Expr.mk_const ctx name s) + + (** + Create a Boolean constant. + *) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) + + (** + The true Term. + *) + let mk_true ( ctx : context ) = + create ctx (Z3native.mk_true (context_gno ctx)) + + (** + The false Term. + *) + let mk_false ( ctx : context ) = + create ctx (Z3native.mk_false (context_gno ctx)) + + (** + Creates a Boolean value. + *) + let mk_val ( ctx : context ) ( value : bool ) = + if value then mk_true ctx else mk_false ctx + + (** + Creates the equality = . + *) + let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = + create ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + (** + Creates a distinct term. + *) + let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = + create ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + + (** + Mk an expression representing not(a). + *) + let mk_not ( ctx : context ) ( a : bool_expr ) = + create ctx (Z3native.mk_not (context_gno ctx) (gno a)) + + (** + Create an expression representing an if-then-else: ite(t1, t2, t3). + @param t1 An expression with Boolean sort + @param t2 An expression + @param t3 An expression with the same sort as + *) + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + create ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + + (** + Create an expression representing t1 iff t2. + *) + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + + (** + Create an expression representing t1 -> t2. + *) + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + (** + Create an expression representing t1 xor t2. + *) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + create ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + + (** + Create an expression representing the AND of args + *) + let mk_and ( ctx : context ) ( args : bool_expr array ) = + create ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + + (** + Create an expression representing the OR of args + *) + let mk_or ( ctx : context ) ( args : bool_expr array ) = + create ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) end (** Quantifier expressions *) -module Quantifiers = -struct +and Quantifiers : +sig + type quantifier = Quantifier of Expr.expr + + val create : context -> Z3native.ptr -> quantifier +end = struct + type quantifier = Quantifier of Expr.expr + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.create ctx no) in + Quantifier(Expr.Expr(a)) + + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) + + (** The de-Burijn index of a bound variable. @@ -1838,11 +1551,11 @@ struct on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its index. *) - let get_index ( x : expr ) = - if not (AST.is_var x) then + let get_index ( x : Expr.expr ) = + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value x#gnc x#gno + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) (** Quantifier patterns @@ -1850,33 +1563,57 @@ struct non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Pattern = - struct + module Patterns : + sig + type pattern = Pattern of AST.ast + + val create : context -> Z3native.ptr -> pattern + val aton : pattern array -> Z3native.ptr array + end = struct + type pattern = Pattern of AST.ast + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + Pattern(res) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + (** The number of terms in the pattern. *) let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms x#gnc x#gno + Z3native.get_pattern_num_terms (gnc x) (gno x) (** The terms in the pattern. *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in - let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in + let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f (** A string representation of the pattern. *) - let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + + let aton (a : pattern array) = + let f (e : pattern) = (gno e) in + Array.map f a end (** Indicates whether the quantifier is universal. *) let is_universal ( x : quantifier ) = - Z3native.is_quantifier_forall x#gnc x#gno + Z3native.is_quantifier_forall (gnc x) (gno x) (** Indicates whether the quantifier is existential. @@ -1886,45 +1623,45 @@ struct (** The weight of the quantifier. *) - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) (** The number of patterns. *) - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) (** The patterns. *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in + let f i = (Patterns.create (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** The number of no-patterns. *) - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) (** The no-patterns. *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in + let f i = (Patterns.create (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** The number of bound variables. *) - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) (** The symbols for the bound variables. *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (Symbol.create x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in + let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in Array.init n f (** @@ -1932,31 +1669,31 @@ struct *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in + let f i = (Sort.create (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f (** The body of the quantifier. *) let get_body ( x : quantifier ) = - (new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno) + Booleans.create (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @param index The de-Bruijn index of the variable @param ty The sort of the variable *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - create_expr ctx (Z3native.mk_bound (context_gno ctx) index ty#gno) + let mk_bound ( ctx : context ) ( index : int ) ( ty : Sort.sort ) = + Expr.create ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) (** Create a quantifier pattern. *) - let mk_pattern ( ctx : context ) ( terms : expr array ) = + let mk_pattern ( ctx : context ) ( terms : Expr.expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - (new pattern ctx)#cnstr_obj (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (astaton terms)) + Patterns.create ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (Expr.aton terms)) (** Create a universal Quantifier. @@ -1977,95 +1714,96 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (patternaton patterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (Patterns.aton patterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - body#gno) + create ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - body#gno) + create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Expr.gno body)) + (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (patternaton patterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) + create ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (Patterns.aton patterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - (Array.length sorts) (astaton sorts) - (Symbol.aton names) - body#gno) - + create ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Array.length sorts) (Sort.aton sorts) + (Symbol.aton names) + (Expr.gno body)) + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - body#gno) + create ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Expr.gno body)) else - (new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expraton bound_constants) - (Array.length patterns) (patternaton patterns) - (Array.length nopatterns) (patternaton nopatterns) - body#gno) + create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (Expr.aton bound_constants) + (Array.length patterns) (Patterns.aton patterns) + (Array.length nopatterns) (Expr.aton nopatterns) + (Expr.gno body)) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -2075,7 +1813,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : pattern array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -2083,75 +1821,104 @@ struct end (** Functions to manipulate Array expressions *) -module Arrays = -struct +and Arrays : +sig + type array_expr = ArrayExpr of Expr.expr + type array_sort = ArraySort of Sort.sort + + val create_expr : context -> Z3native.ptr -> array_expr +end = struct + type array_expr = ArrayExpr of Expr.expr + type array_sort = ArraySort of Sort.sort + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + ArrayExpr(e) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + ArraySort(s) + + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gno s) + + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gno e) + + let aton (a : array_expr array) = + let f (e : array_expr) = (egno e) in + Array.map f a + + (** Create a new array sort. *) - let mk_sort ( ctx : context ) domain range = - (new array_sort ctx)#cnstr_dr domain range + let mk_sort ( ctx : context ) ( domain : Sort.sort ) ( range : Sort.sort ) = + create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** Indicates whether the term is an array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). Array store takes at least 3 arguments. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the function passed as parameter. *) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) (** Indicates whether the term is of an array sort. *) - let is_array ( x : expr ) = - (Z3native.is_app x#gnc x#gno) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT) + let is_array ( x : Expr.expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno) + let get_domain ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno) + let get_range ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort ) ( range : Sort.sort ) = + ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** Create an array constant. *) - let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( domain : Sort.sort ) ( range : Sort.sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range (** @@ -2166,8 +1933,8 @@ struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - ((create_expr ctx (Z3native.mk_select (context_gno ctx) a#gno i#gno)) :> array_expr) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) = + create_expr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) (** Array update. @@ -2185,8 +1952,8 @@ struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_store (context_gno ctx) a#gno i#gno v#gno) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) ( v : Expr.expr ) = + create_expr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) (** Create a constant array. @@ -2196,8 +1963,8 @@ struct *) - let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - (new array_expr ctx)#cnstr_obj (Z3native.mk_const_array (context_gno ctx) domain#gno v#gno) + let mk_const_array ( ctx : context ) ( domain : Sort.sort ) ( v : Expr.expr ) = + create_expr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) (** Maps f on the argument arrays. @@ -2209,8 +1976,8 @@ struct *) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = - ((create_expr ctx (Z3native.mk_map (context_gno ctx) f#gno (Array.length args) (astaton args))) :> array_expr) + let mk_map ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : array_expr array ) = + create_expr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args)) (** Access the array default value. @@ -2219,149 +1986,184 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - ((create_expr ctx (Z3native.mk_array_default (context_gno ctx) arg#gno)) :> array_expr) + create_expr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) -module Sets = -struct +and Sets : +sig + type set_sort = SetSort of Sort.sort + +end = struct + type set_sort = SetSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + SetSort(s) + (** Indicates whether the term is set union *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) (** Create a set type. *) - let mk_sort ( ctx : context ) ( ty : sort) = - (new set_sort ctx)#cnstr_s ty + let mk_sort ( ctx : context ) ( ty : Sort.sort ) = + create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. *) - let mk_empty ( ctx : context ) ( domain : sort ) = - (create_expr ctx (Z3native.mk_empty_set (context_gno ctx) domain#gno)) + let mk_empty ( ctx : context ) ( domain : Sort.sort ) = + (Expr.create ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) (** Create the full set. *) - let mk_full ( ctx : context ) ( domain : sort ) = - create_expr ctx (Z3native.mk_full_set (context_gno ctx) domain#gno) + let mk_full ( ctx : context ) ( domain : Sort.sort ) = + Expr.create ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) (** Add an element to the set. *) - let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_add (context_gno ctx) set#gno element#gno) + let mk_set_add ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) (** Remove an element from a set. *) - let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - create_expr ctx (Z3native.mk_set_del (context_gno ctx) set#gno element#gno) + let mk_del ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) (** Take the union of a list of sets. *) - let mk_union ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (astaton args)) + let mk_union ( ctx : context ) ( args : Expr.expr array ) = + Expr.create ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (Expr.aton args)) (** Take the intersection of a list of sets. *) - let mk_intersection ( ctx : context ) ( args : expr array ) = - create_expr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (astaton args)) + let mk_intersection ( ctx : context ) ( args : Expr.expr array ) = + Expr.create ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (Expr.aton args)) (** Take the difference between two sets. *) - let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_difference (context_gno ctx) arg1#gno arg2#gno) + let mk_difference ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) (** Take the complement of a set. *) - let mk_complement ( ctx : context ) ( arg : expr ) = - create_expr ctx (Z3native.mk_set_complement (context_gno ctx) arg#gno) + let mk_complement ( ctx : context ) ( arg : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) (** Check for set membership. *) - let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - create_expr ctx (Z3native.mk_set_member (context_gno ctx) elem#gno set#gno) + let mk_membership ( ctx : context ) ( elem : Expr.expr ) ( set : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) (** Check for subsetness of sets. *) - let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) = - create_expr ctx (Z3native.mk_set_subset (context_gno ctx) arg1#gno arg2#gno) + let mk_subset ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = + Expr.create ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) end (** Functions to manipulate Finite Domain expressions *) -module FiniteDomains = -struct - (** - Create a new finite domain sort. - *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) size = - (new finite_domain_sort ctx)#cnstr_si name size +and FiniteDomains : +sig + type finite_domain_sort = FiniteDomainSort of Sort.sort + +end = struct + type finite_domain_sort = FiniteDomainSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + FiniteDomainSort(s) + + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) (** Create a new finite domain sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) size = - (new finite_domain_sort ctx)#cnstr_si (Symbol.mk_string ctx name) size + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + create_sort ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size) + + (** + Create a new finite domain sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_sort ctx (Symbol.mk_string ctx name) size (** Indicates whether the term is of an array sort. *) - let is_finite_domain ( x : expr ) = - (Z3native.is_app x#gnc x#gno) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT) + let is_finite_domain ( x : Expr.expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) (** The size of the finite domain sort. *) - let get_size (x : finite_domain_sort) = - let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in + let get_size ( x : finite_domain_sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end (** Functions to manipulate Relation expressions *) -module Relations = -struct +and Relations : +sig + type relation_sort = RelationSort of Sort.sort + +end = struct + type relation_sort = RelationSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + RelationSort(s) + + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) + (** Indicates whether the term is of a relation sort. *) - let is_relation ( x : expr ) = - ((Z3native.is_app x#gnc x#gno) && - (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT)) + let is_relation ( x : Expr.expr ) = + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2370,40 +2172,40 @@ struct The function takes n+1 arguments, where the first argument is the relation and the remaining n elements correspond to the n columns of the relation. *) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) (** Indicates whether the term is an empty relation *) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) (** Indicates whether the term is a test for the emptiness of a relation *) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) (** Indicates whether the term is a relational join *) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_join ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) (** Indicates whether the term is the union or convex hull of two relations. The function takes two arguments. *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) (** Indicates whether the term is the widening of two relations The function takes two arguments. *) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_widen ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). The function takes one argument. *) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_project ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) (** Indicates whether the term is a relation filter @@ -2414,7 +2216,7 @@ struct corresponding to the columns of the relation. So the first column in the relation has index 0. *) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) (** Indicates whether the term is an intersection of a relation with the negation of another. @@ -2429,7 +2231,7 @@ struct target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with ( x : expr ) on the columns c1, d1, .., cN, dN. *) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_negation_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) (** Indicates whether the term is the renaming of a column in a relation @@ -2437,12 +2239,12 @@ struct The function takes one argument. The parameters contain the renaming as a cycle. *) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_rename ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) (** Indicates whether the term is the complement of a relation *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) (** Indicates whether the term is a relational select @@ -2451,7 +2253,7 @@ struct The function takes n+1 arguments, where the first argument is a relation, and the remaining n arguments correspond to a record. *) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) (** Indicates whether the term is a relational clone (copy) @@ -2462,38 +2264,153 @@ struct for terms of kind to perform destructive updates to the first argument. *) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_clone ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) (** The arity of the relation sort. *) - let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno + let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) (** The sorts of the columns of the relation sort. *) - let get_column_sorts (x : relation_sort) = + let get_column_sorts ( x : relation_sort ) = let n = get_arity x in - let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in + let f i = (create_sort (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in Array.init n f end (** Functions to manipulate Datatype expressions *) -module Datatypes = -struct +and Datatypes : +sig + type datatype_expr = DatatypeExpr of Expr.expr + type datatype_sort = DatatypeSort of Sort.sort + + val create_expr : context -> Z3native.ptr -> datatype_expr +end = struct + type datatype_expr = DatatypeExpr of Expr.expr + type datatype_sort = DatatypeSort of Sort.sort + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + DatatypeExpr(e) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + DatatypeSort(s) + + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) + + (** Constructors *) module Constructor = struct + type constructor_extra = { + m_n : int; + mutable m_tester_decl : FuncDecl.func_decl option; + mutable m_constructor_decl : FuncDecl.func_decl option ; + mutable m_accessor_decls : FuncDecl.func_decl array option} + type constructor = Constructor of (z3_native_object * constructor_extra) + + let create_ssssi ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + let n = (Array.length field_names) in + if n != (Array.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if n != (Array.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) + (Symbol.gno recognizer) + n + (Symbol.aton field_names) + (Sort.aton sorts) + sort_refs) in + let no : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + let ex : constructor_extra = { m_n = n; + m_tester_decl = None; + m_constructor_decl = None; + m_accessor_decls = None} in + (z3obj_sno no ctx ptr) ; + (z3obj_create no) ; + let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f no ; + Constructor(no, ex) + + let init_extra ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_tester_decl with + | None -> + let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in + ex.m_constructor_decl <- Some (FuncDecl.create (z3obj_gc no) a) ; + ex.m_tester_decl <- Some (FuncDecl.create (z3obj_gc no) b) ; + ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; + () + | _ -> () + + let get_n ( x : constructor ) = + match x with Constructor(no, ex) -> + ex.m_n + + let rec tester_decl ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_tester_decl with + | Some(s) -> s + | None -> init_extra x ; tester_decl x + + let rec constructor_decl ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_constructor_decl with + | Some(s) -> s + | None -> init_extra x ; constructor_decl x + + let rec accessor_decls ( x : constructor ) = + match x with Constructor(no, ex) -> + match ex.m_accessor_decls with + | Some(s) -> s + | None -> init_extra x ; accessor_decls x + + let aton ( a : constructor array ) = + let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in + Array.map f a + + (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = x#get_n + let get_num_fields ( x : constructor ) = get_n x (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = x#constructor_decl + let get_constructor_decl ( x : constructor ) = constructor_decl x (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = x#tester_decl + let get_tester_decl ( x : constructor ) = tester_decl x (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = x#accessor_decls + let get_accessor_decls ( x : constructor ) = accessor_decls x end + (** Constructor list objects *) + module ConstructorList = + struct + type constructor_list = z3_native_object + + let create ( ctx : context )( c : Constructor.constructor array ) = + let res : constructor_list = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Constructor.aton c))) ; + (z3obj_create res) ; + let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f res; + res + + let aton (a : constructor_list array) = + let f (e : constructor_list) = (z3obj_gno e) in + Array.map f a + end + (* DATATYPES *) (** Create a datatype constructor. @@ -2505,8 +2422,8 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array) = - (new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = + Constructor.create_ssssi ctx name recognizer field_names sorts sort_refs (** @@ -2519,20 +2436,21 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : constructor array) = - (new datatype_sort ctx)#cnstr_sc name constructors + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array) = + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Constructor.aton constructors)) in + create_sort ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2540,16 +2458,16 @@ struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in - let f e = ( (new constructor_list ctx)#cnstr_ca e ) in + let f e = (ConstructorList.create ctx e) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (constructor_listaton cla)) in - let g e = ( (new datatype_sort ctx)#cnstr_obj e) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (ConstructorList.aton cla)) in + let g e = (create_sort ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2558,130 +2476,230 @@ struct c (** The number of constructors of the datatype sort. *) - let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno + let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) (** The range of the array sort. *) - let get_constructors (x : datatype_sort) = + let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in + let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f (** The recognizers. *) - let get_recognizers (x : datatype_sort) = + let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in + let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f (** The constructor accessors. *) - let get_accessors (x : datatype_sort) = + let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in - let ds = (Z3native.get_domain_size fd#gnc fd#gno) in - let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in + let fd = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in + let g j = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in Array.init ds g ) in Array.init n f end (** Functions to manipulate Enumeration expressions *) -module Enumerations = -struct - (** - Create a new enumeration sort. - *) - let mk_sort ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss name enum_names +and Enumerations : +sig + type enum_sort_data + type enum_sort = EnumSort of (Sort.sort * enum_sort_data) +end = struct + type enum_sort_data = { mutable _constdecls : FuncDecl.func_decl array ; + mutable _testerdecls : FuncDecl.func_decl array } + type enum_sort = EnumSort of (Sort.sort * enum_sort_data) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + let s = (Sort.create ctx no) in + let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; + _testerdecls = (let f e = FuncDecl.create ctx e in (Array.map f tdecls)) } in + EnumSort(s, e) + + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) + (** Create a new enumeration sort. *) - let mk_sort_s ( ctx : context ) name enum_names = - (new enum_sort ctx)#cnstr_ss - (Symbol.mk_string ctx name) - (Symbol.mk_strings ctx enum_names) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in + create_sort ctx a b c + + (** + Create a new enumeration sort. + *) + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = + mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls (x : enum_sort) = x#const_decls + let get_const_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._constdecls (** The test predicates for the constants in the enumeration. *) - let get_tester_decls (x : enum_sort) = x#tester_decls + let get_tester_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._testerdecls end (** Functions to manipulate List expressions *) -module Lists = -struct - (** - Create a new list sort. - *) - let mk_sort ( ctx : context ) (name : Symbol.symbol) elem_sort = - (new list_sort ctx)#cnstr_ss name elem_sort +and Lists : +sig + type list_sort_data + type list_sort = ListSort of (Sort.sort * list_sort_data) - (** - Create a new list sort. - *) +end = struct + type list_sort_data = { _nildecl : FuncDecl.func_decl ; + _is_nildecl : FuncDecl.func_decl ; + _consdecl : FuncDecl.func_decl ; + _is_consdecl : FuncDecl.func_decl ; + _headdecl : FuncDecl.func_decl ; + _taildecl : FuncDecl.func_decl } + type list_sort = ListSort of (Sort.sort * list_sort_data) + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + let s = (Sort.create ctx no) in + let e = {_nildecl = FuncDecl.create ctx nildecl; + _is_nildecl = FuncDecl.create ctx is_nildecl; + _consdecl = FuncDecl.create ctx consdecl; + _is_consdecl = FuncDecl.create ctx is_consdecl; + _headdecl = FuncDecl.create ctx headdecl; + _taildecl = FuncDecl.create ctx taildecl} in + ListSort(s, e) + + let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) + + + (** Create a new list sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + create_sort ctx r a b c d e f + + (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl (x : list_sort) = x#nil_decl + let get_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._nildecl (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl (x : list_sort) = x#is_nil_decl + let get_is_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_nildecl (** The declaration of the cons function of this list sort. *) - let get_cons_decl (x : list_sort) = x#cons_decl + let get_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._consdecl (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl (x : list_sort) = x#is_cons_decl + let get_is_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_consdecl (** The declaration of the head function of this list sort. *) - let get_head_decl (x : list_sort) = x#head_decl + let get_head_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._headdecl (** The declaration of the tail function of this list sort. *) - let get_tail_decl (x : list_sort) = x#tail_decl + let get_tail_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._taildecl (** The empty list. *) - let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||] + let nil ( x : list_sort ) = Expr.create_fa (sgc x) (get_nil_decl x) [||] end (** Functions to manipulate Tuple expressions *) -module Tuples = -struct - (** - Create a new tuple sort. - *) - let mk_sort ( ctx : context ) name field_names field_sorts = - (new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts +and Tuples : +sig + type tuple_sort = TupleSort of Sort.sort +end = struct + type tuple_sort = TupleSort of Sort.sort + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let s = (Sort.create ctx no) in + TupleSort(s) + + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) + + (** Create a new tuple sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = + let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Symbol.aton field_names) (Sort.aton field_sorts)) in + (* CMW: leaks a,b? *) + create_sort ctx r (** The constructor function of the tuple. *) - let get_mk_decl (x : tuple_sort) = - (new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno) + let get_mk_decl ( x : tuple_sort ) = + FuncDecl.create (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) (** The number of fields in the tuple. *) - let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno + let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) (** The field declarations. *) - let get_field_decls (x : tuple_sort) = + let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in - let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in + let f i = FuncDecl.create (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end (** Functions to manipulate arithmetic expressions *) -module Arithmetic = -struct +and Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type int_sort = IntSort of Sort.sort + type real_sort = RealSort of Sort.sort + + type arith_expr = Expr of Expr.expr + type int_expr = IntExpr of arith_expr + type real_expr = RealExpr of arith_expr + + type int_num = IntNum of int_expr + type rat_num = RatNum of real_expr + type algebraic_num = AlgebraicNum of arith_expr + + + val create_arith_expr : context -> Z3native.ptr -> arith_expr + val create_int_expr : context -> Z3native.ptr -> int_expr + val create_real_expr : context -> Z3native.ptr -> real_expr + val create_int_num : context -> Z3native.ptr -> int_num + val create_rat_num : context -> Z3native.ptr -> rat_num + val create_algebraic_num : context -> Z3native.ptr -> algebraic_num +end = struct + type arith_sort = ArithSort of Sort.sort + type int_sort = IntSort of Sort.sort + type real_sort = RealSort of Sort.sort + + type arith_expr = ArithExpr of Expr.expr + type int_expr = IntExpr of arith_expr + type real_expr = RealExpr of arith_expr + + type int_num = IntNum of int_expr + type rat_num = RatNum of real_expr + type algebraic_num = AlgebraicNum of arith_expr + + let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = + ArithExpr(Expr.create ctx no) + + let create_int_expr ( ctx : context ) ( no : Z3native.ptr ) = + IntExpr(create_arith_expr ctx no) + + let create_real_expr ( ctx : context ) ( no : Z3native.ptr ) = + RealExpr(create_arith_expr ctx no) + + let create_int_num ( ctx : context ) ( no : Z3native.ptr ) = + IntNum(create_int_expr ctx no) + + let create_rat_num ( ctx : context ) ( no : Z3native.ptr ) = + RatNum(create_real_expr ctx no) + (** Create a new integer sort. *) let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort (context_gno ctx)) + (new int_sort ctx)#create_obj (Z3native.mk_int_sort (context_gno ctx)) (** Create a real sort. *) let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort (context_gno ctx)) + (new real_sort ctx)#create_obj (Z3native.mk_real_sort (context_gno ctx)) (** Indicates whether the term is of integer sort. @@ -2802,11 +2820,11 @@ struct (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno) + (new int_num x#gc)#create_obj (Z3native.get_numerator x#gnc x#gno) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - (new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno) + (new int_num x#gc)#create_obj (Z3native.get_denominator x#gnc x#gno) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2844,75 +2862,92 @@ struct Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (astaton t)) :> arith_expr) + (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - (create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) t#gno) :> arith_expr) + ArithExpr(create ctx (Z3native.mk_unary_minus (context_gno ctx) + (gno (match t with ArithExpr(b) -> b)))) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - (create_expr ctx (Z3native.mk_div (context_gno ctx) t1#gno t2#gno) :> arith_expr) + ArithExpr(create ctx (Z3native.mk_div (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 mod t2. The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_mod (context_gno ctx) t1#gno t2#gno) + IntExpr(create ctx (Z3native.mk_mod (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_rem (context_gno ctx) t1#gno t2#gno) + IntExpr(create ctx (Z3native.mk_rem (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 ^ t2. *) - let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (create_expr ctx (Z3native.mk_power (context_gno ctx) t1#gno t2#gno) :> arith_expr) + let mk_power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + ArithExpr(create_expr ctx (Z3native.mk_power (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_lt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_lt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_le (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_le (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_gt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_gt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_ge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_ge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Coerce an integer to a real. @@ -2925,7 +2960,8 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - (new real_expr ctx)#cnstr_obj (Z3native.mk_int2real (context_gno ctx) t#gno) + RealExpr(create (Z3native.mk_int2real (context_gno ctx) + (gno (match t with BoolExpr(b) -> b)))) (** Coerce a real to an integer. @@ -2935,14 +2971,14 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_real2int (context_gno ctx) t#gno) + (new int_expr ctx)#create_obj (Z3native.mk_real2int (context_gno ctx) t#gno) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int (context_gno ctx) t#gno) - + BoolExpr(create ctx (Z3native.mk_is_int (context_gno ctx) + (gno (match t with BoolExpr(b) -> b)))) (** Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^. @@ -2951,7 +2987,7 @@ struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) + (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) (** Return a lower bound for the given real algebraic number. @@ -2961,7 +2997,7 @@ struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) + (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2981,7 +3017,7 @@ struct raise (Z3native.Exception "Denominator is zero") else - (new rat_num ctx)#cnstr_obj (Z3native.mk_real (context_gno ctx) num den) + (new rat_num ctx)#create_obj (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2989,7 +3025,7 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) + (new rat_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create a real numeral. @@ -2998,14 +3034,14 @@ struct @return A Term with value and sort Real *) let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) + (new rat_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) + (new int_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) (** Create an integer numeral. @@ -3013,7 +3049,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#cnstr_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) + (new int_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno @@ -3021,13 +3057,30 @@ end (** Functions to manipulate bit-vector expressions *) -module BitVectors = -struct +and BitVectors : +sig + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val create_expr : context -> Z3native.ptr -> bitvec_expr + val create_num : context -> Z3native.ptr -> bitvec_num +end = struct + type bitvec_expr = Expr of Expr.expr + type bitvec_num = BitVecExpr of bitvec_expr + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (Expr.create ctx no) in + BitVecExpr(e) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + let e = (create_expr ctx no) in + BitVecNum(e) + (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort (context_gno ctx) size) + (new bitvec_sort ctx)#create_obj (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3328,91 +3381,91 @@ struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) (** Unsigned division. @@ -3424,7 +3477,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) (** Signed division. @@ -3439,7 +3492,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) (** Unsigned remainder. @@ -3449,7 +3502,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) (** Signed remainder. @@ -3461,7 +3514,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) (** Two's complement signed remainder (sign follows divisor). @@ -3470,7 +3523,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) (** Unsigned less-than @@ -3478,7 +3531,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvult (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed less-than @@ -3486,7 +3541,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvslt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned less-than or equal to. @@ -3494,7 +3551,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvule (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed less-than or equal to. @@ -3502,7 +3561,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsle (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned greater than or equal to. @@ -3510,7 +3571,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvuge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed greater than or equal to. @@ -3518,7 +3581,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsge (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Unsigned greater-than. @@ -3526,7 +3591,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvugt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Two's complement signed greater-than. @@ -3534,7 +3601,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsgt (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Bit-vector concatenation. @@ -3545,7 +3614,9 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat (context_gno ctx) t1#gno t2#gno) + BitVectors.BitVecExpr(create ctx (Z3native.mk_concat (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Bit-vector extraction. @@ -3556,7 +3627,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) + (new bitvec_expr ctx)#create_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) (** Bit-vector sign extension. @@ -3566,7 +3637,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_sign_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Bit-vector zero extension. @@ -3577,7 +3648,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_zero_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Bit-vector repetition. @@ -3585,7 +3656,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_repeat (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) (** Shift left. @@ -3600,7 +3671,9 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvshl (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Logical shift right @@ -3614,7 +3687,9 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvlshr (context_gno ctx) + (gno (match t1 with BitVecExpr(b) -> b)) + (gno (match t2 with BitVecExpr(b) -> b)))) (** Arithmetic shift right @@ -3630,7 +3705,9 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_bvashr (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Rotate Left. @@ -3639,7 +3716,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_rotate_left (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) (** Rotate Right. @@ -3648,7 +3725,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right (context_gno ctx) i t#gno) + BitVecExpr(create ctx (Z3native.mk_rotate_right (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) (** Rotate Left. @@ -3657,7 +3734,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_ext_rotate_left (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Rotate Right. @@ -3667,7 +3746,9 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right (context_gno ctx) t1#gno t2#gno) + BitVecExpr(create ctx (Z3native.mk_ext_rotate_right (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create an bit bit-vector from the integer argument . @@ -3680,7 +3761,7 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - (new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv (context_gno ctx) n t#gno) + BitVecExpr(create ctx (Z3native.mk_int2bv (context_gno ctx) n (gno (match t with IntExpr(b) -> b)))) (** Create an integer from the bit-vector argument . @@ -3698,7 +3779,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) + (new int_expr ctx)#create_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3706,7 +3787,10 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3714,23 +3798,30 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow (context_gno ctx) t1#gno t2#gno) - + BoolExpr(create ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) + (** Create a predicate that checks that the bit-wise subtraction does not overflow. The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow (context_gno ctx) t1#gno t2#gno) - + BoolExpr(create ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) + (** Create a predicate that checks that the bit-wise subtraction does not underflow. The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3738,7 +3829,9 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3746,7 +3839,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow (context_gno ctx) t#gno) + BoolExpr(create ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (gno (match t with BitVecExpr(b) -> b)))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3754,7 +3847,10 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow (context_gno ctx) t1#gno t2#gno signed) + BoolExpr(create ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)) + signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3762,7 +3858,9 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow (context_gno ctx) t1#gno t2#gno) + BoolExpr(create ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) + (gno (match t1 with BoolExpr(b) -> b)) + (gno (match t2 with BoolExpr(b) -> b)))) (** Create a bit-vector numeral. @@ -3771,12 +3869,13 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) + (new bitvec_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) end (** Functions to manipulate proof expressions *) -module Proofs = -struct +and Proofs : +sig +end = struct (** Indicates whether the term is a Proof for the expression 'true'. *) @@ -4259,13 +4358,13 @@ struct type goal = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.goal_inc_ref ; dec_ref = Z3native.goal_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4318,7 +4417,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new bool_expr (z3obj_gc x))#create_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4334,7 +4433,7 @@ struct (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = - cnstr to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : Params.params option ) = @@ -4352,7 +4451,7 @@ struct Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; Z3native.tactic_dec_ref (z3obj_gnc x) tn ; - cnstr (z3obj_gc x) res + create (z3obj_gc x) res (** @@ -4365,7 +4464,7 @@ struct @param proofs Indicates whether proof generation should be enabled. *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - cnstr ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) @@ -4380,13 +4479,13 @@ struct type model = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.model_inc_ref ; dec_ref = Z3native.model_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4400,13 +4499,13 @@ struct type func_interp = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.func_interp_inc_ref ; dec_ref = Z3native.func_interp_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4419,13 +4518,13 @@ struct type func_entry = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.func_entry_inc_ref ; dec_ref = Z3native.func_entry_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4467,7 +4566,7 @@ struct *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in - let f i = (FuncEntry.cnstr (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4534,11 +4633,11 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x ((new func_decl f#gc)#cnstr_obj fd) + get_func_interp x ((new func_decl f#gc)#create_obj fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in - if (Z3native.is_null n) then None else Some (FuncInterp.cnstr (z3obj_gc x) n) + if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) @@ -4546,7 +4645,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4556,15 +4655,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = (new func_decl (z3obj_gc x))#cnstr_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4619,7 +4718,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4644,13 +4743,13 @@ struct type probe = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.probe_inc_ref ; dec_ref = Z3native.probe_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4686,48 +4785,48 @@ struct Creates a new Probe. *) let mk_probe ( ctx : context ) ( name : string ) = - (cnstr ctx (Z3native.mk_probe (context_gno ctx) name)) + (create ctx (Z3native.mk_probe (context_gno ctx) name)) (** Create a probe that always evaluates to . *) let const ( ctx : context ) ( v : float ) = - (cnstr ctx (Z3native.probe_const (context_gno ctx) v)) + (create ctx (Z3native.probe_const (context_gno ctx) v)) (** Create a probe that evaluates to "true" when the value returned by is less than the value returned by *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is greater than the value returned by *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is less than or equal the value returned by *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is greater than or equal the value returned by *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value returned by is equal to the value returned by *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4735,7 +4834,7 @@ struct *) (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4743,7 +4842,7 @@ struct *) (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (cnstr ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) (** Create a probe that evaluates to "true" when the value @@ -4751,7 +4850,7 @@ struct *) (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = - (cnstr ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) + (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) end @@ -4767,13 +4866,13 @@ struct type tactic = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.tactic_inc_ref ; dec_ref = Z3native.tactic_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4786,13 +4885,13 @@ struct type apply_result = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.apply_result_inc_ref ; dec_ref = Z3native.apply_result_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -4803,19 +4902,19 @@ struct (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in - let f i = Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = - Goal.cnstr (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) (** Convert a model for the subgoal into a model for the original goal g, that the ApplyResult was obtained from. #return A model for g *) let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.cnstr (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) @@ -4826,13 +4925,13 @@ struct (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with - | None -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) - | Some (pn) -> (ApplyResult.cnstr (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) + | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) (** The number of supported tactics. @@ -4858,7 +4957,7 @@ struct Creates a new Tactic. *) let mk_tactic ( ctx : context ) ( name : string ) = - cnstr ctx (Z3native.mk_tactic (context_gno ctx) name) + create ctx (Z3native.mk_tactic (context_gno ctx) name) (** Create a tactic that applies to a Goal and @@ -4870,17 +4969,17 @@ struct | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in match (Array.fold_left f None ts) with | None -> - cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in - cnstr ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) (** Create a tactic that first applies to a Goal and if it fails then returns the result of applied to the Goal. *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that applies to a goal for milliseconds. @@ -4888,7 +4987,7 @@ struct If does not terminate within milliseconds, then it fails. *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - cnstr ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) + create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) (** Create a tactic that applies to a given goal if the probe @@ -4898,52 +4997,52 @@ struct *) (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - cnstr ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) + create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** Create a tactic that keeps applying until the goal is not modified anymore or the maximum number of iterations is reached. *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - cnstr ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) + create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) (** Create a tactic that just returns the given goal. *) let skip ( ctx : context ) = - cnstr ctx (Z3native.tactic_skip (context_gno ctx)) + create ctx (Z3native.tactic_skip (context_gno ctx)) (** Create a tactic always fails. *) let fail ( ctx : context ) = - cnstr ctx (Z3native.tactic_fail (context_gno ctx)) + create ctx (Z3native.tactic_fail (context_gno ctx)) (** Create a tactic that fails if the probe evaluates to false. *) let fail_if ( ctx : context ) ( p : Probe.probe ) = - cnstr ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains `false'). *) let fail_if_not_decided ( ctx : context ) = - cnstr ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) (** Create a tactic that applies using the given set of parameters . *) let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - cnstr ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) + create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . @@ -4956,14 +5055,14 @@ struct Create a tactic that applies the given tactics in parallel. *) let par_or ( ctx : context ) ( t : tactic array ) = - cnstr ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) + create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) (** Create a tactic that applies to a given goal and then to every subgoal produced by . The subgoals are processed in parallel. *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - cnstr ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) (** Interrupt the execution of a Z3 procedure. @@ -4980,13 +5079,13 @@ struct type solver = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.solver_inc_ref ; dec_ref = Z3native.solver_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5003,13 +5102,13 @@ struct type statistics = z3_native_object (**/**) - let cnstr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.stats_inc_ref ; dec_ref = Z3native.stats_dec_ref } in (z3obj_sno res ctx no) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5028,7 +5127,7 @@ struct mutable m_float : float } (**/**) - let cnstr_si k v = + let create_si k v = let res : statistics_entry = { m_key = k ; m_is_int = true ; @@ -5038,7 +5137,7 @@ struct } in res - let cnstr_sd k v = + let create_sd k v = let res : statistics_entry = { m_key = k ; m_is_int = false ; @@ -5089,9 +5188,9 @@ struct let f i = ( let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - (Entry.cnstr_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.cnstr_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in Array.init n f @@ -5126,7 +5225,7 @@ struct Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5200,7 +5299,7 @@ struct The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5208,9 +5307,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get a i)#gno) in + let f i = ((new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get a i)#gno) in Array.init n f (** @@ -5225,7 +5324,7 @@ struct if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (astaton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (AST.aton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5243,7 +5342,7 @@ struct if (Z3native.is_null q) then None else - Some (Model.cnstr (z3obj_gc x) q) + Some (Model.create (z3obj_gc x) q) (** The proof of the last Check. @@ -5266,7 +5365,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.cnstr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5281,7 +5380,7 @@ struct Solver statistics. *) let get_statistics ( x : solver ) = - (Statistics.cnstr (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) (** Creates a new (incremental) solver. @@ -5292,8 +5391,8 @@ struct *) let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with - | None -> (cnstr ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (cnstr ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) + | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) (** Creates a new (incremental) solver. @@ -5306,7 +5405,7 @@ struct Creates a new (incremental) solver. *) let mk_simple_solver ( ctx : context ) = - (cnstr ctx (Z3native.mk_simple_solver (context_gno ctx))) + (create ctx (Z3native.mk_simple_solver (context_gno ctx))) (** Creates a solver that is implemented using the given tactic. @@ -5315,7 +5414,7 @@ struct will always solve each check from scratch. *) let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = - (cnstr ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) + (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** A string representation of the solver. @@ -5330,13 +5429,13 @@ struct type fixedpoint = z3_native_object (**/**) - let cnstr ( ctx : context ) = + let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.fixedpoint_inc_ref ; dec_ref = Z3native.fixedpoint_dec_ref } in (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; - (z3obj_cnstr res) ; + (z3obj_create res) ; res (**/**) @@ -5356,7 +5455,7 @@ struct Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.create (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. @@ -5487,30 +5586,30 @@ struct Convert benchmark given as set of axioms, rules and queries to a string. *) let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (astaton queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (AST.aton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.cnstr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#cnstr_obj (AST.ASTVector.get v i)#gno in + let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in Array.init n f (** Create a Fixedpoint context. *) - let mk_fixedpoint ( ctx : context ) = cnstr ctx + let mk_fixedpoint ( ctx : context ) = create ctx end (** Global and context options @@ -5590,7 +5689,7 @@ struct *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (astaton assumptions) + (Array.length assumptions) (AST.aton assumptions) formula#gno (** @@ -5613,7 +5712,7 @@ struct Z3native.parse_smtlib_string (context_gno ctx) str cs (Symbol.aton sort_names) - (astaton sorts) + (AST.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5633,7 +5732,7 @@ struct Z3native.parse_smtlib_file (context_gno ctx) file_name cs (Symbol.aton sort_names) - (astaton sorts) + (AST.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5675,7 +5774,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#cnstr_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = (new func_decl ctx)#create_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5708,7 +5807,7 @@ struct Z3native.parse_smtlib2_string (context_gno ctx) str cs (Symbol.aton sort_names) - (astaton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) @@ -5728,7 +5827,7 @@ struct Z3native.parse_smtlib2_string (context_gno ctx) file_name cs (Symbol.aton sort_names) - (astaton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) (func_declaton decls) From 12afbfe6dbc5a74f5fd036bd3c97e20a25a4fcdf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 4 Feb 2013 23:18:55 +0000 Subject: [PATCH 416/646] Checkpoint. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 643 ++++++++++++++++++++++++++--------------------- 1 file changed, 355 insertions(+), 288 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0e47912ae..58c319d4d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1097,6 +1097,7 @@ sig val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val get_func_decl : expr -> FuncDecl.func_decl + val is_numeral : expr -> bool end = struct type expr = Expr of AST.ast @@ -1107,20 +1108,20 @@ end = struct let s = Z3native.get_sort (context_gno ctx) obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.create_algebraic_num ctx obj) with Arithmetic.AlgebraicNum(Arithmetic.Expr(e)) -> e) + (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.Expr(e)) -> e) else if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with - | INT_SORT -> (match (Arithmetic.create_int_num ctx obj) with Arithmetic.IntNum(Arithmetic.IntExpr(Arithmetic.Expr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.create_rat_num ctx obj) with Arithmetic.RatNum(Arithmetic.RealExpr(Arithmetic.Expr(e))) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.Expr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.Expr(e))) -> e) | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) | _ -> raise (Z3native.Exception "Unsupported numeral object") else match sk with - | BOOL_SORT -> (match (Booleans.create ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.create_int_expr ctx obj) with Arithmetic.IntExpr(Arithmetic.Expr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.create_real_expr ctx obj) with Arithmetic.RealExpr(Arithmetic.Expr(e)) -> e) + | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.Expr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.Expr(e)) -> e) | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) @@ -1406,16 +1407,20 @@ sig type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort - val create : context -> Z3native.ptr -> bool_expr + val create_expr : context -> Z3native.ptr -> bool_expr + val create_sort : context -> Z3native.ptr -> bool_sort val aton : bool_expr array -> Z3native.ptr array end = struct type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort - let create ( ctx : context ) ( no : Z3native.ptr ) = + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in BoolExpr(Expr.Expr(a)) + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(Sort.create ctx no) + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) @@ -1444,13 +1449,13 @@ end = struct The true Term. *) let mk_true ( ctx : context ) = - create ctx (Z3native.mk_true (context_gno ctx)) + create_expr ctx (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - create ctx (Z3native.mk_false (context_gno ctx)) + create_expr ctx (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1462,19 +1467,19 @@ end = struct Creates the equality = . *) let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = - create ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + create_expr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) (** Creates a distinct term. *) let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = - create ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + create_expr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - create ctx (Z3native.mk_not (context_gno ctx) (gno a)) + create_expr ctx (Z3native.mk_not (context_gno ctx) (gno a)) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1483,36 +1488,36 @@ end = struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + create_expr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + create_expr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - create ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + create_expr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - create ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) + create_expr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) end (** Quantifier expressions *) @@ -1676,7 +1681,7 @@ end = struct The body of the quantifier. *) let get_body ( x : quantifier ) = - Booleans.create (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + Booleans.create_expr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @@ -2643,416 +2648,478 @@ end and Arithmetic : sig type arith_sort = ArithSort of Sort.sort - type int_sort = IntSort of Sort.sort - type real_sort = RealSort of Sort.sort - type arith_expr = Expr of Expr.expr - type int_expr = IntExpr of arith_expr - type real_expr = RealExpr of arith_expr - - type int_num = IntNum of int_expr - type rat_num = RatNum of real_expr - type algebraic_num = AlgebraicNum of arith_expr - - val create_arith_expr : context -> Z3native.ptr -> arith_expr - val create_int_expr : context -> Z3native.ptr -> int_expr - val create_real_expr : context -> Z3native.ptr -> real_expr - val create_int_num : context -> Z3native.ptr -> int_num - val create_rat_num : context -> Z3native.ptr -> rat_num - val create_algebraic_num : context -> Z3native.ptr -> algebraic_num + val create_expr : context -> Z3native.ptr -> arith_expr + val aton : arith_expr array -> Z3native.ptr array + + module Integers : sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val create_sort : context -> Z3native.ptr -> int_sort + val create_expr : context -> Z3native.ptr -> int_expr + val create_num : context -> Z3native.ptr -> int_num + end + + module Reals : sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val create_sort : context -> Z3native.ptr -> real_sort + val create_expr : context -> Z3native.ptr -> real_expr + val create_num : context -> Z3native.ptr -> rat_num + end + + module AlgebraicNumbers : sig + type algebraic_num = AlgebraicNum of arith_expr + + val create_num : context -> Z3native.ptr -> algebraic_num + end + end = struct type arith_sort = ArithSort of Sort.sort - type int_sort = IntSort of Sort.sort - type real_sort = RealSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - type int_expr = IntExpr of arith_expr - type real_expr = RealExpr of arith_expr - - type int_num = IntNum of int_expr - type rat_num = RatNum of real_expr - type algebraic_num = AlgebraicNum of arith_expr let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) - let create_int_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(create_arith_expr ctx no) + let create_arith_sort ( ctx : context ) ( no : Z3native.ptr ) = + ArithSort(Sort.create ctx no) - let create_real_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(create_arith_expr ctx no) + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) - let create_int_num ( ctx : context ) ( no : Z3native.ptr ) = - IntNum(create_int_expr ctx no) - let create_rat_num ( ctx : context ) ( no : Z3native.ptr ) = - RatNum(create_real_expr ctx no) - - (** - Create a new integer sort. - *) - let mk_int_sort ( ctx : context ) = - (new int_sort ctx)#create_obj (Z3native.mk_int_sort (context_gno ctx)) + module rec Integers : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr - (** - Create a real sort. - *) - let mk_real_sort ( ctx : context ) = - (new real_sort ctx)#create_obj (Z3native.mk_real_sort (context_gno ctx)) + val create_sort : context -> Z3native.ptr -> int_sort + val create_expr : context -> Z3native.ptr -> int_expr + val create_num : context -> Z3native.ptr -> int_num + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + IntSort(create_arith_sort ctx no) + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + IntExpr(create_arith_expr ctx no) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + IntNum(create_expr ctx no) + + let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) + let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) + let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) + let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) + let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) + let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) + let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) + let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) + let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + + (** Create a new integer sort. *) + let mk_sort ( ctx : context ) = + create_sort ctx (Z3native.mk_int_sort (context_gno ctx)) + + (** Retrieve the int value. *) + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + + (** Returns a string representation of the numeral. *) + let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + (** + Creates an integer constant. + *) + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + + (** + Creates an integer constant. + *) + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx (Symbol.mk_string ctx name) + + (** + Create an expression representing t1 mod t2. + The arguments must have int type. + *) + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + create_expr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + + (** + Create an expression representing t1 rem t2. + The arguments must have int type. + *) + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + create_expr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + + (** + Create an integer numeral. + @param v A string representing the Term value in decimal notation. + *) + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Create an integer numeral. + @param v value of the numeral. + @return A Term with value and sort Integer + *) + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. + *) + let mk_int2real ( ctx : context ) ( t : int_expr ) = + Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + end + + and Reals : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val create_sort : context -> Z3native.ptr -> real_sort + val create_expr : context -> Z3native.ptr -> real_expr + val create_num : context -> Z3native.ptr -> rat_num + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + RealSort(create_arith_sort ctx no) + + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + RealExpr(create_arith_expr ctx no) + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + RatNum(create_expr ctx no) + + let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) + let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) + let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) + let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) + let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) + let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) + let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) + let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) + let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) + + (** Create a real sort. *) + let mk_sort ( ctx : context ) = + create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) + + (** The numerator of a rational numeral. *) + let get_numerator ( x : rat_num ) = + Integers.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + + (** The denominator of a rational numeral. *) + let get_denominator ( x : rat_num ) = + Integers.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : rat_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + (** Creates a real constant. *) + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + + (** Creates a real constant. *) + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx (Symbol.mk_string ctx name) + + (** + Create a real from a fraction. + + @param num numerator of rational. + @param den denominator of rational. + @return A Term with value / and sort Real + + *) + let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + create_num ctx (Z3native.mk_real (context_gno ctx) num den) + + (** + Create a real numeral. + @param v A string representing the Term value in decimal notation. + @return A Term with value and sort Real + *) + let mk_numeral_s ( ctx : context ) ( v : string ) = + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + (** + Create a real numeral. + + @param v value of the numeral. + @return A Term with value and sort Real + *) + let mk_numeral_i ( ctx : context ) ( v : int ) = + create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + (** Creates an expression that checks whether a real number is an integer. *) + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + Booleans.create_expr ctx (Z3native.mk_is_int (context_gno ctx) (egno t)) + + (** + Coerce a real to an integer. + + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. + *) + let mk_real2int ( ctx : context ) ( t : real_expr ) = + Integers.create_expr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)) + end + + and AlgebraicNumbers : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val create_num : context -> Z3native.ptr -> algebraic_num + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let create_num ( ctx : context ) ( no : Z3native.ptr ) = + AlgebraicNum(create_arith_expr ctx no) + + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) + let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) + let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + + (** + Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_upper ( x : algebraic_num ) ( precision : int ) = + Reals.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + + (** + Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^. + + @param precision the precision of the result + @return A numeral Expr of sort Real + *) + let to_lower ( x : algebraic_num ) precision = + Reals.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + + (** Returns a string representation in decimal notation. + The result has at most decimal places.*) + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + (** Returns a string representation of the numeral. *) + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + end + + let aton (a : arith_expr array) = + let f (e : arith_expr) = (egno e) in + Array.map f a (** Indicates whether the term is of integer sort. *) - let is_int ( x : expr ) = - (Z3native.is_numeral_ast x#gnc x#gno) && - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT) + let is_int ( x : Expr.expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) (** Indicates whether the term is an arithmetic numeral. *) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) (** Indicates whether the term is a less-than-or-equal *) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) (** Indicates whether the term is a greater-than-or-equal *) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) (** Indicates whether the term is a less-than *) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) (** Indicates whether the term is a greater-than *) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) (** Indicates whether the term is addition (binary) *) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) (** Indicates whether the term is subtraction (binary) *) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) (** Indicates whether the term is a unary minus *) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) (** Indicates whether the term is multiplication (binary) *) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) (** Indicates whether the term is division (binary) *) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) (** Indicates whether the term is integer division (binary) *) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) (** Indicates whether the term is remainder (binary) *) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) (** Indicates whether the term is modulus (binary) *) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) (** Indicates whether the term is a coercion of integer to real (unary) *) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) (** Indicates whether the term is a coercion of real to integer (unary) *) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) (** Indicates whether the term is of sort real. *) - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT) + let is_real ( x : Expr.expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) (** Indicates whether the term is an integer numeral. *) - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + let is_int_numeral ( x : Expr.expr ) = (Expr.is_numeral x) && (is_int x) (** Indicates whether the term is a real numeral. *) - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + let is_rat_num ( x : Expr.expr ) = (Expr.is_numeral x) && (is_real x) (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number x#gnc x#gno - - (** Retrieve the int value. *) - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int x#gnc x#gno in - if r then v - else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) - let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno - - (** The numerator of a rational numeral. *) - let get_numerator ( x : rat_num ) = - (new int_num x#gc)#create_obj (Z3native.get_numerator x#gnc x#gno) - - (** The denominator of a rational numeral. *) - let get_denominator ( x : rat_num ) = - (new int_num x#gc)#create_obj (Z3native.get_denominator x#gnc x#gno) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : rat_num ) (precision : int) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** Returns a string representation of the numeral. *) - let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno - - (** - Creates an integer constant. - *) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = - ((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr) - - (** - Creates an integer constant. - *) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) - - (** - Creates a real constant. - *) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = - ((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr) - - (** - Creates a real constant. - *) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let is_algebraic_number ( x : Expr.expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) (** Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - (create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (AST.aton t)) :> arith_expr) + Arithmetic.create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Arithmetic.aton t)) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - ArithExpr(create ctx (Z3native.mk_unary_minus (context_gno ctx) - (gno (match t with ArithExpr(b) -> b)))) + Arithmetic.create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t)) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - ArithExpr(create ctx (Z3native.mk_div (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an expression representing t1 mod t2. - The arguments must have int type. - *) - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - IntExpr(create ctx (Z3native.mk_mod (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an expression representing t1 rem t2. - The arguments must have int type. - *) - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - IntExpr(create ctx (Z3native.mk_rem (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Arithmetic.create_expr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 ^ t2. *) - let mk_power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - ArithExpr(create_expr ctx (Z3native.mk_power (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Arithmetic.create_expr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 < t2 *) - let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_lt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 <= t2 *) - let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_le (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 > t2 *) - let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_gt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 >= t2 *) - let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - BoolExpr(create ctx (Z3native.mk_ge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - *) - let mk_int2real ( ctx : context ) ( t : int_expr ) = - RealExpr(create (Z3native.mk_int2real (context_gno ctx) - (gno (match t with BoolExpr(b) -> b)))) - - (** - Coerce a real to an integer. - - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - *) - let mk_real2int ( ctx : context ) ( t : real_expr ) = - (new int_expr ctx)#create_obj (Z3native.mk_real2int (context_gno ctx) t#gno) - - (** - Creates an expression that checks whether a real number is an integer. - *) - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - BoolExpr(create ctx (Z3native.mk_is_int (context_gno ctx) - (gno (match t with BoolExpr(b) -> b)))) - (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_upper ( x : algebraic_num ) ( precision : int ) = - (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision) - - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) - let to_lower ( x : algebraic_num ) precision = - (new rat_num x#gc)#create_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision) - - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string x#gnc x#gno precision - - (** - Create a real from a fraction. - - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - *) - let mk_real_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = - if (den == 0) then - raise (Z3native.Exception "Denominator is zero") - else - - (new rat_num ctx)#create_obj (Z3native.mk_real (context_gno ctx) num den) - - (** - Create a real numeral. - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - *) - let mk_real_numeral_s ( ctx : context ) ( v : string ) = - (new rat_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_real_sort ctx)#gno) - - (** - Create a real numeral. - - @param v value of the numeral. - @return A Term with value and sort Real - *) - let mk_real_numeral_i ( ctx : context ) ( v : int ) = - (new rat_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_real_sort ctx)#gno) - - (** - Create an integer numeral. - @param v A string representing the Term value in decimal notation. - *) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = - (new int_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_int_sort ctx)#gno) - - (** - Create an integer numeral. - @param v value of the numeral. - @return A Term with value and sort Integer - *) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = - (new int_num ctx)#create_obj (Z3native.mk_int (context_gno ctx) v (mk_int_sort ctx)#gno) - - (** Returns a string representation of the numeral. *) - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno + let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) end From 9845c8ee269bf2c8e0c3b32bfcfb3d735e537a8c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 5 Feb 2013 00:19:06 +0000 Subject: [PATCH 417/646] ML API: No more objects; type hierarchy exposed; clean separation into modules. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 691 ++++++++++++++++++++++++----------------------- 1 file changed, 357 insertions(+), 334 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 58c319d4d..4cf41f420 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -334,6 +334,13 @@ sig val create : context -> Z3native.ptr -> ast val aton : ast array -> Z3native.ptr array + module ASTVectors : sig + type ast_vector + val create : context -> Z3native.ptr -> ast_vector + val get_size : ast_vector -> int + val get : ast_vector -> int -> ast + end + val is_expr : ast -> bool val is_var : ast -> bool end = struct @@ -354,7 +361,7 @@ end = struct (** Vectors of ASTs *) - module ASTVector = + module ASTVectors = struct type ast_vector = z3_native_object @@ -401,7 +408,7 @@ end = struct (** Translates all ASTs in the vector to . @param to_ctx A context - @return A new ASTVector + @return A new ASTVectors *) let translate ( x : ast_vector ) ( to_ctx : context ) = create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) @@ -466,7 +473,7 @@ end = struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVectors.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -613,16 +620,15 @@ end and Sort : sig type sort = Sort of AST.ast - type bitvec_sort = BitvecSort of sort type uninterpreted_sort = UninterpretedSort of sort val create : context -> Z3native.ptr -> sort - val gno : sort -> Z3native.ptr + val gc : sort -> context val gnc : sort -> Z3native.ptr + val gno : sort -> Z3native.ptr val aton : sort array -> Z3native.ptr array end = struct type sort = Sort of AST.ast - type bitvec_sort = BitvecSort of sort type uninterpreted_sort = UninterpretedSort of sort let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) @@ -713,11 +719,14 @@ sig type func_decl = FuncDecl of AST.ast val create : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context val gno : func_decl -> Z3native.ptr val gnc : func_decl -> Z3native.ptr + val aton : func_decl array -> Z3native.ptr array val get_domain_size : func_decl -> int val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_arity : func_decl -> int end = struct open Sort @@ -1098,6 +1107,7 @@ sig val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val get_func_decl : expr -> FuncDecl.func_decl val is_numeral : expr -> bool + val to_string : expr -> string end = struct type expr = Expr of AST.ast @@ -1108,20 +1118,20 @@ end = struct let s = Z3native.get_sort (context_gno ctx) obj in let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.Expr(e)) -> e) + (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.ArithExpr(e)) -> e) else if (Z3native.is_numeral_ast (context_gno ctx) obj) && (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then match sk with - | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.Expr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.Expr(e))) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e))) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e))) -> e) | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) | _ -> raise (Z3native.Exception "Unsupported numeral object") else match sk with | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.Expr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.Expr(e)) -> e) + | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e)) -> e) + | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e)) -> e) | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) @@ -1409,6 +1419,9 @@ sig val create_expr : context -> Z3native.ptr -> bool_expr val create_sort : context -> Z3native.ptr -> bool_sort + val gc : bool_expr -> context + val gnc : bool_expr -> Z3native.ptr + val gno : bool_expr -> Z3native.ptr val aton : bool_expr array -> Z3native.ptr array end = struct type bool_expr = BoolExpr of Expr.expr @@ -2648,9 +2661,10 @@ end and Arithmetic : sig type arith_sort = ArithSort of Sort.sort - type arith_expr = Expr of Expr.expr + type arith_expr = ArithExpr of Expr.expr val create_expr : context -> Z3native.ptr -> arith_expr + val create_sort : context -> Z3native.ptr -> arith_sort val aton : arith_expr array -> Z3native.ptr array module Integers : sig @@ -2679,14 +2693,53 @@ sig val create_num : context -> Z3native.ptr -> algebraic_num end + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr array -> Arithmetic.arith_expr + val mk_mul : context -> arith_expr array -> Arithmetic.arith_expr + val mk_sub : context -> arith_expr array -> Arithmetic.arith_expr + val mk_unary_minus : + context -> arith_expr -> Arithmetic.arith_expr + val mk_div : + context -> arith_expr -> arith_expr -> Arithmetic.arith_expr + val mk_power : + context -> arith_expr -> arith_expr -> Arithmetic.arith_expr + val mk_lt : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_le : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_gt : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + val mk_ge : + context -> arith_expr -> arith_expr -> Booleans.bool_expr + end = struct type arith_sort = ArithSort of Sort.sort type arith_expr = ArithExpr of Expr.expr - let create_arith_expr ( ctx : context ) ( no : Z3native.ptr ) = + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) - let create_arith_sort ( ctx : context ) ( no : Z3native.ptr ) = + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = ArithSort(Sort.create ctx no) let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) @@ -2712,10 +2765,10 @@ end = struct type int_num = IntNum of int_expr let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - IntSort(create_arith_sort ctx no) + IntSort(Arithmetic.create_sort ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(create_arith_expr ctx no) + IntExpr(Arithmetic.create_expr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = IntNum(create_expr ctx no) @@ -2796,6 +2849,19 @@ end = struct *) let mk_int2real ( ctx : context ) ( t : int_expr ) = Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + + (** + Create an bit bit-vector from the integer argument . + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. + *) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + BitVectors.create_expr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t)) end and Reals : @@ -2813,10 +2879,10 @@ end = struct type rat_num = RatNum of real_expr let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - RealSort(create_arith_sort ctx no) + RealSort(Arithmetic.create_sort ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(create_arith_expr ctx no) + RealExpr(Arithmetic.create_expr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = RatNum(create_expr ctx no) @@ -2914,7 +2980,7 @@ end = struct type algebraic_num = AlgebraicNum of arith_expr let create_num ( ctx : context ) ( no : Z3native.ptr ) = - AlgebraicNum(create_arith_expr ctx no) + AlgebraicNum(Arithmetic.create_expr ctx no) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) @@ -3126,316 +3192,330 @@ end (** Functions to manipulate bit-vector expressions *) and BitVectors : sig + type bitvec_sort = BitVecSort of Sort.sort type bitvec_expr = BitVecExpr of Expr.expr type bitvec_num = BitVecNum of bitvec_expr + val create_sort : context -> Z3native.ptr -> bitvec_sort val create_expr : context -> Z3native.ptr -> bitvec_expr val create_num : context -> Z3native.ptr -> bitvec_num end = struct - type bitvec_expr = Expr of Expr.expr - type bitvec_num = BitVecExpr of bitvec_expr + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + BitVecSort(Sort.create ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in - BitVecExpr(e) + BitVecExpr(Expr.create ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - let e = (create_expr ctx no) in - BitVecNum(e) + BitVecNum(create_expr ctx no) + + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) + let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) + let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) + let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) + let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - (new bitvec_sort ctx)#create_obj (Z3native.mk_bv_sort (context_gno ctx) size) + create_sort ctx (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. *) - let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT) + let is_bv ( x : Expr.expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_ult ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_slt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_and ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_or ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_not ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) (** The size of a bit-vector sort. *) - let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno + let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int x#gnc x#gno in + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") (** Returns a string representation of the numeral. *) - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a bit-vector constant. *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - ((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr) + BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) (** Creates a bit-vector constant. @@ -3448,91 +3528,91 @@ end = struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnot (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredand (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvredor (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvand (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnand (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvnor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvxnor (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvneg (context_gno ctx) t#gno) + create_expr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvadd (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsub (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvmul (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3544,7 +3624,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvudiv (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3559,7 +3639,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsdiv (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3569,7 +3649,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvurem (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3581,7 +3661,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsrem (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3590,7 +3670,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_bvsmod (context_gno ctx) t1#gno t2#gno) + create_expr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3598,9 +3678,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvult (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed less-than @@ -3608,9 +3686,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvslt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than or equal to. @@ -3618,9 +3694,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvule (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed less-than or equal to. @@ -3628,9 +3702,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsle (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2)) (** Unsigned greater than or equal to. @@ -3638,19 +3710,15 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvuge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed greater than or equal to. The arguments must have the same bit-vector sort. *) - let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsge (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Booleans.create_expr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2)) (** Unsigned greater-than. @@ -3658,9 +3726,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvugt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed greater-than. @@ -3668,9 +3734,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsgt (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector concatenation. @@ -3681,9 +3745,7 @@ end = struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVectors.BitVecExpr(create ctx (Z3native.mk_concat (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3694,7 +3756,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - (new bitvec_expr ctx)#create_obj (Z3native.mk_extract (context_gno ctx) high low t#gno) + create_expr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3704,7 +3766,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_sign_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3715,7 +3777,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_zero_ext (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3723,7 +3785,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_repeat (context_gno ctx) i (gno (match t with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3738,9 +3800,8 @@ end = struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvshl (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + (** Logical shift right @@ -3754,9 +3815,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvlshr (context_gno ctx) - (gno (match t1 with BitVecExpr(b) -> b)) - (gno (match t2 with BitVecExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3772,9 +3831,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_bvashr (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3783,7 +3840,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_rotate_left (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3792,7 +3849,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_rotate_right (context_gno ctx) i (gno (match t with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3801,9 +3858,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_ext_rotate_left (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + create_expr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3813,22 +3868,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BitVecExpr(create ctx (Z3native.mk_ext_rotate_right (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - - (** - Create an bit bit-vector from the integer argument . - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - *) - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVecExpr(create ctx (Z3native.mk_int2bv (context_gno ctx) n (gno (match t with IntExpr(b) -> b)))) + create_expr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3845,8 +3885,8 @@ end = struct The argument must be of bit-vector sort. *) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) = - (new int_expr ctx)#create_obj (Z3native.mk_bv2int (context_gno ctx) t#gno signed) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = + Arithmetic.Integers.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3854,10 +3894,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3865,19 +3902,15 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) - + Booleans.create_expr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2)) + (** Create a predicate that checks that the bit-wise subtraction does not overflow. The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2)) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3885,10 +3918,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3896,17 +3926,15 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2)) (** Create a predicate that checks that the bit-wise negation does not overflow. The arguments must be of bit-vector sort. *) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) = - BoolExpr(create ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (gno (match t with BitVecExpr(b) -> b)))) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = + Booleans.create_expr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t)) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3914,10 +3942,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - BoolExpr(create ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)) - signed)) + Booleans.create_expr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3925,9 +3950,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - BoolExpr(create ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) - (gno (match t1 with BoolExpr(b) -> b)) - (gno (match t2 with BoolExpr(b) -> b)))) + Booleans.create_expr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2)) (** Create a bit-vector numeral. @@ -3936,7 +3959,7 @@ end = struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = - (new bitvec_num ctx)#create_obj (Z3native.mk_numeral (context_gno ctx) v (mk_sort ctx size)#gno) + create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) end (** Functions to manipulate proof expressions *) @@ -3946,17 +3969,17 @@ end = struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -3967,7 +3990,7 @@ end = struct [mp T1 T2]: q The second antecedents may also be a proof for (iff p q). *) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. @@ -3976,7 +3999,7 @@ end = struct equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. *) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -3986,7 +4009,7 @@ end = struct [symmetry T1]: (R s t) T1 is the antecedent of this proof object. *) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -3997,7 +4020,7 @@ end = struct T2: (R s u) [trans T1 T2]: (R t u) *) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -4017,7 +4040,7 @@ end = struct if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. *) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -4030,7 +4053,7 @@ end = struct Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. *) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -4039,7 +4062,7 @@ end = struct T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -4056,7 +4079,7 @@ end = struct Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. *) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -4065,7 +4088,7 @@ end = struct T1: (and l_1 ... l_n) [and-elim T1]: l_i *) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -4074,7 +4097,7 @@ end = struct T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) *) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -4088,11 +4111,11 @@ end = struct Remark: if f is bool, then = is iff. Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) + (= (+ ( x : Expr.expr ) 0) x) + (= (+ ( x : Expr.expr ) 1 2) (+ 3 x)) + (iff (or ( x : Expr.expr ) false) x) *) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -4107,14 +4130,14 @@ end = struct - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -4123,7 +4146,7 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents *) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -4136,7 +4159,7 @@ end = struct This proof object has no antecedents *) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_push_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -4148,34 +4171,34 @@ end = struct This proof object has no antecedents. *) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_elim_unused_vars ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. + (iff (forall (x) (or (not (= ( x : Expr.expr ) t)) P[x])) P[t]) + if ( x : Expr.expr ) does not occur in t. This proof object has no antecedents. Several variables can be eliminated simultaneously. *) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_der ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) *) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. Mark a hypothesis in a natural deduction style proof. *) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -4187,7 +4210,7 @@ end = struct It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. *) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -4198,7 +4221,7 @@ end = struct T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true @@ -4206,7 +4229,7 @@ end = struct T1: p [iff-true T1]: (iff p true) *) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false @@ -4214,7 +4237,7 @@ end = struct T1: (not p) [iff-false T1]: (iff p false) *) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -4226,7 +4249,7 @@ end = struct This proof object has no antecedents. Remark: if f is bool, then = is iff. *) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -4261,7 +4284,7 @@ end = struct unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -4283,7 +4306,7 @@ end = struct Otherwise: [def-intro]: (= n e) *) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -4292,7 +4315,7 @@ end = struct F is 'equivalent' to n, given that T1 is a proof that n is a name for F. *) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq @@ -4300,7 +4323,7 @@ end = struct T1: (iff p q) [iff~ T1]: (~ p q) *) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -4327,7 +4350,7 @@ end = struct NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. *) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -4351,7 +4374,7 @@ end = struct [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) *) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -4362,7 +4385,7 @@ end = struct This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -4371,19 +4394,19 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step Proof for: - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + [sk]: (~ (not (forall ( x : Expr.expr ) (p ( x : Expr.expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : Expr.expr ) (p ( x : Expr.expr ) y)) (p (sk y) y)) This proof object has no antecedents. *) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -4393,7 +4416,7 @@ end = struct T2: (~ p q) [mp~ T1 T2]: q *) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -4411,7 +4434,7 @@ end = struct (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_theory_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end @@ -4462,8 +4485,8 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : bool_expr array ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) e#gno in + let assert_ ( x : goal ) ( constraints : Booleans.bool_expr array ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) in ignore (Array.map f constraints) ; () @@ -4484,7 +4507,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (new bool_expr (z3obj_gc x))#create_obj (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = Booleans.create_expr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4599,7 +4622,7 @@ struct Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - create_expr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + Expr.create (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. @@ -4611,7 +4634,7 @@ struct *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (create_expr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (Expr.create (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4639,7 +4662,7 @@ struct (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = create_expr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + let get_else ( x : func_interp ) = Expr.create (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation @@ -4666,31 +4689,31 @@ struct (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : func_decl ) = + let get_const_interp ( x : model ) ( f : FuncDecl.func_decl ) = if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then + (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") else - let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in if (Z3native.is_null np) then None else - Some (create_expr (z3obj_gc x) np) + Some (Expr.create (z3obj_gc x) np) (** Retrieves the interpretation (the assignment) of in the model. A Constant An expression if the constant has an interpretation in the model, null otherwise. *) - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + let get_const_interp_e ( x : model ) ( a : Expr.expr ) = get_const_interp x (Expr.get_func_decl a) (** Retrieves the interpretation (the assignment) of a non-constant in the model. A function declaration of non-zero arity A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range f#gnc f#gno))) in + let rec get_func_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) f#gno in + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in if (Z3native.is_null n) then None else @@ -4700,10 +4723,10 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x ((new func_decl f#gc)#create_obj fd) + get_func_interp x (FuncDecl.create (z3obj_gc x) fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else - let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) f#gno) in + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) (** The number of constants that have an interpretation in the model. *) @@ -4712,7 +4735,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4722,15 +4745,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = (new func_decl (z3obj_gc x))#create_obj (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4751,15 +4774,15 @@ struct The evaluation of in the model. *) - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) t#gno completion) in + let eval ( x : model ) ( t : Expr.expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else - create_expr (z3obj_gc x) v + Expr.create (z3obj_gc x) v (** Alias for eval. *) - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + let evaluate ( x : model ) ( t : Expr.expr ) ( completion : bool ) = eval x t completion (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -4775,7 +4798,7 @@ struct *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in - let f i = (create_sort (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (Sort.create (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f @@ -4784,10 +4807,10 @@ struct An uninterpreted sort An array of expressions, where each is an element of the universe of *) - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) s#gno) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in + let sort_universe ( x : model ) ( s : Sort.sort ) = + let n_univ = AST.ASTVectors.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVectors.get_size n_univ) in + let f i = (AST.ASTVectors.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -5323,8 +5346,8 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : bool_expr array ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in + let assert_ ( x : solver ) ( constraints : Booleans.bool_expr array ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in ignore (Array.map f constraints) (** @@ -5340,11 +5363,11 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : Booleans.bool_expr array ) ( ps : Booleans.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) e#gno (Array.get ps i)#gno) in + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) (Booleans.gno (Array.get ps i))) in ignore (Array.iteri f cs) (** @@ -5359,24 +5382,24 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) c#gno p#gno + let assert_and_track ( x : solver ) ( c : Booleans.bool_expr ) ( p : Booleans.bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno c) (Booleans.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVector.get_size a) + let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVectors.get_size a) (** The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size a) in - let f i = ((new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get a i)#gno) in + let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVectors.get_size a) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get a i)) in Array.init n f (** @@ -5386,12 +5409,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array) = + let check ( x : solver ) ( assumptions : Booleans.bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (AST.aton assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Booleans.aton assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5422,7 +5445,7 @@ struct if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** The unsat core of the last Check. @@ -5432,9 +5455,9 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size cn) in - let f i = (AST.ASTVector.get cn i) in + let cn = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVectors.get_size cn) in + let f i = (AST.ASTVectors.get cn i) in Array.init n f (** @@ -5527,30 +5550,30 @@ struct (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) e#gno) in + let assert_ ( x : fixedpoint ) ( constraints : Booleans.bool_expr array ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in ignore (Array.map f constraints) ; () (** Register predicate as recursive relation. *) - let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) f#gno + let register_relation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) = + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno y) (** Add table fact to the fixedpoint solver. *) - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) pred#gno (Array.length args) args + let add_fact ( x : fixedpoint ) ( pred : FuncDecl.func_decl ) ( args : int array ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args (** Query the fixedpoint solver. @@ -5558,8 +5581,8 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) query#gno)) with + let query ( x : fixedpoint ) ( query : Booleans.bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Booleans.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5570,8 +5593,8 @@ struct The query is satisfiable if there is an instance of some relation that is non-empty. The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - let query_r ( x : fixedpoint ) ( relations : func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (func_declaton relations))) with + let query_r ( x : fixedpoint ) ( relations : FuncDecl.func_decl array ) = + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (FuncDecl.aton relations))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -5595,8 +5618,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) rule#gno (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5607,7 +5630,7 @@ struct if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. @@ -5618,25 +5641,25 @@ struct (** Retrieve the number of levels explored for a given predicate. *) - let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) predicate#gno + let get_num_levels ( x : fixedpoint ) ( predicate : FuncDecl.func_decl ) = + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) (** Retrieve the cover of a predicate. *) - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level predicate#gno) in + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then None else - Some (create_expr (z3obj_gc x) q) + Some (Expr.create (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level predicate#gno property#gno + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) ( property : Expr.expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) (** Retrieve internal string representation of fixedpoint object. @@ -5646,31 +5669,31 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) f#gno (Array.length kinds) (Symbol.aton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) ( kinds : Symbol.symbol array ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Symbol.aton kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (AST.aton queries) + let to_string_q ( x : fixedpoint ) ( queries : Booleans.bool_expr array ) = + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Booleans.aton queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in + let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVectors.get_size v) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = (new bool_expr (z3obj_gc x))#create_obj (AST.ASTVector.get v i)#gno in + let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVectors.get_size v) in + let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in Array.init n f (** @@ -5754,10 +5777,10 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Booleans.bool_expr array ) ( formula : Booleans.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (AST.aton assumptions) - formula#gno + (Array.length assumptions) (Booleans.aton assumptions) + (Booleans.gno formula) (** Parse the given string using the SMT-LIB parser. @@ -5768,7 +5791,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5779,16 +5802,16 @@ struct Z3native.parse_smtlib_string (context_gno ctx) str cs (Symbol.aton sort_names) - (AST.aton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5799,10 +5822,10 @@ struct Z3native.parse_smtlib_file (context_gno ctx) file_name cs (Symbol.aton sort_names) - (AST.aton sorts) + (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. @@ -5814,7 +5837,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) :> bool_expr) in + let f i = Booleans.create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i) in Array.init n f @@ -5828,7 +5851,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = ((create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) :> bool_expr ) in + let f i = Booleans.create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i) in Array.init n f (** @@ -5841,7 +5864,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = (new func_decl ctx)#create_obj (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = FuncDecl.create ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5854,7 +5877,7 @@ struct *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (create_sort ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + let f i = (Sort.create ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5863,7 +5886,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5877,13 +5900,13 @@ struct (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5897,7 +5920,7 @@ struct (Sort.aton sorts) cd (Symbol.aton decl_names) - (func_declaton decls) + (FuncDecl.aton decls) end From 7eedf1556189b437eb67533bfa1ea11ef62333f5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 5 Feb 2013 00:51:20 +0000 Subject: [PATCH 418/646] ML API: documentation fixes. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 246 +++++++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 105 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4cf41f420..aeb9c0d03 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -331,8 +331,10 @@ module rec AST : sig type ast = z3_native_object +(**/**) val create : context -> Z3native.ptr -> ast val aton : ast array -> Z3native.ptr array +(**/**) module ASTVectors : sig type ast_vector @@ -346,6 +348,7 @@ sig end = struct type ast = z3_native_object + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -358,7 +361,7 @@ end = struct let aton (a : ast array) = let f (e : ast) = (z3obj_gno e) in Array.map f a - + (**/**) (** Vectors of ASTs *) module ASTVectors = @@ -615,7 +618,6 @@ end = struct (**/**) end - (** The Sort module implements type information for ASTs *) and Sort : sig @@ -631,6 +633,7 @@ end = struct type sort = Sort of AST.ast type uninterpreted_sort = UninterpretedSort of sort + (**/**) let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -657,6 +660,7 @@ end = struct | FINITE_DOMAIN_SORT | RELATION_SORT -> Sort(q) | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + (**/**) (** @@ -728,10 +732,9 @@ sig val get_decl_kind : func_decl -> Z3enums.decl_kind val get_arity : func_decl -> int end = struct - open Sort - type func_decl = FuncDecl of AST.ast + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res = { m_ctx = ctx ; m_n_obj = null ; @@ -741,7 +744,7 @@ end = struct (z3obj_create res) ; FuncDecl(res) - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -750,7 +753,7 @@ end = struct (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -766,7 +769,8 @@ end = struct let aton (a : func_decl array) = let f (e : func_decl) = (gno e) in Array.map f a - + (**/**) + (** Parameters of Func_Decls *) module Parameter = struct @@ -833,18 +837,16 @@ end = struct | _ -> raise (Z3native.Exception "parameter is not a rational string") end - open Parameter - (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = create_ndr ctx name domain range (** Creates a new function declaration. *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** @@ -852,19 +854,19 @@ end = struct *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = create_pdr ctx prefix domain range (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = create_ndr ctx name [||] range (** Creates a new constant function declaration. *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range (** @@ -872,7 +874,7 @@ end = struct *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = create_pdr ctx prefix [||] range @@ -945,13 +947,13 @@ end = struct let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n @@ -977,6 +979,7 @@ sig type param_descrs = z3_native_object val create : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit end end = struct type params = z3_native_object @@ -998,6 +1001,7 @@ end = struct type param_descrs = z3_native_object val create : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit end = struct type param_descrs = z3_native_object @@ -1025,7 +1029,7 @@ end = struct let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - + (** The size of the ParamDescrs. *) let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) @@ -1092,7 +1096,7 @@ end = struct let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end -(** General expressions (terms), including Boolean logic *) +(** General expressions (terms) *) and Expr : sig type expr = Expr of AST.ast @@ -1111,6 +1115,7 @@ sig end = struct type expr = Expr of AST.ast + (**/**) let create ( ctx : context ) ( obj : Z3native.ptr ) = if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) @@ -1148,7 +1153,12 @@ end = struct let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) - + + let aton (a : expr array) = + let f (e : expr) = (gno e) in + Array.map f a + (**/**) + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier @@ -1405,10 +1415,6 @@ end = struct *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) - - let aton (a : expr array) = - let f (e : expr) = (gno e) in - Array.map f a end (** Boolean expressions *) @@ -1427,6 +1433,7 @@ end = struct type bool_expr = BoolExpr of Expr.expr type bool_sort = BoolSort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in BoolExpr(Expr.Expr(a)) @@ -1441,6 +1448,7 @@ end = struct let aton ( a : bool_expr array ) = let f (e : bool_expr) = (gno e) in Array.map f a + (**/**) let mk_sort ( ctx : context ) = BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) @@ -1542,6 +1550,7 @@ sig end = struct type quantifier = Quantifier of Expr.expr + (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let a = (AST.create ctx no) in Quantifier(Expr.Expr(a)) @@ -1549,7 +1558,61 @@ end = struct let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - + (**/**) + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. + *) + module Patterns : + sig + type pattern = Pattern of AST.ast + + val create : context -> Z3native.ptr -> pattern + val aton : pattern array -> Z3native.ptr array + end = struct + type pattern = Pattern of AST.ast + + (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + Pattern(res) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + + let aton (a : pattern array) = + let f (e : pattern) = (gno e) in + Array.map f a + (**/**) + + (** + The number of terms in the pattern. + *) + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms (gnc x) (gno x) + + (** + The terms in the pattern. + *) + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + Array.init n f + + (** + A string representation of the pattern. + *) + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + end (** The de-Burijn index of a bound variable. @@ -1575,58 +1638,6 @@ end = struct else Z3native.get_index_value (Expr.gnc x) (Expr.gno x) - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) - module Patterns : - sig - type pattern = Pattern of AST.ast - - val create : context -> Z3native.ptr -> pattern - val aton : pattern array -> Z3native.ptr array - end = struct - type pattern = Pattern of AST.ast - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - Pattern(res) - - let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) - let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) - let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - - (** - The number of terms in the pattern. - *) - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - - (** - The terms in the pattern. - *) - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - Array.init n f - - (** - A string representation of the pattern. - *) - let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) - - let aton (a : pattern array) = - let f (e : pattern) = (gno e) in - Array.map f a - end - (** Indicates whether the quantifier is universal. *) @@ -1849,6 +1860,7 @@ end = struct type array_expr = ArrayExpr of Expr.expr type array_sort = ArraySort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let e = (Expr.create ctx no) in ArrayExpr(e) @@ -1868,7 +1880,7 @@ end = struct let aton (a : array_expr array) = let f (e : array_expr) = (egno e) in Array.map f a - + (**/**) (** Create a new array sort. @@ -2120,6 +2132,7 @@ sig end = struct type finite_domain_sort = FiniteDomainSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in FiniteDomainSort(s) @@ -2127,7 +2140,8 @@ end = struct let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) + (** Create a new finite domain sort. *) @@ -2168,6 +2182,7 @@ sig end = struct type relation_sort = RelationSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in RelationSort(s) @@ -2175,7 +2190,8 @@ end = struct let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) + (** Indicates whether the term is of a relation sort. *) @@ -2306,6 +2322,7 @@ end = struct type datatype_expr = DatatypeExpr of Expr.expr type datatype_sort = DatatypeSort of Sort.sort + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = let e = (Expr.create ctx no) in DatatypeExpr(e) @@ -2317,19 +2334,24 @@ end = struct let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) - + (**/**) (** Constructors *) - module Constructor = - struct + module Constructor : sig + type constructor + val create : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> constructor + val aton : constructor array -> Z3native.ptr array + end = struct type constructor_extra = { m_n : int; mutable m_tester_decl : FuncDecl.func_decl option; mutable m_constructor_decl : FuncDecl.func_decl option ; mutable m_accessor_decls : FuncDecl.func_decl array option} + type constructor = Constructor of (z3_native_object * constructor_extra) - let create_ssssi ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + (**/**) + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2356,6 +2378,10 @@ end = struct let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; Constructor(no, ex) + + let aton ( a : constructor array ) = + let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in + Array.map f a let init_extra ( x : constructor ) = match x with Constructor(no, ex) -> @@ -2367,7 +2393,8 @@ end = struct ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; () | _ -> () - + (**/**) + let get_n ( x : constructor ) = match x with Constructor(no, ex) -> ex.m_n @@ -2389,12 +2416,7 @@ end = struct match ex.m_accessor_decls with | Some(s) -> s | None -> init_extra x ; accessor_decls x - - let aton ( a : constructor array ) = - let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in - Array.map f a - - + (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2413,6 +2435,7 @@ end = struct struct type constructor_list = z3_native_object + (**/**) let create ( ctx : context )( c : Constructor.constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; @@ -2427,6 +2450,7 @@ end = struct let aton (a : constructor_list array) = let f (e : constructor_list) = (z3obj_gno e) in Array.map f a + (**/**) end (* DATATYPES *) @@ -2441,7 +2465,7 @@ end = struct referring to one of the recursive datatypes that is declared. *) let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = - Constructor.create_ssssi ctx name recognizer field_names sorts sort_refs + Constructor.create ctx name recognizer field_names sorts sort_refs (** @@ -2530,6 +2554,7 @@ end = struct mutable _testerdecls : FuncDecl.func_decl array } type enum_sort = EnumSort of (Sort.sort * enum_sort_data) + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (Sort.create ctx no) in let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; @@ -2539,7 +2564,7 @@ end = struct let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) - + (**/**) (** Create a new enumeration sort. @@ -2576,6 +2601,7 @@ end = struct _taildecl : FuncDecl.func_decl } type list_sort = ListSort of (Sort.sort * list_sort_data) + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (Sort.create ctx no) in let e = {_nildecl = FuncDecl.create ctx nildecl; @@ -2589,7 +2615,7 @@ end = struct let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) - + (**/**) (** Create a new list sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = @@ -2629,6 +2655,7 @@ sig end = struct type tuple_sort = TupleSort of Sort.sort + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = let s = (Sort.create ctx no) in TupleSort(s) @@ -2636,6 +2663,7 @@ end = struct let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) + (**/**) (** Create a new tuple sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = @@ -2736,6 +2764,7 @@ end = struct type arith_sort = ArithSort of Sort.sort type arith_expr = ArithExpr of Expr.expr + (**/**) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = ArithExpr(Expr.create ctx no) @@ -2749,6 +2778,10 @@ end = struct let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + let aton (a : arith_expr array) = + let f (e : arith_expr) = (egno e) in + Array.map f a + (**/**) module rec Integers : sig @@ -2764,6 +2797,7 @@ end = struct type int_expr = IntExpr of arith_expr type int_num = IntNum of int_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = IntSort(Arithmetic.create_sort ctx no) @@ -2782,6 +2816,7 @@ end = struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + (**/**) (** Create a new integer sort. *) let mk_sort ( ctx : context ) = @@ -2878,6 +2913,7 @@ end = struct type real_expr = RealExpr of arith_expr type rat_num = RatNum of real_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = RealSort(Arithmetic.create_sort ctx no) @@ -2896,7 +2932,8 @@ end = struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - + (**/**) + (** Create a real sort. *) let mk_sort ( ctx : context ) = create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) @@ -2979,12 +3016,14 @@ end = struct end = struct type algebraic_num = AlgebraicNum of arith_expr + (**/**) let create_num ( ctx : context ) ( no : Z3native.ptr ) = AlgebraicNum(Arithmetic.create_expr ctx no) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + (**/**) (** Return a upper bound for a given real algebraic number. @@ -3015,10 +3054,6 @@ end = struct let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) end - let aton (a : arith_expr array) = - let f (e : arith_expr) = (egno e) in - Array.map f a - (** Indicates whether the term is of integer sort. *) @@ -3188,7 +3223,6 @@ end = struct Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) end - (** Functions to manipulate bit-vector expressions *) and BitVectors : sig @@ -3204,6 +3238,7 @@ end = struct type bitvec_expr = BitVecExpr of Expr.expr type bitvec_num = BitVecNum of bitvec_expr + (**/**) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = BitVecSort(Sort.create ctx no) @@ -3222,6 +3257,7 @@ end = struct let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) + (**/**) (** Create a new bit-vector sort. From 7ec027dadb4ae56497ce8b9aaadfe2000d701ef8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 19:49:27 +0000 Subject: [PATCH 419/646] ML API: basic structure and interface Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 81 +- scripts/update_api.py | 30 +- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 2714 +++++++++++++++++++---------------------- 4 files changed, 1380 insertions(+), 1447 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 1d3412c30..cfea8d0f1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1350,10 +1350,17 @@ class MLComponent(Component): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + cmis = '%s/z3enums.cmi %s/z3native.cmi %s/z3.cmi' % (src_dir,src_dir,src_dir) + out.write('%s/z3enums.cmi: %s/z3enums.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3enums.mli\n' % (OCAMLC,src_dir,src_dir)) + out.write('%s/z3native.cmi: %s/z3native.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3native.mli\n' % (OCAMLC,src_dir,src_dir)) + out.write('%s/z3.cmi: %s/z3.mli\n' % (src_dir,src_dir)) + out.write('\t%s -I %s -c %s/z3.mli\n' % (OCAMLC,src_dir,src_dir)) out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(src_dir, mlfile)) out.write('\n') @@ -1361,7 +1368,7 @@ class MLComponent(Component): if DEBUG_MODE: out.write('-g ') out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) - out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT)' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) out.write('\n') @@ -2732,6 +2739,76 @@ def mk_z3consts_ml(api_files): efile.write('end\n') if VERBOSE: print "Generated '%s/z3enums.ml'" % ('%s' % gendir) + efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') + efile.write('(* Automatically generated file *)\n\n') + efile.write('(** The enumeration types of Z3. *)\n\n') + for api_file in api_files: + api_file_c = ml.find_file(api_file, ml.name) + api_file = os.path.join(api_file_c.src_dir, api_file) + + api = open(api_file, 'r') + + SEARCHING = 0 + FOUND_ENUM = 1 + IN_ENUM = 2 + + mode = SEARCHING + decls = {} + idx = 0 + + linenum = 1 + for line in api: + m1 = blank_pat.match(line) + m2 = comment_pat.match(line) + if m1 or m2: + # skip blank lines and comments + linenum = linenum + 1 + elif mode == SEARCHING: + m = typedef_pat.match(line) + if m: + mode = FOUND_ENUM + m = typedef2_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + elif mode == FOUND_ENUM: + m = openbrace_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + else: + assert False, "Invalid %s, line: %s" % (api_file, linenum) + else: + assert mode == IN_ENUM + words = re.split('[^\-a-zA-Z0-9_]+', line) + m = closebrace_pat.match(line) + if m: + name = words[1] + if name not in DeprecatedEnums: + efile.write('(** %s *)\n' % name[3:]) + efile.write('type %s =\n' % name[3:]) # strip Z3_ + for k, i in decls.iteritems(): + efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write('\n') + efile.write('(** Convert %s to int*)\n' % name[3:]) + efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_ + efile.write('(** Convert int to %s*)\n' % name[3:]) + efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ + efile.write('\n') + mode = SEARCHING + else: + if words[2] != '': + if len(words[2]) > 1 and words[2][1] == 'x': + idx = int(words[2], 16) + else: + idx = int(words[2]) + decls[words[1]] = idx + idx = idx + 1 + linenum = linenum + 1 + if VERBOSE: + print "Generated '%s/z3enums.mli'" % ('%s' % gendir) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index c730a325e..6e9c14355 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1147,49 +1147,66 @@ def mk_ml(): return ml_dir = get_component('ml').src_dir ml_nativef = os.path.join(ml_dir, 'z3native.ml') + ml_nativefi = os.path.join(ml_dir, 'z3native.mli') ml_wrapperf = os.path.join(ml_dir, 'z3native.c') ml_native = open(ml_nativef, 'w') + ml_i = open(ml_nativefi, 'w') ml_native.write('(* Automatically generated file *)\n\n') ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') + ml_i.write('(* Automatically generated file *)\n\n') + ml_i.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_native.write('open Z3enums\n\n') ml_native.write('(**/**)\n') ml_native.write('type ptr\n') + ml_i.write('type ptr\n') ml_native.write('and z3_symbol = ptr\n') + ml_i.write('and z3_symbol = ptr\n') for k, v in Type2Str.iteritems(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) + ml_i.write('and %s = ptr\n' % v.lower()) ml_native.write('\n') - ml_native.write('external is_null : ptr -> bool\n') - ml_native.write(' = "n_is_null"\n\n') - ml_native.write('external mk_null : unit -> ptr\n') - ml_native.write(' = "n_mk_null"\n\n') + ml_i.write('\n') + ml_native.write('external is_null : ptr -> bool\n = "n_is_null"\n\n') + ml_native.write('external mk_null : unit -> ptr\n = "n_mk_null"\n\n') ml_native.write('exception Exception of string\n\n') + ml_i.write('val is_null : ptr -> bool\n') + ml_i.write('val mk_null : unit -> ptr\n') + ml_i.write('exception Exception of string\n\n') # ML declarations - ml_native.write(' module ML2C = struct\n\n') + ml_native.write('module ML2C = struct\n\n') for name, result, params in _dotnet_decls: ml_native.write(' external n_%s : ' % ml_method_name(name)) + ml_i.write('val %s : ' % ml_method_name(name)) ip = inparams(params) op = outparams(params) if len(ip) == 0: - ml_native.write(' unit -> ') + ml_native.write(' unit -> ') for p in ip: ml_native.write('%s -> ' % param2ml(p)) + ml_i.write('%s -> ' % param2ml(p)) if len(op) > 0: ml_native.write('(') + ml_i.write('(') first = True if result != VOID or len(op) == 0: ml_native.write('%s' % type2ml(result)) + ml_i.write('%s' % type2ml(result)) first = False for p in op: if first: first = False else: ml_native.write(' * ') + ml_i.write(' * ') ml_native.write('%s' % param2ml(p)) + ml_i.write('%s' % param2ml(p)) if len(op) > 0: ml_native.write(')') + ml_i.write(')') ml_native.write('\n') + ml_i.write('\n') ml_native.write(' = "n_%s"\n' % ml_method_name(name)) if len(ip) > 5: ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) @@ -1201,6 +1218,7 @@ def mk_ml(): ip = inparams(params) op = outparams(params) ml_native.write(' let %s ' % ml_method_name(name)) + first = True i = 0; for p in params: diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index ad5442327..abcefa4af 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.ml -hide Z3 + ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.mli -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index aeb9c0d03..ea8c9576e 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,8 +7,479 @@ open Z3enums -(** Interaction logging for Z3 +(* Some helpers. *) +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) + +(* Internal types *) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = z3_native_context + + + +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } + + +(* Symbol types *) +type int_symbol = z3_native_object +type string_symbol = z3_native_object + +type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + +(* AST types *) +type ast = z3_native_object +type ast_vector = z3_native_object +type ast_map = z3_native_object + +(* FuncDecl types *) +type func_decl = FuncDecl of ast + +(* Sort types *) +type sort = Sort of ast +type uninterpreted_sort = UninterpretedSort of sort +type bool_sort = BoolSort of sort +type array_sort = ArraySort of sort +type set_sort = SetSort of sort +type datatype_sort = DatatypeSort of sort +type relation_sort = RelationSort of sort +type finite_domain_sort = FiniteDomainSort of sort +type enum_sort = EnumSort of sort +type list_sort = ListSort of sort +type tuple_sort = TupleSort of sort +type arith_sort = ArithSort of sort +type bitvec_sort = BitVecSort of sort + +type int_sort = IntSort of arith_sort +type real_sort = RealSort of arith_sort + +(* FuncDecl parameters *) +type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of symbol + | P_Srt of sort + | P_Ast of ast + | P_Fdl of func_decl + | P_Rat of string +type params = z3_native_object +type param_descrs = z3_native_object + +(* Expr types *) +type expr = Expr of ast + +type bool_expr = BoolExpr of expr +type arith_expr = ArithExpr of expr +type int_expr = IntExpr of arith_expr +type real_expr = RealExpr of arith_expr +type bitvec_expr = BitVecExpr of expr +type array_expr = ArrayExpr of expr +type datatype_expr = DatatypeExpr of expr + +(* Numerals *) +type int_num = IntNum of int_expr +type rat_num = RatNum of real_expr +type algebraic_num = AlgebraicNum of arith_expr +type bitvec_num = BitVecNum of bitvec_expr + +(* Quantifier stuff *) +type quantifier = Quantifier of expr +type pattern = Pattern of ast + +(* Datatype stuff *) +type constructor_extra = { + m_n : int; + mutable m_tester_decl : func_decl option; + mutable m_constructor_decl : func_decl option ; + mutable m_accessor_decls : func_decl array option} + +type constructor = Constructor of (z3_native_object * constructor_extra) +type constructor_list = z3_native_object + +(* Tactical interface *) +type goal = z3_native_object +type model = z3_native_object +type func_interp = z3_native_object +type func_entry = z3_native_object +type probe = z3_native_object +type tactic = z3_native_object +type apply_result = z3_native_object +type solver = z3_native_object +type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE +type statistics = z3_native_object +type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } +type fixedpoint = z3_native_object + + +(** Internal stuff *) +module Internal = +struct + let dispose_context ctx = + if ctx.m_n_obj_cnt == 0 then ( + (* Printf.printf "Disposing context \n" ; *) + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; + (* re-queue for finalization? *) + ) + + let create_context settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + (* Printf.printf "Installing finalizer on context \n" ; *) + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + (* CMW: Install error handler here! + m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. + Z3native.set_error_handler(m_ctx, m_n_err_handler); + GC.SuppressFinalize(this); + *) + + let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) + let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) + let context_gno ctx = ctx.m_n_ctx + + + let z3obj_gc o = o.m_ctx + let z3obj_gnc o = (context_gno o.m_ctx) + + let z3obj_gno o = o.m_n_obj + let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + + let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + + let z3obj_create o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + + let z3obj_nil_ref x y = () + + let array_to_native a = + let f e = (z3obj_gno e) in + Array.map f a + + (* Internal coercions *) + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + + let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + + and expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (ptr_of_ast a) in + Array.map f a + + let expr_of_func_app : context -> func_decl -> expr array -> expr = fun ctx f args -> + match f with FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (ptr_of_ast fa) (Array.length args) (expr_aton args) in + expr_of_ptr ctx o +end + + +open Internal + + + +(* Sort coercions *) +let ast_of_sort s = match s with Sort(x) -> x +let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x +let sort_of_bool_sort s = match s with BoolSort(x) -> x +let sort_of_array_sort s = match s with ArraySort(x) -> x +let sort_of_set_sort s = match s with SetSort(x) -> x +let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x +let sort_of_relation_sort s = match s with RelationSort(x) -> x +let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x +let sort_of_enum_sort s = match s with EnumSort(x) -> x +let sort_of_list_sort s = match s with ListSort(x) -> x +let sort_of_tuple_sort s = match s with TupleSort(x) -> x +let sort_of_arith_sort s = match s with ArithSort(x) -> x +let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x +let arith_sort_of_int_sort s = match s with IntSort(x) -> x +let arith_sort_of_real_sort s = match s with RealSort(x) -> x + +let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + +let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + +let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + +let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + +let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + +let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + +let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + +let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + +let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + +let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + +(* FuncDecl coercions *) +let ast_of_func_decl f = match f with FuncDecl(x) -> x + +(* Expr coercions *) +let ast_of_expr e = match e with Expr(a) -> a +let expr_of_bool_expr e = match e with BoolExpr(x) -> x +let expr_of_arith_expr e = match e with ArithExpr(x) -> x +let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x +let expr_of_array_expr e = match e with ArrayExpr(x) -> x +let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + +let arith_expr_of_int_expr e = match e with IntExpr(x) -> x +let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + +let int_expr_of_int_num e = match e with IntNum(x) -> x +let real_expr_of_rat_num e = match e with RatNum(x) -> x +let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x +let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + +let expr_of_quantifier e = match e with Quantifier(x) -> x +let ast_of_pattern e = match e with Pattern(x) -> x + + +let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + +let bool_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) + +let arith_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + +let bitvec_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + +let array_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + +let datatype_expr_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + +let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + +let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + +let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(no))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + +let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(no))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + +let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(no)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + +let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(no)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + +let quantifier_of_expr e = + match e with Expr(no) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc no) (z3obj_gno no))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + +let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + + + +(** Interaction logging for Z3 Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) module Log = @@ -28,6 +499,7 @@ struct let append s = Z3native.append_log s end + (** Version information *) module Version = struct @@ -52,11 +524,6 @@ struct string_of_int rev ^ "." end -(**/**) -(* Some helpers. *) - -let null = Z3native.mk_null() -let is_null o = (Z3native.is_null o) let mk_list ( f : int -> 'a ) ( n : int ) = let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = @@ -66,49 +533,8 @@ let mk_list ( f : int -> 'a ) ( n : int ) = (mk_list' f (i+1) n ((f i) :: tail)) in mk_list' f 0 n [] -(**/**) -(**/**) -type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } -(**/**) -type context = z3_native_context - -(**/**) - -let context_dispose ctx = - if ctx.m_n_obj_cnt == 0 then ( - (* Printf.printf "Disposing context \n" ; *) - (Z3native.del_context ctx.m_n_ctx) - ) else ( - Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) - ) - -let context_create settings = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - (* Printf.printf "Installing finalizer on context \n" ; *) - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> context_dispose o in - Gc.finalise f res; - res -(* CMW: Install error handler here! - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); -*) - -let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) -let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) -let context_gno ctx = ctx.m_n_ctx - -(**/**) - (** Create a context object. Most interactions with Z3 are interpreted in some context; many users will only @@ -130,113 +556,14 @@ let context_gno ctx = ctx.m_n_ctx *) let mk_context ( cfg : ( string * string ) list ) = - context_create cfg + create_context cfg -(**/**) -class virtual z3object ctx_init obj_init = -object (self) - val mutable m_ctx : context = ctx_init - val mutable m_n_obj : Z3native.ptr option = obj_init - - initializer - (match m_n_obj with - | Some (x) -> self#incref (context_gno m_ctx) x; - (context_add1 m_ctx) - | None -> () - ); - (* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *) - let f = fun o -> o#dispose in - let v = self in - Gc.finalise f v - - method virtual incref : Z3native.ptr -> Z3native.ptr -> unit - method virtual decref : Z3native.ptr -> Z3native.ptr -> unit - - method dispose = - (* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *) - (match m_n_obj with - | Some (x) -> - self#decref (context_gno m_ctx) x; - (context_sub1 m_ctx) ; - m_n_obj <- None; - | None -> () - ); - - method gno = match m_n_obj with - | Some(x) -> x - | None -> raise (Z3native.Exception "Z3 object lost") - - method sno (ctx : context) o = - (context_add1 m_ctx) ; - self#incref (context_gno ctx) o ; - (match m_n_obj with - | Some(x) -> self#decref (context_gno ctx) x ; (context_sub1 m_ctx) - | None -> () - ); - m_n_obj <- Some o - - method gc = m_ctx - method gnc = (context_gno m_ctx) -end - - - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - -let z3obj_gc o = o.m_ctx -let z3obj_gnc o = (context_gno o.m_ctx) - -let z3obj_gno o = o.m_n_obj -let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - -let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - -let z3obj_create o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - -let z3obj_nil_ref x y = () - -let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a -(**/**) (** Symbols are used to name several term and type constructors *) module Symbol = -struct - (** Int symbol objects *) - type int_symbol = z3_native_object - - (** String symbol objects *) - type string_symbol = z3_native_object - - (** Symbol Objects *) - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - - (**/**) +struct let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; @@ -255,6 +582,11 @@ struct (z3obj_create res) ; res + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) + let gc ( x : symbol ) = match x with | S_Int(n) -> (z3obj_gc n) @@ -269,17 +601,7 @@ struct match x with | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) - - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) - - let aton a = - let f e = (gno e) in - Array.map f a - (**/**) - + (** The kind of the symbol (int or string) *) let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) @@ -327,48 +649,11 @@ end (** The abstract syntax tree (AST) module *) -module rec AST : -sig - type ast = z3_native_object - -(**/**) - val create : context -> Z3native.ptr -> ast - val aton : ast array -> Z3native.ptr array -(**/**) - - module ASTVectors : sig - type ast_vector - val create : context -> Z3native.ptr -> ast_vector - val get_size : ast_vector -> int - val get : ast_vector -> int -> ast - end - - val is_expr : ast -> bool - val is_var : ast -> bool -end = struct - type ast = z3_native_object - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let aton (a : ast array) = - let f (e : ast) = (z3obj_gno e) in - Array.map f a - (**/**) - +module AST = +struct (** Vectors of ASTs *) - module ASTVectors = + module ASTVector = struct - type ast_vector = z3_native_object - - (**/**) let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; @@ -377,7 +662,7 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The size of the vector *) let get_size ( x : ast_vector ) = @@ -411,7 +696,7 @@ end = struct (** Translates all ASTs in the vector to . @param to_ctx A context - @return A new ASTVectors + @return A new ASTVector *) let translate ( x : ast_vector ) ( to_ctx : context ) = create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) @@ -423,10 +708,8 @@ end = struct (** Map from AST to AST *) module ASTMap = - struct - type ast_map = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; @@ -435,7 +718,7 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Checks whether the map contains the key . @param k An AST @@ -476,7 +759,7 @@ end = struct (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVectors.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = @@ -576,7 +859,7 @@ end = struct if (z3obj_gnc x) == (context_gno to_ctx) then x else - create to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Wraps an AST. @@ -590,7 +873,7 @@ end = struct @param nativeObject The native pointer to wrap. *) let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - create ctx ptr + ast_of_ptr ctx ptr (** Unwraps an AST. @@ -603,66 +886,17 @@ end = struct @param a The AST to unwrap. *) - let unwrap_ast ( x : ast ) = (z3obj_gno x) - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST -> (match (FuncDecl.create ctx no) with FuncDecl.FuncDecl(x) -> x) - | SORT_AST -> (match (Sort.create ctx no) with Sort.Sort(x) -> x) - | QUANTIFIER_AST -> (match (Quantifiers.create ctx no) with Quantifiers.Quantifier(Expr.Expr(x)) -> x) - | APP_AST - | NUMERAL_AST - | VAR_AST -> (match (Expr.create ctx no) with Expr.Expr(x) -> x) - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") -(**/**) + let unwrap_ast ( x : ast ) = (z3obj_gno x) end (** The Sort module implements type information for ASTs *) -and Sort : -sig - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - val create : context -> Z3native.ptr -> sort - val gc : sort -> context - val gnc : sort -> Z3native.ptr - val gno : sort -> Z3native.ptr - val aton : sort array -> Z3native.ptr array -end = struct - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - (**/**) +module Sort = +struct + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - let aton : sort array -> Z3native.ptr array = fun a -> - let f e = (gno e) in - Array.map f a - - let create : context -> Z3native.ptr -> sort = fun ctx no -> - let q : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno q ctx no) ; - (z3obj_create q) ; - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - (**/**) - - (** Comparison operator. @param a A sort @@ -700,7 +934,7 @@ end = struct (** Create a new uninterpreted sort. *) - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let mk_uninterpreted ( ctx : context ) ( s : symbol ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -718,71 +952,37 @@ end (** Function declarations *) -and FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - - val create : context -> Z3native.ptr -> func_decl - val gc : func_decl -> context - val gno : func_decl -> Z3native.ptr - val gnc : func_decl -> Z3native.ptr - val aton : func_decl array -> Z3native.ptr array - - val get_domain_size : func_decl -> int - val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_arity : func_decl -> int -end = struct - type func_decl = FuncDecl of AST.ast - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - FuncDecl(res) - - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = +module FuncDecl = +struct + (**/**) + let create_ndr ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + let f x = (ptr_of_ast (ast_of_sort x)) in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Sort.aton domain) (Sort.gno range))) ; + let f x = (ptr_of_ast (ast_of_sort x)) in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - - let aton (a : func_decl array) = - let f (e : func_decl) = (gno e) in - Array.map f a - (**/**) + (**/**) (** Parameters of Func_Decls *) module Parameter = - struct - type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - + struct (** The kind of the parameter. *) let get_kind ( x : parameter ) = (match x with @@ -840,13 +1040,13 @@ end = struct (** Creates a new function declaration. *) - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = create_ndr ctx name domain range (** Creates a new function declaration. *) - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range (** @@ -854,19 +1054,19 @@ end = struct *) - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : Sort.sort array ) ( range : Sort.sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = create_pdr ctx prefix domain range (** Creates a new constant function declaration. *) - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = + let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort ) = create_ndr ctx name [||] range (** Creates a new constant function declaration. *) - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range (** @@ -874,7 +1074,7 @@ end = struct *) - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = create_pdr ctx prefix [||] range @@ -917,14 +1117,14 @@ end = struct *) let get_domain ( x : func_decl ) = let n = (get_domain_size x) in - let f i = Sort.create (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in Array.init n f (** The range of the function declaration *) let get_range ( x : func_decl ) = - Sort.create (gc x) (Z3native.get_range (gnc x) (gno x)) + sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) (** The kind of the function declaration. @@ -947,13 +1147,13 @@ end = struct let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> Parameter.P_Srt (Sort.create (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> Parameter.P_Ast (AST.create (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (create (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> P_Ast (ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n @@ -961,7 +1161,7 @@ end = struct Create expression that applies function to arguments. @param args The arguments *) - let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.create_fa (gc x) x args + let apply ( x : func_decl ) ( args : expr array ) = expr_of_func_app (gc x) x args end (** @@ -969,43 +1169,12 @@ end A Params objects represents a configuration in the form of symbol/value pairs. *) -and Params : -sig - type params = z3_native_object - - val create : context -> Z3native.ptr -> params - - module ParamDescrs : sig - type param_descrs = z3_native_object - - val create : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - end -end = struct - type params = z3_native_object - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : params = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.params_inc_ref ; - dec_ref = Z3native.params_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - (**/**) - +module Params = +struct (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs : - sig - type param_descrs = z3_native_object - - val create : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - end = struct - type param_descrs = z3_native_object - - (**/**) + module ParamDescrs = + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; @@ -1014,14 +1183,14 @@ end = struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Validate a set of parameters. *) let validate ( x : param_descrs ) ( p : params ) = Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + let get_kind ( x : param_descrs ) ( name : symbol ) = (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) (** Retrieve all names of parameters. *) @@ -1040,25 +1209,25 @@ end = struct (** Adds a parameter setting. *) - let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + let add_int ( x : params ) (name : symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + let add_double ( x : params ) ( name : symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value (** Adds a parameter setting. *) - let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) (** @@ -1081,14 +1250,20 @@ end = struct (** Adds a parameter setting. *) - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = add_symbol x (Symbol.mk_string (z3obj_gc x) name) value (** Creates a new parameter set *) let mk_params ( ctx : context ) = - create ctx (Z3native.mk_params (context_gno ctx)) + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; + (z3obj_create res) ; + res (** A string representation of the parameter set. @@ -1097,76 +1272,16 @@ end = struct end (** General expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - - val create : context -> Z3native.ptr -> expr - val create_fa : context -> FuncDecl.func_decl -> expr array -> expr - val gc : expr -> context - val gno : expr -> Z3native.ptr - val gnc : expr -> Z3native.ptr - val aton : expr array -> Z3native.ptr array - - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - val get_func_decl : expr -> FuncDecl.func_decl - val is_numeral : expr -> bool - val to_string : expr -> string -end = struct - type expr = Expr of AST.ast - - (**/**) - let create ( ctx : context ) ( obj : Z3native.ptr ) = - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) obj) == QUANTIFIER_AST then - (match (Quantifiers.create ctx obj) with Quantifiers.Quantifier(e) -> e) - else - let s = Z3native.get_sort (context_gno ctx) obj in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) obj) then - (match (Arithmetic.AlgebraicNumbers.create_num ctx obj) with Arithmetic.AlgebraicNumbers.AlgebraicNum(Arithmetic.ArithExpr(e)) -> e) - else - if (Z3native.is_numeral_ast (context_gno ctx) obj) && - (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - match sk with - | INT_SORT -> (match (Arithmetic.Integers.create_num ctx obj) with Arithmetic.Integers.IntNum(Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e))) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_num ctx obj) with Arithmetic.Reals.RatNum(Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e))) -> e) - | BV_SORT -> (match (BitVectors.create_num ctx obj) with BitVectors.BitVecNum(BitVectors.BitVecExpr(e)) -> e) - | _ -> raise (Z3native.Exception "Unsupported numeral object") - else - match sk with - | BOOL_SORT -> (match (Booleans.create_expr ctx obj) with Booleans.BoolExpr(e) -> e) - | INT_SORT -> (match (Arithmetic.Integers.create_expr ctx obj) with Arithmetic.Integers.IntExpr(Arithmetic.ArithExpr(e)) -> e) - | REAL_SORT -> (match (Arithmetic.Reals.create_expr ctx obj) with Arithmetic.Reals.RealExpr(Arithmetic.ArithExpr(e)) -> e) - | BV_SORT -> (match (BitVectors.create_expr ctx obj) with BitVectors.BitVecExpr(e) -> e) - | ARRAY_SORT -> (match (Arrays.create_expr ctx obj) with Arrays.ArrayExpr(e) -> e) - | DATATYPE_SORT -> (match (Datatypes.create_expr ctx obj) with Datatypes.DatatypeExpr(e) -> e) - | _ -> Expr(AST.create ctx obj) - - let aton ( a : expr array ) = - let f ( e : expr ) = match e with Expr(a) -> (z3obj_gno a) in - Array.map f a - - let create_fa ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = - let o = Z3native.mk_app (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args) in - Expr.create ctx o - - let gc ( x : expr ) = match x with Expr(a) -> (z3obj_gc a) - let gnc ( x : expr ) = match x with Expr(a) -> (z3obj_gnc a) - let gno ( x : expr ) = match x with Expr(a) -> (z3obj_gno a) - - let aton (a : expr array) = - let f (e : expr) = (gno e) in - Array.map f a - (**/**) - +module Expr = +struct (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> Expr.create (gc x) (Z3native.simplify (gnc x) (gno x)) - | Some pp -> Expr.create (gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) + let simplify ( x : expr ) ( p : params option ) = match p with + | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) + | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) (** a string describing all available parameters to Expr.Simplify. @@ -1183,24 +1298,24 @@ end = struct (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = FuncDecl.create (gc x) (Z3native.get_app_decl (gnc x) (gno x)) + let get_func_decl ( x : expr ) = func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the expression is the true or false expression or something else (L_UNDEF). *) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) (** The number of arguments of the expression. *) - let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) + let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) (** The arguments of the expression. *) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = create (gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in + let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in Array.init n f (** @@ -1211,7 +1326,7 @@ end = struct if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - create (gc x) (Z3native.update_term (gnc x) (gno x) (Array.length args) (aton args)) + expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. @@ -1224,7 +1339,7 @@ end = struct if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - create (gc x) (Z3native.substitute (gnc x) (gno x) (Array.length from) (aton from) (aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) (** Substitute every occurrence of from in the expression with to. @@ -1239,48 +1354,47 @@ end = struct For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) let substitute_vars ( x : expr ) to_ = - create (gc x) (Z3native.substitute_vars (gnc x) (gno x) (Array.length to_) (aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) - (** Translates (copies) the term to the Context . @param ctx A context @return A copy of the term which is associated with *) let translate ( x : expr ) to_ctx = - if (gc x) == to_ctx then + if (c_of_expr x) == to_ctx then x else - create to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) + expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) (** Returns a string representation of the expression. *) - let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) + let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) (** Indicates whether the term is a numeral *) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the term is well-sorted. @return True if the term is well-sorted, false otherwise. *) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) (** The Sort of the term. *) - let get_sort ( x : expr ) = Sort.create (gc x) (Z3native.get_sort (gnc x) (gno x)) + let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the term has Boolean sort. *) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (gnc x) - (Z3native.mk_bool_sort (gnc x)) - (Z3native.get_sort (gnc x) (gno x))) + (Z3native.is_eq_sort (nc_of_expr x) + (Z3native.mk_bool_sort (nc_of_expr x)) + (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) (** Indicates whether the term represents a constant. @@ -1366,14 +1480,14 @@ end = struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : Sort.sort ) = - create ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) + let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) (** Creates a new Constant of sort and named . *) - let mk_const_s ( ctx : context ) ( name : string ) ( range : Sort.sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range @@ -1381,21 +1495,21 @@ end = struct Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = - create_fa ctx f [||] + let mk_const_f ( ctx : context ) ( f : func_decl ) = + expr_of_func_app ctx f [||] (** Creates a fresh constant of sort and a name prefixed with . *) - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : Sort.sort ) = - create ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = - create_fa ctx f args + let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = + expr_of_func_app ctx f args (** Create a numeral of a given sort. @@ -1403,8 +1517,8 @@ end = struct @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. @return A Term with value and sort *) - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : Sort.sort ) = - create ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. @@ -1413,50 +1527,31 @@ end = struct @param ty Sort of the numeral @return A Term with value and type *) - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : Sort.sort ) = - create ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end (** Boolean expressions *) -and Booleans : -sig - type bool_expr = BoolExpr of Expr.expr - type bool_sort = BoolSort of Sort.sort +module Boolean = +struct + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let a = (ast_of_ptr ctx no) in + BoolExpr(Expr(a)) - val create_expr : context -> Z3native.ptr -> bool_expr - val create_sort : context -> Z3native.ptr -> bool_sort - val gc : bool_expr -> context - val gnc : bool_expr -> Z3native.ptr - val gno : bool_expr -> Z3native.ptr - val aton : bool_expr array -> Z3native.ptr array -end = struct - type bool_expr = BoolExpr of Expr.expr - type bool_sort = BoolSort of Sort.sort - - (**/**) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.create ctx no) in - BoolExpr(Expr.Expr(a)) + let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(sort_of_ptr ctx no) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(Sort.create ctx no) - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gc e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gnc e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.gno e) - - let aton ( a : bool_expr array ) = - let f (e : bool_expr) = (gno e) in - Array.map f a - (**/**) + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (ptr_of_expr e) let mk_sort ( ctx : context ) = - BoolSort(Sort.create ctx (Z3native.mk_bool_sort (context_gno ctx))) + BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) (** Create a Boolean constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) @@ -1470,13 +1565,13 @@ end = struct The true Term. *) let mk_true ( ctx : context ) = - create_expr ctx (Z3native.mk_true (context_gno ctx)) + bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) (** The false Term. *) let mk_false ( ctx : context ) = - create_expr ctx (Z3native.mk_false (context_gno ctx)) + bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) (** Creates a Boolean value. @@ -1487,20 +1582,20 @@ end = struct (** Creates the equality = . *) - let mk_eq ( ctx : context ) ( x : Expr.expr ) ( y : Expr.expr ) = - create_expr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) (** Creates a distinct term. *) - let mk_distinct ( ctx : context ) ( args : Expr.expr array ) = - create_expr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_distinct ( ctx : context ) ( args : expr array ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) (** Mk an expression representing not(a). *) let mk_not ( ctx : context ) ( a : bool_expr ) = - create_expr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) (** Create an expression representing an if-then-else: ite(t1, t2, t3). @@ -1509,103 +1604,70 @@ end = struct @param t3 An expression with the same sort as *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - create_expr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) (** Create an expression representing t1 iff t2. *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 -> t2. *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing t1 xor t2. *) let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - create_expr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) (** Create an expression representing the AND of args *) let mk_and ( ctx : context ) ( args : bool_expr array ) = - create_expr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (aton args)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) (** Create an expression representing the OR of args *) let mk_or ( ctx : context ) ( args : bool_expr array ) = - create_expr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (aton args)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) end (** Quantifier expressions *) -and Quantifiers : -sig - type quantifier = Quantifier of Expr.expr - - val create : context -> Z3native.ptr -> quantifier -end = struct - type quantifier = Quantifier of Expr.expr - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.create ctx no) in - Quantifier(Expr.Expr(a)) - - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - (**/**) - +module Quantifier = +struct + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) + (** Quantifier patterns Patterns comprise a list of terms. The list should be non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Patterns : - sig - type pattern = Pattern of AST.ast - - val create : context -> Z3native.ptr -> pattern - val aton : pattern array -> Z3native.ptr array - end = struct - type pattern = Pattern of AST.ast - - (**/**) - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - Pattern(res) - + module Pattern = struct let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - let aton (a : pattern array) = - let f (e : pattern) = (gno e) in - Array.map f a - (**/**) - (** The number of terms in the pattern. *) let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - + Z3native.get_pattern_num_terms (gnc x) (gno x) + (** The terms in the pattern. *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in - let f i = (Expr.create (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f (** @@ -1632,11 +1694,11 @@ end = struct on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its index. *) - let get_index ( x : Expr.expr ) = - if not (AST.is_var (match x with Expr.Expr(a) -> a)) then + let get_index ( x : expr ) = + if not (AST.is_var (match x with Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value (Expr.gnc x) (Expr.gno x) + Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) (** Indicates whether the quantifier is universal. @@ -1664,7 +1726,7 @@ end = struct *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = (Patterns.create (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1677,7 +1739,7 @@ end = struct *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = (Patterns.create (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1698,31 +1760,31 @@ end = struct *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in - let f i = (Sort.create (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f (** The body of the quantifier. *) let get_body ( x : quantifier ) = - Booleans.create_expr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) (** Creates a new bound variable. @param index The de-Bruijn index of the variable @param ty The sort of the variable *) - let mk_bound ( ctx : context ) ( index : int ) ( ty : Sort.sort ) = - Expr.create ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) (** Create a quantifier pattern. *) - let mk_pattern ( ctx : context ) ( terms : Expr.expr array ) = + let mk_pattern ( ctx : context ) ( terms : expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Patterns.create ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (Expr.aton terms)) + Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) (** Create a universal Quantifier. @@ -1743,96 +1805,96 @@ end = struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (Patterns.aton patterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) - + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) + (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (ptr_of_expr body))) (** Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (Patterns.aton patterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Array.length sorts) (Sort.aton sorts) - (Symbol.aton names) - (Expr.gno body)) - + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (let f x = (Symbol.gno x) in (Array.map f names)) + (ptr_of_expr body))) + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - create ctx (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (ptr_of_expr body))) else - create ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (Expr.aton bound_constants) - (Array.length patterns) (Patterns.aton patterns) - (Array.length nopatterns) (Expr.aton nopatterns) - (Expr.gno body)) + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (Array.length bound_constants) (expr_aton bound_constants) + (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length nopatterns) (expr_aton nopatterns) + (ptr_of_expr body))) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : Sort.sort array ) ( names : Symbol.symbol array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1842,7 +1904,7 @@ end = struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : Expr.expr array ) ( body : Expr.expr ) ( weight : int option ) ( patterns : Patterns.pattern array ) ( nopatterns : Expr.expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1850,42 +1912,29 @@ end = struct end (** Functions to manipulate Array expressions *) -and Arrays : -sig - type array_expr = ArrayExpr of Expr.expr - type array_sort = ArraySort of Sort.sort - - val create_expr : context -> Z3native.ptr -> array_expr -end = struct - type array_expr = ArrayExpr of Expr.expr - type array_sort = ArraySort of Sort.sort - - (**/**) +module Array_ = +struct + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in + let e = (expr_of_ptr ctx no) in ArrayExpr(e) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in ArraySort(s) - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort.Sort(s)) -> (z3obj_gno s) + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr.Expr(e)) -> (z3obj_gno e) + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - let aton (a : array_expr array) = - let f (e : array_expr) = (egno e) in - Array.map f a - (**/**) - (** Create a new array sort. *) - let mk_sort ( ctx : context ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** @@ -1893,62 +1942,62 @@ end = struct It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). Array store takes at least 3 arguments. *) - let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) (** Indicates whether the term is an array select. *) - let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) (** Indicates whether the term is a constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - let is_constant_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) (** Indicates whether the term is a default array. For example default(const(v)) = v. The function is unary. *) - let is_default_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) (** Indicates whether the term is an array map. It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - let is_array_map ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) (** Indicates whether the term is an as-array term. An as-array term is n array value that behaves as the function graph of the function passed as parameter. *) - let is_as_array ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) (** Indicates whether the term is of an array sort. *) - let is_array ( x : Expr.expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) + let is_array ( x : expr ) = + (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_domain ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range ( x : array_sort ) = Sort.create (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + let get_range ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** Create an array constant. *) - let mk_const_s ( ctx : context ) ( name : string ) ( domain : Sort.sort ) ( range : Sort.sort ) = + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range (** @@ -1963,8 +2012,8 @@ end = struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) = - create_expr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) (** Array update. @@ -1982,8 +2031,8 @@ end = struct *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : Expr.expr ) ( v : Expr.expr ) = - create_expr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) (** Create a constant array. @@ -1993,8 +2042,8 @@ end = struct *) - let mk_const_array ( ctx : context ) ( domain : Sort.sort ) ( v : Expr.expr ) = - create_expr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) (** Maps f on the argument arrays. @@ -2006,8 +2055,9 @@ end = struct *) - let mk_map ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : array_expr array ) = - create_expr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (aton args)) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + let m x = (ptr_of_expr (expr_of_array_expr x)) in + expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) (** Access the array default value. @@ -2016,137 +2066,122 @@ end = struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - create_expr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) -and Sets : -sig - type set_sort = SetSort of Sort.sort - -end = struct - type set_sort = SetSort of Sort.sort - +module Set = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in SetSort(s) (** Indicates whether the term is set union *) - let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) (** Indicates whether the term is set intersection *) - let is_intersect ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) (** Indicates whether the term is set difference *) - let is_difference ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) (** Indicates whether the term is set complement *) - let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) (** Indicates whether the term is set subset *) - let is_subset ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) (** Create a set type. *) - let mk_sort ( ctx : context ) ( ty : Sort.sort ) = + let mk_sort ( ctx : context ) ( ty : sort ) = create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. *) - let mk_empty ( ctx : context ) ( domain : Sort.sort ) = - (Expr.create ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) + let mk_empty ( ctx : context ) ( domain : sort ) = + (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) (** Create the full set. *) - let mk_full ( ctx : context ) ( domain : Sort.sort ) = - Expr.create ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) + let mk_full ( ctx : context ) ( domain : sort ) = + expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) (** Add an element to the set. *) - let mk_set_add ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) (** Remove an element from a set. *) - let mk_del ( ctx : context ) ( set : Expr.expr ) ( element : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) (** Take the union of a list of sets. *) - let mk_union ( ctx : context ) ( args : Expr.expr array ) = - Expr.create ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_union ( ctx : context ) ( args : expr array ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) (** Take the intersection of a list of sets. *) - let mk_intersection ( ctx : context ) ( args : Expr.expr array ) = - Expr.create ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (Expr.aton args)) + let mk_intersection ( ctx : context ) ( args : expr array ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) (** Take the difference between two sets. *) - let mk_difference ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) (** Take the complement of a set. *) - let mk_complement ( ctx : context ) ( arg : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) + let mk_complement ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) (** Check for set membership. *) - let mk_membership ( ctx : context ) ( elem : Expr.expr ) ( set : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) (** Check for subsetness of sets. *) - let mk_subset ( ctx : context ) ( arg1 : Expr.expr ) ( arg2 : Expr.expr ) = - Expr.create ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) end (** Functions to manipulate Finite Domain expressions *) -and FiniteDomains : -sig - type finite_domain_sort = FiniteDomainSort of Sort.sort - -end = struct - type finite_domain_sort = FiniteDomainSort of Sort.sort - - (**/**) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) - +module FiniteDomain = +struct + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) + (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - create_sort ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size) + let mk_sort ( ctx : context ) ( name : symbol ) ( size : int ) = + let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in + FiniteDomainSort(s) (** Create a new finite domain sort. @@ -2158,14 +2193,15 @@ end = struct (** Indicates whether the term is of an array sort. *) - let is_finite_domain ( x : Expr.expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == FINITE_DOMAIN_SORT) + let is_finite_domain ( x : expr ) = + let nc = (nc_of_expr x) in + (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) (** Indicates whether the term is a less than predicate over a finite domain. *) - let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) (** The size of the finite domain sort. *) let get_size ( x : finite_domain_sort ) = @@ -2175,29 +2211,25 @@ end = struct end (** Functions to manipulate Relation expressions *) -and Relations : -sig - type relation_sort = RelationSort of Sort.sort - -end = struct - type relation_sort = RelationSort of Sort.sort - - (**/**) +module Relation = +struct + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in RelationSort(s) - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) + (** Indicates whether the term is of a relation sort. *) - let is_relation ( x : Expr.expr ) = - ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) == RELATION_SORT)) + let is_relation ( x : expr ) = + let nc = (nc_of_expr x) in + ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) (** Indicates whether the term is an relation store @@ -2206,40 +2238,40 @@ end = struct The function takes n+1 arguments, where the first argument is the relation and the remaining n elements correspond to the n columns of the relation. *) - let is_store ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) (** Indicates whether the term is an empty relation *) - let is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) (** Indicates whether the term is a test for the emptiness of a relation *) - let is_is_empty ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) (** Indicates whether the term is a relational join *) - let is_join ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) (** Indicates whether the term is the union or convex hull of two relations. The function takes two arguments. *) - let is_union ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) (** Indicates whether the term is the widening of two relations The function takes two arguments. *) - let is_widen ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). The function takes one argument. *) - let is_project ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) (** Indicates whether the term is a relation filter @@ -2250,7 +2282,7 @@ end = struct corresponding to the columns of the relation. So the first column in the relation has index 0. *) - let is_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) (** Indicates whether the term is an intersection of a relation with the negation of another. @@ -2265,7 +2297,7 @@ end = struct target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with ( x : expr ) on the columns c1, d1, .., cN, dN. *) - let is_negation_filter ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) (** Indicates whether the term is the renaming of a column in a relation @@ -2273,12 +2305,12 @@ end = struct The function takes one argument. The parameters contain the renaming as a cycle. *) - let is_rename ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) (** Indicates whether the term is the complement of a relation *) - let is_complement ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) (** Indicates whether the term is a relational select @@ -2287,7 +2319,7 @@ end = struct The function takes n+1 arguments, where the first argument is a relation, and the remaining n arguments correspond to a record. *) - let is_select ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) (** Indicates whether the term is a relational clone (copy) @@ -2298,7 +2330,7 @@ end = struct for terms of kind to perform destructive updates to the first argument. *) - let is_clone ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) (** The arity of the relation sort. *) let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) @@ -2312,46 +2344,22 @@ end = struct end (** Functions to manipulate Datatype expressions *) -and Datatypes : -sig - type datatype_expr = DatatypeExpr of Expr.expr - type datatype_sort = DatatypeSort of Sort.sort - - val create_expr : context -> Z3native.ptr -> datatype_expr -end = struct - type datatype_expr = DatatypeExpr of Expr.expr - type datatype_sort = DatatypeSort of Sort.sort - - (**/**) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (Expr.create ctx no) in - DatatypeExpr(e) - +module Datatype = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in DatatypeSort(s) - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) + (** Constructors *) - module Constructor : sig - type constructor - val create : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> constructor - val aton : constructor array -> Z3native.ptr array - end = struct - type constructor_extra = { - m_n : int; - mutable m_tester_decl : FuncDecl.func_decl option; - mutable m_constructor_decl : FuncDecl.func_decl option ; - mutable m_accessor_decls : FuncDecl.func_decl array option} - - type constructor = Constructor of (z3_native_object * constructor_extra) - - (**/**) - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + module Constructor = + struct + + let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2362,8 +2370,8 @@ end = struct let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) n - (Symbol.aton field_names) - (Sort.aton sorts) + (let f x = (Symbol.gno x) in (Array.map f field_names)) + (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) sort_refs) in let no : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -2379,21 +2387,17 @@ end = struct Gc.finalise f no ; Constructor(no, ex) - let aton ( a : constructor array ) = - let f (e : constructor) = match e with Constructor(no, ex) -> (z3obj_gno no)in - Array.map f a - let init_extra ( x : constructor ) = match x with Constructor(no, ex) -> match ex.m_tester_decl with | None -> let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in - ex.m_constructor_decl <- Some (FuncDecl.create (z3obj_gc no) a) ; - ex.m_tester_decl <- Some (FuncDecl.create (z3obj_gc no) b) ; - ex.m_accessor_decls <- Some (let f e = (FuncDecl.create (z3obj_gc no) e) in Array.map f c) ; + ex.m_constructor_decl <- Some (func_decl_of_ptr (z3obj_gc no) a) ; + ex.m_tester_decl <- Some (func_decl_of_ptr (z3obj_gc no) b) ; + ex.m_accessor_decls <- Some (let f e = (func_decl_of_ptr (z3obj_gc no) e) in Array.map f c) ; () | _ -> () - (**/**) + let get_n ( x : constructor ) = match x with Constructor(no, ex) -> @@ -2433,24 +2437,18 @@ end = struct (** Constructor list objects *) module ConstructorList = struct - type constructor_list = z3_native_object - - (**/**) - let create ( ctx : context )( c : Constructor.constructor array ) = + + let create ( ctx : context ) ( c : constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Constructor.aton c))) ; + let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f res; res - - let aton (a : constructor_list array) = - let f (e : constructor_list) = (z3obj_gno e) in - Array.map f a - (**/**) end (* DATATYPES *) @@ -2464,7 +2462,7 @@ end = struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2478,21 +2476,22 @@ end = struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array) = - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Constructor.aton constructors)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = + let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in create_sort ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2500,16 +2499,17 @@ end = struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = + let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = let n = (Array.length names) in - let f e = (ConstructorList.create ctx e) in + let f e = (ptr_of_ast (ConstructorList.create ctx e)) in let cla = (Array.map f c) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.aton names) (ConstructorList.aton cla)) in + let f2 x = (Symbol.gno x) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in let g e = (create_sort ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2523,54 +2523,50 @@ end = struct (** The range of the array sort. *) let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f (** The recognizers. *) let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in - let f i = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f (** The constructor accessors. *) let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = FuncDecl.create (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in Array.init ds g ) in Array.init n f end (** Functions to manipulate Enumeration expressions *) -and Enumerations : -sig - type enum_sort_data - type enum_sort = EnumSort of (Sort.sort * enum_sort_data) -end = struct - type enum_sort_data = { mutable _constdecls : FuncDecl.func_decl array ; - mutable _testerdecls : FuncDecl.func_decl array } - type enum_sort = EnumSort of (Sort.sort * enum_sort_data) - - (**/**) +module Enumeration = +struct + let _constdecls = Hashtbl.create 0 + let _testerdecls = Hashtbl.create 0 + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = - let s = (Sort.create ctx no) in - let e = { _constdecls = (let f e = FuncDecl.create ctx e in (Array.map f cdecls)) ; - _testerdecls = (let f e = FuncDecl.create ctx e in (Array.map f tdecls)) } in - EnumSort(s, e) + let s = (sort_of_ptr ctx no) in + let res = EnumSort(s) in + Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; + Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; + res - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort.Sort(s),_)-> (z3obj_gno s) - (**/**) + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) (** Create a new enumeration sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Symbol.aton enum_names)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( enum_names : symbol array ) = + let f x = Symbol.gno x in + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in create_sort ctx a b c (** @@ -2580,45 +2576,40 @@ end = struct mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._constdecls + let get_const_decls ( x : enum_sort ) = Hashtbl.find _constdecls x (** The test predicates for the constants in the enumeration. *) - let get_tester_decls ( x : enum_sort ) = match x with EnumSort(_,ex) -> ex._testerdecls + let get_tester_decls ( x : enum_sort ) = Hashtbl.find _testerdecls x end (** Functions to manipulate List expressions *) -and Lists : -sig - type list_sort_data - type list_sort = ListSort of (Sort.sort * list_sort_data) - -end = struct - type list_sort_data = { _nildecl : FuncDecl.func_decl ; - _is_nildecl : FuncDecl.func_decl ; - _consdecl : FuncDecl.func_decl ; - _is_consdecl : FuncDecl.func_decl ; - _headdecl : FuncDecl.func_decl ; - _taildecl : FuncDecl.func_decl } - type list_sort = ListSort of (Sort.sort * list_sort_data) - - (**/**) +module List_ = +struct + let _nildecls = Hashtbl.create 0 + let _is_nildecls = Hashtbl.create 0 + let _consdecls = Hashtbl.create 0 + let _is_consdecls = Hashtbl.create 0 + let _headdecls = Hashtbl.create 0 + let _taildecls = Hashtbl.create 0 + let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (Sort.create ctx no) in - let e = {_nildecl = FuncDecl.create ctx nildecl; - _is_nildecl = FuncDecl.create ctx is_nildecl; - _consdecl = FuncDecl.create ctx consdecl; - _is_consdecl = FuncDecl.create ctx is_consdecl; - _headdecl = FuncDecl.create ctx headdecl; - _taildecl = FuncDecl.create ctx taildecl} in - ListSort(s, e) + let s = (sort_of_ptr ctx no) in + let res = ListSort(s) in + Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; + Hashtbl.add _is_nildecls res (func_decl_of_ptr ctx is_nildecl) ; + Hashtbl.add _consdecls res (func_decl_of_ptr ctx consdecl) ; + Hashtbl.add _is_consdecls res (func_decl_of_ptr ctx is_consdecl) ; + Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; + Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; + res - let sgc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort.Sort(s),_)-> (z3obj_gno s) - (**/**) + let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) + (** Create a new list sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : Sort.sort ) = + let mk_sort ( ctx : context ) ( name : symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in create_sort ctx r a b c d e f @@ -2627,53 +2618,51 @@ end = struct mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._nildecl + let get_nil_decl ( x : list_sort ) = (Hashtbl.find _nildecls x) (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_nildecl + let get_is_nil_decl ( x : list_sort ) = (Hashtbl.find _is_nildecls x) (** The declaration of the cons function of this list sort. *) - let get_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._consdecl + let get_cons_decl ( x : list_sort ) = (Hashtbl.find _consdecls x) (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._is_consdecl + let get_is_cons_decl ( x : list_sort ) = (Hashtbl.find _is_consdecls x) (** The declaration of the head function of this list sort. *) - let get_head_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._headdecl + let get_head_decl ( x : list_sort ) = (Hashtbl.find _headdecls x) (** The declaration of the tail function of this list sort. *) - let get_tail_decl ( x : list_sort ) = match x with ListSort(no, ex) -> ex._taildecl + let get_tail_decl ( x : list_sort ) = (Hashtbl.find _taildecls x) (** The empty list. *) - let nil ( x : list_sort ) = Expr.create_fa (sgc x) (get_nil_decl x) [||] + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] end (** Functions to manipulate Tuple expressions *) -and Tuples : -sig - type tuple_sort = TupleSort of Sort.sort -end = struct - type tuple_sort = TupleSort of Sort.sort - - (**/**) +module Tuple = +struct + let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - let s = (Sort.create ctx no) in + let s = (sort_of_ptr ctx no) in TupleSort(s) - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort.Sort(s))-> (z3obj_gno s) - (**/**) + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) + (** Create a new tuple sort. *) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : Sort.sort array ) = - let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Symbol.aton field_names) (Sort.aton field_sorts)) in + let mk_sort ( ctx : context ) ( name : symbol ) ( field_names : symbol array ) ( field_sorts : sort array ) = + let f x = Symbol.gno x in + let f2 x = ptr_of_ast (ast_of_sort x) in + let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in (* CMW: leaks a,b? *) create_sort ctx r (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = - FuncDecl.create (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) (** The number of fields in the tuple. *) let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) @@ -2681,131 +2670,37 @@ end = struct (** The field declarations. *) let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in - let f i = FuncDecl.create (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end (** Functions to manipulate arithmetic expressions *) -and Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val create_expr : context -> Z3native.ptr -> arith_expr - val create_sort : context -> Z3native.ptr -> arith_sort - val aton : arith_expr array -> Z3native.ptr array - - module Integers : sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val create_sort : context -> Z3native.ptr -> int_sort - val create_expr : context -> Z3native.ptr -> int_expr - val create_num : context -> Z3native.ptr -> int_num - end - - module Reals : sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val create_sort : context -> Z3native.ptr -> real_sort - val create_expr : context -> Z3native.ptr -> real_expr - val create_num : context -> Z3native.ptr -> rat_num - end - - module AlgebraicNumbers : sig - type algebraic_num = AlgebraicNum of arith_expr - - val create_num : context -> Z3native.ptr -> algebraic_num - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr array -> Arithmetic.arith_expr - val mk_mul : context -> arith_expr array -> Arithmetic.arith_expr - val mk_sub : context -> arith_expr array -> Arithmetic.arith_expr - val mk_unary_minus : - context -> arith_expr -> Arithmetic.arith_expr - val mk_div : - context -> arith_expr -> arith_expr -> Arithmetic.arith_expr - val mk_power : - context -> arith_expr -> arith_expr -> Arithmetic.arith_expr - val mk_lt : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_le : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_gt : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - val mk_ge : - context -> arith_expr -> arith_expr -> Booleans.bool_expr - -end = struct - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - (**/**) +module Arithmetic = +struct + let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - ArithExpr(Expr.create ctx no) + arith_expr_of_expr (expr_of_ptr ctx no) let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - ArithSort(Sort.create ctx no) + arith_sort_of_sort (sort_of_ptr ctx no) - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort.Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (c_of_expr e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - let aton (a : arith_expr array) = - let f (e : arith_expr) = (egno e) in - Array.map f a - (**/**) - - module rec Integers : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val create_sort : context -> Z3native.ptr -> int_sort - val create_expr : context -> Z3native.ptr -> int_expr - val create_num : context -> Z3native.ptr -> int_num - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - (**/**) + module Integer = + struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - IntSort(Arithmetic.create_sort ctx no) + int_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - IntExpr(Arithmetic.create_expr ctx no) + int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - IntNum(create_expr ctx no) + int_num_of_int_expr (create_expr ctx no) let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) @@ -2816,7 +2711,7 @@ end = struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - (**/**) + (** Create a new integer sort. *) let mk_sort ( ctx : context ) = @@ -2834,7 +2729,7 @@ end = struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_int_const ( ctx : context ) ( name : symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) (** @@ -2848,14 +2743,14 @@ end = struct The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - create_expr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - create_expr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) (** Create an integer numeral. @@ -2883,7 +2778,7 @@ end = struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - Reals.create_expr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)) + real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) (** Create an bit bit-vector from the integer argument . @@ -2896,32 +2791,19 @@ end = struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVectors.create_expr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t)) + bitvec_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end - and Reals : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val create_sort : context -> Z3native.ptr -> real_sort - val create_expr : context -> Z3native.ptr -> real_expr - val create_num : context -> Z3native.ptr -> rat_num - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - (**/**) + module Real = + struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - RealSort(Arithmetic.create_sort ctx no) + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - RealExpr(Arithmetic.create_expr ctx no) - + real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + let create_num ( ctx : context ) ( no : Z3native.ptr ) = - RatNum(create_expr ctx no) + rat_num_of_real_expr (create_expr ctx no) let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) @@ -2932,7 +2814,7 @@ end = struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - (**/**) + (** Create a real sort. *) let mk_sort ( ctx : context ) = @@ -2940,11 +2822,11 @@ end = struct (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - Integers.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + Integer.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - Integers.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + Integer.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2955,7 +2837,7 @@ end = struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_real_const ( ctx : context ) ( name : symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) (** Creates a real constant. *) @@ -2995,7 +2877,7 @@ end = struct (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Booleans.create_expr ctx (Z3native.mk_is_int (context_gno ctx) (egno t)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) (** Coerce a real to an integer. @@ -3005,25 +2887,18 @@ end = struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integers.create_expr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)) + int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end - and AlgebraicNumbers : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val create_num : context -> Z3native.ptr -> algebraic_num - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - (**/**) + module AlgebraicNumber = + struct let create_num ( ctx : context ) ( no : Z3native.ptr ) = - AlgebraicNum(Arithmetic.create_expr ctx no) + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - (**/**) + (** Return a upper bound for a given real algebraic number. @@ -3033,7 +2908,7 @@ end = struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - Reals.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + Real.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) (** Return a lower bound for the given real algebraic number. @@ -3043,7 +2918,7 @@ end = struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - Reals.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + Real.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -3057,207 +2932,197 @@ end = struct (** Indicates whether the term is of integer sort. *) - let is_int ( x : Expr.expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) (** Indicates whether the term is an arithmetic numeral. *) - let is_arithmetic_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) (** Indicates whether the term is a less-than-or-equal *) - let is_le ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) (** Indicates whether the term is a greater-than-or-equal *) - let is_ge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) (** Indicates whether the term is a less-than *) - let is_lt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) (** Indicates whether the term is a greater-than *) - let is_gt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) (** Indicates whether the term is addition (binary) *) - let is_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) (** Indicates whether the term is subtraction (binary) *) - let is_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) (** Indicates whether the term is a unary minus *) - let is_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) (** Indicates whether the term is multiplication (binary) *) - let is_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) (** Indicates whether the term is division (binary) *) - let is_div ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) (** Indicates whether the term is integer division (binary) *) - let is_idiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) (** Indicates whether the term is remainder (binary) *) - let is_remainder ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) (** Indicates whether the term is modulus (binary) *) - let is_modulus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) (** Indicates whether the term is a coercion of integer to real (unary) *) - let is_inttoreal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) (** Indicates whether the term is a coercion of real to integer (unary) *) - let is_real_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - let is_real_is_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) (** Indicates whether the term is of sort real. *) - let is_real ( x : Expr.expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) (** Indicates whether the term is an integer numeral. *) - let is_int_numeral ( x : Expr.expr ) = (Expr.is_numeral x) && (is_int x) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) (** Indicates whether the term is a real numeral. *) - let is_rat_num ( x : Expr.expr ) = (Expr.is_numeral x) && (is_real x) + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) (** Indicates whether the term is an algebraic number *) - let is_algebraic_number ( x : Expr.expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) (** Create an expression representing t[0] + t[1] + .... *) let mk_add ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing t[0] * t[1] * .... *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing t[0] - t[1] - .... *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = - Arithmetic.create_expr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Arithmetic.aton t)) + let f x = (ptr_of_expr (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) (** Create an expression representing -t. *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) (** Create an expression representing t1 / t2. *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 ^ t2. *) let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Arithmetic.create_expr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2)) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Booleans.create_expr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end (** Functions to manipulate bit-vector expressions *) -and BitVectors : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val create_sort : context -> Z3native.ptr -> bitvec_sort - val create_expr : context -> Z3native.ptr -> bitvec_expr - val create_num : context -> Z3native.ptr -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - (**/**) +module BitVector = +struct let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - BitVecSort(Sort.create ctx no) + bitvec_sort_of_sort (sort_of_ptr ctx no) let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - BitVecExpr(Expr.create ctx no) + bitvec_expr_of_expr (expr_of_ptr ctx no) let create_num ( ctx : context ) ( no : Z3native.ptr ) = - BitVecNum(create_expr ctx no) + bitvec_num_of_bitvec_expr (create_expr ctx no) let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (c_of_expr e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (nc_of_expr e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (ptr_of_expr e) let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - (**/**) + (** Create a new bit-vector sort. @@ -3268,272 +3133,272 @@ end = struct (** Indicates whether the terms is of bit-vector sort. *) - let is_bv ( x : Expr.expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) + let is_bv ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) (** Indicates whether the term is a bit-vector numeral *) - let is_bv_numeral ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) (** Indicates whether the term is a one-bit bit-vector with value one *) - let is_bv_bit1 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) (** Indicates whether the term is a one-bit bit-vector with value zero *) - let is_bv_bit0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) (** Indicates whether the term is a bit-vector unary minus *) - let is_bv_uminus ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) (** Indicates whether the term is a bit-vector addition (binary) *) - let is_bv_add ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) (** Indicates whether the term is a bit-vector subtraction (binary) *) - let is_bv_sub ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) (** Indicates whether the term is a bit-vector multiplication (binary) *) - let is_bv_mul ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) (** Indicates whether the term is a bit-vector signed division (binary) *) - let is_bv_sdiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) (** Indicates whether the term is a bit-vector unsigned division (binary) *) - let is_bv_udiv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) (** Indicates whether the term is a bit-vector signed remainder (binary) *) - let is_bv_SRem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - let is_bv_urem ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) (** Indicates whether the term is a bit-vector signed modulus *) - let is_bv_smod ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) (** Indicates whether the term is a bit-vector signed division by zero *) - let is_bv_sdiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) (** Indicates whether the term is a bit-vector unsigned division by zero *) - let is_bv_udiv0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) (** Indicates whether the term is a bit-vector signed remainder by zero *) - let is_bv_srem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - let is_bv_urem0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) (** Indicates whether the term is a bit-vector signed modulus by zero *) - let is_bv_smod0 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - let is_bv_ule ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - let is_bv_sle ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - let is_bv_uge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - let is_bv_sge ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) (** Indicates whether the term is an unsigned bit-vector less-than *) - let is_bv_ult ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) (** Indicates whether the term is a signed bit-vector less-than *) - let is_bv_slt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) (** Indicates whether the term is an unsigned bit-vector greater-than *) - let is_bv_ugt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) (** Indicates whether the term is a signed bit-vector greater-than *) - let is_bv_sgt ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) (** Indicates whether the term is a bit-wise AND *) - let is_bv_and ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) (** Indicates whether the term is a bit-wise OR *) - let is_bv_or ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) (** Indicates whether the term is a bit-wise NOT *) - let is_bv_not ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) (** Indicates whether the term is a bit-wise XOR *) - let is_bv_xor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) (** Indicates whether the term is a bit-wise NAND *) - let is_bv_nand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) (** Indicates whether the term is a bit-wise NOR *) - let is_bv_nor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) (** Indicates whether the term is a bit-wise XNOR *) - let is_bv_xnor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) (** Indicates whether the term is a bit-vector concatenation (binary) *) - let is_bv_concat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) (** Indicates whether the term is a bit-vector sign extension *) - let is_bv_signextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) (** Indicates whether the term is a bit-vector zero extension *) - let is_bv_zeroextension ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) (** Indicates whether the term is a bit-vector extraction *) - let is_bv_extract ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) (** Indicates whether the term is a bit-vector repetition *) - let is_bv_repeat ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) (** Indicates whether the term is a bit-vector reduce OR *) - let is_bv_reduceor ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) (** Indicates whether the term is a bit-vector reduce AND *) - let is_bv_reduceand ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) (** Indicates whether the term is a bit-vector comparison *) - let is_bv_comp ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) (** Indicates whether the term is a bit-vector shift left *) - let is_bv_shiftleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) (** Indicates whether the term is a bit-vector logical shift right *) - let is_bv_shiftrightlogical ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) (** Indicates whether the term is a bit-vector arithmetic shift left *) - let is_bv_shiftrightarithmetic ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) (** Indicates whether the term is a bit-vector rotate left *) - let is_bv_rotateleft ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right *) - let is_bv_rotateright ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) (** Indicates whether the term is a bit-vector rotate left (extended) Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotateleftextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) (** Indicates whether the term is a bit-vector rotate right (extended) Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - let is_bv_rotaterightextended ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_int_to_bv ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - let is_bv_to_int ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - let is_bv_carry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) (** Indicates whether the term is a bit-vector ternary XOR The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - let is_bv_xor3 ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) (** The size of a bit-vector sort. *) let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) @@ -3550,7 +3415,7 @@ end = struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) (** @@ -3564,91 +3429,91 @@ end = struct The argument must have a bit-vector sort. *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) (** Bitwise conjunction. The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - create_expr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3660,7 +3525,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3675,7 +3540,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3685,7 +3550,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3697,7 +3562,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3706,7 +3571,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3714,7 +3579,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than @@ -3722,7 +3587,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) (** Unsigned less-than or equal to. @@ -3730,7 +3595,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than or equal to. @@ -3738,7 +3603,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater than or equal to. @@ -3746,7 +3611,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater than or equal to. @@ -3754,7 +3619,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater-than. @@ -3762,7 +3627,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater-than. @@ -3770,7 +3635,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) (** Bit-vector concatenation. @@ -3781,7 +3646,7 @@ end = struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3792,7 +3657,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3802,7 +3667,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3813,7 +3678,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3821,7 +3686,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3836,7 +3701,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) (** @@ -3851,7 +3716,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3867,7 +3732,7 @@ end = struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3876,7 +3741,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3885,7 +3750,7 @@ end = struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - create_expr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3894,7 +3759,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3904,7 +3769,7 @@ end = struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - create_expr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3922,7 +3787,7 @@ end = struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integers.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + Arithmetic.Integer.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3930,7 +3795,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3938,7 +3803,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3946,7 +3811,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3954,7 +3819,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3962,7 +3827,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3970,7 +3835,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3978,7 +3843,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Booleans.create_expr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3986,7 +3851,7 @@ end = struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Booleans.create_expr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2)) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a bit-vector numeral. @@ -3994,28 +3859,27 @@ end = struct @param v A string representing the value in decimal notation. @param size the size of the bit-vector *) - let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) = + let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) end (** Functions to manipulate proof expressions *) -and Proofs : -sig -end = struct +module Proof = +struct (** Indicates whether the term is a Proof for the expression 'true'. *) - let is_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) (** Indicates whether the term is a proof for a fact asserted by the user. *) - let is_asserted ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - let is_goal ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) (** Indicates whether the term is proof via modus ponens @@ -4026,7 +3890,7 @@ end = struct [mp T1 T2]: q The second antecedents may also be a proof for (iff p q). *) - let is_modus_ponens ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. @@ -4035,7 +3899,7 @@ end = struct equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. *) - let is_reflexivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) (** Indicates whether the term is proof by symmetricity of a relation @@ -4045,7 +3909,7 @@ end = struct [symmetry T1]: (R s t) T1 is the antecedent of this proof object. *) - let is_symmetry ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) (** Indicates whether the term is a proof by transitivity of a relation @@ -4056,7 +3920,7 @@ end = struct T2: (R s u) [trans T1 T2]: (R t u) *) - let is_transitivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) (** Indicates whether the term is a proof by condensed transitivity of a relation @@ -4076,7 +3940,7 @@ end = struct if there is a path from s to t, if we view every antecedent (R a b) as an edge between a and b. *) - let is_Transitivity_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) (** @@ -4089,7 +3953,7 @@ end = struct Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. *) - let is_monotonicity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) (** Indicates whether the term is a quant-intro proof @@ -4098,7 +3962,7 @@ end = struct T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - let is_quant_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) (** Indicates whether the term is a distributivity proof object. @@ -4115,7 +3979,7 @@ end = struct Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. *) - let is_distributivity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) (** Indicates whether the term is a proof by elimination of AND @@ -4124,7 +3988,7 @@ end = struct T1: (and l_1 ... l_n) [and-elim T1]: l_i *) - let is_and_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) (** Indicates whether the term is a proof by eliminiation of not-or @@ -4133,7 +3997,7 @@ end = struct T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) *) - let is_or_elimination ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) (** Indicates whether the term is a proof by rewriting @@ -4147,11 +4011,11 @@ end = struct Remark: if f is bool, then = is iff. Examples: - (= (+ ( x : Expr.expr ) 0) x) - (= (+ ( x : Expr.expr ) 1 2) (+ 3 x)) - (iff (or ( x : Expr.expr ) false) x) + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) - let is_rewrite ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) (** Indicates whether the term is a proof by rewriting @@ -4166,14 +4030,14 @@ end = struct - When converting bit-vectors to Booleans (BIT2BOOL=true) - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - let is_rewrite_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) (** Indicates whether the term is a proof for pulling quantifiers out. A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - let is_pull_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) (** Indicates whether the term is a proof for pulling quantifiers out. @@ -4182,7 +4046,7 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents *) - let is_pull_quant_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) (** Indicates whether the term is a proof for pushing quantifiers in. @@ -4195,7 +4059,7 @@ end = struct This proof object has no antecedents *) - let is_push_quant ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) (** Indicates whether the term is a proof for elimination of unused variables. @@ -4207,34 +4071,34 @@ end = struct This proof object has no antecedents. *) - let is_elim_unused_vars ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) (** Indicates whether the term is a proof for destructive equality resolution A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : Expr.expr ) t)) P[x])) P[t]) - if ( x : Expr.expr ) does not occur in t. + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. This proof object has no antecedents. Several variables can be eliminated simultaneously. *) - let is_der ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) (** Indicates whether the term is a proof for quantifier instantiation A proof of (or (not (forall (x) (P x))) (P a)) *) - let is_quant_inst ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) (** Indicates whether the term is a hypthesis marker. Mark a hypothesis in a natural deduction style proof. *) - let is_hypothesis ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) (** Indicates whether the term is a proof by lemma @@ -4246,7 +4110,7 @@ end = struct It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. *) - let is_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) (** Indicates whether the term is a proof by unit resolution @@ -4257,7 +4121,7 @@ end = struct T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - let is_unit_resolution ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) (** Indicates whether the term is a proof by iff-true @@ -4265,7 +4129,7 @@ end = struct T1: p [iff-true T1]: (iff p true) *) - let is_iff_true ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) (** Indicates whether the term is a proof by iff-false @@ -4273,7 +4137,7 @@ end = struct T1: (not p) [iff-false T1]: (iff p false) *) - let is_iff_false ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) (** Indicates whether the term is a proof by commutativity @@ -4285,7 +4149,7 @@ end = struct This proof object has no antecedents. Remark: if f is bool, then = is iff. *) - let is_commutativity ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) (** Indicates whether the term is a proof for Tseitin-like axioms @@ -4320,7 +4184,7 @@ end = struct unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). *) - let is_def_axiom ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) (** Indicates whether the term is a proof for introduction of a name @@ -4342,7 +4206,7 @@ end = struct Otherwise: [def-intro]: (= n e) *) - let is_def_intro ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) (** Indicates whether the term is a proof for application of a definition @@ -4351,7 +4215,7 @@ end = struct F is 'equivalent' to n, given that T1 is a proof that n is a name for F. *) - let is_apply_def ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) (** Indicates whether the term is a proof iff-oeq @@ -4359,7 +4223,7 @@ end = struct T1: (iff p q) [iff~ T1]: (~ p q) *) - let is_iff_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) (** Indicates whether the term is a proof for a positive NNF step @@ -4386,7 +4250,7 @@ end = struct NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. *) - let is_nnf_pos ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) (** Indicates whether the term is a proof for a negative NNF step @@ -4410,7 +4274,7 @@ end = struct [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) (and (or r_1 r_2) (or r_1' r_2'))) *) - let is_nnf_neg ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. @@ -4421,7 +4285,7 @@ end = struct This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_nnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. @@ -4430,19 +4294,19 @@ end = struct This proof object is only used if the parameter PROOF_MODE is 1. This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - let is_cnf_star ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) (** Indicates whether the term is a proof for a Skolemization step Proof for: - [sk]: (~ (not (forall ( x : Expr.expr ) (p ( x : Expr.expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : Expr.expr ) (p ( x : Expr.expr ) y)) (p (sk y) y)) + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) This proof object has no antecedents. *) - let is_skolemize ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. @@ -4452,7 +4316,7 @@ end = struct T2: (~ p q) [mp~ T1 T2]: q *) - let is_modus_ponens_oeq ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) (** Indicates whether the term is a proof for theory lemma @@ -4470,7 +4334,7 @@ end = struct (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - let is_theory_lemma ( x : Expr.expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end @@ -4480,10 +4344,8 @@ end of formulas, that can be solved and/or transformed using tactics and solvers. *) module Goal = -struct - type goal = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; @@ -4492,7 +4354,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The precision of the goal. @@ -4521,8 +4383,8 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : Booleans.bool_expr array ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) in + let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () @@ -4543,7 +4405,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = Booleans.create_expr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) @@ -4562,7 +4424,7 @@ struct create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : Params.params option ) = + let simplify ( x : goal ) ( p : params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with @@ -4602,9 +4464,7 @@ end A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - type model = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; @@ -4613,7 +4473,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Function interpretations @@ -4622,9 +4482,7 @@ struct *) module FuncInterp = struct - type func_interp = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; @@ -4633,17 +4491,15 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Function interpretations entries An Entry object represents an element in the finite map used to a function interpretation. *) module FuncEntry = - struct - type func_entry = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; @@ -4652,13 +4508,13 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Return the (symbolic) value of this entry. *) let get_value ( x : func_entry ) = - Expr.create (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) (** The number of arguments of the entry. @@ -4670,7 +4526,7 @@ struct *) let get_args ( x : func_entry ) = let n = (get_num_args x) in - let f i = (Expr.create (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f (** @@ -4698,7 +4554,7 @@ struct (** The (symbolic) `else' value of the function interpretation. *) - let get_else ( x : func_interp ) = Expr.create (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) (** The arity of the function interpretation @@ -4725,7 +4581,7 @@ struct (** Retrieves the interpretation (the assignment) of in the model. A function declaration of zero arity An expression if the function has an interpretation in the model, null otherwise. *) - let get_const_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let get_const_interp ( x : model ) ( f : func_decl ) = if (FuncDecl.get_arity f) != 0 || (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") @@ -4734,19 +4590,19 @@ struct if (Z3native.is_null np) then None else - Some (Expr.create (z3obj_gc x) np) + Some (expr_of_ptr (z3obj_gc x) np) (** Retrieves the interpretation (the assignment) of in the model. A Constant An expression if the constant has an interpretation in the model, null otherwise. *) - let get_const_interp_e ( x : model ) ( a : Expr.expr ) = get_const_interp x (Expr.get_func_decl a) + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) (** Retrieves the interpretation (the assignment) of a non-constant in the model. A function declaration of non-zero arity A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - let rec get_func_interp ( x : model ) ( f : FuncDecl.func_decl ) = + let rec get_func_interp ( x : model ) ( f : func_decl ) = let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in @@ -4759,7 +4615,7 @@ struct raise (Z3native.Exception "Argument was not an array constant") else let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x (FuncDecl.create (z3obj_gc x) fd) + get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); else let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in @@ -4771,7 +4627,7 @@ struct (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f @@ -4781,15 +4637,15 @@ struct (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in - let f i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = FuncDecl.create (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) @@ -4810,15 +4666,15 @@ struct The evaluation of in the model. *) - let eval ( x : model ) ( t : Expr.expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else - Expr.create (z3obj_gc x) v + expr_of_ptr (z3obj_gc x) v (** Alias for eval. *) - let evaluate ( x : model ) ( t : Expr.expr ) ( completion : bool ) = + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -4834,7 +4690,7 @@ struct *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in - let f i = (Sort.create (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f @@ -4843,10 +4699,10 @@ struct An uninterpreted sort An array of expressions, where each is an element of the universe of *) - let sort_universe ( x : model ) ( s : Sort.sort ) = - let n_univ = AST.ASTVectors.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in - let n = (AST.ASTVectors.get_size n_univ) in - let f i = (AST.ASTVectors.get n_univ i) in + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in Array.init n f (** Conversion of models to strings. @@ -4866,9 +4722,7 @@ end *) module Probe = struct - type probe = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; @@ -4877,14 +4731,14 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Execute the probe over the goal. A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : Goal.goal) = + let apply ( x : probe ) (g : goal) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** @@ -4988,10 +4842,8 @@ end It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. *) module Tactic = -struct - type tactic = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; @@ -5000,7 +4852,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Tactic application results @@ -5008,9 +4860,7 @@ struct tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct - type apply_result = z3_native_object - - (**/**) + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; @@ -5019,7 +4869,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = @@ -5039,7 +4889,7 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) @@ -5054,7 +4904,7 @@ struct Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = + let apply ( x : tactic ) ( g : goal ) ( p : params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) @@ -5122,14 +4972,14 @@ struct If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** @@ -5154,7 +5004,7 @@ struct (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : Probe.probe ) = + let fail_if ( ctx : context ) ( p : probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** @@ -5167,14 +5017,14 @@ struct (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = using_params ctx t p (** @@ -5201,10 +5051,8 @@ end (** Solvers *) module Solver = -struct - type solver = z3_native_object - - (**/**) +struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; @@ -5213,9 +5061,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) - - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" @@ -5224,10 +5070,8 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = - struct - type statistics = z3_native_object - - (**/**) + struct + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; @@ -5236,7 +5080,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - (**/**) + (** Statistical data is organized into pairs of \[Key, Entry\], where every @@ -5245,14 +5089,7 @@ struct *) module Entry = struct - type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } - - (**/**) + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -5272,7 +5109,7 @@ struct m_float = v } in res - (**/**) + (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key @@ -5344,7 +5181,7 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( p : Params.params )= + let set_parameters ( x : solver ) ( p : params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** @@ -5382,8 +5219,8 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : Booleans.bool_expr array ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in + let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) (** @@ -5399,11 +5236,11 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : Booleans.bool_expr array ) ( ps : Booleans.bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e) (Booleans.gno (Array.get ps i))) in + let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in ignore (Array.iteri f cs) (** @@ -5418,24 +5255,24 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : Booleans.bool_expr ) ( p : Booleans.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Booleans.gno c) (Booleans.gno p) + let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVectors.get_size a) + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVector.get_size a) (** The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVectors.get_size a) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get a i)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size a) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f (** @@ -5445,12 +5282,13 @@ struct *) - let check ( x : solver ) ( assumptions : Booleans.bool_expr array) = + let check ( x : solver ) ( assumptions : bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Booleans.aton assumptions)) + let f x = (ptr_of_expr (expr_of_bool_expr x)) in + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) in match r with | L_TRUE -> SATISFIABLE @@ -5481,7 +5319,7 @@ struct if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** The unsat core of the last Check. @@ -5491,9 +5329,9 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVectors.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVectors.get_size cn) in - let f i = (AST.ASTVectors.get cn i) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in Array.init n f (** @@ -5515,7 +5353,7 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = + let mk_solver ( ctx : context ) ( logic : symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) @@ -5539,7 +5377,7 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + let mk_solver_t ( ctx : context ) ( t : tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** @@ -5551,10 +5389,7 @@ end (** Fixedpoint solving *) module Fixedpoint = -struct - type fixedpoint = z3_native_object - - (**/**) +struct let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; @@ -5563,7 +5398,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_create res) ; res - (**/**) + (** A string that describes all available fixedpoint solver parameters. @@ -5574,7 +5409,7 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : Params.params )= + let set_params ( x : fixedpoint ) ( p : params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** @@ -5586,29 +5421,29 @@ struct (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : Booleans.bool_expr array ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Booleans.gno e)) in + let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () (** Register predicate as recursive relation. *) - let register_relation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) = + let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) (** Add table fact to the fixedpoint solver. *) - let add_fact ( x : fixedpoint ) ( pred : FuncDecl.func_decl ) ( args : int array ) = + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args (** @@ -5617,11 +5452,11 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : Booleans.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Booleans.gno query))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN + let query ( x : fixedpoint ) ( query : bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN (** Query the fixedpoint solver. @@ -5629,11 +5464,12 @@ struct The query is satisfiable if there is an instance of some relation that is non-empty. The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - let query_r ( x : fixedpoint ) ( relations : FuncDecl.func_decl array ) = - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (FuncDecl.aton relations))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN + let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + let f x = ptr_of_ast (ast_of_func_decl x) in + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN (** Creates a backtracking point. @@ -5654,8 +5490,8 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : Booleans.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Booleans.gno rule) (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) (** Retrieve satisfying instance or instances of solver, @@ -5666,7 +5502,7 @@ struct if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** Retrieve explanation why fixedpoint engine returned status Unknown. @@ -5677,25 +5513,25 @@ struct (** Retrieve the number of levels explored for a given predicate. *) - let get_num_levels ( x : fixedpoint ) ( predicate : FuncDecl.func_decl ) = + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) (** Retrieve the cover of a predicate. *) - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) = + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then None else - Some (Expr.create (z3obj_gc x) q) + Some (expr_of_ptr (z3obj_gc x) q) (** Add property about the predicate. The property is added at level. *) - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : FuncDecl.func_decl ) ( property : Expr.expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) (** Retrieve internal string representation of fixedpoint object. @@ -5705,31 +5541,33 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : FuncDecl.func_decl ) ( kinds : Symbol.symbol array ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Symbol.aton kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + let f2 x = (Symbol.gno x) in + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : Booleans.bool_expr array ) = - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Booleans.aton queries) + let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = + let f x = ptr_of_expr (expr_of_bool_expr x) in + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVectors.get_size v) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVectors.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVectors.get_size v) in - let f i = Booleans.create_expr (z3obj_gc x) (z3obj_gno (AST.ASTVectors.get v i)) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** @@ -5813,10 +5651,10 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Booleans.bool_expr array ) ( formula : Booleans.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (Booleans.aton assumptions) - (Booleans.gno formula) + (Array.length assumptions) (let f x = ptr_of_expr (expr_of_bool_expr x) in (Array.map f assumptions)) + (Boolean.gno formula) (** Parse the given string using the SMT-LIB parser. @@ -5827,7 +5665,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5837,17 +5675,17 @@ struct else Z3native.parse_smtlib_string (context_gno ctx) str cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)) (** Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5857,11 +5695,11 @@ struct else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)) (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. @@ -5873,7 +5711,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = Booleans.create_expr ctx (Z3native.get_smtlib_formula (context_gno ctx) i) in + let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f @@ -5887,7 +5725,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = Booleans.create_expr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i) in + let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f (** @@ -5900,7 +5738,7 @@ struct *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in - let f i = FuncDecl.create ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in + let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f (** @@ -5913,7 +5751,7 @@ struct *) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in - let f i = (Sort.create ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f (** @@ -5922,7 +5760,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5930,19 +5768,19 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.aton sort_names) - (Sort.aton sorts) - cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : Sort.sort array ) ( decl_names : Symbol.symbol array ) ( decls : FuncDecl.func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5950,13 +5788,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Z3native.parse_smtlib2_string (context_gno ctx) file_name + bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (Symbol.aton sort_names) - (Sort.aton sorts) + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) cd - (Symbol.aton decl_names) - (FuncDecl.aton decls) + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) end From 4e8d05dcf6bcdd69c85d763dda6730be87783b4d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 19:51:09 +0000 Subject: [PATCH 420/646] ML API: formatting. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.mli | 3331 +++++++++------------------------------------ 1 file changed, 654 insertions(+), 2677 deletions(-) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index b2f0939d0..f82492e8a 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1,3001 +1,978 @@ (** - The Z3 ML/OCaml Interface. + The Z3 ML/Ocaml Interface. Copyright (C) 2012 Microsoft Corporation @author CM Wintersteiger (cwinter) 2012-12-17 *) -(** General Z3 exceptions - - Many functions in this API may throw an exception; if they do, it is this one.*) -exception Error of string - -(** Context objects. - - Most interactions with Z3 are interpreted in some context; many users will only - require one such object, but power users may require more than one. To start using - Z3, do - - - let ctx = (mk_context []) in - (...) - - - where a list of pairs of strings may be passed to set options on - the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (mk_context cfg) in - (...) - -*) type context -(** Create a context object - The following parameters can be set: - - - proof (Boolean) Enable proof generation - - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting - - trace (Boolean) Tracing support for VCC - - trace_file_name (String) Trace out file for VCC traces - - timeout (unsigned) default timeout (in milliseconds) used for solvers - - well_sorted_check type checker - - auto_config use heuristics to automatically select solver and configure it - - model model generation for solvers, this parameter can be overwritten when creating a solver - - model_validate validate models produced by solvers - - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver -*) -val mk_context : (string * string) list -> context +type int_symbol +type string_symbol +type symbol = S_Int of int_symbol | S_Str of string_symbol + +type ast +type ast_vector +type ast_map + +type sort = Sort of ast + +type uninterpreted_sort = UninterpretedSort of sort +type bool_sort = BoolSort of sort +type array_sort = ArraySort of sort +type set_sort = SetSort of sort +type datatype_sort = DatatypeSort of sort +type relation_sort = RelationSort of sort +type finite_domain_sort = FiniteDomainSort of sort +type enum_sort = EnumSort of sort +type list_sort = ListSort of sort +type tuple_sort = TupleSort of sort +type arith_sort = ArithSort of sort +type bitvec_sort = BitVecSort of sort +type int_sort = IntSort of arith_sort +type real_sort = RealSort of arith_sort + +type func_decl = FuncDecl of ast + +type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of symbol + | P_Srt of sort + | P_Ast of ast + | P_Fdl of func_decl + | P_Rat of string + +type params +type param_descrs + +type expr = Expr of ast +type bool_expr = BoolExpr of expr +type arith_expr = ArithExpr of expr +type int_expr = IntExpr of arith_expr +type real_expr = RealExpr of arith_expr +type bitvec_expr = BitVecExpr of expr +type array_expr = ArrayExpr of expr +type datatype_expr = DatatypeExpr of expr +type int_num = IntNum of int_expr +type rat_num = RatNum of real_expr +type algebraic_num = AlgebraicNum of arith_expr +type bitvec_num = BitVecNum of bitvec_expr +type quantifier = Quantifier of expr +type pattern = Pattern of ast + +type constructor + +type goal + +type model +type func_interp +type func_entry + +type probe + +type tactic +type apply_result + +type solver +type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + +type statistics +type statistics_entry + +type fixedpoint + +val ast_of_sort : sort -> ast +val sort_of_uninterpreted_sort : uninterpreted_sort -> sort +val sort_of_bool_sort : bool_sort -> sort +val sort_of_array_sort : array_sort -> sort +val sort_of_set_sort : set_sort -> sort +val sort_of_datatype_sort : datatype_sort -> sort +val sort_of_relation_sort : relation_sort -> sort +val sort_of_finite_domain_sort : finite_domain_sort -> sort +val sort_of_enum_sort : enum_sort -> sort +val sort_of_list_sort : list_sort -> sort +val sort_of_tuple_sort : tuple_sort -> sort +val sort_of_arith_sort : arith_sort -> sort +val sort_of_bitvec_sort : bitvec_sort -> sort +val arith_sort_of_int_sort : int_sort -> arith_sort +val arith_sort_of_real_sort : real_sort -> arith_sort +val uninterpreted_sort_of_sort : sort -> uninterpreted_sort +val bool_sort_of_sort : sort -> bool_sort +val array_sort_of_sort : sort -> array_sort +val datatype_sort_of_sort : sort -> datatype_sort +val relation_sort_of_sort : sort -> relation_sort +val finite_domain_sort_of_sort : sort -> finite_domain_sort +val arith_sort_of_sort : sort -> arith_sort +val bitvec_sort_of_sort : sort -> bitvec_sort +val int_sort_of_arith_sort : arith_sort -> int_sort +val real_sort_of_arith_sort : arith_sort -> real_sort +val ast_of_func_decl : func_decl -> ast +val ast_of_expr : expr -> ast +val expr_of_bool_expr : bool_expr -> expr +val expr_of_arith_expr : arith_expr -> expr +val expr_of_bitvec_expr : bitvec_expr -> expr +val expr_of_array_expr : array_expr -> expr +val expr_of_datatype_expr : datatype_expr -> expr +val arith_expr_of_int_expr : int_expr -> arith_expr +val arith_expr_of_real_expr : real_expr -> arith_expr +val int_expr_of_int_num : int_num -> int_expr +val real_expr_of_rat_num : rat_num -> real_expr +val arith_expr_of_algebraic_num : algebraic_num -> arith_expr +val bitvec_expr_of_bitvec_num : bitvec_num -> bitvec_expr +val expr_of_quantifier : quantifier -> expr +val ast_of_pattern : pattern -> ast +val expr_of_ast : ast -> expr +val bool_expr_of_expr : expr -> bool_expr +val arith_expr_of_expr : expr -> arith_expr +val bitvec_expr_of_expr : expr -> bitvec_expr +val array_expr_of_expr : expr -> array_expr +val datatype_expr_of_expr : expr -> datatype_expr +val int_expr_of_arith_expr : arith_expr -> int_expr +val real_expr_of_arith_expr : arith_expr -> real_expr +val int_num_of_int_expr : int_expr -> int_num +val rat_num_of_real_expr : real_expr -> rat_num +val algebraic_num_of_arith_expr : arith_expr -> algebraic_num +val bitvec_num_of_bitvec_expr : bitvec_expr -> bitvec_num +val quantifier_of_expr : expr -> quantifier +val pattern_of_ast : ast -> pattern -(** Interaction logging for Z3 - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) module Log : sig - (** Open an interaction log file. - @return True if opening the log file succeeds, false otherwise. *) - (* CMW: "open" is a reserved keyword. *) val open_ : string -> bool - - (** Closes the interaction log. *) - val close : unit -> unit - - (** Appends a user-provided string to the interaction log. *) + val close : unit val append : string -> unit end -(** Version information *) module Version : sig - (** The major version. *) val major : int - - (** The minor version. *) val minor : int - - (** The build version. *) val build : int - - (** The revision. *) val revision : int - - (** A string representation of the version information. *) val to_string : string end -(** Symbols are used to name several term and type constructors *) +val mk_context : (string * string) list -> context + module Symbol : sig - type symbol - - (** The kind of the symbol (int or string) *) val kind : symbol -> Z3enums.symbol_kind - - (** Indicates whether the symbol is of Int kind *) val is_int_symbol : symbol -> bool - - (** Indicates whether the symbol is of string kind. *) val is_string_symbol : symbol -> bool - - (** The int value of the symbol. *) - val get_int : symbol -> int - - (** The string value of the symbol. *) - val get_string : symbol -> string - - (** A string representation of the symbol. *) + val get_int : int_symbol -> int + val get_string : string_symbol -> string val to_string : symbol -> string - - (** Creates a new symbol using an integer. - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. *) val mk_int : context -> int -> symbol - - (** Creates a new symbol using a string. *) val mk_string : context -> string -> symbol - - (** Create a list of symbols. *) - val mk_ints : context -> int list -> symbol list - - (** Create a list of symbols. *) - val mk_strings : context -> string list -> symbol list + val mk_ints : context -> int array -> symbol array + val mk_strings : context -> string array -> symbol array end -(** The abstract syntax tree (AST) module *) module AST : sig - type ast - (** Vectors of ASTs *) module ASTVector : sig - type ast_vector - - (** Create an empty AST vector *) - val mk_ast_vector : context -> ast_vector - - (** The size of the vector *) val get_size : ast_vector -> int - - (** Retrieves the i-th object in the vector. - @return An AST *) - val get : ast_vector -> int -> ast - - (** Sets the i-th object in the vector. *) + val get : ast_vector -> int -> ast_vector val set : ast_vector -> int -> ast -> unit - - (** Resize the vector to a new size. *) val resize : ast_vector -> int -> unit - - (** Add an ast to the back of the vector. The size - is increased by 1. *) val push : ast_vector -> ast -> unit - - (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) val translate : ast_vector -> context -> ast_vector - - (** Retrieves a string representation of the vector. *) val to_string : ast_vector -> string end - (** Map from AST to AST *) module ASTMap : sig - type ast_map - - (** Create an empty mapping from AST to AST *) - val mk_ast_map : context -> ast_map - - (** Checks whether the map contains a key. - @return True if the key in the map, false otherwise. *) val contains : ast_map -> ast -> bool - - (** Finds the value associated with the key. - This function signs an error when the key is not a key in the map. *) - val find : ast_map -> ast -> ast - - (** Stores or replaces a new key/value pair in the map. *) + val find : ast_map -> ast -> ast_map val insert : ast_map -> ast -> ast -> unit - - (** Erases the key from the map.*) val erase : ast_map -> ast -> unit - - (** Removes all keys from the map. *) val reset : ast_map -> unit - - (** The size of the map *) val get_size : ast_map -> int - - (** The keys stored in the map. *) - val get_keys : ast_map -> ast list - - (** Retrieves a string representation of the map.*) + val get_keys : ast_map -> ast_vector val to_string : ast_map -> string end - (** The AST's hash code. - @return A hash code *) - val hash : ast -> int - - (** A unique identifier for the AST (unique among all ASTs). *) + val get_hash_code : ast -> int val get_id : ast -> int - - (** The kind of the AST. *) val get_ast_kind : ast -> Z3enums.ast_kind - - (** Indicates whether the AST is an Expr *) val is_expr : ast -> bool - - (** Indicates whether the AST is a bound variable*) val is_var : ast -> bool - - (** Indicates whether the AST is a Quantifier *) val is_quantifier : ast -> bool - - (** Indicates whether the AST is a Sort *) val is_sort : ast -> bool - - (** Indicates whether the AST is a func_decl *) val is_func_decl : ast -> bool - - (** A string representation of the AST. *) val to_string : ast -> string - - (** A string representation of the AST in s-expression notation. *) val to_sexpr : ast -> string - - (** Comparison operator. - @return True if the two ast's are from the same context - and represent the same sort; false otherwise. *) - val equal : ast -> ast -> bool - - (** Object Comparison. - @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + val ( = ) : ast -> ast -> bool val compare : ast -> ast -> int - - (** Translates (copies) the AST to another context. - @return A copy of the AST which is associated with the other context. *) + val ( < ) : ast -> ast -> int val translate : ast -> context -> ast - - (** Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - [Z3native.inc_ref]). - {!wrap_ast} *) + val wrap : context -> Z3native.z3_ast -> ast val unwrap_ast : ast -> Z3native.ptr - - (** Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., - [Z3native.inc_ref]). *) - val wrap_ast : context -> Z3native.z3_ast -> ast end -(** The Sort module implements type information for ASTs *) module Sort : sig - type sort = Sort of AST.ast - - val ast_of_sort : sort -> AST.ast - - (** Comparison operator. - @return True if the two sorts are from the same context - and represent the same sort; false otherwise. *) - val equal : sort -> sort -> bool - - (** Returns a unique identifier for the sort. *) + val ( = ) : sort -> sort -> bool val get_id : sort -> int - - (** The kind of the sort. *) val get_sort_kind : sort -> Z3enums.sort_kind - - (** The name of the sort *) - val get_name : sort -> Symbol.symbol - - (** A string representation of the sort. *) + val get_name : sort -> symbol val to_string : sort -> string - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted : context -> Symbol.symbol -> sort - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted_s : context -> string -> sort + val mk_uninterpreted : context -> symbol -> uninterpreted_sort + val mk_uninterpreted_s : context -> string -> uninterpreted_sort end -(** Function declarations *) -module rec FuncDecl : +module FuncDecl : sig - type func_decl = FuncDecl of AST.ast - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - - (** Parameters of Func_Decls *) module Parameter : sig - (** Parameters of func_decls *) - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - (** The kind of the parameter. *) val get_kind : parameter -> Z3enums.parameter_kind - - (** The int value of the parameter.*) val get_int : parameter -> int - - (** The float value of the parameter.*) val get_float : parameter -> float - - (** The Symbol.Symbol value of the parameter.*) - val get_symbol : parameter -> Symbol.symbol - - (** The Sort value of the parameter.*) - val get_sort : parameter -> Sort.sort - - (** The AST value of the parameter.*) - val get_ast : parameter -> AST.ast - - (** The FunctionDeclaration value of the parameter.*) - val get_func_decl : parameter -> func_decl - - (** The rational string value of the parameter.*) - val get_rational : parameter -> string + val get_symbol : parameter -> symbol + val get_sort : parameter -> sort + val get_ast : parameter -> ast + val get_func_decl : parameter -> string end - (** Creates a new function declaration. *) - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new function declaration. *) - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - (** Creates a fresh function declaration with a name prefixed with a prefix string. *) - - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - - (** Creates a fresh constant function declaration with a name prefixed with a prefix string. - {!mk_func_decl} - {!mk_func_decl} *) - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - - (** Comparison operator. - @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) - val equal : func_decl -> func_decl -> bool - - (** A string representations of the function declaration. *) + val mk_func_decl : context -> symbol -> sort array -> sort -> func_decl + val mk_func_decl_s : context -> string -> sort array -> sort -> func_decl + val mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl + val mk_const_decl : context -> symbol -> sort -> func_decl + val mk_const_decl_s : context -> string -> sort -> func_decl + val mk_fresh_const_decl : context -> string -> sort -> func_decl + val ( = ) : func_decl -> func_decl -> bool val to_string : func_decl -> string - - (** Returns a unique identifier for the function declaration. *) val get_id : func_decl -> int - - (** The arity of the function declaration *) val get_arity : func_decl -> int - - (** The size of the domain of the function declaration - {!get_arity} *) val get_domain_size : func_decl -> int - - (** The domain of the function declaration *) - val get_domain : func_decl -> Sort.sort list - - (** The range of the function declaration *) - val get_range : func_decl -> Sort.sort - - (** The kind of the function declaration. *) + val get_domain : func_decl -> sort array + val get_range : func_decl -> sort val get_decl_kind : func_decl -> Z3enums.decl_kind - - (** The name of the function declaration*) - val get_name : func_decl -> Symbol.symbol - - (** The number of parameters of the function declaration *) + val get_name : func_decl -> symbol val get_num_parameters : func_decl -> int - - (** The parameters of the function declaration *) - val get_parameters : func_decl -> Parameter.parameter list - - (** Create expression that applies function to arguments. *) - val apply : func_decl -> Expr.expr list -> Expr.expr + val get_parameters : func_decl -> parameter list + val apply : func_decl -> expr array -> expr end -(** Parameter sets (of Solvers, Tactics, ...) - - A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) -and Params : +module Params : sig - type params - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) module ParamDescrs : sig - type param_descrs - - (** Validate a set of parameters. *) val validate : param_descrs -> params -> unit - - (** Retrieve kind of parameter. *) - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - - (** Retrieve all names of parameters. *) - val get_names : param_descrs -> Symbol.symbol list - - (** The size of the ParamDescrs. *) + val get_kind : param_descrs -> symbol -> Z3enums.param_kind + val get_names : param_descrs -> symbol array val get_size : param_descrs -> int - - (** Retrieves a string representation of the ParamDescrs. *) val to_string : param_descrs -> string end - (** Adds a parameter setting. *) - val add_bool : params -> Symbol.symbol -> bool -> unit - - (** Adds a parameter setting. *) - val add_int : params -> Symbol.symbol -> int -> unit - - (** Adds a parameter setting. *) - val add_float : params -> Symbol.symbol -> float -> unit - - (** Adds a parameter setting. *) - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - - (** Creates a new parameter set *) + val add_bool : params -> symbol -> bool -> unit + val add_int : params -> symbol -> int -> unit + val add_double : params -> symbol -> float -> unit + val add_symbol : params -> symbol -> symbol -> unit + val add_s_bool : params -> string -> bool -> unit + val add_s_int : params -> string -> int -> unit + val add_s_double : params -> string -> float -> unit + val add_s_symbol : params -> string -> symbol -> unit val mk_params : context -> params - - (** A string representation of the parameter set. *) val to_string : params -> string - - (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - [z3.exe -p] - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. *) - val update_param_value : context -> string -> string -> unit - - (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) - val set_print_mode : context -> Z3enums.ast_print_mode -> unit end -(** General Expressions (terms) *) -and Expr : +module Expr : sig - type expr = Expr of AST.ast - - val ast_of_expr : Expr.expr -> AST.ast - val expr_of_ast : AST.ast -> Expr.expr - - (** Returns a simplified version of the expression. - {!get_simplify_help} *) - val simplify : Expr.expr -> Params.params option -> expr - - (** A string describing all available parameters to [Expr.Simplify]. *) + val simplify : expr -> params option -> expr val get_simplify_help : context -> string - - (** Retrieves parameter descriptions for simplifier. *) - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - - (** The function declaration of the function that is applied in this expression. *) - val get_func_decl : Expr.expr -> FuncDecl.func_decl - - (** The number of arguments of the expression. *) - val get_num_args : Expr.expr -> int - - (** The arguments of the expression. *) - val get_args : Expr.expr -> Expr.expr list - - (** Update the arguments of the expression using an array of expressions. - The number of new arguments should coincide with the current number of arguments. *) - val update : Expr.expr -> Expr.expr list -> expr - - (** Substitute every occurrence of [from[i]] in the expression with [to[i]], for [i] smaller than [num_exprs]. - - The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. - For every [i] smaller than [num_exprs], we must have that - sort of [from[i]] must be equal to sort of [to[i]]. *) - val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr - - (** Substitute every occurrence of [from] in the expression with [to]. - {!substitute} *) - val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr - - (** Substitute the free variables in the expression with the expressions in the expr array - - For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) - val substitute_vars : Expr.expr -> Expr.expr list -> expr - - (** Translates (copies) the term to another context. - @return A copy of the term which is associated with the other context *) - val translate : Expr.expr -> context -> expr - - (** Returns a string representation of the expression. *) - val to_string : Expr.expr -> string - - (** Indicates whether the term is a numeral *) - val is_numeral : Expr.expr -> bool - - (** Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. *) - val is_well_sorted : Expr.expr -> bool - - (** The Sort of the term. *) - val get_sort : Expr.expr -> Sort.sort - - (** Indicates whether the term represents a constant. *) - val is_const : Expr.expr -> bool - - (** Creates a new constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - - (** Creates a new constant. *) - val mk_const_s : context -> string -> Sort.sort -> expr - - (** Creates a constant from the func_decl. *) - val mk_const_f : context -> FuncDecl.func_decl -> expr - - (** Creates a fresh constant with a name prefixed with a string. *) - val mk_fresh_const : context -> string -> Sort.sort -> expr - - (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - - (** Create a numeral of a given sort. - @return A Term with the given value and sort *) - val mk_numeral_string : context -> string -> Sort.sort -> expr - - (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. - @return A Term with the given value and sort *) - val mk_numeral_int : context -> int -> Sort.sort -> expr - - (** Comparison operator. - @return True if the two expr's are equal; false otherwise. *) - val equal : expr -> expr -> bool - - (** Object Comparison. - @return Negative if the first expr should be sorted before the second, positive if after, else zero. *) - val compare : expr -> expr -> int + val get_simplify_parameter_descrs : context -> param_descrs + val get_func_decl : expr -> func_decl + val get_bool_value : expr -> Z3enums.lbool + val get_num_args : expr -> int + val get_args : expr -> expr array + val update : expr -> expr array -> expr + val substitute : expr -> expr array -> expr array -> expr + val substitute_one : expr -> expr -> expr -> expr + val substitute_vars : expr -> expr array -> expr + val translate : expr -> context -> expr + val to_string : expr -> string + val is_numeral : expr -> bool + val is_well_sorted : expr -> bool + val get_sort : expr -> sort + val is_bool : expr -> bool + val is_const : expr -> bool + val is_true : expr -> bool + val is_false : expr -> bool + val is_eq : expr -> bool + val is_distinct : expr -> bool + val is_ite : expr -> bool + val is_and : expr -> bool + val is_or : expr -> bool + val is_iff : expr -> bool + val is_xor : expr -> bool + val is_not : expr -> bool + val is_implies : expr -> bool + val is_label : expr -> bool + val is_oeq : expr -> bool + val mk_const : context -> symbol -> sort -> expr + val mk_const_s : context -> string -> sort -> expr + val mk_const_f : context -> func_decl -> expr + val mk_fresh_const : context -> string -> sort -> expr + val mk_app : context -> func_decl -> expr array -> expr + val mk_numeral_string : context -> string -> sort -> expr + val mk_numeral_int : context -> int -> sort -> expr end -(** Boolean expressions; Propositional logic and equality *) module Boolean : sig - (** Create a Boolean sort *) - val mk_sort : context -> Sort.sort - - (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> Expr.expr - - (** Create a Boolean constant. *) - val mk_const_s : context -> string -> Expr.expr - - (** The true Term. *) - val mk_true : context -> Expr.expr - - (** The false Term. *) - val mk_false : context -> Expr.expr - - (** Creates a Boolean value. *) - val mk_val : context -> bool -> Expr.expr - - (** Mk an expression representing [not(a)]. *) - val mk_not : context -> Expr.expr -> Expr.expr - - (** Create an expression representing an if-then-else: [ite(t1, t2, t3)]. *) - val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 iff t2]. *) - val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 -> t2]. *) - val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 xor t2]. *) - val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing the AND of args *) - val mk_and : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing the OR of args *) - val mk_or : context -> Expr.expr list -> Expr.expr - - (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Creates a [distinct] term. *) - val mk_distinct : context -> Expr.expr list -> Expr.expr - - (** Indicates whether the expression is the true or false expression - or something else (L_UNDEF). *) - val get_bool_value : Expr.expr -> Z3enums.lbool - - (** Indicates whether the term has Boolean sort. *) - val is_bool : Expr.expr -> bool - - (** Indicates whether the term is the constant true. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is the constant false. *) - val is_false : Expr.expr -> bool - - (** Indicates whether the term is an equality predicate. *) - val is_eq : Expr.expr -> bool - - (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) - val is_distinct : Expr.expr -> bool - - (** Indicates whether the term is a ternary if-then-else term *) - val is_ite : Expr.expr -> bool - - (** Indicates whether the term is an n-ary conjunction *) - val is_and : Expr.expr -> bool - - (** Indicates whether the term is an n-ary disjunction *) - val is_or : Expr.expr -> bool - - (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) - val is_iff : Expr.expr -> bool - - (** Indicates whether the term is an exclusive or *) - val is_xor : Expr.expr -> bool - - (** Indicates whether the term is a negation *) - val is_not : Expr.expr -> bool - - (** Indicates whether the term is an implication *) - val is_implies : Expr.expr -> bool + val mk_sort : context -> bool_sort + val mk_const : context -> symbol -> bool_expr + val mk_const_s : context -> string -> bool_expr + val mk_true : context -> bool_expr + val mk_false : context -> bool_expr + val mk_val : context -> bool -> bool_expr + val mk_eq : context -> expr -> expr -> bool_expr + val mk_distinct : context -> expr array -> bool_expr + val mk_not : context -> bool_expr -> bool_expr + val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr + val mk_iff : context -> bool_expr -> bool_expr -> bool_expr + val mk_implies : context -> bool_expr -> bool_expr -> bool_expr + val mk_xor : context -> bool_expr -> bool_expr -> bool_expr + val mk_and : context -> bool_expr array -> bool_expr + val mk_or : context -> bool_expr array -> bool_expr end -(** Quantifier expressions *) module Quantifier : sig - type quantifier = Quantifier of Expr.expr - val expr_of_quantifier : quantifier -> Expr.expr - val quantifier_of_expr : Expr.expr -> quantifier - - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. *) module Pattern : sig - type pattern = Pattern of AST.ast - - val ast_of_pattern : pattern -> AST.ast - val pattern_of_ast : AST.ast -> pattern - - (** The number of terms in the pattern. *) val get_num_terms : pattern -> int - - (** The terms in the pattern. *) - val get_terms : pattern -> Expr.expr list - - (** A string representation of the pattern. *) + val get_terms : pattern -> expr array val to_string : pattern -> string end - - (** The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. *) - val get_index : Expr.expr -> int - - (** Indicates whether the quantifier is universal. *) + val get_index : expr -> int val is_universal : quantifier -> bool - - (** Indicates whether the quantifier is existential. *) val is_existential : quantifier -> bool - - (** The weight of the quantifier. *) val get_weight : quantifier -> int - - (** The number of patterns. *) val get_num_patterns : quantifier -> int - - (** The patterns. *) - val get_patterns : quantifier -> Pattern.pattern list - - (** The number of no-patterns. *) + val get_patterns : quantifier -> pattern array val get_num_no_patterns : quantifier -> int - - (** The no-patterns. *) - val get_no_patterns : quantifier -> Pattern.pattern list - - (** The number of bound variables. *) + val get_no_patterns : quantifier -> pattern array val get_num_bound : quantifier -> int - - (** The symbols for the bound variables. *) - val get_bound_variable_names : quantifier -> Symbol.symbol list - - (** The sorts of the bound variables. *) - val get_bound_variable_sorts : quantifier -> Sort.sort list - - (** The body of the quantifier. *) - val get_body : quantifier -> Expr.expr - - (** Creates a new bound variable. *) - val mk_bound : context -> int -> Sort.sort -> Expr.expr - - (** Create a quantifier pattern. *) - val mk_pattern : context -> Expr.expr list -> Pattern.pattern - - (** Create a universal Quantifier. *) - val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a universal Quantifier. *) - val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** A string representation of the quantifier. *) - val to_string : quantifier -> string + val get_bound_variable_names : quantifier -> symbol array + val get_bound_variable_sorts : quantifier -> sort array + val get_body : quantifier -> bool_expr + val mk_bound : context -> int -> sort -> expr + val mk_pattern : context -> expr array -> pattern + val mk_forall : + context -> + sort array -> + symbol array -> + expr -> + int option -> + pattern array -> + expr array -> symbol option -> symbol option -> quantifier + val mk_forall_const : + context -> + expr array -> + expr -> + int option -> + pattern array -> + expr array -> symbol option -> symbol option -> quantifier + val mk_exists : + context -> + sort array -> + symbol array -> + expr -> + int option -> + pattern array -> + expr array -> symbol option -> symbol option -> quantifier + val mk_exists_const : + context -> + expr array -> + expr -> + int option -> + pattern array -> + expr array -> symbol option -> symbol option -> quantifier + val mk_quantifier : + context -> + bool -> + expr array -> + expr -> + int option -> + pattern array -> + expr array -> symbol option -> symbol option -> quantifier end -(** Functions to manipulate Array expressions *) -module Z3Array : +module Array_ : sig - (** Create a new array sort. *) - val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort - - (** Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an array select. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - val is_constant_array : Expr.expr -> bool - - (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. *) - val is_default_array : Expr.expr -> bool - - (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - val is_array_map : Expr.expr -> bool - - (** Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. *) - val is_as_array : Expr.expr -> bool - - (** Indicates whether the term is of an array sort. *) - val is_array : Expr.expr -> bool - - (** The domain of the array sort. *) - val get_domain : Sort.sort -> Sort.sort - - (** The range of the array sort. *) - val get_range : Sort.sort -> Sort.sort - - (** Create an array constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> Expr.expr - - (** Create an array constant. *) - val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> Expr.expr - - (** Array read. - - The argument [a] is the array and [i] is the index - of the array that gets read. - - The node [a] must have an array sort [[domain -> range]], - and [i] must have the sort [domain]. - The sort of the result is [range]. - {!Z3Array.mk_sort} - {!mk_store} *) - val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Array update. - - The node [a] must have an array sort [[domain -> range]], - [i] must have sort [domain], - [v] must have sort range. The sort of the result is [[domain -> range]]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to [a] - (with respect to [select]) - on all indices except for [i], where it maps to [v] - (and the [select] of [a] with - respect to [i] may be a different value). - {!Z3Array.mk_sort} - {!mk_select} *) - val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a constant array. - - The resulting term is an array, such that a [select]on an arbitrary index - produces the value [v]. - {!Z3Array.mk_sort} - {!mk_select} *) - val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr - - (** Maps f on the argument arrays. - - Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. - The function declaration [f] must have type [ range_1 .. range_n -> range]. - [v] must have sort range. The sort of the result is [[domain_i -> range]]. - {!Z3Array.mk_sort} - {!mk_select} - {!mk_store} *) - val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr - - (** Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. *) - val mk_term_array : context -> Expr.expr -> Expr.expr + val mk_sort : context -> sort -> sort -> array_sort + val is_store : expr -> bool + val is_select : expr -> bool + val is_constant_array : expr -> bool + val is_default_array : expr -> bool + val is_array_map : expr -> bool + val is_as_array : expr -> bool + val is_array : expr -> bool + val get_domain : array_sort -> sort + val get_range : array_sort -> sort + val mk_const : context -> symbol -> sort -> sort -> array_expr + val mk_const_s : context -> string -> sort -> sort -> array_expr + val mk_select : context -> array_expr -> expr -> expr -> expr + val mk_const_array : context -> sort -> expr -> expr + val mk_map : context -> func_decl -> array_expr array -> expr + val mk_term_array : context -> array_expr -> expr end -(** Functions to manipulate Set expressions *) module Set : sig - (** Create a set type. *) - val mk_sort : context -> Sort.sort -> Sort.sort - - (** Indicates whether the term is set union *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is set intersection *) - val is_intersect : Expr.expr -> bool - - (** Indicates whether the term is set difference *) - val is_difference : Expr.expr -> bool - - (** Indicates whether the term is set complement *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is set subset *) - val is_subset : Expr.expr -> bool - - (** Create an empty set. *) - val mk_empty : context -> Sort.sort -> Expr.expr - - (** Create the full set. *) - val mk_full : context -> Sort.sort -> Expr.expr - - (** Add an element to the set. *) - val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Remove an element from a set. *) - val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the union of a list of sets. *) - val mk_union : context -> Expr.expr list -> Expr.expr - - (** Take the intersection of a list of sets. *) - val mk_intersection : context -> Expr.expr list -> Expr.expr - - (** Take the difference between two sets. *) - val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the complement of a set. *) - val mk_complement : context -> Expr.expr -> Expr.expr - - (** Check for set membership. *) - val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Check for subsetness of sets. *) - val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr + val is_union : expr -> bool + val is_intersect : expr -> bool + val is_difference : expr -> bool + val is_complement : expr -> bool + val is_subset : expr -> bool + val mk_sort : context -> sort -> set_sort + val mk_empty : context -> sort -> expr + val mk_full : context -> sort -> expr + val mk_set_add : context -> expr -> expr -> expr + val mk_del : context -> expr -> expr -> expr + val mk_union : context -> expr array -> expr + val mk_intersection : context -> expr array -> expr + val mk_difference : context -> expr -> expr -> expr + val mk_complement : context -> expr -> expr + val mk_membership : context -> expr -> expr -> expr + val mk_subset : context -> expr -> expr -> expr end -(** Functions to manipulate Finite Domain expressions *) module FiniteDomain : sig - (** Create a new finite domain sort. *) - val mk_sort : context -> Symbol.symbol -> int -> Sort.sort - - (** Create a new finite domain sort. *) - val mk_sort_s : context -> string -> int -> Sort.sort - - (** Indicates whether the term is of an array sort. *) - val is_finite_domain : Expr.expr -> bool - - (** Indicates whether the term is a less than predicate over a finite domain. *) - val is_lt : Expr.expr -> bool - - (** The size of the finite domain sort. *) - val get_size : Sort.sort -> int + val mk_sort : context -> symbol -> int -> finite_domain_sort + val mk_sort_s : context -> string -> int -> finite_domain_sort + val is_finite_domain : expr -> bool + val is_lt : expr -> bool + val get_size : finite_domain_sort -> int end - -(** Functions to manipulate Relation expressions *) module Relation : sig - (** Indicates whether the term is of a relation sort. *) - val is_relation : Expr.expr -> bool - - (** Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements - correspond to the [n] columns of the relation. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an empty relation *) - val is_empty : Expr.expr -> bool - - (** Indicates whether the term is a test for the emptiness of a relation *) - val is_is_empty : Expr.expr -> bool - - (** Indicates whether the term is a relational join *) - val is_join : Expr.expr -> bool - - (** Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is the widening of two relations - The function takes two arguments. *) - val is_widen : Expr.expr -> bool - - (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. *) - val is_project : Expr.expr -> bool - - (** Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. *) - val is_filter : Expr.expr -> bool - - (** Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. *) - val is_negation_filter : Expr.expr -> bool - - (** Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. *) - val is_rename : Expr.expr -> bool - - (** Indicates whether the term is the complement of a relation *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes [n+1] arguments, where the first argument is a relation, - and the remaining [n] arguments correspond to a record. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind {!is_union} - to perform destructive updates to the first argument. *) - val is_clone : Expr.expr -> bool - - (** The arity of the relation sort. *) - val get_arity : Sort.sort -> int - - (** The sorts of the columns of the relation sort. *) - val get_column_sorts : Sort.sort -> Sort.sort list + val is_relation : expr -> bool + val is_store : expr -> bool + val is_empty : expr -> bool + val is_is_empty : expr -> bool + val is_join : expr -> bool + val is_union : expr -> bool + val is_widen : expr -> bool + val is_project : expr -> bool + val is_filter : expr -> bool + val is_negation_filter : expr -> bool + val is_rename : expr -> bool + val is_complement : expr -> bool + val is_select : expr -> bool + val is_clone : expr -> bool + val get_arity : relation_sort -> int + val get_column_sorts : relation_sort -> relation_sort array end -(** Functions to manipulate Datatype expressions *) module Datatype : sig - (** Datatype Constructors *) + module Constructor : sig - type constructor - - (** The number of fields of the constructor. *) + val get_n : constructor -> int + val tester_decl : constructor -> func_decl + val constructor_decl : constructor -> func_decl + val accessor_decls : constructor -> func_decl array val get_num_fields : constructor -> int - - (** The function declaration of the constructor. *) - val get_constructor_decl : constructor -> FuncDecl.func_decl - - (** The function declaration of the tester. *) - val get_tester_decl : constructor -> FuncDecl.func_decl - - (** The function declarations of the accessors *) - val get_accessor_decls : constructor -> FuncDecl.func_decl list + val get_constructor_decl : constructor -> func_decl + val get_tester_decl : constructor -> func_decl + val get_accessor_decls : constructor -> func_decl array end - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor - - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor - - (** Create a new datatype sort. *) - val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> Sort.sort - - (** Create a new datatype sort. *) - val mk_sort_s : context -> string -> Constructor.constructor list -> Sort.sort - - (** Create mutually recursive datatypes. *) - val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> Sort.sort list - - (** Create mutually recursive data-types. *) - val mk_sorts_s : context -> string list -> Constructor.constructor list list -> Sort.sort list - - - (** The number of constructors of the datatype sort. *) - val get_num_constructors : Sort.sort -> int - - (** The constructors. *) - val get_constructors : Sort.sort -> FuncDecl.func_decl list - - (** The recognizers. *) - val get_recognizers : Sort.sort -> FuncDecl.func_decl list - - (** The constructor accessors. *) - val get_accessors : Sort.sort -> FuncDecl.func_decl list list + val mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor + val mk_constructor_s : context -> string -> symbol -> symbol array -> sort array -> int array -> constructor + val mk_sort : context -> symbol -> constructor array -> datatype_sort + val mk_sort_s : context -> string -> constructor array -> datatype_sort + val mk_sorts : context -> symbol array -> constructor array array -> datatype_sort array + val mk_sorts_s : context -> string array -> constructor array array -> datatype_sort array + val get_num_constructors : datatype_sort -> int + val get_constructors : datatype_sort -> func_decl array + val get_recognizers : datatype_sort -> func_decl array + val get_accessors : datatype_sort -> func_decl array array end -(** Functions to manipulate Enumeration expressions *) module Enumeration : sig - (** Create a new enumeration sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort - - (** Create a new enumeration sort. *) - val mk_sort_s : context -> string -> string list -> Sort.sort - - (** The function declarations of the constants in the enumeration. *) - val get_const_decls : Sort.sort -> FuncDecl.func_decl list - - (** The test predicates for the constants in the enumeration. *) - val get_tester_decls : Sort.sort -> FuncDecl.func_decl list + val mk_sort : context -> symbol -> symbol array -> enum_sort + val mk_sort_s : context -> string -> string array -> enum_sort + val get_const_decls : enum_sort -> func_decl array + val get_tester_decls : enum_sort -> func_decl array end -(** Functions to manipulate List expressions *) -module Z3List : +module List_ : sig - (** Create a new list sort. *) - val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort - - (** Create a new list sort. *) - val mk_list_s : context -> string -> Sort.sort -> Sort.sort - - (** The declaration of the nil function of this list sort. *) - val get_nil_decl : Sort.sort -> FuncDecl.func_decl - - (** The declaration of the isNil function of this list sort. *) - val get_is_nil_decl : Sort.sort -> FuncDecl.func_decl - - (** The declaration of the cons function of this list sort. *) - val get_cons_decl : Sort.sort -> FuncDecl.func_decl - - (** The declaration of the isCons function of this list sort. *) - val get_is_cons_decl : Sort.sort -> FuncDecl.func_decl - - (** The declaration of the head function of this list sort. *) - val get_head_decl : Sort.sort -> FuncDecl.func_decl - - (** The declaration of the tail function of this list sort. *) - val get_tail_decl : Sort.sort -> FuncDecl.func_decl - - (** The empty list. *) - val nil : Sort.sort -> Expr.expr + val mk_sort : context -> symbol -> sort -> list_sort + val mk_list_s : context -> string -> sort -> list_sort + val get_nil_decl : list_sort -> func_decl + val get_is_nil_decl : list_sort -> func_decl + val get_cons_decl : list_sort -> func_decl + val get_is_cons_decl : list_sort -> func_decl + val get_head_decl : list_sort -> func_decl + val get_tail_decl : list_sort -> func_decl + val nil : list_sort -> expr end -(** Functions to manipulate Tuple expressions *) module Tuple : sig - (** Create a new tuple sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> Sort.sort - - (** The constructor function of the tuple. *) - val get_mk_decl : Sort.sort -> FuncDecl.func_decl - - (** The number of fields in the tuple. *) - val get_num_fields : Sort.sort -> int - - (** The field declarations. *) - val get_field_decls : Sort.sort -> FuncDecl.func_decl list + val mk_sort : + context -> symbol -> symbol array -> sort array -> tuple_sort + val get_mk_decl : tuple_sort -> func_decl + val get_num_fields : tuple_sort -> int + val get_field_decls : tuple_sort -> func_decl array end -(** Functions to manipulate arithmetic expressions *) module Arithmetic : sig - (** Integer Arithmetic *) + module Integer : sig - (** Create a new integer sort. *) - val mk_sort : context -> Sort.sort - - (** Retrieve the int value. *) - val get_int : Expr.expr -> int - - (** Get a big_int from an integer numeral *) - val get_big_int : Expr.expr -> Big_int.big_int - - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string - - (** Creates an integer constant. *) - val mk_const : context -> Symbol.symbol -> Expr.expr - - (** Creates an integer constant. *) - val mk_const_s : context -> string -> Expr.expr - - (** Create an expression representing [t1 mod t2]. - The arguments must have int type. *) - val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 rem t2]. - The arguments must have int type. *) - val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an integer numeral. *) - val mk_numeral_s : context -> string -> Expr.expr - - (** Create an integer numeral. - @return A Term with the given value and sort Integer *) - val mk_numeral_i : context -> int -> Expr.expr - - (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term [k] and - and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. - The argument must be of integer sort. *) - val mk_int2real : context -> Expr.expr -> Expr.expr - - (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) - val mk_int2bv : context -> int -> Expr.expr -> Expr.expr + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> expr + val mk_rem : context -> int_expr -> int_expr -> expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> real_expr + val mk_int2bv : context -> int -> int_expr -> bitvec_expr end - (** Real Arithmetic *) module Real : sig - (** Create a real sort. *) - val mk_sort : context -> Sort.sort - - (** The numerator of a rational numeral. *) - val get_numerator : Expr.expr -> Expr.expr - - (** The denominator of a rational numeral. *) - val get_denominator : Expr.expr -> Expr.expr - - (** Get a ratio from a real numeral *) - val get_ratio : Expr.expr -> Ratio.ratio - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as indicated by the int argument.*) - val to_decimal_string : Expr.expr-> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr-> string - - (** Creates a real constant. *) - val mk_const : context -> Symbol.symbol -> Expr.expr - - (** Creates a real constant. *) - val mk_const_s : context -> string -> Expr.expr - - (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) - val mk_numeral_nd : context -> int -> int -> Expr.expr - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_s : context -> string -> Expr.expr - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_i : context -> int -> Expr.expr - - (** Creates an expression that checks whether a real number is an integer. *) - val mk_is_integer : context -> Expr.expr -> Expr.expr - - (** Coerce a real to an integer. - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) - val mk_real2int : context -> Expr.expr -> Expr.expr - - (** Algebraic Numbers *) - module AlgebraicNumber : - sig - (** Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_upper : Expr.expr -> int -> Expr.expr - - (** Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_lower : Expr.expr -> int -> Expr.expr - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as the int argument provided.*) - val to_decimal_string : Expr.expr -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string - end + val mk_sort : context -> real_sort + val get_numerator : rat_num -> int_num + val get_denominator : rat_num -> int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> bool_expr + val mk_real2int : context -> real_expr -> int_expr end - (** Indicates whether the term is of integer sort. *) - val is_int : Expr.expr -> bool + module AlgebraicNumber : + sig + val to_upper : algebraic_num -> int -> rat_num + val to_lower : algebraic_num -> int -> rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end - (** Indicates whether the term is an arithmetic numeral. *) - val is_arithmetic_numeral : Expr.expr -> bool - - (** Indicates whether the term is a less-than-or-equal *) - val is_le : Expr.expr -> bool - - (** Indicates whether the term is a greater-than-or-equal *) - val is_ge : Expr.expr -> bool - - (** Indicates whether the term is a less-than *) - val is_lt : Expr.expr -> bool - - (** Indicates whether the term is a greater-than *) - val is_gt : Expr.expr -> bool - - (** Indicates whether the term is addition (binary) *) - val is_add : Expr.expr -> bool - - (** Indicates whether the term is subtraction (binary) *) - val is_sub : Expr.expr -> bool - - (** Indicates whether the term is a unary minus *) - val is_uminus : Expr.expr -> bool - - (** Indicates whether the term is multiplication (binary) *) - val is_mul : Expr.expr -> bool - - (** Indicates whether the term is division (binary) *) - val is_div : Expr.expr -> bool - - (** Indicates whether the term is integer division (binary) *) - val is_idiv : Expr.expr -> bool - - (** Indicates whether the term is remainder (binary) *) - val is_remainder : Expr.expr -> bool - - (** Indicates whether the term is modulus (binary) *) - val is_modulus : Expr.expr -> bool - - (** Indicates whether the term is a coercion of integer to real (unary) *) - val is_inttoreal : Expr.expr -> bool - - (** Indicates whether the term is a coercion of real to integer (unary) *) - val is_real_to_int : Expr.expr -> bool - - (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - val is_real_is_int : Expr.expr -> bool - - (** Indicates whether the term is of sort real. *) - val is_real : Expr.expr -> bool - - (** Indicates whether the term is an integer numeral. *) - val is_int_numeral : Expr.expr -> bool - - (** Indicates whether the term is a real numeral. *) - val is_rat_numeral : Expr.expr -> bool - - (** Indicates whether the term is an algebraic number *) - val is_algebraic_number : Expr.expr -> bool - - (** Create an expression representing [t[0] + t[1] + ...]. *) - val mk_add : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing [t[0] * t[1] * ...]. *) - val mk_mul : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing [t[0] - t[1] - ...]. *) - val mk_sub : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing [-t]. *) - val mk_unary_minus : context -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 / t2]. *) - val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 ^ t2]. *) - val mk_power : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 < t2] *) - val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 <= t2] *) - val mk_le : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 > t2] *) - val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing [t1 >= t2] *) - val mk_ge : context -> Expr.expr -> Expr.expr -> Expr.expr + val is_int : expr -> bool + val is_arithmetic_numeral : expr -> bool + val is_le : expr -> bool + val is_ge : expr -> bool + val is_lt : expr -> bool + val is_gt : expr -> bool + val is_add : expr -> bool + val is_sub : expr -> bool + val is_uminus : expr -> bool + val is_mul : expr -> bool + val is_div : expr -> bool + val is_idiv : expr -> bool + val is_remainder : expr -> bool + val is_modulus : expr -> bool + val is_inttoreal : expr -> bool + val is_real_to_int : expr -> bool + val is_real_is_int : expr -> bool + val is_real : expr -> bool + val is_int_numeral : expr -> bool + val is_rat_num : expr -> bool + val is_algebraic_number : expr -> bool + val mk_add : context -> arith_expr array -> arith_expr + val mk_mul : context -> arith_expr array -> arith_expr + val mk_sub : context -> arith_expr array -> arith_expr + val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_lt : context -> arith_expr -> arith_expr -> bool_expr + val mk_le : context -> arith_expr -> arith_expr -> bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> bool_expr end -(** Functions to manipulate bit-vector expressions *) module BitVector : sig - (** Create a new bit-vector sort. *) - val mk_sort : context -> int -> Sort.sort - - (** Indicates whether the terms is of bit-vector sort. *) - val is_bv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector numeral *) - val is_bv_numeral : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value one *) - val is_bv_bit1 : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value zero *) - val is_bv_bit0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unary minus *) - val is_bv_uminus : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector addition (binary) *) - val is_bv_add : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector subtraction (binary) *) - val is_bv_sub : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector multiplication (binary) *) - val is_bv_mul : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division (binary) *) - val is_bv_sdiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division (binary) *) - val is_bv_udiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder (binary) *) - val is_bv_SRem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - val is_bv_urem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus *) - val is_bv_smod : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division by zero *) - val is_bv_sdiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division by zero *) - val is_bv_udiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder by zero *) - val is_bv_srem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - val is_bv_urem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus by zero *) - val is_bv_smod0 : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - val is_bv_ule : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - val is_bv_sle : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - val is_bv_uge : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - val is_bv_sge : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than *) - val is_bv_ult : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than *) - val is_bv_slt : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than *) - val is_bv_ugt : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than *) - val is_bv_sgt : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise AND *) - val is_bv_and : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise OR *) - val is_bv_or : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOT *) - val is_bv_not : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XOR *) - val is_bv_xor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NAND *) - val is_bv_nand : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOR *) - val is_bv_nor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XNOR *) - val is_bv_xnor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector concatenation (binary) *) - val is_bv_concat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector sign extension *) - val is_bv_signextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector zero extension *) - val is_bv_zeroextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector extraction *) - val is_bv_extract : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector repetition *) - val is_bv_repeat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce OR *) - val is_bv_reduceor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce AND *) - val is_bv_reduceand : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector comparison *) - val is_bv_comp : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector shift left *) - val is_bv_shiftleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector logical shift right *) - val is_bv_shiftrightlogical : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector arithmetic shift left *) - val is_bv_shiftrightarithmetic : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left *) - val is_bv_rotateleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right *) - val is_bv_rotateright : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotateleftextended : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotaterightextended : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - - (** Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_int_to_bv : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_bv_to_int : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - val is_bv_carry : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - val is_bv_xor3 : Expr.expr -> bool - - (** The size of a bit-vector sort. *) - val get_size : Sort.sort -> int - - (** Retrieve the int value. *) - val get_int : Expr.expr -> int - - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string - - (** Creates a bit-vector constant. *) - val mk_const : context -> Symbol.symbol -> int -> Expr.expr - - (** Creates a bit-vector constant. *) - val mk_const_s : context -> string -> int -> Expr.expr - - (** Bitwise negation. - The argument must have a bit-vector sort. *) - val mk_not : context -> Expr.expr -> Expr.expr - - (** Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redand : context -> Expr.expr -> Expr.expr - - (** Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redor : context -> Expr.expr -> Expr.expr - - (** Bitwise conjunction. - The arguments must have a bit-vector sort. *) - val mk_and : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bitwise disjunction. - The arguments must have a bit-vector sort. *) - val mk_or : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bitwise XOR. - The arguments must have a bit-vector sort. *) - val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bitwise NAND. - The arguments must have a bit-vector sort. *) - val mk_nand : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bitwise NOR. - The arguments must have a bit-vector sort. *) - val mk_nor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bitwise XNOR. - The arguments must have a bit-vector sort. *) - val mk_xnor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Standard two's complement unary minus. - The arguments must have a bit-vector sort. *) - val mk_neg : context -> Expr.expr -> Expr.expr - - (** Two's complement addition. - The arguments must have the same bit-vector sort. *) - val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement subtraction. - The arguments must have the same bit-vector sort. *) - val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement multiplication. - The arguments must have the same bit-vector sort. *) - val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned division. - - It is defined as the floor of [t1/t2] if \c t2 is - different from zero. If [t2] is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. *) - val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Signed division. - - It is defined in the following way: - - - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. - - - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. - - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned remainder. - - It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Signed remainder. - - It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement signed remainder (sign follows divisor). - - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned less-than - - The arguments must have the same bit-vector sort. *) - val mk_ult : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement signed less-than - - The arguments must have the same bit-vector sort. *) - val mk_slt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_ule : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sle : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_uge : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sge : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Unsigned greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_ugt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_sgt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size [n1+n2], where [n1] ([n2]) - is the size of [t1] ([t2]). *) - val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Bit-vector extraction. - - Extract the bits between two limits from a bitvector of - size [m] to yield a new bitvector of size [n], where - [n = high - low + 1]. *) - val mk_extract : context -> int -> int -> Expr.expr -> Expr.expr - - (** Bit-vector sign extension. - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size [m+i], where \c m is the size of the given bit-vector. *) - val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr - - (** Bit-vector zero extension. - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size [m+i], where \c m is the size of the - given bit-vector. *) - val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr - - (** Bit-vector repetition. *) - val mk_repeat : context -> int -> Expr.expr -> Expr.expr - - (** Shift left. - - It is equivalent to multiplication by [2^x] where \c x is the value of third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling.*) - val mk_shl : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Logical shift right - - It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_lshr : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_ashr : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Rotate Left. - Rotate bits of \c t to the left \c i times. *) - val mk_rotate_left : context -> int -> Expr.expr -> Expr.expr - - (** Rotate Right. - Rotate bits of \c t to the right \c i times.*) - val mk_rotate_right : context -> int -> Expr.expr -> Expr.expr - - (** Rotate Left. - Rotate bits of the second argument to the left.*) - val mk_ext_rotate_left : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Rotate Right. - Rotate bits of the second argument to the right. *) - val mk_ext_rotate_right : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an integer from the bit-vector argument - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [[0..2^N-1]], where - N are the number of bits in the argument. - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function.*) - val mk_bv2int : context -> Expr.expr -> bool -> Expr.expr - - (** Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr - - (** Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_underflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr - - (** Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sdiv_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_neg_no_overflow : context -> Expr.expr -> Expr.expr - - (** Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr - - (** Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a bit-vector numeral. *) - val mk_numeral : context -> string -> int -> Expr.expr + val mk_sort : context -> int -> bitvec_sort + val is_bv : expr -> bool + val is_bv_numeral : expr -> bool + val is_bv_bit1 : expr -> bool + val is_bv_bit0 : expr -> bool + val is_bv_uminus : expr -> bool + val is_bv_add : expr -> bool + val is_bv_sub : expr -> bool + val is_bv_mul : expr -> bool + val is_bv_sdiv : expr -> bool + val is_bv_udiv : expr -> bool + val is_bv_SRem : expr -> bool + val is_bv_urem : expr -> bool + val is_bv_smod : expr -> bool + val is_bv_sdiv0 : expr -> bool + val is_bv_udiv0 : expr -> bool + val is_bv_srem0 : expr -> bool + val is_bv_urem0 : expr -> bool + val is_bv_smod0 : expr -> bool + val is_bv_ule : expr -> bool + val is_bv_sle : expr -> bool + val is_bv_uge : expr -> bool + val is_bv_sge : expr -> bool + val is_bv_ult : expr -> bool + val is_bv_slt : expr -> bool + val is_bv_ugt : expr -> bool + val is_bv_sgt : expr -> bool + val is_bv_and : expr -> bool + val is_bv_or : expr -> bool + val is_bv_not : expr -> bool + val is_bv_xor : expr -> bool + val is_bv_nand : expr -> bool + val is_bv_nor : expr -> bool + val is_bv_xnor : expr -> bool + val is_bv_concat : expr -> bool + val is_bv_signextension : expr -> bool + val is_bv_zeroextension : expr -> bool + val is_bv_extract : expr -> bool + val is_bv_repeat : expr -> bool + val is_bv_reduceor : expr -> bool + val is_bv_reduceand : expr -> bool + val is_bv_comp : expr -> bool + val is_bv_shiftleft : expr -> bool + val is_bv_shiftrightlogical : expr -> bool + val is_bv_shiftrightarithmetic : expr -> bool + val is_bv_rotateleft : expr -> bool + val is_bv_rotateright : expr -> bool + val is_bv_rotateleftextended : expr -> bool + val is_bv_rotaterightextended : expr -> bool + val is_int_to_bv : expr -> bool + val is_bv_to_int : expr -> bool + val is_bv_carry : expr -> bool + val is_bv_xor3 : expr -> bool + val get_size : bitvec_sort -> int + val get_int : bitvec_num -> int + val to_string : bitvec_num -> string + val mk_const : context -> symbol -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> bitvec_expr + val mk_not : context -> bitvec_expr -> expr + val mk_redand : context -> bitvec_expr -> expr + val mk_redor : context -> bitvec_expr -> expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> expr + val mk_neg : context -> bitvec_expr -> expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> expr + val mk_extract : context -> int -> int -> bitvec_expr -> expr + val mk_sign_ext : context -> int -> bitvec_expr -> expr + val mk_zero_ext : context -> int -> bitvec_expr -> expr + val mk_repeat : context -> int -> bitvec_expr -> expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> expr + val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> expr + val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> expr + val mk_bv2int : context -> bitvec_expr -> bool -> int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_numeral : context -> string -> int -> bitvec_num end -(** Functions to manipulate proof expressions *) module Proof : sig - (** Indicates whether the term is a Proof for the expression 'true'. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact asserted by the user. *) - val is_asserted : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - val is_goal : Expr.expr -> bool - - (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) - val is_oeq : Expr.expr -> bool - - (** Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). *) - val is_modus_ponens : Expr.expr -> bool - - (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. *) - val is_reflexivity : Expr.expr -> bool - - (** Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. *) - val is_symmetry : Expr.expr -> bool - - (** Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) *) - val is_transitivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. *) - val is_Transitivity_star : Expr.expr -> bool - - (** Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. *) - val is_monotonicity : Expr.expr -> bool - - (** Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - val is_quant_intro : Expr.expr -> bool - - (** Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. *) - val is_distributivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i *) - val is_and_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) *) - val is_or_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) *) - val is_rewrite : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - val is_rewrite_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - val is_pull_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents *) - val is_pull_quant_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents *) - val is_push_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. *) - val is_elim_unused_vars : Expr.expr -> bool - - (** Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. *) - val is_der : Expr.expr -> bool - - (** Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) *) - val is_quant_inst : Expr.expr -> bool - - (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. *) - val is_hypothesis : Expr.expr -> bool - - (** Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. *) - val is_lemma : Expr.expr -> bool - - (** Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - val is_unit_resolution : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) *) - val is_iff_true : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) *) - val is_iff_false : Expr.expr -> bool - - (** Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. *) - val is_commutativity : Expr.expr -> bool - - (** Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). *) - val is_def_axiom : Expr.expr -> bool - - (** Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) *) - val is_def_intro : Expr.expr -> bool - - (** Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. *) - val is_apply_def : Expr.expr -> bool - - (** Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) *) - val is_iff_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. *) - val is_nnf_pos : Expr.expr -> bool - - (** Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) *) - val is_nnf_neg : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_nnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_cnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. *) - val is_skolemize : Expr.expr -> bool - - (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q *) - val is_modus_ponens_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - val is_theory_lemma : Expr.expr -> bool + val is_true : expr -> bool + val is_asserted : expr -> bool + val is_goal : expr -> bool + val is_modus_ponens : expr -> bool + val is_reflexivity : expr -> bool + val is_symmetry : expr -> bool + val is_transitivity : expr -> bool + val is_Transitivity_star : expr -> bool + val is_monotonicity : expr -> bool + val is_quant_intro : expr -> bool + val is_distributivity : expr -> bool + val is_and_elimination : expr -> bool + val is_or_elimination : expr -> bool + val is_rewrite : expr -> bool + val is_rewrite_star : expr -> bool + val is_pull_quant : expr -> bool + val is_pull_quant_star : expr -> bool + val is_push_quant : expr -> bool + val is_elim_unused_vars : expr -> bool + val is_der : expr -> bool + val is_quant_inst : expr -> bool + val is_hypothesis : expr -> bool + val is_lemma : expr -> bool + val is_unit_resolution : expr -> bool + val is_iff_true : expr -> bool + val is_iff_false : expr -> bool + val is_commutativity : expr -> bool + val is_def_axiom : expr -> bool + val is_def_intro : expr -> bool + val is_apply_def : expr -> bool + val is_iff_oeq : expr -> bool + val is_nnf_pos : expr -> bool + val is_nnf_neg : expr -> bool + val is_nnf_star : expr -> bool + val is_cnf_star : expr -> bool + val is_skolemize : expr -> bool + val is_modus_ponens_oeq : expr -> bool + val is_theory_lemma : expr -> bool end -(** Goals - - A goal (aka problem). A goal is essentially a - of formulas, that can be solved and/or transformed using - tactics and solvers. *) module Goal : sig - type goal - - (** The precision of the goal. - - Goals can be transformed using over and under approximations. - An under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. *) val get_precision : goal -> Z3enums.goal_prec - - (** Indicates whether the goal is precise. *) val is_precise : goal -> bool - - (** Indicates whether the goal is an under-approximation. *) val is_underapproximation : goal -> bool - - (** Indicates whether the goal is an over-approximation. *) val is_overapproximation : goal -> bool - - (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) val is_garbage : goal -> bool - - (** Adds the constraints to the given goal. *) - val add : goal -> Expr.expr list -> unit - - (** Indicates whether the goal contains `false'. *) + val assert_ : goal -> bool_expr array -> unit val is_inconsistent : goal -> bool - - (** The depth of the goal. - This tracks how many transformations were applied to it. *) val get_depth : goal -> int - - (** Erases all formulas from the given goal. *) val reset : goal -> unit - - (** The number of formulas in the goal. *) val get_size : goal -> int - - (** The formulas in the goal. *) - val get_formulas : goal -> Expr.expr list - - (** The number of formulas, subformulas and terms in the goal. *) + val get_formulas : goal -> bool_expr array val get_num_exprs : goal -> int - - (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) val is_decided_sat : goal -> bool - - (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) val is_decided_unsat : goal -> bool - - (** Translates (copies) the Goal to another context.. *) val translate : goal -> context -> goal - - (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - val simplify : goal -> Params.params option -> goal - - (** Creates a new Goal. - - Note that the Context must have been created with proof generation support if - the fourth argument is set to true here. *) + val simplify : goal -> params option -> goal val mk_goal : context -> bool -> bool -> bool -> goal - - (** A string representation of the Goal. *) val to_string : goal -> string end -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) module Model : sig - type model - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. *) module FuncInterp : sig - type func_interp - - (** Function interpretations entries - An Entry object represents an element in the finite map used to a function interpretation. *) module FuncEntry : sig - type func_entry - - (** Return the (symbolic) value of this entry. - *) - val get_value : func_entry -> Expr.expr - - (** The number of arguments of the entry. - *) + val get_value : func_entry -> expr val get_num_args : func_entry -> int - - (** The arguments of the function entry. - *) - val get_args : func_entry -> Expr.expr list - - (** A string representation of the function entry. - *) + val get_args : func_entry -> expr array val to_string : func_entry -> string end - (** The number of entries in the function interpretation. *) val get_num_entries : func_interp -> int - - (** The entries in the function interpretation *) - val get_entries : func_interp -> FuncEntry.func_entry list - - (** The (symbolic) `else' value of the function interpretation. *) - val get_else : func_interp -> Expr.expr - - (** The arity of the function interpretation *) + val get_entries : func_interp -> func_entry array + val get_else : func_interp -> expr val get_arity : func_interp -> int - - (** A string representation of the function interpretation. *) val to_string : func_interp -> string end - (** Retrieves the interpretation (the assignment) of a func_decl in the model. - @return An expression if the function has an interpretation in the model, null otherwise. *) - val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of an expression in the model. - @return An expression if the constant has an interpretation in the model, null otherwise. *) - val get_const_interp_e : model -> Expr.expr -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. - @return A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option - - (** The number of constant interpretations in the model. *) + val get_const_interp : model -> func_decl -> expr option + val get_const_interp_e : model -> expr -> expr option + val get_func_interp : model -> func_decl -> func_interp option val get_num_consts : model -> int - - (** The function declarations of the constants in the model. *) - val get_const_decls : model -> FuncDecl.func_decl list - - (** The number of function interpretations in the model. *) + val get_const_decls : model -> func_decl array val get_num_funcs : model -> int - - (** The function declarations of the function interpretations in the model. *) - val get_func_decls : model -> FuncDecl.func_decl list - - (** All symbols that have an interpretation in the model. *) - val get_decls : model -> FuncDecl.func_decl list - - (** Evaluates an expression in the current model. - - This function may fail if the argument contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. - In this case a [ModelEvaluationFailedException] is thrown. - *) - val eval : model -> Expr.expr -> bool -> Expr.expr option - - (** Alias for [eval]. *) - val evaluate : model -> Expr.expr -> bool -> Expr.expr option - - (** The number of uninterpreted sorts that the model has an interpretation for. *) + val get_func_decls : model -> func_decl array + val get_decls : model -> func_decl array + exception ModelEvaluationFailedException of string + val eval : model -> expr -> bool -> expr + val evaluate : model -> expr -> bool -> expr val get_num_sorts : model -> int - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - {!get_num_sorts} - {!sort_universe} *) - val get_sorts : model -> Sort.sort list - - (** The finite set of distinct values that represent the interpretation of a sort. - {!get_sorts} - @return A list of expressions, where each is an element of the universe of the sort *) - val sort_universe : model -> Sort.sort -> AST.ast list - - (** Conversion of models to strings. - @return A string representation of the model. *) + val get_sorts : model -> sort array + val sort_universe : model -> sort -> ast_vector array val to_string : model -> string end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures [Context.NumProbes] - and [Context.ProbeNames]. - It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. -*) module Probe : sig - type probe - - (** Execute the probe over the goal. - @return A probe always produce a float value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - val apply : probe -> Goal.goal -> float - - (** The number of supported Probes. *) + val apply : probe -> goal -> float val get_num_probes : context -> int - - (** The names of all supported Probes. *) - val get_probe_names : context -> string list - - (** Returns a string containing a description of the probe with the given name. *) + val get_probe_names : context -> string array val get_probe_description : context -> string -> string - - (** Creates a new Probe. *) val mk_probe : context -> string -> probe - - (** Create a probe that always evaluates to a float value. *) val const : context -> float -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than the value returned by second argument *) val lt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than the value returned by second argument *) val gt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than or equal the value returned by second argument *) val le : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than or equal the value returned by second argument *) val ge : context -> probe -> probe -> probe - - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is equal the value returned by second argument *) val eq : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) val and_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) val or_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) val not_ : context -> probe -> probe end -(** Tactics - - Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using [Context.get_num_tactics] - and [Context.get_tactic_names]. - It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. -*) module Tactic : sig - type tactic - (** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult : sig - type apply_result - - (** The number of Subgoals. *) val get_num_subgoals : apply_result -> int - - (** Retrieves the subgoals from the apply_result. *) - val get_subgoals : apply_result -> Goal.goal list - - (** Retrieves a subgoal from the apply_result. *) - val get_subgoal : apply_result -> int -> Goal.goal - - (** Convert a model for a subgoal into a model for the original - goal [g], that the ApplyResult was obtained from. - #return A model for [g] *) - val convert_model : apply_result -> int -> Model.model -> Model.model - - (** A string representation of the ApplyResult. *) + val get_subgoals : apply_result -> goal array + val get_subgoal : apply_result -> int -> goal + val convert_model : apply_result -> int -> model -> model val to_string : apply_result -> string end - (** A string containing a description of parameters accepted by the tactic. *) val get_help : tactic -> string - - (** Retrieves parameter descriptions for Tactics. *) - val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs - - (** Apply the tactic to the goal. *) - val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result - - (** The number of supported tactics. *) + val get_param_descrs : tactic -> param_descrs + val apply : tactic -> goal -> params option -> apply_result val get_num_tactics : context -> int - - (** The names of all supported tactics. *) - val get_tactic_names : context -> string list - - (** Returns a string containing a description of the tactic with the given name. *) + val get_tactic_names : context -> string array val get_tactic_description : context -> string -> string - - (** Creates a new Tactic. *) val mk_tactic : context -> string -> tactic - - (** Create a tactic that applies one tactic to a Goal and - then another one to every subgoal produced by the first one. *) - val and_then : context -> tactic -> tactic -> tactic list -> tactic - - (** Create a tactic that first applies one tactic to a Goal and - if it fails then returns the result of another tactic applied to the Goal. *) + val and_then : context -> tactic -> tactic -> tactic array -> tactic val or_else : context -> tactic -> tactic -> tactic - - (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). - - If the tactic does not terminate within the timeout, then it fails. *) val try_for : context -> tactic -> int -> tactic - - (** Create a tactic that applies one tactic to a given goal if the probe - evaluates to true. - - If the probe evaluates to false, then the new tactic behaves like the [skip] tactic. *) - val when_ : context -> Probe.probe -> tactic -> tactic - - (** Create a tactic that applies a tactic to a given goal if the probe - evaluates to true and another tactic otherwise. *) - val cond : context -> Probe.probe -> tactic -> tactic -> tactic - - (** Create a tactic that keeps applying one tactic until the goal is not - modified anymore or the maximum number of iterations is reached. *) + val when_ : context -> probe -> tactic -> tactic + val cond : context -> probe -> tactic -> tactic -> tactic val repeat : context -> tactic -> int -> tactic - - (** Create a tactic that just returns the given goal. *) val skip : context -> tactic - - (** Create a tactic always fails. *) val fail : context -> tactic - - (** Create a tactic that fails if the probe evaluates to false. *) - val fail_if : context -> Probe.probe -> tactic - - (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). *) + val fail_if : context -> probe -> tactic val fail_if_not_decided : context -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. *) - val using_params : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. - Alias for [UsingParams]*) - val with_ : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies the given tactics in parallel. *) - val par_or : context -> tactic list -> tactic - - (** Create a tactic that applies a tactic to a given goal and then another tactic - to every subgoal produced by the first one. The subgoals are processed in parallel. *) + val using_params : context -> tactic -> params -> tactic + val with_ : context -> tactic -> params -> tactic + val par_or : context -> tactic array -> tactic val par_and_then : context -> tactic -> tactic -> tactic - - (** Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. *) val interrupt : context -> unit end -(** Solvers *) module Solver : sig - type solver - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - val string_of_status : status -> string - (** Objects that track statistical information about solvers. *) module Statistics : sig - type statistics - (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - *) module Entry : sig - type statistics_entry - - (** The key of the entry. *) val get_key : statistics_entry -> string - - (** The int-value of the entry. *) val get_int : statistics_entry -> int - - (** The float-value of the entry. *) val get_float : statistics_entry -> float - - (** True if the entry is uint-valued. *) val is_int : statistics_entry -> bool - - (** True if the entry is float-valued. *) val is_float : statistics_entry -> bool - - (** The string representation of the the entry's value. *) val to_string_value : statistics_entry -> string - - (** The string representation of the entry (key and value) *) val to_string : statistics_entry -> string end - (** A string representation of the statistical data. *) val to_string : statistics -> string - - (** The number of statistical data. *) val get_size : statistics -> int - - (** The data entries. *) - val get_entries : statistics -> Entry.statistics_entry list - - (** The statistical counters. *) - val get_keys : statistics -> string list - - (** The value of a particular statistical counter. *) - val get : statistics -> string -> Entry.statistics_entry option + val get_entries : statistics -> statistics_entry array + val get_keys : statistics -> string array + val get : statistics -> string -> statistics_entry option end - (** A string that describes all available solver parameters. *) val get_help : solver -> string - - (** Sets the solver parameters. *) - val set_parameters : solver -> Params.params -> unit - - (** Retrieves parameter descriptions for solver. *) - val get_param_descrs : solver -> Params.ParamDescrs.param_descrs - - (** The current number of backtracking points (scopes). - {!pop} - {!push} *) + val set_parameters : solver -> params -> unit + val get_param_descrs : solver -> param_descrs val get_num_scopes : solver -> int - - (** Creates a backtracking point. - {!pop} *) val push : solver -> unit - - (** Backtracks a number of backtracking points. - Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} - {!push} *) val pop : solver -> int -> unit - - (** Resets the Solver. - This removes all assertions from the solver. *) val reset : solver -> unit - - (** Assert a constraint (or multiple) into the solver. *) - val add : solver -> Expr.expr list -> unit - - (** * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit - - (** * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit - - (** The number of assertions in the solver. *) + val assert_ : solver -> bool_expr array -> unit + val assert_and_track : solver -> bool_expr -> bool_expr -> unit val get_num_assertions : solver -> int - - (** The set of asserted formulas. *) - val get_assertions : solver -> Expr.expr list - - (** Checks whether the assertions in the solver are consistent or not. - - {!Model} - {!get_unsat_core} - {!Proof} *) - val check : solver -> Expr.expr list -> status - - (** The model of the last [Check]. - - The result is [None] if [Check] was not invoked before, - if its results was not [SATISFIABLE], or if model production is not enabled. *) - val get_model : solver -> Model.model option - - (** The proof of the last [Check]. - - The result is [null] if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if proof production is disabled. *) - val get_proof : solver -> Expr.expr option - - (** The unsat core of the last [Check]. - - The unsat core is a subset of [Assertions] - The result is empty if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if core production is disabled. *) - val get_unsat_core : solver -> AST.ast list - - (** A brief justification of why the last call to [Check] returned [UNKNOWN]. *) + val get_assertions : solver -> bool_expr array + val check : solver -> bool_expr array -> status + val get_model : solver -> model option + val get_proof : solver -> expr option + val get_unsat_core : solver -> ast_vector array val get_reason_unknown : solver -> string - - (** Solver statistics. *) - val get_statistics : solver -> Statistics.statistics - - (** Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. *) - val mk_solver : context -> Symbol.symbol option -> solver - - (** Creates a new (incremental) solver. - {!mk_solver} *) + val get_statistics : solver -> statistics + val mk_solver : context -> symbol option -> solver val mk_solver_s : context -> string -> solver - - (** Creates a new (incremental) solver. *) val mk_simple_solver : context -> solver - - (** Creates a solver that is implemented using the given tactic. - - The solver supports the commands [Push] and [Pop], but it - will always solve each check from scratch. *) - val mk_solver_t : context -> Tactic.tactic -> solver - - (** A string representation of the solver. *) + val mk_solver_t : context -> tactic -> solver val to_string : solver -> string end -(** Fixedpoint solving *) module Fixedpoint : sig - type fixedpoint - - (** A string that describes all available fixedpoint solver parameters. *) val get_help : fixedpoint -> string - - (** Sets the fixedpoint solver parameters. *) - val set_params : fixedpoint -> Params.params -> unit - - (** Retrieves parameter descriptions for Fixedpoint solver. *) - val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs - - (** Assert a constraints into the fixedpoint solver. *) - val add : fixedpoint -> Expr.expr list -> unit - - (** Register predicate as recursive relation. *) - val register_relation : fixedpoint -> FuncDecl.func_decl -> unit - - (** Add rule into the fixedpoint solver. *) - val add_rule : fixedpoint -> Expr.expr -> Symbol.symbol option -> unit - - (** Add table fact to the fixedpoint solver. *) - val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit - - (** Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. *) - val query : fixedpoint -> Expr.expr -> Solver.status - - (** Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status - - (** Creates a backtracking point. - {!pop} *) + val set_params : fixedpoint -> params -> unit + val get_param_descrs : fixedpoint -> param_descrs + val assert_ : fixedpoint -> bool_expr array -> unit + val register_relation : fixedpoint -> func_decl -> unit + val add_rule : fixedpoint -> bool_expr -> symbol option -> unit + val add_fact : fixedpoint -> func_decl -> int array -> unit + val query : fixedpoint -> bool_expr -> status + val query_r : fixedpoint -> func_decl array -> status val push : fixedpoint -> unit - - (** Backtrack one backtracking point. - - Note that an exception is thrown if Pop is called without a corresponding [Push] - {!push} *) val pop : fixedpoint -> unit - - (** Update named rule into in the fixedpoint solver. *) - val update_rule : fixedpoint -> Expr.expr -> Symbol.symbol -> unit - - (** Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. *) - val get_answer : fixedpoint -> Expr.expr option - - (** Retrieve explanation why fixedpoint engine returned status Unknown. *) + val update_rule : fixedpoint -> bool_expr -> symbol -> unit + val get_answer : fixedpoint -> expr option val get_reason_unknown : fixedpoint -> string - - (** Retrieve the number of levels explored for a given predicate. *) - val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int - - (** Retrieve the cover of a predicate. *) - val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option - - (** Add property about the predicate. - The property is added at level. *) - val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit - - (** Retrieve internal string representation of fixedpoint object. *) + val get_num_levels : fixedpoint -> func_decl -> int + val get_cover_delta : fixedpoint -> int -> func_decl -> expr option + val add_cover : fixedpoint -> int -> func_decl -> expr -> unit val to_string : fixedpoint -> string - - (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit - - (** Convert benchmark given as set of axioms, rules and queries to a string. *) - val to_string_q : fixedpoint -> Expr.expr list -> string - - (** Retrieve set of rules added to fixedpoint context. *) - val get_rules : fixedpoint -> Expr.expr list - - (** Retrieve set of assertions added to fixedpoint context. *) - val get_assertions : fixedpoint -> Expr.expr list - - (** Create a Fixedpoint context. *) + val set_predicate_representation : fixedpoint -> func_decl -> symbol array -> unit + val to_string_q : fixedpoint -> bool_expr array -> string + val get_rules : fixedpoint -> bool_expr array + val get_assertions : fixedpoint -> bool_expr array val mk_fixedpoint : context -> fixedpoint end -(** Functions for handling SMT and SMT2 expressions and files *) +module Options : +sig + val update_param_value : context -> string -> string -> unit + val get_param_value : context -> string -> string option + val set_print_mode : context -> Z3enums.ast_print_mode -> unit + val toggle_warning_messages : bool -> unit +end + module SMT : sig - (** Convert a benchmark into an SMT-LIB formatted string. - - @return A string representation of the benchmark. *) - val benchmark_to_smtstring : context -> string -> string -> string -> string -> Expr.expr list -> Expr.expr -> string - - (** Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays in the third and fifth argument - don't need to match the names of the sorts and declarations in the arrays in the fourth - and sixth argument. This is a useful feature since we can use arbitrary names to - reference sorts and declarations. *) - val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** Parse the given file using the SMT-LIB parser. - {!parse_smtlib_string} *) - val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** The number of SMTLIB formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) + val benchmark_to_smtstring : context -> string -> string -> string -> string -> bool_expr array -> bool_expr -> string + val parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit + val parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit val get_num_smtlib_formulas : context -> int - - (** The formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) - val get_smtlib_formulas : context -> Expr.expr list - - (** The number of SMTLIB assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) + val get_smtlib_formulas : context -> bool_expr array val get_num_smtlib_assumptions : context -> int - - (** The assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) - val get_smtlib_assumptions : context -> Expr.expr list - - (** The number of SMTLIB declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) + val get_smtlib_assumptions : context -> bool_expr array val get_num_smtlib_decls : context -> int - - (** The declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) - val get_smtlib_decls : context -> FuncDecl.func_decl list - - (** The number of SMTLIB sorts parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) + val get_smtlib_decls : context -> func_decl array val get_num_smtlib_sorts : context -> int - - (** The sort declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) - val get_smtlib_sorts : context -> Sort.sort list - - (** Parse the given string using the SMT-LIB2 parser. - - {!parse_smtlib_string} - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr - - (** Parse the given file using the SMT-LIB2 parser. - {!parse_smtlib2_string} *) - val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr + val get_smtlib_sorts : context -> sort array + val parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> bool_expr + val parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> bool_expr end -(** Interpolation *) -module Interpolation : -sig - - (** Create an AST node marking a formula position for interpolation. - The expression must have Boolean sort. *) - val mk_interpolant : context -> Expr.expr -> Expr.expr - - (** The interpolation context is suitable for generation of interpolants. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val mk_interpolation_context : (string * string) list -> context - - (** Gets an interpolant. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val get_interpolant : context -> Expr.expr -> Expr.expr -> Params.params -> AST.ASTVector.ast_vector - - (** Computes an interpolant. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val compute_interpolant : context -> Expr.expr -> Params.params -> (AST.ASTVector.ast_vector * Model.model) - - (** Retrieves an interpolation profile. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val get_interpolation_profile : context -> string - - (** Read an interpolation problem from file. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val read_interpolation_problem : context -> string -> (Expr.expr list * int list * Expr.expr list) - - (** Check the correctness of an interpolant. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val check_interpolant : context -> int -> Expr.expr list -> int list -> Expr.expr list -> int -> Expr.expr list -> unit - - (** Write an interpolation problem to file suitable for reading with - Z3_read_interpolation_problem. - For more information on interpolation please refer - too the C/C++ API, which is well documented. *) - val write_interpolation_problem : context -> int -> Expr.expr list -> int list -> string -> int -> Expr.expr list -> unit - -end - -(** Set a global (or module) parameter, which is shared by all Z3 contexts. - - When a Z3 module is initialized it will use the value of these parameters - when Z3_params objects are not provided. - The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - The character '.' is a delimiter (more later). - The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - This function can be used to set parameters for a specific Z3 module. - This can be done by using .. - For example: - (set_global_param "pp.decimal" "true") - will set the parameter "decimal" in the module "pp" to true. -*) val set_global_param : string -> string -> unit - -(** Get a global (or module) parameter. - - Returns None if the parameter does not exist. - The caller must invoke #Z3_global_param_del_value to delete the value returned at param_value. - This function cannot be invoked simultaneously from different threads without synchronization. - The result string stored in param_value is stored in a shared location. -*) val get_global_param : string -> string option - -(** Restore the value of all global (and module) parameters. - - This command will not affect already created objects (such as tactics and solvers) - {!set_global_param} -*) - -val global_param_reset_all : unit -> unit - -(** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) -val toggle_warning_messages : bool -> unit - +val global_param_reset_all : unit From fd78e45a2a6f0b040a96705494038186f4b361bd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 20:04:11 +0000 Subject: [PATCH 421/646] ML API: got rid of "extra" objects on types. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 73 +++++++++++++++-------------------------------- src/api/ml/z3.mli | 2 +- 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index ea8c9576e..aa919e7fc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -93,13 +93,7 @@ type quantifier = Quantifier of expr type pattern = Pattern of ast (* Datatype stuff *) -type constructor_extra = { - m_n : int; - mutable m_tester_decl : func_decl option; - mutable m_constructor_decl : func_decl option ; - mutable m_accessor_decls : func_decl array option} - -type constructor = Constructor of (z3_native_object * constructor_extra) +type constructor = z3_native_object type constructor_list = z3_native_object (* Tactical interface *) @@ -2358,7 +2352,8 @@ struct (** Constructors *) module Constructor = struct - + let _counts = Hashtbl.create 0 + let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then @@ -2373,53 +2368,31 @@ struct (let f x = (Symbol.gno x) in (Array.map f field_names)) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) sort_refs) in - let no : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - let ex : constructor_extra = { m_n = n; - m_tester_decl = None; - m_constructor_decl = None; - m_accessor_decls = None} in + let no : constructor = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + Hashtbl.add _counts no n ; (z3obj_sno no ctx ptr) ; (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; - Constructor(no, ex) + no - let init_extra ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_tester_decl with - | None -> - let (a, b, c) = (Z3native.query_constructor (z3obj_gnc no) (z3obj_gno no) ex.m_n) in - ex.m_constructor_decl <- Some (func_decl_of_ptr (z3obj_gc no) a) ; - ex.m_tester_decl <- Some (func_decl_of_ptr (z3obj_gc no) b) ; - ex.m_accessor_decls <- Some (let f e = (func_decl_of_ptr (z3obj_gc no) e) in Array.map f c) ; - () - | _ -> () - - - let get_n ( x : constructor ) = - match x with Constructor(no, ex) -> - ex.m_n + let get_n ( x : constructor ) = (Hashtbl.find _counts x) - let rec tester_decl ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_tester_decl with - | Some(s) -> s - | None -> init_extra x ; tester_decl x - let rec constructor_decl ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_constructor_decl with - | Some(s) -> s - | None -> init_extra x ; constructor_decl x + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + func_decl_of_ptr (z3obj_gc x) a + + let rec tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + func_decl_of_ptr (z3obj_gc x) b let rec accessor_decls ( x : constructor ) = - match x with Constructor(no, ex) -> - match ex.m_accessor_decls with - | Some(s) -> s - | None -> init_extra x ; accessor_decls x + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let f y = func_decl_of_ptr (z3obj_gc x) y in + Array.map f c (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2443,7 +2416,7 @@ struct m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let f x =(z3obj_gno x) in (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in @@ -2462,7 +2435,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) = + let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2483,8 +2456,8 @@ struct (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) = - let f x = match x with Constructor(no,_) -> (z3obj_gno no) in + let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array ) = + let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in create_sort ctx x diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index f82492e8a..5d5d7adf0 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -482,8 +482,8 @@ sig module Constructor : sig val get_n : constructor -> int - val tester_decl : constructor -> func_decl val constructor_decl : constructor -> func_decl + val tester_decl : constructor -> func_decl val accessor_decls : constructor -> func_decl array val get_num_fields : constructor -> int val get_constructor_decl : constructor -> func_decl From 25615aedd9173d7f17b113e50aab9b9ab89fc2c2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 22:49:19 +0000 Subject: [PATCH 422/646] ML API: build system fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index cfea8d0f1..5a5dbc3a4 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1342,40 +1342,49 @@ class MLComponent(Component): def mk_makefile(self, out): if is_ml_enabled(): + CP_CMD = "cp" + if IS_WINDOWS: + CP_CMD = "copy" src_dir = self.to_src_dir sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): - shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) + out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) + out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): - shutil.copyfile(os.path.join(self.src_dir, f), os.path.join(BUILD_DIR, sub_dir, f)) - cmis = '%s/z3enums.cmi %s/z3native.cmi %s/z3.cmi' % (src_dir,src_dir,src_dir) - out.write('%s/z3enums.cmi: %s/z3enums.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3enums.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('%s/z3native.cmi: %s/z3native.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3native.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('%s/z3.cmi: %s/z3.mli\n' % (src_dir,src_dir)) - out.write('\t%s -I %s -c %s/z3.mli\n' % (OCAMLC,src_dir,src_dir)) - out.write('api/ml/libz3ml$(LIB_EXT): %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, src_dir)) + out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) + out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + modules = ["z3enums", "z3native", "z3"] # dependencies in this order! + prev = '' + for m in modules: + out.write('%s/%s.mli: %s/%s.ml %s\n' % (sub_dir,m,sub_dir,m,prev)) + out.write('\t%s -I %s -i -c %s/%s.ml > %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m,sub_dir,m)) + prev = prev + ' ' + sub_dir + '/' + m + '.mli' + cmis = '' + for m in modules: + out.write('%s/%s.cmi: %s/%s.mli\n' % (sub_dir,m,sub_dir,m)) + out.write('\t%s -I %s -c %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m)) + cmis = cmis + ' ' + sub_dir + '/' + m + '.cmi' + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(src_dir, mlfile)) + out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(self.to_src_dir, mlfile)) + out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-ccopt "-I../../%s" -cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (api_src,src_dir,src_dir,src_dir,src_dir)) + out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') From 9142901efe0322e9d30c20c3da819924727ece18 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Feb 2013 23:42:50 +0000 Subject: [PATCH 423/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 54 +++++++++++++++++++++-------------- src/api/ml/z3.ml | 60 ++++++++++++++++++++++----------------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 3b13a2462..49db6fb50 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -7,6 +7,7 @@ open Z3 open Z3.Symbol open Z3.Sort open Z3.Expr +open Z3.Boolean open Z3.FuncDecl open Z3.Goal open Z3.Tactic @@ -22,12 +23,20 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = ((mk_const ctx (Symbol.mk_string ctx "x") (mk_real_sort ctx )) :> arith_expr) in - let yr = ((mk_const ctx (Symbol.mk_string ctx "y") (mk_real_sort ctx )) :> arith_expr) in + let xr = (arith_expr_of_expr + (Expr.mk_const ctx (Symbol.mk_string ctx "x") + (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in + let yr = (arith_expr_of_expr + (Expr.mk_const ctx (Symbol.mk_string ctx "y") + (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [| (mk_gt ctx xr (mk_real_numeral_nd ctx 10 1)) |]) ; - (Goal.assert_ g4 [| (mk_eq ctx yr (mk_add ctx [| xr; (mk_real_numeral_nd ctx 1 1) |] )) |] ) ; - (Goal.assert_ g4 [| (mk_gt ctx yr (mk_real_numeral_nd ctx 1 1)) |]) ; + (Goal.assert_ g4 [| (mk_gt ctx xr + (arith_expr_of_real_expr (real_expr_of_rat_num + (Real.mk_numeral_nd ctx 10 1)))) |]) ; + (Goal.assert_ g4 [| (mk_eq ctx + (expr_of_arith_expr yr) + (expr_of_arith_expr (mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |] ))) |] ) ; + (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -67,15 +76,15 @@ let model_converter_test ( ctx : context ) = *) let basic_tests ( ctx : context ) = Printf.printf "BasicTests\n" ; - let qi = (mk_int ctx 1) in +(* let qi = (mk_int ctx 1) in *) let fname = (mk_string ctx "f") in let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in - let bs = (Sort.mk_bool ctx) in + let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in let domain = [| bs; bs |] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f - [| (mk_const ctx x bs); (mk_const ctx y bs) |]) in + [| (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) |]) in let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in let domain2 = [| bs |] in let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in @@ -110,8 +119,11 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [| (mk_eq ctx (mk_numeral_int ctx 1 (BitVectors.mk_sort ctx 32)) - (mk_numeral_int ctx 2 (BitVectors.mk_sort ctx 32))) |] ) + (Goal.assert_ g [| (mk_eq ctx + (mk_numeral_int ctx 1 + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) + (mk_numeral_int ctx 2 + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) |] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -132,7 +144,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [| (mk_false ctx) |]) ; + (Goal.assert_ g2 [| (Boolean.mk_false ctx) |]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -142,10 +154,10 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (mk_const ctx (Symbol.mk_string ctx "x") (mk_int_sort ctx)) in - let yc = (mk_const ctx (Symbol.mk_string ctx "y") (mk_int_sort ctx)) in - (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (mk_int_sort ctx))) |]) ; - (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (mk_int_sort ctx))) |]) ; + let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in + let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in + (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; + (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; let constr = (mk_eq ctx xc yc) in (Goal.assert_ g3 [| constr |] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in @@ -208,14 +220,14 @@ let _ = let ctx = (mk_context cfg) in let is = (Symbol.mk_int ctx 42) in let ss = (Symbol.mk_string ctx "mySymbol") in - let bs = (Sort.mk_bool ctx) in - let ints = (mk_int_sort ctx) in - let rs = (mk_real_sort ctx) in + let bs = (Boolean.mk_sort ctx) in + let ints = (Integer.mk_sort ctx) in + let rs = (Real.mk_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string is); Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string bs); - Printf.printf "int sort: %s\n" (Sort.to_string ints); - Printf.printf "real sort: %s\n" (Sort.to_string rs); + Printf.printf "bool sort: %s\n" (Sort.to_string (sort_of_bool_sort bs)); + Printf.printf "int sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_int_sort ints))); + Printf.printf "real sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_real_sort rs))); basic_tests ctx ; Printf.printf "Disposing...\n"; Gc.full_major () diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index aa919e7fc..651102bc8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -240,7 +240,7 @@ struct Expr(z3_native_object_of_ast_ptr ctx no) else let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in if (Z3native.is_algebraic_number (context_gno ctx) no) then Expr(z3_native_object_of_ast_ptr ctx no) else @@ -376,92 +376,99 @@ let expr_of_ast a = Expr(a) let bool_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.BOOL_SORT) then raise (Z3native.Exception "Invalid coercion") else BoolExpr(e) let arith_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then raise (Z3native.Exception "Invalid coercion") else ArithExpr(e) let bitvec_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.BV_SORT) then raise (Z3native.Exception "Invalid coercion") else BitVecExpr(e) let array_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.ARRAY_SORT) then raise (Z3native.Exception "Invalid coercion") else ArrayExpr(e) let datatype_expr_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.DATATYPE_SORT) then raise (Z3native.Exception "Invalid coercion") else DatatypeExpr(e) let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.INT_SORT) then raise (Z3native.Exception "Invalid coercion") else IntExpr(e) let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in if (q != Z3enums.REAL_SORT) then raise (Z3native.Exception "Invalid coercion") else RealExpr(e) let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(no))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else IntNum(e) let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(no))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else RatNum(e) let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(no)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc no) (z3obj_gno no))) then + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else AlgebraicNum(e) let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(no)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc no) (z3obj_gno no))) then + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then raise (Z3native.Exception "Invalid coercion") else BitVecNum(e) let quantifier_of_expr e = - match e with Expr(no) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc no) (z3obj_gno no))) in + match e with Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in if (q != Z3enums.QUANTIFIER_AST) then raise (Z3native.Exception "Invalid coercion") else @@ -4378,7 +4385,8 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i)) in + let f i = (bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f (** The number of formulas, subformulas and terms in the goal. *) From dcdcd7b14050991be33513212e8b95dc21fc5032 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 11:49:00 +0000 Subject: [PATCH 424/646] ML API: Build system and error handling fixes. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 8 ++++++-- scripts/update_api.py | 12 ++++++++++++ src/api/ml/z3.ml | 6 +----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5a5dbc3a4..4082bb2b8 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1351,10 +1351,14 @@ class MLComponent(Component): api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) + if IS_WINDOWS: str = str.replace('/','\\') + out.write(str) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - out.write('\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f)) + str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) + if IS_WINDOWS: str = str.replace('/','\\') + out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: diff --git a/scripts/update_api.py b/scripts/update_api.py index 6e9c14355..e5c66dd39 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1169,9 +1169,11 @@ def mk_ml(): ml_i.write('\n') ml_native.write('external is_null : ptr -> bool\n = "n_is_null"\n\n') ml_native.write('external mk_null : unit -> ptr\n = "n_mk_null"\n\n') + ml_native.write('external set_internal_error_handler : ptr -> unit\n = "n_set_internal_error_handler"\n\n') ml_native.write('exception Exception of string\n\n') ml_i.write('val is_null : ptr -> bool\n') ml_i.write('val mk_null : unit -> ptr\n') + ml_i.write('val set_internal_error_handler : ptr -> unit\n\n') ml_i.write('exception Exception of string\n\n') # ML declarations @@ -1329,6 +1331,16 @@ def mk_ml(): ml_wrapper.write(' memcpy( Data_custom_val(result), &z3_result, sizeof(void*));\n') ml_wrapper.write(' CAMLreturn (result);\n') ml_wrapper.write('}\n\n') + ml_wrapper.write('void MLErrorHandler(Z3_context c, Z3_error_code e)\n') + ml_wrapper.write('{\n') + ml_wrapper.write(' // Internal do-nothing error handler. This is required to avoid that Z3 calls exit()\n') + ml_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') + ml_wrapper.write(' // wrappers below.\n') + ml_wrapper.write('}\n\n') + ml_wrapper.write('void n_set_internal_error_handler(Z3_context c)\n') + ml_wrapper.write('{\n') + ml_wrapper.write(' Z3_set_error_handler(c, MLErrorHandler);\n') + ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) op = outparams(params) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 651102bc8..45faae468 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -135,16 +135,12 @@ struct let v = Z3native.mk_context_rc cfg in Z3native.del_config(cfg) ; Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; (* Printf.printf "Installing finalizer on context \n" ; *) let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in let f = fun o -> dispose_context o in Gc.finalise f res; res - (* CMW: Install error handler here! - m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected. - Z3native.set_error_handler(m_ctx, m_n_err_handler); - GC.SuppressFinalize(this); - *) let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) From 6842acbea85d6417dc4f1deb0752a551c9e5f580 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 18:37:52 +0000 Subject: [PATCH 425/646] ML API: Cleanup Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 5 +- scripts/update_api.py | 2 + src/api/ml/z3.ml | 2247 +++++++++++++++++++------------------ src/api/ml/z3.mli | 1462 +++++++++++++++--------- 4 files changed, 2064 insertions(+), 1652 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 49db6fb50..6dfe11623 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -15,6 +15,9 @@ open Z3.Tactic.ApplyResult open Z3.Probe open Z3.Solver open Z3.Arithmetic +open Z3.Arithmetic.Integer +open Z3.Arithmetic.Real +open Z3.BitVector exception TestFailedException of string @@ -35,7 +38,7 @@ let model_converter_test ( ctx : context ) = (Real.mk_numeral_nd ctx 10 1)))) |]) ; (Goal.assert_ g4 [| (mk_eq ctx (expr_of_arith_expr yr) - (expr_of_arith_expr (mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |] ))) |] ) ; + (expr_of_arith_expr (Arithmetic.mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |]) ) ) |] ) ; (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in diff --git a/scripts/update_api.py b/scripts/update_api.py index e5c66dd39..a0b7e6250 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1155,6 +1155,7 @@ def mk_ml(): ml_native.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') ml_i.write('(* Automatically generated file *)\n\n') ml_i.write('(** The native (raw) interface to the dynamic Z3 library. *)\n\n') + ml_i.write('(**/**)\n\n'); ml_native.write('open Z3enums\n\n') ml_native.write('(**/**)\n') ml_native.write('type ptr\n') @@ -1214,6 +1215,7 @@ def mk_ml(): ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) ml_native.write('\n') ml_native.write(' end\n\n') + ml_i.write('\n(**/**)\n'); # Exception wrappers for name, result, params in _dotnet_decls: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 45faae468..c261fce05 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -16,104 +16,11 @@ let is_null o = (Z3native.is_null o) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context - - type z3_native_object = { m_ctx : context ; mutable m_n_obj : Z3native.ptr ; inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - - -(* Symbol types *) -type int_symbol = z3_native_object -type string_symbol = z3_native_object - -type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - -(* AST types *) -type ast = z3_native_object -type ast_vector = z3_native_object -type ast_map = z3_native_object - -(* FuncDecl types *) -type func_decl = FuncDecl of ast - -(* Sort types *) -type sort = Sort of ast -type uninterpreted_sort = UninterpretedSort of sort -type bool_sort = BoolSort of sort -type array_sort = ArraySort of sort -type set_sort = SetSort of sort -type datatype_sort = DatatypeSort of sort -type relation_sort = RelationSort of sort -type finite_domain_sort = FiniteDomainSort of sort -type enum_sort = EnumSort of sort -type list_sort = ListSort of sort -type tuple_sort = TupleSort of sort -type arith_sort = ArithSort of sort -type bitvec_sort = BitVecSort of sort - -type int_sort = IntSort of arith_sort -type real_sort = RealSort of arith_sort - -(* FuncDecl parameters *) -type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of symbol - | P_Srt of sort - | P_Ast of ast - | P_Fdl of func_decl - | P_Rat of string -type params = z3_native_object -type param_descrs = z3_native_object - -(* Expr types *) -type expr = Expr of ast - -type bool_expr = BoolExpr of expr -type arith_expr = ArithExpr of expr -type int_expr = IntExpr of arith_expr -type real_expr = RealExpr of arith_expr -type bitvec_expr = BitVecExpr of expr -type array_expr = ArrayExpr of expr -type datatype_expr = DatatypeExpr of expr - -(* Numerals *) -type int_num = IntNum of int_expr -type rat_num = RatNum of real_expr -type algebraic_num = AlgebraicNum of arith_expr -type bitvec_num = BitVecNum of bitvec_expr - -(* Quantifier stuff *) -type quantifier = Quantifier of expr -type pattern = Pattern of ast - -(* Datatype stuff *) -type constructor = z3_native_object -type constructor_list = z3_native_object - -(* Tactical interface *) -type goal = z3_native_object -type model = z3_native_object -type func_interp = z3_native_object -type func_entry = z3_native_object -type probe = z3_native_object -type tactic = z3_native_object -type apply_result = z3_native_object -type solver = z3_native_object -type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE -type statistics = z3_native_object -type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } -type fixedpoint = z3_native_object (** Internal stuff *) @@ -121,11 +28,9 @@ module Internal = struct let dispose_context ctx = if ctx.m_n_obj_cnt == 0 then ( - (* Printf.printf "Disposing context \n" ; *) (Z3native.del_context ctx.m_n_ctx) ) else ( - Printf.printf "NOT DISPOSING context because it still has %d objects alive\n" ctx.m_n_obj_cnt; - (* re-queue for finalization? *) + Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; ) let create_context settings = @@ -136,7 +41,6 @@ struct Z3native.del_config(cfg) ; Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; Z3native.set_internal_error_handler v ; - (* Printf.printf "Installing finalizer on context \n" ; *) let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in let f = fun o -> dispose_context o in Gc.finalise f res; @@ -178,16 +82,6 @@ struct let array_to_native a = let f e = (z3obj_gno e) in Array.map f a - - (* Internal coercions *) - let context_of_ast ( x : ast ) = (z3obj_gc x) - let nc_of_ast ( x : ast ) = (z3obj_gnc x) - let ptr_of_ast ( x : ast ) = (z3obj_gno x) - - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> let res : z3_native_object = { m_ctx = ctx ; @@ -196,323 +90,25 @@ struct dec_ref = Z3native.dec_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; - res - - let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> - let q = (z3_native_object_of_ast_ptr ctx no) in - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then - raise (Z3native.Exception "Invalid coercion") - else - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - - let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - FuncDecl(z3_native_object_of_ast_ptr ctx no) - - let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST - | SORT_AST - | QUANTIFIER_AST - | APP_AST - | NUMERAL_AST - | VAR_AST -> z3_native_object_of_ast_ptr ctx no - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") - - and expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then - Expr(z3_native_object_of_ast_ptr ctx no) - else - let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) no) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - raise (Z3native.Exception "Unsupported numeral object") - else - Expr(z3_native_object_of_ast_ptr ctx no) - - let expr_aton ( a : expr array ) = - let f ( e : expr ) = match e with Expr(a) -> (ptr_of_ast a) in - Array.map f a - - let expr_of_func_app : context -> func_decl -> expr array -> expr = fun ctx f args -> - match f with FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (ptr_of_ast fa) (Array.length args) (expr_aton args) in - expr_of_ptr ctx o + res end - open Internal - - -(* Sort coercions *) -let ast_of_sort s = match s with Sort(x) -> x -let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x -let sort_of_bool_sort s = match s with BoolSort(x) -> x -let sort_of_array_sort s = match s with ArraySort(x) -> x -let sort_of_set_sort s = match s with SetSort(x) -> x -let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x -let sort_of_relation_sort s = match s with RelationSort(x) -> x -let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x -let sort_of_enum_sort s = match s with EnumSort(x) -> x -let sort_of_list_sort s = match s with ListSort(x) -> x -let sort_of_tuple_sort s = match s with TupleSort(x) -> x -let sort_of_arith_sort s = match s with ArithSort(x) -> x -let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x -let arith_sort_of_int_sort s = match s with IntSort(x) -> x -let arith_sort_of_real_sort s = match s with RealSort(x) -> x - -let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - -let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - -let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - -let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - -let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - -let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - -let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - -let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - -let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - -let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - -(* FuncDecl coercions *) -let ast_of_func_decl f = match f with FuncDecl(x) -> x - -(* Expr coercions *) -let ast_of_expr e = match e with Expr(a) -> a -let expr_of_bool_expr e = match e with BoolExpr(x) -> x -let expr_of_arith_expr e = match e with ArithExpr(x) -> x -let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x -let expr_of_array_expr e = match e with ArrayExpr(x) -> x -let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - -let arith_expr_of_int_expr e = match e with IntExpr(x) -> x -let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - -let int_expr_of_int_num e = match e with IntNum(x) -> x -let real_expr_of_rat_num e = match e with RatNum(x) -> x -let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x -let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - -let expr_of_quantifier e = match e with Quantifier(x) -> x -let ast_of_pattern e = match e with Pattern(x) -> x - - -let expr_of_ast a = - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Expr(a) - -let bool_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - -let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - -let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - -let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - -let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - -let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - -let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - -let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - -let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - -let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - -let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - -let quantifier_of_expr e = - match e with Expr(a) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.QUANTIFIER_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Quantifier(e) - -let pattern_of_ast a = - (* CMW: Unchecked ok? *) - Pattern(a) - - - -(** Interaction logging for Z3 - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) module Log = struct - (** Open an interaction log file. - @param filename the name of the file to open. - @return True if opening the log file succeeds, false otherwise. - *) - (* CMW: "open" seems to be a reserved keyword? *) let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - - (** Closes the interaction log. *) let close = Z3native.close_log - - (** Appends a user-provided string to the interaction log. - @param s the string to append*) let append s = Z3native.append_log s end -(** Version information *) module Version = struct - (** The major version. *) let major = let (x, _, _, _) = Z3native.get_version in x - - (** The minor version. *) let minor = let (_, x, _, _) = Z3native.get_version in x - - (** The build version. *) let build = let (_, _, x, _) = Z3native.get_version in x - - (** The revision. *) let revision = let (_, _, _, x) = Z3native.get_version in x - - (** A string representation of the version information. *) let to_string = let (mj, mn, bld, rev) = Z3native.get_version in string_of_int mj ^ "." ^ @@ -532,35 +128,21 @@ let mk_list ( f : int -> 'a ) ( n : int ) = mk_list' f 0 n [] -(** Create a context object. - - Most interactions with Z3 are interpreted in some context; many users will only - require one such object, but power users may require more than one. To start using - Z3, do - - - let ctx = (mk_context []) in - (...) - - - where a list of pairs of strings may be passed to set options on - the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (mk_context cfg) in - (...) - -*) let mk_context ( cfg : ( string * string ) list ) = create_context cfg - - -(** Symbols are used to name several term and type constructors *) module Symbol = -struct +struct + (* Symbol types *) + type int_symbol = z3_native_object + type string_symbol = z3_native_object + + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + + let create_i ( ctx : context ) ( no : Z3native.ptr ) = let res : int_symbol = { m_ctx = ctx ; m_n_obj = null ; @@ -588,7 +170,7 @@ struct match x with | S_Int(n) -> (z3obj_gc n) | S_Str(n) -> (z3obj_gc n) - + let gnc ( x : symbol ) = match x with | S_Int(n) -> (z3obj_gnc n) @@ -599,59 +181,55 @@ struct | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) - (** The kind of the symbol (int or string) *) - let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) - - (** Indicates whether the symbol is of Int kind *) + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL - - (** Indicates whether the symbol is of string kind. *) let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - - (** The int value of the symbol. *) let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - - (** The string value of the symbol. *) let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) - - (** A string representation of the symbol. *) let to_string ( o : symbol ) = match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) - (** - Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) let mk_int ( ctx : context ) ( i : int ) = S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) - (** Creates a new symbol using a string. *) let mk_string ( ctx : context ) ( s : string ) = S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - (** Create an array of symbols. *) let mk_ints ( ctx : context ) ( names : int array ) = let f elem = mk_int ( ctx : context ) elem in (Array.map f names) - (** Create an array of symbols. *) let mk_strings ( ctx : context ) ( names : string array ) = let f elem = mk_string ( ctx : context ) elem in (Array.map f names) end -(** The abstract syntax tree (AST) module *) module AST = -struct - (** Vectors of ASTs *) +struct + type ast = z3_native_object + + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + module ASTVector = struct - let create ( ctx : context ) ( no : Z3native.ptr ) = + type ast_vector = z3_native_object + + let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; @@ -659,55 +237,34 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** The size of the vector *) + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) - (** - Retrieves the i-th object in the vector. - @param i Index - @return An AST - *) let get ( x : ast_vector ) ( i : int ) = - create (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) - (** Sets the i-th object in the vector. *) let set ( x : ast_vector ) ( i : int ) ( value : ast ) = Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) - (** Resize the vector to . - @param newSize The new size of the vector. *) let resize ( x : ast_vector ) ( new_size : int ) = Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size - (** - Add the AST to the back of the vector. The size - is increased by 1. - @param a An AST - *) let push ( x : ast_vector ) ( a : ast ) = Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) - (** - Translates all ASTs in the vector to . - @param to_ctx A context - @return A new ASTVector - *) let translate ( x : ast_vector ) ( to_ctx : context ) = - create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** Retrieves a string representation of the vector. *) let to_string ( x : ast_vector ) = Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) end - (** Map from AST to AST *) module ASTMap = struct + type ast_map = z3_native_object - let create ( ctx : context ) ( no : Z3native.ptr ) = + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_map_inc_ref ; @@ -715,73 +272,36 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** Checks whether the map contains the key . - @param k An AST - @return True if is a key in the map, false otherwise. *) + let contains ( x : ast_map ) ( key : ast ) = Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - (** Finds the value associated with the key . - - This function signs an error when is not a key in the map. - @param k An AST - *) let find ( x : ast_map ) ( key : ast ) = - create (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) + ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - (** - Stores or replaces a new key/value pair in the map. - @param k The key AST - @param v The value AST - *) let insert ( x : ast_map ) ( key : ast ) ( value : ast) = Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) - (** - Erases the key from the map. - @param k An AST - *) let erase ( x : ast_map ) ( key : ast ) = Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - (** Removes all keys from the map. *) let reset ( x : ast_map ) = Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) - (** The size of the map *) let get_size ( x : ast_map ) = Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) - (** The keys stored in the map. *) let get_keys ( x : ast_map ) = - ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) - (** Retrieves a string representation of the map.*) let to_string ( x : ast_map ) = Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end - (** - The AST's hash code. - @return A hash code - *) let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) - - (** - A unique identifier for the AST (unique among all ASTs). - *) let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) - - (** - The kind of the AST. - *) let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) - (** - Indicates whether the AST is an Expr - *) let is_expr ( x : ast ) = match get_ast_kind ( x : ast ) with | APP_AST @@ -790,117 +310,77 @@ struct | VAR_AST -> true | _ -> false - (** - Indicates whether the AST is a bound variable - *) let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST - - (** - Indicates whether the AST is a Quantifier - *) let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST - - - (** - Indicates whether the AST is a Sort - *) let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST - - (** - Indicates whether the AST is a FunctionDeclaration - *) let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST - (** - A string representation of the AST. - *) let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - - (** - A string representation of the AST in s-expression notation. - *) let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - (** - Comparison operator. - @param a An AST - @param b An AST - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || if (z3obj_gnc a) != (z3obj_gnc b) then false else Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) - (** - Object Comparison. - @param other Another ast - @return Negative if the object should be sorted before , positive if after else zero. - *) let compare a b = if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - (** Operator < *) let ( < ) (a : ast) (b : ast) = (compare a b) - (** - Translates (copies) the AST to the Context . - @param ctx A context - @return A copy of the AST which is associated with - *) let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then x else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** - Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) - and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - *) - let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = - ast_of_ptr ctx ptr - - (** - Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - *) + let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr let unwrap_ast ( x : ast ) = (z3obj_gno x) end -(** The Sort module implements type information for ASTs *) +open AST + + module Sort = struct - + type sort = Sort of AST.ast + type uninterpreted_sort = UninterpretedSort of sort + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let ast_of_sort s = match s with Sort(x) -> x + let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x + + let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - - (** - Comparison operator. - @param a A sort - @param b A sort - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + let ( = ) : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then @@ -908,30 +388,13 @@ struct else (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) - (** - Returns a unique identifier for the sort. - *) + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) - - (** - The kind of the sort. - *) let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) - - (** - The name of the sort - *) let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) - - (** - A string representation of the sort. - *) let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) - - (** - Create a new uninterpreted sort. - *) - let mk_uninterpreted ( ctx : context ) ( s : symbol ) = + + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; @@ -940,24 +403,76 @@ struct (z3obj_create res) ; UninterpretedSort(Sort(res)) - (** - Create a new uninterpreted sort. - *) let mk_uninterpreted_s ( ctx : context ) ( s : string ) = mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) end +open Sort -(** Function declarations *) -module FuncDecl = -struct - (**/**) - let create_ndr ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = + +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + val func_decl_of_ptr : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context + val gnc : func_decl -> Z3native.ptr + val gno : func_decl -> Z3native.ptr + module Parameter : + sig + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + val get_kind : parameter -> Z3enums.parameter_kind + val get_int : parameter -> int + val get_float : parameter -> float + val get_symbol : parameter -> Symbol.symbol + val get_sort : parameter -> Sort.sort + val get_ast : parameter -> AST.ast + val get_func_decl : parameter -> func_decl + val get_rational : parameter -> string + end + val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + val ( = ) : func_decl -> func_decl -> bool + val to_string : func_decl -> string + val get_id : func_decl -> int + val get_arity : func_decl -> int + val get_domain_size : func_decl -> int + val get_domain : func_decl -> Sort.sort array + val get_range : func_decl -> Sort.sort + val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_name : func_decl -> Symbol.symbol + val get_num_parameters : func_decl -> int + val get_parameters : func_decl -> Parameter.parameter list + val apply : func_decl -> Expr.expr array -> Expr.expr +end = struct + type func_decl = FuncDecl of AST.ast + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let ast_of_func_decl f = match f with FuncDecl(x) -> x + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (ptr_of_ast (ast_of_sort x)) in + let f x = (AST.ptr_of_ast (ast_of_sort x)) in (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) @@ -967,20 +482,26 @@ struct m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (ptr_of_ast (ast_of_sort x)) in + let f x = (AST.ptr_of_ast (ast_of_sort x)) in (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) - let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - (**/**) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - (** Parameters of Func_Decls *) module Parameter = - struct - (** The kind of the parameter. *) + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + let get_kind ( x : parameter ) = (match x with | P_Int(_) -> PARAMETER_INT @@ -991,188 +512,137 @@ struct | P_Fdl(_) -> PARAMETER_FUNC_DECL | P_Rat(_) -> PARAMETER_RATIONAL) - (**The int value of the parameter.*) let get_int ( x : parameter ) = match x with | P_Int(x) -> x | _ -> raise (Z3native.Exception "parameter is not an int") - - (**The double value of the parameter.*) + let get_float ( x : parameter ) = match x with | P_Dbl(x) -> x | _ -> raise (Z3native.Exception "parameter is not a double") - - (**The Symbol value of the parameter.*) + let get_symbol ( x : parameter ) = match x with | P_Sym(x) -> x | _ -> raise (Z3native.Exception "parameter is not a symbol") - (**The Sort value of the parameter.*) let get_sort ( x : parameter ) = match x with | P_Srt(x) -> x | _ -> raise (Z3native.Exception "parameter is not a sort") - (**The AST value of the parameter.*) let get_ast ( x : parameter ) = match x with | P_Ast(x) -> x | _ -> raise (Z3native.Exception "parameter is not an ast") - (**The FunctionDeclaration value of the parameter.*) let get_func_decl ( x : parameter ) = match x with | P_Fdl(x) -> x | _ -> raise (Z3native.Exception "parameter is not a func_decl") - (**The rational string value of the parameter.*) - let get_func_decl ( x : parameter ) = + let get_rational ( x : parameter ) = match x with | P_Rat(x) -> x | _ -> raise (Z3native.Exception "parameter is not a rational string") end - (** - Creates a new function declaration. - *) - let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = create_ndr ctx name domain range - (** - Creates a new function declaration. - *) let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range - (** - Creates a fresh function declaration with a name prefixed with . - - - *) let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = create_pdr ctx prefix domain range - (** - Creates a new constant function declaration. - *) - let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort ) = + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = create_ndr ctx name [||] range - (** - Creates a new constant function declaration. - *) let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = create_ndr ctx (Symbol.mk_string ctx name) [||] range - (** - Creates a fresh constant function declaration with a name prefixed with . - - - *) let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = create_pdr ctx prefix [||] range - (** - Comparison operator. - @param a A func_decl - @param b A func_decl - @return True if and are from the same context - and represent the same func_decl; false otherwise. - *) let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || if (gnc a) != (gnc b) then false else (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) - (** - A string representations of the function declaration. - *) let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) - (** - Returns a unique identifier for the function declaration. - *) let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) - (** - The arity of the function declaration - *) let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) - (** - The size of the domain of the function declaration - - *) let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) - (** - The domain of the function declaration - *) let get_domain ( x : func_decl ) = let n = (get_domain_size x) in let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in Array.init n f - (** - The range of the function declaration - *) let get_range ( x : func_decl ) = sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) - (** - The kind of the function declaration. - *) let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) - (** - The name of the function declaration - *) let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) - (** - The number of parameters of the function declaration - *) let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) - (** - The parameters of the function declaration - *) let get_parameters ( x : func_decl ) = let n = (get_num_parameters x) in let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> P_Ast (ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) ) in mk_list f n - (** - Create expression that applies function to arguments. - @param args The arguments - *) - let apply ( x : func_decl ) ( args : expr array ) = expr_of_func_app (gc x) x args + let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.expr_of_func_app (gc x) x args end -(** - Parameter sets (of Solvers, Tactics, ...) - A Params objects represents a configuration in the form of symbol/value pairs. -*) -module Params = -struct - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) +and Params : +sig + type params = z3_native_object + module ParamDescrs : + sig + type param_descrs + val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + val get_names : param_descrs -> Symbol.symbol array + val get_size : param_descrs -> int + val to_string : param_descrs -> string + end + val add_bool : params -> Symbol.symbol -> bool -> unit + val add_int : params -> Symbol.symbol -> int -> unit + val add_double : params -> Symbol.symbol -> float -> unit + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + val add_s_bool : params -> string -> bool -> unit + val add_s_int : params -> string -> int -> unit + val add_s_double : params -> string -> float -> unit + val add_s_symbol : params -> string -> Symbol.symbol -> unit + val mk_params : context -> params + val to_string : params -> string +end = struct + type params = z3_native_object + module ParamDescrs = - struct - - let create ( ctx : context ) ( no : Z3native.ptr ) = + struct + type param_descrs = z3_native_object + + let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : param_descrs = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.param_descrs_inc_ref ; @@ -1180,79 +650,46 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - - - (** Validate a set of parameters. *) + let validate ( x : param_descrs ) ( p : params ) = Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) - (** Retrieve kind of parameter. *) - let get_kind ( x : param_descrs ) ( name : symbol ) = + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) - (** Retrieve all names of parameters. *) let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** The size of the ParamDescrs. *) - let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) - - (** Retrieves a string representation of the ParamDescrs. *) + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) end - (** - Adds a parameter setting. - *) - let add_bool ( x : params ) ( name : symbol ) ( value : bool ) = + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_int ( x : params ) (name : symbol ) ( value : int ) = + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_double ( x : params ) ( name : symbol ) ( value : float ) = + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - (** - Adds a parameter setting. - *) - let add_symbol ( x : params ) ( name : symbol ) ( value : symbol ) = + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - (** - Adds a parameter setting. - *) let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = add_bool x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) let add_s_int ( x : params) ( name : string ) ( value : int ) = add_int x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) let add_s_double ( x : params ) ( name : string ) ( value : float ) = add_double x (Symbol.mk_string (z3obj_gc x) name) value - (** - Adds a parameter setting. - *) - let add_s_symbol ( x : params ) ( name : string ) ( value : symbol ) = + + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - (** - Creates a new parameter set - *) let mk_params ( ctx : context ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; @@ -1262,21 +699,107 @@ struct (z3obj_create res) ; res - (** - A string representation of the parameter set. - *) let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) end (** General expressions (terms) *) -module Expr = -struct +and Expr : +sig + type expr = Expr of AST.ast + val expr_of_ptr : context -> Z3native.ptr -> expr + val c_of_expr : expr -> context + val nc_of_expr : expr -> Z3native.ptr + val ptr_of_expr : expr -> Z3native.ptr + val expr_aton : expr array -> Z3native.ptr array + val ast_of_expr : expr -> AST.ast + val expr_of_ast : AST.ast -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr + val simplify : expr -> Params.params option -> expr + val get_simplify_help : context -> string + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + val get_func_decl : expr -> FuncDecl.func_decl + val get_bool_value : expr -> Z3enums.lbool + val get_num_args : expr -> int + val get_args : expr -> expr array + val update : expr -> expr array -> expr + val substitute : expr -> expr array -> expr array -> expr + val substitute_one : expr -> expr -> expr -> expr + val substitute_vars : expr -> expr array -> expr + val translate : expr -> context -> expr + val to_string : expr -> string + val is_numeral : expr -> bool + val is_well_sorted : expr -> bool + val get_sort : expr -> Sort.sort + val is_bool : expr -> bool + val is_const : expr -> bool + val is_true : expr -> bool + val is_false : expr -> bool + val is_eq : expr -> bool + val is_distinct : expr -> bool + val is_ite : expr -> bool + val is_and : expr -> bool + val is_or : expr -> bool + val is_iff : expr -> bool + val is_xor : expr -> bool + val is_not : expr -> bool + val is_implies : expr -> bool + val is_label : expr -> bool + val is_oeq : expr -> bool + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val mk_const_s : context -> string -> Sort.sort -> expr + val mk_const_f : context -> FuncDecl.func_decl -> expr + val mk_fresh_const : context -> string -> Sort.sort -> expr + val mk_app : context -> FuncDecl.func_decl -> expr array -> expr + val mk_numeral_string : context -> string -> Sort.sort -> expr + val mk_numeral_int : context -> int -> Sort.sort -> expr +end = struct + type expr = Expr of AST.ast + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + + let ast_of_expr e = match e with Expr(a) -> a + + let expr_aton ( a : expr array ) = + let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in + Array.map f a + + let expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr = fun ctx f args -> + match f with FuncDecl.FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in + expr_of_ptr ctx o + (** Returns a simplified version of the expression. @param p A set of parameters to configure the simplifier *) - let simplify ( x : expr ) ( p : params option ) = match p with + let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) @@ -1290,12 +813,12 @@ struct Retrieves parameter descriptions for simplifier. *) let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.create ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) (** The function declaration of the function that is applied in this expression. *) - let get_func_decl ( x : expr ) = func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) (** Indicates whether the expression is the true or false expression @@ -1477,7 +1000,7 @@ struct (** Creates a new Constant of sort and named . *) - let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -1492,8 +1015,7 @@ struct Creates a constant from the func_decl . @param f An expression of a 0-arity function *) - let mk_const_f ( ctx : context ) ( f : func_decl ) = - expr_of_func_app ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] (** Creates a fresh constant of sort and a @@ -1505,8 +1027,7 @@ struct (** Create a new function application. *) - let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) = - expr_of_func_app ctx f args + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args (** Create a numeral of a given sort. @@ -1528,19 +1049,44 @@ struct expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end +open FuncDecl +open Expr + (** Boolean expressions *) module Boolean = -struct +struct + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (ast_of_ptr ctx no) in - BoolExpr(Expr(a)) + let a = (AST.ast_of_ptr ctx no) in + BoolExpr(Expr.Expr(a)) + + let bool_expr_of_expr e = + match e with Expr.Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = BoolSort(sort_of_ptr ctx no) - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (ptr_of_expr e) + let sort_of_bool_sort s = match s with BoolSort(x) -> x + + let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + + let expr_of_bool_expr e = match e with BoolExpr(x) -> x + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) let mk_sort ( ctx : context ) = BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) @@ -1548,7 +1094,7 @@ struct (** Create a Boolean constant. *) - let mk_const ( ctx : context ) ( name : symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) @@ -1638,17 +1184,38 @@ end (** Quantifier expressions *) module Quantifier = struct + type quantifier = Quantifier of expr + + let expr_of_quantifier e = match e with Quantifier(x) -> x + + let quantifier_of_expr e = + match e with Expr.Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) - + (** Quantifier patterns Patterns comprise a list of terms. The list should be non-empty. If the list comprises of more than one term, it is also called a multi-pattern. *) - module Pattern = struct + module Pattern = + struct + type pattern = Pattern of ast + + let ast_of_pattern e = match e with Pattern(x) -> x + + let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) @@ -1692,7 +1259,7 @@ struct index. *) let get_index ( x : expr ) = - if not (AST.is_var (match x with Expr(a) -> a)) then + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) @@ -1723,7 +1290,7 @@ struct *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1736,7 +1303,7 @@ struct *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in - let f i = Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f (** @@ -1781,7 +1348,7 @@ struct if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) (** Create a universal Quantifier. @@ -1802,14 +1369,14 @@ struct @param quantifierID optional symbol to track quantifier. @param skolemID optional symbol to track skolem constants. *) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) else @@ -1817,21 +1384,21 @@ struct (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) (** Create a universal Quantifier. *) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true @@ -1839,7 +1406,7 @@ struct (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) @@ -1847,14 +1414,14 @@ struct Create an existential Quantifier. *) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) else @@ -1862,21 +1429,21 @@ struct (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - + (** Create an existential Quantifier. *) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false @@ -1884,14 +1451,14 @@ struct (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (ptr_of_ast (ast_of_pattern x)) in (Array.map f patterns)) + (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else @@ -1901,7 +1468,7 @@ struct (** Create a Quantifier. *) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : pattern array ) ( nopatterns : expr array ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1911,14 +1478,35 @@ end (** Functions to manipulate Array expressions *) module Array_ = struct + type array_sort = ArraySort of sort + type array_expr = ArrayExpr of expr - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let e = (expr_of_ptr ctx no) in ArrayExpr(e) - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in - ArraySort(s) + ArraySort(s) + + let sort_of_array_sort s = match s with ArraySort(x) -> x + + let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + + let array_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + + let expr_of_array_expr e = match e with ArrayExpr(x) -> x let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) @@ -1932,7 +1520,7 @@ struct Create a new array sort. *) let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - create_sort ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) (** Indicates whether the term is an array store. @@ -1979,16 +1567,15 @@ struct ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) (** The domain of the array sort. *) - let get_domain ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) (** The range of the array sort. *) - let get_range ( x : array_sort ) = sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - + let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) (** Create an array constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) (** @@ -2010,7 +1597,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) (** Array update. @@ -2029,7 +1616,7 @@ struct *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) + array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) (** Create a constant array. @@ -2040,7 +1627,7 @@ struct *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) + array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) (** Maps f on the argument arrays. @@ -2054,7 +1641,7 @@ struct *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in - expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) (** Access the array default value. @@ -2063,16 +1650,20 @@ struct finite maps with a default range value. *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = - expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end (** Functions to manipulate Set expressions *) module Set = struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type set_sort = SetSort of sort + + let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in SetSort(s) + let sort_of_set_sort s = match s with SetSort(x) -> x + (** Indicates whether the term is set union *) @@ -2102,7 +1693,7 @@ struct Create a set type. *) let mk_sort ( ctx : context ) ( ty : sort ) = - create_sort ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) (** Create an empty set. @@ -2169,14 +1760,24 @@ end (** Functions to manipulate Finite Domain expressions *) module FiniteDomain = struct + type finite_domain_sort = FiniteDomainSort of sort + + let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x + + let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - + (** Create a new finite domain sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( size : int ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in FiniteDomainSort(s) @@ -2210,15 +1811,24 @@ end (** Functions to manipulate Relation expressions *) module Relation = struct - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type relation_sort = RelationSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in RelationSort(s) + let sort_of_relation_sort s = match s with RelationSort(x) -> x + + let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - + (** Indicates whether the term is of a relation sort. @@ -2335,29 +1945,53 @@ struct (** The sorts of the columns of the relation sort. *) let get_column_sorts ( x : relation_sort ) = let n = get_arity x in - let f i = (create_sort (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in Array.init n f end (** Functions to manipulate Datatype expressions *) module Datatype = -struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = +struct + type datatype_sort = DatatypeSort of sort + type datatype_expr = DatatypeExpr of expr + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in DatatypeSort(s) + let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x + + let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + + let datatype_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + + let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - + (** Constructors *) module Constructor = struct + type constructor = z3_native_object + let _counts = Hashtbl.create 0 - let create ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -2366,11 +2000,11 @@ struct raise (Z3native.Exception "Number of field names does not match number of sort refs") else let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) - (Symbol.gno recognizer) - n - (let f x = (Symbol.gno x) in (Array.map f field_names)) - (let f x = (ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - sort_refs) in + (Symbol.gno recognizer) + n + (let f x = (Symbol.gno x) in (Array.map f field_names)) + (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) + sort_refs) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -2383,7 +2017,7 @@ struct no let get_n ( x : constructor ) = (Hashtbl.find _counts x) - + let rec constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in func_decl_of_ptr (z3obj_gc x) a @@ -2391,12 +2025,12 @@ struct let rec tester_decl ( x : constructor ) = let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in func_decl_of_ptr (z3obj_gc x) b - + let rec accessor_decls ( x : constructor ) = let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in let f y = func_decl_of_ptr (z3obj_gc x) y in Array.map f c - + (** The number of fields of the constructor. *) let get_num_fields ( x : constructor ) = get_n x @@ -2413,8 +2047,9 @@ struct (** Constructor list objects *) module ConstructorList = struct - - let create ( ctx : context ) ( c : constructor array ) = + type constructor_list = z3_native_object + + let create ( ctx : context ) ( c : Constructor.constructor array ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -2438,7 +2073,7 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs @@ -2452,22 +2087,22 @@ struct if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs (** Create a new datatype sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in - create_sort ctx x + sort_of_ptr ctx x (** Create a new datatype sort. *) - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors (** @@ -2475,17 +2110,17 @@ struct @param names names of datatype sorts @param c list of constructors, one list per sort. *) - let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) = + let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in - let f e = (ptr_of_ast (ConstructorList.create ctx e)) in + let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in let cla = (Array.map f c) in let f2 x = (Symbol.gno x) in let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in - let g e = (create_sort ctx e) in + let g e = (sort_of_ptr ctx e) in (Array.map g r) (** Create mutually recursive data-types. *) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in @@ -2522,17 +2157,21 @@ end (** Functions to manipulate Enumeration expressions *) module Enumeration = -struct +struct + type enum_sort = EnumSort of sort + let _constdecls = Hashtbl.create 0 let _testerdecls = Hashtbl.create 0 - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; res + let sort_of_enum_sort s = match s with EnumSort(x) -> x + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) @@ -2540,10 +2179,10 @@ struct (** Create a new enumeration sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( enum_names : symbol array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = let f x = Symbol.gno x in let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in - create_sort ctx a b c + sort_of_ptr ctx a b c (** Create a new enumeration sort. @@ -2561,14 +2200,16 @@ end (** Functions to manipulate List expressions *) module List_ = struct + type list_sort = ListSort of sort + let _nildecls = Hashtbl.create 0 let _is_nildecls = Hashtbl.create 0 let _consdecls = Hashtbl.create 0 let _is_consdecls = Hashtbl.create 0 let _headdecls = Hashtbl.create 0 let _taildecls = Hashtbl.create 0 - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in let res = ListSort(s) in Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; @@ -2578,16 +2219,18 @@ struct Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; res + + let sort_of_list_sort s = match s with ListSort(x) -> x let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - + + (** Create a new list sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( elem_sort : sort ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - create_sort ctx r a b c d e f + sort_of_ptr ctx r a b c d e f (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = @@ -2618,23 +2261,26 @@ end (** Functions to manipulate Tuple expressions *) module Tuple = struct - - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + type tuple_sort = TupleSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in TupleSort(s) + let sort_of_tuple_sort s = match s with TupleSort(x) -> x + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - + (** Create a new tuple sort. *) - let mk_sort ( ctx : context ) ( name : symbol ) ( field_names : symbol array ) ( field_sorts : sort array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = let f x = Symbol.gno x in let f2 x = ptr_of_ast (ast_of_sort x) in let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in (* CMW: leaks a,b? *) - create_sort ctx r + sort_of_ptr ctx r (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = @@ -2651,13 +2297,144 @@ struct end (** Functions to manipulate arithmetic expressions *) -module Arithmetic = -struct - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> arith_sort + val expr_of_arith_expr : arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> arith_expr - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end + + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr array -> arith_expr + val mk_mul : context -> arith_expr array -> arith_expr + val mk_sub : context -> arith_expr array -> arith_expr + val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end = struct + type arith_sort = ArithSort of sort + type arith_expr = ArithExpr of expr + + let arith_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + + let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_expr_of_expr (expr_of_ptr ctx no) + + let sort_of_arith_sort s = match s with ArithSort(x) -> x + let expr_of_arith_expr e = match e with ArithExpr(x) -> x + + let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + + let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = arith_sort_of_sort (sort_of_ptr ctx no) let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) @@ -2667,16 +2444,72 @@ struct let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - module Integer = - struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (create_expr ctx no) + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + + let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + + let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_num_of_int_expr (int_expr_of_ptr ctx no) + + let arith_sort_of_int_sort s = match s with IntSort(x) -> x + let arith_expr_of_int_expr e = match e with IntExpr(x) -> x + let int_expr_of_int_num e = match e with IntNum(x) -> x + + let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + + let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) @@ -2687,11 +2520,11 @@ struct let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - + (** Create a new integer sort. *) let mk_sort ( ctx : context ) = - create_sort ctx (Z3native.mk_int_sort (context_gno ctx)) + int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) (** Retrieve the int value. *) let get_int ( x : int_num ) = @@ -2705,7 +2538,7 @@ struct (** Creates an integer constant. *) - let mk_int_const ( ctx : context ) ( name : symbol ) = + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) (** @@ -2719,21 +2552,21 @@ struct The arguments must have int type. *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) (** Create an expression representing t1 rem t2. The arguments must have int type. *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) (** Create an integer numeral. @param v A string representing the Term value in decimal notation. *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) (** Create an integer numeral. @@ -2741,7 +2574,7 @@ struct @return A Term with value and sort Integer *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) (** Coerce an integer to a real. @@ -2754,7 +2587,7 @@ struct The argument must be of integer sort. *) let mk_int2real ( ctx : context ) ( t : int_expr ) = - real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) (** Create an bit bit-vector from the integer argument . @@ -2767,19 +2600,76 @@ struct The argument must be of integer sort. *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - bitvec_expr_of_expr (expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end - module Real = - struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (create_expr ctx no) + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : real_sort -> arith_sort + val real_sort_of_arith_sort : arith_sort -> real_sort + val arith_expr_of_real_expr : real_expr -> arith_expr + val real_expr_of_rat_num : rat_num -> real_expr + val real_expr_of_arith_expr : arith_expr -> real_expr + val rat_num_of_real_expr : real_expr -> rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let arith_sort_of_real_sort s = match s with RealSort(x) -> x + let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + let real_expr_of_rat_num e = match e with RatNum(x) -> x + + let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + + let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + + let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + rat_num_of_real_expr (real_expr_of_ptr ctx no) + + let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + + let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) @@ -2790,19 +2680,19 @@ struct let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - + (** Create a real sort. *) let mk_sort ( ctx : context ) = - create_sort ctx (Z3native.mk_real_sort (context_gno ctx)) + real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = - Integer.create_num (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = - Integer.create_num (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -2813,7 +2703,7 @@ struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) (** Creates a real constant. *) - let mk_real_const ( ctx : context ) ( name : symbol ) = + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) (** Creates a real constant. *) @@ -2832,7 +2722,7 @@ struct if (den == 0) then raise (Z3native.Exception "Denominator is zero") else - create_num ctx (Z3native.mk_real (context_gno ctx) num den) + rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) (** Create a real numeral. @@ -2840,7 +2730,7 @@ struct @return A Term with value and sort Real *) let mk_numeral_s ( ctx : context ) ( v : string ) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) (** Create a real numeral. @@ -2849,11 +2739,11 @@ struct @return A Term with value and sort Real *) let mk_numeral_i ( ctx : context ) ( v : int ) = - create_num ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) (** Coerce a real to an integer. @@ -2863,18 +2753,39 @@ struct The argument must be of real sort. *) let mk_real2int ( ctx : context ) ( t : real_expr ) = - int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end - module AlgebraicNumber = - struct - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x + + let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + + let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - + (** Return a upper bound for a given real algebraic number. @@ -2884,7 +2795,7 @@ struct @return A numeral Expr of sort Real *) let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.create_num (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) (** Return a lower bound for the given real algebraic number. @@ -2894,7 +2805,7 @@ struct @return A numeral Expr of sort Real *) let to_lower ( x : algebraic_num ) precision = - Real.create_num (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) (** Returns a string representation in decimal notation. The result has at most decimal places.*) @@ -3056,38 +2967,186 @@ struct Create an expression representing t1 < t2 *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 <= t2 *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 > t2 *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) (** Create an expression representing t1 >= t2 *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end (** Functions to manipulate bit-vector expressions *) -module BitVector = -struct - let create_sort ( ctx : context ) ( no : Z3native.ptr ) = +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + val mk_sort : context -> int -> bitvec_sort + val is_bv : Expr.expr -> bool + val is_bv_numeral : Expr.expr -> bool + val is_bv_bit1 : Expr.expr -> bool + val is_bv_bit0 : Expr.expr -> bool + val is_bv_uminus : Expr.expr -> bool + val is_bv_add : Expr.expr -> bool + val is_bv_sub : Expr.expr -> bool + val is_bv_mul : Expr.expr -> bool + val is_bv_sdiv : Expr.expr -> bool + val is_bv_udiv : Expr.expr -> bool + val is_bv_SRem : Expr.expr -> bool + val is_bv_urem : Expr.expr -> bool + val is_bv_smod : Expr.expr -> bool + val is_bv_sdiv0 : Expr.expr -> bool + val is_bv_udiv0 : Expr.expr -> bool + val is_bv_srem0 : Expr.expr -> bool + val is_bv_urem0 : Expr.expr -> bool + val is_bv_smod0 : Expr.expr -> bool + val is_bv_ule : Expr.expr -> bool + val is_bv_sle : Expr.expr -> bool + val is_bv_uge : Expr.expr -> bool + val is_bv_sge : Expr.expr -> bool + val is_bv_ult : Expr.expr -> bool + val is_bv_slt : Expr.expr -> bool + val is_bv_ugt : Expr.expr -> bool + val is_bv_sgt : Expr.expr -> bool + val is_bv_and : Expr.expr -> bool + val is_bv_or : Expr.expr -> bool + val is_bv_not : Expr.expr -> bool + val is_bv_xor : Expr.expr -> bool + val is_bv_nand : Expr.expr -> bool + val is_bv_nor : Expr.expr -> bool + val is_bv_xnor : Expr.expr -> bool + val is_bv_concat : Expr.expr -> bool + val is_bv_signextension : Expr.expr -> bool + val is_bv_zeroextension : Expr.expr -> bool + val is_bv_extract : Expr.expr -> bool + val is_bv_repeat : Expr.expr -> bool + val is_bv_reduceor : Expr.expr -> bool + val is_bv_reduceand : Expr.expr -> bool + val is_bv_comp : Expr.expr -> bool + val is_bv_shiftleft : Expr.expr -> bool + val is_bv_shiftrightlogical : Expr.expr -> bool + val is_bv_shiftrightarithmetic : Expr.expr -> bool + val is_bv_rotateleft : Expr.expr -> bool + val is_bv_rotateright : Expr.expr -> bool + val is_bv_rotateleftextended : Expr.expr -> bool + val is_bv_rotaterightextended : Expr.expr -> bool + val is_int_to_bv : Expr.expr -> bool + val is_bv_to_int : Expr.expr -> bool + val is_bv_carry : Expr.expr -> bool + val is_bv_xor3 : Expr.expr -> bool + val get_size : bitvec_sort -> int + val get_int : bitvec_num -> int + val to_string : bitvec_num -> string + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> bitvec_expr + val mk_not : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_numeral : context -> string -> int -> bitvec_num +end = struct + type bitvec_sort = BitVecSort of sort + type bitvec_expr = BitVecExpr of expr + type bitvec_num = BitVecNum of bitvec_expr + + let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x + + let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + + let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = bitvec_sort_of_sort (sort_of_ptr ctx no) - let create_expr ( ctx : context ) ( no : Z3native.ptr ) = + let bitvec_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + + let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = bitvec_expr_of_expr (expr_of_ptr ctx no) - let create_num ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (create_expr ctx no) + let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + + let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) + + let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x + let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) @@ -3098,13 +3157,13 @@ struct let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - + (** Create a new bit-vector sort. *) let mk_sort ( ctx : context ) size = - create_sort ctx (Z3native.mk_bv_sort (context_gno ctx) size) + bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) (** Indicates whether the terms is of bit-vector sort. @@ -3391,8 +3450,8 @@ struct (** Creates a bit-vector constant. *) - let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (mk_sort ctx size) with BitVecSort(s) -> s)) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) (** Creates a bit-vector constant. @@ -3426,70 +3485,70 @@ struct The arguments must have a bit-vector sort. *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise disjunction. The arguments must have a bit-vector sort. *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XOR. The arguments must have a bit-vector sort. *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NAND. The arguments must have a bit-vector sort. *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) (** Bitwise NOR. The arguments must have a bit-vector sort. *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) (** Bitwise XNOR. The arguments must have a bit-vector sort. *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) (** Two's complement addition. The arguments must have the same bit-vector sort. *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) (** Unsigned division. @@ -3501,7 +3560,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) (** Signed division. @@ -3516,7 +3575,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) (** Unsigned remainder. @@ -3526,7 +3585,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) (** Signed remainder. @@ -3538,7 +3597,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) (** Two's complement signed remainder (sign follows divisor). @@ -3547,7 +3606,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) (** Unsigned less-than @@ -3555,7 +3614,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than @@ -3563,7 +3622,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) (** Unsigned less-than or equal to. @@ -3571,7 +3630,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed less-than or equal to. @@ -3579,7 +3638,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater than or equal to. @@ -3587,7 +3646,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater than or equal to. @@ -3595,7 +3654,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) (** Unsigned greater-than. @@ -3603,7 +3662,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) (** Two's complement signed greater-than. @@ -3611,7 +3670,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) (** Bit-vector concatenation. @@ -3622,7 +3681,7 @@ struct is the size of t1 (t2). *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) (** Bit-vector extraction. @@ -3633,7 +3692,7 @@ struct The argument must have a bit-vector sort. *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) (** Bit-vector sign extension. @@ -3643,7 +3702,7 @@ struct The argument must have a bit-vector sort. *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) (** Bit-vector zero extension. @@ -3654,7 +3713,7 @@ struct The argument must have a bit-vector sort. *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) (** Bit-vector repetition. @@ -3662,7 +3721,7 @@ struct The argument must have a bit-vector sort. *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) (** Shift left. @@ -3677,8 +3736,8 @@ struct The arguments must have a bit-vector sort. *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - + bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + (** Logical shift right @@ -3692,7 +3751,7 @@ struct The arguments must have a bit-vector sort. *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) (** Arithmetic shift right @@ -3708,7 +3767,7 @@ struct The arguments must have a bit-vector sort. *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) (** Rotate Left. @@ -3717,7 +3776,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) (** Rotate Right. @@ -3726,7 +3785,7 @@ struct The argument must have a bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) (** Rotate Left. @@ -3735,7 +3794,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) (** Rotate Right. @@ -3745,7 +3804,7 @@ struct The arguments must have the same bit-vector sort. *) let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) (** Create an integer from the bit-vector argument . @@ -3763,7 +3822,7 @@ struct The argument must be of bit-vector sort. *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.create_expr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) (** Create a predicate that checks that the bit-wise addition does not overflow. @@ -3771,7 +3830,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise addition does not underflow. @@ -3779,7 +3838,7 @@ struct The arguments must be of bit-vector sort. *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not overflow. @@ -3787,7 +3846,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise subtraction does not underflow. @@ -3795,7 +3854,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise signed division does not overflow. @@ -3803,7 +3862,7 @@ struct The arguments must be of bit-vector sort. *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) (** Create a predicate that checks that the bit-wise negation does not overflow. @@ -3811,7 +3870,7 @@ struct The arguments must be of bit-vector sort. *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) (** Create a predicate that checks that the bit-wise multiplication does not overflow. @@ -3819,7 +3878,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) (** Create a predicate that checks that the bit-wise multiplication does not underflow. @@ -3827,7 +3886,7 @@ struct The arguments must be of bit-vector sort. *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) (** Create a bit-vector numeral. @@ -3836,7 +3895,7 @@ struct @param size the size of the bit-vector *) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - create_num ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx size))) + bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) end (** Functions to manipulate proof expressions *) @@ -4321,7 +4380,8 @@ end tactics and solvers. *) module Goal = struct - + type goal = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : goal = { m_ctx = ctx ; m_n_obj = null ; @@ -4330,7 +4390,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** The precision of the goal. @@ -4359,7 +4419,7 @@ struct (** Adds the constraints to the given goal. *) (* CMW: assert seems to be a keyword. *) - let assert_ ( x : goal ) ( constraints : bool_expr array ) = + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () @@ -4381,7 +4441,7 @@ struct (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in - let f i = (bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f @@ -4401,7 +4461,7 @@ struct create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - let simplify ( x : goal ) ( p : params option ) = + let simplify ( x : goal ) ( p : Params.params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; let arn = match p with @@ -4441,7 +4501,8 @@ end A Model contains interpretations (assignments) of constants and functions. *) module Model = struct - + type model = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : model = { m_ctx = ctx ; m_n_obj = null ; @@ -4450,7 +4511,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Function interpretations @@ -4459,7 +4520,8 @@ struct *) module FuncInterp = struct - + type func_interp = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_interp = { m_ctx = ctx ; m_n_obj = null ; @@ -4468,7 +4530,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Function interpretations entries @@ -4476,7 +4538,8 @@ struct *) module FuncEntry = struct - + type func_entry = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : func_entry = { m_ctx = ctx ; m_n_obj = null ; @@ -4485,7 +4548,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Return the (symbolic) value of this entry. @@ -4677,7 +4740,7 @@ struct An array of expressions, where each is an element of the universe of *) let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f @@ -4699,7 +4762,8 @@ end *) module Probe = struct - + type probe = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : probe = { m_ctx = ctx ; m_n_obj = null ; @@ -4708,14 +4772,14 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Execute the probe over the goal. A probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - let apply ( x : probe ) (g : goal) = + let apply ( x : probe ) ( g : Goal.goal ) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (** @@ -4820,7 +4884,8 @@ end *) module Tactic = struct - + type tactic = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : tactic = { m_ctx = ctx ; m_n_obj = null ; @@ -4829,7 +4894,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** Tactic application results @@ -4837,7 +4902,8 @@ struct tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct - + type apply_result = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : apply_result = { m_ctx = ctx ; m_n_obj = null ; @@ -4846,7 +4912,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = @@ -4866,7 +4932,7 @@ struct goal g, that the ApplyResult was obtained from. #return A model for g *) - let convert_model ( x : apply_result ) ( i : int ) ( m : model ) = + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) (** A string representation of the ApplyResult. *) @@ -4878,10 +4944,10 @@ struct (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Apply the tactic to the goal. *) - let apply ( x : tactic ) ( g : goal ) ( p : params option ) = + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) @@ -4949,14 +5015,14 @@ struct If evaluates to false, then the new tactic behaves like the skip tactic. *) (* CMW: when is a keyword *) - let when_ ( ctx : context ) ( p : probe ) ( t : tactic ) = + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) (** Create a tactic that applies to a given goal if the probe evaluates to true and otherwise. *) - let cond ( ctx : context ) ( p : probe ) ( t1 : tactic ) ( t2 : tactic ) = + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) (** @@ -4981,7 +5047,7 @@ struct (** Create a tactic that fails if the probe evaluates to false. *) - let fail_if ( ctx : context ) ( p : probe ) = + let fail_if ( ctx : context ) ( p : Probe.probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) (** @@ -4994,14 +5060,14 @@ struct (** Create a tactic that applies using the given set of parameters . *) - let using_params ( ctx : context ) ( t : tactic ) ( p : params ) = + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) (** Create a tactic that applies using the given set of parameters . Alias for UsingParams*) (* CMW: with is a keyword *) - let with_ ( ctx : context ) ( t : tactic ) ( p : params ) = + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p (** @@ -5029,7 +5095,9 @@ end (** Solvers *) module Solver = struct - + type solver = z3_native_object + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : solver = { m_ctx = ctx ; m_n_obj = null ; @@ -5038,7 +5106,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" @@ -5048,7 +5116,8 @@ struct (** Objects that track statistical information about solvers. *) module Statistics = struct - + type statistics = z3_native_object + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : statistics = { m_ctx = ctx ; m_n_obj = null ; @@ -5066,7 +5135,13 @@ struct *) module Entry = struct - + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -5086,7 +5161,7 @@ struct m_float = v } in res - + (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key @@ -5142,11 +5217,9 @@ struct let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** - The value of a particular statistical counter. - *) + (** The value of a particular statistical counter. *) let get ( x : statistics ) ( key : string ) = - let f p c = (if (Entry.get_key c) = key then (Some c) else p) in + let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in Array.fold_left f None (get_entries x) end @@ -5158,14 +5231,14 @@ struct (** Sets the solver parameters. *) - let set_parameters ( x : solver ) ( p : params )= + let set_parameters ( x : solver ) ( p : Params.params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for solver. *) let get_param_descrs ( x : solver ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** The current number of backtracking points (scopes). @@ -5196,7 +5269,7 @@ struct (** Assert a constraint (or multiple) into the solver. *) - let assert_ ( x : solver ) ( constraints : bool_expr array ) = + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) @@ -5213,7 +5286,7 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( cs : bool_expr array ) ( ps : bool_expr array ) = + let assert_and_track ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else @@ -5232,14 +5305,14 @@ struct * and the Boolean literals * provided using with assumptions. *) - let assert_and_track ( x : solver ) ( c : bool_expr ) ( p : bool_expr ) = + let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) (** The number of assertions in the solver. *) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) @@ -5247,9 +5320,9 @@ struct The set of asserted formulas. *) let get_assertions ( x : solver ) = - let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f (** @@ -5259,12 +5332,12 @@ struct *) - let check ( x : solver ) ( assumptions : bool_expr array) = + let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = let r = if ((Array.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - let f x = (ptr_of_expr (expr_of_bool_expr x)) in + let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) in match r with @@ -5306,7 +5379,7 @@ struct if its results was not UNSATISFIABLE, or if core production is disabled. *) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f @@ -5330,7 +5403,7 @@ struct check-sat command, and check-sat commands that take more than a given number of milliseconds to be solved. *) - let mk_solver ( ctx : context ) ( logic : symbol option ) = + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) @@ -5354,7 +5427,7 @@ struct The solver supports the commands Push and Pop, but it will always solve each check from scratch. *) - let mk_solver_t ( ctx : context ) ( t : tactic ) = + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) (** @@ -5366,7 +5439,9 @@ end (** Fixedpoint solving *) module Fixedpoint = -struct +struct + type fixedpoint = z3_native_object + let create ( ctx : context ) = let res : fixedpoint = { m_ctx = ctx ; m_n_obj = null ; @@ -5375,7 +5450,7 @@ struct (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; (z3obj_create res) ; res - + (** A string that describes all available fixedpoint solver parameters. @@ -5386,19 +5461,19 @@ struct (** Sets the fixedpoint solver parameters. *) - let set_params ( x : fixedpoint ) ( p : params )= + let set_params ( x : fixedpoint ) ( p : Params.params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) (** Retrieves parameter descriptions for Fixedpoint solver. *) let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.create (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) (** Assert a constraints into the fixedpoint solver. *) - let assert_ ( x : fixedpoint ) ( constraints : bool_expr array ) = + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () @@ -5412,7 +5487,7 @@ struct (** Add rule into the fixedpoint solver. *) - let add_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) @@ -5429,11 +5504,11 @@ struct The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - let query ( x : fixedpoint ) ( query : bool_expr ) = + let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN (** Query the fixedpoint solver. @@ -5444,9 +5519,9 @@ struct let query_r ( x : fixedpoint ) ( relations : func_decl array ) = let f x = ptr_of_ast (ast_of_func_decl x) in match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN (** Creates a backtracking point. @@ -5467,7 +5542,7 @@ struct (** Update named rule into in the fixedpoint solver. *) - let update_rule ( x : fixedpoint ) ( rule : bool_expr ) ( name : symbol ) = + let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) (** @@ -5518,33 +5593,33 @@ struct (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : symbol array ) = + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = let f2 x = (Symbol.gno x) in Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) (** Convert benchmark given as set of axioms, rules and queries to a string. *) - let to_string_q ( x : fixedpoint ) ( queries : bool_expr array ) = - let f x = ptr_of_expr (expr_of_bool_expr x) in + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = + let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) (** Retrieve set of rules added to fixedpoint context. *) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** Retrieve set of assertions added to fixedpoint context. *) let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f (** @@ -5628,9 +5703,9 @@ struct @param formula Formula to be checked for consistency in conjunction with assumptions. @return A string representation of the benchmark. *) - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : bool_expr array ) ( formula : bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (let f x = ptr_of_expr (expr_of_bool_expr x) in (Array.map f assumptions)) + (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) (Boolean.gno formula) (** @@ -5642,7 +5717,7 @@ struct and . This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5662,7 +5737,7 @@ struct Parse the given file using the SMT-LIB parser. *) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5688,7 +5763,7 @@ struct *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f @@ -5702,7 +5777,7 @@ struct *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f (** @@ -5737,7 +5812,7 @@ struct @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5745,19 +5820,19 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) - cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) (** Parse the given file using the SMT-LIB2 parser. *) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : symbol array ) ( sorts : sort array ) ( decl_names : symbol array ) ( decls : func_decl array ) = + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in let cdn = (Array.length decl_names) in @@ -5765,13 +5840,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) - cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (let f x = Symbol.gno x in (Array.map f sort_names)) + (let f x = Sort.gno x in (Array.map f sorts)) + cd + (let f x = Symbol.gno x in (Array.map f decl_names)) + (let f x = FuncDecl.gno x in (Array.map f decls)))) end @@ -5818,23 +5893,3 @@ let get_global_param ( id : string ) = *) let global_param_reset_all = Z3native.global_param_reset_all - - - -(* - -(** - A delegate which is executed when an error is raised. - - Note that it is possible for memory leaks to occur if error handlers - throw exceptions. -*) - public delegate void ErrorHandler(Context ctx, error_code errorCode, string errorString); - - internal Z3native.error_handler m_n_err_handler = null; - - internal void NativeErrorHandler(IntPtr ctx, error_code errorCode) - - Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. - -*) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 5d5d7adf0..5b1b2073a 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -7,333 +7,566 @@ type context -type int_symbol -type string_symbol -type symbol = S_Int of int_symbol | S_Str of string_symbol +(** Create a context object. -type ast -type ast_vector -type ast_map + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do -type sort = Sort of ast + + let ctx = (mk_context []) in + (...) + -type uninterpreted_sort = UninterpretedSort of sort -type bool_sort = BoolSort of sort -type array_sort = ArraySort of sort -type set_sort = SetSort of sort -type datatype_sort = DatatypeSort of sort -type relation_sort = RelationSort of sort -type finite_domain_sort = FiniteDomainSort of sort -type enum_sort = EnumSort of sort -type list_sort = ListSort of sort -type tuple_sort = TupleSort of sort -type arith_sort = ArithSort of sort -type bitvec_sort = BitVecSort of sort -type int_sort = IntSort of arith_sort -type real_sort = RealSort of arith_sort + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: -type func_decl = FuncDecl of ast + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (mk_context cfg) in + (...) + +*) +val mk_context : (string * string) list -> context -type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of symbol - | P_Srt of sort - | P_Ast of ast - | P_Fdl of func_decl - | P_Rat of string - -type params -type param_descrs - -type expr = Expr of ast -type bool_expr = BoolExpr of expr -type arith_expr = ArithExpr of expr -type int_expr = IntExpr of arith_expr -type real_expr = RealExpr of arith_expr -type bitvec_expr = BitVecExpr of expr -type array_expr = ArrayExpr of expr -type datatype_expr = DatatypeExpr of expr -type int_num = IntNum of int_expr -type rat_num = RatNum of real_expr -type algebraic_num = AlgebraicNum of arith_expr -type bitvec_num = BitVecNum of bitvec_expr -type quantifier = Quantifier of expr -type pattern = Pattern of ast - -type constructor - -type goal - -type model -type func_interp -type func_entry - -type probe - -type tactic -type apply_result - -type solver -type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - -type statistics -type statistics_entry - -type fixedpoint - -val ast_of_sort : sort -> ast -val sort_of_uninterpreted_sort : uninterpreted_sort -> sort -val sort_of_bool_sort : bool_sort -> sort -val sort_of_array_sort : array_sort -> sort -val sort_of_set_sort : set_sort -> sort -val sort_of_datatype_sort : datatype_sort -> sort -val sort_of_relation_sort : relation_sort -> sort -val sort_of_finite_domain_sort : finite_domain_sort -> sort -val sort_of_enum_sort : enum_sort -> sort -val sort_of_list_sort : list_sort -> sort -val sort_of_tuple_sort : tuple_sort -> sort -val sort_of_arith_sort : arith_sort -> sort -val sort_of_bitvec_sort : bitvec_sort -> sort -val arith_sort_of_int_sort : int_sort -> arith_sort -val arith_sort_of_real_sort : real_sort -> arith_sort -val uninterpreted_sort_of_sort : sort -> uninterpreted_sort -val bool_sort_of_sort : sort -> bool_sort -val array_sort_of_sort : sort -> array_sort -val datatype_sort_of_sort : sort -> datatype_sort -val relation_sort_of_sort : sort -> relation_sort -val finite_domain_sort_of_sort : sort -> finite_domain_sort -val arith_sort_of_sort : sort -> arith_sort -val bitvec_sort_of_sort : sort -> bitvec_sort -val int_sort_of_arith_sort : arith_sort -> int_sort -val real_sort_of_arith_sort : arith_sort -> real_sort -val ast_of_func_decl : func_decl -> ast -val ast_of_expr : expr -> ast -val expr_of_bool_expr : bool_expr -> expr -val expr_of_arith_expr : arith_expr -> expr -val expr_of_bitvec_expr : bitvec_expr -> expr -val expr_of_array_expr : array_expr -> expr -val expr_of_datatype_expr : datatype_expr -> expr -val arith_expr_of_int_expr : int_expr -> arith_expr -val arith_expr_of_real_expr : real_expr -> arith_expr -val int_expr_of_int_num : int_num -> int_expr -val real_expr_of_rat_num : rat_num -> real_expr -val arith_expr_of_algebraic_num : algebraic_num -> arith_expr -val bitvec_expr_of_bitvec_num : bitvec_num -> bitvec_expr -val expr_of_quantifier : quantifier -> expr -val ast_of_pattern : pattern -> ast -val expr_of_ast : ast -> expr -val bool_expr_of_expr : expr -> bool_expr -val arith_expr_of_expr : expr -> arith_expr -val bitvec_expr_of_expr : expr -> bitvec_expr -val array_expr_of_expr : expr -> array_expr -val datatype_expr_of_expr : expr -> datatype_expr -val int_expr_of_arith_expr : arith_expr -> int_expr -val real_expr_of_arith_expr : arith_expr -> real_expr -val int_num_of_int_expr : int_expr -> int_num -val rat_num_of_real_expr : real_expr -> rat_num -val algebraic_num_of_arith_expr : arith_expr -> algebraic_num -val bitvec_num_of_bitvec_expr : bitvec_expr -> bitvec_num -val quantifier_of_expr : expr -> quantifier -val pattern_of_ast : ast -> pattern +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) module Log : sig + (** Open an interaction log file. + @param filename the name of the file to open. + @return True if opening the log file succeeds, false otherwise. + *) + (* CMW: "open" seems to be a reserved keyword? *) val open_ : string -> bool + + (** Closes the interaction log. *) val close : unit + + (** Appends a user-provided string to the interaction log. + @param s the string to append*) val append : string -> unit end +(** Version information *) module Version : sig + (** The major version. *) val major : int + + (** The minor version. *) val minor : int + + (** The build version. *) val build : int + + (** The revision. *) val revision : int + + (** A string representation of the version information. *) val to_string : string end -val mk_context : (string * string) list -> context - +(** Symbols are used to name several term and type constructors *) module Symbol : sig + (** Numbered Symbols *) + type int_symbol + + (** Named Symbols *) + type string_symbol + + (** Symbols *) + type symbol = S_Int of int_symbol | S_Str of string_symbol + + (** The kind of the symbol (int or string) *) val kind : symbol -> Z3enums.symbol_kind + + (** Indicates whether the symbol is of Int kind *) val is_int_symbol : symbol -> bool + + (** Indicates whether the symbol is of string kind. *) val is_string_symbol : symbol -> bool + + (** The int value of the symbol. *) val get_int : int_symbol -> int + + (** The string value of the symbol. *) val get_string : string_symbol -> string + + (** A string representation of the symbol. *) val to_string : symbol -> string + + (** + Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. + *) val mk_int : context -> int -> symbol + + (** Creates a new symbol using a string. *) val mk_string : context -> string -> symbol + + (** Create an array of symbols. *) val mk_ints : context -> int array -> symbol array + + (** Create an array of symbols. *) val mk_strings : context -> string array -> symbol array end +(** The abstract syntax tree (AST) module *) module AST : sig + type ast + (** Vectors of ASTs *) module ASTVector : sig + type ast_vector + + (** The size of the vector *) val get_size : ast_vector -> int - val get : ast_vector -> int -> ast_vector + + (** + Retrieves the i-th object in the vector. + @param i Index + @return An AST + *) + val get : ast_vector -> int -> ast + + (** Sets the i-th object in the vector. *) val set : ast_vector -> int -> ast -> unit + + (** Resize the vector to . + @param newSize The new size of the vector. *) val resize : ast_vector -> int -> unit + + (** + Add the AST to the back of the vector. The size + is increased by 1. + @param a An AST + *) val push : ast_vector -> ast -> unit + + (** + Translates all ASTs in the vector to . + @param to_ctx A context + @return A new ASTVector + *) val translate : ast_vector -> context -> ast_vector + + (** Retrieves a string representation of the vector. *) val to_string : ast_vector -> string end + (** Map from AST to AST *) module ASTMap : sig + type ast_map + + (** Checks whether the map contains the key . + @param k An AST + @return True if is a key in the map, false otherwise. *) val contains : ast_map -> ast -> bool - val find : ast_map -> ast -> ast_map + + (** Finds the value associated with the key . + + This function signs an error when is not a key in the map. + @param k An AST + *) + val find : ast_map -> ast -> ast + + (** + Stores or replaces a new key/value pair in the map. + @param k The key AST + @param v The value AST + *) val insert : ast_map -> ast -> ast -> unit + + (** + Erases the key from the map. + @param k An AST + *) val erase : ast_map -> ast -> unit + + (** Removes all keys from the map. *) val reset : ast_map -> unit + + (** The size of the map *) val get_size : ast_map -> int - val get_keys : ast_map -> ast_vector + + (** The keys stored in the map. *) + val get_keys : ast_map -> ASTVector.ast_vector + + (** Retrieves a string representation of the map.*) val to_string : ast_map -> string end + (** + The AST's hash code. + @return A hash code + *) val get_hash_code : ast -> int + + (** A unique identifier for the AST (unique among all ASTs). *) val get_id : ast -> int + + (** The kind of the AST. *) val get_ast_kind : ast -> Z3enums.ast_kind + + (** Indicates whether the AST is an Expr *) val is_expr : ast -> bool + + (** Indicates whether the AST is a bound variable*) val is_var : ast -> bool + + (** Indicates whether the AST is a Quantifier *) val is_quantifier : ast -> bool + + (** Indicates whether the AST is a Sort *) val is_sort : ast -> bool + + (** Indicates whether the AST is a func_decl *) val is_func_decl : ast -> bool + + (** A string representation of the AST. *) val to_string : ast -> string + + (** A string representation of the AST in s-expression notation. *) val to_sexpr : ast -> string + + (** + Comparison operator. + @param a An AST + @param b An AST + @return True if and are from the same context + and represent the same sort; false otherwise. + *) val ( = ) : ast -> ast -> bool + + (** + Object Comparison. + @param other Another ast + @return Negative if the object should be sorted before , positive if after else zero. + *) val compare : ast -> ast -> int + + (** Operator < *) val ( < ) : ast -> ast -> int + + (** + Translates (copies) the AST to the Context . + @param ctx A context + @return A copy of the AST which is associated with + *) val translate : ast -> context -> ast + + (** + Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that must be a + native object obtained from Z3 (e.g., through ) + and that it must have a correct reference count (see e.g., + . + + @param nativeObject The native pointer to wrap. + *) val wrap : context -> Z3native.z3_ast -> ast + + (** + Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + ). + + @param a The AST to unwrap. + *) val unwrap_ast : ast -> Z3native.ptr end +(** The Sort module implements type information for ASTs *) module Sort : sig + (** Sorts *) + type sort = Sort of AST.ast + + (** Uninterpreted Sorts *) + type uninterpreted_sort = UninterpretedSort of sort + + val ast_of_sort : sort -> AST.ast + val sort_of_uninterpreted_sort : uninterpreted_sort -> sort + val uninterpreted_sort_of_sort : sort -> uninterpreted_sort + + (** + Comparison operator. + @param a A sort + @param b A sort + @return True if and are from the same context + and represent the same sort; false otherwise. + *) val ( = ) : sort -> sort -> bool + + (** Returns a unique identifier for the sort. *) val get_id : sort -> int + + (** The kind of the sort. *) val get_sort_kind : sort -> Z3enums.sort_kind - val get_name : sort -> symbol + + (** The name of the sort *) + val get_name : sort -> Symbol.symbol + + (** A string representation of the sort. *) val to_string : sort -> string - val mk_uninterpreted : context -> symbol -> uninterpreted_sort + + (** Create a new uninterpreted sort. *) + val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort + + (** Create a new uninterpreted sort. *) val mk_uninterpreted_s : context -> string -> uninterpreted_sort end -module FuncDecl : +(** Function declarations *) +module rec FuncDecl : sig + type func_decl = FuncDecl of AST.ast + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + + (** Parameters of Func_Decls *) module Parameter : sig + (** Parameters of func_decls *) + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) val get_kind : parameter -> Z3enums.parameter_kind + + (** The int value of the parameter.*) val get_int : parameter -> int + + (** The double value of the parameter.*) val get_float : parameter -> float - val get_symbol : parameter -> symbol - val get_sort : parameter -> sort - val get_ast : parameter -> ast - val get_func_decl : parameter -> string + + (** The Symbol.Symbol value of the parameter.*) + val get_symbol : parameter -> Symbol.symbol + + (** The Sort value of the parameter.*) + val get_sort : parameter -> Sort.sort + + (** The AST value of the parameter.*) + val get_ast : parameter -> AST.ast + + (** The FunctionDeclaration value of the parameter.*) + val get_func_decl : parameter -> func_decl + + (** The rational string value of the parameter.*) + val get_rational : parameter -> string end - val mk_func_decl : context -> symbol -> sort array -> sort -> func_decl - val mk_func_decl_s : context -> string -> sort array -> sort -> func_decl - val mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl - val mk_const_decl : context -> symbol -> sort -> func_decl - val mk_const_decl_s : context -> string -> sort -> func_decl - val mk_fresh_const_decl : context -> string -> sort -> func_decl + (** Creates a new function declaration. *) + val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl + + (** Creates a new function declaration. *) + val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl + (** Creates a fresh function declaration with a name prefixed with . + + *) + + val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + + (** Creates a fresh constant function declaration with a name prefixed with . + + *) + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + + (** Comparison operator. + @param a A func_decl + @param b A func_decl + @return True if and are from the same context + and represent the same func_decl; false otherwise. *) val ( = ) : func_decl -> func_decl -> bool + + (** A string representations of the function declaration. *) val to_string : func_decl -> string + + (** Returns a unique identifier for the function declaration. *) val get_id : func_decl -> int + + (** The arity of the function declaration *) val get_arity : func_decl -> int + + (** The size of the domain of the function declaration + *) val get_domain_size : func_decl -> int - val get_domain : func_decl -> sort array - val get_range : func_decl -> sort + + (** The domain of the function declaration *) + val get_domain : func_decl -> Sort.sort array + + (** The range of the function declaration *) + val get_range : func_decl -> Sort.sort + + (** The kind of the function declaration. *) val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_name : func_decl -> symbol + + (** The name of the function declaration*) + val get_name : func_decl -> Symbol.symbol + + (** The number of parameters of the function declaration *) val get_num_parameters : func_decl -> int - val get_parameters : func_decl -> parameter list - val apply : func_decl -> expr array -> expr + + (** The parameters of the function declaration *) + val get_parameters : func_decl -> Parameter.parameter list + + (** Create expression that applies function to arguments. + @param args The arguments *) + val apply : func_decl -> Expr.expr array -> Expr.expr end -module Params : -sig +(** Parameter sets (of Solvers, Tactics, ...) + A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) +and Params : +sig + type params + + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) module ParamDescrs : sig + type param_descrs + + (** Validate a set of parameters. *) val validate : param_descrs -> params -> unit - val get_kind : param_descrs -> symbol -> Z3enums.param_kind - val get_names : param_descrs -> symbol array + + (** Retrieve kind of parameter. *) + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + + (** Retrieve all names of parameters. *) + val get_names : param_descrs -> Symbol.symbol array + + (** The size of the ParamDescrs. *) val get_size : param_descrs -> int + + (** Retrieves a string representation of the ParamDescrs. *) val to_string : param_descrs -> string end - val add_bool : params -> symbol -> bool -> unit - val add_int : params -> symbol -> int -> unit - val add_double : params -> symbol -> float -> unit - val add_symbol : params -> symbol -> symbol -> unit + (** Adds a parameter setting. *) + val add_bool : params -> Symbol.symbol -> bool -> unit + + (** Adds a parameter setting. *) + val add_int : params -> Symbol.symbol -> int -> unit + + (** Adds a parameter setting. *) + val add_double : params -> Symbol.symbol -> float -> unit + + (** Adds a parameter setting. *) + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + + (** Adds a parameter setting. *) val add_s_bool : params -> string -> bool -> unit + + (** Adds a parameter setting. *) val add_s_int : params -> string -> int -> unit + + (** Adds a parameter setting. *) val add_s_double : params -> string -> float -> unit - val add_s_symbol : params -> string -> symbol -> unit + + (** Adds a parameter setting. *) + val add_s_symbol : params -> string -> Symbol.symbol -> unit + + (** Creates a new parameter set *) val mk_params : context -> params + + (** A string representation of the parameter set. *) val to_string : params -> string end -module Expr : +and Expr : sig - val simplify : expr -> params option -> expr + (** General Expressions (Terms) *) + type expr = Expr of AST.ast + + val ast_of_expr : Expr.expr -> AST.ast + val expr_of_ast : AST.ast -> Expr.expr + + val simplify : Expr.expr -> Params.params option -> expr val get_simplify_help : context -> string - val get_simplify_parameter_descrs : context -> param_descrs - val get_func_decl : expr -> func_decl - val get_bool_value : expr -> Z3enums.lbool - val get_num_args : expr -> int - val get_args : expr -> expr array - val update : expr -> expr array -> expr - val substitute : expr -> expr array -> expr array -> expr - val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr array -> expr - val translate : expr -> context -> expr - val to_string : expr -> string - val is_numeral : expr -> bool - val is_well_sorted : expr -> bool - val get_sort : expr -> sort - val is_bool : expr -> bool - val is_const : expr -> bool - val is_true : expr -> bool - val is_false : expr -> bool - val is_eq : expr -> bool - val is_distinct : expr -> bool - val is_ite : expr -> bool - val is_and : expr -> bool - val is_or : expr -> bool - val is_iff : expr -> bool - val is_xor : expr -> bool - val is_not : expr -> bool - val is_implies : expr -> bool - val is_label : expr -> bool - val is_oeq : expr -> bool - val mk_const : context -> symbol -> sort -> expr - val mk_const_s : context -> string -> sort -> expr - val mk_const_f : context -> func_decl -> expr - val mk_fresh_const : context -> string -> sort -> expr - val mk_app : context -> func_decl -> expr array -> expr - val mk_numeral_string : context -> string -> sort -> expr - val mk_numeral_int : context -> int -> sort -> expr + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + val get_func_decl : Expr.expr -> FuncDecl.func_decl + val get_bool_value : Expr.expr -> Z3enums.lbool + val get_num_args : Expr.expr -> int + val get_args : Expr.expr -> Expr.expr array + val update : Expr.expr -> Expr.expr array -> expr + val substitute : Expr.expr -> Expr.expr array -> Expr.expr array -> expr + val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr + val substitute_vars : Expr.expr -> Expr.expr array -> expr + val translate : Expr.expr -> context -> expr + val to_string : Expr.expr -> string + val is_numeral : Expr.expr -> bool + val is_well_sorted : Expr.expr -> bool + val get_sort : Expr.expr -> Sort.sort + val is_bool : Expr.expr -> bool + val is_const : Expr.expr -> bool + val is_true : Expr.expr -> bool + val is_false : Expr.expr -> bool + val is_eq : Expr.expr -> bool + val is_distinct : Expr.expr -> bool + val is_ite : Expr.expr -> bool + val is_and : Expr.expr -> bool + val is_or : Expr.expr -> bool + val is_iff : Expr.expr -> bool + val is_xor : Expr.expr -> bool + val is_not : Expr.expr -> bool + val is_implies : Expr.expr -> bool + val is_label : Expr.expr -> bool + val is_oeq : Expr.expr -> bool + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val mk_const_s : context -> string -> Sort.sort -> expr + val mk_const_f : context -> FuncDecl.func_decl -> expr + val mk_fresh_const : context -> string -> Sort.sort -> expr + val mk_app : context -> FuncDecl.func_decl -> Expr.expr array -> expr + val mk_numeral_string : context -> string -> Sort.sort -> expr + val mk_numeral_int : context -> int -> Sort.sort -> expr end module Boolean : sig + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + + val expr_of_bool_expr : bool_expr -> Expr.expr + val sort_of_bool_sort : bool_sort -> Sort.sort + val bool_sort_of_sort : Sort.sort -> bool_sort + val bool_expr_of_expr : Expr.expr -> bool_expr + val mk_sort : context -> bool_sort - val mk_const : context -> symbol -> bool_expr + val mk_const : context -> Symbol.symbol -> bool_expr val mk_const_s : context -> string -> bool_expr val mk_true : context -> bool_expr val mk_false : context -> bool_expr val mk_val : context -> bool -> bool_expr - val mk_eq : context -> expr -> expr -> bool_expr - val mk_distinct : context -> expr array -> bool_expr + val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr + val mk_distinct : context -> Expr.expr array -> bool_expr val mk_not : context -> bool_expr -> bool_expr val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr val mk_iff : context -> bool_expr -> bool_expr -> bool_expr @@ -345,482 +578,590 @@ end module Quantifier : sig + type quantifier = Quantifier of Expr.expr + + val expr_of_quantifier : quantifier -> Expr.expr + val quantifier_of_expr : Expr.expr -> quantifier + module Pattern : sig + type pattern = Pattern of AST.ast + + val ast_of_pattern : pattern -> AST.ast + val pattern_of_ast : AST.ast -> pattern + val get_num_terms : pattern -> int - val get_terms : pattern -> expr array + val get_terms : pattern -> Expr.expr array val to_string : pattern -> string end - val get_index : expr -> int + val get_index : Expr.expr -> int val is_universal : quantifier -> bool val is_existential : quantifier -> bool val get_weight : quantifier -> int val get_num_patterns : quantifier -> int - val get_patterns : quantifier -> pattern array + val get_patterns : quantifier -> Pattern.pattern array val get_num_no_patterns : quantifier -> int - val get_no_patterns : quantifier -> pattern array + val get_no_patterns : quantifier -> Pattern.pattern array val get_num_bound : quantifier -> int - val get_bound_variable_names : quantifier -> symbol array - val get_bound_variable_sorts : quantifier -> sort array - val get_body : quantifier -> bool_expr - val mk_bound : context -> int -> sort -> expr - val mk_pattern : context -> expr array -> pattern + val get_bound_variable_names : quantifier -> Symbol.symbol array + val get_bound_variable_sorts : quantifier -> Sort.sort array + val get_body : quantifier -> Boolean.bool_expr + val mk_bound : context -> int -> Sort.sort -> Expr.expr + val mk_pattern : context -> Expr.expr array -> Pattern.pattern val mk_forall : context -> - sort array -> - symbol array -> - expr -> + Sort.sort array -> + Symbol.symbol array -> + Expr.expr -> int option -> - pattern array -> - expr array -> symbol option -> symbol option -> quantifier + Pattern.pattern array -> + Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier val mk_forall_const : context -> - expr array -> - expr -> + Expr.expr array -> + Expr.expr -> int option -> - pattern array -> - expr array -> symbol option -> symbol option -> quantifier + Pattern.pattern array -> + Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier val mk_exists : context -> - sort array -> - symbol array -> - expr -> + Sort.sort array -> + Symbol.symbol array -> + Expr.expr -> int option -> - pattern array -> - expr array -> symbol option -> symbol option -> quantifier + Pattern.pattern array -> + Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier val mk_exists_const : context -> - expr array -> - expr -> + Expr.expr array -> + Expr.expr -> int option -> - pattern array -> - expr array -> symbol option -> symbol option -> quantifier + Pattern.pattern array -> + Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier val mk_quantifier : context -> bool -> - expr array -> - expr -> + Expr.expr array -> + Expr.expr -> int option -> - pattern array -> - expr array -> symbol option -> symbol option -> quantifier + Pattern.pattern array -> + Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier end module Array_ : sig - val mk_sort : context -> sort -> sort -> array_sort - val is_store : expr -> bool - val is_select : expr -> bool - val is_constant_array : expr -> bool - val is_default_array : expr -> bool - val is_array_map : expr -> bool - val is_as_array : expr -> bool - val is_array : expr -> bool - val get_domain : array_sort -> sort - val get_range : array_sort -> sort - val mk_const : context -> symbol -> sort -> sort -> array_expr - val mk_const_s : context -> string -> sort -> sort -> array_expr - val mk_select : context -> array_expr -> expr -> expr -> expr - val mk_const_array : context -> sort -> expr -> expr - val mk_map : context -> func_decl -> array_expr array -> expr - val mk_term_array : context -> array_expr -> expr + type array_sort = ArraySort of Sort.sort + type array_expr = ArrayExpr of Expr.expr + + val sort_of_array_sort : array_sort -> Sort.sort + val array_sort_of_sort : Sort.sort -> array_sort + val expr_of_array_expr : array_expr -> Expr.expr + + val array_expr_of_expr : Expr.expr -> array_expr + + val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort + val is_store : Expr.expr -> bool + val is_select : Expr.expr -> bool + val is_constant_array : Expr.expr -> bool + val is_default_array : Expr.expr -> bool + val is_array_map : Expr.expr -> bool + val is_as_array : Expr.expr -> bool + val is_array : Expr.expr -> bool + val get_domain : array_sort -> Sort.sort + val get_range : array_sort -> Sort.sort + val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr + val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr + val mk_select : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr + val mk_map : context -> FuncDecl.func_decl -> array_expr array -> array_expr + val mk_term_array : context -> array_expr -> array_expr end module Set : sig - val is_union : expr -> bool - val is_intersect : expr -> bool - val is_difference : expr -> bool - val is_complement : expr -> bool - val is_subset : expr -> bool - val mk_sort : context -> sort -> set_sort - val mk_empty : context -> sort -> expr - val mk_full : context -> sort -> expr - val mk_set_add : context -> expr -> expr -> expr - val mk_del : context -> expr -> expr -> expr - val mk_union : context -> expr array -> expr - val mk_intersection : context -> expr array -> expr - val mk_difference : context -> expr -> expr -> expr - val mk_complement : context -> expr -> expr - val mk_membership : context -> expr -> expr -> expr - val mk_subset : context -> expr -> expr -> expr + type set_sort = SetSort of Sort.sort + + val sort_of_set_sort : set_sort -> Sort.sort + + val is_union : Expr.expr -> bool + val is_intersect : Expr.expr -> bool + val is_difference : Expr.expr -> bool + val is_complement : Expr.expr -> bool + val is_subset : Expr.expr -> bool + val mk_sort : context -> Sort.sort -> set_sort + val mk_empty : context -> Sort.sort -> Expr.expr + val mk_full : context -> Sort.sort -> Expr.expr + val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr + val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr + val mk_union : context -> Expr.expr array -> Expr.expr + val mk_intersection : context -> Expr.expr array -> Expr.expr + val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr + val mk_complement : context -> Expr.expr -> Expr.expr + val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr + val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr end module FiniteDomain : sig - val mk_sort : context -> symbol -> int -> finite_domain_sort + type finite_domain_sort = FiniteDomainSort of Sort.sort + + val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort + val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort + + val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort val mk_sort_s : context -> string -> int -> finite_domain_sort - val is_finite_domain : expr -> bool - val is_lt : expr -> bool + val is_finite_domain : Expr.expr -> bool + val is_lt : Expr.expr -> bool val get_size : finite_domain_sort -> int end module Relation : sig - val is_relation : expr -> bool - val is_store : expr -> bool - val is_empty : expr -> bool - val is_is_empty : expr -> bool - val is_join : expr -> bool - val is_union : expr -> bool - val is_widen : expr -> bool - val is_project : expr -> bool - val is_filter : expr -> bool - val is_negation_filter : expr -> bool - val is_rename : expr -> bool - val is_complement : expr -> bool - val is_select : expr -> bool - val is_clone : expr -> bool + type relation_sort = RelationSort of Sort.sort + + val sort_of_relation_sort : relation_sort -> Sort.sort + val relation_sort_of_sort : Sort.sort -> relation_sort + + val is_relation : Expr.expr -> bool + val is_store : Expr.expr -> bool + val is_empty : Expr.expr -> bool + val is_is_empty : Expr.expr -> bool + val is_join : Expr.expr -> bool + val is_union : Expr.expr -> bool + val is_widen : Expr.expr -> bool + val is_project : Expr.expr -> bool + val is_filter : Expr.expr -> bool + val is_negation_filter : Expr.expr -> bool + val is_rename : Expr.expr -> bool + val is_complement : Expr.expr -> bool + val is_select : Expr.expr -> bool + val is_clone : Expr.expr -> bool val get_arity : relation_sort -> int val get_column_sorts : relation_sort -> relation_sort array end module Datatype : sig + type datatype_sort = DatatypeSort of Sort.sort + type datatype_expr = DatatypeExpr of Expr.expr + + val sort_of_datatype_sort : datatype_sort -> Sort.sort + val datatype_sort_of_sort : Sort.sort -> datatype_sort + val expr_of_datatype_expr : datatype_expr -> Expr.expr + val datatype_expr_of_expr : Expr.expr -> datatype_expr module Constructor : sig + (** Constructors *) + type constructor + val get_n : constructor -> int - val constructor_decl : constructor -> func_decl - val tester_decl : constructor -> func_decl - val accessor_decls : constructor -> func_decl array + val constructor_decl : constructor -> FuncDecl.func_decl + val tester_decl : constructor -> FuncDecl.func_decl + val accessor_decls : constructor -> FuncDecl.func_decl array val get_num_fields : constructor -> int - val get_constructor_decl : constructor -> func_decl - val get_tester_decl : constructor -> func_decl - val get_accessor_decls : constructor -> func_decl array + val get_constructor_decl : constructor -> FuncDecl.func_decl + val get_tester_decl : constructor -> FuncDecl.func_decl + val get_accessor_decls : constructor -> FuncDecl.func_decl array end - val mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - val mk_constructor_s : context -> string -> symbol -> symbol array -> sort array -> int array -> constructor - val mk_sort : context -> symbol -> constructor array -> datatype_sort - val mk_sort_s : context -> string -> constructor array -> datatype_sort - val mk_sorts : context -> symbol array -> constructor array array -> datatype_sort array - val mk_sorts_s : context -> string array -> constructor array array -> datatype_sort array + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + val mk_sort : context -> Symbol.symbol -> Constructor.constructor array -> datatype_sort + val mk_sort_s : context -> string -> Constructor.constructor array -> datatype_sort + val mk_sorts : context -> Symbol.symbol array -> Constructor.constructor array array -> datatype_sort array + val mk_sorts_s : context -> string array -> Constructor.constructor array array -> datatype_sort array val get_num_constructors : datatype_sort -> int - val get_constructors : datatype_sort -> func_decl array - val get_recognizers : datatype_sort -> func_decl array - val get_accessors : datatype_sort -> func_decl array array + val get_constructors : datatype_sort -> FuncDecl.func_decl array + val get_recognizers : datatype_sort -> FuncDecl.func_decl array + val get_accessors : datatype_sort -> FuncDecl.func_decl array array end module Enumeration : sig - val mk_sort : context -> symbol -> symbol array -> enum_sort + type enum_sort = EnumSort of Sort.sort + + val sort_of_enum_sort : enum_sort -> Sort.sort + + val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> enum_sort val mk_sort_s : context -> string -> string array -> enum_sort - val get_const_decls : enum_sort -> func_decl array - val get_tester_decls : enum_sort -> func_decl array + val get_const_decls : enum_sort -> FuncDecl.func_decl array + val get_tester_decls : enum_sort -> FuncDecl.func_decl array end module List_ : sig - val mk_sort : context -> symbol -> sort -> list_sort - val mk_list_s : context -> string -> sort -> list_sort - val get_nil_decl : list_sort -> func_decl - val get_is_nil_decl : list_sort -> func_decl - val get_cons_decl : list_sort -> func_decl - val get_is_cons_decl : list_sort -> func_decl - val get_head_decl : list_sort -> func_decl - val get_tail_decl : list_sort -> func_decl - val nil : list_sort -> expr + type list_sort = ListSort of Sort.sort + + val sort_of_list_sort : list_sort -> Sort.sort + + val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort + val mk_list_s : context -> string -> Sort.sort -> list_sort + val get_nil_decl : list_sort -> FuncDecl.func_decl + val get_is_nil_decl : list_sort -> FuncDecl.func_decl + val get_cons_decl : list_sort -> FuncDecl.func_decl + val get_is_cons_decl : list_sort -> FuncDecl.func_decl + val get_head_decl : list_sort -> FuncDecl.func_decl + val get_tail_decl : list_sort -> FuncDecl.func_decl + val nil : list_sort -> Expr.expr end module Tuple : sig - val mk_sort : - context -> symbol -> symbol array -> sort array -> tuple_sort - val get_mk_decl : tuple_sort -> func_decl + type tuple_sort = TupleSort of Sort.sort + + val sort_of_tuple_sort : tuple_sort -> Sort.sort + + val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> tuple_sort + val get_mk_decl : tuple_sort -> FuncDecl.func_decl val get_num_fields : tuple_sort -> int - val get_field_decls : tuple_sort -> func_decl array + val get_field_decls : tuple_sort -> FuncDecl.func_decl array end -module Arithmetic : +module rec Arithmetic : sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr - module Integer : + val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort + val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr + + module rec Integer : sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort + val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort + val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr + val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr + val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr + val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num + val mk_sort : context -> int_sort val get_int : int_num -> int val to_string : int_num -> string - val mk_int_const : context -> symbol -> int_expr + val mk_int_const : context -> Symbol.symbol -> int_expr val mk_int_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> expr - val mk_rem : context -> int_expr -> int_expr -> expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr val mk_int_numeral_s : context -> string -> int_num val mk_int_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> real_expr - val mk_int2bv : context -> int -> int_expr -> bitvec_expr + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end - module Real : + and Real : sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + val mk_sort : context -> real_sort - val get_numerator : rat_num -> int_num - val get_denominator : rat_num -> int_num + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num val to_decimal_string : rat_num -> int -> string val to_string : rat_num -> string - val mk_real_const : context -> symbol -> real_expr + val mk_real_const : context -> Symbol.symbol -> real_expr val mk_real_const_s : context -> string -> real_expr val mk_numeral_nd : context -> int -> int -> rat_num val mk_numeral_s : context -> string -> rat_num val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> bool_expr - val mk_real2int : context -> real_expr -> int_expr + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr end - module AlgebraicNumber : + and AlgebraicNumber : sig - val to_upper : algebraic_num -> int -> rat_num - val to_lower : algebraic_num -> int -> rat_num + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr + val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num val to_decimal_string : algebraic_num -> int -> string val to_string : algebraic_num -> string end - val is_int : expr -> bool - val is_arithmetic_numeral : expr -> bool - val is_le : expr -> bool - val is_ge : expr -> bool - val is_lt : expr -> bool - val is_gt : expr -> bool - val is_add : expr -> bool - val is_sub : expr -> bool - val is_uminus : expr -> bool - val is_mul : expr -> bool - val is_div : expr -> bool - val is_idiv : expr -> bool - val is_remainder : expr -> bool - val is_modulus : expr -> bool - val is_inttoreal : expr -> bool - val is_real_to_int : expr -> bool - val is_real_is_int : expr -> bool - val is_real : expr -> bool - val is_int_numeral : expr -> bool - val is_rat_num : expr -> bool - val is_algebraic_number : expr -> bool + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool val mk_add : context -> arith_expr array -> arith_expr val mk_mul : context -> arith_expr array -> arith_expr val mk_sub : context -> arith_expr array -> arith_expr val mk_unary_minus : context -> arith_expr -> arith_expr val mk_div : context -> arith_expr -> arith_expr -> arith_expr val mk_power : context -> arith_expr -> arith_expr -> arith_expr - val mk_lt : context -> arith_expr -> arith_expr -> bool_expr - val mk_le : context -> arith_expr -> arith_expr -> bool_expr - val mk_gt : context -> arith_expr -> arith_expr -> bool_expr - val mk_ge : context -> arith_expr -> arith_expr -> bool_expr + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr end -module BitVector : +and BitVector : sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + val mk_sort : context -> int -> bitvec_sort - val is_bv : expr -> bool - val is_bv_numeral : expr -> bool - val is_bv_bit1 : expr -> bool - val is_bv_bit0 : expr -> bool - val is_bv_uminus : expr -> bool - val is_bv_add : expr -> bool - val is_bv_sub : expr -> bool - val is_bv_mul : expr -> bool - val is_bv_sdiv : expr -> bool - val is_bv_udiv : expr -> bool - val is_bv_SRem : expr -> bool - val is_bv_urem : expr -> bool - val is_bv_smod : expr -> bool - val is_bv_sdiv0 : expr -> bool - val is_bv_udiv0 : expr -> bool - val is_bv_srem0 : expr -> bool - val is_bv_urem0 : expr -> bool - val is_bv_smod0 : expr -> bool - val is_bv_ule : expr -> bool - val is_bv_sle : expr -> bool - val is_bv_uge : expr -> bool - val is_bv_sge : expr -> bool - val is_bv_ult : expr -> bool - val is_bv_slt : expr -> bool - val is_bv_ugt : expr -> bool - val is_bv_sgt : expr -> bool - val is_bv_and : expr -> bool - val is_bv_or : expr -> bool - val is_bv_not : expr -> bool - val is_bv_xor : expr -> bool - val is_bv_nand : expr -> bool - val is_bv_nor : expr -> bool - val is_bv_xnor : expr -> bool - val is_bv_concat : expr -> bool - val is_bv_signextension : expr -> bool - val is_bv_zeroextension : expr -> bool - val is_bv_extract : expr -> bool - val is_bv_repeat : expr -> bool - val is_bv_reduceor : expr -> bool - val is_bv_reduceand : expr -> bool - val is_bv_comp : expr -> bool - val is_bv_shiftleft : expr -> bool - val is_bv_shiftrightlogical : expr -> bool - val is_bv_shiftrightarithmetic : expr -> bool - val is_bv_rotateleft : expr -> bool - val is_bv_rotateright : expr -> bool - val is_bv_rotateleftextended : expr -> bool - val is_bv_rotaterightextended : expr -> bool - val is_int_to_bv : expr -> bool - val is_bv_to_int : expr -> bool - val is_bv_carry : expr -> bool - val is_bv_xor3 : expr -> bool + val is_bv : Expr.expr -> bool + val is_bv_numeral : Expr.expr -> bool + val is_bv_bit1 : Expr.expr -> bool + val is_bv_bit0 : Expr.expr -> bool + val is_bv_uminus : Expr.expr -> bool + val is_bv_add : Expr.expr -> bool + val is_bv_sub : Expr.expr -> bool + val is_bv_mul : Expr.expr -> bool + val is_bv_sdiv : Expr.expr -> bool + val is_bv_udiv : Expr.expr -> bool + val is_bv_SRem : Expr.expr -> bool + val is_bv_urem : Expr.expr -> bool + val is_bv_smod : Expr.expr -> bool + val is_bv_sdiv0 : Expr.expr -> bool + val is_bv_udiv0 : Expr.expr -> bool + val is_bv_srem0 : Expr.expr -> bool + val is_bv_urem0 : Expr.expr -> bool + val is_bv_smod0 : Expr.expr -> bool + val is_bv_ule : Expr.expr -> bool + val is_bv_sle : Expr.expr -> bool + val is_bv_uge : Expr.expr -> bool + val is_bv_sge : Expr.expr -> bool + val is_bv_ult : Expr.expr -> bool + val is_bv_slt : Expr.expr -> bool + val is_bv_ugt : Expr.expr -> bool + val is_bv_sgt : Expr.expr -> bool + val is_bv_and : Expr.expr -> bool + val is_bv_or : Expr.expr -> bool + val is_bv_not : Expr.expr -> bool + val is_bv_xor : Expr.expr -> bool + val is_bv_nand : Expr.expr -> bool + val is_bv_nor : Expr.expr -> bool + val is_bv_xnor : Expr.expr -> bool + val is_bv_concat : Expr.expr -> bool + val is_bv_signextension : Expr.expr -> bool + val is_bv_zeroextension : Expr.expr -> bool + val is_bv_extract : Expr.expr -> bool + val is_bv_repeat : Expr.expr -> bool + val is_bv_reduceor : Expr.expr -> bool + val is_bv_reduceand : Expr.expr -> bool + val is_bv_comp : Expr.expr -> bool + val is_bv_shiftleft : Expr.expr -> bool + val is_bv_shiftrightlogical : Expr.expr -> bool + val is_bv_shiftrightarithmetic : Expr.expr -> bool + val is_bv_rotateleft : Expr.expr -> bool + val is_bv_rotateright : Expr.expr -> bool + val is_bv_rotateleftextended : Expr.expr -> bool + val is_bv_rotaterightextended : Expr.expr -> bool + val is_int_to_bv : Expr.expr -> bool + val is_bv_to_int : Expr.expr -> bool + val is_bv_carry : Expr.expr -> bool + val is_bv_xor3 : Expr.expr -> bool val get_size : bitvec_sort -> int val get_int : bitvec_num -> int val to_string : bitvec_num -> string - val mk_const : context -> symbol -> int -> bitvec_expr + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr val mk_const_s : context -> string -> int -> bitvec_expr - val mk_not : context -> bitvec_expr -> expr - val mk_redand : context -> bitvec_expr -> expr - val mk_redor : context -> bitvec_expr -> expr - val mk_and : context -> bitvec_expr -> bitvec_expr -> expr - val mk_or : context -> bitvec_expr -> bitvec_expr -> expr - val mk_xor : context -> bitvec_expr -> bitvec_expr -> expr - val mk_nand : context -> bitvec_expr -> bitvec_expr -> expr - val mk_nor : context -> bitvec_expr -> bitvec_expr -> expr - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> expr - val mk_neg : context -> bitvec_expr -> expr - val mk_add : context -> bitvec_expr -> bitvec_expr -> expr - val mk_sub : context -> bitvec_expr -> bitvec_expr -> expr - val mk_mul : context -> bitvec_expr -> bitvec_expr -> expr - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> expr - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> expr - val mk_urem : context -> bitvec_expr -> bitvec_expr -> expr - val mk_srem : context -> bitvec_expr -> bitvec_expr -> expr - val mk_smod : context -> bitvec_expr -> bitvec_expr -> expr - val mk_ult : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_slt : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_ule : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_sle : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_uge : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_sge : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_concat : context -> bitvec_expr -> bitvec_expr -> expr - val mk_extract : context -> int -> int -> bitvec_expr -> expr - val mk_sign_ext : context -> int -> bitvec_expr -> expr - val mk_zero_ext : context -> int -> bitvec_expr -> expr - val mk_repeat : context -> int -> bitvec_expr -> expr - val mk_shl : context -> bitvec_expr -> bitvec_expr -> expr - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> expr - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> expr - val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> expr - val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> expr - val mk_bv2int : context -> bitvec_expr -> bool -> int_expr - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool_expr - val mk_neg_no_overflow : context -> bitvec_expr -> bool_expr - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> bool_expr - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool_expr + val mk_not : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr val mk_numeral : context -> string -> int -> bitvec_num end module Proof : sig - val is_true : expr -> bool - val is_asserted : expr -> bool - val is_goal : expr -> bool - val is_modus_ponens : expr -> bool - val is_reflexivity : expr -> bool - val is_symmetry : expr -> bool - val is_transitivity : expr -> bool - val is_Transitivity_star : expr -> bool - val is_monotonicity : expr -> bool - val is_quant_intro : expr -> bool - val is_distributivity : expr -> bool - val is_and_elimination : expr -> bool - val is_or_elimination : expr -> bool - val is_rewrite : expr -> bool - val is_rewrite_star : expr -> bool - val is_pull_quant : expr -> bool - val is_pull_quant_star : expr -> bool - val is_push_quant : expr -> bool - val is_elim_unused_vars : expr -> bool - val is_der : expr -> bool - val is_quant_inst : expr -> bool - val is_hypothesis : expr -> bool - val is_lemma : expr -> bool - val is_unit_resolution : expr -> bool - val is_iff_true : expr -> bool - val is_iff_false : expr -> bool - val is_commutativity : expr -> bool - val is_def_axiom : expr -> bool - val is_def_intro : expr -> bool - val is_apply_def : expr -> bool - val is_iff_oeq : expr -> bool - val is_nnf_pos : expr -> bool - val is_nnf_neg : expr -> bool - val is_nnf_star : expr -> bool - val is_cnf_star : expr -> bool - val is_skolemize : expr -> bool - val is_modus_ponens_oeq : expr -> bool - val is_theory_lemma : expr -> bool + val is_true : Expr.expr -> bool + val is_asserted : Expr.expr -> bool + val is_goal : Expr.expr -> bool + val is_modus_ponens : Expr.expr -> bool + val is_reflexivity : Expr.expr -> bool + val is_symmetry : Expr.expr -> bool + val is_transitivity : Expr.expr -> bool + val is_Transitivity_star : Expr.expr -> bool + val is_monotonicity : Expr.expr -> bool + val is_quant_intro : Expr.expr -> bool + val is_distributivity : Expr.expr -> bool + val is_and_elimination : Expr.expr -> bool + val is_or_elimination : Expr.expr -> bool + val is_rewrite : Expr.expr -> bool + val is_rewrite_star : Expr.expr -> bool + val is_pull_quant : Expr.expr -> bool + val is_pull_quant_star : Expr.expr -> bool + val is_push_quant : Expr.expr -> bool + val is_elim_unused_vars : Expr.expr -> bool + val is_der : Expr.expr -> bool + val is_quant_inst : Expr.expr -> bool + val is_hypothesis : Expr.expr -> bool + val is_lemma : Expr.expr -> bool + val is_unit_resolution : Expr.expr -> bool + val is_iff_true : Expr.expr -> bool + val is_iff_false : Expr.expr -> bool + val is_commutativity : Expr.expr -> bool + val is_def_axiom : Expr.expr -> bool + val is_def_intro : Expr.expr -> bool + val is_apply_def : Expr.expr -> bool + val is_iff_oeq : Expr.expr -> bool + val is_nnf_pos : Expr.expr -> bool + val is_nnf_neg : Expr.expr -> bool + val is_nnf_star : Expr.expr -> bool + val is_cnf_star : Expr.expr -> bool + val is_skolemize : Expr.expr -> bool + val is_modus_ponens_oeq : Expr.expr -> bool + val is_theory_lemma : Expr.expr -> bool end + module Goal : sig + type goal + val get_precision : goal -> Z3enums.goal_prec val is_precise : goal -> bool val is_underapproximation : goal -> bool val is_overapproximation : goal -> bool val is_garbage : goal -> bool - val assert_ : goal -> bool_expr array -> unit + val assert_ : goal -> Boolean.bool_expr array -> unit val is_inconsistent : goal -> bool val get_depth : goal -> int val reset : goal -> unit val get_size : goal -> int - val get_formulas : goal -> bool_expr array + val get_formulas : goal -> Boolean.bool_expr array val get_num_exprs : goal -> int val is_decided_sat : goal -> bool val is_decided_unsat : goal -> bool val translate : goal -> context -> goal - val simplify : goal -> params option -> goal + val simplify : goal -> Params.params option -> goal val mk_goal : context -> bool -> bool -> bool -> goal val to_string : goal -> string end module Model : sig + type model module FuncInterp : sig - + type func_interp + module FuncEntry : sig - val get_value : func_entry -> expr + type func_entry + + val get_value : func_entry -> Expr.expr val get_num_args : func_entry -> int - val get_args : func_entry -> expr array + val get_args : func_entry -> Expr.expr array val to_string : func_entry -> string end val get_num_entries : func_interp -> int - val get_entries : func_interp -> func_entry array - val get_else : func_interp -> expr + val get_entries : func_interp -> FuncEntry.func_entry array + val get_else : func_interp -> Expr.expr val get_arity : func_interp -> int val to_string : func_interp -> string end - val get_const_interp : model -> func_decl -> expr option - val get_const_interp_e : model -> expr -> expr option - val get_func_interp : model -> func_decl -> func_interp option + val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option + val get_const_interp_e : model -> Expr.expr -> Expr.expr option + val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option val get_num_consts : model -> int - val get_const_decls : model -> func_decl array + val get_const_decls : model -> FuncDecl.func_decl array val get_num_funcs : model -> int - val get_func_decls : model -> func_decl array - val get_decls : model -> func_decl array + val get_func_decls : model -> FuncDecl.func_decl array + val get_decls : model -> FuncDecl.func_decl array exception ModelEvaluationFailedException of string - val eval : model -> expr -> bool -> expr - val evaluate : model -> expr -> bool -> expr + val eval : model -> Expr.expr -> bool -> Expr.expr + val evaluate : model -> Expr.expr -> bool -> Expr.expr val get_num_sorts : model -> int - val get_sorts : model -> sort array - val sort_universe : model -> sort -> ast_vector array + val get_sorts : model -> Sort.sort array + val sort_universe : model -> Sort.sort -> AST.ASTVector.ast_vector array val to_string : model -> string end module Probe : sig - val apply : probe -> goal -> float + type probe + + val apply : probe -> Goal.goal -> float val get_num_probes : context -> int val get_probe_names : context -> string array val get_probe_description : context -> string -> string @@ -838,19 +1179,22 @@ end module Tactic : sig + type tactic module ApplyResult : sig + type apply_result + val get_num_subgoals : apply_result -> int - val get_subgoals : apply_result -> goal array - val get_subgoal : apply_result -> int -> goal - val convert_model : apply_result -> int -> model -> model + val get_subgoals : apply_result -> Goal.goal array + val get_subgoal : apply_result -> int -> Goal.goal + val convert_model : apply_result -> int -> Model.model -> Model.model val to_string : apply_result -> string end val get_help : tactic -> string - val get_param_descrs : tactic -> param_descrs - val apply : tactic -> goal -> params option -> apply_result + val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs + val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result val get_num_tactics : context -> int val get_tactic_names : context -> string array val get_tactic_description : context -> string -> string @@ -858,15 +1202,15 @@ sig val and_then : context -> tactic -> tactic -> tactic array -> tactic val or_else : context -> tactic -> tactic -> tactic val try_for : context -> tactic -> int -> tactic - val when_ : context -> probe -> tactic -> tactic - val cond : context -> probe -> tactic -> tactic -> tactic + val when_ : context -> Probe.probe -> tactic -> tactic + val cond : context -> Probe.probe -> tactic -> tactic -> tactic val repeat : context -> tactic -> int -> tactic val skip : context -> tactic val fail : context -> tactic - val fail_if : context -> probe -> tactic + val fail_if : context -> Probe.probe -> tactic val fail_if_not_decided : context -> tactic - val using_params : context -> tactic -> params -> tactic - val with_ : context -> tactic -> params -> tactic + val using_params : context -> tactic -> Params.params -> tactic + val with_ : context -> tactic -> Params.params -> tactic val par_or : context -> tactic array -> tactic val par_and_then : context -> tactic -> tactic -> tactic val interrupt : context -> unit @@ -874,13 +1218,19 @@ end module Solver : sig + type solver + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + val string_of_status : status -> string module Statistics : sig + type statistics module Entry : sig + type statistics_entry + val get_key : statistics_entry -> string val get_int : statistics_entry -> int val get_float : statistics_entry -> float @@ -892,59 +1242,61 @@ sig val to_string : statistics -> string val get_size : statistics -> int - val get_entries : statistics -> statistics_entry array + val get_entries : statistics -> Entry.statistics_entry array val get_keys : statistics -> string array - val get : statistics -> string -> statistics_entry option + val get : statistics -> string -> Entry.statistics_entry option end val get_help : solver -> string - val set_parameters : solver -> params -> unit - val get_param_descrs : solver -> param_descrs + val set_parameters : solver -> Params.params -> unit + val get_param_descrs : solver -> Params.ParamDescrs.param_descrs val get_num_scopes : solver -> int val push : solver -> unit val pop : solver -> int -> unit val reset : solver -> unit - val assert_ : solver -> bool_expr array -> unit - val assert_and_track : solver -> bool_expr -> bool_expr -> unit + val assert_ : solver -> Boolean.bool_expr array -> unit + val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit val get_num_assertions : solver -> int - val get_assertions : solver -> bool_expr array - val check : solver -> bool_expr array -> status - val get_model : solver -> model option - val get_proof : solver -> expr option - val get_unsat_core : solver -> ast_vector array + val get_assertions : solver -> Boolean.bool_expr array + val check : solver -> Boolean.bool_expr array -> status + val get_model : solver -> Model.model option + val get_proof : solver -> Expr.expr option + val get_unsat_core : solver -> AST.ASTVector.ast_vector array val get_reason_unknown : solver -> string - val get_statistics : solver -> statistics - val mk_solver : context -> symbol option -> solver + val get_statistics : solver -> Statistics.statistics + val mk_solver : context -> Symbol.symbol option -> solver val mk_solver_s : context -> string -> solver val mk_simple_solver : context -> solver - val mk_solver_t : context -> tactic -> solver + val mk_solver_t : context -> Tactic.tactic -> solver val to_string : solver -> string end module Fixedpoint : sig + type fixedpoint + val get_help : fixedpoint -> string - val set_params : fixedpoint -> params -> unit - val get_param_descrs : fixedpoint -> param_descrs - val assert_ : fixedpoint -> bool_expr array -> unit - val register_relation : fixedpoint -> func_decl -> unit - val add_rule : fixedpoint -> bool_expr -> symbol option -> unit - val add_fact : fixedpoint -> func_decl -> int array -> unit - val query : fixedpoint -> bool_expr -> status - val query_r : fixedpoint -> func_decl array -> status + val set_params : fixedpoint -> Params.params -> unit + val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs + val assert_ : fixedpoint -> Boolean.bool_expr array -> unit + val register_relation : fixedpoint -> FuncDecl.func_decl -> unit + val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit + val add_fact : fixedpoint -> FuncDecl.func_decl -> int array -> unit + val query : fixedpoint -> Boolean.bool_expr -> Solver.status + val query_r : fixedpoint -> FuncDecl.func_decl array -> Solver.status val push : fixedpoint -> unit val pop : fixedpoint -> unit - val update_rule : fixedpoint -> bool_expr -> symbol -> unit - val get_answer : fixedpoint -> expr option + val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit + val get_answer : fixedpoint -> Expr.expr option val get_reason_unknown : fixedpoint -> string - val get_num_levels : fixedpoint -> func_decl -> int - val get_cover_delta : fixedpoint -> int -> func_decl -> expr option - val add_cover : fixedpoint -> int -> func_decl -> expr -> unit + val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int + val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option + val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit val to_string : fixedpoint -> string - val set_predicate_representation : fixedpoint -> func_decl -> symbol array -> unit - val to_string_q : fixedpoint -> bool_expr array -> string - val get_rules : fixedpoint -> bool_expr array - val get_assertions : fixedpoint -> bool_expr array + val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol array -> unit + val to_string_q : fixedpoint -> Boolean.bool_expr array -> string + val get_rules : fixedpoint -> Boolean.bool_expr array + val get_assertions : fixedpoint -> Boolean.bool_expr array val mk_fixedpoint : context -> fixedpoint end @@ -958,19 +1310,19 @@ end module SMT : sig - val benchmark_to_smtstring : context -> string -> string -> string -> string -> bool_expr array -> bool_expr -> string - val parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - val parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr array -> Boolean.bool_expr -> string + val parse_smtlib_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit + val parse_smtlib_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit val get_num_smtlib_formulas : context -> int - val get_smtlib_formulas : context -> bool_expr array + val get_smtlib_formulas : context -> Boolean.bool_expr array val get_num_smtlib_assumptions : context -> int - val get_smtlib_assumptions : context -> bool_expr array + val get_smtlib_assumptions : context -> Boolean.bool_expr array val get_num_smtlib_decls : context -> int - val get_smtlib_decls : context -> func_decl array + val get_smtlib_decls : context -> FuncDecl.func_decl array val get_num_smtlib_sorts : context -> int - val get_smtlib_sorts : context -> sort array - val parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> bool_expr - val parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> bool_expr + val get_smtlib_sorts : context -> Sort.sort array + val parse_smtlib2_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr + val parse_smtlib2_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr end val set_global_param : string -> string -> unit From dc03e2903f619d1191b143c62c84e8ce9f092c57 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 19:49:09 +0000 Subject: [PATCH 426/646] ML API: proper use of datatype API for list/enum/constructor. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/Makefile | 2 +- src/api/ml/z3.ml | 47 ++++++++++++++++++++------------------------- src/api/ml/z3.mli | 7 +++++-- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile index abcefa4af..96fd0a55d 100644 --- a/src/api/ml/Makefile +++ b/src/api/ml/Makefile @@ -7,4 +7,4 @@ all: doc: *.ml mkdir -p doc - ocamldoc -html -d doc -I ../../../bld_dbg/api/ml -sort *.mli -hide Z3 + ocamldoc -html -d doc -I _build -sort *.mli -hide Z3 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c261fce05..344e542f7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2159,15 +2159,10 @@ end module Enumeration = struct type enum_sort = EnumSort of sort - - let _constdecls = Hashtbl.create 0 - let _testerdecls = Hashtbl.create 0 let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in - Hashtbl.add _constdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f cdecls)) ; - Hashtbl.add _testerdecls res (let f e = func_decl_of_ptr ctx e in (Array.map f tdecls)) ; res let sort_of_enum_sort s = match s with EnumSort(x) -> x @@ -2191,33 +2186,27 @@ struct mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) (** The function declarations of the constants in the enumeration. *) - let get_const_decls ( x : enum_sort ) = Hashtbl.find _constdecls x + let get_const_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + Array.init n f (** The test predicates for the constants in the enumeration. *) - let get_tester_decls ( x : enum_sort ) = Hashtbl.find _testerdecls x + let get_tester_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + Array.init n f + end (** Functions to manipulate List expressions *) module List_ = struct type list_sort = ListSort of sort - - let _nildecls = Hashtbl.create 0 - let _is_nildecls = Hashtbl.create 0 - let _consdecls = Hashtbl.create 0 - let _is_consdecls = Hashtbl.create 0 - let _headdecls = Hashtbl.create 0 - let _taildecls = Hashtbl.create 0 let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = let s = (sort_of_ptr ctx no) in let res = ListSort(s) in - Hashtbl.add _nildecls res (func_decl_of_ptr ctx nildecl) ; - Hashtbl.add _is_nildecls res (func_decl_of_ptr ctx is_nildecl) ; - Hashtbl.add _consdecls res (func_decl_of_ptr ctx consdecl) ; - Hashtbl.add _is_consdecls res (func_decl_of_ptr ctx is_consdecl) ; - Hashtbl.add _headdecls res (func_decl_of_ptr ctx headdecl) ; - Hashtbl.add _taildecls res (func_decl_of_ptr ctx taildecl) ; res let sort_of_list_sort s = match s with ListSort(x) -> x @@ -2237,22 +2226,28 @@ struct mk_sort ctx (Symbol.mk_string ctx name) elem_sort (** The declaration of the nil function of this list sort. *) - let get_nil_decl ( x : list_sort ) = (Hashtbl.find _nildecls x) + let get_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) (** The declaration of the isNil function of this list sort. *) - let get_is_nil_decl ( x : list_sort ) = (Hashtbl.find _is_nildecls x) + let get_is_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) (** The declaration of the cons function of this list sort. *) - let get_cons_decl ( x : list_sort ) = (Hashtbl.find _consdecls x) + let get_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) (** The declaration of the isCons function of this list sort. *) - let get_is_cons_decl ( x : list_sort ) = (Hashtbl.find _is_consdecls x) + let get_is_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) (** The declaration of the head function of this list sort. *) - let get_head_decl ( x : list_sort ) = (Hashtbl.find _headdecls x) + let get_head_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) (** The declaration of the tail function of this list sort. *) - let get_tail_decl ( x : list_sort ) = (Hashtbl.find _taildecls x) + let get_tail_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) (** The empty list. *) let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 5b1b2073a..87318d2a7 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -5,9 +5,9 @@ @author CM Wintersteiger (cwinter) 2012-12-17 *) -type context -(** Create a context object. + +(** Context objects. Most interactions with Z3 are interpreted in some context; many users will only require one such object, but power users may require more than one. To start using @@ -27,6 +27,9 @@ type context (...) *) +type context + +(** Create a context object *) val mk_context : (string * string) list -> context From 303b4e6735246634bcb3f76aa25e687c8c8e2b44 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 20 Feb 2013 22:07:18 +0000 Subject: [PATCH 427/646] ML API savepoint Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2595 +-------------------------------------------- src/api/ml/z3.mli | 2049 ++++++++++++++++++++++++++++++++--- 2 files changed, 1942 insertions(+), 2702 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 344e542f7..b1e40fcac 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -338,7 +338,7 @@ struct else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - let wrap ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr + let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr let unwrap_ast ( x : ast ) = (z3obj_gno x) end @@ -744,6 +744,7 @@ sig val is_not : expr -> bool val is_implies : expr -> bool val is_label : expr -> bool + val is_label_lit : expr -> bool val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr @@ -794,257 +795,97 @@ end = struct let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in expr_of_ptr ctx o - (** - Returns a simplified version of the expression. - @param p A set of parameters to configure the simplifier - - *) let simplify ( x : expr ) ( p : Params.params option ) = match p with | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) - (** - a string describing all available parameters to Expr.Simplify. - *) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) - (** - Retrieves parameter descriptions for simplifier. - *) let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - - (** - The function declaration of the function that is applied in this expression. - *) let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the expression is the true or false expression - or something else (L_UNDEF). - *) let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) - (** - The number of arguments of the expression. - *) let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) - (** - The arguments of the expression. - *) let get_args ( x : expr ) = let n = (get_num_args x) in let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in Array.init n f - (** - Update the arguments of the expression using the arguments - The number of new arguments should coincide with the current number of arguments. - *) let update ( x : expr ) args = if (Array.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) - (** - Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. - - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. - *) let substitute ( x : expr ) from to_ = if (Array.length from) <> (Array.length to_) then raise (Z3native.Exception "Argument sizes do not match") else expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) - (** - Substitute every occurrence of from in the expression with to. - - *) let substitute_one ( x : expr ) from to_ = substitute ( x : expr ) [| from |] [| to_ |] - (** - Substitute the free variables in the expression with the expressions in - - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. - *) let substitute_vars ( x : expr ) to_ = expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) - (** - Translates (copies) the term to the Context . - @param ctx A context - @return A copy of the term which is associated with - *) let translate ( x : expr ) to_ctx = if (c_of_expr x) == to_ctx then x else expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) - (** - Returns a string representation of the expression. - *) let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) - (** - Indicates whether the term is a numeral - *) let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. - *) let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) - (** - The Sort of the term. - *) let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) - (** - Indicates whether the term has Boolean sort. - *) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (Z3native.is_eq_sort (nc_of_expr x) (Z3native.mk_bool_sort (nc_of_expr x)) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) - (** - Indicates whether the term represents a constant. - *) let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - - (** - Indicates whether the term is the constant true. - *) + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - - (** - Indicates whether the term is the constant false. - *) let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - - (** - Indicates whether the term is an equality predicate. - *) let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - - (** - Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). - *) let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - - (** - Indicates whether the term is a ternary if-then-else term - *) let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - - (** - Indicates whether the term is an n-ary conjunction - *) let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - - (** - Indicates whether the term is an n-ary disjunction - *) let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - - (** - Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) - *) let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - - (** - Indicates whether the term is an exclusive or - *) let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - - (** - Indicates whether the term is a negation - *) let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - - (** - Indicates whether the term is an implication - *) let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - - (** - Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. - *) let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - - (** - Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) - *) - - (** - Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. - *) + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - (** - Creates a new Constant of sort and named . - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) - - (** - Creates a new Constant of sort and named . - *) let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range - - (** - Creates a constant from the func_decl . - @param f An expression of a 0-arity function - *) let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] - (** - Creates a fresh constant of sort and a - name prefixed with . - *) let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - (** - Create a new function application. - *) let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args - (** - Create a numeral of a given sort. - @param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. - @return A Term with value and sort - *) let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) - (** - Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @param v Value of the numeral - @param ty Sort of the numeral - @return A Term with value and type - *) let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) end @@ -1052,7 +893,6 @@ end open FuncDecl open Expr -(** Boolean expressions *) module Boolean = struct type bool_sort = BoolSort of Sort.sort @@ -1091,97 +931,53 @@ struct let mk_sort ( ctx : context ) = BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) - (** - Create a Boolean constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = let s = (match (mk_sort ctx) with BoolSort(q) -> q) in BoolExpr(Expr.mk_const ctx name s) - (** - Create a Boolean constant. - *) let mk_const_s ( ctx : context ) ( name : string ) = mk_const ctx (Symbol.mk_string ctx name) - (** - The true Term. - *) let mk_true ( ctx : context ) = bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) - (** - The false Term. - *) let mk_false ( ctx : context ) = bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) - (** - Creates a Boolean value. - *) let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx - (** - Creates the equality = . - *) let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) - (** - Creates a distinct term. - *) let mk_distinct ( ctx : context ) ( args : expr array ) = bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Mk an expression representing not(a). - *) let mk_not ( ctx : context ) ( a : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - (** - Create an expression representing an if-then-else: ite(t1, t2, t3). - @param t1 An expression with Boolean sort - @param t2 An expression - @param t3 An expression with the same sort as - *) let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - (** - Create an expression representing t1 iff t2. - *) let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing t1 -> t2. - *) let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing t1 xor t2. - *) + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - (** - Create an expression representing the AND of args - *) let mk_and ( ctx : context ) ( args : bool_expr array ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) - (** - Create an expression representing the OR of args - *) let mk_or ( ctx : context ) ( args : bool_expr array ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) end -(** Quantifier expressions *) + module Quantifier = struct type quantifier = Quantifier of expr @@ -1200,12 +996,6 @@ struct let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. - *) module Pattern = struct type pattern = Pattern of ast @@ -1220,155 +1010,68 @@ struct let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - (** - The number of terms in the pattern. - *) let get_num_terms ( x : pattern ) = Z3native.get_pattern_num_terms (gnc x) (gno x) - (** - The terms in the pattern. - *) let get_terms ( x : pattern ) = let n = (get_num_terms x) in let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in Array.init n f - (** - A string representation of the pattern. - *) let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) end - (** - The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. - *) let get_index ( x : expr ) = if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) - (** - Indicates whether the quantifier is universal. - *) let is_universal ( x : quantifier ) = Z3native.is_quantifier_forall (gnc x) (gno x) - (** - Indicates whether the quantifier is existential. - *) let is_existential ( x : quantifier ) = not (is_universal x) - (** - The weight of the quantifier. - *) let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) - (** - The number of patterns. - *) let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) - (** - The patterns. - *) let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in Array.init n f - (** - The number of no-patterns. - *) let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) - (** - The no-patterns. - *) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in Array.init n f - (** - The number of bound variables. - *) let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) - (** - The symbols for the bound variables. - *) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in Array.init n f - (** - The sorts of the bound variables. - *) let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in Array.init n f - (** - The body of the quantifier. - *) let get_body ( x : quantifier ) = Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) - (** - Creates a new bound variable. - @param index The de-Bruijn index of the variable - @param ty The sort of the variable - *) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - (** - Create a quantifier pattern. - *) let mk_pattern ( ctx : context ) ( terms : expr array ) = if (Array.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) - (** - Create a universal Quantifier. - - Creates a forall formula, where is the weight, - is an array of patterns, is an array - with the sorts of the bound variables, is an array with the - 'names' of the bound variables, and is the body of the - quantifier. Quantifiers are associated with weights indicating - the importance of using the quantifier during instantiation. - - @param sorts the sorts of the bound variables. - @param names names of the bound variables - @param body the body of the quantifier. - @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. - @param patterns array containing the patterns created using MkPattern. - @param noPatterns array containing the anti-patterns created using MkPattern. - @param quantifierID optional symbol to track quantifier. - @param skolemID optional symbol to track skolem constants. - *) let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") @@ -1390,9 +1093,6 @@ struct (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - (** - Create a universal Quantifier. - *) let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true @@ -1410,10 +1110,6 @@ struct (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) - (** - Create an existential Quantifier. - - *) let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (Array.length sorts) != (Array.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") @@ -1435,9 +1131,6 @@ struct (let f x = (Symbol.gno x) in (Array.map f names)) (ptr_of_expr body))) - (** - Create an existential Quantifier. - *) let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false @@ -1455,19 +1148,12 @@ struct (Array.length nopatterns) (expr_aton nopatterns) (ptr_of_expr body))) - (** - Create a Quantifier. - *) let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - - (** - Create a Quantifier. - *) let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id @@ -1475,7 +1161,7 @@ struct mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id end -(** Functions to manipulate Array expressions *) + module Array_ = struct type array_sort = ArraySort of sort @@ -1516,144 +1202,46 @@ struct let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - (** - Create a new array sort. - *) let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - (** - Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. - *) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - - (** - Indicates whether the term is an array select. - *) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - - (** - Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. - *) let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - - (** - Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. - *) let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - - (** - Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. - *) let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - - (** - Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. - *) let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) - - (** - Indicates whether the term is of an array sort. - *) let is_array ( x : expr ) = (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) - (** The domain of the array sort. *) let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - - (** The range of the array sort. *) let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - (** - Create an array constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) - (** - Create an array constant. - *) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range - (** - Array read. - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - - - *) let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) - - (** - Array update. - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - - - *) - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + + let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) - (** - Create a constant array. - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - - - *) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) - (** - Maps f on the argument arrays. - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - - - - *) let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) - (** - Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. - *) let mk_term_array ( ctx : context ) ( arg : array_expr ) = array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) end -(** Functions to manipulate Set expressions *) + module Set = struct type set_sort = SetSort of sort @@ -1664,100 +1252,49 @@ struct let sort_of_set_sort s = match s with SetSort(x) -> x - (** - Indicates whether the term is set union - *) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - - (** - Indicates whether the term is set intersection - *) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - - (** - Indicates whether the term is set difference - *) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - - (** - Indicates whether the term is set complement - *) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - - (** - Indicates whether the term is set subset - *) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) - - (** - Create a set type. - *) let mk_sort ( ctx : context ) ( ty : sort ) = set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - (** - Create an empty set. - *) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + + let mk_empty ( ctx : context ) ( domain : sort ) = (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) - (** - Create the full set. - *) let mk_full ( ctx : context ) ( domain : sort ) = expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) - (** - Add an element to the set. - *) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - (** - Remove an element from a set. - *) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - (** - Take the union of a list of sets. - *) let mk_union ( ctx : context ) ( args : expr array ) = expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Take the intersection of a list of sets. - *) let mk_intersection ( ctx : context ) ( args : expr array ) = expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) - (** - Take the difference between two sets. - *) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) - (** - Take the complement of a set. - *) let mk_complement ( ctx : context ) ( arg : expr ) = expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) - (** - Check for set membership. - *) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) - (** - Check for subsetness of sets. - *) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) end -(** Functions to manipulate Finite Domain expressions *) + module FiniteDomain = struct type finite_domain_sort = FiniteDomainSort of sort @@ -1774,41 +1311,28 @@ struct let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - (** - Create a new finite domain sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in FiniteDomainSort(s) - (** - Create a new finite domain sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = mk_sort ctx (Symbol.mk_string ctx name) size - (** - Indicates whether the term is of an array sort. - *) let is_finite_domain ( x : expr ) = let nc = (nc_of_expr x) in (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) - (** - Indicates whether the term is a less than predicate over a finite domain. - *) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - (** The size of the finite domain sort. *) let get_size ( x : finite_domain_sort ) = let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end -(** Functions to manipulate Relation expressions *) + module Relation = struct type relation_sort = RelationSort of sort @@ -1830,119 +1354,27 @@ struct let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - (** - Indicates whether the term is of a relation sort. - *) let is_relation ( x : expr ) = let nc = (nc_of_expr x) in ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) - (** - Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. - *) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - - (** - Indicates whether the term is an empty relation - *) let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - - (** - Indicates whether the term is a test for the emptiness of a relation - *) let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - - (** - Indicates whether the term is a relational join - *) let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - - (** - Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. - *) let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - - (** - Indicates whether the term is the widening of two relations - The function takes two arguments. - *) let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - - (** - Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. - *) let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - - (** - Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. - *) let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - - (** - Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. - *) let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - - (** - Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. - *) let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - - (** - Indicates whether the term is the complement of a relation - *) let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - - (** - Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. - *) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - - (** - Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind - to perform destructive updates to the first argument. - *) let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - (** The arity of the relation sort. *) let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) - (** The sorts of the columns of the relation sort. *) let get_column_sorts ( x : relation_sort ) = let n = get_arity x in let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in @@ -1950,7 +1382,7 @@ struct end -(** Functions to manipulate Datatype expressions *) + module Datatype = struct type datatype_sort = DatatypeSort of sort @@ -1983,14 +1415,10 @@ struct let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - - (** Constructors *) module Constructor = struct type constructor = z3_native_object - let _counts = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = let n = (Array.length field_names) in if n != (Array.length sorts) then @@ -2009,42 +1437,29 @@ struct m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in - Hashtbl.add _counts no n ; (z3obj_sno no ctx ptr) ; (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; no + + let get_num_fields ( x : constructor ) = Z3native.get_arity (z3obj_gnc x) (z3obj_gno x) - let get_n ( x : constructor ) = (Hashtbl.find _counts x) - - let rec constructor_decl ( x : constructor ) = - let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let get_constructor_decl ( x : constructor ) = + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in func_decl_of_ptr (z3obj_gc x) a - let rec tester_decl ( x : constructor ) = - let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + let get_tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in func_decl_of_ptr (z3obj_gc x) b - - let rec accessor_decls ( x : constructor ) = - let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (Hashtbl.find _counts x)) in + + let get_accessor_decls ( x : constructor ) = + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in let f y = func_decl_of_ptr (z3obj_gc x) y in Array.map f c - (** The number of fields of the constructor. *) - let get_num_fields ( x : constructor ) = get_n x - - (** The function declaration of the constructor. *) - let get_constructor_decl ( x : constructor ) = constructor_decl x - - (** The function declaration of the tester. *) - let get_tester_decl ( x : constructor ) = tester_decl x - - (** The function declarations of the accessors *) - let get_accessor_decls ( x : constructor ) = accessor_decls x end - (** Constructor list objects *) module ConstructorList = struct type constructor_list = z3_native_object @@ -2062,54 +1477,21 @@ struct res end - (* DATATYPES *) - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = Constructor.create ctx name recognizer field_names sorts sort_refs - (** - Create a datatype constructor. - @param name constructor name - @param recognizer name of recognizer function. - @param fieldNames names of the constructor fields. - @param sorts field sorts, 0 if the field sort refers to a recursive sort. - @param sortRefs reference to datatype sort that is an argument to the constructor; - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. - *) let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - - (** - Create a new datatype sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = let f x = (z3obj_gno x) in let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in sort_of_ptr ctx x - (** - Create a new datatype sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = mk_sort ctx (Symbol.mk_string ctx name) constructors - (** - Create mutually recursive datatypes. - @param names names of datatype sorts - @param c list of constructors, one list per sort. - *) let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = let n = (Array.length names) in let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in @@ -2119,7 +1501,6 @@ struct let g e = (sort_of_ptr ctx e) in (Array.map g r) - (** Create mutually recursive data-types. *) let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = mk_sorts ctx ( @@ -2128,22 +1509,18 @@ struct ) c - (** The number of constructors of the datatype sort. *) let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) - (** The range of the array sort. *) let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in Array.init n f - (** The recognizers. *) let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in Array.init n f - (** The constructor accessors. *) let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = ( @@ -2155,7 +1532,7 @@ struct Array.init n f end -(** Functions to manipulate Enumeration expressions *) + module Enumeration = struct type enum_sort = EnumSort of sort @@ -2171,27 +1548,19 @@ struct let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - (** - Create a new enumeration sort. - *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = let f x = Symbol.gno x in let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in sort_of_ptr ctx a b c - (** - Create a new enumeration sort. - *) let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - (** The function declarations of the constants in the enumeration. *) let get_const_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in Array.init n f - (** The test predicates for the constants in the enumeration. *) let get_tester_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in @@ -2199,7 +1568,7 @@ struct end -(** Functions to manipulate List expressions *) + module List_ = struct type list_sort = ListSort of sort @@ -2214,46 +1583,36 @@ struct let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - - (** Create a new list sort. *) + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in sort_of_ptr ctx r a b c d e f - (** Create a new list sort. *) let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort - (** The declaration of the nil function of this list sort. *) let get_nil_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) - (** The declaration of the isNil function of this list sort. *) let get_is_nil_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) - (** The declaration of the cons function of this list sort. *) let get_cons_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) - (** The declaration of the isCons function of this list sort. *) let get_is_cons_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) - (** The declaration of the head function of this list sort. *) let get_head_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) - (** The declaration of the tail function of this list sort. *) let get_tail_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - (** The empty list. *) let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] end -(** Functions to manipulate Tuple expressions *) + module Tuple = struct type tuple_sort = TupleSort of sort @@ -2268,30 +1627,24 @@ struct let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - - (** Create a new tuple sort. *) let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = let f x = Symbol.gno x in let f2 x = ptr_of_ast (ast_of_sort x) in - let (r, a, b) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in - (* CMW: leaks a,b? *) + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in sort_of_ptr ctx r - (** The constructor function of the tuple. *) let get_mk_decl ( x : tuple_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) - (** The number of fields in the tuple. *) let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) - (** The field declarations. *) let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in Array.init n f end -(** Functions to manipulate arithmetic expressions *) + module rec Arithmetic : sig type arith_sort = ArithSort of Sort.sort @@ -2516,84 +1869,37 @@ end = struct let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - - (** Create a new integer sort. *) let mk_sort ( ctx : context ) = int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - (** Retrieve the int value. *) let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - (** Returns a string representation of the numeral. *) let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - (** - Creates an integer constant. - *) let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - (** - Creates an integer constant. - *) let mk_int_const_s ( ctx : context ) ( name : string ) = mk_int_const ctx (Symbol.mk_string ctx name) - (** - Create an expression representing t1 mod t2. - The arguments must have int type. - *) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) - (** - Create an expression representing t1 rem t2. - The arguments must have int type. - *) let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - (** - Create an integer numeral. - @param v A string representing the Term value in decimal notation. - *) let mk_int_numeral_s ( ctx : context ) ( v : string ) = int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Create an integer numeral. - @param v value of the numeral. - @return A Term with value and sort Integer - *) let mk_int_numeral_i ( ctx : context ) ( v : int ) = int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. - *) let mk_int2real ( ctx : context ) ( t : int_expr ) = Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) - (** - Create an bit bit-vector from the integer argument . - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. - *) let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) end @@ -2677,76 +1983,41 @@ end = struct let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - (** Create a real sort. *) let mk_sort ( ctx : context ) = real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - (** The numerator of a rational numeral. *) let get_numerator ( x : rat_num ) = Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) - (** The denominator of a rational numeral. *) let get_denominator ( x : rat_num ) = Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) let to_decimal_string ( x : rat_num ) ( precision : int ) = Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - (** Returns a string representation of the numeral. *) let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - (** Creates a real constant. *) let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - (** Creates a real constant. *) let mk_real_const_s ( ctx : context ) ( name : string ) = mk_real_const ctx (Symbol.mk_string ctx name) - (** - Create a real from a fraction. - - @param num numerator of rational. - @param den denominator of rational. - @return A Term with value / and sort Real - - *) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then raise (Z3native.Exception "Denominator is zero") else rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) - (** - Create a real numeral. - @param v A string representing the Term value in decimal notation. - @return A Term with value and sort Real - *) let mk_numeral_s ( ctx : context ) ( v : string ) = rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - (** - Create a real numeral. - - @param v value of the numeral. - @return A Term with value and sort Real - *) let mk_numeral_i ( ctx : context ) ( v : int ) = rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - (** Creates an expression that checks whether a real number is an integer. *) let mk_is_integer ( ctx : context ) ( t : real_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) - (** - Coerce a real to an integer. - - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. - *) let mk_real2int ( ctx : context ) ( t : real_expr ) = Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) end @@ -2782,208 +2053,97 @@ end = struct let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - (** - Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) let to_upper ( x : algebraic_num ) ( precision : int ) = Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) - (** - Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^. - - @param precision the precision of the result - @return A numeral Expr of sort Real - *) let to_lower ( x : algebraic_num ) precision = Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) - (** Returns a string representation in decimal notation. - The result has at most decimal places.*) let to_decimal_string ( x : algebraic_num ) ( precision : int ) = Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - (** Returns a string representation of the numeral. *) let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) end - (** - Indicates whether the term is of integer sort. - *) let is_int ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) - (** - Indicates whether the term is an arithmetic numeral. - *) let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - (** - Indicates whether the term is a less-than-or-equal - *) let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - (** - Indicates whether the term is a greater-than-or-equal - *) let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - (** - Indicates whether the term is a less-than - *) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - (** - Indicates whether the term is a greater-than - *) let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - (** - Indicates whether the term is addition (binary) - *) let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - (** - Indicates whether the term is subtraction (binary) - *) let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - (** - Indicates whether the term is a unary minus - *) let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - (** - Indicates whether the term is multiplication (binary) - *) let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - (** - Indicates whether the term is division (binary) - *) let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - (** - Indicates whether the term is integer division (binary) - *) let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - (** - Indicates whether the term is remainder (binary) - *) let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - (** - Indicates whether the term is modulus (binary) - *) let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - (** - Indicates whether the term is a coercion of integer to real (unary) - *) let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - (** - Indicates whether the term is a coercion of real to integer (unary) - *) let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - (** - Indicates whether the term is a check that tests whether a real is integral (unary) - *) let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - (** - Indicates whether the term is of sort real. - *) let is_real ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) - - (** - Indicates whether the term is an integer numeral. - *) let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - (** - Indicates whether the term is a real numeral. - *) let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - (** - Indicates whether the term is an algebraic number - *) let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) - (** - Create an expression representing t[0] + t[1] + .... - *) let mk_add ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing t[0] * t[1] * .... - *) let mk_mul ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing t[0] - t[1] - .... - *) let mk_sub ( ctx : context ) ( t : arith_expr array ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) - (** - Create an expression representing -t. - *) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) - (** - Create an expression representing t1 / t2. - *) let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 ^ t2. - *) let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 < t2 - *) let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 <= t2 - *) let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 > t2 - *) let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) - (** - Create an expression representing t1 >= t2 - *) let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) end -(** Functions to manipulate bit-vector expressions *) + and BitVector : sig type bitvec_sort = BitVecSort of Sort.sort @@ -3089,8 +2249,10 @@ sig val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr @@ -3154,1225 +2316,213 @@ end = struct let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - (** - Create a new bit-vector sort. - *) let mk_sort ( ctx : context ) size = bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) - - (** - Indicates whether the terms is of bit-vector sort. - *) let is_bv ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) - - (** - Indicates whether the term is a bit-vector numeral - *) let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - - (** - Indicates whether the term is a one-bit bit-vector with value one - *) let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - - (** - Indicates whether the term is a one-bit bit-vector with value zero - *) let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - - (** - Indicates whether the term is a bit-vector unary minus - *) let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - - (** - Indicates whether the term is a bit-vector addition (binary) - *) let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - - (** - Indicates whether the term is a bit-vector subtraction (binary) - *) let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - - (** - Indicates whether the term is a bit-vector multiplication (binary) - *) let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - - (** - Indicates whether the term is a bit-vector signed division (binary) - *) let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - - (** - Indicates whether the term is a bit-vector unsigned division (binary) - *) let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - - (** - Indicates whether the term is a bit-vector signed remainder (binary) - *) let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - - (** - Indicates whether the term is a bit-vector unsigned remainder (binary) - *) let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - - (** - Indicates whether the term is a bit-vector signed modulus - *) let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - - (** - Indicates whether the term is a bit-vector signed division by zero - *) let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - - (** - Indicates whether the term is a bit-vector unsigned division by zero - *) let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - - (** - Indicates whether the term is a bit-vector signed remainder by zero - *) let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - - (** - Indicates whether the term is a bit-vector unsigned remainder by zero - *) let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - - (** - Indicates whether the term is a bit-vector signed modulus by zero - *) let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - - (** - Indicates whether the term is an unsigned bit-vector less-than-or-equal - *) let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - - (** - Indicates whether the term is a signed bit-vector less-than-or-equal - *) let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - - (** - Indicates whether the term is an unsigned bit-vector greater-than-or-equal - *) let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - - (** - Indicates whether the term is a signed bit-vector greater-than-or-equal - *) let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - - (** - Indicates whether the term is an unsigned bit-vector less-than - *) let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - - (** - Indicates whether the term is a signed bit-vector less-than - *) let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - - (** - Indicates whether the term is an unsigned bit-vector greater-than - *) let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - - (** - Indicates whether the term is a signed bit-vector greater-than - *) let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - - (** - Indicates whether the term is a bit-wise AND - *) let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - - (** - Indicates whether the term is a bit-wise OR - *) let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - - (** - Indicates whether the term is a bit-wise NOT - *) let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - - (** - Indicates whether the term is a bit-wise XOR - *) let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - - (** - Indicates whether the term is a bit-wise NAND - *) let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - - (** - Indicates whether the term is a bit-wise NOR - *) let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - - (** - Indicates whether the term is a bit-wise XNOR - *) let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - - (** - Indicates whether the term is a bit-vector concatenation (binary) - *) let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - - (** - Indicates whether the term is a bit-vector sign extension - *) let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - - (** - Indicates whether the term is a bit-vector zero extension - *) let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - - (** - Indicates whether the term is a bit-vector extraction - *) let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - - (** - Indicates whether the term is a bit-vector repetition - *) let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - - (** - Indicates whether the term is a bit-vector reduce OR - *) let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - - (** - Indicates whether the term is a bit-vector reduce AND - *) let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - - (** - Indicates whether the term is a bit-vector comparison - *) let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - - (** - Indicates whether the term is a bit-vector shift left - *) let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - - (** - Indicates whether the term is a bit-vector logical shift right - *) let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - - (** - Indicates whether the term is a bit-vector arithmetic shift left - *) let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - - (** - Indicates whether the term is a bit-vector rotate left - *) let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - - (** - Indicates whether the term is a bit-vector rotate right - *) let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - - (** - Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. - *) let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - - (** - Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. - *) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - - (** - Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - *) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - - (** - Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. - *) let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - - (** - Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) - *) let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - - (** - Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) - *) let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - - (** The size of a bit-vector sort. *) let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - - (** Retrieve the int value. *) let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - - (** Returns a string representation of the numeral. *) let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - (** - Creates a bit-vector constant. - *) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) - - (** - Creates a bit-vector constant. - *) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = mk_const ctx (Symbol.mk_string ctx name) size - - (** - Bitwise negation. - The argument must have a bit-vector sort. - *) let mk_not ( ctx : context ) ( t : bitvec_expr ) = expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - - (** - Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. - *) let mk_redand ( ctx : context ) ( t : bitvec_expr) = expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - - (** - Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. - *) let mk_redor ( ctx : context ) ( t : bitvec_expr) = expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - - (** - Bitwise conjunction. - The arguments must have a bit-vector sort. - *) let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise disjunction. - The arguments must have a bit-vector sort. - *) let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise XOR. - The arguments must have a bit-vector sort. - *) let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise NAND. - The arguments must have a bit-vector sort. - *) let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise NOR. - The arguments must have a bit-vector sort. - *) let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - - (** - Bitwise XNOR. - The arguments must have a bit-vector sort. - *) let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - - (** - Standard two's complement unary minus. - The arguments must have a bit-vector sort. - *) let mk_neg ( ctx : context ) ( t : bitvec_expr) = bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - - (** - Two's complement addition. - The arguments must have the same bit-vector sort. - *) let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement subtraction. - The arguments must have the same bit-vector sort. - *) let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement multiplication. - The arguments must have the same bit-vector sort. - *) let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned division. - - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. - *) let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - - (** - Signed division. - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned remainder. - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - - (** - Signed remainder. - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - - (** - Two's complement signed remainder (sign follows divisor). - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. - *) let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - - (** - Unsigned less-than - - The arguments must have the same bit-vector sort. - *) let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed less-than - - The arguments must have the same bit-vector sort. - *) let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. - *) let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - - (** - Unsigned greater-than. - - The arguments must have the same bit-vector sort. - *) let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - - (** - Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. - *) let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - - (** - Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). - *) let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - - (** - Bit-vector extraction. - - Extract the bits down to from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. - The argument must have a bit-vector sort. - *) let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - - (** - Bit-vector sign extension. - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. - The argument must have a bit-vector sort. - *) let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - - (** - Bit-vector zero extension. - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. - The argument must have a bit-vector sort. - *) let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - - (** - Bit-vector repetition. - - The argument must have a bit-vector sort. - *) let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - - (** - Shift left. - - - It is equivalent to multiplication by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - - - (** - Logical shift right - - It is equivalent to unsigned division by 2^x where \c x is the value of . - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - - (** - Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. - *) let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - - (** - Rotate Left. - - Rotate bits of \c t to the left \c i times. - The argument must have a bit-vector sort. - *) let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - - (** - Rotate Right. - - Rotate bits of \c t to the right \c i times. - The argument must have a bit-vector sort. - *) let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - - (** - Rotate Left. - - Rotate bits of to the left times. - The arguments must have the same bit-vector sort. - *) - let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - - (** - Rotate Right. - - - Rotate bits of to the right times. - The arguments must have the same bit-vector sort. - *) - let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - - (** - Create an integer from the bit-vector argument . - - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in . - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of bit-vector sort. - *) let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - - (** - Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - - (** - Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. - *) let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - - (** - Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. - *) let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) - - (** - Create a bit-vector numeral. - - @param v A string representing the value in decimal notation. - @param size the size of the bit-vector - *) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) end -(** Functions to manipulate proof expressions *) + module Proof = struct - (** - Indicates whether the term is a Proof for the expression 'true'. - *) let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - - (** - Indicates whether the term is a proof for a fact asserted by the user. - *) let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - - (** - Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. - *) let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - - (** - Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). - *) let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - - (** - Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. - *) let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - - (** - Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. - *) let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - - (** - Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) - *) let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - - (** - Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. - *) let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - - - (** - Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. - *) let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - - (** - Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - *) let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - - (** - Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. - *) let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - - (** - Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i - *) let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - - (** - Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) - *) let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - - (** - Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) - *) let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - - (** - Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) - *) let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - - (** - Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - *) let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - - (** - Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents - *) let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - - (** - Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents - *) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - - (** - Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. - *) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - - (** - Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. - *) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - - (** - Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) - *) let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - - (** - Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. - *) let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - - (** - Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. - *) let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - - (** - Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') - *) let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - - (** - Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) - *) let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - - (** - Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) - *) let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - - (** - Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. - *) let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - - (** - Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). - *) let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - - (** - Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) - *) let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - - (** - Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. - *) let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - - (** - Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) - *) let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - - (** - Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. - *) let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - - (** - Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) - *) let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - - (** - Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - - (** - Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - *) let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - - (** - Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. - *) let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - - (** - Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q - *) let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - - (** - Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. - *) let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end -(** Goals - - A goal (aka problem). A goal is essentially a - of formulas, that can be solved and/or transformed using - tactics and solvers. *) module Goal = struct type goal = z3_native_object @@ -4386,76 +2536,52 @@ struct (z3obj_create res) ; res - - (** The precision of the goal. - - Goals can be transformed using over and under approximations. - An under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. - *) let get_precision ( x : goal ) = goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) - (** Indicates whether the goal is precise. *) let is_precise ( x : goal ) = (get_precision x) == GOAL_PRECISE - (** Indicates whether the goal is an under-approximation. *) let is_underapproximation ( x : goal ) = (get_precision x) == GOAL_UNDER - (** Indicates whether the goal is an over-approximation. *) let is_overapproximation ( x : goal ) = (get_precision x) == GOAL_OVER - (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - (** Adds the constraints to the given goal. *) - (* CMW: assert seems to be a keyword. *) let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in ignore (Array.map f constraints) ; () - (** Indicates whether the goal contains `false'. *) let is_inconsistent ( x : goal ) = Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) - (** The depth of the goal. - This tracks how many transformations were applied to it. *) let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) - (** Erases all formulas from the given goal. *) let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) - (** The number of formulas in the goal. *) let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) - (** The formulas in the goal. *) let get_formulas ( x : goal ) = let n = get_size x in let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in Array.init n f - (** The number of formulas, subformulas and terms in the goal. *) let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) - (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) let is_decided_sat ( x : goal ) = Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) - (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) let is_decided_unsat ( x : goal ) = Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) - (** Translates (copies) the Goal to the target Context . *) let translate ( x : goal ) ( to_ctx : context ) = create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) let simplify ( x : goal ) ( p : Params.params option ) = let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in Z3native.tactic_inc_ref (z3obj_gnc x) tn ; @@ -4473,27 +2599,13 @@ struct Z3native.tactic_dec_ref (z3obj_gnc x) tn ; create (z3obj_gc x) res - - (** - Creates a new Goal. - - Note that the Context must have been created with proof generation support if - is set to true here. - @param models Indicates whether model generation should be enabled. - @param unsat_cores Indicates whether unsat core generation should be enabled. - @param proofs Indicates whether proof generation should be enabled. - *) let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) - (** A string representation of the Goal. *) let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) module Model = struct type model = z3_native_object @@ -4507,12 +2619,6 @@ struct (z3obj_create res) ; res - - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. - *) module FuncInterp = struct type func_interp = z3_native_object @@ -4526,11 +2632,6 @@ struct (z3obj_create res) ; res - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. - *) module FuncEntry = struct type func_entry = z3_native_object @@ -4544,61 +2645,33 @@ struct (z3obj_create res) ; res - - (** - Return the (symbolic) value of this entry. - *) let get_value ( x : func_entry ) = expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) - (** - The number of arguments of the entry. - *) let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) - (** - The arguments of the function entry. - *) let get_args ( x : func_entry ) = let n = (get_num_args x) in let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - (** - A string representation of the function entry. - *) let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end - (** - The number of entries in the function interpretation. - *) let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) - (** - The entries in the function interpretation - *) let get_entries ( x : func_interp ) = let n = (get_num_entries x) in let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - (** - The (symbolic) `else' value of the function interpretation. - *) let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) - (** - The arity of the function interpretation - *) let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) - (** - A string representation of the function interpretation. - *) let to_string ( x : func_interp ) = let f c p = ( let n = (FuncEntry.get_num_args c) in @@ -4613,9 +2686,6 @@ struct Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") end - (** Retrieves the interpretation (the assignment) of in the model. - A function declaration of zero arity - An expression if the function has an interpretation in the model, null otherwise. *) let get_const_interp ( x : model ) ( f : func_decl ) = if (FuncDecl.get_arity f) != 0 || (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then @@ -4627,16 +2697,9 @@ struct else Some (expr_of_ptr (z3obj_gc x) np) - (** Retrieves the interpretation (the assignment) of in the model. - A Constant - An expression if the constant has an interpretation in the model, null otherwise. - *) let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - (** Retrieves the interpretation (the assignment) of a non-constant in the model. - A function declaration of non-zero arity - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) let rec get_func_interp ( x : model ) ( f : func_decl ) = let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in if (FuncDecl.get_arity f) == 0 then @@ -4659,23 +2722,18 @@ struct (** The number of constants that have an interpretation in the model. *) let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) - (** The function declarations of the constants in the model. *) let get_const_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - - (** The number of function interpretations in the model. *) let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) - (** The function declarations of the function interpretations in the model. *) let get_func_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** All symbols that have an interpretation in the model. *) let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in @@ -4683,24 +2741,8 @@ struct let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in Array.append (Array.init n_funcs f) (Array.init n_consts g) - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) exception ModelEvaluationFailedException of string - (** - Evaluates the expression in the current model. - - - This function may fail if contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - - An expression - - When this flag is enabled, a model value will be assigned to any constant - or function that does not have an interpretation in the model. - - The evaluation of in the model. - *) let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in if not r then @@ -4708,53 +2750,26 @@ struct else expr_of_ptr (z3obj_gc x) v - (** Alias for eval. *) let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion - (** The number of uninterpreted sorts that the model has an interpretation for. *) let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - - - *) let get_sorts ( x : model ) = let n = (get_num_sorts x) in let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in Array.init n f - - (** The finite set of distinct values that represent the interpretation for sort . - - An uninterpreted sort - An array of expressions, where each is an element of the universe of - *) let sort_universe ( x : model ) ( s : sort ) = let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in Array.init n f - - (** Conversion of models to strings. - A string representation of the model. - *) + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) module Probe = struct type probe = z3_native_object @@ -4769,114 +2784,52 @@ struct res - (** - Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - *) let apply ( x : probe ) ( g : Goal.goal ) = Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) - (** - The number of supported Probes. - *) let get_num_probes ( ctx : context ) = Z3native.get_num_probes (context_gno ctx) - (** - The names of all supported Probes. - *) let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in let f i = (Z3native.get_probe_name (context_gno ctx) i) in Array.init n f - (** - Returns a string containing a description of the probe with the given name. - *) let get_probe_description ( ctx : context ) ( name : string ) = Z3native.probe_get_descr (context_gno ctx) name - (** - Creates a new Probe. - *) let mk_probe ( ctx : context ) ( name : string ) = (create ctx (Z3native.mk_probe (context_gno ctx) name)) - (** - Create a probe that always evaluates to . - *) let const ( ctx : context ) ( v : float ) = (create ctx (Z3native.probe_const (context_gno ctx) v)) - (** - Create a probe that evaluates to "true" when the value returned by - is less than the value returned by - *) let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is greater than the value returned by - *) let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is less than or equal the value returned by - *) let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is greater than or equal the value returned by - *) let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value returned by - is equal to the value returned by - *) let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - and evaluate to "true". - *) - (* CMW: and is a keyword *) let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - or evaluate to "true". - *) - (* CMW: or is a keyword *) let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - (** - Create a probe that evaluates to "true" when the value - does not evaluate to "true". - *) - (* CMW: is not a keyword? *) let not_ ( ctx : context ) ( p : probe ) = (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) end -(** Tactics - - Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) module Tactic = struct type tactic = z3_native_object @@ -4890,11 +2843,6 @@ struct (z3obj_create res) ; res - - (** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult = struct type apply_result = z3_native_object @@ -4908,75 +2856,46 @@ struct (z3obj_create res) ; res - - (** The number of Subgoals. *) let get_num_subgoals ( x : apply_result ) = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) - (** Retrieves the subgoals from the apply_result. *) let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** Retrieves the subgoals from the apply_result. *) let get_subgoal ( x : apply_result ) ( i : int ) = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) - (** Convert a model for the subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g - *) let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) - (** A string representation of the ApplyResult. *) let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) end - (** A string containing a description of parameters accepted by the tactic. *) let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) - (** Retrieves parameter descriptions for Tactics. *) let get_param_descrs ( x : tactic ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** Apply the tactic to the goal. *) let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = match p with | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) - (** - The number of supported tactics. - *) let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) - (** - The names of all supported tactics. - *) let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in let f i = (Z3native.get_tactic_name (context_gno ctx) i) in Array.init n f - - (** - Returns a string containing a description of the tactic with the given name. - *) let get_tactic_description ( ctx : context ) ( name : string ) = Z3native.tactic_get_descr (context_gno ctx) name - (** - Creates a new Tactic. - *) let mk_tactic ( ctx : context ) ( name : string ) = create ctx (Z3native.mk_tactic (context_gno ctx) name) - (** - Create a tactic that applies to a Goal and - then to every subgoal produced by . - *) let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = let f p c = (match p with | None -> (Some (z3obj_gno c)) @@ -4988,106 +2907,50 @@ struct let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) - (** - Create a tactic that first applies to a Goal and - if it fails then returns the result of applied to the Goal. - *) let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - (** - Create a tactic that applies to a goal for milliseconds. - - If does not terminate within milliseconds, then it fails. - *) let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) - (** - Create a tactic that applies to a given goal if the probe - evaluates to true. - - If evaluates to false, then the new tactic behaves like the skip tactic. - *) - (* CMW: when is a keyword *) let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) - (** - Create a tactic that applies to a given goal if the probe - evaluates to true and otherwise. - *) let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) - (** - Create a tactic that keeps applying until the goal is not - modified anymore or the maximum number of iterations is reached. - *) let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) - (** - Create a tactic that just returns the given goal. - *) let skip ( ctx : context ) = create ctx (Z3native.tactic_skip (context_gno ctx)) - (** - Create a tactic always fails. - *) let fail ( ctx : context ) = create ctx (Z3native.tactic_fail (context_gno ctx)) - (** - Create a tactic that fails if the probe evaluates to false. - *) let fail_if ( ctx : context ) ( p : Probe.probe ) = create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) - (** - Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). - *) let fail_if_not_decided ( ctx : context ) = create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) - (** - Create a tactic that applies using the given set of parameters . - *) let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) - (** - Create a tactic that applies using the given set of parameters . - Alias for UsingParams*) - (* CMW: with is a keyword *) let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p - (** - Create a tactic that applies the given tactics in parallel. - *) let par_or ( ctx : context ) ( t : tactic array ) = create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) - (** - Create a tactic that applies to a given goal and then - to every subgoal produced by . The subgoals are processed in parallel. - *) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - (** - Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. - *) let interrupt ( ctx : context ) = Z3native.interrupt (context_gno ctx) end -(** Solvers *) module Solver = struct type solver = z3_native_object @@ -5102,13 +2965,11 @@ struct (z3obj_create res) ; res - let string_of_status ( s : status) = match s with | UNSATISFIABLE -> "unsatisfiable" | SATISFIABLE -> "satisfiable" | _ -> "unknown" - (** Objects that track statistical information about solvers. *) module Statistics = struct type statistics = z3_native_object @@ -5123,11 +2984,6 @@ struct res - (** - Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - - *) module Entry = struct type statistics_entry = { @@ -5158,22 +3014,11 @@ struct res - (** The key of the entry. *) let get_key (x : statistics_entry) = x.m_key - - (** The int-value of the entry. *) - let get_int (x : statistics_entry) = x.m_int - - (** The float-value of the entry. *) + let get_int (x : statistics_entry) = x.m_int let get_float (x : statistics_entry) = x.m_float - - (** True if the entry is uint-valued. *) let is_int (x : statistics_entry) = x.m_is_int - - (** True if the entry is double-valued. *) let is_float (x : statistics_entry) = x.m_is_float - - (** The string representation of the the entry's value. *) let to_string_value (x : statistics_entry) = if (is_int x) then string_of_int (get_int x) @@ -5181,18 +3026,13 @@ struct string_of_float (get_float x) else raise (Z3native.Exception "Unknown statistical entry type") - - (** The string representation of the entry (key and value) *) let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) end - (** A string representation of the statistical data. *) let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) - (** The number of statistical data. *) let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) - (** The data entries. *) let get_entries ( x : statistics ) = let n = (get_size x ) in let f i = ( @@ -5204,129 +3044,56 @@ struct ) in Array.init n f - (** - The statistical counters. - *) let get_keys ( x : statistics ) = let n = (get_size x) in let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in Array.init n f - (** The value of a particular statistical counter. *) let get ( x : statistics ) ( key : string ) = let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in Array.fold_left f None (get_entries x) end - (** - A string that describes all available solver parameters. - *) let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) - (** - Sets the solver parameters. - *) let set_parameters ( x : solver ) ( p : Params.params )= Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - (** - Retrieves parameter descriptions for solver. - *) let get_param_descrs ( x : solver ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** - The current number of backtracking points (scopes). - - - *) let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) - (** - Creates a backtracking point. - - *) let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) - (** - Backtracks backtracking points. - Note that an exception is thrown if is not smaller than NumScopes - - *) let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n - (** - Resets the Solver. - This removes all assertions from the solver. - *) let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - (** - Assert a constraint (or multiple) into the solver. - *) let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) - (** - * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using - * and the Boolean literals - * provided using with assumptions. - *) - let assert_and_track ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = if ((Array.length cs) != (Array.length ps)) then raise (Z3native.Exception "Argument size mismatch") else let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in ignore (Array.iteri f cs) - (** - * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using - * and the Boolean literals - * provided using with assumptions. - *) let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) - (** - The number of assertions in the solver. - *) let get_num_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) - - (** - The set of asserted formulas. - *) let get_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in Array.init n f - (** - Checks whether the assertions in the solver are consistent or not. - - - - - *) let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = let r = if ((Array.length assumptions) == 0) then @@ -5340,12 +3107,6 @@ struct | L_FALSE -> UNSATISFIABLE | _ -> UNKNOWN - (** - The model of the last Check. - - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. - *) let get_model ( x : solver ) = let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then @@ -5353,12 +3114,6 @@ struct else Some (Model.create (z3obj_gc x) q) - (** - The proof of the last Check. - - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. - *) let get_proof ( x : solver ) = let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in if (Z3native.is_null q) then @@ -5366,73 +3121,35 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - The unsat core of the last Check. - - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. - *) let get_unsat_core ( x : solver ) = let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in Array.init n f - (** - A brief justification of why the last call to Check returned UNKNOWN. - *) let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - (** - Solver statistics. - *) let get_statistics ( x : solver ) = (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) - (** - Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. - *) let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = match logic with | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) - (** - Creates a new (incremental) solver. - - *) let mk_solver_s ( ctx : context ) ( logic : string ) = mk_solver ctx (Some (Symbol.mk_string ctx logic)) - (** - Creates a new (incremental) solver. - *) let mk_simple_solver ( ctx : context ) = (create ctx (Z3native.mk_simple_solver (context_gno ctx))) - (** - Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. - *) let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) - (** - A string representation of the solver. - *) let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) end -(** Fixedpoint solving *) module Fixedpoint = struct type fixedpoint = z3_native_object @@ -5447,70 +3164,37 @@ struct res - (** - A string that describes all available fixedpoint solver parameters. - *) let get_help ( x : fixedpoint ) = Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) - (** - Sets the fixedpoint solver parameters. - *) let set_params ( x : fixedpoint ) ( p : Params.params )= Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - (** - Retrieves parameter descriptions for Fixedpoint solver. - *) let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - (** - Assert a constraints into the fixedpoint solver. - *) let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in ignore (Array.map f constraints) ; () - (** - Register predicate as recursive relation. - *) let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - (** - Add rule into the fixedpoint solver. - *) let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = match name with | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - (** - Add table fact to the fixedpoint solver. - *) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args - (** - Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. - *) let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - (** - Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. - *) let query_r ( x : fixedpoint ) ( relations : func_decl array ) = let f x = ptr_of_ast (ast_of_func_decl x) in match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with @@ -5518,32 +3202,15 @@ struct | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - (** - Creates a backtracking point. - - *) let push ( x : fixedpoint ) = Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) - (** - Backtrack one backtracking point. - - Note that an exception is thrown if Pop is called without a corresponding Push - - *) let pop ( x : fixedpoint ) = Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - (** - Update named rule into in the fixedpoint solver. - *) let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) - (** - Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. - *) let get_answer ( x : fixedpoint ) = let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in if (Z3native.is_null q) then @@ -5551,21 +3218,12 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - Retrieve explanation why fixedpoint engine returned status Unknown. - *) let get_reason_unknown ( x : fixedpoint ) = Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - (** - Retrieve the number of levels explored for a given predicate. - *) let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) - (** - Retrieve the cover of a predicate. - *) let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in if (Z3native.is_null q) then @@ -5573,82 +3231,40 @@ struct else Some (expr_of_ptr (z3obj_gc x) q) - (** - Add property about the predicate. - The property is added at level. - *) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) - (** - Retrieve internal string representation of fixedpoint object. - *) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - (** - Instrument the Datalog engine on which table representation to use for recursive predicate. - *) let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = let f2 x = (Symbol.gno x) in Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) - (** - Convert benchmark given as set of axioms, rules and queries to a string. - *) let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) - (** - Retrieve set of rules added to fixedpoint context. - *) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f - (** - Retrieve set of assertions added to fixedpoint context. - *) let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in Array.init n f - (** - Create a Fixedpoint context. - *) let mk_fixedpoint ( ctx : context ) = create ctx end -(** Global and context options - - Note: This module contains functions that set parameters/options for context - objects as well as functions that set options that are used globally, across - contexts.*) module Options = struct - (** - Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - - *) let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value - (** - Get a configuration parameter. - - Returns None if the parameter value does not exist. - - *) let get_param_value ( ctx : context ) ( id : string ) = let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in if not r then @@ -5656,62 +3272,21 @@ struct else Some v - (** - Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - - - - *) let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - (** - Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. - *) let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled end -(** Functions for handling SMT and SMT2 expressions and files *) + module SMT = struct - (** - Convert a benchmark into an SMT-LIB formatted string. - - @param name Name of the benchmark. The argument is optional. - @param logic The benchmark logic. - @param status The status string (sat, unsat, or unknown) - @param attributes Other attributes, such as source, difficulty or category. - @param assumptions Auxiliary assumptions. - @param formula Formula to be checked for consistency in conjunction with assumptions. - @return A string representation of the benchmark. - *) let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) (Boolean.gno formula) - (** - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays and - don't need to match the names of the sorts and declarations in the arrays - and . This is a useful feature since we can use arbitrary names to - reference sorts and declarations. - *) let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5728,10 +3303,6 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)) - (** - Parse the given file using the SMT-LIB parser. - - *) let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5748,65 +3319,34 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)) - (** - The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) - (** - The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in Array.init n f - - (** - The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) - (** - The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in Array.init n f - (** - The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) - (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in Array.init n f - (** - The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - - (** - The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. - *) + let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in Array.init n f - (** - Parse the given string using the SMT-LIB2 parser. - - - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. - *) let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5823,10 +3363,6 @@ struct (let f x = Symbol.gno x in (Array.map f decl_names)) (let f x = FuncDecl.gno x in (Array.map f decls)))) - (** - Parse the given file using the SMT-LIB2 parser. - - *) let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = let csn = (Array.length sort_names) in let cs = (Array.length sorts) in @@ -5845,34 +3381,9 @@ struct end -(* Global functions *) - -(** - * Set a global (or module) parameter, which is shared by all Z3 contexts. - * - * When a Z3 module is initialized it will use the value of these parameters - * when Z3_params objects are not provided. - * The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - * The character '.' is a delimiter (more later). - * The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - * Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - * This function can be used to set parameters for a specific Z3 module. - * This can be done by using .. - * For example: - * (set_global_param "pp.decimal" "true") - * will set the parameter "decimal" in the module "pp" to true. -*) let set_global_param ( id : string ) ( value : string ) = (Z3native.global_param_set id value) -(** - * Get a global (or module) parameter. - * - * Returns None if the parameter does not exist. - * The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. - * This function cannot be invoked simultaneously from different threads without synchronization. - * The result string stored in param_value is stored in a shared location. -*) let get_global_param ( id : string ) = let (r, v) = (Z3native.global_param_get id) in if not r then @@ -5880,11 +3391,5 @@ let get_global_param ( id : string ) = else Some v -(** - * Restore the value of all global (and module) parameters. - * - * This command will not affect already created objects (such as tactics and solvers) - * -*) let global_param_reset_all = Z3native.global_param_reset_all diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 87318d2a7..49a78f724 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -5,8 +5,6 @@ @author CM Wintersteiger (cwinter) 2012-12-17 *) - - (** Context objects. Most interactions with Z3 are interpreted in some context; many users will only @@ -39,17 +37,14 @@ val mk_context : (string * string) list -> context module Log : sig (** Open an interaction log file. - @param filename the name of the file to open. - @return True if opening the log file succeeds, false otherwise. - *) + @return True if opening the log file succeeds, false otherwise. *) (* CMW: "open" seems to be a reserved keyword? *) val open_ : string -> bool (** Closes the interaction log. *) val close : unit - (** Appends a user-provided string to the interaction log. - @param s the string to append*) + (** Appends a user-provided string to the interaction log. *) val append : string -> unit end @@ -102,12 +97,10 @@ sig (** A string representation of the symbol. *) val to_string : symbol -> string - (** - Creates a new symbol using an integer. + (** Creates a new symbol using an integer. Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. - *) + The legal range of unsigned integers is 0 to 2^30-1. *) val mk_int : context -> int -> symbol (** Creates a new symbol using a string. *) @@ -135,30 +128,21 @@ sig (** Retrieves the i-th object in the vector. - @param i Index - @return An AST - *) + @return An AST *) val get : ast_vector -> int -> ast (** Sets the i-th object in the vector. *) val set : ast_vector -> int -> ast -> unit - (** Resize the vector to . - @param newSize The new size of the vector. *) + (** Resize the vector to a new size. *) val resize : ast_vector -> int -> unit - (** - Add the AST to the back of the vector. The size - is increased by 1. - @param a An AST - *) + (** Add an ast to the back of the vector. The size + is increased by 1. *) val push : ast_vector -> ast -> unit - (** - Translates all ASTs in the vector to . - @param to_ctx A context - @return A new ASTVector - *) + (** Translates all ASTs in the vector to another context. + @return A new ASTVector *) val translate : ast_vector -> context -> ast_vector (** Retrieves a string representation of the vector. *) @@ -170,29 +154,18 @@ sig sig type ast_map - (** Checks whether the map contains the key . - @param k An AST - @return True if is a key in the map, false otherwise. *) + (** Checks whether the map contains a key. + @return True if the key in the map, false otherwise. *) val contains : ast_map -> ast -> bool - (** Finds the value associated with the key . - - This function signs an error when is not a key in the map. - @param k An AST - *) + (** Finds the value associated with the key. + This function signs an error when the key is not a key in the map. *) val find : ast_map -> ast -> ast - (** - Stores or replaces a new key/value pair in the map. - @param k The key AST - @param v The value AST - *) + (** Stores or replaces a new key/value pair in the map. *) val insert : ast_map -> ast -> ast -> unit - (** - Erases the key from the map. - @param k An AST - *) + (** Erases the key from the map.*) val erase : ast_map -> ast -> unit (** Removes all keys from the map. *) @@ -208,10 +181,8 @@ sig val to_string : ast_map -> string end - (** - The AST's hash code. - @return A hash code - *) + (** The AST's hash code. + @return A hash code *) val get_hash_code : ast -> int (** A unique identifier for the AST (unique among all ASTs). *) @@ -241,56 +212,39 @@ sig (** A string representation of the AST in s-expression notation. *) val to_sexpr : ast -> string - (** - Comparison operator. - @param a An AST - @param b An AST - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + (** Comparison operator. + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) val ( = ) : ast -> ast -> bool - (** - Object Comparison. - @param other Another ast - @return Negative if the object should be sorted before , positive if after else zero. - *) + (** Object Comparison. + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) val compare : ast -> ast -> int (** Operator < *) val ( < ) : ast -> ast -> int - (** - Translates (copies) the AST to the Context . - @param ctx A context - @return A copy of the AST which is associated with - *) + (** Translates (copies) the AST to another context. + @return A copy of the AST which is associated with the other context. *) val translate : ast -> context -> ast - (** - Wraps an AST. + (** Wraps an AST. - This function is used for transitions between native and - managed objects. Note that must be a - native object obtained from Z3 (e.g., through ) + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) and that it must have a correct reference count (see e.g., - . - - @param nativeObject The native pointer to wrap. - *) - val wrap : context -> Z3native.z3_ast -> ast + Z3native.inc_ref). *) + val wrap_ast : context -> Z3native.z3_ast -> ast - (** - Unwraps an AST. - This function is used for transitions between native and + (** Unwraps an AST. + This function is used for transitions between native and managed objects. It returns the native pointer to the AST. Note that AST objects are reference counted and unwrapping an AST disables automatic reference counting, i.e., all references to the IntPtr that is returned must be handled externally and through native calls (see e.g., - ). - - @param a The AST to unwrap. - *) + Z3native.inc_ref). + {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr end @@ -307,13 +261,9 @@ sig val sort_of_uninterpreted_sort : uninterpreted_sort -> sort val uninterpreted_sort_of_sort : sort -> uninterpreted_sort - (** - Comparison operator. - @param a A sort - @param b A sort - @return True if and are from the same context - and represent the same sort; false otherwise. - *) + (** Comparison operator. + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) val ( = ) : sort -> sort -> bool (** Returns a unique identifier for the sort. *) @@ -385,9 +335,7 @@ sig (** Creates a new function declaration. *) val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl - (** Creates a fresh function declaration with a name prefixed with . - - *) + (** Creates a fresh function declaration with a name prefixed with a prefix string. *) val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl @@ -397,16 +345,13 @@ sig (** Creates a new constant function declaration. *) val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - (** Creates a fresh constant function declaration with a name prefixed with . - - *) + (** Creates a fresh constant function declaration with a name prefixed with a prefix string. + {!mk_func_decl} + {!mk_func_decl} *) val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl (** Comparison operator. - @param a A func_decl - @param b A func_decl - @return True if and are from the same context - and represent the same func_decl; false otherwise. *) + @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) val ( = ) : func_decl -> func_decl -> bool (** A string representations of the function declaration. *) @@ -419,7 +364,7 @@ sig val get_arity : func_decl -> int (** The size of the domain of the function declaration - *) + {!get_arity} *) val get_domain_size : func_decl -> int (** The domain of the function declaration *) @@ -440,8 +385,7 @@ sig (** The parameters of the function declaration *) val get_parameters : func_decl -> Parameter.parameter list - (** Create expression that applies function to arguments. - @param args The arguments *) + (** Create expression that applies function to arguments. *) val apply : func_decl -> Expr.expr array -> Expr.expr end @@ -504,54 +448,153 @@ sig val to_string : params -> string end +(** General Expressions (terms) *) and Expr : sig - (** General Expressions (Terms) *) type expr = Expr of AST.ast val ast_of_expr : Expr.expr -> AST.ast val expr_of_ast : AST.ast -> Expr.expr + (** Returns a simplified version of the expression. + {!get_simplify_help} *) val simplify : Expr.expr -> Params.params option -> expr + + (** A string describing all available parameters to Expr.Simplify. *) val get_simplify_help : context -> string + + (** Retrieves parameter descriptions for simplifier. *) val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + + (** The function declaration of the function that is applied in this expression. *) val get_func_decl : Expr.expr -> FuncDecl.func_decl + + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) val get_bool_value : Expr.expr -> Z3enums.lbool + + (** The number of arguments of the expression. *) val get_num_args : Expr.expr -> int + + (** The arguments of the expression. *) val get_args : Expr.expr -> Expr.expr array + + (** Update the arguments of the expression using an array of expressions. + The number of new arguments should coincide with the current number of arguments. *) val update : Expr.expr -> Expr.expr array -> expr + + (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. *) val substitute : Expr.expr -> Expr.expr array -> Expr.expr array -> expr + + (** Substitute every occurrence of from in the expression with to. + {!substitute} *) val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr + + (** Substitute the free variables in the expression with the expressions in the expr array + + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) val substitute_vars : Expr.expr -> Expr.expr array -> expr + + (** Translates (copies) the term to another context. + @return A copy of the term which is associated with the other context *) val translate : Expr.expr -> context -> expr + + (** Returns a string representation of the expression. *) val to_string : Expr.expr -> string + + (** Indicates whether the term is a numeral *) val is_numeral : Expr.expr -> bool + + (** Indicates whether the term is well-sorted. + @return True if the term is well-sorted, false otherwise. *) val is_well_sorted : Expr.expr -> bool + + (** The Sort of the term. *) val get_sort : Expr.expr -> Sort.sort + + (** Indicates whether the term has Boolean sort. *) val is_bool : Expr.expr -> bool + + (** Indicates whether the term represents a constant. *) val is_const : Expr.expr -> bool + + (** Indicates whether the term is the constant true. *) val is_true : Expr.expr -> bool + + (** Indicates whether the term is the constant false. *) val is_false : Expr.expr -> bool + + (** Indicates whether the term is an equality predicate. *) val is_eq : Expr.expr -> bool + + (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) val is_distinct : Expr.expr -> bool + + (** Indicates whether the term is a ternary if-then-else term *) val is_ite : Expr.expr -> bool + + (** Indicates whether the term is an n-ary conjunction *) val is_and : Expr.expr -> bool + + (** Indicates whether the term is an n-ary disjunction *) val is_or : Expr.expr -> bool + + (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) val is_iff : Expr.expr -> bool + + (** Indicates whether the term is an exclusive or *) val is_xor : Expr.expr -> bool + + (** Indicates whether the term is a negation *) val is_not : Expr.expr -> bool + + (** Indicates whether the term is an implication *) val is_implies : Expr.expr -> bool + + (** Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) val is_label : Expr.expr -> bool + + (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) + val is_label_lit : Expr.expr -> bool + + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) val is_oeq : Expr.expr -> bool + + (** Creates a new constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) val mk_app : context -> FuncDecl.func_decl -> Expr.expr array -> expr + + (** Create a numeral of a given sort. + @return A Term with the goven value and sort *) val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) val mk_numeral_int : context -> int -> Sort.sort -> expr end +(** Boolean expressions *) module Boolean : sig type bool_sort = BoolSort of Sort.sort @@ -562,23 +605,53 @@ sig val bool_sort_of_sort : Sort.sort -> bool_sort val bool_expr_of_expr : Expr.expr -> bool_expr + (** Create a Boolean sort *) val mk_sort : context -> bool_sort + + (** Create a Boolean constant. *) val mk_const : context -> Symbol.symbol -> bool_expr + + (** Create a Boolean constant. *) val mk_const_s : context -> string -> bool_expr + + (** The true Term. *) val mk_true : context -> bool_expr + + (** The false Term. *) val mk_false : context -> bool_expr + + (** Creates a Boolean value. *) val mk_val : context -> bool -> bool_expr + + (** Creates the equality between two expr's. *) val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr + + (** Creates a distinct term. *) val mk_distinct : context -> Expr.expr array -> bool_expr + + (** Mk an expression representing not(a). *) val mk_not : context -> bool_expr -> bool_expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 iff t2. *) val mk_iff : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 -> t2. *) val mk_implies : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 xor t2. *) val mk_xor : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing the AND of args *) val mk_and : context -> bool_expr array -> bool_expr + + (** Create an expression representing the OR of args *) val mk_or : context -> bool_expr array -> bool_expr end +(** Quantifier expressions *) module Quantifier : sig type quantifier = Quantifier of Expr.expr @@ -586,7 +659,11 @@ sig val expr_of_quantifier : quantifier -> Expr.expr val quantifier_of_expr : Expr.expr -> quantifier + (** Quantifier patterns + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. *) module Pattern : sig type pattern = Pattern of AST.ast @@ -594,65 +671,94 @@ sig val ast_of_pattern : pattern -> AST.ast val pattern_of_ast : AST.ast -> pattern + (** The number of terms in the pattern. *) val get_num_terms : pattern -> int + + (** The terms in the pattern. *) val get_terms : pattern -> Expr.expr array + + (** A string representation of the pattern. *) val to_string : pattern -> string end + + (** The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) val get_index : Expr.expr -> int + + (** Indicates whether the quantifier is universal. *) val is_universal : quantifier -> bool + + (** Indicates whether the quantifier is existential. *) val is_existential : quantifier -> bool + + (** The weight of the quantifier. *) val get_weight : quantifier -> int + + (** The number of patterns. *) val get_num_patterns : quantifier -> int + + (** The patterns. *) val get_patterns : quantifier -> Pattern.pattern array + + (** The number of no-patterns. *) val get_num_no_patterns : quantifier -> int + + (** The no-patterns. *) val get_no_patterns : quantifier -> Pattern.pattern array - val get_num_bound : quantifier -> int + + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) val get_bound_variable_names : quantifier -> Symbol.symbol array + + (** The sorts of the bound variables. *) val get_bound_variable_sorts : quantifier -> Sort.sort array + + (** The body of the quantifier. *) val get_body : quantifier -> Boolean.bool_expr + + (** Creates a new bound variable. *) val mk_bound : context -> int -> Sort.sort -> Expr.expr + + (** Create a quantifier pattern. *) val mk_pattern : context -> Expr.expr array -> Pattern.pattern - val mk_forall : - context -> - Sort.sort array -> - Symbol.symbol array -> - Expr.expr -> - int option -> - Pattern.pattern array -> - Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier - val mk_forall_const : - context -> - Expr.expr array -> - Expr.expr -> - int option -> - Pattern.pattern array -> - Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier - val mk_exists : - context -> - Sort.sort array -> - Symbol.symbol array -> - Expr.expr -> - int option -> - Pattern.pattern array -> - Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier - val mk_exists_const : - context -> - Expr.expr array -> - Expr.expr -> - int option -> - Pattern.pattern array -> - Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier - val mk_quantifier : - context -> - bool -> - Expr.expr array -> - Expr.expr -> - int option -> - Pattern.pattern array -> - Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a universal Quantifier. *) + val mk_forall : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a universal Quantifier. *) + val mk_forall_const : context -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists_const : context -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> bool -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier end +(** Functions to manipulate Array expressions *) module Array_ : sig type array_sort = ArraySort of Sort.sort @@ -664,48 +770,159 @@ sig val array_expr_of_expr : Expr.expr -> array_expr + (** Create a new array sort. *) val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort + + (** Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) val is_store : Expr.expr -> bool + + (** Indicates whether the term is an array select. *) val is_select : Expr.expr -> bool + + (** Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) val is_constant_array : Expr.expr -> bool + + (** Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. *) val is_default_array : Expr.expr -> bool + + (** Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) val is_array_map : Expr.expr -> bool + + (** Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) val is_as_array : Expr.expr -> bool + + (** Indicates whether the term is of an array sort. *) val is_array : Expr.expr -> bool + + (** The domain of the array sort. *) val get_domain : array_sort -> Sort.sort + + (** The range of the array sort. *) val get_range : array_sort -> Sort.sort + + (** Create an array constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr + + (** Create an array constant. *) val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr - val mk_select : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + + (** Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + {!Array_.mk_sort} + {!mk_store} *) + val mk_select : context -> array_expr -> Expr.expr -> array_expr + + (** Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + {!Array_.mk_sort} + {!mk_select} *) + val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + + (** Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + {!Array_.mk_sort} + {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr + + (** Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + {!Array_.mk_sort} + {!mk_select} + {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> array_expr array -> array_expr + + (** Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) val mk_term_array : context -> array_expr -> array_expr end +(** Functions to manipulate Set expressions *) module Set : sig type set_sort = SetSort of Sort.sort val sort_of_set_sort : set_sort -> Sort.sort - val is_union : Expr.expr -> bool - val is_intersect : Expr.expr -> bool - val is_difference : Expr.expr -> bool - val is_complement : Expr.expr -> bool - val is_subset : Expr.expr -> bool + (** Create a set type. *) val mk_sort : context -> Sort.sort -> set_sort + + (** Indicates whether the term is set union *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is set intersection *) + val is_intersect : Expr.expr -> bool + + (** Indicates whether the term is set difference *) + val is_difference : Expr.expr -> bool + + (** Indicates whether the term is set complement *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is set subset *) + val is_subset : Expr.expr -> bool + + (** Create an empty set. *) val mk_empty : context -> Sort.sort -> Expr.expr + + (** Create the full set. *) val mk_full : context -> Sort.sort -> Expr.expr + + (** Add an element to the set. *) val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Remove an element from a set. *) val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the union of a list of sets. *) val mk_union : context -> Expr.expr array -> Expr.expr + + (** Take the intersection of a list of sets. *) val mk_intersection : context -> Expr.expr array -> Expr.expr + + (** Take the difference between two sets. *) val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the complement of a set. *) val mk_complement : context -> Expr.expr -> Expr.expr + + (** Check for set membership. *) val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Check for subsetness of sets. *) val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr end +(** Functions to manipulate Finite Domain expressions *) module FiniteDomain : sig type finite_domain_sort = FiniteDomainSort of Sort.sort @@ -713,13 +930,24 @@ sig val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort + (** Create a new finite domain sort. *) val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort + + (** Create a new finite domain sort. *) val mk_sort_s : context -> string -> int -> finite_domain_sort + + (** Indicates whether the term is of an array sort. *) val is_finite_domain : Expr.expr -> bool + + (** Indicates whether the term is a less than predicate over a finite domain. *) val is_lt : Expr.expr -> bool + + (** The size of the finite domain sort. *) val get_size : finite_domain_sort -> int end + +(** Functions to manipulate Relation expressions *) module Relation : sig type relation_sort = RelationSort of Sort.sort @@ -727,24 +955,92 @@ sig val sort_of_relation_sort : relation_sort -> Sort.sort val relation_sort_of_sort : Sort.sort -> relation_sort + (** Indicates whether the term is of a relation sort. *) val is_relation : Expr.expr -> bool + + (** Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. *) val is_store : Expr.expr -> bool + + (** Indicates whether the term is an empty relation *) val is_empty : Expr.expr -> bool + + (** Indicates whether the term is a test for the emptiness of a relation *) val is_is_empty : Expr.expr -> bool + + (** Indicates whether the term is a relational join *) val is_join : Expr.expr -> bool + + (** Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. *) val is_union : Expr.expr -> bool + + (** Indicates whether the term is the widening of two relations + The function takes two arguments. *) val is_widen : Expr.expr -> bool + + (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. *) val is_project : Expr.expr -> bool + + (** Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) val is_filter : Expr.expr -> bool + + (** Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) val is_negation_filter : Expr.expr -> bool + + (** Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. *) val is_rename : Expr.expr -> bool + + (** Indicates whether the term is the complement of a relation *) val is_complement : Expr.expr -> bool + + (** Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. *) val is_select : Expr.expr -> bool + + (** Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) val is_clone : Expr.expr -> bool + + (** The arity of the relation sort. *) val get_arity : relation_sort -> int + + (** The sorts of the columns of the relation sort. *) val get_column_sorts : relation_sort -> relation_sort array end +(** Functions to manipulate Datatype expressions *) module Datatype : sig type datatype_sort = DatatypeSort of Sort.sort @@ -755,74 +1051,136 @@ sig val expr_of_datatype_expr : datatype_expr -> Expr.expr val datatype_expr_of_expr : Expr.expr -> datatype_expr + (** Datatype Constructors *) module Constructor : sig - (** Constructors *) type constructor - val get_n : constructor -> int - val constructor_decl : constructor -> FuncDecl.func_decl - val tester_decl : constructor -> FuncDecl.func_decl - val accessor_decls : constructor -> FuncDecl.func_decl array + (** The number of fields of the constructor. *) val get_num_fields : constructor -> int + + (** The function declaration of the constructor. *) val get_constructor_decl : constructor -> FuncDecl.func_decl + + (** The function declaration of the tester. *) val get_tester_decl : constructor -> FuncDecl.func_decl + + (** The function declarations of the accessors *) val get_accessor_decls : constructor -> FuncDecl.func_decl array end + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + + (** Create a new datatype sort. *) val mk_sort : context -> Symbol.symbol -> Constructor.constructor array -> datatype_sort + + (** Create a new datatype sort. *) val mk_sort_s : context -> string -> Constructor.constructor array -> datatype_sort + + (** Create mutually recursive datatypes. *) val mk_sorts : context -> Symbol.symbol array -> Constructor.constructor array array -> datatype_sort array + + (** Create mutually recursive data-types. *) val mk_sorts_s : context -> string array -> Constructor.constructor array array -> datatype_sort array + + + (** The number of constructors of the datatype sort. *) val get_num_constructors : datatype_sort -> int + + (** The constructors. *) val get_constructors : datatype_sort -> FuncDecl.func_decl array + + (** The recognizers. *) val get_recognizers : datatype_sort -> FuncDecl.func_decl array + + (** The constructor accessors. *) val get_accessors : datatype_sort -> FuncDecl.func_decl array array end +(** Functions to manipulate Enumeration expressions *) module Enumeration : sig type enum_sort = EnumSort of Sort.sort val sort_of_enum_sort : enum_sort -> Sort.sort + (** Create a new enumeration sort. *) val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> enum_sort + + (** Create a new enumeration sort. *) val mk_sort_s : context -> string -> string array -> enum_sort + + (** The function declarations of the constants in the enumeration. *) val get_const_decls : enum_sort -> FuncDecl.func_decl array + + (** The test predicates for the constants in the enumeration. *) val get_tester_decls : enum_sort -> FuncDecl.func_decl array end +(** Functions to manipulate List expressions *) module List_ : sig type list_sort = ListSort of Sort.sort val sort_of_list_sort : list_sort -> Sort.sort + (** Create a new list sort. *) val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort + + (** Create a new list sort. *) val mk_list_s : context -> string -> Sort.sort -> list_sort + + (** The declaration of the nil function of this list sort. *) val get_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isNil function of this list sort. *) val get_is_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the cons function of this list sort. *) val get_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isCons function of this list sort. *) val get_is_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the head function of this list sort. *) val get_head_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the tail function of this list sort. *) val get_tail_decl : list_sort -> FuncDecl.func_decl + + (** The empty list. *) val nil : list_sort -> Expr.expr end +(** Functions to manipulate Tuple expressions *) module Tuple : sig type tuple_sort = TupleSort of Sort.sort val sort_of_tuple_sort : tuple_sort -> Sort.sort + (** Create a new tuple sort. *) val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> tuple_sort + + (** The constructor function of the tuple. *) val get_mk_decl : tuple_sort -> FuncDecl.func_decl + + (** The number of fields in the tuple. *) val get_num_fields : tuple_sort -> int + + (** The field declarations. *) val get_field_decls : tuple_sort -> FuncDecl.func_decl array end +(** Functions to manipulate arithmetic expressions *) module rec Arithmetic : sig type arith_sort = ArithSort of Sort.sort @@ -833,6 +1191,7 @@ sig val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr + (** Integer Arithmetic *) module rec Integer : sig type int_sort = IntSort of arith_sort @@ -845,20 +1204,59 @@ sig val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num - + + (** Create a new integer sort. *) val mk_sort : context -> int_sort + + (** Retrieve the int value. *) val get_int : int_num -> int + + (** Returns a string representation of the numeral. *) val to_string : int_num -> string + + (** Creates an integer constant. *) val mk_int_const : context -> Symbol.symbol -> int_expr + + (** Creates an integer constant. *) val mk_int_const_s : context -> string -> int_expr + + (** Create an expression representing t1 mod t2. + The arguments must have int type. *) val mk_mod : context -> int_expr -> int_expr -> int_expr + + (** Create an expression representing t1 rem t2. + The arguments must have int type. *) val mk_rem : context -> int_expr -> int_expr -> int_expr + + (** Create an integer numeral. *) val mk_int_numeral_s : context -> string -> int_num + + (** Create an integer numeral. + @return A Term with the given value and sort Integer *) val mk_int_numeral_i : context -> int -> int_num + + (** Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. *) val mk_int2real : context -> int_expr -> Real.real_expr + + (** Create an n-bit bit-vector from an integer argument. + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end + (** Real Arithmetic *) and Real : sig type real_sort = RealSort of arith_sort @@ -872,20 +1270,52 @@ sig val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + (** Create a real sort. *) val mk_sort : context -> real_sort + + (** The numerator of a rational numeral. *) val get_numerator : rat_num -> Integer.int_num + + (** The denominator of a rational numeral. *) val get_denominator : rat_num -> Integer.int_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as indicated by the int argument.*) val to_decimal_string : rat_num -> int -> string + + (** Returns a string representation of the numeral. *) val to_string : rat_num -> string + + (** Creates a real constant. *) val mk_real_const : context -> Symbol.symbol -> real_expr + + (** Creates a real constant. *) val mk_real_const_s : context -> string -> real_expr + + (** Create a real numeral from a fraction. + @return A Term with rational value and sort Real + {!mk_numeral_s} *) val mk_numeral_nd : context -> int -> int -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) val mk_numeral_s : context -> string -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) val mk_numeral_i : context -> int -> rat_num + + (** Creates an expression that checks whether a real number is an integer. *) val mk_is_integer : context -> real_expr -> Boolean.bool_expr + + (** Coerce a real to an integer. + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) val mk_real2int : context -> real_expr -> Integer.int_expr end + (** Algebraic Numbers *) and AlgebraicNumber : sig type algebraic_num = AlgebraicNum of arith_expr @@ -893,45 +1323,121 @@ sig val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num + (** Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) val to_upper : algebraic_num -> int -> Real.rat_num + + (** Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) val to_lower : algebraic_num -> int -> Real.rat_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as the int argument provided.*) val to_decimal_string : algebraic_num -> int -> string + + (** Returns a string representation of the numeral. *) val to_string : algebraic_num -> string end + (** Indicates whether the term is of integer sort. *) val is_int : Expr.expr -> bool + + (** Indicates whether the term is an arithmetic numeral. *) val is_arithmetic_numeral : Expr.expr -> bool + + (** Indicates whether the term is a less-than-or-equal *) val is_le : Expr.expr -> bool + + (** Indicates whether the term is a greater-than-or-equal *) val is_ge : Expr.expr -> bool + + (** Indicates whether the term is a less-than *) val is_lt : Expr.expr -> bool + + (** Indicates whether the term is a greater-than *) val is_gt : Expr.expr -> bool + + (** Indicates whether the term is addition (binary) *) val is_add : Expr.expr -> bool + + (** Indicates whether the term is subtraction (binary) *) val is_sub : Expr.expr -> bool + + (** Indicates whether the term is a unary minus *) val is_uminus : Expr.expr -> bool + + (** Indicates whether the term is multiplication (binary) *) val is_mul : Expr.expr -> bool + + (** Indicates whether the term is division (binary) *) val is_div : Expr.expr -> bool + + (** Indicates whether the term is integer division (binary) *) val is_idiv : Expr.expr -> bool + + (** Indicates whether the term is remainder (binary) *) val is_remainder : Expr.expr -> bool + + (** Indicates whether the term is modulus (binary) *) val is_modulus : Expr.expr -> bool + + (** Indicates whether the term is a coercion of integer to real (unary) *) val is_inttoreal : Expr.expr -> bool + + (** Indicates whether the term is a coercion of real to integer (unary) *) val is_real_to_int : Expr.expr -> bool + + (** Indicates whether the term is a check that tests whether a real is integral (unary) *) val is_real_is_int : Expr.expr -> bool + + (** Indicates whether the term is of sort real. *) val is_real : Expr.expr -> bool + + (** Indicates whether the term is an integer numeral. *) val is_int_numeral : Expr.expr -> bool + + (** Indicates whether the term is a real numeral. *) val is_rat_num : Expr.expr -> bool + + (** Indicates whether the term is an algebraic number *) val is_algebraic_number : Expr.expr -> bool + + (** Create an expression representing t[0] + t[1] + .... *) val mk_add : context -> arith_expr array -> arith_expr + + (** Create an expression representing t[0] * t[1] * .... *) val mk_mul : context -> arith_expr array -> arith_expr + + (** Create an expression representing t[0] - t[1] - .... *) val mk_sub : context -> arith_expr array -> arith_expr + + (** Create an expression representing -t. *) val mk_unary_minus : context -> arith_expr -> arith_expr + + (** Create an expression representing t1 / t2. *) val mk_div : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 ^ t2. *) val mk_power : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 < t2 *) val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 <= t2 *) val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 > t2 *) val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 >= t2 *) val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr end +(** Functions to manipulate bit-vector expressions *) and BitVector : sig type bitvec_sort = BitVecSort of Sort.sort @@ -945,280 +1451,1229 @@ sig val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + (** Create a new bit-vector sort. *) val mk_sort : context -> int -> bitvec_sort + + (** Indicates whether the terms is of bit-vector sort. *) val is_bv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector numeral *) val is_bv_numeral : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value one *) val is_bv_bit1 : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value zero *) val is_bv_bit0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unary minus *) val is_bv_uminus : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector addition (binary) *) val is_bv_add : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector subtraction (binary) *) val is_bv_sub : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector multiplication (binary) *) val is_bv_mul : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division (binary) *) val is_bv_sdiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division (binary) *) val is_bv_udiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder (binary) *) val is_bv_SRem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) val is_bv_urem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus *) val is_bv_smod : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division by zero *) val is_bv_sdiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division by zero *) val is_bv_udiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder by zero *) val is_bv_srem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder by zero *) val is_bv_urem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus by zero *) val is_bv_smod0 : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) val is_bv_ule : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than-or-equal *) val is_bv_sle : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) val is_bv_uge : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) val is_bv_sge : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than *) val is_bv_ult : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than *) val is_bv_slt : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than *) val is_bv_ugt : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than *) val is_bv_sgt : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise AND *) val is_bv_and : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise OR *) val is_bv_or : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOT *) val is_bv_not : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XOR *) val is_bv_xor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NAND *) val is_bv_nand : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOR *) val is_bv_nor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XNOR *) val is_bv_xnor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector concatenation (binary) *) val is_bv_concat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector sign extension *) val is_bv_signextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector zero extension *) val is_bv_zeroextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector extraction *) val is_bv_extract : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector repetition *) val is_bv_repeat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce OR *) val is_bv_reduceor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce AND *) val is_bv_reduceand : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector comparison *) val is_bv_comp : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector shift left *) val is_bv_shiftleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector logical shift right *) val is_bv_shiftrightlogical : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector arithmetic shift left *) val is_bv_shiftrightarithmetic : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left *) val is_bv_rotateleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right *) val is_bv_rotateright : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) val is_bv_rotateleftextended : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) val is_bv_rotaterightextended : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + + (** Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_int_to_bv : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_bv_to_int : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) val is_bv_carry : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) val is_bv_xor3 : Expr.expr -> bool + + (** The size of a bit-vector sort. *) val get_size : bitvec_sort -> int + + (** Retrieve the int value. *) val get_int : bitvec_num -> int + + (** Returns a string representation of the numeral. *) val to_string : bitvec_num -> string + + (** Creates a bit-vector constant. *) val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + + (** Creates a bit-vector constant. *) val mk_const_s : context -> string -> int -> bitvec_expr + + (** Bitwise negation. + The argument must have a bit-vector sort. *) val mk_not : context -> bitvec_expr -> Expr.expr + + (** Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) val mk_redand : context -> bitvec_expr -> Expr.expr + + (** Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) val mk_redor : context -> bitvec_expr -> Expr.expr + + (** Bitwise conjunction. + The arguments must have a bit-vector sort. *) val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise disjunction. + The arguments must have a bit-vector sort. *) val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XOR. + The arguments must have a bit-vector sort. *) val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NAND. + The arguments must have a bit-vector sort. *) val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NOR. + The arguments must have a bit-vector sort. *) val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XNOR. + The arguments must have a bit-vector sort. *) val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Standard two's complement unary minus. + The arguments must have a bit-vector sort. *) val mk_neg : context -> bitvec_expr -> bitvec_expr + + (** Two's complement addition. + The arguments must have the same bit-vector sort. *) val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement subtraction. + The arguments must have the same bit-vector sort. *) val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement multiplication. + The arguments must have the same bit-vector sort. *) val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned less-than + + The arguments must have the same bit-vector sort. *) val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than + + The arguments must have the same bit-vector sort. *) val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. *) val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. *) val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. *) val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. *) val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater-than. + + The arguments must have the same bit-vector sort. *) val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. *) val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). *) val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bit-vector extraction. + + Extract the bits between two limits from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. *) val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. *) val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. *) val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector repetition. *) val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + + (** Shift left. + + It is equivalent to multiplication by 2^x where \c x is the value of third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling.*) val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of \c t to the left \c i times. *) + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of \c t to the right \c i times.*) + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of the second argument to the left.*) + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of the second argument to the right. *) + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Create an integer from the bit-vector argument + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in the argument. + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function.*) val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + + (** Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. *) val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. *) val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. *) val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. *) val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. *) val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. *) val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. *) val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. *) val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a bit-vector numeral. *) val mk_numeral : context -> string -> int -> bitvec_num end +(** Functions to manipulate proof expressions *) module Proof : sig + (** Indicates whether the term is a Proof for the expression 'true'. *) val is_true : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact asserted by the user. *) val is_asserted : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) val is_goal : Expr.expr -> bool + + (** Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) val is_modus_ponens : Expr.expr -> bool + + (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) val is_reflexivity : Expr.expr -> bool + + (** Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) val is_symmetry : Expr.expr -> bool + + (** Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) val is_transitivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) val is_Transitivity_star : Expr.expr -> bool + + (** Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) val is_monotonicity : Expr.expr -> bool + + (** Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) val is_quant_intro : Expr.expr -> bool + + (** Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) val is_distributivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) val is_and_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) val is_or_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) val is_rewrite : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) val is_rewrite_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) val is_pull_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) val is_pull_quant_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) val is_push_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) val is_elim_unused_vars : Expr.expr -> bool + + (** Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) val is_der : Expr.expr -> bool + + (** Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) *) val is_quant_inst : Expr.expr -> bool + + (** Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. *) val is_hypothesis : Expr.expr -> bool + + (** Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) val is_lemma : Expr.expr -> bool + + (** Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) val is_unit_resolution : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) *) val is_iff_true : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) *) val is_iff_false : Expr.expr -> bool + + (** Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) val is_commutativity : Expr.expr -> bool + + (** Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) val is_def_axiom : Expr.expr -> bool + + (** Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) val is_def_intro : Expr.expr -> bool + + (** Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) val is_apply_def : Expr.expr -> bool + + (** Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) *) val is_iff_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) val is_nnf_pos : Expr.expr -> bool + + (** Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) val is_nnf_neg : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_nnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_cnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) val is_skolemize : Expr.expr -> bool + + (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) val is_modus_ponens_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) val is_theory_lemma : Expr.expr -> bool end +(** Goals + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) module Goal : sig type goal + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. *) val get_precision : goal -> Z3enums.goal_prec + + (** Indicates whether the goal is precise. *) val is_precise : goal -> bool + + (** Indicates whether the goal is an under-approximation. *) val is_underapproximation : goal -> bool + + (** Indicates whether the goal is an over-approximation. *) val is_overapproximation : goal -> bool + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) val is_garbage : goal -> bool + + (** Adds the constraints to the given goal. *) val assert_ : goal -> Boolean.bool_expr array -> unit + + (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) val get_depth : goal -> int + + (** Erases all formulas from the given goal. *) val reset : goal -> unit + + (** The number of formulas in the goal. *) val get_size : goal -> int + + (** The formulas in the goal. *) val get_formulas : goal -> Boolean.bool_expr array + + (** The number of formulas, subformulas and terms in the goal. *) val get_num_exprs : goal -> int + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) val is_decided_sat : goal -> bool + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) val is_decided_unsat : goal -> bool + + (** Translates (copies) the Goal to another context.. *) val translate : goal -> context -> goal + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) val simplify : goal -> Params.params option -> goal + + (** Creates a new Goal. + + Note that the Context must have been created with proof generation support if + the fourth argument is set to true here. *) val mk_goal : context -> bool -> bool -> bool -> goal + + (** A string representation of the Goal. *) val to_string : goal -> string end +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) module Model : sig type model + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. *) module FuncInterp : sig type func_interp - + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. *) module FuncEntry : sig type func_entry - + + (** Return the (symbolic) value of this entry. + *) val get_value : func_entry -> Expr.expr + + (** The number of arguments of the entry. + *) val get_num_args : func_entry -> int + + (** The arguments of the function entry. + *) val get_args : func_entry -> Expr.expr array + + (** A string representation of the function entry. + *) val to_string : func_entry -> string end + (** The number of entries in the function interpretation. *) val get_num_entries : func_interp -> int + + (** The entries in the function interpretation *) val get_entries : func_interp -> FuncEntry.func_entry array + + (** The (symbolic) `else' value of the function interpretation. *) val get_else : func_interp -> Expr.expr + + (** The arity of the function interpretation *) val get_arity : func_interp -> int + + (** A string representation of the function interpretation. *) val to_string : func_interp -> string end + (** Retrieves the interpretation (the assignment) of a func_decl in the model. + An expression if the function has an interpretation in the model, null otherwise. *) val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of an expression in the model. + An expression if the constant has an interpretation in the model, null otherwise. *) val get_const_interp_e : model -> Expr.expr -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option + + (** The number of constant interpretations in the model. *) val get_num_consts : model -> int + + (** The function declarations of the constants in the model. *) val get_const_decls : model -> FuncDecl.func_decl array + + (** The number of function interpretations in the model. *) val get_num_funcs : model -> int + + (** The function declarations of the function interpretations in the model. *) val get_func_decls : model -> FuncDecl.func_decl array + + (** All symbols that have an interpretation in the model. *) val get_decls : model -> FuncDecl.func_decl array + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) exception ModelEvaluationFailedException of string + + (** Evaluates an expression in the current model. + + This function may fail if the argument contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + *) val eval : model -> Expr.expr -> bool -> Expr.expr + + (** Alias for eval. *) val evaluate : model -> Expr.expr -> bool -> Expr.expr + + (** The number of uninterpreted sorts that the model has an interpretation for. *) val get_num_sorts : model -> int + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + {!get_num_sorts} + {!sort_universe} *) val get_sorts : model -> Sort.sort array + + (** The finite set of distinct values that represent the interpretation of a sort. + {!get_sorts} + @returns An array of expressions, where each is an element of the universe of the sort *) val sort_universe : model -> Sort.sort -> AST.ASTVector.ast_vector array + + (** Conversion of models to strings. + A string representation of the model. *) val to_string : model -> string end +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) module Probe : sig type probe + (** Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float + + (** The number of supported Probes. *) val get_num_probes : context -> int + + (** The names of all supported Probes. *) val get_probe_names : context -> string array + + (** Returns a string containing a description of the probe with the given name. *) val get_probe_description : context -> string -> string + + (** Creates a new Probe. *) val mk_probe : context -> string -> probe + + (** Create a probe that always evaluates to a float value. *) val const : context -> float -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than the value returned by second argument *) val lt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than the value returned by second argument *) val gt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than or equal the value returned by second argument *) val le : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than or equal the value returned by second argument *) val ge : context -> probe -> probe -> probe + + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is equal the value returned by second argument *) val eq : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) val and_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) val or_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) val not_ : context -> probe -> probe end +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) module Tactic : sig type tactic + (** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) module ApplyResult : sig type apply_result + (** The number of Subgoals. *) val get_num_subgoals : apply_result -> int + + (** Retrieves the subgoals from the apply_result. *) val get_subgoals : apply_result -> Goal.goal array + + (** Retrieves a subgoal from the apply_result. *) val get_subgoal : apply_result -> int -> Goal.goal + + (** Convert a model for a subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g *) val convert_model : apply_result -> int -> Model.model -> Model.model + + (** A string representation of the ApplyResult. *) val to_string : apply_result -> string end + (** A string containing a description of parameters accepted by the tactic. *) val get_help : tactic -> string + + (** Retrieves parameter descriptions for Tactics. *) val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs + + (** Apply the tactic to the goal. *) val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result + + (** The number of supported tactics. *) val get_num_tactics : context -> int + + (** The names of all supported tactics. *) val get_tactic_names : context -> string array + + (** Returns a string containing a description of the tactic with the given name. *) val get_tactic_description : context -> string -> string + + (** Creates a new Tactic. *) val mk_tactic : context -> string -> tactic + + (** Create a tactic that applies one tactic to a Goal and + then another one to every subgoal produced by the first one. *) val and_then : context -> tactic -> tactic -> tactic array -> tactic + + (** Create a tactic that first applies one tactic to a Goal and + if it fails then returns the result of another tactic applied to the Goal. *) val or_else : context -> tactic -> tactic -> tactic + + (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). + + If the tactic does not terminate within the timeout, then it fails. *) val try_for : context -> tactic -> int -> tactic + + (** Create a tactic that applies one tactic to a given goal if the probe + evaluates to true. + + If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) val when_ : context -> Probe.probe -> tactic -> tactic + + (** Create a tactic that applies a tactic to a given goal if the probe + evaluates to true and another tactic otherwise. *) val cond : context -> Probe.probe -> tactic -> tactic -> tactic + + (** Create a tactic that keeps applying one tactic until the goal is not + modified anymore or the maximum number of iterations is reached. *) val repeat : context -> tactic -> int -> tactic + + (** Create a tactic that just returns the given goal. *) val skip : context -> tactic + + (** Create a tactic always fails. *) val fail : context -> tactic + + (** Create a tactic that fails if the probe evaluates to false. *) val fail_if : context -> Probe.probe -> tactic + + (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) val fail_if_not_decided : context -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. *) val using_params : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. + Alias for UsingParams*) val with_ : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies the given tactics in parallel. *) val par_or : context -> tactic array -> tactic + + (** Create a tactic that applies a tactic to a given goal and then another tactic + to every subgoal produced by the first one. The subgoals are processed in parallel. *) val par_and_then : context -> tactic -> tactic -> tactic + + (** Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) val interrupt : context -> unit end +(** Solvers *) module Solver : sig type solver @@ -1226,108 +2681,388 @@ sig val string_of_status : status -> string + (** Objects that track statistical information about solvers. *) module Statistics : sig type statistics + (** Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) module Entry : sig type statistics_entry + (** The key of the entry. *) val get_key : statistics_entry -> string + + (** The int-value of the entry. *) val get_int : statistics_entry -> int + + (** The float-value of the entry. *) val get_float : statistics_entry -> float + + (** True if the entry is uint-valued. *) val is_int : statistics_entry -> bool + + (** True if the entry is double-valued. *) val is_float : statistics_entry -> bool + + (** The string representation of the the entry's value. *) val to_string_value : statistics_entry -> string + + (** The string representation of the entry (key and value) *) val to_string : statistics_entry -> string end + (** A string representation of the statistical data. *) val to_string : statistics -> string + + (** The number of statistical data. *) val get_size : statistics -> int + + (** The data entries. *) val get_entries : statistics -> Entry.statistics_entry array + + (** The statistical counters. *) val get_keys : statistics -> string array + + (** The value of a particular statistical counter. *) val get : statistics -> string -> Entry.statistics_entry option end + (** A string that describes all available solver parameters. *) val get_help : solver -> string + + (** Sets the solver parameters. *) val set_parameters : solver -> Params.params -> unit + + (** Retrieves parameter descriptions for solver. *) val get_param_descrs : solver -> Params.ParamDescrs.param_descrs + + (** The current number of backtracking points (scopes). + {!pop} + {!push} *) val get_num_scopes : solver -> int + + (** Creates a backtracking point. + {!pop} *) val push : solver -> unit + + (** Backtracks a number of backtracking points. + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) val pop : solver -> int -> unit + + (** Resets the Solver. + This removes all assertions from the solver. *) val reset : solver -> unit + + (** Assert a constraint (or multiple) into the solver. *) val assert_ : solver -> Boolean.bool_expr array -> unit + + (** * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track_a : solver -> Boolean.bool_expr array -> Boolean.bool_expr array -> unit + + (** * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit + + (** The number of assertions in the solver. *) val get_num_assertions : solver -> int + + (** The set of asserted formulas. *) val get_assertions : solver -> Boolean.bool_expr array + + (** Checks whether the assertions in the solver are consistent or not. + + {!Model} + {!get_unsat_core} + {!Proof} *) val check : solver -> Boolean.bool_expr array -> status + + (** The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. *) val get_model : solver -> Model.model option + + (** The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. *) val get_proof : solver -> Expr.expr option + + (** The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. *) val get_unsat_core : solver -> AST.ASTVector.ast_vector array + + (** A brief justification of why the last call to Check returned UNKNOWN. *) val get_reason_unknown : solver -> string + + (** Solver statistics. *) val get_statistics : solver -> Statistics.statistics + + (** Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) val mk_solver : context -> Symbol.symbol option -> solver + + (** Creates a new (incremental) solver. + {!mk_solver} *) val mk_solver_s : context -> string -> solver + + (** Creates a new (incremental) solver. *) val mk_simple_solver : context -> solver + + (** Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) val mk_solver_t : context -> Tactic.tactic -> solver + + (** A string representation of the solver. *) val to_string : solver -> string end +(** Fixedpoint solving *) module Fixedpoint : sig type fixedpoint + (** A string that describes all available fixedpoint solver parameters. *) val get_help : fixedpoint -> string + + (** Sets the fixedpoint solver parameters. *) val set_params : fixedpoint -> Params.params -> unit + + (** Retrieves parameter descriptions for Fixedpoint solver. *) val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs + + (** Assert a constraints into the fixedpoint solver. *) val assert_ : fixedpoint -> Boolean.bool_expr array -> unit + + (** Register predicate as recursive relation. *) val register_relation : fixedpoint -> FuncDecl.func_decl -> unit + + (** Add rule into the fixedpoint solver. *) val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit + + (** Add table fact to the fixedpoint solver. *) val add_fact : fixedpoint -> FuncDecl.func_decl -> int array -> unit + + (** Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) val query : fixedpoint -> Boolean.bool_expr -> Solver.status + + (** Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) val query_r : fixedpoint -> FuncDecl.func_decl array -> Solver.status + + (** Creates a backtracking point. + {!pop} *) val push : fixedpoint -> unit + + (** Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + {!push} *) val pop : fixedpoint -> unit + + (** Update named rule into in the fixedpoint solver. *) val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit + + (** Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. *) val get_answer : fixedpoint -> Expr.expr option + + (** Retrieve explanation why fixedpoint engine returned status Unknown. *) val get_reason_unknown : fixedpoint -> string + + (** Retrieve the number of levels explored for a given predicate. *) val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int + + (** Retrieve the cover of a predicate. *) val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option + + (** Add property about the predicate. + The property is added at level. *) val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit + + (** Retrieve internal string representation of fixedpoint object. *) val to_string : fixedpoint -> string + + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol array -> unit + + (** Convert benchmark given as set of axioms, rules and queries to a string. *) val to_string_q : fixedpoint -> Boolean.bool_expr array -> string + + (** Retrieve set of rules added to fixedpoint context. *) val get_rules : fixedpoint -> Boolean.bool_expr array + + (** Retrieve set of assertions added to fixedpoint context. *) val get_assertions : fixedpoint -> Boolean.bool_expr array + + (** Create a Fixedpoint context. *) val mk_fixedpoint : context -> fixedpoint end +(** Global and context options + + Note: This module contains functions that set parameters/options for context + objects as well as functions that set options that are used globally, across + contexts.*) module Options : sig + (** Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + {!get_param_value} *) val update_param_value : context -> string -> string -> unit + + (** Get a configuration parameter. + + Returns None if the parameter value does not exist. + {!update_param_value} *) val get_param_value : context -> string -> string option + + (** Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) val set_print_mode : context -> Z3enums.ast_print_mode -> unit + + (** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) val toggle_warning_messages : bool -> unit end +(** Functions for handling SMT and SMT2 expressions and files *) module SMT : sig + (** Convert a benchmark into an SMT-LIB formatted string. + + @return A string representation of the benchmark. *) val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr array -> Boolean.bool_expr -> string + + (** Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays in the third and fifth argument + don't need to match the names of the sorts and declarations in the arrays in the fourth + and sixth argument. This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) val parse_smtlib_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit + + (** Parse the given file using the SMT-LIB parser. + {!parse_smtlib_string} *) val parse_smtlib_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit + + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_formulas : context -> int + + (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_smtlib_formulas : context -> Boolean.bool_expr array + + (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_assumptions : context -> int + + (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_smtlib_assumptions : context -> Boolean.bool_expr array + + (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_decls : context -> int + + (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_smtlib_decls : context -> FuncDecl.func_decl array + + (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_sorts : context -> int + + (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_smtlib_sorts : context -> Sort.sort array + + (** Parse the given string using the SMT-LIB2 parser. + + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) val parse_smtlib2_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr + + (** Parse the given file using the SMT-LIB2 parser. + {!parse_smtlib2_string} *) val parse_smtlib2_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr end +(** Set a global (or module) parameter, which is shared by all Z3 contexts. + + When a Z3 module is initialized it will use the value of these parameters + when Z3_params objects are not provided. + The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + The character '.' is a delimiter (more later). + The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + This function can be used to set parameters for a specific Z3 module. + This can be done by using .. + For example: + (set_global_param "pp.decimal" "true") + will set the parameter "decimal" in the module "pp" to true. +*) val set_global_param : string -> string -> unit + +(** Get a global (or module) parameter. + + Returns None if the parameter does not exist. + The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + This function cannot be invoked simultaneously from different threads without synchronization. + The result string stored in param_value is stored in a shared location. +*) val get_global_param : string -> string option + +(** Restore the value of all global (and module) parameters. + + This command will not affect already created objects (such as tactics and solvers) + {!set_global_param} +*) val global_param_reset_all : unit From 79d0c32c919a18b175b1d33e6b64b7a0caa1319a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 00:29:51 +0000 Subject: [PATCH 428/646] ML API: replaced arrays with lists. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 46 ++-- src/api/ml/z3.ml | 507 +++++++++++++++++++------------------- src/api/ml/z3.mli | 184 +++++++------- 3 files changed, 371 insertions(+), 366 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 6dfe11623..31f31d566 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -33,13 +33,13 @@ let model_converter_test ( ctx : context ) = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [| (mk_gt ctx xr + (Goal.assert_ g4 [ (mk_gt ctx xr (arith_expr_of_real_expr (real_expr_of_rat_num - (Real.mk_numeral_nd ctx 10 1)))) |]) ; - (Goal.assert_ g4 [| (mk_eq ctx + (Real.mk_numeral_nd ctx 10 1)))) ]) ; + (Goal.assert_ g4 [ (mk_eq ctx (expr_of_arith_expr yr) - (expr_of_arith_expr (Arithmetic.mk_add ctx [| xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) |]) ) ) |] ) ; - (Goal.assert_ g4 [| (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) |]) ; + (expr_of_arith_expr (Arithmetic.mk_add ctx [ xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) ]) ) ) ] ) ; + (Goal.assert_ g4 [ (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -50,7 +50,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ); ( - let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") [||]) g4 None) in + let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") []) g4 None) in if ((get_num_subgoals ar) == 1 && ((is_decided_sat (get_subgoal ar 0)) || (is_decided_unsat (get_subgoal ar 0)))) then @@ -59,9 +59,9 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ; let solver = (mk_solver ctx None) in - let f e = (Solver.assert_ solver [| e |]) in - ignore (Array.map f (get_formulas (get_subgoal ar 0))) ; - let q = (check solver [||]) in + let f e = (Solver.assert_ solver [ e ]) in + ignore (List.map f (get_formulas (get_subgoal ar 0))) ; + let q = (check solver []) in if q != SATISFIABLE then raise (TestFailedException "") else @@ -84,23 +84,23 @@ let basic_tests ( ctx : context ) = let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in - let domain = [| bs; bs |] in + let domain = [ bs; bs ] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f - [| (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) |]) in - let fargs2 = [| (mk_fresh_const ctx "cp" bs) |] in - let domain2 = [| bs |] in + [ (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) ]) in + let fargs2 = [ (mk_fresh_const ctx "cp" bs) ] in + let domain2 = [ bs ] in let fapp2 = (mk_app ctx (mk_fresh_func_decl ctx "fp" domain2 bs) fargs2) in let trivial_eq = (mk_eq ctx fapp fapp) in let nontrivial_eq = (mk_eq ctx fapp fapp2) in let g = (mk_goal ctx true false false) in - (Goal.assert_ g [| trivial_eq |]) ; - (Goal.assert_ g [| nontrivial_eq |]) ; + (Goal.assert_ g [ trivial_eq ]) ; + (Goal.assert_ g [ nontrivial_eq ]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; ( let solver = (mk_solver ctx None) in - (Array.iter (fun a -> (Solver.assert_ solver [| a |])) (get_formulas g)) ; - if (check solver [||]) != SATISFIABLE then + (List.iter (fun a -> (Solver.assert_ solver [ a ])) (get_formulas g)) ; + if (check solver []) != SATISFIABLE then raise (TestFailedException "") else Printf.printf "Test passed.\n" @@ -122,11 +122,11 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [| (mk_eq ctx + (Goal.assert_ g [ (mk_eq ctx (mk_numeral_int ctx 1 (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) (mk_numeral_int ctx 2 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) |] ) + (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) ] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -147,7 +147,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [| (Boolean.mk_false ctx) |]) ; + (Goal.assert_ g2 [ (Boolean.mk_false ctx) ]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -159,10 +159,10 @@ let basic_tests ( ctx : context ) = let g3 = (mk_goal ctx true true false) in let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - (Goal.assert_ g3 [| (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; - (Goal.assert_ g3 [| (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) |]) ; + (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; + (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; let constr = (mk_eq ctx xc yc) in - (Goal.assert_ g3 [| constr |] ) ; + (Goal.assert_ g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b1e40fcac..56d319c1a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -79,10 +79,6 @@ struct let z3obj_nil_ref x y = () - let array_to_native a = - let f e = (z3obj_gno e) in - Array.map f a - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> let res : z3_native_object = { m_ctx = ctx ; m_n_obj = null ; @@ -127,6 +123,9 @@ let mk_list ( f : int -> 'a ) ( n : int ) = in mk_list' f 0 n [] +let list_of_array ( x : _ array ) = + let f i = (Array.get x i) in + mk_list f (Array.length x) let mk_context ( cfg : ( string * string ) list ) = create_context cfg @@ -180,6 +179,10 @@ struct match x with | S_Int(n) -> (z3obj_gno n) | S_Str(n) -> (z3obj_gno n) + + let symbol_lton ( a : symbol list ) = + let f ( e : symbol ) = (gno e) in + Array.of_list (List.map f a) let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL @@ -197,13 +200,13 @@ struct let mk_string ( ctx : context ) ( s : string ) = S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - let mk_ints ( ctx : context ) ( names : int array ) = + let mk_ints ( ctx : context ) ( names : int list ) = let f elem = mk_int ( ctx : context ) elem in - (Array.map f names) + (List.map f names) - let mk_strings ( ctx : context ) ( names : string array ) = + let mk_strings ( ctx : context ) ( names : string list ) = let f elem = mk_string ( ctx : context ) elem in - (Array.map f names) + (List.map f names) end @@ -292,7 +295,9 @@ struct Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) let get_keys ( x : ast_map ) = - ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) + let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let f i = (ASTVector.get av i) in + mk_list f (ASTVector.get_size av) let to_string ( x : ast_map ) = Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) @@ -376,10 +381,13 @@ struct else UninterpretedSort(s) - let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let sort_lton ( a : sort list ) = + let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) let ( = ) : sort -> sort -> bool = fun a b -> (a == b) || @@ -438,9 +446,9 @@ sig val get_func_decl : parameter -> func_decl val get_rational : parameter -> string end - val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl - val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl - val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl val mk_const_decl_s : context -> string -> Sort.sort -> func_decl val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl @@ -449,13 +457,13 @@ sig val get_id : func_decl -> int val get_arity : func_decl -> int val get_domain_size : func_decl -> int - val get_domain : func_decl -> Sort.sort array + val get_domain : func_decl -> Sort.sort list val get_range : func_decl -> Sort.sort val get_decl_kind : func_decl -> Z3enums.decl_kind val get_name : func_decl -> Symbol.symbol val get_num_parameters : func_decl -> int val get_parameters : func_decl -> Parameter.parameter list - val apply : func_decl -> Expr.expr array -> Expr.expr + val apply : func_decl -> Expr.expr list -> Expr.expr end = struct type func_decl = FuncDecl of AST.ast @@ -467,23 +475,21 @@ end = struct let ast_of_func_decl f = match f with FuncDecl(x) -> x - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (AST.ptr_of_ast (ast_of_sort x)) in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (Array.length domain) (Array.map f domain) (Sort.gno range))) ; + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = let res = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.inc_ref ; dec_ref = Z3native.dec_ref } in - let f x = (AST.ptr_of_ast (ast_of_sort x)) in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (Array.length domain) (Array.map f domain) (Sort.gno range))) ; + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; (z3obj_create res) ; FuncDecl(res) @@ -548,23 +554,23 @@ end = struct | _ -> raise (Z3native.Exception "parameter is not a rational string") end - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = create_ndr ctx name domain range - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort ) = + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = mk_func_decl ctx (Symbol.mk_string ctx name) domain range - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort ) = + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = create_pdr ctx prefix domain range let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_ndr ctx name [||] range + create_ndr ctx name [] range let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = - create_ndr ctx (Symbol.mk_string ctx name) [||] range + create_ndr ctx (Symbol.mk_string ctx name) [] range let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = - create_pdr ctx prefix [||] range + create_pdr ctx prefix [] range let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || @@ -584,7 +590,7 @@ end = struct let get_domain ( x : func_decl ) = let n = (get_domain_size x) in let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in - Array.init n f + mk_list f n let get_range ( x : func_decl ) = sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) @@ -608,7 +614,7 @@ end = struct ) in mk_list f n - let apply ( x : func_decl ) ( args : Expr.expr array ) = Expr.expr_of_func_app (gc x) x args + let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args end @@ -621,7 +627,7 @@ sig val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs val validate : param_descrs -> params -> unit val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - val get_names : param_descrs -> Symbol.symbol array + val get_names : param_descrs -> Symbol.symbol list val get_size : param_descrs -> int val to_string : param_descrs -> string end @@ -660,7 +666,7 @@ end = struct let get_names ( x : param_descrs ) = let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) @@ -710,21 +716,21 @@ sig val c_of_expr : expr -> context val nc_of_expr : expr -> Z3native.ptr val ptr_of_expr : expr -> Z3native.ptr - val expr_aton : expr array -> Z3native.ptr array + val expr_lton : expr list -> Z3native.ptr array val ast_of_expr : expr -> AST.ast val expr_of_ast : AST.ast -> expr - val expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr val simplify : expr -> Params.params option -> expr val get_simplify_help : context -> string val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs val get_func_decl : expr -> FuncDecl.func_decl val get_bool_value : expr -> Z3enums.lbool val get_num_args : expr -> int - val get_args : expr -> expr array - val update : expr -> expr array -> expr - val substitute : expr -> expr array -> expr array -> expr + val get_args : expr -> expr list + val update : expr -> expr list -> expr + val substitute : expr -> expr list -> expr list -> expr val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr array -> expr + val substitute_vars : expr -> expr list -> expr val translate : expr -> context -> expr val to_string : expr -> string val is_numeral : expr -> bool @@ -750,7 +756,7 @@ sig val mk_const_s : context -> string -> Sort.sort -> expr val mk_const_f : context -> FuncDecl.func_decl -> expr val mk_fresh_const : context -> string -> Sort.sort -> expr - val mk_app : context -> FuncDecl.func_decl -> expr array -> expr + val mk_app : context -> FuncDecl.func_decl -> expr list -> expr val mk_numeral_string : context -> string -> Sort.sort -> expr val mk_numeral_int : context -> int -> Sort.sort -> expr end = struct @@ -786,13 +792,13 @@ end = struct let ast_of_expr e = match e with Expr(a) -> a - let expr_aton ( a : expr array ) = + let expr_lton ( a : expr list ) = let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in - Array.map f a + Array.of_list (List.map f a) - let expr_of_func_app : context -> FuncDecl.func_decl -> expr array -> expr = fun ctx f args -> + let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> match f with FuncDecl.FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (Array.length args) (expr_aton args) in + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in expr_of_ptr ctx o let simplify ( x : expr ) ( p : Params.params option ) = match p with @@ -812,25 +818,25 @@ end = struct let get_args ( x : expr ) = let n = (get_num_args x) in let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in - Array.init n f + mk_list f n - let update ( x : expr ) args = - if (Array.length args <> (get_num_args x)) then + let update ( x : expr ) ( args : expr list ) = + if (List.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (Array.length args) (expr_aton args)) + expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (List.length args) (expr_lton args)) let substitute ( x : expr ) from to_ = - if (Array.length from) <> (Array.length to_) then + if (List.length from) <> (List.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (Array.length from) (expr_aton from) (expr_aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (List.length from) (expr_lton from) (expr_lton to_)) let substitute_one ( x : expr ) from to_ = - substitute ( x : expr ) [| from |] [| to_ |] + substitute ( x : expr ) [ from ] [ to_ ] let substitute_vars ( x : expr ) to_ = - expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (Array.length to_) (expr_aton to_)) + expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (List.length to_) (expr_lton to_)) let translate ( x : expr ) to_ctx = if (c_of_expr x) == to_ctx then @@ -876,12 +882,12 @@ end = struct let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) range - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [||] + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr array ) = expr_of_func_app ctx f args + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) @@ -950,8 +956,8 @@ struct let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) - let mk_distinct ( ctx : context ) ( args : expr array ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_distinct ( ctx : context ) ( args : expr list ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) let mk_not ( ctx : context ) ( a : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) @@ -968,13 +974,13 @@ struct let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - let mk_and ( ctx : context ) ( args : bool_expr array ) = + let mk_and ( ctx : context ) ( args : bool_expr list ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (Array.length args) (Array.map f args)) + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - let mk_or ( ctx : context ) ( args : bool_expr array ) = + let mk_or ( ctx : context ) ( args : bool_expr list ) = let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (Array.length args) (Array.map f args)) + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) end @@ -1016,7 +1022,7 @@ struct let get_terms ( x : pattern ) = let n = (get_num_terms x) in let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) end @@ -1039,26 +1045,26 @@ struct let get_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) let get_no_patterns ( x : quantifier ) = let n = (get_num_patterns x) in let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) let get_bound_variable_names ( x : quantifier ) = let n = (get_num_bound x) in let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_bound_variable_sorts ( x : quantifier ) = let n = (get_num_bound x) in let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in - Array.init n f + mk_list f n let get_body ( x : quantifier ) = Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) @@ -1066,95 +1072,95 @@ struct let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - let mk_pattern ( ctx : context ) ( terms : expr array ) = - if (Array.length terms) == 0 then + let mk_pattern ( ctx : context ) ( terms : expr list ) = + if (List.length terms) == 0 then raise (Z3native.Exception "Cannot create a pattern from zero terms") else - Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (Array.length terms) (expr_aton terms))) + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) - let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (Array.length sorts) != (Array.length names) then + let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) - let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) (ptr_of_expr body))) - let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (Array.length sorts) != (Array.length names) then + let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) - (Array.length sorts) (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - (let f x = (Symbol.gno x) in (Array.map f names)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) (ptr_of_expr body))) - let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((Array.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (ptr_of_expr body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (Array.length bound_constants) (expr_aton bound_constants) - (Array.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.map f patterns)) - (Array.length nopatterns) (expr_aton nopatterns) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) (ptr_of_expr body))) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : Symbol.symbol array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) else (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern array ) ( nopatterns : expr array ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else @@ -1233,9 +1239,9 @@ struct let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) = + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = let m x = (ptr_of_expr (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (Array.length args) (Array.map m args)) + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) let mk_term_array ( ctx : context ) ( arg : array_expr ) = array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) @@ -1274,11 +1280,11 @@ struct let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) - let mk_union ( ctx : context ) ( args : expr array ) = - expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_union ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) - let mk_intersection ( ctx : context ) ( args : expr array ) = - expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (Array.length args) (expr_aton args)) + let mk_intersection ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) @@ -1378,7 +1384,7 @@ struct let get_column_sorts ( x : relation_sort ) = let n = get_arity x in let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in - Array.init n f + mk_list f n end @@ -1418,21 +1424,23 @@ struct module Constructor = struct type constructor = z3_native_object + + let _sizes = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = - let n = (Array.length field_names) in - if n != (Array.length sorts) then + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let n = (List.length field_names) in + if n != (List.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") else - if n != (Array.length sort_refs) then + if n != (List.length sort_refs) then raise (Z3native.Exception "Number of field names does not match number of sort refs") else let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) (Symbol.gno recognizer) n - (let f x = (Symbol.gno x) in (Array.map f field_names)) - (let f x = (AST.ptr_of_ast (ast_of_sort x)) in (Array.map f sorts)) - sort_refs) in + (Symbol.symbol_lton field_names) + (sort_lton sorts) + (Array.of_list sort_refs)) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; @@ -1441,9 +1449,10 @@ struct (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; + Hashtbl.add _sizes no n ; no - let get_num_fields ( x : constructor ) = Z3native.get_arity (z3obj_gnc x) (z3obj_gno x) + let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x let get_constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in @@ -1455,8 +1464,8 @@ struct let get_accessor_decls ( x : constructor ) = let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - let f y = func_decl_of_ptr (z3obj_gc x) y in - Array.map f c + let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in + mk_list f (Array.length c) end @@ -1464,48 +1473,47 @@ struct struct type constructor_list = z3_native_object - let create ( ctx : context ) ( c : Constructor.constructor array ) = + let create ( ctx : context ) ( c : Constructor.constructor list ) = let res : constructor_list = { m_ctx = ctx ; m_n_obj = null ; inc_ref = z3obj_nil_ref ; dec_ref = z3obj_nil_ref} in let f x =(z3obj_gno x) in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (Array.length c) (Array.map f c))) ; + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; (z3obj_create res) ; let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f res; res end - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = Constructor.create ctx name recognizer field_names sorts sort_refs - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( sorts : sort array ) ( sort_refs : int array ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor array ) = + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = let f x = (z3obj_gno x) in - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (Array.length constructors) (Array.map f constructors)) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in sort_of_ptr ctx x - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = mk_sort ctx (Symbol.mk_string ctx name) constructors - let mk_sorts ( ctx : context ) ( names : Symbol.symbol array ) ( c : Constructor.constructor array array ) = - let n = (Array.length names) in + let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = + let n = (List.length names) in let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in - let cla = (Array.map f c) in - let f2 x = (Symbol.gno x) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Array.map f2 names) cla) in - let g e = (sort_of_ptr ctx e) in - (Array.map g r) + let cla = (Array.of_list (List.map f c)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in + let g i = (sort_of_ptr ctx (Array.get r i)) in + mk_list g (Array.length r) - let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : Constructor.constructor array array ) = + let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = mk_sorts ctx ( let f e = (Symbol.mk_string ctx e) in - Array.map f names + List.map f names ) c @@ -1514,12 +1522,12 @@ struct let get_constructors ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n let get_recognizers ( x : datatype_sort ) = let n = (get_num_constructors x) in let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n let get_accessors ( x : datatype_sort ) = let n = (get_num_constructors x) in @@ -1527,9 +1535,9 @@ struct let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in - Array.init ds g + mk_list g ds ) in - Array.init n f + mk_list f n end @@ -1537,7 +1545,7 @@ module Enumeration = struct type enum_sort = EnumSort of sort - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl array ) ( tdecls : Z3native.z3_func_decl array ) = + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = let s = (sort_of_ptr ctx no) in let res = EnumSort(s) in res @@ -1548,23 +1556,22 @@ struct let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol array ) = - let f x = Symbol.gno x in - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (Array.length enum_names) (Array.map f enum_names)) in - sort_of_ptr ctx a b c + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a (list_of_array b) (list_of_array c) - let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string array ) = + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) let get_const_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in - Array.init n f + mk_list f n let get_tester_decls ( x : enum_sort ) = let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in - Array.init n f + mk_list f n end @@ -1609,7 +1616,7 @@ struct let get_tail_decl ( x : list_sort ) = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [||] + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] end @@ -1627,10 +1634,8 @@ struct let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol array ) ( field_sorts : sort array ) = - let f x = Symbol.gno x in - let f2 x = ptr_of_ast (ast_of_sort x) in - let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (Array.length field_names) (Array.map f field_names) (Array.map f2 field_sorts)) in + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in sort_of_ptr ctx r let get_mk_decl ( x : tuple_sort ) = @@ -1641,7 +1646,7 @@ struct let get_field_decls ( x : tuple_sort ) = let n = get_num_fields x in let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in - Array.init n f + mk_list f n end @@ -1746,9 +1751,9 @@ sig val is_int_numeral : Expr.expr -> bool val is_rat_num : Expr.expr -> bool val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr array -> arith_expr - val mk_mul : context -> arith_expr array -> arith_expr - val mk_sub : context -> arith_expr array -> arith_expr + val mk_add : context -> arith_expr list -> arith_expr + val mk_mul : context -> arith_expr list -> arith_expr + val mk_sub : context -> arith_expr list -> arith_expr val mk_unary_minus : context -> arith_expr -> arith_expr val mk_div : context -> arith_expr -> arith_expr -> arith_expr val mk_power : context -> arith_expr -> arith_expr -> arith_expr @@ -2109,17 +2114,17 @@ end = struct let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) - let mk_add ( ctx : context ) ( t : arith_expr array ) = + let mk_add ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_mul ( ctx : context ) ( t : arith_expr array ) = + let mk_mul ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_sub ( ctx : context ) ( t : arith_expr array ) = + let mk_sub ( ctx : context ) ( t : arith_expr list ) = let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (Array.length t) (Array.map f t))) + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) @@ -2551,9 +2556,9 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in - ignore (Array.map f constraints) ; + ignore (List.map f constraints) ; () let is_inconsistent ( x : goal ) = @@ -2569,7 +2574,7 @@ struct let n = get_size x in let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in - Array.init n f + mk_list f n let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) @@ -2653,12 +2658,12 @@ struct let get_args ( x : func_entry ) = let n = (get_num_args x) in let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let to_string ( x : func_entry ) = let a = (get_args x) in let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") end let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) @@ -2666,7 +2671,7 @@ struct let get_entries ( x : func_interp ) = let n = (get_num_entries x) in let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) @@ -2678,12 +2683,12 @@ struct p ^ let g c p = (p ^ (Expr.to_string c) ^ ", ") in (if n > 1 then "[" else "") ^ - (Array.fold_right + (List.fold_right g (FuncEntry.get_args c) ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) ) in - Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") end let get_const_interp ( x : model ) ( f : func_decl ) = @@ -2725,21 +2730,21 @@ struct let get_const_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) let get_func_decls ( x : model ) = let n = (get_num_consts x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_decls ( x : model ) = let n_funcs = (get_num_funcs x) in let n_consts = (get_num_consts x ) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - Array.append (Array.init n_funcs f) (Array.init n_consts g) + (mk_list f n_funcs) @ (mk_list g n_consts) exception ModelEvaluationFailedException of string @@ -2758,13 +2763,13 @@ struct let get_sorts ( x : model ) = let n = (get_num_sorts x) in let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in - Array.init n f + mk_list f n let sort_universe ( x : model ) ( s : sort ) = let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in - Array.init n f + mk_list f n let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) end @@ -2793,7 +2798,7 @@ struct let get_probe_names ( ctx : context ) = let n = (get_num_probes ctx) in let f i = (Z3native.get_probe_name (context_gno ctx) i) in - Array.init n f + mk_list f n let get_probe_description ( ctx : context ) ( name : string ) = Z3native.probe_get_descr (context_gno ctx) name @@ -2862,7 +2867,7 @@ struct let get_subgoals ( x : apply_result ) = let n = (get_num_subgoals x) in let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get_subgoal ( x : apply_result ) ( i : int ) = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) @@ -2888,7 +2893,7 @@ struct let get_tactic_names ( ctx : context ) = let n = (get_num_tactics ctx ) in let f i = (Z3native.get_tactic_name (context_gno ctx) i) in - Array.init n f + mk_list f n let get_tactic_description ( ctx : context ) ( name : string ) = Z3native.tactic_get_descr (context_gno ctx) name @@ -2896,11 +2901,11 @@ struct let mk_tactic ( ctx : context ) ( name : string ) = create ctx (Z3native.mk_tactic (context_gno ctx) name) - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic array ) = + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = let f p c = (match p with | None -> (Some (z3obj_gno c)) | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in - match (Array.fold_left f None ts) with + match (List.fold_left f None ts) with | None -> create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) | Some(x) -> @@ -2940,8 +2945,9 @@ struct let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = using_params ctx t p - let par_or ( ctx : context ) ( t : tactic array ) = - create ctx (Z3native.tactic_par_or (context_gno ctx) (Array.length t) (array_to_native t)) + let par_or ( ctx : context ) ( t : tactic list ) = + let f e = (z3obj_gno e) in + create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) @@ -3042,16 +3048,16 @@ struct else (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in - Array.init n f + mk_list f n let get_keys ( x : statistics ) = let n = (get_size x) in let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in - Array.init n f + mk_list f n let get ( x : statistics ) ( key : string ) = let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in - Array.fold_left f None (get_entries x) + List.fold_left f None (get_entries x) end let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) @@ -3070,16 +3076,16 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (Array.map f constraints) + ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr array ) ( ps : Boolean.bool_expr array ) = - if ((Array.length cs) != (Array.length ps)) then + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f i e = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) (Boolean.gno (Array.get ps i))) in - ignore (Array.iteri f cs) + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + ignore (List.iter2 f cs ps) let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) @@ -3092,15 +3098,15 @@ struct let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in - Array.init n f + mk_list f n - let check ( x : solver ) ( assumptions : Boolean.bool_expr array) = + let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = let r = - if ((Array.length assumptions) == 0) then + if ((List.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (Array.length assumptions) (Array.map f assumptions)) + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) in match r with | L_TRUE -> SATISFIABLE @@ -3125,7 +3131,7 @@ struct let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in - Array.init n f + mk_list f n let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) @@ -3173,9 +3179,9 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr array ) = + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (Array.map f constraints) ; + ignore (List.map f constraints) ; () let register_relation ( x : fixedpoint ) ( f : func_decl ) = @@ -3186,8 +3192,8 @@ struct | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int array ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (Array.length args) args + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with @@ -3195,9 +3201,9 @@ struct | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN - let query_r ( x : fixedpoint ) ( relations : func_decl array ) = + let query_r ( x : fixedpoint ) ( relations : func_decl list ) = let f x = ptr_of_ast (ast_of_func_decl x) in - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (Array.length relations) (Array.map f relations))) with + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -3236,25 +3242,24 @@ struct let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol array ) = - let f2 x = (Symbol.gno x) in - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (Array.length kinds) (Array.map f2 kinds) + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr array ) = + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (Array.length queries) (Array.map f queries) + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - Array.init n f + mk_list f n let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - Array.init n f + mk_list f n let mk_fixedpoint ( ctx : context ) = create ctx end @@ -3282,102 +3287,102 @@ end module SMT = struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr array ) ( formula : Boolean.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (Array.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.map f assumptions)) + (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) (Boolean.gno formula) - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Z3native.parse_smtlib_string (context_gno ctx) str cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Z3native.parse_smtlib_file (context_gno ctx) file_name cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in - Array.init n f + mk_list f n let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in - Array.init n f + mk_list f n let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) let get_smtlib_decls ( ctx : context ) = let n = (get_num_smtlib_decls ctx) in let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in - Array.init n f + mk_list f n let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in - Array.init n f + mk_list f n - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol array ) ( sorts : sort array ) ( decl_names : Symbol.symbol array ) ( decls : func_decl array ) = - let csn = (Array.length sort_names) in - let cs = (Array.length sorts) in - let cdn = (Array.length decl_names) in - let cd = (Array.length decls) in + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name cs - (let f x = Symbol.gno x in (Array.map f sort_names)) - (let f x = Sort.gno x in (Array.map f sorts)) + (Symbol.symbol_lton sort_names) + (sort_lton sorts) cd - (let f x = Symbol.gno x in (Array.map f decl_names)) - (let f x = FuncDecl.gno x in (Array.map f decls)))) + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 49a78f724..9f451c45f 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -106,11 +106,11 @@ sig (** Creates a new symbol using a string. *) val mk_string : context -> string -> symbol - (** Create an array of symbols. *) - val mk_ints : context -> int array -> symbol array + (** Create a list of symbols. *) + val mk_ints : context -> int list -> symbol list - (** Create an array of symbols. *) - val mk_strings : context -> string array -> symbol array + (** Create a list of symbols. *) + val mk_strings : context -> string list -> symbol list end (** The abstract syntax tree (AST) module *) @@ -175,7 +175,7 @@ sig val get_size : ast_map -> int (** The keys stored in the map. *) - val get_keys : ast_map -> ASTVector.ast_vector + val get_keys : ast_map -> ast list (** Retrieves a string representation of the map.*) val to_string : ast_map -> string @@ -331,13 +331,13 @@ sig end (** Creates a new function declaration. *) - val mk_func_decl : context -> Symbol.symbol -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl (** Creates a new function declaration. *) - val mk_func_decl_s : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl (** Creates a fresh function declaration with a name prefixed with a prefix string. *) - val mk_fresh_func_decl : context -> string -> Sort.sort array -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl (** Creates a new constant function declaration. *) val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl @@ -368,7 +368,7 @@ sig val get_domain_size : func_decl -> int (** The domain of the function declaration *) - val get_domain : func_decl -> Sort.sort array + val get_domain : func_decl -> Sort.sort list (** The range of the function declaration *) val get_range : func_decl -> Sort.sort @@ -386,7 +386,7 @@ sig val get_parameters : func_decl -> Parameter.parameter list (** Create expression that applies function to arguments. *) - val apply : func_decl -> Expr.expr array -> Expr.expr + val apply : func_decl -> Expr.expr list -> Expr.expr end (** Parameter sets (of Solvers, Tactics, ...) @@ -408,7 +408,7 @@ sig val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind (** Retrieve all names of parameters. *) - val get_names : param_descrs -> Symbol.symbol array + val get_names : param_descrs -> Symbol.symbol list (** The size of the ParamDescrs. *) val get_size : param_descrs -> int @@ -477,18 +477,18 @@ sig val get_num_args : Expr.expr -> int (** The arguments of the expression. *) - val get_args : Expr.expr -> Expr.expr array + val get_args : Expr.expr -> Expr.expr list (** Update the arguments of the expression using an array of expressions. The number of new arguments should coincide with the current number of arguments. *) - val update : Expr.expr -> Expr.expr array -> expr + val update : Expr.expr -> Expr.expr list -> expr (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. The result is the new expression. The arrays from and to must have size num_exprs. For every i smaller than num_exprs, we must have that sort of from[i] must be equal to sort of to[i]. *) - val substitute : Expr.expr -> Expr.expr array -> Expr.expr array -> expr + val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr (** Substitute every occurrence of from in the expression with to. {!substitute} *) @@ -497,7 +497,7 @@ sig (** Substitute the free variables in the expression with the expressions in the expr array For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) - val substitute_vars : Expr.expr -> Expr.expr array -> expr + val substitute_vars : Expr.expr -> Expr.expr list -> expr (** Translates (copies) the term to another context. @return A copy of the term which is associated with the other context *) @@ -582,7 +582,7 @@ sig val mk_fresh_const : context -> string -> Sort.sort -> expr (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr array -> expr + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr (** Create a numeral of a given sort. @return A Term with the goven value and sort *) @@ -627,7 +627,7 @@ sig val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr array -> bool_expr + val mk_distinct : context -> Expr.expr list -> bool_expr (** Mk an expression representing not(a). *) val mk_not : context -> bool_expr -> bool_expr @@ -645,10 +645,10 @@ sig val mk_xor : context -> bool_expr -> bool_expr -> bool_expr (** Create an expression representing the AND of args *) - val mk_and : context -> bool_expr array -> bool_expr + val mk_and : context -> bool_expr list -> bool_expr (** Create an expression representing the OR of args *) - val mk_or : context -> bool_expr array -> bool_expr + val mk_or : context -> bool_expr list -> bool_expr end (** Quantifier expressions *) @@ -675,7 +675,7 @@ sig val get_num_terms : pattern -> int (** The terms in the pattern. *) - val get_terms : pattern -> Expr.expr array + val get_terms : pattern -> Expr.expr list (** A string representation of the pattern. *) val to_string : pattern -> string @@ -713,22 +713,22 @@ sig val get_num_patterns : quantifier -> int (** The patterns. *) - val get_patterns : quantifier -> Pattern.pattern array + val get_patterns : quantifier -> Pattern.pattern list (** The number of no-patterns. *) val get_num_no_patterns : quantifier -> int (** The no-patterns. *) - val get_no_patterns : quantifier -> Pattern.pattern array + val get_no_patterns : quantifier -> Pattern.pattern list (** The number of bound variables. *) val get_num_bound : quantifier -> int (** The symbols for the bound variables. *) - val get_bound_variable_names : quantifier -> Symbol.symbol array + val get_bound_variable_names : quantifier -> Symbol.symbol list (** The sorts of the bound variables. *) - val get_bound_variable_sorts : quantifier -> Sort.sort array + val get_bound_variable_sorts : quantifier -> Sort.sort list (** The body of the quantifier. *) val get_body : quantifier -> Boolean.bool_expr @@ -737,25 +737,25 @@ sig val mk_bound : context -> int -> Sort.sort -> Expr.expr (** Create a quantifier pattern. *) - val mk_pattern : context -> Expr.expr array -> Pattern.pattern + val mk_pattern : context -> Expr.expr list -> Pattern.pattern (** Create a universal Quantifier. *) - val mk_forall : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** Create a universal Quantifier. *) - val mk_forall_const : context -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** Create an existential Quantifier. *) - val mk_exists : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** Create an existential Quantifier. *) - val mk_exists_const : context -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** Create a Quantifier. *) - val mk_quantifier : context -> Sort.sort array -> Symbol.symbol array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** Create a Quantifier. *) - val mk_quantifier : context -> bool -> Expr.expr array -> Expr.expr -> int option -> Pattern.pattern array -> Expr.expr array -> Symbol.symbol option -> Symbol.symbol option -> quantifier + val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier end (** Functions to manipulate Array expressions *) @@ -857,7 +857,7 @@ sig {!Array_.mk_sort} {!mk_select} {!mk_store} *) - val mk_map : context -> FuncDecl.func_decl -> array_expr array -> array_expr + val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr (** Access the array default value. @@ -904,10 +904,10 @@ sig val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr (** Take the union of a list of sets. *) - val mk_union : context -> Expr.expr array -> Expr.expr + val mk_union : context -> Expr.expr list -> Expr.expr (** Take the intersection of a list of sets. *) - val mk_intersection : context -> Expr.expr array -> Expr.expr + val mk_intersection : context -> Expr.expr list -> Expr.expr (** Take the difference between two sets. *) val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1037,7 +1037,7 @@ sig val get_arity : relation_sort -> int (** The sorts of the columns of the relation sort. *) - val get_column_sorts : relation_sort -> relation_sort array + val get_column_sorts : relation_sort -> relation_sort list end (** Functions to manipulate Datatype expressions *) @@ -1066,43 +1066,43 @@ sig val get_tester_decl : constructor -> FuncDecl.func_decl (** The function declarations of the accessors *) - val get_accessor_decls : constructor -> FuncDecl.func_decl array + val get_accessor_decls : constructor -> FuncDecl.func_decl list end (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> int array -> Constructor.constructor + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor (** Create a new datatype sort. *) - val mk_sort : context -> Symbol.symbol -> Constructor.constructor array -> datatype_sort + val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort (** Create a new datatype sort. *) - val mk_sort_s : context -> string -> Constructor.constructor array -> datatype_sort + val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort (** Create mutually recursive datatypes. *) - val mk_sorts : context -> Symbol.symbol array -> Constructor.constructor array array -> datatype_sort array + val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list (** Create mutually recursive data-types. *) - val mk_sorts_s : context -> string array -> Constructor.constructor array array -> datatype_sort array + val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list (** The number of constructors of the datatype sort. *) val get_num_constructors : datatype_sort -> int (** The constructors. *) - val get_constructors : datatype_sort -> FuncDecl.func_decl array + val get_constructors : datatype_sort -> FuncDecl.func_decl list (** The recognizers. *) - val get_recognizers : datatype_sort -> FuncDecl.func_decl array + val get_recognizers : datatype_sort -> FuncDecl.func_decl list (** The constructor accessors. *) - val get_accessors : datatype_sort -> FuncDecl.func_decl array array + val get_accessors : datatype_sort -> FuncDecl.func_decl list list end (** Functions to manipulate Enumeration expressions *) @@ -1113,16 +1113,16 @@ sig val sort_of_enum_sort : enum_sort -> Sort.sort (** Create a new enumeration sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> enum_sort + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort (** Create a new enumeration sort. *) - val mk_sort_s : context -> string -> string array -> enum_sort + val mk_sort_s : context -> string -> string list -> enum_sort (** The function declarations of the constants in the enumeration. *) - val get_const_decls : enum_sort -> FuncDecl.func_decl array + val get_const_decls : enum_sort -> FuncDecl.func_decl list (** The test predicates for the constants in the enumeration. *) - val get_tester_decls : enum_sort -> FuncDecl.func_decl array + val get_tester_decls : enum_sort -> FuncDecl.func_decl list end (** Functions to manipulate List expressions *) @@ -1168,7 +1168,7 @@ sig val sort_of_tuple_sort : tuple_sort -> Sort.sort (** Create a new tuple sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol array -> Sort.sort array -> tuple_sort + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort (** The constructor function of the tuple. *) val get_mk_decl : tuple_sort -> FuncDecl.func_decl @@ -1177,7 +1177,7 @@ sig val get_num_fields : tuple_sort -> int (** The field declarations. *) - val get_field_decls : tuple_sort -> FuncDecl.func_decl array + val get_field_decls : tuple_sort -> FuncDecl.func_decl list end (** Functions to manipulate arithmetic expressions *) @@ -1407,13 +1407,13 @@ sig val is_algebraic_number : Expr.expr -> bool (** Create an expression representing t[0] + t[1] + .... *) - val mk_add : context -> arith_expr array -> arith_expr + val mk_add : context -> arith_expr list -> arith_expr (** Create an expression representing t[0] * t[1] * .... *) - val mk_mul : context -> arith_expr array -> arith_expr + val mk_mul : context -> arith_expr list -> arith_expr (** Create an expression representing t[0] - t[1] - .... *) - val mk_sub : context -> arith_expr array -> arith_expr + val mk_sub : context -> arith_expr list -> arith_expr (** Create an expression representing -t. *) val mk_unary_minus : context -> arith_expr -> arith_expr @@ -2332,7 +2332,7 @@ sig val is_garbage : goal -> bool (** Adds the constraints to the given goal. *) - val assert_ : goal -> Boolean.bool_expr array -> unit + val assert_ : goal -> Boolean.bool_expr list -> unit (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool @@ -2348,7 +2348,7 @@ sig val get_size : goal -> int (** The formulas in the goal. *) - val get_formulas : goal -> Boolean.bool_expr array + val get_formulas : goal -> Boolean.bool_expr list (** The number of formulas, subformulas and terms in the goal. *) val get_num_exprs : goal -> int @@ -2407,7 +2407,7 @@ sig (** The arguments of the function entry. *) - val get_args : func_entry -> Expr.expr array + val get_args : func_entry -> Expr.expr list (** A string representation of the function entry. *) @@ -2418,7 +2418,7 @@ sig val get_num_entries : func_interp -> int (** The entries in the function interpretation *) - val get_entries : func_interp -> FuncEntry.func_entry array + val get_entries : func_interp -> FuncEntry.func_entry list (** The (symbolic) `else' value of the function interpretation. *) val get_else : func_interp -> Expr.expr @@ -2446,16 +2446,16 @@ sig val get_num_consts : model -> int (** The function declarations of the constants in the model. *) - val get_const_decls : model -> FuncDecl.func_decl array + val get_const_decls : model -> FuncDecl.func_decl list (** The number of function interpretations in the model. *) val get_num_funcs : model -> int (** The function declarations of the function interpretations in the model. *) - val get_func_decls : model -> FuncDecl.func_decl array + val get_func_decls : model -> FuncDecl.func_decl list (** All symbols that have an interpretation in the model. *) - val get_decls : model -> FuncDecl.func_decl array + val get_decls : model -> FuncDecl.func_decl list (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) exception ModelEvaluationFailedException of string @@ -2481,12 +2481,12 @@ sig the "universe" of the sort. {!get_num_sorts} {!sort_universe} *) - val get_sorts : model -> Sort.sort array + val get_sorts : model -> Sort.sort list (** The finite set of distinct values that represent the interpretation of a sort. {!get_sorts} - @returns An array of expressions, where each is an element of the universe of the sort *) - val sort_universe : model -> Sort.sort -> AST.ASTVector.ast_vector array + @returns A list of expressions, where each is an element of the universe of the sort *) + val sort_universe : model -> Sort.sort -> AST.ast list (** Conversion of models to strings. A string representation of the model. *) @@ -2514,7 +2514,7 @@ sig val get_num_probes : context -> int (** The names of all supported Probes. *) - val get_probe_names : context -> string array + val get_probe_names : context -> string list (** Returns a string containing a description of the probe with the given name. *) val get_probe_description : context -> string -> string @@ -2579,7 +2579,7 @@ sig val get_num_subgoals : apply_result -> int (** Retrieves the subgoals from the apply_result. *) - val get_subgoals : apply_result -> Goal.goal array + val get_subgoals : apply_result -> Goal.goal list (** Retrieves a subgoal from the apply_result. *) val get_subgoal : apply_result -> int -> Goal.goal @@ -2606,7 +2606,7 @@ sig val get_num_tactics : context -> int (** The names of all supported tactics. *) - val get_tactic_names : context -> string array + val get_tactic_names : context -> string list (** Returns a string containing a description of the tactic with the given name. *) val get_tactic_description : context -> string -> string @@ -2616,7 +2616,7 @@ sig (** Create a tactic that applies one tactic to a Goal and then another one to every subgoal produced by the first one. *) - val and_then : context -> tactic -> tactic -> tactic array -> tactic + val and_then : context -> tactic -> tactic -> tactic list -> tactic (** Create a tactic that first applies one tactic to a Goal and if it fails then returns the result of another tactic applied to the Goal. *) @@ -2662,7 +2662,7 @@ sig val with_ : context -> tactic -> Params.params -> tactic (** Create a tactic that applies the given tactics in parallel. *) - val par_or : context -> tactic array -> tactic + val par_or : context -> tactic list -> tactic (** Create a tactic that applies a tactic to a given goal and then another tactic to every subgoal produced by the first one. The subgoals are processed in parallel. *) @@ -2722,10 +2722,10 @@ sig val get_size : statistics -> int (** The data entries. *) - val get_entries : statistics -> Entry.statistics_entry array + val get_entries : statistics -> Entry.statistics_entry list (** The statistical counters. *) - val get_keys : statistics -> string array + val get_keys : statistics -> string list (** The value of a particular statistical counter. *) val get : statistics -> string -> Entry.statistics_entry option @@ -2759,7 +2759,7 @@ sig val reset : solver -> unit (** Assert a constraint (or multiple) into the solver. *) - val assert_ : solver -> Boolean.bool_expr array -> unit + val assert_ : solver -> Boolean.bool_expr list -> unit (** * Assert multiple constraints (cs) into the solver, and track them (in the * unsat) core @@ -2772,7 +2772,7 @@ sig * of the Boolean variables provided using {!assert_and_track} * and the Boolean literals * provided using {!check} with assumptions. *) - val assert_and_track_a : solver -> Boolean.bool_expr array -> Boolean.bool_expr array -> unit + val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit (** * Assert a constraint (c) into the solver, and track it (in the unsat) core * using the Boolean constant p. @@ -2790,14 +2790,14 @@ sig val get_num_assertions : solver -> int (** The set of asserted formulas. *) - val get_assertions : solver -> Boolean.bool_expr array + val get_assertions : solver -> Boolean.bool_expr list (** Checks whether the assertions in the solver are consistent or not. {!Model} {!get_unsat_core} {!Proof} *) - val check : solver -> Boolean.bool_expr array -> status + val check : solver -> Boolean.bool_expr list -> status (** The model of the last Check. @@ -2816,7 +2816,7 @@ sig The unsat core is a subset of Assertions The result is empty if Check was not invoked before, if its results was not UNSATISFIABLE, or if core production is disabled. *) - val get_unsat_core : solver -> AST.ASTVector.ast_vector array + val get_unsat_core : solver -> AST.ast list (** A brief justification of why the last call to Check returned UNKNOWN. *) val get_reason_unknown : solver -> string @@ -2863,7 +2863,7 @@ sig val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs (** Assert a constraints into the fixedpoint solver. *) - val assert_ : fixedpoint -> Boolean.bool_expr array -> unit + val assert_ : fixedpoint -> Boolean.bool_expr list -> unit (** Register predicate as recursive relation. *) val register_relation : fixedpoint -> FuncDecl.func_decl -> unit @@ -2872,7 +2872,7 @@ sig val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit (** Add table fact to the fixedpoint solver. *) - val add_fact : fixedpoint -> FuncDecl.func_decl -> int array -> unit + val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit (** Query the fixedpoint solver. A query is a conjunction of constraints. The constraints may include the recursively defined relations. @@ -2884,7 +2884,7 @@ sig A query is an array of relations. The query is satisfiable if there is an instance of some relation that is non-empty. The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - val query_r : fixedpoint -> FuncDecl.func_decl array -> Solver.status + val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status (** Creates a backtracking point. {!pop} *) @@ -2920,16 +2920,16 @@ sig val to_string : fixedpoint -> string (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol array -> unit + val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit (** Convert benchmark given as set of axioms, rules and queries to a string. *) - val to_string_q : fixedpoint -> Boolean.bool_expr array -> string + val to_string_q : fixedpoint -> Boolean.bool_expr list -> string (** Retrieve set of rules added to fixedpoint context. *) - val get_rules : fixedpoint -> Boolean.bool_expr array + val get_rules : fixedpoint -> Boolean.bool_expr list (** Retrieve set of assertions added to fixedpoint context. *) - val get_assertions : fixedpoint -> Boolean.bool_expr array + val get_assertions : fixedpoint -> Boolean.bool_expr list (** Create a Fixedpoint context. *) val mk_fixedpoint : context -> fixedpoint @@ -2985,7 +2985,7 @@ sig (** Convert a benchmark into an SMT-LIB formatted string. @return A string representation of the benchmark. *) - val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr array -> Boolean.bool_expr -> string + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string (** Parse the given string using the SMT-LIB parser. @@ -2994,45 +2994,45 @@ sig don't need to match the names of the sorts and declarations in the arrays in the fourth and sixth argument. This is a useful feature since we can use arbitrary names to reference sorts and declarations. *) - val parse_smtlib_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit + val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** Parse the given file using the SMT-LIB parser. {!parse_smtlib_string} *) - val parse_smtlib_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> unit + val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_formulas : context -> int (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_formulas : context -> Boolean.bool_expr array + val get_smtlib_formulas : context -> Boolean.bool_expr list (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_assumptions : context -> int (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_assumptions : context -> Boolean.bool_expr array + val get_smtlib_assumptions : context -> Boolean.bool_expr list (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_decls : context -> int (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_decls : context -> FuncDecl.func_decl array + val get_smtlib_decls : context -> FuncDecl.func_decl list (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_sorts : context -> int (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_sorts : context -> Sort.sort array + val get_smtlib_sorts : context -> Sort.sort list (** Parse the given string using the SMT-LIB2 parser. {!parse_smtlib_string} @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - val parse_smtlib2_string : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr + val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr (** Parse the given file using the SMT-LIB2 parser. {!parse_smtlib2_string} *) - val parse_smtlib2_file : context -> string -> Symbol.symbol array -> Sort.sort array -> Symbol.symbol array -> FuncDecl.func_decl array -> Boolean.bool_expr + val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr end (** Set a global (or module) parameter, which is shared by all Z3 contexts. From d293b579f376045db72bd30569583bd2cbd2ba41 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 13:25:31 +0000 Subject: [PATCH 429/646] ML API: flat & rich layer in place. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 40 +- src/api/ml/z3.ml | 1458 ++++------------ src/api/ml/z3.mli | 460 ++--- src/api/ml/z3_rich.ml | 3400 +++++++++++++++++++++++++++++++++++++ src/api/ml/z3_rich.mli | 3072 +++++++++++++++++++++++++++++++++ 5 files changed, 7040 insertions(+), 1390 deletions(-) create mode 100644 src/api/ml/z3_rich.ml create mode 100644 src/api/ml/z3_rich.mli diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 31f31d566..823a08fe2 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -26,20 +26,14 @@ exception TestFailedException of string *) let model_converter_test ( ctx : context ) = Printf.printf "ModelConverterTest\n"; - let xr = (arith_expr_of_expr - (Expr.mk_const ctx (Symbol.mk_string ctx "x") - (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in - let yr = (arith_expr_of_expr - (Expr.mk_const ctx (Symbol.mk_string ctx "y") - (sort_of_arith_sort (arith_sort_of_real_sort (Real.mk_sort ctx))))) in + let xr = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Real.mk_sort ctx)) in + let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [ (mk_gt ctx xr - (arith_expr_of_real_expr (real_expr_of_rat_num - (Real.mk_numeral_nd ctx 10 1)))) ]) ; + (Goal.assert_ g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; (Goal.assert_ g4 [ (mk_eq ctx - (expr_of_arith_expr yr) - (expr_of_arith_expr (Arithmetic.mk_add ctx [ xr; (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1))) ]) ) ) ] ) ; - (Goal.assert_ g4 [ (mk_gt ctx yr (arith_expr_of_real_expr (real_expr_of_rat_num (Real.mk_numeral_nd ctx 1 1)))) ]) ; + yr + (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1) ])) ]) ; + (Goal.assert_ g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -83,7 +77,7 @@ let basic_tests ( ctx : context ) = let fname = (mk_string ctx "f") in let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in - let bs = (sort_of_bool_sort (Boolean.mk_sort ctx)) in + let bs = (Boolean.mk_sort ctx) in let domain = [ bs; bs ] in let f = (FuncDecl.mk_func_decl ctx fname domain bs) in let fapp = (mk_app ctx f @@ -123,10 +117,8 @@ let basic_tests ( ctx : context ) = Printf.printf "Test passed.\n" ); (Goal.assert_ g [ (mk_eq ctx - (mk_numeral_int ctx 1 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32))) - (mk_numeral_int ctx 2 - (sort_of_bitvec_sort (BitVector.mk_sort ctx 32)))) ] ) + (mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) + (mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) ; ( let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in @@ -157,10 +149,10 @@ let basic_tests ( ctx : context ) = ); ( let g3 = (mk_goal ctx true true false) in - let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx)))) in - (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; - (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (sort_of_arith_sort (arith_sort_of_int_sort (Integer.mk_sort ctx))))) ]) ; + let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Integer.mk_sort ctx)) in + let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Integer.mk_sort ctx)) in + (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; + (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; let constr = (mk_eq ctx xc yc) in (Goal.assert_ g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in @@ -228,9 +220,9 @@ let _ = let rs = (Real.mk_sort ctx) in Printf.printf "int symbol: %s\n" (Symbol.to_string is); Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string (sort_of_bool_sort bs)); - Printf.printf "int sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_int_sort ints))); - Printf.printf "real sort: %s\n" (Sort.to_string (sort_of_arith_sort (arith_sort_of_real_sort rs))); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); basic_tests ctx ; Printf.printf "Disposing...\n"; Gc.full_major () diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 56d319c1a..0676f1a39 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -133,52 +133,34 @@ let mk_context ( cfg : ( string * string ) list ) = module Symbol = struct - (* Symbol types *) - type int_symbol = z3_native_object - type string_symbol = z3_native_object - - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - + type symbol = z3_native_object let create_i ( ctx : context ) ( no : Z3native.ptr ) = - let res : int_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in + let res : symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let create_s ( ctx : context ) ( no : Z3native.ptr ) = - let res : string_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in + let res : symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in (z3obj_sno res ctx no) ; (z3obj_create res) ; res let create ( ctx : context ) ( no : Z3native.ptr ) = match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) + | INT_SYMBOL -> (create_i ctx no) + | STRING_SYMBOL -> (create_s ctx no) - let gc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gc n) - | S_Str(n) -> (z3obj_gc n) - - let gnc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gnc n) - | S_Str(n) -> (z3obj_gnc n) - - let gno ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gno n) - | S_Str(n) -> (z3obj_gno n) + let gc ( x : symbol ) = (z3obj_gc x) + let gnc ( x : symbol ) = (z3obj_gnc x) + let gno ( x : symbol ) = (z3obj_gno x) let symbol_lton ( a : symbol list ) = let f ( e : symbol ) = (gno e) in @@ -187,18 +169,18 @@ struct let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + let get_int (o : symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + let get_string (o : symbol ) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) let to_string ( o : symbol ) = match (kind o) with | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) let mk_int ( ctx : context ) ( i : int ) = - S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) let mk_string ( ctx : context ) ( s : string ) = - S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) let mk_ints ( ctx : context ) ( names : int list ) = let f elem = mk_int ( ctx : context ) elem in @@ -353,7 +335,6 @@ open AST module Sort = struct type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> let q = (z3_native_object_of_ast_ptr ctx no) in @@ -373,14 +354,7 @@ struct | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") let ast_of_sort s = match s with Sort(x) -> x - let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x - - let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -409,7 +383,7 @@ struct dec_ref = Z3native.dec_ref } in (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; (z3obj_create res) ; - UninterpretedSort(Sort(res)) + Sort(res) let mk_uninterpreted_s ( ctx : context ) ( s : string ) = mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) @@ -713,9 +687,9 @@ and Expr : sig type expr = Expr of AST.ast val expr_of_ptr : context -> Z3native.ptr -> expr - val c_of_expr : expr -> context - val nc_of_expr : expr -> Z3native.ptr - val ptr_of_expr : expr -> Z3native.ptr + val gc : expr -> context + val gnc : expr -> Z3native.ptr + val gno : expr -> Z3native.ptr val expr_lton : expr list -> Z3native.ptr array val ast_of_expr : expr -> AST.ast val expr_of_ast : AST.ast -> expr @@ -762,9 +736,9 @@ sig end = struct type expr = Expr of AST.ast - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + let gc e = match e with Expr(a) -> (z3obj_gc a) + let gnc e = match e with Expr(a) -> (z3obj_gnc a) + let gno e = match e with Expr(a) -> (z3obj_gno a) let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then @@ -802,60 +776,60 @@ end = struct expr_of_ptr ctx o let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> expr_of_ptr (c_of_expr x) (Z3native.simplify (nc_of_expr x) (ptr_of_expr x)) - | Some pp -> expr_of_ptr (c_of_expr x) (Z3native.simplify_ex (nc_of_expr x) (ptr_of_expr x) (z3obj_gno pp)) + | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (gnc x) (gno x)) + | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (gnc x) (gno x) (z3obj_gno pp)) let get_simplify_help ( ctx : context ) = Z3native.simplify_get_help (context_gno ctx) let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (c_of_expr x) (Z3native.get_app_decl (nc_of_expr x) (ptr_of_expr x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (nc_of_expr x) (ptr_of_expr x)) + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) - let get_num_args ( x : expr ) = Z3native.get_app_num_args (nc_of_expr x) (ptr_of_expr x) + let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = expr_of_ptr (c_of_expr x) (Z3native.get_app_arg (nc_of_expr x) (ptr_of_expr x) i) in + let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (gnc x) (gno x) i) in mk_list f n let update ( x : expr ) ( args : expr list ) = if (List.length args <> (get_num_args x)) then raise (Z3native.Exception "Number of arguments does not match") else - expr_of_ptr (c_of_expr x) (Z3native.update_term (nc_of_expr x) (ptr_of_expr x) (List.length args) (expr_lton args)) + expr_of_ptr (Expr.gc x) (Z3native.update_term (gnc x) (gno x) (List.length args) (expr_lton args)) let substitute ( x : expr ) from to_ = if (List.length from) <> (List.length to_) then raise (Z3native.Exception "Argument sizes do not match") else - expr_of_ptr (c_of_expr x) (Z3native.substitute (nc_of_expr x) (ptr_of_expr x) (List.length from) (expr_lton from) (expr_lton to_)) + expr_of_ptr (Expr.gc x) (Z3native.substitute (gnc x) (gno x) (List.length from) (expr_lton from) (expr_lton to_)) let substitute_one ( x : expr ) from to_ = substitute ( x : expr ) [ from ] [ to_ ] let substitute_vars ( x : expr ) to_ = - expr_of_ptr (c_of_expr x) (Z3native.substitute_vars (nc_of_expr x) (ptr_of_expr x) (List.length to_) (expr_lton to_)) + expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (gnc x) (gno x) (List.length to_) (expr_lton to_)) let translate ( x : expr ) to_ctx = - if (c_of_expr x) == to_ctx then + if (Expr.gc x) == to_ctx then x else - expr_of_ptr to_ctx (Z3native.translate (nc_of_expr x) (ptr_of_expr x) (context_gno to_ctx)) + expr_of_ptr to_ctx (Z3native.translate (gnc x) (gno x) (context_gno to_ctx)) - let to_string ( x : expr ) = Z3native.ast_to_string (nc_of_expr x) (ptr_of_expr x) + let to_string ( x : expr ) = Z3native.ast_to_string (gnc x) (gno x) - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (nc_of_expr x) (ptr_of_expr x)) + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (gnc x) (gno x)) - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (nc_of_expr x) (ptr_of_expr x) + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) - let get_sort ( x : expr ) = sort_of_ptr (c_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)) + let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (nc_of_expr x) - (Z3native.mk_bool_sort (nc_of_expr x)) - (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x))) + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && (get_num_args x) == 0 && @@ -901,86 +875,52 @@ open Expr module Boolean = struct - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.ast_of_ptr ctx no) in - BoolExpr(Expr.Expr(a)) - - let bool_expr_of_expr e = - match e with Expr.Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - - let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(sort_of_ptr ctx no) - - let sort_of_bool_sort s = match s with BoolSort(x) -> x - - let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - - let expr_of_bool_expr e = match e with BoolExpr(x) -> x - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) - let mk_sort ( ctx : context ) = - BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) + (sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - let s = (match (mk_sort ctx) with BoolSort(q) -> q) in - BoolExpr(Expr.mk_const ctx name s) + (Expr.mk_const ctx name (mk_sort ctx)) let mk_const_s ( ctx : context ) ( name : string ) = mk_const ctx (Symbol.mk_string ctx name) let mk_true ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) + expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) let mk_false ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) + expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (ptr_of_expr x) (ptr_of_expr y)) + expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) let mk_distinct ( ctx : context ) ( args : expr list ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) - let mk_not ( ctx : context ) ( a : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + let mk_not ( ctx : context ) ( a : expr ) = + expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + let mk_ite ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( t3 : expr ) = + expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + let mk_iff ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + let mk_implies ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - let mk_and ( ctx : context ) ( args : bool_expr list ) = - let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) + let mk_and ( ctx : context ) ( args : expr list ) = + let f x = (Expr.gno (x)) in + expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - let mk_or ( ctx : context ) ( args : bool_expr list ) = - let f x = (ptr_of_expr (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) + let mk_or ( ctx : context ) ( args : expr list ) = + let f x = (Expr.gno (x)) in + expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) end @@ -998,9 +938,9 @@ struct else Quantifier(e) - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (c_of_expr e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (nc_of_expr e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (ptr_of_expr e) + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) module Pattern = struct @@ -1031,7 +971,7 @@ struct if not (AST.is_var (match x with Expr.Expr(a) -> a)) then raise (Z3native.Exception "Term is not a bound variable.") else - Z3native.get_index_value (nc_of_expr x) (ptr_of_expr x) + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) let is_universal ( x : quantifier ) = Z3native.is_quantifier_forall (gnc x) (gno x) @@ -1067,7 +1007,7 @@ struct mk_list f n let get_body ( x : quantifier ) = - Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) @@ -1087,7 +1027,7 @@ struct (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1097,7 +1037,7 @@ struct (List.length nopatterns) (expr_lton nopatterns) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1105,7 +1045,7 @@ struct (match weight with | None -> 1 | Some(x) -> x) (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true (match weight with | None -> 1 | Some(x) -> x) @@ -1114,7 +1054,7 @@ struct (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length nopatterns) (expr_lton nopatterns) - (ptr_of_expr body))) + (Expr.gno body))) let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (List.length sorts) != (List.length names) then @@ -1125,7 +1065,7 @@ struct (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -1135,7 +1075,7 @@ struct (List.length nopatterns) (expr_lton nopatterns) (List.length sorts) (sort_lton sorts) (Symbol.symbol_lton names) - (ptr_of_expr body))) + (Expr.gno body))) let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then @@ -1143,7 +1083,7 @@ struct (match weight with | None -> 1 | Some(x) -> x) (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (ptr_of_expr body))) + (Expr.gno body))) else Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false (match weight with | None -> 1 | Some(x) -> x) @@ -1152,7 +1092,7 @@ struct (List.length bound_constants) (expr_lton bound_constants) (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) (List.length nopatterns) (expr_lton nopatterns) - (ptr_of_expr body))) + (Expr.gno body))) let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = if (universal) then @@ -1170,46 +1110,8 @@ end module Array_ = struct - type array_sort = ArraySort of sort - type array_expr = ArrayExpr of expr - - let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (expr_of_ptr ctx no) in - ArrayExpr(e) - - let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - ArraySort(s) - - let sort_of_array_sort s = match s with ArraySort(x) -> x - - let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - - let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - - let expr_of_array_expr e = match e with ArrayExpr(x) -> x - - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) @@ -1218,48 +1120,40 @@ struct let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) let is_array ( x : expr ) = - (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == ARRAY_SORT) + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) - let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + let get_domain ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_domain (Sort.gnc x) (Sort.gno x)) + let get_range ( x : sort ) = Sort.sort_of_ptr (Sort.gc x) (Z3native.get_array_sort_range (Sort.gnc x) (Sort.gno x)) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) + (Expr.mk_const ctx name (mk_sort ctx domain range)) let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = mk_const ctx (Symbol.mk_string ctx name) domain range - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (ptr_of_expr i)) + let mk_select ( ctx : context ) ( a : expr ) ( i : expr ) = + expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (Expr.gno a) (Expr.gno i)) - let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (ptr_of_expr i) (ptr_of_expr v)) + let mk_store ( ctx : context ) ( a : expr ) ( i : expr ) ( v : expr ) = + expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (Expr.gno a) (Expr.gno i) (Expr.gno v)) let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (ptr_of_expr v)) + expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = - let m x = (ptr_of_expr (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) + let mk_map ( ctx : context ) ( f : func_decl ) ( args : expr list ) = + let m x = (Expr.gno x) in + expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) - let mk_term_array ( ctx : context ) ( arg : array_expr ) = - array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) + let mk_term_array ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (Expr.gno arg)) end module Set = struct - type set_sort = SetSort of sort - - let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - SetSort(s) - - let sort_of_set_sort s = match s with SetSort(x) -> x - let mk_sort ( ctx : context ) ( ty : sort ) = - set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) @@ -1275,10 +1169,10 @@ struct expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (ptr_of_expr set) (ptr_of_expr element)) + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) let mk_union ( ctx : context ) ( args : expr list ) = expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) @@ -1287,53 +1181,37 @@ struct expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) let mk_complement ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (ptr_of_expr arg)) + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (ptr_of_expr elem) (ptr_of_expr set)) + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (ptr_of_expr arg1) (ptr_of_expr arg2)) + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) end module FiniteDomain = struct - type finite_domain_sort = FiniteDomainSort of sort - - let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x - - let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in - FiniteDomainSort(s) + (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = mk_sort ctx (Symbol.mk_string ctx name) size - let is_finite_domain ( x : expr ) = - let nc = (nc_of_expr x) in - (Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == FINITE_DOMAIN_SORT) + let nc = (Expr.gnc x) in + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - let get_size ( x : finite_domain_sort ) = - let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in + let get_size ( x : sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (Sort.gnc x) (Sort.gno x)) in if r then v else raise (Z3native.Exception "Conversion failed.") end @@ -1341,29 +1219,10 @@ end module Relation = struct - type relation_sort = RelationSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - RelationSort(s) - - let sort_of_relation_sort s = match s with RelationSort(x) -> x - - let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - - let is_relation ( x : expr ) = - let nc = (nc_of_expr x) in - ((Z3native.is_app (nc_of_expr x) (ptr_of_expr x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (ptr_of_expr x))) == RELATION_SORT)) + let nc = (Expr.gnc x) in + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) @@ -1379,48 +1238,17 @@ struct let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) + let get_arity ( x : sort ) = Z3native.get_relation_arity (Sort.gnc x) (Sort.gno x) - let get_column_sorts ( x : relation_sort ) = + let get_column_sorts ( x : sort ) = let n = get_arity x in - let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + let f i = (sort_of_ptr (Sort.gc x) (Z3native.get_relation_column (Sort.gnc x) (Sort.gno x) i)) in mk_list f n - end module Datatype = struct - type datatype_sort = DatatypeSort of sort - type datatype_expr = DatatypeExpr of expr - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - DatatypeSort(s) - - let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x - - let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - - let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - - let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - module Constructor = struct type constructor = z3_native_object @@ -1517,24 +1345,24 @@ struct ) c - let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) + let get_num_constructors ( x : sort ) = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) - let get_constructors ( x : datatype_sort ) = + let get_constructors ( x : sort ) = let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in mk_list f n - let get_recognizers ( x : datatype_sort ) = + let get_recognizers ( x : sort ) = let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i) in mk_list f n - let get_accessors ( x : datatype_sort ) = + let get_accessors ( x : sort ) = let n = (get_num_constructors x) in let f i = ( - let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let fd = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i) in let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + let g j = func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) i j) in mk_list g ds ) in mk_list f n @@ -1543,467 +1371,133 @@ end module Enumeration = struct - type enum_sort = EnumSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = - let s = (sort_of_ptr ctx no) in - let res = EnumSort(s) in - res - - let sort_of_enum_sort s = match s with EnumSort(x) -> x - - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in - sort_of_ptr ctx a (list_of_array b) (list_of_array c) + let (a, _, _) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - let get_const_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + let get_const_decls ( x : sort ) = + let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in + let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i)) in mk_list f n - let get_tester_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + let get_tester_decls ( x : sort ) = + let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in + let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i)) in mk_list f n end module List_ = -struct - type list_sort = ListSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - let res = ListSort(s) in - res - - let sort_of_list_sort s = match s with ListSort(x) -> x - - let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - +struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - sort_of_ptr ctx r a b c d e f + let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + sort_of_ptr ctx r let mk_list_s ( ctx : context ) (name : string) elem_sort = mk_sort ctx (Symbol.mk_string ctx name) elem_sort - let get_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) + let get_nil_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 0) - let get_is_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) + let get_is_nil_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 0) - let get_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) + let get_cons_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) 1) - let get_is_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) + let get_is_cons_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) 1) - let get_head_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) + let get_head_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 0) - let get_tail_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) + let get_tail_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor_accessor (Sort.gnc x) (Sort.gno x) 1 1) - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] + let nil ( x : sort ) = expr_of_func_app (Sort.gc x) (get_nil_decl x) [] end module Tuple = struct - type tuple_sort = TupleSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - TupleSort(s) - - let sort_of_tuple_sort s = match s with TupleSort(x) -> x - - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in sort_of_ptr ctx r - let get_mk_decl ( x : tuple_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + let get_mk_decl ( x : sort ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_mk_decl (Sort.gnc x) (Sort.gno x)) - let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) + let get_num_fields ( x : sort ) = Z3native.get_tuple_sort_num_fields (Sort.gnc x) (Sort.gno x) - let get_field_decls ( x : tuple_sort ) = + let get_field_decls ( x : sort ) = let n = get_num_fields x in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + let f i = func_decl_of_ptr (Sort.gc x) (Z3native.get_tuple_sort_field_decl (Sort.gnc x) (Sort.gno x) i) in mk_list f n end -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> arith_sort - val expr_of_arith_expr : arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> arith_expr +module Arithmetic = +struct - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr list -> arith_expr - val mk_mul : context -> arith_expr list -> arith_expr - val mk_sub : context -> arith_expr list -> arith_expr - val mk_unary_minus : context -> arith_expr -> arith_expr - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end = struct - type arith_sort = ArithSort of sort - type arith_expr = ArithExpr of expr - - let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - - let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) - - let sort_of_arith_sort s = match s with ArithSort(x) -> x - let expr_of_arith_expr e = match e with ArithExpr(x) -> x - - let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - - let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_sort_of_sort (sort_of_ptr ctx no) - - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (c_of_expr e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (nc_of_expr e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (ptr_of_expr e) - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - - let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - - let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (int_expr_of_ptr ctx no) - - let arith_sort_of_int_sort s = match s with IntSort(x) -> x - let arith_expr_of_int_expr e = match e with IntExpr(x) -> x - let int_expr_of_int_num e = match e with IntNum(x) -> x - - let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - - let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) - - let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) - let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) - let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) - let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) - let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) - let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) - let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) - let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) - let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - + module Integer = + struct let mk_sort ( ctx : context ) = - int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) + sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + let get_int ( x : expr ) = + let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = - IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + Expr.mk_const ctx name (mk_sort ctx) let mk_int_const_s ( ctx : context ) ( name : string ) = mk_int_const ctx (Symbol.mk_string ctx name) - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + let mk_mod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) let mk_int_numeral_s ( ctx : context ) ( v : string ) = - int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_int_numeral_i ( ctx : context ) ( v : int ) = - int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_int2real ( ctx : context ) ( t : int_expr ) = - Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + let mk_int2real ( ctx : context ) ( t : expr ) = + (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (Expr.gno t))) - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + let mk_int2bv ( ctx : context ) ( n : int ) ( t : expr ) = + (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (Expr.gno t))) end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : real_sort -> arith_sort - val real_sort_of_arith_sort : arith_sort -> real_sort - val arith_expr_of_real_expr : real_expr -> arith_expr - val real_expr_of_rat_num : rat_num -> real_expr - val real_expr_of_arith_expr : arith_expr -> real_expr - val rat_num_of_real_expr : real_expr -> rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - let arith_sort_of_real_sort s = match s with RealSort(x) -> x - let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - let real_expr_of_rat_num e = match e with RatNum(x) -> x - - let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - - let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - - let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (real_expr_of_ptr ctx no) - - let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - - let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) - let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) - let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) - let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) - let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) - let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) - let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) - let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) - let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - - + module Real = + struct let mk_sort ( ctx : context ) = - real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) + sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - let get_numerator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + let get_numerator ( x : expr ) = + expr_of_ptr (Expr.gc x) (Z3native.get_numerator (Expr.gnc x) (Expr.gno x)) - let get_denominator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + let get_denominator ( x : expr ) = + expr_of_ptr (Expr.gc x) (Z3native.get_denominator (Expr.gnc x) (Expr.gno x)) - let to_decimal_string ( x : rat_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = - RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + Expr.mk_const ctx name (mk_sort ctx) let mk_real_const_s ( ctx : context ) ( name : string ) = mk_real_const ctx (Symbol.mk_string ctx name) @@ -2012,67 +1506,38 @@ end = struct if (den == 0) then raise (Z3native.Exception "Denominator is zero") else - rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) + expr_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) let mk_numeral_s ( ctx : context ) ( v : string ) = - rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_numeral_i ( ctx : context ) ( v : int ) = - rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + let mk_is_integer ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (Expr.gno t))) - let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + let mk_real2int ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (Expr.gno t))) end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x - - let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - - let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) - - let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) - let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) - let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - - - let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + module AlgebraicNumber = + struct + let to_upper ( x : expr ) ( precision : int ) = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) - let to_lower ( x : algebraic_num ) precision = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + let to_lower ( x : expr ) precision = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) end let is_int ( x : expr ) = - (Z3native.is_numeral_ast (nc_of_expr x) (nc_of_expr x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == INT_SORT) + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) @@ -2107,224 +1572,55 @@ end = struct let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (nc_of_expr x)))) == REAL_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (nc_of_expr x) (nc_of_expr x) + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - let mk_add ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_add ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_mul ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_mul ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_sub ( ctx : context ) ( t : arith_expr list ) = - let f x = (ptr_of_expr (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + let mk_sub ( ctx : context ) ( t : expr list ) = + let f x = (Expr.gno x) in + (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) + let mk_unary_minus ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) - let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) + let mk_div ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) + let mk_power ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + let mk_le ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + let mk_gt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) + let mk_ge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) end -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - val mk_sort : context -> int -> bitvec_sort - val is_bv : Expr.expr -> bool - val is_bv_numeral : Expr.expr -> bool - val is_bv_bit1 : Expr.expr -> bool - val is_bv_bit0 : Expr.expr -> bool - val is_bv_uminus : Expr.expr -> bool - val is_bv_add : Expr.expr -> bool - val is_bv_sub : Expr.expr -> bool - val is_bv_mul : Expr.expr -> bool - val is_bv_sdiv : Expr.expr -> bool - val is_bv_udiv : Expr.expr -> bool - val is_bv_SRem : Expr.expr -> bool - val is_bv_urem : Expr.expr -> bool - val is_bv_smod : Expr.expr -> bool - val is_bv_sdiv0 : Expr.expr -> bool - val is_bv_udiv0 : Expr.expr -> bool - val is_bv_srem0 : Expr.expr -> bool - val is_bv_urem0 : Expr.expr -> bool - val is_bv_smod0 : Expr.expr -> bool - val is_bv_ule : Expr.expr -> bool - val is_bv_sle : Expr.expr -> bool - val is_bv_uge : Expr.expr -> bool - val is_bv_sge : Expr.expr -> bool - val is_bv_ult : Expr.expr -> bool - val is_bv_slt : Expr.expr -> bool - val is_bv_ugt : Expr.expr -> bool - val is_bv_sgt : Expr.expr -> bool - val is_bv_and : Expr.expr -> bool - val is_bv_or : Expr.expr -> bool - val is_bv_not : Expr.expr -> bool - val is_bv_xor : Expr.expr -> bool - val is_bv_nand : Expr.expr -> bool - val is_bv_nor : Expr.expr -> bool - val is_bv_xnor : Expr.expr -> bool - val is_bv_concat : Expr.expr -> bool - val is_bv_signextension : Expr.expr -> bool - val is_bv_zeroextension : Expr.expr -> bool - val is_bv_extract : Expr.expr -> bool - val is_bv_repeat : Expr.expr -> bool - val is_bv_reduceor : Expr.expr -> bool - val is_bv_reduceand : Expr.expr -> bool - val is_bv_comp : Expr.expr -> bool - val is_bv_shiftleft : Expr.expr -> bool - val is_bv_shiftrightlogical : Expr.expr -> bool - val is_bv_shiftrightarithmetic : Expr.expr -> bool - val is_bv_rotateleft : Expr.expr -> bool - val is_bv_rotateright : Expr.expr -> bool - val is_bv_rotateleftextended : Expr.expr -> bool - val is_bv_rotaterightextended : Expr.expr -> bool - val is_int_to_bv : Expr.expr -> bool - val is_bv_to_int : Expr.expr -> bool - val is_bv_carry : Expr.expr -> bool - val is_bv_xor3 : Expr.expr -> bool - val get_size : bitvec_sort -> int - val get_int : bitvec_num -> int - val to_string : bitvec_num -> string - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - val mk_const_s : context -> string -> int -> bitvec_expr - val mk_not : context -> bitvec_expr -> Expr.expr - val mk_redand : context -> bitvec_expr -> Expr.expr - val mk_redor : context -> bitvec_expr -> Expr.expr - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_neg : context -> bitvec_expr -> bitvec_expr - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_numeral : context -> string -> int -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of sort - type bitvec_expr = BitVecExpr of expr - type bitvec_num = BitVecNum of bitvec_expr - - let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x - - let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - - let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_sort_of_sort (sort_of_ptr ctx no) - - let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - - let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_expr_of_expr (expr_of_ptr ctx no) - - let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - - let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) - - let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x - let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - - - let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) - let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) - let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (c_of_expr e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (nc_of_expr e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (ptr_of_expr e) - let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) - let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) - let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - - +module BitVector = +struct let mk_sort ( ctx : context ) size = - bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) + sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (nc_of_expr x) (Z3native.get_sort (nc_of_expr x) (ptr_of_expr x)))) == BV_SORT) + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) @@ -2376,112 +1672,112 @@ end = struct let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) + let get_int ( x : expr ) = + let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) + Expr.mk_const ctx name (mk_sort ctx size) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = mk_const ctx (Symbol.mk_string ctx name) size - let mk_not ( ctx : context ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - let mk_redand ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - let mk_redor ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - let mk_neg ( ctx : context ) ( t : bitvec_expr) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_not ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (Expr.gno t)) + let mk_redand ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (Expr.gno t)) + let mk_redor ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (Expr.gno t)) + let mk_and ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_or ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_xor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_nand ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_nor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_xnor ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_neg ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (Expr.gno t)) + let mk_add ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_sub ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_mul ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_udiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_sdiv ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_urem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_srem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_smod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ult ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_slt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_ule ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sle ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_uge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sge ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_ugt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sgt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_concat ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (Expr.gno t)) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (Expr.gno t)) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (Expr.gno t)) + let mk_repeat ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (Expr.gno t)) + let mk_shl ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_lshr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ashr ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (Expr.gno t)) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (Expr.gno t)) + let mk_ext_rotate_left ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_ext_rotate_right ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_bv2int ( ctx : context ) ( t : expr ) ( signed : bool ) = + expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (Expr.gno t) signed) + let mk_add_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_add_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sub_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_sub_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + let mk_neg_no_overflow ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (Expr.gno t))) + let mk_mul_no_overflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) ( signed : bool) = + (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) + let mk_mul_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx size))) end @@ -2556,8 +1852,8 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in + let assert_ ( x : goal ) ( constraints : expr list ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e) in ignore (List.map f constraints) ; () @@ -2572,7 +1868,7 @@ struct let get_formulas ( x : goal ) = let n = get_size x in - let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + let f i = ((expr_of_ptr (z3obj_gc x) (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in mk_list f n @@ -2749,7 +2045,7 @@ struct exception ModelEvaluationFailedException of string let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (ptr_of_expr t) completion) in + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then raise (ModelEvaluationFailedException "evaluation failed") else @@ -3076,19 +2372,19 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + let assert_ ( x : solver ) ( constraints : expr list ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + let assert_and_track_a ( x : solver ) ( cs : expr list ) ( ps : expr list ) = if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else - let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno a) (Expr.gno b)) in ignore (List.iter2 f cs ps) - let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) + let assert_and_track ( x : solver ) ( c : expr ) ( p : expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno c) (Expr.gno p) let get_num_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in @@ -3097,15 +2393,15 @@ struct let get_assertions ( x : solver ) = let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + let f i = (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in mk_list f n - let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = + let check ( x : solver ) ( assumptions : expr list ) = let r = if ((List.length assumptions) == 0) then lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) else - let f x = (ptr_of_expr (Boolean.expr_of_bool_expr x)) in + let f x = (Expr.gno x) in lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) in match r with @@ -3179,24 +2475,24 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + let assert_ ( x : fixedpoint ) ( constraints : expr list ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) ; () let register_relation ( x : fixedpoint ) ( f : func_decl ) = Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = + let add_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol option ) = match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno y) let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) - let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + let query ( x : fixedpoint ) ( query : expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Expr.gno query))) with | L_TRUE -> Solver.SATISFIABLE | L_FALSE -> Solver.UNSATISFIABLE | _ -> Solver.UNKNOWN @@ -3214,8 +2510,8 @@ struct let pop ( x : fixedpoint ) = Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) + let update_rule ( x : fixedpoint ) ( rule : expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Expr.gno rule) (Symbol.gno name) let get_answer ( x : fixedpoint ) = let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in @@ -3238,27 +2534,27 @@ struct Some (expr_of_ptr (z3obj_gc x) q) let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (ptr_of_expr property) + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = - let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in + let to_string_q ( x : fixedpoint ) ( queries : expr list ) = + let f x = Expr.gno x in Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let get_assertions ( x : fixedpoint ) = let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let mk_fixedpoint ( ctx : context ) = create ctx @@ -3287,10 +2583,10 @@ end module SMT = struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : expr list ) ( formula : expr ) = Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) - (Boolean.gno formula) + (List.length assumptions) (let f x = Expr.gno (x) in (Array.of_list (List.map f assumptions))) + (Expr.gno formula) let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = let csn = (List.length sort_names) in @@ -3328,14 +2624,14 @@ struct let get_smtlib_formulas ( ctx : context ) = let n = (get_num_smtlib_formulas ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + let f i =(expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in mk_list f n let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) let get_smtlib_assumptions ( ctx : context ) = let n = (get_num_smtlib_assumptions ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + let f i = (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in mk_list f n let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) @@ -3360,14 +2656,14 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - + (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = let csn = (List.length sort_names) in let cs = (List.length sorts) in @@ -3376,13 +2672,13 @@ struct if (csn != cs || cdn != cd) then raise (Z3native.Exception "Argument size mismatch") else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 9f451c45f..908b3023d 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -70,14 +70,7 @@ end (** Symbols are used to name several term and type constructors *) module Symbol : sig - (** Numbered Symbols *) - type int_symbol - - (** Named Symbols *) - type string_symbol - - (** Symbols *) - type symbol = S_Int of int_symbol | S_Str of string_symbol + type symbol (** The kind of the symbol (int or string) *) val kind : symbol -> Z3enums.symbol_kind @@ -89,10 +82,10 @@ sig val is_string_symbol : symbol -> bool (** The int value of the symbol. *) - val get_int : int_symbol -> int + val get_int : symbol -> int (** The string value of the symbol. *) - val get_string : string_symbol -> string + val get_string : symbol -> string (** A string representation of the symbol. *) val to_string : symbol -> string @@ -251,15 +244,9 @@ end (** The Sort module implements type information for ASTs *) module Sort : sig - (** Sorts *) type sort = Sort of AST.ast - (** Uninterpreted Sorts *) - type uninterpreted_sort = UninterpretedSort of sort - val ast_of_sort : sort -> AST.ast - val sort_of_uninterpreted_sort : uninterpreted_sort -> sort - val uninterpreted_sort_of_sort : sort -> uninterpreted_sort (** Comparison operator. @return True if the two sorts are from the same context @@ -279,10 +266,10 @@ sig val to_string : sort -> string (** Create a new uninterpreted sort. *) - val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort + val mk_uninterpreted : context -> Symbol.symbol -> sort (** Create a new uninterpreted sort. *) - val mk_uninterpreted_s : context -> string -> uninterpreted_sort + val mk_uninterpreted_s : context -> string -> sort end (** Function declarations *) @@ -597,58 +584,50 @@ end (** Boolean expressions *) module Boolean : sig - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - val expr_of_bool_expr : bool_expr -> Expr.expr - val sort_of_bool_sort : bool_sort -> Sort.sort - val bool_sort_of_sort : Sort.sort -> bool_sort - val bool_expr_of_expr : Expr.expr -> bool_expr - (** Create a Boolean sort *) - val mk_sort : context -> bool_sort + val mk_sort : context -> Sort.sort (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> bool_expr + val mk_const : context -> Symbol.symbol -> Expr.expr (** Create a Boolean constant. *) - val mk_const_s : context -> string -> bool_expr + val mk_const_s : context -> string -> Expr.expr (** The true Term. *) - val mk_true : context -> bool_expr + val mk_true : context -> Expr.expr (** The false Term. *) - val mk_false : context -> bool_expr + val mk_false : context -> Expr.expr (** Creates a Boolean value. *) - val mk_val : context -> bool -> bool_expr + val mk_val : context -> bool -> Expr.expr (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr list -> bool_expr + val mk_distinct : context -> Expr.expr list -> Expr.expr (** Mk an expression representing not(a). *) - val mk_not : context -> bool_expr -> bool_expr + val mk_not : context -> Expr.expr -> Expr.expr (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) - val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr + val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 iff t2. *) - val mk_iff : context -> bool_expr -> bool_expr -> bool_expr + val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 -> t2. *) - val mk_implies : context -> bool_expr -> bool_expr -> bool_expr + val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 xor t2. *) - val mk_xor : context -> bool_expr -> bool_expr -> bool_expr + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing the AND of args *) - val mk_and : context -> bool_expr list -> bool_expr + val mk_and : context -> Expr.expr list -> Expr.expr (** Create an expression representing the OR of args *) - val mk_or : context -> bool_expr list -> bool_expr + val mk_or : context -> Expr.expr list -> Expr.expr end (** Quantifier expressions *) @@ -731,7 +710,7 @@ sig val get_bound_variable_sorts : quantifier -> Sort.sort list (** The body of the quantifier. *) - val get_body : quantifier -> Boolean.bool_expr + val get_body : quantifier -> Expr.expr (** Creates a new bound variable. *) val mk_bound : context -> int -> Sort.sort -> Expr.expr @@ -761,17 +740,8 @@ end (** Functions to manipulate Array expressions *) module Array_ : sig - type array_sort = ArraySort of Sort.sort - type array_expr = ArrayExpr of Expr.expr - - val sort_of_array_sort : array_sort -> Sort.sort - val array_sort_of_sort : Sort.sort -> array_sort - val expr_of_array_expr : array_expr -> Expr.expr - - val array_expr_of_expr : Expr.expr -> array_expr - (** Create a new array sort. *) - val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort + val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort (** Indicates whether the term is an array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). @@ -802,16 +772,16 @@ sig val is_array : Expr.expr -> bool (** The domain of the array sort. *) - val get_domain : array_sort -> Sort.sort + val get_domain : Sort.sort -> Sort.sort (** The range of the array sort. *) - val get_range : array_sort -> Sort.sort + val get_range : Sort.sort -> Sort.sort (** Create an array constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr + val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> Expr.expr (** Create an array constant. *) - val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr + val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> Expr.expr (** Array read. @@ -823,7 +793,7 @@ sig The sort of the result is range. {!Array_.mk_sort} {!mk_store} *) - val mk_select : context -> array_expr -> Expr.expr -> array_expr + val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr (** Array update. @@ -839,7 +809,7 @@ sig respect to i may be a different value). {!Array_.mk_sort} {!mk_select} *) - val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create a constant array. @@ -847,7 +817,7 @@ sig produces the value v. {!Array_.mk_sort} {!mk_select} *) - val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr + val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr (** Maps f on the argument arrays. @@ -857,24 +827,20 @@ sig {!Array_.mk_sort} {!mk_select} {!mk_store} *) - val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr + val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr (** Access the array default value. Produces the default range value, for arrays that can be represented as finite maps with a default range value. *) - val mk_term_array : context -> array_expr -> array_expr + val mk_term_array : context -> Expr.expr -> Expr.expr end (** Functions to manipulate Set expressions *) module Set : sig - type set_sort = SetSort of Sort.sort - - val sort_of_set_sort : set_sort -> Sort.sort - (** Create a set type. *) - val mk_sort : context -> Sort.sort -> set_sort + val mk_sort : context -> Sort.sort -> Sort.sort (** Indicates whether the term is set union *) val is_union : Expr.expr -> bool @@ -925,16 +891,11 @@ end (** Functions to manipulate Finite Domain expressions *) module FiniteDomain : sig - type finite_domain_sort = FiniteDomainSort of Sort.sort - - val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort - val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort + (** Create a new finite domain sort. *) + val mk_sort : context -> Symbol.symbol -> int -> Sort.sort (** Create a new finite domain sort. *) - val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort - - (** Create a new finite domain sort. *) - val mk_sort_s : context -> string -> int -> finite_domain_sort + val mk_sort_s : context -> string -> int -> Sort.sort (** Indicates whether the term is of an array sort. *) val is_finite_domain : Expr.expr -> bool @@ -943,18 +904,13 @@ sig val is_lt : Expr.expr -> bool (** The size of the finite domain sort. *) - val get_size : finite_domain_sort -> int + val get_size : Sort.sort -> int end (** Functions to manipulate Relation expressions *) module Relation : sig - type relation_sort = RelationSort of Sort.sort - - val sort_of_relation_sort : relation_sort -> Sort.sort - val relation_sort_of_sort : Sort.sort -> relation_sort - (** Indicates whether the term is of a relation sort. *) val is_relation : Expr.expr -> bool @@ -1034,23 +990,15 @@ sig val is_clone : Expr.expr -> bool (** The arity of the relation sort. *) - val get_arity : relation_sort -> int + val get_arity : Sort.sort -> int (** The sorts of the columns of the relation sort. *) - val get_column_sorts : relation_sort -> relation_sort list + val get_column_sorts : Sort.sort -> Sort.sort list end (** Functions to manipulate Datatype expressions *) module Datatype : sig - type datatype_sort = DatatypeSort of Sort.sort - type datatype_expr = DatatypeExpr of Expr.expr - - val sort_of_datatype_sort : datatype_sort -> Sort.sort - val datatype_sort_of_sort : Sort.sort -> datatype_sort - val expr_of_datatype_expr : datatype_expr -> Expr.expr - val datatype_expr_of_expr : Expr.expr -> datatype_expr - (** Datatype Constructors *) module Constructor : sig @@ -1080,160 +1028,129 @@ sig val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor (** Create a new datatype sort. *) - val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort + val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> Sort.sort (** Create a new datatype sort. *) - val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort + val mk_sort_s : context -> string -> Constructor.constructor list -> Sort.sort (** Create mutually recursive datatypes. *) - val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list + val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> Sort.sort list (** Create mutually recursive data-types. *) - val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list + val mk_sorts_s : context -> string list -> Constructor.constructor list list -> Sort.sort list (** The number of constructors of the datatype sort. *) - val get_num_constructors : datatype_sort -> int + val get_num_constructors : Sort.sort -> int (** The constructors. *) - val get_constructors : datatype_sort -> FuncDecl.func_decl list + val get_constructors : Sort.sort -> FuncDecl.func_decl list (** The recognizers. *) - val get_recognizers : datatype_sort -> FuncDecl.func_decl list + val get_recognizers : Sort.sort -> FuncDecl.func_decl list (** The constructor accessors. *) - val get_accessors : datatype_sort -> FuncDecl.func_decl list list + val get_accessors : Sort.sort -> FuncDecl.func_decl list list end (** Functions to manipulate Enumeration expressions *) module Enumeration : sig - type enum_sort = EnumSort of Sort.sort - - val sort_of_enum_sort : enum_sort -> Sort.sort + (** Create a new enumeration sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort (** Create a new enumeration sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort - - (** Create a new enumeration sort. *) - val mk_sort_s : context -> string -> string list -> enum_sort + val mk_sort_s : context -> string -> string list -> Sort.sort (** The function declarations of the constants in the enumeration. *) - val get_const_decls : enum_sort -> FuncDecl.func_decl list + val get_const_decls : Sort.sort -> FuncDecl.func_decl list (** The test predicates for the constants in the enumeration. *) - val get_tester_decls : enum_sort -> FuncDecl.func_decl list + val get_tester_decls : Sort.sort -> FuncDecl.func_decl list end (** Functions to manipulate List expressions *) module List_ : sig - type list_sort = ListSort of Sort.sort - - val sort_of_list_sort : list_sort -> Sort.sort + (** Create a new list sort. *) + val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort (** Create a new list sort. *) - val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort - - (** Create a new list sort. *) - val mk_list_s : context -> string -> Sort.sort -> list_sort + val mk_list_s : context -> string -> Sort.sort -> Sort.sort (** The declaration of the nil function of this list sort. *) - val get_nil_decl : list_sort -> FuncDecl.func_decl + val get_nil_decl : Sort.sort -> FuncDecl.func_decl (** The declaration of the isNil function of this list sort. *) - val get_is_nil_decl : list_sort -> FuncDecl.func_decl + val get_is_nil_decl : Sort.sort -> FuncDecl.func_decl (** The declaration of the cons function of this list sort. *) - val get_cons_decl : list_sort -> FuncDecl.func_decl + val get_cons_decl : Sort.sort -> FuncDecl.func_decl (** The declaration of the isCons function of this list sort. *) - val get_is_cons_decl : list_sort -> FuncDecl.func_decl + val get_is_cons_decl : Sort.sort -> FuncDecl.func_decl (** The declaration of the head function of this list sort. *) - val get_head_decl : list_sort -> FuncDecl.func_decl + val get_head_decl : Sort.sort -> FuncDecl.func_decl (** The declaration of the tail function of this list sort. *) - val get_tail_decl : list_sort -> FuncDecl.func_decl + val get_tail_decl : Sort.sort -> FuncDecl.func_decl (** The empty list. *) - val nil : list_sort -> Expr.expr + val nil : Sort.sort -> Expr.expr end (** Functions to manipulate Tuple expressions *) module Tuple : sig - type tuple_sort = TupleSort of Sort.sort - - val sort_of_tuple_sort : tuple_sort -> Sort.sort - (** Create a new tuple sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> Sort.sort (** The constructor function of the tuple. *) - val get_mk_decl : tuple_sort -> FuncDecl.func_decl + val get_mk_decl : Sort.sort -> FuncDecl.func_decl (** The number of fields in the tuple. *) - val get_num_fields : tuple_sort -> int + val get_num_fields : Sort.sort -> int (** The field declarations. *) - val get_field_decls : tuple_sort -> FuncDecl.func_decl list + val get_field_decls : Sort.sort -> FuncDecl.func_decl list end (** Functions to manipulate arithmetic expressions *) module rec Arithmetic : sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort - val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr - (** Integer Arithmetic *) module rec Integer : sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort - val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort - val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr - val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr - val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr - val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num - (** Create a new integer sort. *) - val mk_sort : context -> int_sort + val mk_sort : context -> Sort.sort (** Retrieve the int value. *) - val get_int : int_num -> int + val get_int : Expr.expr -> int (** Returns a string representation of the numeral. *) - val to_string : int_num -> string + val to_string : Expr.expr -> string (** Creates an integer constant. *) - val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const : context -> Symbol.symbol -> Expr.expr (** Creates an integer constant. *) - val mk_int_const_s : context -> string -> int_expr + val mk_int_const_s : context -> string -> Expr.expr (** Create an expression representing t1 mod t2. The arguments must have int type. *) - val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 rem t2. The arguments must have int type. *) - val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer numeral. *) - val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_s : context -> string -> Expr.expr (** Create an integer numeral. @return A Term with the given value and sort Integer *) - val mk_int_numeral_i : context -> int -> int_num + val mk_int_numeral_i : context -> int -> Expr.expr (** Coerce an integer to a real. @@ -1243,7 +1160,7 @@ sig You can take the floor of a real by creating an auxiliary integer Term k and and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. The argument must be of integer sort. *) - val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2real : context -> Expr.expr -> Expr.expr (** Create an n-bit bit-vector from an integer argument. @@ -1253,94 +1170,78 @@ sig when solving constraints with this function. The argument must be of integer sort. *) - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + val mk_int2bv : context -> int -> Expr.expr -> Expr.expr end (** Real Arithmetic *) and Real : sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - (** Create a real sort. *) - val mk_sort : context -> real_sort + val mk_sort : context -> Sort.sort (** The numerator of a rational numeral. *) - val get_numerator : rat_num -> Integer.int_num + val get_numerator : Expr.expr-> Expr.expr (** The denominator of a rational numeral. *) - val get_denominator : rat_num -> Integer.int_num + val get_denominator : Expr.expr-> Expr.expr (** Returns a string representation in decimal notation. The result has at most as many decimal places as indicated by the int argument.*) - val to_decimal_string : rat_num -> int -> string + val to_decimal_string : Expr.expr-> int -> string (** Returns a string representation of the numeral. *) - val to_string : rat_num -> string + val to_string : Expr.expr-> string (** Creates a real constant. *) - val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const : context -> Symbol.symbol -> Expr.expr (** Creates a real constant. *) - val mk_real_const_s : context -> string -> real_expr + val mk_real_const_s : context -> string -> Expr.expr (** Create a real numeral from a fraction. @return A Term with rational value and sort Real {!mk_numeral_s} *) - val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_nd : context -> int -> int -> Expr.expr (** Create a real numeral. @return A Term with the given value and sort Real *) - val mk_numeral_s : context -> string -> rat_num + val mk_numeral_s : context -> string -> Expr.expr (** Create a real numeral. @return A Term with the given value and sort Real *) - val mk_numeral_i : context -> int -> rat_num + val mk_numeral_i : context -> int -> Expr.expr (** Creates an expression that checks whether a real number is an integer. *) - val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_is_integer : context -> Expr.expr -> Expr.expr (** Coerce a real to an integer. The semantics of this function follows the SMT-LIB standard for the function to_int. The argument must be of real sort. *) - val mk_real2int : context -> real_expr -> Integer.int_expr + val mk_real2int : context -> Expr.expr -> Expr.expr end (** Algebraic Numbers *) and AlgebraicNumber : sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr - val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num - (** Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^precision. {!is_algebraic_number} @return A numeral Expr of sort Real *) - val to_upper : algebraic_num -> int -> Real.rat_num + val to_upper : Expr.expr -> int -> Expr.expr (** Return a lower bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^precision. {!is_algebraic_number} @return A numeral Expr of sort Real *) - val to_lower : algebraic_num -> int -> Real.rat_num + val to_lower : Expr.expr -> int -> Expr.expr (** Returns a string representation in decimal notation. The result has at most as many decimal places as the int argument provided.*) - val to_decimal_string : algebraic_num -> int -> string + val to_decimal_string : Expr.expr -> int -> string (** Returns a string representation of the numeral. *) - val to_string : algebraic_num -> string + val to_string : Expr.expr -> string end (** Indicates whether the term is of integer sort. *) @@ -1407,52 +1308,41 @@ sig val is_algebraic_number : Expr.expr -> bool (** Create an expression representing t[0] + t[1] + .... *) - val mk_add : context -> arith_expr list -> arith_expr + val mk_add : context -> Expr.expr list -> Expr.expr (** Create an expression representing t[0] * t[1] * .... *) - val mk_mul : context -> arith_expr list -> arith_expr + val mk_mul : context -> Expr.expr list -> Expr.expr (** Create an expression representing t[0] - t[1] - .... *) - val mk_sub : context -> arith_expr list -> arith_expr + val mk_sub : context -> Expr.expr list -> Expr.expr (** Create an expression representing -t. *) - val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_unary_minus : context -> Expr.expr -> Expr.expr (** Create an expression representing t1 / t2. *) - val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 ^ t2. *) - val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 < t2 *) - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 <= t2 *) - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 > t2 *) - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing t1 >= t2 *) - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> Expr.expr -> Expr.expr -> Expr.expr end (** Functions to manipulate bit-vector expressions *) and BitVector : sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - (** Create a new bit-vector sort. *) - val mk_sort : context -> int -> bitvec_sort + val mk_sort : context -> int -> Sort.sort (** Indicates whether the terms is of bit-vector sort. *) val is_bv : Expr.expr -> bool @@ -1624,71 +1514,71 @@ sig val is_bv_xor3 : Expr.expr -> bool (** The size of a bit-vector sort. *) - val get_size : bitvec_sort -> int + val get_size : Sort.sort -> int (** Retrieve the int value. *) - val get_int : bitvec_num -> int + val get_int : Expr.expr -> int (** Returns a string representation of the numeral. *) - val to_string : bitvec_num -> string + val to_string : Expr.expr -> string (** Creates a bit-vector constant. *) - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + val mk_const : context -> Symbol.symbol -> int -> Expr.expr (** Creates a bit-vector constant. *) - val mk_const_s : context -> string -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> Expr.expr (** Bitwise negation. The argument must have a bit-vector sort. *) - val mk_not : context -> bitvec_expr -> Expr.expr + val mk_not : context -> Expr.expr -> Expr.expr (** Take conjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) - val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> Expr.expr -> Expr.expr (** Take disjunction of bits in a vector,vector of length 1. The argument must have a bit-vector sort. *) - val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> Expr.expr -> Expr.expr (** Bitwise conjunction. The arguments must have a bit-vector sort. *) - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_and : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise disjunction. The arguments must have a bit-vector sort. *) - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XOR. The arguments must have a bit-vector sort. *) - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NAND. The arguments must have a bit-vector sort. *) - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NOR. The arguments must have a bit-vector sort. *) - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XNOR. The arguments must have a bit-vector sort. *) - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Standard two's complement unary minus. The arguments must have a bit-vector sort. *) - val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_neg : context -> Expr.expr -> Expr.expr (** Two's complement addition. The arguments must have the same bit-vector sort. *) - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement subtraction. The arguments must have the same bit-vector sort. *) - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement multiplication. The arguments must have the same bit-vector sort. *) - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned division. @@ -1697,7 +1587,7 @@ sig different from zero. If t2 is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed division. @@ -1709,14 +1599,14 @@ sig If t2 is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned remainder. It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. If t2 is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed remainder. @@ -1725,53 +1615,53 @@ sig If t2 is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed remainder (sign follows divisor). If t2 is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than The arguments must have the same bit-vector sort. *) - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ult : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed less-than The arguments must have the same bit-vector sort. *) - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than or equal to. The arguments must have the same bit-vector sort. *) - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed less-than or equal to. The arguments must have the same bit-vector sort. *) - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater than or equal to. The arguments must have the same bit-vector sort. *) - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater than or equal to. The arguments must have the same bit-vector sort. *) - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater-than. The arguments must have the same bit-vector sort. *) - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater-than. The arguments must have the same bit-vector sort. *) - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector concatenation. @@ -1779,30 +1669,30 @@ sig @return The result is a bit-vector of size n1+n2, where n1 (n2) is the size of t1 (t2). *) - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector extraction. Extract the bits between two limits from a bitvector of size m to yield a new bitvector of size n, where n = high - low + 1. *) - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> Expr.expr -> Expr.expr (** Bit-vector sign extension. Sign-extends the given bit-vector to the (signed) equivalent bitvector of size m+i, where \c m is the size of the given bit-vector. *) - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector zero extension. Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size m+i, where \c m is the size of the given bit-vector. *) - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector repetition. *) - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> Expr.expr -> Expr.expr (** Shift left. @@ -1811,7 +1701,7 @@ sig NB. The semantics of shift operations varies between environments. This definition does not necessarily capture directly the semantics of the programming language or assembly architecture you are modeling.*) - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_shl : context -> Expr.expr -> Expr.expr -> Expr.expr (** Logical shift right @@ -1822,7 +1712,7 @@ sig programming language or assembly architecture you are modeling. The arguments must have a bit-vector sort. *) - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Arithmetic shift right @@ -1835,23 +1725,23 @@ sig programming language or assembly architecture you are modeling. The arguments must have a bit-vector sort. *) - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Rotate Left. Rotate bits of \c t to the left \c i times. *) - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> int -> Expr.expr -> Expr.expr (** Rotate Right. Rotate bits of \c t to the right \c i times.*) - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> int -> Expr.expr -> Expr.expr (** Rotate Left. Rotate bits of the second argument to the left.*) - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_left : context -> Expr.expr -> Expr.expr -> Expr.expr (** Rotate Right. Rotate bits of the second argument to the right. *) - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_right : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer from the bit-vector argument @@ -1863,50 +1753,50 @@ sig NB. This function is essentially treated as uninterpreted. So you cannot expect Z3 to precisely reflect the semantics of this function when solving constraints with this function.*) - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_bv2int : context -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not overflow. The arguments must be of bit-vector sort. *) - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not underflow. The arguments must be of bit-vector sort. *) - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_add_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not overflow. The arguments must be of bit-vector sort. *) - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not underflow. The arguments must be of bit-vector sort. *) - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sub_no_underflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise signed division does not overflow. The arguments must be of bit-vector sort. *) - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise negation does not overflow. The arguments must be of bit-vector sort. *) - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not overflow. The arguments must be of bit-vector sort. *) - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not underflow. The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a bit-vector numeral. *) - val mk_numeral : context -> string -> int -> bitvec_num + val mk_numeral : context -> string -> int -> Expr.expr end (** Functions to manipulate proof expressions *) @@ -2332,7 +2222,7 @@ sig val is_garbage : goal -> bool (** Adds the constraints to the given goal. *) - val assert_ : goal -> Boolean.bool_expr list -> unit + val assert_ : goal -> Expr.expr list -> unit (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool @@ -2348,7 +2238,7 @@ sig val get_size : goal -> int (** The formulas in the goal. *) - val get_formulas : goal -> Boolean.bool_expr list + val get_formulas : goal -> Expr.expr list (** The number of formulas, subformulas and terms in the goal. *) val get_num_exprs : goal -> int @@ -2759,7 +2649,7 @@ sig val reset : solver -> unit (** Assert a constraint (or multiple) into the solver. *) - val assert_ : solver -> Boolean.bool_expr list -> unit + val assert_ : solver -> Expr.expr list -> unit (** * Assert multiple constraints (cs) into the solver, and track them (in the * unsat) core @@ -2772,7 +2662,7 @@ sig * of the Boolean variables provided using {!assert_and_track} * and the Boolean literals * provided using {!check} with assumptions. *) - val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit + val assert_and_track_a : solver -> Expr.expr list -> Expr.expr list -> unit (** * Assert a constraint (c) into the solver, and track it (in the unsat) core * using the Boolean constant p. @@ -2784,20 +2674,20 @@ sig * of the Boolean variables provided using {!assert_and_track} * and the Boolean literals * provided using {!check} with assumptions. *) - val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit + val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit (** The number of assertions in the solver. *) val get_num_assertions : solver -> int (** The set of asserted formulas. *) - val get_assertions : solver -> Boolean.bool_expr list + val get_assertions : solver -> Expr.expr list (** Checks whether the assertions in the solver are consistent or not. {!Model} {!get_unsat_core} {!Proof} *) - val check : solver -> Boolean.bool_expr list -> status + val check : solver -> Expr.expr list -> status (** The model of the last Check. @@ -2863,13 +2753,13 @@ sig val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs (** Assert a constraints into the fixedpoint solver. *) - val assert_ : fixedpoint -> Boolean.bool_expr list -> unit + val assert_ : fixedpoint -> Expr.expr list -> unit (** Register predicate as recursive relation. *) val register_relation : fixedpoint -> FuncDecl.func_decl -> unit (** Add rule into the fixedpoint solver. *) - val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit + val add_rule : fixedpoint -> Expr.expr -> Symbol.symbol option -> unit (** Add table fact to the fixedpoint solver. *) val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit @@ -2878,7 +2768,7 @@ sig A query is a conjunction of constraints. The constraints may include the recursively defined relations. The query is satisfiable if there is an instance of the query variables and a derivation for it. The query is unsatisfiable if there are no derivations satisfying the query variables. *) - val query : fixedpoint -> Boolean.bool_expr -> Solver.status + val query : fixedpoint -> Expr.expr -> Solver.status (** Query the fixedpoint solver. A query is an array of relations. @@ -2897,7 +2787,7 @@ sig val pop : fixedpoint -> unit (** Update named rule into in the fixedpoint solver. *) - val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit + val update_rule : fixedpoint -> Expr.expr -> Symbol.symbol -> unit (** Retrieve satisfying instance or instances of solver, or definitions for the recursive predicates that show unsatisfiability. *) @@ -2923,13 +2813,13 @@ sig val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit (** Convert benchmark given as set of axioms, rules and queries to a string. *) - val to_string_q : fixedpoint -> Boolean.bool_expr list -> string + val to_string_q : fixedpoint -> Expr.expr list -> string (** Retrieve set of rules added to fixedpoint context. *) - val get_rules : fixedpoint -> Boolean.bool_expr list + val get_rules : fixedpoint -> Expr.expr list (** Retrieve set of assertions added to fixedpoint context. *) - val get_assertions : fixedpoint -> Boolean.bool_expr list + val get_assertions : fixedpoint -> Expr.expr list (** Create a Fixedpoint context. *) val mk_fixedpoint : context -> fixedpoint @@ -2985,7 +2875,7 @@ sig (** Convert a benchmark into an SMT-LIB formatted string. @return A string representation of the benchmark. *) - val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Expr.expr list -> Expr.expr -> string (** Parse the given string using the SMT-LIB parser. @@ -3004,13 +2894,13 @@ sig val get_num_smtlib_formulas : context -> int (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_formulas : context -> Boolean.bool_expr list + val get_smtlib_formulas : context -> Expr.expr list (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_assumptions : context -> int (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_assumptions : context -> Boolean.bool_expr list + val get_smtlib_assumptions : context -> Expr.expr list (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) val get_num_smtlib_decls : context -> int @@ -3028,11 +2918,11 @@ sig {!parse_smtlib_string} @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr + val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr (** Parse the given file using the SMT-LIB2 parser. {!parse_smtlib2_string} *) - val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr + val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr end (** Set a global (or module) parameter, which is shared by all Z3 contexts. diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml new file mode 100644 index 000000000..052ca5e22 --- /dev/null +++ b/src/api/ml/z3_rich.ml @@ -0,0 +1,3400 @@ +(** + The Z3 ML/Ocaml Interface. + + Copyright (C) 2012 Microsoft Corporation + @author CM Wintersteiger (cwinter) 2012-12-17 +*) + +open Z3enums + +(* Some helpers. *) +let null = Z3native.mk_null() +let is_null o = (Z3native.is_null o) + + +(* Internal types *) +type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } +type context = z3_native_context + +type z3_native_object = { + m_ctx : context ; + mutable m_n_obj : Z3native.ptr ; + inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; + dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } + + +(** Internal stuff *) +module Internal = +struct + let dispose_context ctx = + if ctx.m_n_obj_cnt == 0 then ( + (Z3native.del_context ctx.m_n_ctx) + ) else ( + Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; + ) + + let create_context settings = + let cfg = Z3native.mk_config in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_context_rc cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + + let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) + let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) + let context_gno ctx = ctx.m_n_ctx + + + let z3obj_gc o = o.m_ctx + let z3obj_gnc o = (context_gno o.m_ctx) + + let z3obj_gno o = o.m_n_obj + let z3obj_sno o ctx no = + (context_add1 ctx) ; + o.inc_ref (context_gno ctx) no ; + ( + if not (is_null o.m_n_obj) then + o.dec_ref (context_gno ctx) o.m_n_obj ; + (context_sub1 ctx) + ) ; + o.m_n_obj <- no + + let z3obj_dispose o = + if not (is_null o.m_n_obj) then + ( + o.dec_ref (z3obj_gnc o) o.m_n_obj ; + (context_sub1 (z3obj_gc o)) + ) ; + o.m_n_obj <- null + + let z3obj_create o = + let f = fun o -> (z3obj_dispose o) in + Gc.finalise f o + + let z3obj_nil_ref x y = () + + let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> + let res : z3_native_object = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res +end + +open Internal + +module Log = +struct + let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) + let close = Z3native.close_log + let append s = Z3native.append_log s +end + + +module Version = +struct + let major = let (x, _, _, _) = Z3native.get_version in x + let minor = let (_, x, _, _) = Z3native.get_version in x + let build = let (_, _, x, _) = Z3native.get_version in x + let revision = let (_, _, _, x) = Z3native.get_version in x + let to_string = + let (mj, mn, bld, rev) = Z3native.get_version in + string_of_int mj ^ "." ^ + string_of_int mn ^ "." ^ + string_of_int bld ^ "." ^ + string_of_int rev ^ "." +end + + +let mk_list ( f : int -> 'a ) ( n : int ) = + let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = + if (i >= n) then + tail + else + (mk_list' f (i+1) n ((f i) :: tail)) + in + mk_list' f 0 n [] + +let list_of_array ( x : _ array ) = + let f i = (Array.get x i) in + mk_list f (Array.length x) + +let mk_context ( cfg : ( string * string ) list ) = + create_context cfg + + +module Symbol = +struct + (* Symbol types *) + type int_symbol = z3_native_object + type string_symbol = z3_native_object + + type symbol = + | S_Int of int_symbol + | S_Str of string_symbol + + + let create_i ( ctx : context ) ( no : Z3native.ptr ) = + let res : int_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let create_s ( ctx : context ) ( no : Z3native.ptr ) = + let res : string_symbol = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let create ( ctx : context ) ( no : Z3native.ptr ) = + match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with + | INT_SYMBOL -> S_Int (create_i ctx no) + | STRING_SYMBOL -> S_Str (create_s ctx no) + + let gc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gc n) + | S_Str(n) -> (z3obj_gc n) + + let gnc ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gnc n) + | S_Str(n) -> (z3obj_gnc n) + + let gno ( x : symbol ) = + match x with + | S_Int(n) -> (z3obj_gno n) + | S_Str(n) -> (z3obj_gno n) + + let symbol_lton ( a : symbol list ) = + let f ( e : symbol ) = (gno e) in + Array.of_list (List.map f a) + + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) + let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL + let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL + let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) + let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) + let to_string ( o : symbol ) = + match (kind o) with + | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) + | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) + + let mk_int ( ctx : context ) ( i : int ) = + S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) + + let mk_string ( ctx : context ) ( s : string ) = + S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) + + let mk_ints ( ctx : context ) ( names : int list ) = + let f elem = mk_int ( ctx : context ) elem in + (List.map f names) + + let mk_strings ( ctx : context ) ( names : string list ) = + let f elem = mk_string ( ctx : context ) elem in + (List.map f names) +end + + +module AST = +struct + type ast = z3_native_object + + let context_of_ast ( x : ast ) = (z3obj_gc x) + let nc_of_ast ( x : ast ) = (z3obj_gnc x) + let ptr_of_ast ( x : ast ) = (z3obj_gno x) + + let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> + match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with + | FUNC_DECL_AST + | SORT_AST + | QUANTIFIER_AST + | APP_AST + | NUMERAL_AST + | VAR_AST -> z3_native_object_of_ast_ptr ctx no + | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") + + module ASTVector = + struct + type ast_vector = z3_native_object + + let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_vector = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_vector_inc_ref ; + dec_ref = Z3native.ast_vector_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_size ( x : ast_vector ) = + Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) + + let get ( x : ast_vector ) ( i : int ) = + ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) + + let set ( x : ast_vector ) ( i : int ) ( value : ast ) = + Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) + + let resize ( x : ast_vector ) ( new_size : int ) = + Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size + + let push ( x : ast_vector ) ( a : ast ) = + Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) + + let translate ( x : ast_vector ) ( to_ctx : context ) = + ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let to_string ( x : ast_vector ) = + Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) + end + + module ASTMap = + struct + type ast_map = z3_native_object + + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let contains ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) + + let find ( x : ast_map ) ( key : ast ) = + ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) + + let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) + + let erase ( x : ast_map ) ( key : ast ) = + Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) + + let reset ( x : ast_map ) = + Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : ast_map ) = + Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) + + let get_keys ( x : ast_map ) = + let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let f i = (ASTVector.get av i) in + mk_list f (ASTVector.get_size av) + + let to_string ( x : ast_map ) = + Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) + let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) + let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) + + let is_expr ( x : ast ) = + match get_ast_kind ( x : ast ) with + | APP_AST + | NUMERAL_AST + | QUANTIFIER_AST + | VAR_AST -> true + | _ -> false + + let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST + let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST + let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST + let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST + + let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) + let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) + + + let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + if (z3obj_gnc a) != (z3obj_gnc b) then + false + else + Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) + + let compare a b = + if (get_id a) < (get_id b) then -1 else + if (get_id a) > (get_id b) then 1 else + 0 + + let ( < ) (a : ast) (b : ast) = (compare a b) + + let translate ( x : ast ) ( to_ctx : context ) = + if (z3obj_gnc x) == (context_gno to_ctx) then + x + else + ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr + let unwrap_ast ( x : ast ) = (z3obj_gno x) +end + +open AST + + +module Sort = +struct + type sort = Sort of AST.ast + type uninterpreted_sort = UninterpretedSort of sort + + let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> + let q = (z3_native_object_of_ast_ptr ctx no) in + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then + raise (Z3native.Exception "Invalid coercion") + else + match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with + | ARRAY_SORT + | BOOL_SORT + | BV_SORT + | DATATYPE_SORT + | INT_SORT + | REAL_SORT + | UNINTERPRETED_SORT + | FINITE_DOMAIN_SORT + | RELATION_SORT -> Sort(q) + | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") + + let ast_of_sort s = match s with Sort(x) -> x + let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x + + let uninterpreted_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + UninterpretedSort(s) + + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) + let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) + let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) + + let sort_lton ( a : sort list ) = + let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) + + let ( = ) : sort -> sort -> bool = fun a b -> + (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) + + + let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) + let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) + let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) + let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) + + let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; + (z3obj_create res) ; + UninterpretedSort(Sort(res)) + + let mk_uninterpreted_s ( ctx : context ) ( s : string ) = + mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) +end + +open Sort + + +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + val func_decl_of_ptr : context -> Z3native.ptr -> func_decl + val gc : func_decl -> context + val gnc : func_decl -> Z3native.ptr + val gno : func_decl -> Z3native.ptr + module Parameter : + sig + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + val get_kind : parameter -> Z3enums.parameter_kind + val get_int : parameter -> int + val get_float : parameter -> float + val get_symbol : parameter -> Symbol.symbol + val get_sort : parameter -> Sort.sort + val get_ast : parameter -> AST.ast + val get_func_decl : parameter -> func_decl + val get_rational : parameter -> string + end + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + val ( = ) : func_decl -> func_decl -> bool + val to_string : func_decl -> string + val get_id : func_decl -> int + val get_arity : func_decl -> int + val get_domain_size : func_decl -> int + val get_domain : func_decl -> Sort.sort list + val get_range : func_decl -> Sort.sort + val get_decl_kind : func_decl -> Z3enums.decl_kind + val get_name : func_decl -> Symbol.symbol + val get_num_parameters : func_decl -> int + val get_parameters : func_decl -> Parameter.parameter list + val apply : func_decl -> Expr.expr list -> Expr.expr +end = struct + type func_decl = FuncDecl of AST.ast + + let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> + if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + FuncDecl(z3_native_object_of_ast_ptr ctx no) + + let ast_of_func_decl f = match f with FuncDecl(x) -> x + + let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = + let res = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.inc_ref ; + dec_ref = Z3native.dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; + (z3obj_create res) ; + FuncDecl(res) + + let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) + let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) + let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) + + module Parameter = + struct + type parameter = + | P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + let get_kind ( x : parameter ) = + (match x with + | P_Int(_) -> PARAMETER_INT + | P_Dbl(_) -> PARAMETER_DOUBLE + | P_Sym(_) -> PARAMETER_SYMBOL + | P_Srt(_) -> PARAMETER_SORT + | P_Ast(_) -> PARAMETER_AST + | P_Fdl(_) -> PARAMETER_FUNC_DECL + | P_Rat(_) -> PARAMETER_RATIONAL) + + let get_int ( x : parameter ) = + match x with + | P_Int(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an int") + + let get_float ( x : parameter ) = + match x with + | P_Dbl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a double") + + let get_symbol ( x : parameter ) = + match x with + | P_Sym(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a symbol") + + let get_sort ( x : parameter ) = + match x with + | P_Srt(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a sort") + + let get_ast ( x : parameter ) = + match x with + | P_Ast(x) -> x + | _ -> raise (Z3native.Exception "parameter is not an ast") + + let get_func_decl ( x : parameter ) = + match x with + | P_Fdl(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a func_decl") + + let get_rational ( x : parameter ) = + match x with + | P_Rat(x) -> x + | _ -> raise (Z3native.Exception "parameter is not a rational string") + end + + let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = + create_ndr ctx name domain range + + let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = + mk_func_decl ctx (Symbol.mk_string ctx name) domain range + + let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = + create_pdr ctx prefix domain range + + let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + create_ndr ctx name [] range + + let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = + create_ndr ctx (Symbol.mk_string ctx name) [] range + + let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = + create_pdr ctx prefix [] range + + + let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + if (gnc a) != (gnc b) then + false + else + (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) + + let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) + + let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) + + let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) + + let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) + + let get_domain ( x : func_decl ) = + let n = (get_domain_size x) in + let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in + mk_list f n + + let get_range ( x : func_decl ) = + sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) + + let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) + + let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) + + let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) + + let get_parameters ( x : func_decl ) = + let n = (get_num_parameters x) in + let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with + | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) + | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) + | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) + | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) + | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) + | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) + | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) + ) in + mk_list f n + + let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args +end + + +and Params : +sig + type params = z3_native_object + module ParamDescrs : + sig + type param_descrs + val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs + val validate : param_descrs -> params -> unit + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + val get_names : param_descrs -> Symbol.symbol list + val get_size : param_descrs -> int + val to_string : param_descrs -> string + end + val add_bool : params -> Symbol.symbol -> bool -> unit + val add_int : params -> Symbol.symbol -> int -> unit + val add_double : params -> Symbol.symbol -> float -> unit + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + val add_s_bool : params -> string -> bool -> unit + val add_s_int : params -> string -> int -> unit + val add_s_double : params -> string -> float -> unit + val add_s_symbol : params -> string -> Symbol.symbol -> unit + val mk_params : context -> params + val to_string : params -> string +end = struct + type params = z3_native_object + + module ParamDescrs = + struct + type param_descrs = z3_native_object + + let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let res : param_descrs = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.param_descrs_inc_ref ; + dec_ref = Z3native.param_descrs_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let validate ( x : param_descrs ) ( p : params ) = + Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) + + let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = + (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) + + let get_names ( x : param_descrs ) = + let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in + let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) + let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = + Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = + Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value + + let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = + Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) + + let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = + add_bool x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_int ( x : params) ( name : string ) ( value : int ) = + add_int x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_double ( x : params ) ( name : string ) ( value : float ) = + add_double x (Symbol.mk_string (z3obj_gc x) name) value + + let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = + add_symbol x (Symbol.mk_string (z3obj_gc x) name) value + + let mk_params ( ctx : context ) = + let res : params = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.params_inc_ref ; + dec_ref = Z3native.params_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; + (z3obj_create res) ; + res + + let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) +end + +(** General expressions (terms) *) +and Expr : +sig + type expr = Expr of AST.ast + val expr_of_ptr : context -> Z3native.ptr -> expr + val gc : expr -> context + val gnc : expr -> Z3native.ptr + val gno : expr -> Z3native.ptr + val expr_lton : expr list -> Z3native.ptr array + val ast_of_expr : expr -> AST.ast + val expr_of_ast : AST.ast -> expr + val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr + val simplify : expr -> Params.params option -> expr + val get_simplify_help : context -> string + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + val get_func_decl : expr -> FuncDecl.func_decl + val get_bool_value : expr -> Z3enums.lbool + val get_num_args : expr -> int + val get_args : expr -> expr list + val update : expr -> expr list -> expr + val substitute : expr -> expr list -> expr list -> expr + val substitute_one : expr -> expr -> expr -> expr + val substitute_vars : expr -> expr list -> expr + val translate : expr -> context -> expr + val to_string : expr -> string + val is_numeral : expr -> bool + val is_well_sorted : expr -> bool + val get_sort : expr -> Sort.sort + val is_bool : expr -> bool + val is_const : expr -> bool + val is_true : expr -> bool + val is_false : expr -> bool + val is_eq : expr -> bool + val is_distinct : expr -> bool + val is_ite : expr -> bool + val is_and : expr -> bool + val is_or : expr -> bool + val is_iff : expr -> bool + val is_xor : expr -> bool + val is_not : expr -> bool + val is_implies : expr -> bool + val is_label : expr -> bool + val is_label_lit : expr -> bool + val is_oeq : expr -> bool + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + val mk_const_s : context -> string -> Sort.sort -> expr + val mk_const_f : context -> FuncDecl.func_decl -> expr + val mk_fresh_const : context -> string -> Sort.sort -> expr + val mk_app : context -> FuncDecl.func_decl -> expr list -> expr + val mk_numeral_string : context -> string -> Sort.sort -> expr + val mk_numeral_int : context -> int -> Sort.sort -> expr +end = struct + type expr = Expr of AST.ast + + let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) + let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) + let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) + + let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> + if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then + Expr(z3_native_object_of_ast_ptr ctx no) + else + let s = Z3native.get_sort (context_gno ctx) no in + let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in + if (Z3native.is_algebraic_number (context_gno ctx) no) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + if (Z3native.is_numeral_ast (context_gno ctx) no) then + if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + Expr(z3_native_object_of_ast_ptr ctx no) + else + raise (Z3native.Exception "Unsupported numeral object") + else + Expr(z3_native_object_of_ast_ptr ctx no) + + let expr_of_ast a = + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Expr(a) + + let ast_of_expr e = match e with Expr(a) -> a + + let expr_lton ( a : expr list ) = + let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) + + let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> + match f with FuncDecl.FuncDecl(fa) -> + let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in + expr_of_ptr ctx o + + let simplify ( x : expr ) ( p : Params.params option ) = match p with + | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (Expr.gnc x) (Expr.gno x)) + | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (Expr.gnc x) (Expr.gno x) (z3obj_gno pp)) + + let get_simplify_help ( ctx : context ) = + Z3native.simplify_get_help (context_gno ctx) + + let get_simplify_parameter_descrs ( ctx : context ) = + Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (Expr.gnc x) (Expr.gno x)) + + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (Expr.gnc x) (Expr.gno x)) + + let get_num_args ( x : expr ) = Z3native.get_app_num_args (Expr.gnc x) (Expr.gno x) + + let get_args ( x : expr ) = let n = (get_num_args x) in + let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (Expr.gnc x) (Expr.gno x) i) in + mk_list f n + + let update ( x : expr ) ( args : expr list ) = + if (List.length args <> (get_num_args x)) then + raise (Z3native.Exception "Number of arguments does not match") + else + expr_of_ptr (Expr.gc x) (Z3native.update_term (Expr.gnc x) (Expr.gno x) (List.length args) (expr_lton args)) + + let substitute ( x : expr ) from to_ = + if (List.length from) <> (List.length to_) then + raise (Z3native.Exception "Argument sizes do not match") + else + expr_of_ptr (Expr.gc x) (Z3native.substitute (Expr.gnc x) (Expr.gno x) (List.length from) (expr_lton from) (expr_lton to_)) + + let substitute_one ( x : expr ) from to_ = + substitute ( x : expr ) [ from ] [ to_ ] + + let substitute_vars ( x : expr ) to_ = + expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (Expr.gnc x) (Expr.gno x) (List.length to_) (expr_lton to_)) + + let translate ( x : expr ) to_ctx = + if (Expr.gc x) == to_ctx then + x + else + expr_of_ptr to_ctx (Z3native.translate (Expr.gnc x) (Expr.gno x) (context_gno to_ctx)) + + let to_string ( x : expr ) = Z3native.ast_to_string (Expr.gnc x) (Expr.gno x) + + let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) + + let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (Expr.gnc x) (Expr.gno x) + + let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)) + + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (Expr.gnc x) + (Z3native.mk_bool_sort (Expr.gnc x)) + (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) + + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (get_num_args x) == 0 && + (FuncDecl.get_domain_size (get_func_decl x)) == 0 + + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) + let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) + + let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = + mk_const ctx (Symbol.mk_string ctx name) range + + let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] + + let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = + expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) + + let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args + + let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) + + let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) +end + +open FuncDecl +open Expr + +module Boolean = +struct + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + + let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let a = (AST.ast_of_ptr ctx no) in + BoolExpr(Expr.Expr(a)) + + let bool_expr_of_expr e = + match e with Expr.Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolExpr(e) + + let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + BoolSort(sort_of_ptr ctx no) + + let sort_of_bool_sort s = match s with BoolSort(x) -> x + + let bool_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BoolSort(s) + + let expr_of_bool_expr e = match e with BoolExpr(x) -> x + + let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) + let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) + let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) + + let mk_sort ( ctx : context ) = + BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = + let s = (match (mk_sort ctx) with BoolSort(q) -> q) in + BoolExpr(Expr.mk_const ctx name s) + + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) + + let mk_true ( ctx : context ) = + bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) + + let mk_false ( ctx : context ) = + bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) + + let mk_val ( ctx : context ) ( value : bool ) = + if value then mk_true ctx else mk_false ctx + + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + let mk_distinct ( ctx : context ) ( args : expr list ) = + bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_not ( ctx : context ) ( a : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) + + let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) + + let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) + + let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) + + let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = + bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) + + let mk_and ( ctx : context ) ( args : bool_expr list ) = + let f x = (Expr.gno (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) + + let mk_or ( ctx : context ) ( args : bool_expr list ) = + let f x = (Expr.gno (expr_of_bool_expr x)) in + bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) +end + + +module Quantifier = +struct + type quantifier = Quantifier of expr + + let expr_of_quantifier e = match e with Quantifier(x) -> x + + let quantifier_of_expr e = + match e with Expr.Expr(a) -> + let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.QUANTIFIER_AST) then + raise (Z3native.Exception "Invalid coercion") + else + Quantifier(e) + + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) + let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) + let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) + + module Pattern = + struct + type pattern = Pattern of ast + + let ast_of_pattern e = match e with Pattern(x) -> x + + let pattern_of_ast a = + (* CMW: Unchecked ok? *) + Pattern(a) + + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) + let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) + let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) + + let get_num_terms ( x : pattern ) = + Z3native.get_pattern_num_terms (gnc x) (gno x) + + let get_terms ( x : pattern ) = + let n = (get_num_terms x) in + let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in + mk_list f n + + let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) + end + + let get_index ( x : expr ) = + if not (AST.is_var (match x with Expr.Expr(a) -> a)) then + raise (Z3native.Exception "Term is not a bound variable.") + else + Z3native.get_index_value (Expr.gnc x) (Expr.gno x) + + let is_universal ( x : quantifier ) = + Z3native.is_quantifier_forall (gnc x) (gno x) + + let is_existential ( x : quantifier ) = not (is_universal x) + + let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) + + let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) + + let get_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in + mk_list f n + + let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) + + let get_no_patterns ( x : quantifier ) = + let n = (get_num_patterns x) in + let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in + mk_list f n + + let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) + + let get_bound_variable_names ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in + mk_list f n + + let get_bound_variable_sorts ( x : quantifier ) = + let n = (get_num_bound x) in + let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in + mk_list f n + + let get_body ( x : quantifier ) = + Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) + + let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = + expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) + + let mk_pattern ( ctx : context ) ( terms : expr list ) = + if (List.length terms) == 0 then + raise (Z3native.Exception "Cannot create a pattern from zero terms") + else + Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) + + let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + + let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (Expr.gno body))) + + let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (List.length sorts) != (List.length names) then + raise (Z3native.Exception "Number of sorts does not match number of names") + else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (List.length sorts) (sort_lton sorts) + (Symbol.symbol_lton names) + (Expr.gno body))) + + let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (Expr.gno body))) + else + Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false + (match weight with | None -> 1 | Some(x) -> x) + (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) + (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) + (List.length bound_constants) (expr_lton bound_constants) + (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) + (List.length nopatterns) (expr_lton nopatterns) + (Expr.gno body))) + + let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (universal) then + (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + else + (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) + + let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = + if (universal) then + mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + else + mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id +end + + +module Array_ = +struct + type array_sort = ArraySort of sort + type array_expr = ArrayExpr of expr + + let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let e = (expr_of_ptr ctx no) in + ArrayExpr(e) + + let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + ArraySort(s) + + let sort_of_array_sort s = match s with ArraySort(x) -> x + + let array_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArraySort(s) + + let array_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.ARRAY_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArrayExpr(e) + + let expr_of_array_expr e = match e with ArrayExpr(x) -> x + + let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) + + let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) + let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) + let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) + + let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = + array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) + + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_array ( x : expr ) = + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) + + let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) + let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) + + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = + ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) + + let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = + mk_const ctx (Symbol.mk_string ctx name) domain range + + let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = + array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) + + let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) + + let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = + array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) + + let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = + let m x = (Expr.gno (expr_of_array_expr x)) in + array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) + + let mk_term_array ( ctx : context ) ( arg : array_expr ) = + array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) +end + + +module Set = +struct + type set_sort = SetSort of sort + + let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + SetSort(s) + + let sort_of_set_sort s = match s with SetSort(x) -> x + + let mk_sort ( ctx : context ) ( ty : sort ) = + set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) + + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + + + let mk_empty ( ctx : context ) ( domain : sort ) = + (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) + + let mk_full ( ctx : context ) ( domain : sort ) = + expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) + + let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) + + let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = + expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) + + let mk_union ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_intersection ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) + + let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + + let mk_complement ( ctx : context ) ( arg : expr ) = + expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) + + let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = + expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) + + let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = + expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) + +end + + +module FiniteDomain = +struct + type finite_domain_sort = FiniteDomainSort of sort + + let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x + + let finite_domain_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + FiniteDomainSort(s) + + let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in + FiniteDomainSort(s) + + let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_sort ctx (Symbol.mk_string ctx name) size + + + let is_finite_domain ( x : expr ) = + let nc = (Expr.gnc x) in + (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) + + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + + let get_size ( x : finite_domain_sort ) = + let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in + if r then v + else raise (Z3native.Exception "Conversion failed.") +end + + +module Relation = +struct + type relation_sort = RelationSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + RelationSort(s) + + let sort_of_relation_sort s = match s with RelationSort(x) -> x + + let relation_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RelationSort(s) + + let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) + let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) + let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) + + + let is_relation ( x : expr ) = + let nc = (Expr.gnc x) in + ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && + (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) + + let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + + let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) + + let get_column_sorts ( x : relation_sort ) = + let n = get_arity x in + let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in + mk_list f n + +end + + +module Datatype = +struct + type datatype_sort = DatatypeSort of sort + type datatype_expr = DatatypeExpr of expr + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + DatatypeSort(s) + + let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x + + let datatype_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeSort(s) + + let datatype_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.DATATYPE_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + DatatypeExpr(e) + + let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x + + let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) + + module Constructor = + struct + type constructor = z3_native_object + + let _sizes = Hashtbl.create 0 + + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let n = (List.length field_names) in + if n != (List.length sorts) then + raise (Z3native.Exception "Number of field names does not match number of sorts") + else + if n != (List.length sort_refs) then + raise (Z3native.Exception "Number of field names does not match number of sort refs") + else + let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) + (Symbol.gno recognizer) + n + (Symbol.symbol_lton field_names) + (sort_lton sorts) + (Array.of_list sort_refs)) in + let no : constructor = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + (z3obj_sno no ctx ptr) ; + (z3obj_create no) ; + let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f no ; + Hashtbl.add _sizes no n ; + no + + let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x + + let get_constructor_decl ( x : constructor ) = + let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + func_decl_of_ptr (z3obj_gc x) a + + let get_tester_decl ( x : constructor ) = + let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + func_decl_of_ptr (z3obj_gc x) b + + let get_accessor_decls ( x : constructor ) = + let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in + let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in + mk_list f (Array.length c) + + end + + module ConstructorList = + struct + type constructor_list = z3_native_object + + let create ( ctx : context ) ( c : Constructor.constructor list ) = + let res : constructor_list = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = z3obj_nil_ref ; + dec_ref = z3obj_nil_ref} in + let f x =(z3obj_gno x) in + (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; + (z3obj_create res) ; + let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in + Gc.finalise f res; + res + end + + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + Constructor.create ctx name recognizer field_names sorts sort_refs + + + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = + let f x = (z3obj_gno x) in + let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in + sort_of_ptr ctx x + + let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = + mk_sort ctx (Symbol.mk_string ctx name) constructors + + let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = + let n = (List.length names) in + let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in + let cla = (Array.of_list (List.map f c)) in + let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in + let g i = (sort_of_ptr ctx (Array.get r i)) in + mk_list g (Array.length r) + + let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = + mk_sorts ctx + ( + let f e = (Symbol.mk_string ctx e) in + List.map f names + ) + c + + let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) + + let get_constructors ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + mk_list f n + + let get_recognizers ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in + mk_list f n + + let get_accessors ( x : datatype_sort ) = + let n = (get_num_constructors x) in + let f i = ( + let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in + let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in + let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in + mk_list g ds + ) in + mk_list f n +end + + +module Enumeration = +struct + type enum_sort = EnumSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = + let s = (sort_of_ptr ctx no) in + let res = EnumSort(s) in + res + + let sort_of_enum_sort s = match s with EnumSort(x) -> x + + let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = + let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in + sort_of_ptr ctx a (list_of_array b) (list_of_array c) + + let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = + mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) + + let get_const_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in + mk_list f n + + let get_tester_decls ( x : enum_sort ) = + let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in + let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in + mk_list f n + +end + + +module List_ = +struct + type list_sort = ListSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + let res = ListSort(s) in + res + + let sort_of_list_sort s = match s with ListSort(x) -> x + + let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = + let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in + sort_of_ptr ctx r a b c d e f + + let mk_list_s ( ctx : context ) (name : string) elem_sort = + mk_sort ctx (Symbol.mk_string ctx name) elem_sort + + let get_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) + + let get_is_nil_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) + + let get_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) + + let get_is_cons_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) + + let get_head_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) + + let get_tail_decl ( x : list_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) + + let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] +end + + +module Tuple = +struct + type tuple_sort = TupleSort of sort + + let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let s = (sort_of_ptr ctx no) in + TupleSort(s) + + let sort_of_tuple_sort s = match s with TupleSort(x) -> x + + let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) + + let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = + let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in + sort_of_ptr ctx r + + let get_mk_decl ( x : tuple_sort ) = + func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) + + let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) + + let get_field_decls ( x : tuple_sort ) = + let n = get_num_fields x in + let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in + mk_list f n +end + + +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> arith_sort + val expr_of_arith_expr : arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> arith_expr + + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end + + val is_int : Expr.expr -> bool + val is_arithmetic_numeral : Expr.expr -> bool + val is_le : Expr.expr -> bool + val is_ge : Expr.expr -> bool + val is_lt : Expr.expr -> bool + val is_gt : Expr.expr -> bool + val is_add : Expr.expr -> bool + val is_sub : Expr.expr -> bool + val is_uminus : Expr.expr -> bool + val is_mul : Expr.expr -> bool + val is_div : Expr.expr -> bool + val is_idiv : Expr.expr -> bool + val is_remainder : Expr.expr -> bool + val is_modulus : Expr.expr -> bool + val is_inttoreal : Expr.expr -> bool + val is_real_to_int : Expr.expr -> bool + val is_real_is_int : Expr.expr -> bool + val is_real : Expr.expr -> bool + val is_int_numeral : Expr.expr -> bool + val is_rat_num : Expr.expr -> bool + val is_algebraic_number : Expr.expr -> bool + val mk_add : context -> arith_expr list -> arith_expr + val mk_mul : context -> arith_expr list -> arith_expr + val mk_sub : context -> arith_expr list -> arith_expr + val mk_unary_minus : context -> arith_expr -> arith_expr + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end = struct + type arith_sort = ArithSort of sort + type arith_expr = ArithExpr of expr + + let arith_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithExpr(e) + + let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_expr_of_expr (expr_of_ptr ctx no) + + let sort_of_arith_sort s = match s with ArithSort(x) -> x + let expr_of_arith_expr e = match e with ArithExpr(x) -> x + + let arith_sort_of_sort s = match s with Sort(a) -> + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in + if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + ArithSort(s) + + let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + arith_sort_of_sort (sort_of_ptr ctx no) + + let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) + let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) + let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) + let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) + let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) + let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) + + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val int_expr_of_ptr : context -> Z3native.ptr -> int_expr + val int_num_of_ptr : context -> Z3native.ptr -> int_num + + val arith_sort_of_int_sort : Integer.int_sort -> arith_sort + val int_sort_of_arith_sort : arith_sort -> int_sort + val arith_expr_of_int_expr : int_expr -> arith_expr + val int_expr_of_int_num : int_num -> int_expr + val int_expr_of_arith_expr : arith_expr -> int_expr + val int_num_of_int_expr : int_expr -> int_num + + val mk_sort : context -> int_sort + val get_int : int_num -> int + val to_string : int_num -> string + val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_int_const_s : context -> string -> int_expr + val mk_mod : context -> int_expr -> int_expr -> int_expr + val mk_rem : context -> int_expr -> int_expr -> int_expr + val mk_int_numeral_s : context -> string -> int_num + val mk_int_numeral_i : context -> int -> int_num + val mk_int2real : context -> int_expr -> Real.real_expr + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end = struct + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + let int_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntExpr(e) + + let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let int_num_of_int_expr e = + match e with IntExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + IntNum(e) + + let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_num_of_int_expr (int_expr_of_ptr ctx no) + + let arith_sort_of_int_sort s = match s with IntSort(x) -> x + let arith_expr_of_int_expr e = match e with IntExpr(x) -> x + let int_expr_of_int_num e = match e with IntNum(x) -> x + + let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + IntSort(s) + + let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) + + let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) + let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) + let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) + let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) + let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) + let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) + let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) + let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) + let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) + + let mk_sort ( ctx : context ) = + int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) + + let get_int ( x : int_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + + let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) + + let mk_int_const_s ( ctx : context ) ( name : string ) = + mk_int_const ctx (Symbol.mk_string ctx name) + + let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) + + let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = + int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) + + let mk_int_numeral_s ( ctx : context ) ( v : string ) = + int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_int_numeral_i ( ctx : context ) ( v : int ) = + int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_int2real ( ctx : context ) ( t : int_expr ) = + Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) + + let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = + BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) + end + + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val real_expr_of_ptr : context -> Z3native.ptr -> real_expr + val rat_num_of_ptr : context -> Z3native.ptr -> rat_num + + val arith_sort_of_real_sort : real_sort -> arith_sort + val real_sort_of_arith_sort : arith_sort -> real_sort + val arith_expr_of_real_expr : real_expr -> arith_expr + val real_expr_of_rat_num : rat_num -> real_expr + val real_expr_of_arith_expr : arith_expr -> real_expr + val rat_num_of_real_expr : real_expr -> rat_num + + val mk_sort : context -> real_sort + val get_numerator : rat_num -> Integer.int_num + val get_denominator : rat_num -> Integer.int_num + val to_decimal_string : rat_num -> int -> string + val to_string : rat_num -> string + val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_real_const_s : context -> string -> real_expr + val mk_numeral_nd : context -> int -> int -> rat_num + val mk_numeral_s : context -> string -> rat_num + val mk_numeral_i : context -> int -> rat_num + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + val mk_real2int : context -> real_expr -> Integer.int_expr + end = struct + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + let arith_sort_of_real_sort s = match s with RealSort(x) -> x + let arith_expr_of_real_expr e = match e with RealExpr(x) -> x + let real_expr_of_rat_num e = match e with RatNum(x) -> x + + let real_expr_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealExpr(e) + + let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) + + let rat_num_of_real_expr e = + match e with RealExpr(ArithExpr(Expr(a))) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + RatNum(e) + + let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + rat_num_of_real_expr (real_expr_of_ptr ctx no) + + let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + RealSort(s) + + let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) + + let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) + let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) + let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) + let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) + let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) + let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) + let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) + let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) + let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) + + + let mk_sort ( ctx : context ) = + real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) + + let get_numerator ( x : rat_num ) = + Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) + + let get_denominator ( x : rat_num ) = + Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) + + let to_decimal_string ( x : rat_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + + let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) + + let mk_real_const_s ( ctx : context ) ( name : string ) = + mk_real_const ctx (Symbol.mk_string ctx name) + + let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + if (den == 0) then + raise (Z3native.Exception "Denominator is zero") + else + rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) + + let mk_numeral_s ( ctx : context ) ( v : string ) = + rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_numeral_i ( ctx : context ) ( v : int ) = + rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) + + let mk_is_integer ( ctx : context ) ( t : real_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) + + let mk_real2int ( ctx : context ) ( t : real_expr ) = + Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) + end + + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : algebraic_num -> arith_expr + val algebraic_num_of_arith_expr : arith_expr -> algebraic_num + + val to_upper : algebraic_num -> int -> Real.rat_num + val to_lower : algebraic_num -> int -> Real.rat_num + val to_decimal_string : algebraic_num -> int -> string + val to_string : algebraic_num -> string + end = struct + type algebraic_num = AlgebraicNum of arith_expr + + let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x + + let algebraic_num_of_arith_expr e = + match e with ArithExpr(Expr(a)) -> + if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + AlgebraicNum(e) + + let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) + + let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) + let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) + let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) + + + let to_upper ( x : algebraic_num ) ( precision : int ) = + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) + + let to_lower ( x : algebraic_num ) precision = + Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) + + let to_decimal_string ( x : algebraic_num ) ( precision : int ) = + Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision + + let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + end + + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + + let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) + + let mk_add ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_mul ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_sub ( ctx : context ) ( t : arith_expr list ) = + let f x = (Expr.gno (expr_of_arith_expr x)) in + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + + let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) + + let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) + + let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) + + let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) + + let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) + + let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) + + let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) +end + + +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + val mk_sort : context -> int -> bitvec_sort + val is_bv : Expr.expr -> bool + val is_bv_numeral : Expr.expr -> bool + val is_bv_bit1 : Expr.expr -> bool + val is_bv_bit0 : Expr.expr -> bool + val is_bv_uminus : Expr.expr -> bool + val is_bv_add : Expr.expr -> bool + val is_bv_sub : Expr.expr -> bool + val is_bv_mul : Expr.expr -> bool + val is_bv_sdiv : Expr.expr -> bool + val is_bv_udiv : Expr.expr -> bool + val is_bv_SRem : Expr.expr -> bool + val is_bv_urem : Expr.expr -> bool + val is_bv_smod : Expr.expr -> bool + val is_bv_sdiv0 : Expr.expr -> bool + val is_bv_udiv0 : Expr.expr -> bool + val is_bv_srem0 : Expr.expr -> bool + val is_bv_urem0 : Expr.expr -> bool + val is_bv_smod0 : Expr.expr -> bool + val is_bv_ule : Expr.expr -> bool + val is_bv_sle : Expr.expr -> bool + val is_bv_uge : Expr.expr -> bool + val is_bv_sge : Expr.expr -> bool + val is_bv_ult : Expr.expr -> bool + val is_bv_slt : Expr.expr -> bool + val is_bv_ugt : Expr.expr -> bool + val is_bv_sgt : Expr.expr -> bool + val is_bv_and : Expr.expr -> bool + val is_bv_or : Expr.expr -> bool + val is_bv_not : Expr.expr -> bool + val is_bv_xor : Expr.expr -> bool + val is_bv_nand : Expr.expr -> bool + val is_bv_nor : Expr.expr -> bool + val is_bv_xnor : Expr.expr -> bool + val is_bv_concat : Expr.expr -> bool + val is_bv_signextension : Expr.expr -> bool + val is_bv_zeroextension : Expr.expr -> bool + val is_bv_extract : Expr.expr -> bool + val is_bv_repeat : Expr.expr -> bool + val is_bv_reduceor : Expr.expr -> bool + val is_bv_reduceand : Expr.expr -> bool + val is_bv_comp : Expr.expr -> bool + val is_bv_shiftleft : Expr.expr -> bool + val is_bv_shiftrightlogical : Expr.expr -> bool + val is_bv_shiftrightarithmetic : Expr.expr -> bool + val is_bv_rotateleft : Expr.expr -> bool + val is_bv_rotateright : Expr.expr -> bool + val is_bv_rotateleftextended : Expr.expr -> bool + val is_bv_rotaterightextended : Expr.expr -> bool + val is_int_to_bv : Expr.expr -> bool + val is_bv_to_int : Expr.expr -> bool + val is_bv_carry : Expr.expr -> bool + val is_bv_xor3 : Expr.expr -> bool + val get_size : bitvec_sort -> int + val get_int : bitvec_num -> int + val to_string : bitvec_num -> string + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + val mk_const_s : context -> string -> int -> bitvec_expr + val mk_not : context -> bitvec_expr -> Expr.expr + val mk_redand : context -> bitvec_expr -> Expr.expr + val mk_redor : context -> bitvec_expr -> Expr.expr + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_neg : context -> bitvec_expr -> bitvec_expr + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + val mk_numeral : context -> string -> int -> bitvec_num +end = struct + type bitvec_sort = BitVecSort of sort + type bitvec_expr = BitVecExpr of expr + type bitvec_num = BitVecNum of bitvec_expr + + let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x + + let bitvec_sort_of_sort s = match s with Sort(a) -> + if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecSort(s) + + let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_sort_of_sort (sort_of_ptr ctx no) + + let bitvec_expr_of_expr e = + match e with Expr(a) -> + let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in + let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in + if (q != Z3enums.BV_SORT) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecExpr(e) + + let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_expr_of_expr (expr_of_ptr ctx no) + + let bitvec_num_of_bitvec_expr e = + match e with BitVecExpr(Expr(a)) -> + if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then + raise (Z3native.Exception "Invalid coercion") + else + BitVecNum(e) + + let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) + + let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x + let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x + + + let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) + let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) + let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) + let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) + let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) + let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) + let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) + let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) + let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) + + + let mk_sort ( ctx : context ) size = + bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) + let is_bv ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) + let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) + let get_int ( x : bitvec_num ) = + let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in + if r then v + else raise (Z3native.Exception "Conversion failed.") + let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = + BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) + let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = + mk_const ctx (Symbol.mk_string ctx name) size + let mk_not ( ctx : context ) ( t : bitvec_expr ) = + expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) + let mk_redand ( ctx : context ) ( t : bitvec_expr) = + expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) + let mk_redor ( ctx : context ) ( t : bitvec_expr) = + expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) + let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) + let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) + let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) + let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) + let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) + let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) + let mk_neg ( ctx : context ) ( t : bitvec_expr) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) + let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) + let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) + let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) + let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) + let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) + let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) + let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) + let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) + let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) + let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) + let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) + let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) + let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) + let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) + let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) + let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) + let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) + let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) + let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) + let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) + let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) + let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) + let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) + let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) + let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) + let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) + let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) + let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) + let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = + Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) + let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) + let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) + let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) + let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) + let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) + let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = + bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) +end + + +module Proof = +struct + let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) +end + + +module Goal = +struct + type goal = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : goal = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.goal_inc_ref ; + dec_ref = Z3native.goal_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_precision ( x : goal ) = + goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) + + let is_precise ( x : goal ) = + (get_precision x) == GOAL_PRECISE + + let is_underapproximation ( x : goal ) = + (get_precision x) == GOAL_UNDER + + let is_overapproximation ( x : goal ) = + (get_precision x) == GOAL_OVER + + let is_garbage ( x : goal ) = + (get_precision x) == GOAL_UNDER_OVER + + let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = + let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in + ignore (List.map f constraints) ; + () + + let is_inconsistent ( x : goal ) = + Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) + + let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) + + let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) + + let get_formulas ( x : goal ) = + let n = get_size x in + let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in + mk_list f n + + let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) + + let is_decided_sat ( x : goal ) = + Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) + + let is_decided_unsat ( x : goal ) = + Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) + + let translate ( x : goal ) ( to_ctx : context ) = + create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + + let simplify ( x : goal ) ( p : Params.params option ) = + let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in + Z3native.tactic_inc_ref (z3obj_gnc x) tn ; + let arn = match p with + | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) + | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) + in + Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; + let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in + let res = if sg == 0 then + raise (Z3native.Exception "No subgoals") + else + Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in + Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; + Z3native.tactic_dec_ref (z3obj_gnc x) tn ; + create (z3obj_gc x) res + + let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = + create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) + + let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Model = +struct + type model = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : model = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.model_inc_ref ; + dec_ref = Z3native.model_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module FuncInterp = + struct + type func_interp = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_interp = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_interp_inc_ref ; + dec_ref = Z3native.func_interp_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module FuncEntry = + struct + type func_entry = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : func_entry = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.func_entry_inc_ref ; + dec_ref = Z3native.func_entry_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_value ( x : func_entry ) = + expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) + + let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) + + let get_args ( x : func_entry ) = + let n = (get_num_args x) in + let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let to_string ( x : func_entry ) = + let a = (get_args x) in + let f c p = (p ^ (Expr.to_string c) ^ ", ") in + "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") + end + + let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) + + let get_entries ( x : func_interp ) = + let n = (get_num_entries x) in + let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) + + let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) + + let to_string ( x : func_interp ) = + let f c p = ( + let n = (FuncEntry.get_num_args c) in + p ^ + let g c p = (p ^ (Expr.to_string c) ^ ", ") in + (if n > 1 then "[" else "") ^ + (List.fold_right + g + (FuncEntry.get_args c) + ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) + ) in + List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") + end + + let get_const_interp ( x : model ) ( f : func_decl ) = + if (FuncDecl.get_arity f) != 0 || + (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then + raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") + else + let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in + if (Z3native.is_null np) then + None + else + Some (expr_of_ptr (z3obj_gc x) np) + + let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) + + + let rec get_func_interp ( x : model ) ( f : func_decl ) = + let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in + if (FuncDecl.get_arity f) == 0 then + let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in + if (Z3native.is_null n) then + None + else + match sk with + | ARRAY_SORT -> + if not (Z3native.is_as_array (z3obj_gnc x) n) then + raise (Z3native.Exception "Argument was not an array constant") + else + let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in + get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) + | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); + else + let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in + if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) + + (** The number of constants that have an interpretation in the model. *) + let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) + + let get_const_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) + + let get_func_decls ( x : model ) = + let n = (get_num_consts x) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_decls ( x : model ) = + let n_funcs = (get_num_funcs x) in + let n_consts = (get_num_consts x ) in + let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in + let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in + (mk_list f n_funcs) @ (mk_list g n_consts) + + exception ModelEvaluationFailedException of string + + let eval ( x : model ) ( t : expr ) ( completion : bool ) = + let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in + if not r then + raise (ModelEvaluationFailedException "evaluation failed") + else + expr_of_ptr (z3obj_gc x) v + + let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = + eval x t completion + + let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) + + let get_sorts ( x : model ) = + let n = (get_num_sorts x) in + let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in + mk_list f n + + let sort_universe ( x : model ) ( s : sort ) = + let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n = (AST.ASTVector.get_size n_univ) in + let f i = (AST.ASTVector.get n_univ i) in + mk_list f n + + let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Probe = +struct + type probe = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : probe = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.probe_inc_ref ; + dec_ref = Z3native.probe_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + + let apply ( x : probe ) ( g : Goal.goal ) = + Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) + + let get_num_probes ( ctx : context ) = + Z3native.get_num_probes (context_gno ctx) + + let get_probe_names ( ctx : context ) = + let n = (get_num_probes ctx) in + let f i = (Z3native.get_probe_name (context_gno ctx) i) in + mk_list f n + + let get_probe_description ( ctx : context ) ( name : string ) = + Z3native.probe_get_descr (context_gno ctx) name + + let mk_probe ( ctx : context ) ( name : string ) = + (create ctx (Z3native.mk_probe (context_gno ctx) name)) + + let const ( ctx : context ) ( v : float ) = + (create ctx (Z3native.probe_const (context_gno ctx) v)) + + let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = + (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) + + let not_ ( ctx : context ) ( p : probe ) = + (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) +end + + +module Tactic = +struct + type tactic = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : tactic = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.tactic_inc_ref ; + dec_ref = Z3native.tactic_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + module ApplyResult = + struct + type apply_result = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : apply_result = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.apply_result_inc_ref ; + dec_ref = Z3native.apply_result_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let get_num_subgoals ( x : apply_result ) = + Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) + + let get_subgoals ( x : apply_result ) = + let n = (get_num_subgoals x) in + let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get_subgoal ( x : apply_result ) ( i : int ) = + Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) + + let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = + Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) + + let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) + end + + let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) + + let get_param_descrs ( x : tactic ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = + match p with + | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) + | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) + + let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) + + let get_tactic_names ( ctx : context ) = + let n = (get_num_tactics ctx ) in + let f i = (Z3native.get_tactic_name (context_gno ctx) i) in + mk_list f n + + let get_tactic_description ( ctx : context ) ( name : string ) = + Z3native.tactic_get_descr (context_gno ctx) name + + let mk_tactic ( ctx : context ) ( name : string ) = + create ctx (Z3native.mk_tactic (context_gno ctx) name) + + let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = + let f p c = (match p with + | None -> (Some (z3obj_gno c)) + | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in + match (List.fold_left f None ts) with + | None -> + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + | Some(x) -> + let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in + create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) + + let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + + let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = + create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) + + let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = + create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) + + let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) + + let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = + create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) + + let skip ( ctx : context ) = + create ctx (Z3native.tactic_skip (context_gno ctx)) + + let fail ( ctx : context ) = + create ctx (Z3native.tactic_fail (context_gno ctx)) + + let fail_if ( ctx : context ) ( p : Probe.probe ) = + create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) + + let fail_if_not_decided ( ctx : context ) = + create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) + + let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) + + let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = + using_params ctx t p + + let par_or ( ctx : context ) ( t : tactic list ) = + let f e = (z3obj_gno e) in + create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) + + let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = + create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) + + let interrupt ( ctx : context ) = + Z3native.interrupt (context_gno ctx) +end + + +module Solver = +struct + type solver = z3_native_object + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : solver = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.solver_inc_ref ; + dec_ref = Z3native.solver_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + let string_of_status ( s : status) = match s with + | UNSATISFIABLE -> "unsatisfiable" + | SATISFIABLE -> "satisfiable" + | _ -> "unknown" + + module Statistics = + struct + type statistics = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : statistics = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.stats_inc_ref ; + dec_ref = Z3native.stats_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + + + module Entry = + struct + type statistics_entry = { + mutable m_key : string; + mutable m_is_int : bool ; + mutable m_is_float : bool ; + mutable m_int : int ; + mutable m_float : float } + + let create_si k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = true ; + m_is_float = false ; + m_int = v ; + m_float = 0.0 + } in + res + + let create_sd k v = + let res : statistics_entry = { + m_key = k ; + m_is_int = false ; + m_is_float = true ; + m_int = 0 ; + m_float = v + } in + res + + + let get_key (x : statistics_entry) = x.m_key + let get_int (x : statistics_entry) = x.m_int + let get_float (x : statistics_entry) = x.m_float + let is_int (x : statistics_entry) = x.m_is_int + let is_float (x : statistics_entry) = x.m_is_float + let to_string_value (x : statistics_entry) = + if (is_int x) then + string_of_int (get_int x) + else if (is_float x) then + string_of_float (get_float x) + else + raise (Z3native.Exception "Unknown statistical entry type") + let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) + end + + let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) + + let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) + + let get_entries ( x : statistics ) = + let n = (get_size x ) in + let f i = ( + let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in + if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then + (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) + else + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + ) in + mk_list f n + + let get_keys ( x : statistics ) = + let n = (get_size x) in + let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in + mk_list f n + + let get ( x : statistics ) ( key : string ) = + let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in + List.fold_left f None (get_entries x) + end + + let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) + + let set_parameters ( x : solver ) ( p : Params.params )= + Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) + + let get_param_descrs ( x : solver ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) + + let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) + + let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n + + let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) + + let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = + let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + ignore (List.map f constraints) + + let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = + if ((List.length cs) != (List.length ps)) then + raise (Z3native.Exception "Argument size mismatch") + else + let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in + ignore (List.iter2 f cs ps) + + let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = + Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) + + let get_num_assertions ( x : solver ) = + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + (AST.ASTVector.get_size a) + + let get_assertions ( x : solver ) = + let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size a) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in + mk_list f n + + let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = + let r = + if ((List.length assumptions) == 0) then + lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) + else + let f x = (Expr.gno (Boolean.expr_of_bool_expr x)) in + lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) + in + match r with + | L_TRUE -> SATISFIABLE + | L_FALSE -> UNSATISFIABLE + | _ -> UNKNOWN + + let get_model ( x : solver ) = + let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in + if (Z3native.is_null q) then + None + else + Some (Model.create (z3obj_gc x) q) + + let get_proof ( x : solver ) = + let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let get_unsat_core ( x : solver ) = + let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let n = (AST.ASTVector.get_size cn) in + let f i = (AST.ASTVector.get cn i) in + mk_list f n + + let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) + + let get_statistics ( x : solver ) = + (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) + + let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = + match logic with + | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) + | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) + + let mk_solver_s ( ctx : context ) ( logic : string ) = + mk_solver ctx (Some (Symbol.mk_string ctx logic)) + + let mk_simple_solver ( ctx : context ) = + (create ctx (Z3native.mk_simple_solver (context_gno ctx))) + + let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = + (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) + + let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) +end + + +module Fixedpoint = +struct + type fixedpoint = z3_native_object + + let create ( ctx : context ) = + let res : fixedpoint = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.fixedpoint_inc_ref ; + dec_ref = Z3native.fixedpoint_dec_ref } in + (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; + (z3obj_create res) ; + res + + + let get_help ( x : fixedpoint ) = + Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) + + let set_params ( x : fixedpoint ) ( p : Params.params )= + Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) + + let get_param_descrs ( x : fixedpoint ) = + Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) + + let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = + let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in + ignore (List.map f constraints) ; + () + + let register_relation ( x : fixedpoint ) ( f : func_decl ) = + Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) + + let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = + match name with + | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null + | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) + + let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = + Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) + + let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = + match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + let query_r ( x : fixedpoint ) ( relations : func_decl list ) = + let f x = ptr_of_ast (ast_of_func_decl x) in + match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with + | L_TRUE -> Solver.SATISFIABLE + | L_FALSE -> Solver.UNSATISFIABLE + | _ -> Solver.UNKNOWN + + let push ( x : fixedpoint ) = + Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) + + let pop ( x : fixedpoint ) = + Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) + + let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = + Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) + + let get_answer ( x : fixedpoint ) = + let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let get_reason_unknown ( x : fixedpoint ) = + Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) + + let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = + Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) + + let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = + let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in + if (Z3native.is_null q) then + None + else + Some (expr_of_ptr (z3obj_gc x) q) + + let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = + Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) + + let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] + + let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = + Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) + + let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = + let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in + Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) + + let get_rules ( x : fixedpoint ) = + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + mk_list f n + + let get_assertions ( x : fixedpoint ) = + let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let n = (AST.ASTVector.get_size v) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in + mk_list f n + + let mk_fixedpoint ( ctx : context ) = create ctx +end + +module Options = +struct + + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value (context_gno ctx) id value + + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in + if not r then + None + else + Some v + + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) + + let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages enabled +end + + +module SMT = +struct + let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = + Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes + (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) + (Boolean.gno formula) + + let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) + + let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Z3native.parse_smtlib_file (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) + + let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) + + let get_smtlib_formulas ( ctx : context ) = + let n = (get_num_smtlib_formulas ctx ) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in + mk_list f n + + let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) + + let get_smtlib_assumptions ( ctx : context ) = + let n = (get_num_smtlib_assumptions ctx ) in + let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in + mk_list f n + + let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) + + let get_smtlib_decls ( ctx : context ) = + let n = (get_num_smtlib_decls ctx) in + let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in + mk_list f n + + let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) + + let get_smtlib_sorts ( ctx : context ) = + let n = (get_num_smtlib_sorts ctx) in + let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in + mk_list f n + + let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) + + let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = + let csn = (List.length sort_names) in + let cs = (List.length sorts) in + let cdn = (List.length decl_names) in + let cd = (List.length decls) in + if (csn != cs || cdn != cd) then + raise (Z3native.Exception "Argument size mismatch") + else + Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name + cs + (Symbol.symbol_lton sort_names) + (sort_lton sorts) + cd + (Symbol.symbol_lton decl_names) + (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) +end + + +let set_global_param ( id : string ) ( value : string ) = + (Z3native.global_param_set id value) + +let get_global_param ( id : string ) = + let (r, v) = (Z3native.global_param_get id) in + if not r then + None + else + Some v + +let global_param_reset_all = + Z3native.global_param_reset_all diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli new file mode 100644 index 000000000..8b6681e11 --- /dev/null +++ b/src/api/ml/z3_rich.mli @@ -0,0 +1,3072 @@ +(** + The Z3 ML/Ocaml Interface. + + Copyright (C) 2012 Microsoft Corporation + @author CM Wintersteiger (cwinter) 2012-12-17 + + NOTE: This is the *rich* version of the interface, using more + type information directly in the type system. Coercion functions + are provided to tran coerce on type into another where applicable. +*) + +(** Context objects. + + Most interactions with Z3 are interpreted in some context; many users will only + require one such object, but power users may require more than one. To start using + Z3, do + + + let ctx = (mk_context []) in + (...) + + + where a list of pairs of strings may be passed to set options on + the context, e.g., like so: + + + let cfg = [("model", "true"); ("...", "...")] in + let ctx = (mk_context cfg) in + (...) + +*) +type context + +(** Create a context object *) +val mk_context : (string * string) list -> context + + +(** Interaction logging for Z3 + Note that this is a global, static log and if multiple Context + objects are created, it logs the interaction with all of them. *) +module Log : +sig + (** Open an interaction log file. + @return True if opening the log file succeeds, false otherwise. *) + (* CMW: "open" seems to be a reserved keyword? *) + val open_ : string -> bool + + (** Closes the interaction log. *) + val close : unit + + (** Appends a user-provided string to the interaction log. *) + val append : string -> unit +end + +(** Version information *) +module Version : +sig + (** The major version. *) + val major : int + + (** The minor version. *) + val minor : int + + (** The build version. *) + val build : int + + (** The revision. *) + val revision : int + + (** A string representation of the version information. *) + val to_string : string +end + +(** Symbols are used to name several term and type constructors *) +module Symbol : +sig + (** Numbered Symbols *) + type int_symbol + + (** Named Symbols *) + type string_symbol + + (** Symbols *) + type symbol = S_Int of int_symbol | S_Str of string_symbol + + (** The kind of the symbol (int or string) *) + val kind : symbol -> Z3enums.symbol_kind + + (** Indicates whether the symbol is of Int kind *) + val is_int_symbol : symbol -> bool + + (** Indicates whether the symbol is of string kind. *) + val is_string_symbol : symbol -> bool + + (** The int value of the symbol. *) + val get_int : int_symbol -> int + + (** The string value of the symbol. *) + val get_string : string_symbol -> string + + (** A string representation of the symbol. *) + val to_string : symbol -> string + + (** Creates a new symbol using an integer. + + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. *) + val mk_int : context -> int -> symbol + + (** Creates a new symbol using a string. *) + val mk_string : context -> string -> symbol + + (** Create a list of symbols. *) + val mk_ints : context -> int list -> symbol list + + (** Create a list of symbols. *) + val mk_strings : context -> string list -> symbol list +end + +(** The abstract syntax tree (AST) module *) +module AST : +sig + type ast + + (** Vectors of ASTs *) + module ASTVector : + sig + type ast_vector + + (** The size of the vector *) + val get_size : ast_vector -> int + + (** + Retrieves the i-th object in the vector. + @return An AST *) + val get : ast_vector -> int -> ast + + (** Sets the i-th object in the vector. *) + val set : ast_vector -> int -> ast -> unit + + (** Resize the vector to a new size. *) + val resize : ast_vector -> int -> unit + + (** Add an ast to the back of the vector. The size + is increased by 1. *) + val push : ast_vector -> ast -> unit + + (** Translates all ASTs in the vector to another context. + @return A new ASTVector *) + val translate : ast_vector -> context -> ast_vector + + (** Retrieves a string representation of the vector. *) + val to_string : ast_vector -> string + end + + (** Map from AST to AST *) + module ASTMap : + sig + type ast_map + + (** Checks whether the map contains a key. + @return True if the key in the map, false otherwise. *) + val contains : ast_map -> ast -> bool + + (** Finds the value associated with the key. + This function signs an error when the key is not a key in the map. *) + val find : ast_map -> ast -> ast + + (** Stores or replaces a new key/value pair in the map. *) + val insert : ast_map -> ast -> ast -> unit + + (** Erases the key from the map.*) + val erase : ast_map -> ast -> unit + + (** Removes all keys from the map. *) + val reset : ast_map -> unit + + (** The size of the map *) + val get_size : ast_map -> int + + (** The keys stored in the map. *) + val get_keys : ast_map -> ast list + + (** Retrieves a string representation of the map.*) + val to_string : ast_map -> string + end + + (** The AST's hash code. + @return A hash code *) + val get_hash_code : ast -> int + + (** A unique identifier for the AST (unique among all ASTs). *) + val get_id : ast -> int + + (** The kind of the AST. *) + val get_ast_kind : ast -> Z3enums.ast_kind + + (** Indicates whether the AST is an Expr *) + val is_expr : ast -> bool + + (** Indicates whether the AST is a bound variable*) + val is_var : ast -> bool + + (** Indicates whether the AST is a Quantifier *) + val is_quantifier : ast -> bool + + (** Indicates whether the AST is a Sort *) + val is_sort : ast -> bool + + (** Indicates whether the AST is a func_decl *) + val is_func_decl : ast -> bool + + (** A string representation of the AST. *) + val to_string : ast -> string + + (** A string representation of the AST in s-expression notation. *) + val to_sexpr : ast -> string + + (** Comparison operator. + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) + val ( = ) : ast -> ast -> bool + + (** Object Comparison. + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + val compare : ast -> ast -> int + + (** Operator < *) + val ( < ) : ast -> ast -> int + + (** Translates (copies) the AST to another context. + @return A copy of the AST which is associated with the other context. *) + val translate : ast -> context -> ast + + (** Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., + Z3native.inc_ref). *) + val wrap_ast : context -> Z3native.z3_ast -> ast + + (** Unwraps an AST. + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + Z3native.inc_ref). + {!wrap_ast} *) + val unwrap_ast : ast -> Z3native.ptr +end + +(** The Sort module implements type information for ASTs *) +module Sort : +sig + (** Sorts *) + type sort = Sort of AST.ast + + (** Uninterpreted Sorts *) + type uninterpreted_sort = UninterpretedSort of sort + + val ast_of_sort : sort -> AST.ast + val sort_of_uninterpreted_sort : uninterpreted_sort -> sort + val uninterpreted_sort_of_sort : sort -> uninterpreted_sort + + (** Comparison operator. + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) + val ( = ) : sort -> sort -> bool + + (** Returns a unique identifier for the sort. *) + val get_id : sort -> int + + (** The kind of the sort. *) + val get_sort_kind : sort -> Z3enums.sort_kind + + (** The name of the sort *) + val get_name : sort -> Symbol.symbol + + (** A string representation of the sort. *) + val to_string : sort -> string + + (** Create a new uninterpreted sort. *) + val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort + + (** Create a new uninterpreted sort. *) + val mk_uninterpreted_s : context -> string -> uninterpreted_sort +end + +(** Function declarations *) +module rec FuncDecl : +sig + type func_decl = FuncDecl of AST.ast + + val ast_of_func_decl : FuncDecl.func_decl -> AST.ast + + (** Parameters of Func_Decls *) + module Parameter : + sig + (** Parameters of func_decls *) + type parameter = + P_Int of int + | P_Dbl of float + | P_Sym of Symbol.symbol + | P_Srt of Sort.sort + | P_Ast of AST.ast + | P_Fdl of func_decl + | P_Rat of string + + (** The kind of the parameter. *) + val get_kind : parameter -> Z3enums.parameter_kind + + (** The int value of the parameter.*) + val get_int : parameter -> int + + (** The double value of the parameter.*) + val get_float : parameter -> float + + (** The Symbol.Symbol value of the parameter.*) + val get_symbol : parameter -> Symbol.symbol + + (** The Sort value of the parameter.*) + val get_sort : parameter -> Sort.sort + + (** The AST value of the parameter.*) + val get_ast : parameter -> AST.ast + + (** The FunctionDeclaration value of the parameter.*) + val get_func_decl : parameter -> func_decl + + (** The rational string value of the parameter.*) + val get_rational : parameter -> string + end + + (** Creates a new function declaration. *) + val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl + + (** Creates a new function declaration. *) + val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl + (** Creates a fresh function declaration with a name prefixed with a prefix string. *) + + val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl + + (** Creates a new constant function declaration. *) + val mk_const_decl_s : context -> string -> Sort.sort -> func_decl + + (** Creates a fresh constant function declaration with a name prefixed with a prefix string. + {!mk_func_decl} + {!mk_func_decl} *) + val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl + + (** Comparison operator. + @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) + val ( = ) : func_decl -> func_decl -> bool + + (** A string representations of the function declaration. *) + val to_string : func_decl -> string + + (** Returns a unique identifier for the function declaration. *) + val get_id : func_decl -> int + + (** The arity of the function declaration *) + val get_arity : func_decl -> int + + (** The size of the domain of the function declaration + {!get_arity} *) + val get_domain_size : func_decl -> int + + (** The domain of the function declaration *) + val get_domain : func_decl -> Sort.sort list + + (** The range of the function declaration *) + val get_range : func_decl -> Sort.sort + + (** The kind of the function declaration. *) + val get_decl_kind : func_decl -> Z3enums.decl_kind + + (** The name of the function declaration*) + val get_name : func_decl -> Symbol.symbol + + (** The number of parameters of the function declaration *) + val get_num_parameters : func_decl -> int + + (** The parameters of the function declaration *) + val get_parameters : func_decl -> Parameter.parameter list + + (** Create expression that applies function to arguments. *) + val apply : func_decl -> Expr.expr list -> Expr.expr +end + +(** Parameter sets (of Solvers, Tactics, ...) + + A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) +and Params : +sig + type params + + (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) + module ParamDescrs : + sig + type param_descrs + + (** Validate a set of parameters. *) + val validate : param_descrs -> params -> unit + + (** Retrieve kind of parameter. *) + val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind + + (** Retrieve all names of parameters. *) + val get_names : param_descrs -> Symbol.symbol list + + (** The size of the ParamDescrs. *) + val get_size : param_descrs -> int + + (** Retrieves a string representation of the ParamDescrs. *) + val to_string : param_descrs -> string + end + + (** Adds a parameter setting. *) + val add_bool : params -> Symbol.symbol -> bool -> unit + + (** Adds a parameter setting. *) + val add_int : params -> Symbol.symbol -> int -> unit + + (** Adds a parameter setting. *) + val add_double : params -> Symbol.symbol -> float -> unit + + (** Adds a parameter setting. *) + val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit + + (** Adds a parameter setting. *) + val add_s_bool : params -> string -> bool -> unit + + (** Adds a parameter setting. *) + val add_s_int : params -> string -> int -> unit + + (** Adds a parameter setting. *) + val add_s_double : params -> string -> float -> unit + + (** Adds a parameter setting. *) + val add_s_symbol : params -> string -> Symbol.symbol -> unit + + (** Creates a new parameter set *) + val mk_params : context -> params + + (** A string representation of the parameter set. *) + val to_string : params -> string +end + +(** General Expressions (terms) *) +and Expr : +sig + type expr = Expr of AST.ast + + val ast_of_expr : Expr.expr -> AST.ast + val expr_of_ast : AST.ast -> Expr.expr + + (** Returns a simplified version of the expression. + {!get_simplify_help} *) + val simplify : Expr.expr -> Params.params option -> expr + + (** A string describing all available parameters to Expr.Simplify. *) + val get_simplify_help : context -> string + + (** Retrieves parameter descriptions for simplifier. *) + val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs + + (** The function declaration of the function that is applied in this expression. *) + val get_func_decl : Expr.expr -> FuncDecl.func_decl + + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) + val get_bool_value : Expr.expr -> Z3enums.lbool + + (** The number of arguments of the expression. *) + val get_num_args : Expr.expr -> int + + (** The arguments of the expression. *) + val get_args : Expr.expr -> Expr.expr list + + (** Update the arguments of the expression using an array of expressions. + The number of new arguments should coincide with the current number of arguments. *) + val update : Expr.expr -> Expr.expr list -> expr + + (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + + The result is the new expression. The arrays from and to must have size num_exprs. + For every i smaller than num_exprs, we must have that + sort of from[i] must be equal to sort of to[i]. *) + val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr + + (** Substitute every occurrence of from in the expression with to. + {!substitute} *) + val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr + + (** Substitute the free variables in the expression with the expressions in the expr array + + For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) + val substitute_vars : Expr.expr -> Expr.expr list -> expr + + (** Translates (copies) the term to another context. + @return A copy of the term which is associated with the other context *) + val translate : Expr.expr -> context -> expr + + (** Returns a string representation of the expression. *) + val to_string : Expr.expr -> string + + (** Indicates whether the term is a numeral *) + val is_numeral : Expr.expr -> bool + + (** Indicates whether the term is well-sorted. + @return True if the term is well-sorted, false otherwise. *) + val is_well_sorted : Expr.expr -> bool + + (** The Sort of the term. *) + val get_sort : Expr.expr -> Sort.sort + + (** Indicates whether the term has Boolean sort. *) + val is_bool : Expr.expr -> bool + + (** Indicates whether the term represents a constant. *) + val is_const : Expr.expr -> bool + + (** Indicates whether the term is the constant true. *) + val is_true : Expr.expr -> bool + + (** Indicates whether the term is the constant false. *) + val is_false : Expr.expr -> bool + + (** Indicates whether the term is an equality predicate. *) + val is_eq : Expr.expr -> bool + + (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) + val is_distinct : Expr.expr -> bool + + (** Indicates whether the term is a ternary if-then-else term *) + val is_ite : Expr.expr -> bool + + (** Indicates whether the term is an n-ary conjunction *) + val is_and : Expr.expr -> bool + + (** Indicates whether the term is an n-ary disjunction *) + val is_or : Expr.expr -> bool + + (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) + val is_iff : Expr.expr -> bool + + (** Indicates whether the term is an exclusive or *) + val is_xor : Expr.expr -> bool + + (** Indicates whether the term is a negation *) + val is_not : Expr.expr -> bool + + (** Indicates whether the term is an implication *) + val is_implies : Expr.expr -> bool + + (** Indicates whether the term is a label (used by the Boogie Verification condition generator). + The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) + val is_label : Expr.expr -> bool + + (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). + A label literal has a set of string parameters. It takes no arguments. + let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) + val is_label_lit : Expr.expr -> bool + + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) + val is_oeq : Expr.expr -> bool + + (** Creates a new constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) + val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) + val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) + val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr + + (** Create a numeral of a given sort. + @return A Term with the goven value and sort *) + val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) + val mk_numeral_int : context -> int -> Sort.sort -> expr +end + +(** Boolean expressions *) +module Boolean : +sig + type bool_sort = BoolSort of Sort.sort + type bool_expr = BoolExpr of Expr.expr + + val expr_of_bool_expr : bool_expr -> Expr.expr + val sort_of_bool_sort : bool_sort -> Sort.sort + val bool_sort_of_sort : Sort.sort -> bool_sort + val bool_expr_of_expr : Expr.expr -> bool_expr + + (** Create a Boolean sort *) + val mk_sort : context -> bool_sort + + (** Create a Boolean constant. *) + val mk_const : context -> Symbol.symbol -> bool_expr + + (** Create a Boolean constant. *) + val mk_const_s : context -> string -> bool_expr + + (** The true Term. *) + val mk_true : context -> bool_expr + + (** The false Term. *) + val mk_false : context -> bool_expr + + (** Creates a Boolean value. *) + val mk_val : context -> bool -> bool_expr + + (** Creates the equality between two expr's. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr + + (** Creates a distinct term. *) + val mk_distinct : context -> Expr.expr list -> bool_expr + + (** Mk an expression representing not(a). *) + val mk_not : context -> bool_expr -> bool_expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 iff t2. *) + val mk_iff : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 -> t2. *) + val mk_implies : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing t1 xor t2. *) + val mk_xor : context -> bool_expr -> bool_expr -> bool_expr + + (** Create an expression representing the AND of args *) + val mk_and : context -> bool_expr list -> bool_expr + + (** Create an expression representing the OR of args *) + val mk_or : context -> bool_expr list -> bool_expr +end + +(** Quantifier expressions *) +module Quantifier : +sig + type quantifier = Quantifier of Expr.expr + + val expr_of_quantifier : quantifier -> Expr.expr + val quantifier_of_expr : Expr.expr -> quantifier + + (** Quantifier patterns + + Patterns comprise a list of terms. The list should be + non-empty. If the list comprises of more than one term, it is + also called a multi-pattern. *) + module Pattern : + sig + type pattern = Pattern of AST.ast + + val ast_of_pattern : pattern -> AST.ast + val pattern_of_ast : AST.ast -> pattern + + (** The number of terms in the pattern. *) + val get_num_terms : pattern -> int + + (** The terms in the pattern. *) + val get_terms : pattern -> Expr.expr list + + (** A string representation of the pattern. *) + val to_string : pattern -> string + end + + + (** The de-Burijn index of a bound variable. + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) + val get_index : Expr.expr -> int + + (** Indicates whether the quantifier is universal. *) + val is_universal : quantifier -> bool + + (** Indicates whether the quantifier is existential. *) + val is_existential : quantifier -> bool + + (** The weight of the quantifier. *) + val get_weight : quantifier -> int + + (** The number of patterns. *) + val get_num_patterns : quantifier -> int + + (** The patterns. *) + val get_patterns : quantifier -> Pattern.pattern list + + (** The number of no-patterns. *) + val get_num_no_patterns : quantifier -> int + + (** The no-patterns. *) + val get_no_patterns : quantifier -> Pattern.pattern list + + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) + val get_bound_variable_names : quantifier -> Symbol.symbol list + + (** The sorts of the bound variables. *) + val get_bound_variable_sorts : quantifier -> Sort.sort list + + (** The body of the quantifier. *) + val get_body : quantifier -> Boolean.bool_expr + + (** Creates a new bound variable. *) + val mk_bound : context -> int -> Sort.sort -> Expr.expr + + (** Create a quantifier pattern. *) + val mk_pattern : context -> Expr.expr list -> Pattern.pattern + + (** Create a universal Quantifier. *) + val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a universal Quantifier. *) + val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create an existential Quantifier. *) + val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** Create a Quantifier. *) + val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier +end + +(** Functions to manipulate Array expressions *) +module Array_ : +sig + type array_sort = ArraySort of Sort.sort + type array_expr = ArrayExpr of Expr.expr + + val sort_of_array_sort : array_sort -> Sort.sort + val array_sort_of_sort : Sort.sort -> array_sort + val expr_of_array_expr : array_expr -> Expr.expr + + val array_expr_of_expr : Expr.expr -> array_expr + + (** Create a new array sort. *) + val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort + + (** Indicates whether the term is an array store. + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) + val is_store : Expr.expr -> bool + + (** Indicates whether the term is an array select. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a constant array. + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) + val is_constant_array : Expr.expr -> bool + + (** Indicates whether the term is a default array. + For example default(const(v)) = v. The function is unary. *) + val is_default_array : Expr.expr -> bool + + (** Indicates whether the term is an array map. + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) + val is_array_map : Expr.expr -> bool + + (** Indicates whether the term is an as-array term. + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) + val is_as_array : Expr.expr -> bool + + (** Indicates whether the term is of an array sort. *) + val is_array : Expr.expr -> bool + + (** The domain of the array sort. *) + val get_domain : array_sort -> Sort.sort + + (** The range of the array sort. *) + val get_range : array_sort -> Sort.sort + + (** Create an array constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr + + (** Create an array constant. *) + val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr + + (** Array read. + + The argument a is the array and i is the index + of the array that gets read. + + The node a must have an array sort [domain -> range], + and i must have the sort domain. + The sort of the result is range. + {!Array_.mk_sort} + {!mk_store} *) + val mk_select : context -> array_expr -> Expr.expr -> array_expr + + (** Array update. + + The node a must have an array sort [domain -> range], + i must have sort domain, + v must have sort range. The sort of the result is [domain -> range]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to a + (with respect to select) + on all indices except for i, where it maps to v + (and the select of a with + respect to i may be a different value). + {!Array_.mk_sort} + {!mk_select} *) + val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr + + (** Create a constant array. + + The resulting term is an array, such that a selecton an arbitrary index + produces the value v. + {!Array_.mk_sort} + {!mk_select} *) + val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr + + (** Maps f on the argument arrays. + + Eeach element of args must be of an array sort [domain_i -> range_i]. + The function declaration f must have type range_1 .. range_n -> range. + v must have sort range. The sort of the result is [domain_i -> range]. + {!Array_.mk_sort} + {!mk_select} + {!mk_store} *) + val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr + + (** Access the array default value. + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) + val mk_term_array : context -> array_expr -> array_expr +end + +(** Functions to manipulate Set expressions *) +module Set : +sig + type set_sort = SetSort of Sort.sort + + val sort_of_set_sort : set_sort -> Sort.sort + + (** Create a set type. *) + val mk_sort : context -> Sort.sort -> set_sort + + (** Indicates whether the term is set union *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is set intersection *) + val is_intersect : Expr.expr -> bool + + (** Indicates whether the term is set difference *) + val is_difference : Expr.expr -> bool + + (** Indicates whether the term is set complement *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is set subset *) + val is_subset : Expr.expr -> bool + + (** Create an empty set. *) + val mk_empty : context -> Sort.sort -> Expr.expr + + (** Create the full set. *) + val mk_full : context -> Sort.sort -> Expr.expr + + (** Add an element to the set. *) + val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Remove an element from a set. *) + val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the union of a list of sets. *) + val mk_union : context -> Expr.expr list -> Expr.expr + + (** Take the intersection of a list of sets. *) + val mk_intersection : context -> Expr.expr list -> Expr.expr + + (** Take the difference between two sets. *) + val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Take the complement of a set. *) + val mk_complement : context -> Expr.expr -> Expr.expr + + (** Check for set membership. *) + val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Check for subsetness of sets. *) + val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr +end + +(** Functions to manipulate Finite Domain expressions *) +module FiniteDomain : +sig + type finite_domain_sort = FiniteDomainSort of Sort.sort + + val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort + val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort + + (** Create a new finite domain sort. *) + val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort + + (** Create a new finite domain sort. *) + val mk_sort_s : context -> string -> int -> finite_domain_sort + + (** Indicates whether the term is of an array sort. *) + val is_finite_domain : Expr.expr -> bool + + (** Indicates whether the term is a less than predicate over a finite domain. *) + val is_lt : Expr.expr -> bool + + (** The size of the finite domain sort. *) + val get_size : finite_domain_sort -> int +end + + +(** Functions to manipulate Relation expressions *) +module Relation : +sig + type relation_sort = RelationSort of Sort.sort + + val sort_of_relation_sort : relation_sort -> Sort.sort + val relation_sort_of_sort : Sort.sort -> relation_sort + + (** Indicates whether the term is of a relation sort. *) + val is_relation : Expr.expr -> bool + + (** Indicates whether the term is an relation store + + Insert a record into a relation. + The function takes n+1 arguments, where the first argument is the relation and the remaining n elements + correspond to the n columns of the relation. *) + val is_store : Expr.expr -> bool + + (** Indicates whether the term is an empty relation *) + val is_empty : Expr.expr -> bool + + (** Indicates whether the term is a test for the emptiness of a relation *) + val is_is_empty : Expr.expr -> bool + + (** Indicates whether the term is a relational join *) + val is_join : Expr.expr -> bool + + (** Indicates whether the term is the union or convex hull of two relations. + The function takes two arguments. *) + val is_union : Expr.expr -> bool + + (** Indicates whether the term is the widening of two relations + The function takes two arguments. *) + val is_widen : Expr.expr -> bool + + (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). + The function takes one argument. *) + val is_project : Expr.expr -> bool + + (** Indicates whether the term is a relation filter + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) + val is_filter : Expr.expr -> bool + + (** Indicates whether the term is an intersection of a relation with the negation of another. + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) + val is_negation_filter : Expr.expr -> bool + + (** Indicates whether the term is the renaming of a column in a relation + + The function takes one argument. + The parameters contain the renaming as a cycle. *) + val is_rename : Expr.expr -> bool + + (** Indicates whether the term is the complement of a relation *) + val is_complement : Expr.expr -> bool + + (** Indicates whether the term is a relational select + + Check if a record is an element of the relation. + The function takes n+1 arguments, where the first argument is a relation, + and the remaining n arguments correspond to a record. *) + val is_select : Expr.expr -> bool + + (** Indicates whether the term is a relational clone (copy) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) + val is_clone : Expr.expr -> bool + + (** The arity of the relation sort. *) + val get_arity : relation_sort -> int + + (** The sorts of the columns of the relation sort. *) + val get_column_sorts : relation_sort -> relation_sort list +end + +(** Functions to manipulate Datatype expressions *) +module Datatype : +sig + type datatype_sort = DatatypeSort of Sort.sort + type datatype_expr = DatatypeExpr of Expr.expr + + val sort_of_datatype_sort : datatype_sort -> Sort.sort + val datatype_sort_of_sort : Sort.sort -> datatype_sort + val expr_of_datatype_expr : datatype_expr -> Expr.expr + val datatype_expr_of_expr : Expr.expr -> datatype_expr + + (** Datatype Constructors *) + module Constructor : + sig + type constructor + + (** The number of fields of the constructor. *) + val get_num_fields : constructor -> int + + (** The function declaration of the constructor. *) + val get_constructor_decl : constructor -> FuncDecl.func_decl + + (** The function declaration of the tester. *) + val get_tester_decl : constructor -> FuncDecl.func_decl + + (** The function declarations of the accessors *) + val get_accessor_decls : constructor -> FuncDecl.func_decl list + end + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a datatype constructor. + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + + (** Create a new datatype sort. *) + val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort + + (** Create a new datatype sort. *) + val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort + + (** Create mutually recursive datatypes. *) + val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list + + (** Create mutually recursive data-types. *) + val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list + + + (** The number of constructors of the datatype sort. *) + val get_num_constructors : datatype_sort -> int + + (** The constructors. *) + val get_constructors : datatype_sort -> FuncDecl.func_decl list + + (** The recognizers. *) + val get_recognizers : datatype_sort -> FuncDecl.func_decl list + + (** The constructor accessors. *) + val get_accessors : datatype_sort -> FuncDecl.func_decl list list +end + +(** Functions to manipulate Enumeration expressions *) +module Enumeration : +sig + type enum_sort = EnumSort of Sort.sort + + val sort_of_enum_sort : enum_sort -> Sort.sort + + (** Create a new enumeration sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort + + (** Create a new enumeration sort. *) + val mk_sort_s : context -> string -> string list -> enum_sort + + (** The function declarations of the constants in the enumeration. *) + val get_const_decls : enum_sort -> FuncDecl.func_decl list + + (** The test predicates for the constants in the enumeration. *) + val get_tester_decls : enum_sort -> FuncDecl.func_decl list +end + +(** Functions to manipulate List expressions *) +module List_ : +sig + type list_sort = ListSort of Sort.sort + + val sort_of_list_sort : list_sort -> Sort.sort + + (** Create a new list sort. *) + val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort + + (** Create a new list sort. *) + val mk_list_s : context -> string -> Sort.sort -> list_sort + + (** The declaration of the nil function of this list sort. *) + val get_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isNil function of this list sort. *) + val get_is_nil_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the cons function of this list sort. *) + val get_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the isCons function of this list sort. *) + val get_is_cons_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the head function of this list sort. *) + val get_head_decl : list_sort -> FuncDecl.func_decl + + (** The declaration of the tail function of this list sort. *) + val get_tail_decl : list_sort -> FuncDecl.func_decl + + (** The empty list. *) + val nil : list_sort -> Expr.expr +end + +(** Functions to manipulate Tuple expressions *) +module Tuple : +sig + type tuple_sort = TupleSort of Sort.sort + + val sort_of_tuple_sort : tuple_sort -> Sort.sort + + (** Create a new tuple sort. *) + val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort + + (** The constructor function of the tuple. *) + val get_mk_decl : tuple_sort -> FuncDecl.func_decl + + (** The number of fields in the tuple. *) + val get_num_fields : tuple_sort -> int + + (** The field declarations. *) + val get_field_decls : tuple_sort -> FuncDecl.func_decl list +end + +(** Functions to manipulate arithmetic expressions *) +module rec Arithmetic : +sig + type arith_sort = ArithSort of Sort.sort + type arith_expr = ArithExpr of Expr.expr + + val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort + val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort + val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr + val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr + + (** Integer Arithmetic *) + module rec Integer : + sig + type int_sort = IntSort of arith_sort + type int_expr = IntExpr of arith_expr + type int_num = IntNum of int_expr + + val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort + val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort + val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr + val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr + val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr + val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num + + (** Create a new integer sort. *) + val mk_sort : context -> int_sort + + (** Retrieve the int value. *) + val get_int : int_num -> int + + (** Returns a string representation of the numeral. *) + val to_string : int_num -> string + + (** Creates an integer constant. *) + val mk_int_const : context -> Symbol.symbol -> int_expr + + (** Creates an integer constant. *) + val mk_int_const_s : context -> string -> int_expr + + (** Create an expression representing t1 mod t2. + The arguments must have int type. *) + val mk_mod : context -> int_expr -> int_expr -> int_expr + + (** Create an expression representing t1 rem t2. + The arguments must have int type. *) + val mk_rem : context -> int_expr -> int_expr -> int_expr + + (** Create an integer numeral. *) + val mk_int_numeral_s : context -> string -> int_num + + (** Create an integer numeral. + @return A Term with the given value and sort Integer *) + val mk_int_numeral_i : context -> int -> int_num + + (** Coerce an integer to a real. + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term k and + and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + The argument must be of integer sort. *) + val mk_int2real : context -> int_expr -> Real.real_expr + + (** Create an n-bit bit-vector from an integer argument. + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) + val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr + end + + (** Real Arithmetic *) + and Real : + sig + type real_sort = RealSort of arith_sort + type real_expr = RealExpr of arith_expr + type rat_num = RatNum of real_expr + + val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort + val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort + val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr + val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr + val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr + val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num + + (** Create a real sort. *) + val mk_sort : context -> real_sort + + (** The numerator of a rational numeral. *) + val get_numerator : rat_num -> Integer.int_num + + (** The denominator of a rational numeral. *) + val get_denominator : rat_num -> Integer.int_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as indicated by the int argument.*) + val to_decimal_string : rat_num -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : rat_num -> string + + (** Creates a real constant. *) + val mk_real_const : context -> Symbol.symbol -> real_expr + + (** Creates a real constant. *) + val mk_real_const_s : context -> string -> real_expr + + (** Create a real numeral from a fraction. + @return A Term with rational value and sort Real + {!mk_numeral_s} *) + val mk_numeral_nd : context -> int -> int -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_s : context -> string -> rat_num + + (** Create a real numeral. + @return A Term with the given value and sort Real *) + val mk_numeral_i : context -> int -> rat_num + + (** Creates an expression that checks whether a real number is an integer. *) + val mk_is_integer : context -> real_expr -> Boolean.bool_expr + + (** Coerce a real to an integer. + + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) + val mk_real2int : context -> real_expr -> Integer.int_expr + end + + (** Algebraic Numbers *) + and AlgebraicNumber : + sig + type algebraic_num = AlgebraicNum of arith_expr + + val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr + val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num + + (** Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_upper : algebraic_num -> int -> Real.rat_num + + (** Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_lower : algebraic_num -> int -> Real.rat_num + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as the int argument provided.*) + val to_decimal_string : algebraic_num -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : algebraic_num -> string + end + + (** Indicates whether the term is of integer sort. *) + val is_int : Expr.expr -> bool + + (** Indicates whether the term is an arithmetic numeral. *) + val is_arithmetic_numeral : Expr.expr -> bool + + (** Indicates whether the term is a less-than-or-equal *) + val is_le : Expr.expr -> bool + + (** Indicates whether the term is a greater-than-or-equal *) + val is_ge : Expr.expr -> bool + + (** Indicates whether the term is a less-than *) + val is_lt : Expr.expr -> bool + + (** Indicates whether the term is a greater-than *) + val is_gt : Expr.expr -> bool + + (** Indicates whether the term is addition (binary) *) + val is_add : Expr.expr -> bool + + (** Indicates whether the term is subtraction (binary) *) + val is_sub : Expr.expr -> bool + + (** Indicates whether the term is a unary minus *) + val is_uminus : Expr.expr -> bool + + (** Indicates whether the term is multiplication (binary) *) + val is_mul : Expr.expr -> bool + + (** Indicates whether the term is division (binary) *) + val is_div : Expr.expr -> bool + + (** Indicates whether the term is integer division (binary) *) + val is_idiv : Expr.expr -> bool + + (** Indicates whether the term is remainder (binary) *) + val is_remainder : Expr.expr -> bool + + (** Indicates whether the term is modulus (binary) *) + val is_modulus : Expr.expr -> bool + + (** Indicates whether the term is a coercion of integer to real (unary) *) + val is_inttoreal : Expr.expr -> bool + + (** Indicates whether the term is a coercion of real to integer (unary) *) + val is_real_to_int : Expr.expr -> bool + + (** Indicates whether the term is a check that tests whether a real is integral (unary) *) + val is_real_is_int : Expr.expr -> bool + + (** Indicates whether the term is of sort real. *) + val is_real : Expr.expr -> bool + + (** Indicates whether the term is an integer numeral. *) + val is_int_numeral : Expr.expr -> bool + + (** Indicates whether the term is a real numeral. *) + val is_rat_num : Expr.expr -> bool + + (** Indicates whether the term is an algebraic number *) + val is_algebraic_number : Expr.expr -> bool + + (** Create an expression representing t[0] + t[1] + .... *) + val mk_add : context -> arith_expr list -> arith_expr + + (** Create an expression representing t[0] * t[1] * .... *) + val mk_mul : context -> arith_expr list -> arith_expr + + (** Create an expression representing t[0] - t[1] - .... *) + val mk_sub : context -> arith_expr list -> arith_expr + + (** Create an expression representing -t. *) + val mk_unary_minus : context -> arith_expr -> arith_expr + + (** Create an expression representing t1 / t2. *) + val mk_div : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 ^ t2. *) + val mk_power : context -> arith_expr -> arith_expr -> arith_expr + + (** Create an expression representing t1 < t2 *) + val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 <= t2 *) + val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 > t2 *) + val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr + + (** Create an expression representing t1 >= t2 *) + val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr +end + +(** Functions to manipulate bit-vector expressions *) +and BitVector : +sig + type bitvec_sort = BitVecSort of Sort.sort + type bitvec_expr = BitVecExpr of Expr.expr + type bitvec_num = BitVecNum of bitvec_expr + + val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort + val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort + val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr + val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr + val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr + val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num + + (** Create a new bit-vector sort. *) + val mk_sort : context -> int -> bitvec_sort + + (** Indicates whether the terms is of bit-vector sort. *) + val is_bv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector numeral *) + val is_bv_numeral : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value one *) + val is_bv_bit1 : Expr.expr -> bool + + (** Indicates whether the term is a one-bit bit-vector with value zero *) + val is_bv_bit0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unary minus *) + val is_bv_uminus : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector addition (binary) *) + val is_bv_add : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector subtraction (binary) *) + val is_bv_sub : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector multiplication (binary) *) + val is_bv_mul : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division (binary) *) + val is_bv_sdiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division (binary) *) + val is_bv_udiv : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder (binary) *) + val is_bv_SRem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) + val is_bv_urem : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus *) + val is_bv_smod : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed division by zero *) + val is_bv_sdiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned division by zero *) + val is_bv_udiv0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed remainder by zero *) + val is_bv_srem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector unsigned remainder by zero *) + val is_bv_urem0 : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector signed modulus by zero *) + val is_bv_smod0 : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) + val is_bv_ule : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than-or-equal *) + val is_bv_sle : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) + val is_bv_uge : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) + val is_bv_sge : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector less-than *) + val is_bv_ult : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector less-than *) + val is_bv_slt : Expr.expr -> bool + + (** Indicates whether the term is an unsigned bit-vector greater-than *) + val is_bv_ugt : Expr.expr -> bool + + (** Indicates whether the term is a signed bit-vector greater-than *) + val is_bv_sgt : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise AND *) + val is_bv_and : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise OR *) + val is_bv_or : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOT *) + val is_bv_not : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XOR *) + val is_bv_xor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NAND *) + val is_bv_nand : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise NOR *) + val is_bv_nor : Expr.expr -> bool + + (** Indicates whether the term is a bit-wise XNOR *) + val is_bv_xnor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector concatenation (binary) *) + val is_bv_concat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector sign extension *) + val is_bv_signextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector zero extension *) + val is_bv_zeroextension : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector extraction *) + val is_bv_extract : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector repetition *) + val is_bv_repeat : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce OR *) + val is_bv_reduceor : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector reduce AND *) + val is_bv_reduceand : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector comparison *) + val is_bv_comp : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector shift left *) + val is_bv_shiftleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector logical shift right *) + val is_bv_shiftrightlogical : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector arithmetic shift left *) + val is_bv_shiftrightarithmetic : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left *) + val is_bv_rotateleft : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right *) + val is_bv_rotateright : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate left (extended) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotateleftextended : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector rotate right (extended) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) + val is_bv_rotaterightextended : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + + (** Indicates whether the term is a coercion from bit-vector to integer + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_int_to_bv : Expr.expr -> bool + + (** Indicates whether the term is a coercion from integer to bit-vector + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) + val is_bv_to_int : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector carry + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) + val is_bv_carry : Expr.expr -> bool + + (** Indicates whether the term is a bit-vector ternary XOR + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) + val is_bv_xor3 : Expr.expr -> bool + + (** The size of a bit-vector sort. *) + val get_size : bitvec_sort -> int + + (** Retrieve the int value. *) + val get_int : bitvec_num -> int + + (** Returns a string representation of the numeral. *) + val to_string : bitvec_num -> string + + (** Creates a bit-vector constant. *) + val mk_const : context -> Symbol.symbol -> int -> bitvec_expr + + (** Creates a bit-vector constant. *) + val mk_const_s : context -> string -> int -> bitvec_expr + + (** Bitwise negation. + The argument must have a bit-vector sort. *) + val mk_not : context -> bitvec_expr -> Expr.expr + + (** Take conjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redand : context -> bitvec_expr -> Expr.expr + + (** Take disjunction of bits in a vector,vector of length 1. + The argument must have a bit-vector sort. *) + val mk_redor : context -> bitvec_expr -> Expr.expr + + (** Bitwise conjunction. + The arguments must have a bit-vector sort. *) + val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise disjunction. + The arguments must have a bit-vector sort. *) + val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XOR. + The arguments must have a bit-vector sort. *) + val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NAND. + The arguments must have a bit-vector sort. *) + val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise NOR. + The arguments must have a bit-vector sort. *) + val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bitwise XNOR. + The arguments must have a bit-vector sort. *) + val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Standard two's complement unary minus. + The arguments must have a bit-vector sort. *) + val mk_neg : context -> bitvec_expr -> bitvec_expr + + (** Two's complement addition. + The arguments must have the same bit-vector sort. *) + val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement subtraction. + The arguments must have the same bit-vector sort. *) + val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement multiplication. + The arguments must have the same bit-vector sort. *) + val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned division. + + + It is defined as the floor of t1/t2 if \c t2 is + different from zero. If t2 is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) + val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed division. + + It is defined in the following way: + + - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + + - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned remainder. + + It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Signed remainder. + + It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Two's complement signed remainder (sign follows divisor). + + If t2 is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) + val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Unsigned less-than + + The arguments must have the same bit-vector sort. *) + val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than + + The arguments must have the same bit-vector sort. *) + val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed less-than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater than or equal to. + + The arguments must have the same bit-vector sort. *) + val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Unsigned greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Two's complement signed greater-than. + + The arguments must have the same bit-vector sort. *) + val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Bit-vector concatenation. + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size n1+n2, where n1 (n2) + is the size of t1 (t2). *) + val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Bit-vector extraction. + + Extract the bits between two limits from a bitvector of + size m to yield a new bitvector of size n, where + n = high - low + 1. *) + val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector sign extension. + + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size m+i, where \c m is the size of the given bit-vector. *) + val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector zero extension. + + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size m+i, where \c m is the size of the + given bit-vector. *) + val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr + + (** Bit-vector repetition. *) + val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr + + (** Shift left. + + It is equivalent to multiplication by 2^x where \c x is the value of third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling.*) + val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Logical shift right + + It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Arithmetic shift right + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. + + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. + + The arguments must have a bit-vector sort. *) + val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of \c t to the left \c i times. *) + val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of \c t to the right \c i times.*) + val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr + + (** Rotate Left. + Rotate bits of the second argument to the left.*) + val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Rotate Right. + Rotate bits of the second argument to the right. *) + val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr + + (** Create an integer from the bit-vector argument + + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. + So the result is non-negative and in the range [0..2^N-1], where + N are the number of bits in the argument. + If \c is_signed is true, \c t1 is treated as a signed bit-vector. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function.*) + val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr + + (** Create a predicate that checks that the bit-wise addition does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise addition does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise subtraction does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise signed division does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise negation does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not overflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr + + (** Create a predicate that checks that the bit-wise multiplication does not underflow. + + The arguments must be of bit-vector sort. *) + val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr + + (** Create a bit-vector numeral. *) + val mk_numeral : context -> string -> int -> bitvec_num +end + +(** Functions to manipulate proof expressions *) +module Proof : +sig + (** Indicates whether the term is a Proof for the expression 'true'. *) + val is_true : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact asserted by the user. *) + val is_asserted : Expr.expr -> bool + + (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) + val is_goal : Expr.expr -> bool + + (** Indicates whether the term is proof via modus ponens + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) + val is_modus_ponens : Expr.expr -> bool + + (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) + val is_reflexivity : Expr.expr -> bool + + (** Indicates whether the term is proof by symmetricity of a relation + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) + val is_symmetry : Expr.expr -> bool + + (** Indicates whether the term is a proof by transitivity of a relation + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) + val is_transitivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by condensed transitivity of a relation + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) + val is_Transitivity_star : Expr.expr -> bool + + (** Indicates whether the term is a monotonicity proof object. + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) + val is_monotonicity : Expr.expr -> bool + + (** Indicates whether the term is a quant-intro proof + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) + val is_quant_intro : Expr.expr -> bool + + (** Indicates whether the term is a distributivity proof object. + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) + val is_distributivity : Expr.expr -> bool + + (** Indicates whether the term is a proof by elimination of AND + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) + val is_and_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by eliminiation of not-or + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) + val is_or_elimination : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) + val is_rewrite : Expr.expr -> bool + + (** Indicates whether the term is a proof by rewriting + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) + val is_rewrite_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) + val is_pull_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for pulling quantifiers out. + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) + val is_pull_quant_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for pushing quantifiers in. + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) + val is_push_quant : Expr.expr -> bool + + (** Indicates whether the term is a proof for elimination of unused variables. + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) + val is_elim_unused_vars : Expr.expr -> bool + + (** Indicates whether the term is a proof for destructive equality resolution + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) + val is_der : Expr.expr -> bool + + (** Indicates whether the term is a proof for quantifier instantiation + + A proof of (or (not (forall (x) (P x))) (P a)) *) + val is_quant_inst : Expr.expr -> bool + + (** Indicates whether the term is a hypthesis marker. + Mark a hypothesis in a natural deduction style proof. *) + val is_hypothesis : Expr.expr -> bool + + (** Indicates whether the term is a proof by lemma + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) + val is_lemma : Expr.expr -> bool + + (** Indicates whether the term is a proof by unit resolution + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) + val is_unit_resolution : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-true + + T1: p + [iff-true T1]: (iff p true) *) + val is_iff_true : Expr.expr -> bool + + (** Indicates whether the term is a proof by iff-false + + T1: (not p) + [iff-false T1]: (iff p false) *) + val is_iff_false : Expr.expr -> bool + + (** Indicates whether the term is a proof by commutativity + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) + val is_commutativity : Expr.expr -> bool + + (** Indicates whether the term is a proof for Tseitin-like axioms + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) + val is_def_axiom : Expr.expr -> bool + + (** Indicates whether the term is a proof for introduction of a name + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) + val is_def_intro : Expr.expr -> bool + + (** Indicates whether the term is a proof for application of a definition + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) + val is_apply_def : Expr.expr -> bool + + (** Indicates whether the term is a proof iff-oeq + + T1: (iff p q) + [iff~ T1]: (~ p q) *) + val is_iff_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for a positive NNF step + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) + val is_nnf_pos : Expr.expr -> bool + + (** Indicates whether the term is a proof for a negative NNF step + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) + val is_nnf_neg : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_nnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + val is_cnf_star : Expr.expr -> bool + + (** Indicates whether the term is a proof for a Skolemization step + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) + val is_skolemize : Expr.expr -> bool + + (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) + val is_modus_ponens_oeq : Expr.expr -> bool + + (** Indicates whether the term is a proof for theory lemma + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) + val is_theory_lemma : Expr.expr -> bool +end + +(** Goals + + A goal (aka problem). A goal is essentially a + of formulas, that can be solved and/or transformed using + tactics and solvers. *) +module Goal : +sig + type goal + + (** The precision of the goal. + + Goals can be transformed using over and under approximations. + An under approximation is applied when the objective is to find a model for a given goal. + An over approximation is applied when the objective is to find a proof for a given goal. *) + val get_precision : goal -> Z3enums.goal_prec + + (** Indicates whether the goal is precise. *) + val is_precise : goal -> bool + + (** Indicates whether the goal is an under-approximation. *) + val is_underapproximation : goal -> bool + + (** Indicates whether the goal is an over-approximation. *) + val is_overapproximation : goal -> bool + + (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) + val is_garbage : goal -> bool + + (** Adds the constraints to the given goal. *) + val assert_ : goal -> Boolean.bool_expr list -> unit + + (** Indicates whether the goal contains `false'. *) + val is_inconsistent : goal -> bool + + (** The depth of the goal. + This tracks how many transformations were applied to it. *) + val get_depth : goal -> int + + (** Erases all formulas from the given goal. *) + val reset : goal -> unit + + (** The number of formulas in the goal. *) + val get_size : goal -> int + + (** The formulas in the goal. *) + val get_formulas : goal -> Boolean.bool_expr list + + (** The number of formulas, subformulas and terms in the goal. *) + val get_num_exprs : goal -> int + + (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) + val is_decided_sat : goal -> bool + + (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) + val is_decided_unsat : goal -> bool + + (** Translates (copies) the Goal to another context.. *) + val translate : goal -> context -> goal + + (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) + val simplify : goal -> Params.params option -> goal + + (** Creates a new Goal. + + Note that the Context must have been created with proof generation support if + the fourth argument is set to true here. *) + val mk_goal : context -> bool -> bool -> bool -> goal + + (** A string representation of the Goal. *) + val to_string : goal -> string +end + +(** Models + + A Model contains interpretations (assignments) of constants and functions. *) +module Model : +sig + type model + + (** Function interpretations + + A function interpretation is represented as a finite map and an 'else'. + Each entry in the finite map represents the value of a function given a set of arguments. *) + module FuncInterp : + sig + type func_interp + + (** Function interpretations entries + + An Entry object represents an element in the finite map used to a function interpretation. *) + module FuncEntry : + sig + type func_entry + + (** Return the (symbolic) value of this entry. + *) + val get_value : func_entry -> Expr.expr + + (** The number of arguments of the entry. + *) + val get_num_args : func_entry -> int + + (** The arguments of the function entry. + *) + val get_args : func_entry -> Expr.expr list + + (** A string representation of the function entry. + *) + val to_string : func_entry -> string + end + + (** The number of entries in the function interpretation. *) + val get_num_entries : func_interp -> int + + (** The entries in the function interpretation *) + val get_entries : func_interp -> FuncEntry.func_entry list + + (** The (symbolic) `else' value of the function interpretation. *) + val get_else : func_interp -> Expr.expr + + (** The arity of the function interpretation *) + val get_arity : func_interp -> int + + (** A string representation of the function interpretation. *) + val to_string : func_interp -> string + end + + (** Retrieves the interpretation (the assignment) of a func_decl in the model. + An expression if the function has an interpretation in the model, null otherwise. *) + val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of an expression in the model. + An expression if the constant has an interpretation in the model, null otherwise. *) + val get_const_interp_e : model -> Expr.expr -> Expr.expr option + + (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. + A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option + + (** The number of constant interpretations in the model. *) + val get_num_consts : model -> int + + (** The function declarations of the constants in the model. *) + val get_const_decls : model -> FuncDecl.func_decl list + + (** The number of function interpretations in the model. *) + val get_num_funcs : model -> int + + (** The function declarations of the function interpretations in the model. *) + val get_func_decls : model -> FuncDecl.func_decl list + + (** All symbols that have an interpretation in the model. *) + val get_decls : model -> FuncDecl.func_decl list + + (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) + exception ModelEvaluationFailedException of string + + (** Evaluates an expression in the current model. + + This function may fail if the argument contains quantifiers, + is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. + In this case a ModelEvaluationFailedException is thrown. + *) + val eval : model -> Expr.expr -> bool -> Expr.expr + + (** Alias for eval. *) + val evaluate : model -> Expr.expr -> bool -> Expr.expr + + (** The number of uninterpreted sorts that the model has an interpretation for. *) + val get_num_sorts : model -> int + + (** The uninterpreted sorts that the model has an interpretation for. + + Z3 also provides an intepretation for uninterpreted sorts used in a formula. + The interpretation for a sort is a finite set of distinct values. We say this finite set is + the "universe" of the sort. + {!get_num_sorts} + {!sort_universe} *) + val get_sorts : model -> Sort.sort list + + (** The finite set of distinct values that represent the interpretation of a sort. + {!get_sorts} + @returns A list of expressions, where each is an element of the universe of the sort *) + val sort_universe : model -> Sort.sort -> AST.ast list + + (** Conversion of models to strings. + A string representation of the model. *) + val to_string : model -> string +end + +(** Probes + + Probes are used to inspect a goal (aka problem) and collect information that may be used to decide + which solver and/or preprocessing step will be used. + The complete list of probes may be obtained using the procedures Context.NumProbes + and Context.ProbeNames. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Probe : +sig + type probe + + (** Execute the probe over the goal. + A probe always produce a double value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + val apply : probe -> Goal.goal -> float + + (** The number of supported Probes. *) + val get_num_probes : context -> int + + (** The names of all supported Probes. *) + val get_probe_names : context -> string list + + (** Returns a string containing a description of the probe with the given name. *) + val get_probe_description : context -> string -> string + + (** Creates a new Probe. *) + val mk_probe : context -> string -> probe + + (** Create a probe that always evaluates to a float value. *) + val const : context -> float -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than the value returned by second argument *) + val lt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than the value returned by second argument *) + val gt : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is less than or equal the value returned by second argument *) + val le : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is greater than or equal the value returned by second argument *) + val ge : context -> probe -> probe -> probe + + + (** Create a probe that evaluates to "true" when the value returned by the first argument + is equal the value returned by second argument *) + val eq : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) + val and_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) + val or_ : context -> probe -> probe -> probe + + (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) + val not_ : context -> probe -> probe +end + +(** Tactics + + Tactics are the basic building block for creating custom solvers for specific problem domains. + The complete list of tactics may be obtained using Context.get_num_tactics + and Context.get_tactic_names. + It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. +*) +module Tactic : +sig + type tactic + + (** Tactic application results + + ApplyResult objects represent the result of an application of a + tactic to a goal. It contains the subgoals that were produced. *) + module ApplyResult : + sig + type apply_result + + (** The number of Subgoals. *) + val get_num_subgoals : apply_result -> int + + (** Retrieves the subgoals from the apply_result. *) + val get_subgoals : apply_result -> Goal.goal list + + (** Retrieves a subgoal from the apply_result. *) + val get_subgoal : apply_result -> int -> Goal.goal + + (** Convert a model for a subgoal into a model for the original + goal g, that the ApplyResult was obtained from. + #return A model for g *) + val convert_model : apply_result -> int -> Model.model -> Model.model + + (** A string representation of the ApplyResult. *) + val to_string : apply_result -> string + end + + (** A string containing a description of parameters accepted by the tactic. *) + val get_help : tactic -> string + + (** Retrieves parameter descriptions for Tactics. *) + val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs + + (** Apply the tactic to the goal. *) + val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result + + (** The number of supported tactics. *) + val get_num_tactics : context -> int + + (** The names of all supported tactics. *) + val get_tactic_names : context -> string list + + (** Returns a string containing a description of the tactic with the given name. *) + val get_tactic_description : context -> string -> string + + (** Creates a new Tactic. *) + val mk_tactic : context -> string -> tactic + + (** Create a tactic that applies one tactic to a Goal and + then another one to every subgoal produced by the first one. *) + val and_then : context -> tactic -> tactic -> tactic list -> tactic + + (** Create a tactic that first applies one tactic to a Goal and + if it fails then returns the result of another tactic applied to the Goal. *) + val or_else : context -> tactic -> tactic -> tactic + + (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). + + If the tactic does not terminate within the timeout, then it fails. *) + val try_for : context -> tactic -> int -> tactic + + (** Create a tactic that applies one tactic to a given goal if the probe + evaluates to true. + + If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) + val when_ : context -> Probe.probe -> tactic -> tactic + + (** Create a tactic that applies a tactic to a given goal if the probe + evaluates to true and another tactic otherwise. *) + val cond : context -> Probe.probe -> tactic -> tactic -> tactic + + (** Create a tactic that keeps applying one tactic until the goal is not + modified anymore or the maximum number of iterations is reached. *) + val repeat : context -> tactic -> int -> tactic + + (** Create a tactic that just returns the given goal. *) + val skip : context -> tactic + + (** Create a tactic always fails. *) + val fail : context -> tactic + + (** Create a tactic that fails if the probe evaluates to false. *) + val fail_if : context -> Probe.probe -> tactic + + (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) + or trivially unsatisfiable (i.e., contains `false'). *) + val fail_if_not_decided : context -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. *) + val using_params : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies a tactic using the given set of parameters. + Alias for UsingParams*) + val with_ : context -> tactic -> Params.params -> tactic + + (** Create a tactic that applies the given tactics in parallel. *) + val par_or : context -> tactic list -> tactic + + (** Create a tactic that applies a tactic to a given goal and then another tactic + to every subgoal produced by the first one. The subgoals are processed in parallel. *) + val par_and_then : context -> tactic -> tactic -> tactic + + (** Interrupt the execution of a Z3 procedure. + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) + val interrupt : context -> unit +end + +(** Solvers *) +module Solver : +sig + type solver + type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE + + val string_of_status : status -> string + + (** Objects that track statistical information about solvers. *) + module Statistics : + sig + type statistics + + (** Statistical data is organized into pairs of \[Key, Entry\], where every + Entry is either a floating point or integer value. + *) + module Entry : + sig + type statistics_entry + + (** The key of the entry. *) + val get_key : statistics_entry -> string + + (** The int-value of the entry. *) + val get_int : statistics_entry -> int + + (** The float-value of the entry. *) + val get_float : statistics_entry -> float + + (** True if the entry is uint-valued. *) + val is_int : statistics_entry -> bool + + (** True if the entry is double-valued. *) + val is_float : statistics_entry -> bool + + (** The string representation of the the entry's value. *) + val to_string_value : statistics_entry -> string + + (** The string representation of the entry (key and value) *) + val to_string : statistics_entry -> string + end + + (** A string representation of the statistical data. *) + val to_string : statistics -> string + + (** The number of statistical data. *) + val get_size : statistics -> int + + (** The data entries. *) + val get_entries : statistics -> Entry.statistics_entry list + + (** The statistical counters. *) + val get_keys : statistics -> string list + + (** The value of a particular statistical counter. *) + val get : statistics -> string -> Entry.statistics_entry option + end + + (** A string that describes all available solver parameters. *) + val get_help : solver -> string + + (** Sets the solver parameters. *) + val set_parameters : solver -> Params.params -> unit + + (** Retrieves parameter descriptions for solver. *) + val get_param_descrs : solver -> Params.ParamDescrs.param_descrs + + (** The current number of backtracking points (scopes). + {!pop} + {!push} *) + val get_num_scopes : solver -> int + + (** Creates a backtracking point. + {!pop} *) + val push : solver -> unit + + (** Backtracks a number of backtracking points. + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) + val pop : solver -> int -> unit + + (** Resets the Solver. + This removes all assertions from the solver. *) + val reset : solver -> unit + + (** Assert a constraint (or multiple) into the solver. *) + val assert_ : solver -> Boolean.bool_expr list -> unit + + (** * Assert multiple constraints (cs) into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit + + (** * Assert a constraint (c) into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) + val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit + + (** The number of assertions in the solver. *) + val get_num_assertions : solver -> int + + (** The set of asserted formulas. *) + val get_assertions : solver -> Boolean.bool_expr list + + (** Checks whether the assertions in the solver are consistent or not. + + {!Model} + {!get_unsat_core} + {!Proof} *) + val check : solver -> Boolean.bool_expr list -> status + + (** The model of the last Check. + + The result is None if Check was not invoked before, + if its results was not SATISFIABLE, or if model production is not enabled. *) + val get_model : solver -> Model.model option + + (** The proof of the last Check. + + The result is null if Check was not invoked before, + if its results was not UNSATISFIABLE, or if proof production is disabled. *) + val get_proof : solver -> Expr.expr option + + (** The unsat core of the last Check. + + The unsat core is a subset of Assertions + The result is empty if Check was not invoked before, + if its results was not UNSATISFIABLE, or if core production is disabled. *) + val get_unsat_core : solver -> AST.ast list + + (** A brief justification of why the last call to Check returned UNKNOWN. *) + val get_reason_unknown : solver -> string + + (** Solver statistics. *) + val get_statistics : solver -> Statistics.statistics + + (** Creates a new (incremental) solver. + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) + val mk_solver : context -> Symbol.symbol option -> solver + + (** Creates a new (incremental) solver. + {!mk_solver} *) + val mk_solver_s : context -> string -> solver + + (** Creates a new (incremental) solver. *) + val mk_simple_solver : context -> solver + + (** Creates a solver that is implemented using the given tactic. + + The solver supports the commands Push and Pop, but it + will always solve each check from scratch. *) + val mk_solver_t : context -> Tactic.tactic -> solver + + (** A string representation of the solver. *) + val to_string : solver -> string +end + +(** Fixedpoint solving *) +module Fixedpoint : +sig + type fixedpoint + + (** A string that describes all available fixedpoint solver parameters. *) + val get_help : fixedpoint -> string + + (** Sets the fixedpoint solver parameters. *) + val set_params : fixedpoint -> Params.params -> unit + + (** Retrieves parameter descriptions for Fixedpoint solver. *) + val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs + + (** Assert a constraints into the fixedpoint solver. *) + val assert_ : fixedpoint -> Boolean.bool_expr list -> unit + + (** Register predicate as recursive relation. *) + val register_relation : fixedpoint -> FuncDecl.func_decl -> unit + + (** Add rule into the fixedpoint solver. *) + val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit + + (** Add table fact to the fixedpoint solver. *) + val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit + + (** Query the fixedpoint solver. + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) + val query : fixedpoint -> Boolean.bool_expr -> Solver.status + + (** Query the fixedpoint solver. + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) + val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status + + (** Creates a backtracking point. + {!pop} *) + val push : fixedpoint -> unit + + (** Backtrack one backtracking point. + + Note that an exception is thrown if Pop is called without a corresponding Push + {!push} *) + val pop : fixedpoint -> unit + + (** Update named rule into in the fixedpoint solver. *) + val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit + + (** Retrieve satisfying instance or instances of solver, + or definitions for the recursive predicates that show unsatisfiability. *) + val get_answer : fixedpoint -> Expr.expr option + + (** Retrieve explanation why fixedpoint engine returned status Unknown. *) + val get_reason_unknown : fixedpoint -> string + + (** Retrieve the number of levels explored for a given predicate. *) + val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int + + (** Retrieve the cover of a predicate. *) + val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option + + (** Add property about the predicate. + The property is added at level. *) + val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit + + (** Retrieve internal string representation of fixedpoint object. *) + val to_string : fixedpoint -> string + + (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) + val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit + + (** Convert benchmark given as set of axioms, rules and queries to a string. *) + val to_string_q : fixedpoint -> Boolean.bool_expr list -> string + + (** Retrieve set of rules added to fixedpoint context. *) + val get_rules : fixedpoint -> Boolean.bool_expr list + + (** Retrieve set of assertions added to fixedpoint context. *) + val get_assertions : fixedpoint -> Boolean.bool_expr list + + (** Create a Fixedpoint context. *) + val mk_fixedpoint : context -> fixedpoint +end + +(** Global and context options + + Note: This module contains functions that set parameters/options for context + objects as well as functions that set options that are used globally, across + contexts.*) +module Options : +sig + (** Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -ini? + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + {!get_param_value} *) + val update_param_value : context -> string -> string -> unit + + (** Get a configuration parameter. + + Returns None if the parameter value does not exist. + {!update_param_value} *) + val get_param_value : context -> string -> string option + + (** Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) + val set_print_mode : context -> Z3enums.ast_print_mode -> unit + + (** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) + val toggle_warning_messages : bool -> unit +end + +(** Functions for handling SMT and SMT2 expressions and files *) +module SMT : +sig + (** Convert a benchmark into an SMT-LIB formatted string. + + @return A string representation of the benchmark. *) + val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string + + (** Parse the given string using the SMT-LIB parser. + + The symbol table of the parser can be initialized using the given sorts and declarations. + The symbols in the arrays in the third and fifth argument + don't need to match the names of the sorts and declarations in the arrays in the fourth + and sixth argument. This is a useful feature since we can use arbitrary names to + reference sorts and declarations. *) + val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit + + (** Parse the given file using the SMT-LIB parser. + {!parse_smtlib_string} *) + val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit + + (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_formulas : context -> int + + (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_formulas : context -> Boolean.bool_expr list + + (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_assumptions : context -> int + + (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_assumptions : context -> Boolean.bool_expr list + + (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_decls : context -> int + + (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_decls : context -> FuncDecl.func_decl list + + (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_num_smtlib_sorts : context -> int + + (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + val get_smtlib_sorts : context -> Sort.sort list + + (** Parse the given string using the SMT-LIB2 parser. + + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) + val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr + + (** Parse the given file using the SMT-LIB2 parser. + {!parse_smtlib2_string} *) + val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr +end + +(** Set a global (or module) parameter, which is shared by all Z3 contexts. + + When a Z3 module is initialized it will use the value of these parameters + when Z3_params objects are not provided. + The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + The character '.' is a delimiter (more later). + The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + This function can be used to set parameters for a specific Z3 module. + This can be done by using .. + For example: + (set_global_param "pp.decimal" "true") + will set the parameter "decimal" in the module "pp" to true. +*) +val set_global_param : string -> string -> unit + +(** Get a global (or module) parameter. + + Returns None if the parameter does not exist. + The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + This function cannot be invoked simultaneously from different threads without synchronization. + The result string stored in param_value is stored in a shared location. +*) +val get_global_param : string -> string option + +(** Restore the value of all global (and module) parameters. + + This command will not affect already created objects (such as tactics and solvers) + {!set_global_param} +*) +val global_param_reset_all : unit From eea13a087f0caec61ec1ef3235944921a07b97e3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 14:17:35 +0000 Subject: [PATCH 430/646] ML API savegame Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 124 +++++++++++++++++++------------------- src/api/ml/z3.ml | 18 +++--- src/api/ml/z3.mli | 23 ++++--- src/api/ml/z3_rich.ml | 43 +++++++------ src/api/ml/z3_rich.mli | 13 ++-- 5 files changed, 107 insertions(+), 114 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 823a08fe2..f7a4cbc00 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -162,70 +162,68 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ) ; - model_converter_test ctx -(* - // Real num/den test. - RatNum rn = ctx.MkReal(42, 43); - Expr inum = rn.Numerator; - Expr iden = rn.Denominator; - Console.WriteLine("Numerator: " + inum + " Denominator: " + iden); - if (inum.ToString() != "42" || iden.ToString() != "43") - throw new TestFailedException(); - - if (rn.ToDecimalString(3) != "0.976?") - throw new TestFailedException(); - - BigIntCheck(ctx, ctx.MkReal("-1231231232/234234333")); - BigIntCheck(ctx, ctx.MkReal("-123123234234234234231232/234234333")); - BigIntCheck(ctx, ctx.MkReal("-234234333")); - BigIntCheck(ctx, ctx.MkReal("234234333/2")); - - - string bn = "1234567890987654321"; - - if (ctx.MkInt(bn).BigInteger.ToString() != bn) - throw new TestFailedException(); - - if (ctx.MkBV(bn, 128).BigInteger.ToString() != bn) - throw new TestFailedException(); - - if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn) - throw new TestFailedException(); - - // Error handling test. - try - { - IntExpr i = ctx.MkInt("1/2"); - throw new TestFailedException(); // unreachable - } - catch (Z3Exception) - { - } - } -*) + model_converter_test ctx ; + (* Real num/den test. *) + let rn = Real.mk_numeral_nd ctx 42 43 in + let inum = (get_numerator rn) in + let iden = get_denominator rn in + Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; + if ((Real.to_string inum) <> "42" or (Real.to_string iden) <> "43") then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + if ((to_decimal_string rn 3) <> "0.976?") then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ; + if (to_decimal_string (Real.mk_numeral_s ctx "-1231231232/234234333") 5 <> "-5.25640?") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "-123123234234234234231232/234234333") 5 <> "-525641278361333.28170?") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "-234234333") 5 <> "-234234333") then + raise (TestFailedException "") + else if (to_decimal_string (Real.mk_numeral_s ctx "234234333/2") 5 <> "117117166.5") then + raise (TestFailedException "") + ; + (* Error handling test. *) + try ( + let i = Integer.mk_numeral_s ctx "1/2" in + raise (TestFailedException "") (* unreachable *) + ) + with Z3native.Exception(_) -> ( + Printf.printf "Exception caught, OK.\n" + ) let _ = - if not (Log.open_ "z3.log") then - raise (TestFailedException "Log couldn't be opened.") - else - ( - Printf.printf "Running Z3 version %s\n" Version.to_string ; - let cfg = [("model", "true"); ("proof", "false")] in - let ctx = (mk_context cfg) in - let is = (Symbol.mk_int ctx 42) in - let ss = (Symbol.mk_string ctx "mySymbol") in - let bs = (Boolean.mk_sort ctx) in - let ints = (Integer.mk_sort ctx) in - let rs = (Real.mk_sort ctx) in - Printf.printf "int symbol: %s\n" (Symbol.to_string is); - Printf.printf "string symbol: %s\n" (Symbol.to_string ss); - Printf.printf "bool sort: %s\n" (Sort.to_string bs); - Printf.printf "int sort: %s\n" (Sort.to_string ints); - Printf.printf "real sort: %s\n" (Sort.to_string rs); - basic_tests ctx ; - Printf.printf "Disposing...\n"; - Gc.full_major () - ); - Printf.printf "Exiting.\n"; + try ( + if not (Log.open_ "z3.log") then + raise (TestFailedException "Log couldn't be opened.") + else + ( + Printf.printf "Running Z3 version %s\n" Version.to_string ; + let cfg = [("model", "true"); ("proof", "false")] in + let ctx = (mk_context cfg) in + let is = (Symbol.mk_int ctx 42) in + let ss = (Symbol.mk_string ctx "mySymbol") in + let bs = (Boolean.mk_sort ctx) in + let ints = (Integer.mk_sort ctx) in + let rs = (Real.mk_sort ctx) in + Printf.printf "int symbol: %s\n" (Symbol.to_string is); + Printf.printf "string symbol: %s\n" (Symbol.to_string ss); + Printf.printf "bool sort: %s\n" (Sort.to_string bs); + Printf.printf "int sort: %s\n" (Sort.to_string ints); + Printf.printf "real sort: %s\n" (Sort.to_string rs); + basic_tests ctx ; + Printf.printf "Disposing...\n"; + Gc.full_major () + ); + Printf.printf "Exiting.\n" ; + exit 0 + ) with Z3native.Exception(msg) -> ( + Printf.printf "Z3 EXCEPTION: %s\n" msg ; + exit 1 + ) ;; diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 0676f1a39..e62732924 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -11,7 +11,6 @@ open Z3enums let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) - (* Internal types *) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context @@ -21,7 +20,6 @@ type z3_native_object = { mutable m_n_obj : Z3native.ptr ; inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - (** Internal stuff *) module Internal = @@ -1455,11 +1453,11 @@ struct let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_mod ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) @@ -1467,10 +1465,10 @@ struct let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = + let mk_numeral_s ( ctx : context ) ( v : string ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx))) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = + let mk_numeral_i ( ctx : context ) ( v : int ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno (mk_sort ctx))) let mk_int2real ( ctx : context ) ( t : expr ) = @@ -1496,11 +1494,11 @@ struct let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 908b3023d..d7e179cd4 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -30,7 +30,6 @@ type context (** Create a context object *) val mk_context : (string * string) list -> context - (** Interaction logging for Z3 Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) @@ -1117,10 +1116,10 @@ sig end (** Functions to manipulate arithmetic expressions *) -module rec Arithmetic : +module Arithmetic : sig (** Integer Arithmetic *) - module rec Integer : + module Integer : sig (** Create a new integer sort. *) val mk_sort : context -> Sort.sort @@ -1132,10 +1131,10 @@ sig val to_string : Expr.expr -> string (** Creates an integer constant. *) - val mk_int_const : context -> Symbol.symbol -> Expr.expr + val mk_const : context -> Symbol.symbol -> Expr.expr (** Creates an integer constant. *) - val mk_int_const_s : context -> string -> Expr.expr + val mk_const_s : context -> string -> Expr.expr (** Create an expression representing t1 mod t2. The arguments must have int type. *) @@ -1146,11 +1145,11 @@ sig val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer numeral. *) - val mk_int_numeral_s : context -> string -> Expr.expr + val mk_numeral_s : context -> string -> Expr.expr (** Create an integer numeral. @return A Term with the given value and sort Integer *) - val mk_int_numeral_i : context -> int -> Expr.expr + val mk_numeral_i : context -> int -> Expr.expr (** Coerce an integer to a real. @@ -1174,7 +1173,7 @@ sig end (** Real Arithmetic *) - and Real : + module Real : sig (** Create a real sort. *) val mk_sort : context -> Sort.sort @@ -1193,10 +1192,10 @@ sig val to_string : Expr.expr-> string (** Creates a real constant. *) - val mk_real_const : context -> Symbol.symbol -> Expr.expr + val mk_const : context -> Symbol.symbol -> Expr.expr (** Creates a real constant. *) - val mk_real_const_s : context -> string -> Expr.expr + val mk_const_s : context -> string -> Expr.expr (** Create a real numeral from a fraction. @return A Term with rational value and sort Real @@ -1222,7 +1221,7 @@ sig end (** Algebraic Numbers *) - and AlgebraicNumber : + module AlgebraicNumber : sig (** Return a upper bound for a given real algebraic number. The interval isolating the number is smaller than 1/10^precision. @@ -1339,7 +1338,7 @@ sig end (** Functions to manipulate bit-vector expressions *) -and BitVector : +module BitVector : sig (** Create a new bit-vector sort. *) val mk_sort : context -> int -> Sort.sort diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml index 052ca5e22..0c2f95b6b 100644 --- a/src/api/ml/z3_rich.ml +++ b/src/api/ml/z3_rich.ml @@ -1,4 +1,4 @@ -(** +\(** The Z3 ML/Ocaml Interface. Copyright (C) 2012 Microsoft Corporation @@ -11,7 +11,6 @@ open Z3enums let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) - (* Internal types *) type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } type context = z3_native_context @@ -1679,12 +1678,12 @@ sig val mk_sort : context -> int_sort val get_int : int_num -> int val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr + val mk_const_s : context -> string -> int_expr val mk_mod : context -> int_expr -> int_expr -> int_expr val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_s : context -> string -> int_num + val mk_numeral_i : context -> int -> int_num val mk_int2real : context -> int_expr -> Real.real_expr val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end @@ -1709,8 +1708,8 @@ sig val get_denominator : rat_num -> Integer.int_num val to_decimal_string : rat_num -> int -> string val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr + val mk_const_s : context -> string -> real_expr val mk_numeral_nd : context -> int -> int -> rat_num val mk_numeral_s : context -> string -> rat_num val mk_numeral_i : context -> int -> rat_num @@ -1816,12 +1815,12 @@ end = struct val mk_sort : context -> int_sort val get_int : int_num -> int val to_string : int_num -> string - val mk_int_const : context -> Symbol.symbol -> int_expr - val mk_int_const_s : context -> string -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr + val mk_const_s : context -> string -> int_expr val mk_mod : context -> int_expr -> int_expr -> int_expr val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_int_numeral_s : context -> string -> int_num - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_s : context -> string -> int_num + val mk_numeral_i : context -> int -> int_num val mk_int2real : context -> int_expr -> Real.real_expr val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr end = struct @@ -1884,11 +1883,11 @@ end = struct let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_int_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - let mk_int_const_s ( ctx : context ) ( name : string ) = - mk_int_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) @@ -1896,10 +1895,10 @@ end = struct let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - let mk_int_numeral_s ( ctx : context ) ( v : string ) = + let mk_numeral_s ( ctx : context ) ( v : string ) = int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - let mk_int_numeral_i ( ctx : context ) ( v : int ) = + let mk_numeral_i ( ctx : context ) ( v : int ) = int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) let mk_int2real ( ctx : context ) ( t : int_expr ) = @@ -1930,8 +1929,8 @@ end = struct val get_denominator : rat_num -> Integer.int_num val to_decimal_string : rat_num -> int -> string val to_string : rat_num -> string - val mk_real_const : context -> Symbol.symbol -> real_expr - val mk_real_const_s : context -> string -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr + val mk_const_s : context -> string -> real_expr val mk_numeral_nd : context -> int -> int -> rat_num val mk_numeral_s : context -> string -> rat_num val mk_numeral_i : context -> int -> rat_num @@ -2002,11 +2001,11 @@ end = struct let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_real_const ( ctx : context ) ( name : Symbol.symbol ) = + let mk_const ( ctx : context ) ( name : Symbol.symbol ) = RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - let mk_real_const_s ( ctx : context ) ( name : string ) = - mk_real_const ctx (Symbol.mk_string ctx name) + let mk_const_s ( ctx : context ) ( name : string ) = + mk_const ctx (Symbol.mk_string ctx name) let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = if (den == 0) then diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli index 8b6681e11..f2ecd326d 100644 --- a/src/api/ml/z3_rich.mli +++ b/src/api/ml/z3_rich.mli @@ -34,7 +34,6 @@ type context (** Create a context object *) val mk_context : (string * string) list -> context - (** Interaction logging for Z3 Note that this is a global, static log and if multiple Context objects are created, it logs the interaction with all of them. *) @@ -1219,10 +1218,10 @@ sig val to_string : int_num -> string (** Creates an integer constant. *) - val mk_int_const : context -> Symbol.symbol -> int_expr + val mk_const : context -> Symbol.symbol -> int_expr (** Creates an integer constant. *) - val mk_int_const_s : context -> string -> int_expr + val mk_const_s : context -> string -> int_expr (** Create an expression representing t1 mod t2. The arguments must have int type. *) @@ -1233,11 +1232,11 @@ sig val mk_rem : context -> int_expr -> int_expr -> int_expr (** Create an integer numeral. *) - val mk_int_numeral_s : context -> string -> int_num + val mk_numeral_s : context -> string -> int_num (** Create an integer numeral. @return A Term with the given value and sort Integer *) - val mk_int_numeral_i : context -> int -> int_num + val mk_numeral_i : context -> int -> int_num (** Coerce an integer to a real. @@ -1291,10 +1290,10 @@ sig val to_string : rat_num -> string (** Creates a real constant. *) - val mk_real_const : context -> Symbol.symbol -> real_expr + val mk_const : context -> Symbol.symbol -> real_expr (** Creates a real constant. *) - val mk_real_const_s : context -> string -> real_expr + val mk_const_s : context -> string -> real_expr (** Create a real numeral from a fraction. @return A Term with rational value and sort Real From 050629536ab7e195bb1fe076e77e8c4043d563bb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 21 Feb 2013 18:53:29 +0000 Subject: [PATCH 431/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- examples/ml/Makefile | 4 ++-- scripts/update_api.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/ml/Makefile b/examples/ml/Makefile index a7f8e6ee0..818f0cacc 100644 --- a/examples/ml/Makefile +++ b/examples/ml/Makefile @@ -3,5 +3,5 @@ # in the top-level build directory. all: - OCAML_COMPAT=c C:/ocamlw32/bin/ocamlc -g -annot -o ml_example.byte -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cma ml_example.ml - C:/ocamlw32/bin/ocamlopt -g -annot -o ml_example -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml + source /cygdrive/c/cwinter/.msenv32 ; OCAML_COMPAT=c C:/ocamlw32/bin/ocamlc -g -custom -cclib '-L../../bld_dbg -lz3' -annot -o ml_example.byte -I ../../bld_dbg/api/ml z3.cma ml_example.ml + source /cygdrive/c/cwinter/.msenv32 ; C:/ocamlw32/bin/ocamlopt -g -annot -o ml_example -cclib '-L../../bld_dbg -lz3' -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml diff --git a/scripts/update_api.py b/scripts/update_api.py index a0b7e6250..44d871348 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1339,9 +1339,10 @@ def mk_ml(): ml_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') ml_wrapper.write(' // wrappers below.\n') ml_wrapper.write('}\n\n') - ml_wrapper.write('void n_set_internal_error_handler(Z3_context c)\n') + ml_wrapper.write('void n_set_internal_error_handler(value a0)\n') ml_wrapper.write('{\n') - ml_wrapper.write(' Z3_set_error_handler(c, MLErrorHandler);\n') + ml_wrapper.write(' Z3_context _a0 = * (Z3_context*) Data_custom_val(a0);\n') + ml_wrapper.write(' Z3_set_error_handler(_a0, MLErrorHandler);\n') ml_wrapper.write('}\n\n') for name, result, params in _dotnet_decls: ip = inparams(params) From c1e29dabe7858fbbf9eb112028c010d18f4b666c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 26 Feb 2013 19:45:45 +0000 Subject: [PATCH 432/646] ML API: renamed assert_ to add Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 24 ++++++++++++------------ src/api/ml/z3.ml | 8 ++++---- src/api/ml/z3.mli | 8 ++++---- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index f7a4cbc00..c9ed1d948 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -29,11 +29,11 @@ let model_converter_test ( ctx : context ) = let xr = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Real.mk_sort ctx)) in let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in let g4 = (mk_goal ctx true false false ) in - (Goal.assert_ g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; - (Goal.assert_ g4 [ (mk_eq ctx + (Goal.add g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; + (Goal.add g4 [ (mk_eq ctx yr (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1) ])) ]) ; - (Goal.assert_ g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; + (Goal.add g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; ( let ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in if ((get_num_subgoals ar) == 1 && @@ -53,7 +53,7 @@ let model_converter_test ( ctx : context ) = Printf.printf "Test passed.\n" ; let solver = (mk_solver ctx None) in - let f e = (Solver.assert_ solver [ e ]) in + let f e = (Solver.add solver [ e ]) in ignore (List.map f (get_formulas (get_subgoal ar 0))) ; let q = (check solver []) in if q != SATISFIABLE then @@ -88,12 +88,12 @@ let basic_tests ( ctx : context ) = let trivial_eq = (mk_eq ctx fapp fapp) in let nontrivial_eq = (mk_eq ctx fapp fapp2) in let g = (mk_goal ctx true false false) in - (Goal.assert_ g [ trivial_eq ]) ; - (Goal.assert_ g [ nontrivial_eq ]) ; + (Goal.add g [ trivial_eq ]) ; + (Goal.add g [ nontrivial_eq ]) ; Printf.printf "%s\n" ("Goal: " ^ (Goal.to_string g)) ; ( let solver = (mk_solver ctx None) in - (List.iter (fun a -> (Solver.assert_ solver [ a ])) (get_formulas g)) ; + (List.iter (fun a -> (Solver.add solver [ a ])) (get_formulas g)) ; if (check solver []) != SATISFIABLE then raise (TestFailedException "") else @@ -116,7 +116,7 @@ let basic_tests ( ctx : context ) = else Printf.printf "Test passed.\n" ); - (Goal.assert_ g [ (mk_eq ctx + (Goal.add g [ (mk_eq ctx (mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) (mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) ; @@ -139,7 +139,7 @@ let basic_tests ( ctx : context ) = ); ( let g2 = (mk_goal ctx true true false) in - (Goal.assert_ g2 [ (Boolean.mk_false ctx) ]) ; + (Goal.add g2 [ (Boolean.mk_false ctx) ]) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then @@ -151,10 +151,10 @@ let basic_tests ( ctx : context ) = let g3 = (mk_goal ctx true true false) in let xc = (Expr.mk_const ctx (Symbol.mk_string ctx "x") (Integer.mk_sort ctx)) in let yc = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Integer.mk_sort ctx)) in - (Goal.assert_ g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; - (Goal.assert_ g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; + (Goal.add g3 [ (mk_eq ctx xc (mk_numeral_int ctx 1 (Integer.mk_sort ctx))) ]) ; + (Goal.add g3 [ (mk_eq ctx yc (mk_numeral_int ctx 2 (Integer.mk_sort ctx))) ]) ; let constr = (mk_eq ctx xc yc) in - (Goal.assert_ g3 [ constr ] ) ; + (Goal.add g3 [ constr ] ) ; let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in if ((get_num_subgoals ar) == 1 && (not (is_decided_unsat (get_subgoal ar 0)))) then diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index e62732924..8eb5427bb 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1850,7 +1850,7 @@ struct let is_garbage ( x : goal ) = (get_precision x) == GOAL_UNDER_OVER - let assert_ ( x : goal ) ( constraints : expr list ) = + let add ( x : goal ) ( constraints : expr list ) = let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e) in ignore (List.map f constraints) ; () @@ -2370,11 +2370,11 @@ struct let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - let assert_ ( x : solver ) ( constraints : expr list ) = + let add ( x : solver ) ( constraints : expr list ) = let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) - let assert_and_track_a ( x : solver ) ( cs : expr list ) ( ps : expr list ) = + let assert_and_track_l ( x : solver ) ( cs : expr list ) ( ps : expr list ) = if ((List.length cs) != (List.length ps)) then raise (Z3native.Exception "Argument size mismatch") else @@ -2473,7 +2473,7 @@ struct let get_param_descrs ( x : fixedpoint ) = Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - let assert_ ( x : fixedpoint ) ( constraints : expr list ) = + let add ( x : fixedpoint ) ( constraints : expr list ) = let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Expr.gno e)) in ignore (List.map f constraints) ; () diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index d7e179cd4..cde99a90d 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -2221,7 +2221,7 @@ sig val is_garbage : goal -> bool (** Adds the constraints to the given goal. *) - val assert_ : goal -> Expr.expr list -> unit + val add : goal -> Expr.expr list -> unit (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool @@ -2648,7 +2648,7 @@ sig val reset : solver -> unit (** Assert a constraint (or multiple) into the solver. *) - val assert_ : solver -> Expr.expr list -> unit + val add : solver -> Expr.expr list -> unit (** * Assert multiple constraints (cs) into the solver, and track them (in the * unsat) core @@ -2661,7 +2661,7 @@ sig * of the Boolean variables provided using {!assert_and_track} * and the Boolean literals * provided using {!check} with assumptions. *) - val assert_and_track_a : solver -> Expr.expr list -> Expr.expr list -> unit + val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit (** * Assert a constraint (c) into the solver, and track it (in the unsat) core * using the Boolean constant p. @@ -2752,7 +2752,7 @@ sig val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs (** Assert a constraints into the fixedpoint solver. *) - val assert_ : fixedpoint -> Expr.expr list -> unit + val add : fixedpoint -> Expr.expr list -> unit (** Register predicate as recursive relation. *) val register_relation : fixedpoint -> FuncDecl.func_decl -> unit From aaa835484f5db085b3e8bac7df6e15ba7bd7f0b3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Jun 2013 18:51:40 +0100 Subject: [PATCH 433/646] Updates to ML API. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 43 ++++++++-------- src/api/ml/z3.mli | 126 ++++++++++++++++++++++++---------------------- 2 files changed, 86 insertions(+), 83 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8eb5427bb..4a8fbaa0a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -323,8 +323,8 @@ struct else ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + let unwrap_ast ( x : ast ) = (z3obj_gno x) let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr - let unwrap_ast ( x : ast ) = (z3obj_gno x) end open AST @@ -678,6 +678,19 @@ end = struct res let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) + + let update_param_value ( ctx : context ) ( id : string) ( value : string )= + Z3native.update_param_value (context_gno ctx) id value + + let get_param_value ( ctx : context ) ( id : string ) = + let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in + if not r then + None + else + Some v + + let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = + Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) end (** General expressions (terms) *) @@ -1106,7 +1119,7 @@ struct end -module Array_ = +module Array = struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) @@ -1389,7 +1402,7 @@ struct end -module List_ = +module List = struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in @@ -2558,26 +2571,6 @@ struct let mk_fixedpoint ( ctx : context ) = create ctx end -module Options = -struct - - let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value (context_gno ctx) id value - - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - - let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages enabled -end - module SMT = struct @@ -2692,3 +2685,7 @@ let get_global_param ( id : string ) = let global_param_reset_all = Z3native.global_param_reset_all + +let toggle_warning_messages ( enabled: bool ) = + Z3native.toggle_warning_messages enabled + diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index cde99a90d..1c4c4e922 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -27,7 +27,20 @@ *) type context -(** Create a context object *) +(** Create a context object + The following parameters can be set: + + - proof (Boolean) Enable proof generation + - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting + - trace (Boolean) Tracing support for VCC + - trace_file_name (String) Trace out file for VCC traces + - timeout (unsigned) default timeout (in milliseconds) used for solvers + - well_sorted_check type checker + - auto_config use heuristics to automatically select solver and configure it + - model model generation for solvers, this parameter can be overwritten when creating a solver + - model_validate validate models produced by solvers + - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver +*) val mk_context : (string * string) list -> context (** Interaction logging for Z3 @@ -220,15 +233,6 @@ sig @return A copy of the AST which is associated with the other context. *) val translate : ast -> context -> ast - (** Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., - Z3native.inc_ref). *) - val wrap_ast : context -> Z3native.z3_ast -> ast - (** Unwraps an AST. This function is used for transitions between native and managed objects. It returns the native pointer to the AST. Note that @@ -238,6 +242,15 @@ sig Z3native.inc_ref). {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr + + (** Wraps an AST. + + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., + Z3native.inc_ref). *) + val wrap_ast : context -> Z3native.z3_ast -> ast end (** The Sort module implements type information for ASTs *) @@ -432,6 +445,36 @@ sig (** A string representation of the parameter set. *) val to_string : params -> string + + (** Update a mutable configuration parameter. + + The list of all configuration parameters can be obtained using the Z3 executable: + z3.exe -p + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. + {!get_param_value} *) + val update_param_value : context -> string -> string -> unit + + (** Get a configuration parameter. + + Returns None if the parameter value does not exist. + {!update_param_value} *) + val get_param_value : context -> string -> string option + + (** Selects the format used for pretty-printing expressions. + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) + val set_print_mode : context -> Z3enums.ast_print_mode -> unit end (** General Expressions (terms) *) @@ -737,7 +780,7 @@ sig end (** Functions to manipulate Array expressions *) -module Array_ : +module Array : sig (** Create a new array sort. *) val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort @@ -790,7 +833,7 @@ sig The node a must have an array sort [domain -> range], and i must have the sort domain. The sort of the result is range. - {!Array_.mk_sort} + {!Array.mk_sort} {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -806,7 +849,7 @@ sig on all indices except for i, where it maps to v (and the select of a with respect to i may be a different value). - {!Array_.mk_sort} + {!Array.mk_sort} {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr @@ -814,7 +857,7 @@ sig The resulting term is an array, such that a selecton an arbitrary index produces the value v. - {!Array_.mk_sort} + {!Array.mk_sort} {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr @@ -823,7 +866,7 @@ sig Eeach element of args must be of an array sort [domain_i -> range_i]. The function declaration f must have type range_1 .. range_n -> range. v must have sort range. The sort of the result is [domain_i -> range]. - {!Array_.mk_sort} + {!Array.mk_sort} {!mk_select} {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr @@ -1069,7 +1112,7 @@ sig end (** Functions to manipulate List expressions *) -module List_ : +module List : sig (** Create a new list sort. *) val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort @@ -2824,50 +2867,6 @@ sig val mk_fixedpoint : context -> fixedpoint end -(** Global and context options - - Note: This module contains functions that set parameters/options for context - objects as well as functions that set options that are used globally, across - contexts.*) -module Options : -sig - (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - {!get_param_value} *) - val update_param_value : context -> string -> string -> unit - - (** Get a configuration parameter. - - Returns None if the parameter value does not exist. - {!update_param_value} *) - val get_param_value : context -> string -> string option - - (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) - val set_print_mode : context -> Z3enums.ast_print_mode -> unit - - (** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) - val toggle_warning_messages : bool -> unit -end - (** Functions for handling SMT and SMT2 expressions and files *) module SMT : sig @@ -2954,4 +2953,11 @@ val get_global_param : string -> string option This command will not affect already created objects (such as tactics and solvers) {!set_global_param} *) + val global_param_reset_all : unit + + (** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) + val toggle_warning_messages : bool -> unit From b81bae76b2ae554e4521cf65c5b71b4e3cfc0b58 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Jun 2013 19:12:00 +0100 Subject: [PATCH 434/646] ML API: refactoring Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 74 +++++++++++------------------ src/api/ml/z3.mli | 115 +++++++++++++++++++--------------------------- 2 files changed, 73 insertions(+), 116 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4a8fbaa0a..081433f1f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -7,6 +7,8 @@ open Z3enums +exception Error = Z3native.Exception + (* Some helpers. *) let null = Z3native.mk_null() let is_null o = (Z3native.is_null o) @@ -283,7 +285,7 @@ struct Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) end - let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) + let hash ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) @@ -304,7 +306,7 @@ struct let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - let ( = ) ( a : ast ) ( b : ast ) = (a == b) || + let equal ( a : ast ) ( b : ast ) = (a == b) || if (z3obj_gnc a) != (z3obj_gnc b) then false else @@ -314,8 +316,6 @@ struct if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - - let ( < ) (a : ast) (b : ast) = (compare a b) let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then @@ -361,7 +361,7 @@ struct let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) - let ( = ) : sort -> sort -> bool = fun a b -> + let equal : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then false @@ -424,7 +424,7 @@ sig val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl val mk_const_decl_s : context -> string -> Sort.sort -> func_decl val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - val ( = ) : func_decl -> func_decl -> bool + val equal : func_decl -> func_decl -> bool val to_string : func_decl -> string val get_id : func_decl -> int val get_arity : func_decl -> int @@ -498,7 +498,7 @@ end = struct let get_float ( x : parameter ) = match x with | P_Dbl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a double") + | _ -> raise (Z3native.Exception "parameter is not a float") let get_symbol ( x : parameter ) = match x with @@ -545,7 +545,7 @@ end = struct create_pdr ctx prefix [] range - let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || + let equal ( a : func_decl ) ( b : func_decl ) = (a == b) || if (gnc a) != (gnc b) then false else @@ -605,12 +605,8 @@ sig end val add_bool : params -> Symbol.symbol -> bool -> unit val add_int : params -> Symbol.symbol -> int -> unit - val add_double : params -> Symbol.symbol -> float -> unit + val add_float : params -> Symbol.symbol -> float -> unit val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - val add_s_bool : params -> string -> bool -> unit - val add_s_int : params -> string -> int -> unit - val add_s_double : params -> string -> float -> unit - val add_s_symbol : params -> string -> Symbol.symbol -> unit val mk_params : context -> params val to_string : params -> string end = struct @@ -650,24 +646,12 @@ end = struct let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = + let add_float ( x : params ) ( name : Symbol.symbol ) ( value : float ) = Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = - add_bool x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = - add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - let mk_params ( ctx : context ) = let res : params = { m_ctx = ctx ; m_n_obj = null ; @@ -734,8 +718,6 @@ sig val is_xor : expr -> bool val is_not : expr -> bool val is_implies : expr -> bool - val is_label : expr -> bool - val is_label_lit : expr -> bool val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr @@ -857,8 +839,6 @@ end = struct let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = @@ -1530,20 +1510,20 @@ struct let mk_real2int ( ctx : context ) ( t : expr ) = (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (Expr.gno t))) - end - module AlgebraicNumber = - struct - let to_upper ( x : expr ) ( precision : int ) = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) - - let to_lower ( x : expr ) precision = - expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) - - let to_decimal_string ( x : expr ) ( precision : int ) = - Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + module AlgebraicNumber = + struct + let to_upper ( x : expr ) ( precision : int ) = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_upper (Expr.gnc x) (Expr.gno x) precision) + + let to_lower ( x : expr ) precision = + expr_of_ptr (Expr.gc x) (Z3native.get_algebraic_number_lower (Expr.gnc x) (Expr.gno x) precision) + + let to_decimal_string ( x : expr ) ( precision : int ) = + Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision + + let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + end end let is_int ( x : expr ) = @@ -2052,13 +2032,11 @@ struct let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in (mk_list f n_funcs) @ (mk_list g n_consts) - - exception ModelEvaluationFailedException of string - + let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then - raise (ModelEvaluationFailedException "evaluation failed") + None else expr_of_ptr (z3obj_gc x) v @@ -2353,7 +2331,7 @@ struct if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_float_value (z3obj_gnc x) (z3obj_gno x) i)) ) in mk_list f n diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 1c4c4e922..570ff8717 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -5,6 +5,11 @@ @author CM Wintersteiger (cwinter) 2012-12-17 *) +(** General Z3 exceptions + + Many functions in this API may throw an exception; if they do, it is this one.*) +exception Error + (** Context objects. Most interactions with Z3 are interpreted in some context; many users will only @@ -188,7 +193,7 @@ sig (** The AST's hash code. @return A hash code *) - val get_hash_code : ast -> int + val hash : ast -> int (** A unique identifier for the AST (unique among all ASTs). *) val get_id : ast -> int @@ -220,15 +225,12 @@ sig (** Comparison operator. @return True if the two ast's are from the same context and represent the same sort; false otherwise. *) - val ( = ) : ast -> ast -> bool + val equal : ast -> ast -> bool (** Object Comparison. @return Negative if the first ast should be sorted before the second, positive if after else zero. *) val compare : ast -> ast -> int - (** Operator < *) - val ( < ) : ast -> ast -> int - (** Translates (copies) the AST to another context. @return A copy of the AST which is associated with the other context. *) val translate : ast -> context -> ast @@ -263,7 +265,7 @@ sig (** Comparison operator. @return True if the two sorts are from the same context and represent the same sort; false otherwise. *) - val ( = ) : sort -> sort -> bool + val equal : sort -> sort -> bool (** Returns a unique identifier for the sort. *) val get_id : sort -> int @@ -310,7 +312,7 @@ sig (** The int value of the parameter.*) val get_int : parameter -> int - (** The double value of the parameter.*) + (** The float value of the parameter.*) val get_float : parameter -> float (** The Symbol.Symbol value of the parameter.*) @@ -351,7 +353,7 @@ sig (** Comparison operator. @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) - val ( = ) : func_decl -> func_decl -> bool + val equal : func_decl -> func_decl -> bool (** A string representations of the function declaration. *) val to_string : func_decl -> string @@ -423,23 +425,11 @@ sig val add_int : params -> Symbol.symbol -> int -> unit (** Adds a parameter setting. *) - val add_double : params -> Symbol.symbol -> float -> unit + val add_float : params -> Symbol.symbol -> float -> unit (** Adds a parameter setting. *) val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - (** Adds a parameter setting. *) - val add_s_bool : params -> string -> bool -> unit - - (** Adds a parameter setting. *) - val add_s_int : params -> string -> int -> unit - - (** Adds a parameter setting. *) - val add_s_double : params -> string -> float -> unit - - (** Adds a parameter setting. *) - val add_s_symbol : params -> string -> Symbol.symbol -> unit - (** Creates a new parameter set *) val mk_params : context -> params @@ -583,16 +573,7 @@ sig (** Indicates whether the term is an implication *) val is_implies : Expr.expr -> bool - - (** Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) - val is_label : Expr.expr -> bool - - (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) - val is_label_lit : Expr.expr -> bool - + (** Indicates whether the term is a binary equivalence modulo namings. This binary predicate is used in proof terms. It captures equisatisfiability and equivalence modulo renamings. *) @@ -1261,29 +1242,29 @@ sig The semantics of this function follows the SMT-LIB standard for the function to_int. The argument must be of real sort. *) val mk_real2int : context -> Expr.expr -> Expr.expr - end - - (** Algebraic Numbers *) - module AlgebraicNumber : - sig - (** Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_upper : Expr.expr -> int -> Expr.expr - - (** Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_lower : Expr.expr -> int -> Expr.expr - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as the int argument provided.*) - val to_decimal_string : Expr.expr -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string + + (** Algebraic Numbers *) + module AlgebraicNumber : + sig + (** Return a upper bound for a given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_upper : Expr.expr -> int -> Expr.expr + + (** Return a lower bound for the given real algebraic number. + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) + val to_lower : Expr.expr -> int -> Expr.expr + + (** Returns a string representation in decimal notation. + The result has at most as many decimal places as the int argument provided.*) + val to_decimal_string : Expr.expr -> int -> string + + (** Returns a string representation of the numeral. *) + val to_string : Expr.expr -> string + end end (** Indicates whether the term is of integer sort. *) @@ -2389,19 +2370,16 @@ sig (** All symbols that have an interpretation in the model. *) val get_decls : model -> FuncDecl.func_decl list - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - (** Evaluates an expression in the current model. This function may fail if the argument contains quantifiers, is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. In this case a ModelEvaluationFailedException is thrown. *) - val eval : model -> Expr.expr -> bool -> Expr.expr + val eval : model -> Expr.expr -> bool -> Expr.expr option (** Alias for eval. *) - val evaluate : model -> Expr.expr -> bool -> Expr.expr + val evaluate : model -> Expr.expr -> bool -> Expr.expr option (** The number of uninterpreted sorts that the model has an interpretation for. *) val get_num_sorts : model -> int @@ -2438,7 +2416,7 @@ sig type probe (** Execute the probe over the goal. - A probe always produce a double value. + A probe always produce a float value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float @@ -2637,7 +2615,7 @@ sig (** True if the entry is uint-valued. *) val is_int : statistics_entry -> bool - (** True if the entry is double-valued. *) + (** True if the entry is float-valued. *) val is_float : statistics_entry -> bool (** The string representation of the the entry's value. *) @@ -2954,10 +2932,11 @@ val get_global_param : string -> string option {!set_global_param} *) -val global_param_reset_all : unit - - (** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) - val toggle_warning_messages : bool -> unit +val global_param_reset_all : unit -> unit + +(** Enable/disable printing of warning messages to the console. + + Note that this function is static and effects the behaviour of + all contexts globally. *) +val toggle_warning_messages : bool -> unit + From e40b69d97f2f75477c671cbb7551f3f7272ff224 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 4 Jun 2013 16:46:47 +0100 Subject: [PATCH 435/646] ML API: removing rich layer for now. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3_rich.ml | 3399 ---------------------------------------- src/api/ml/z3_rich.mli | 3071 ------------------------------------ 2 files changed, 6470 deletions(-) delete mode 100644 src/api/ml/z3_rich.ml delete mode 100644 src/api/ml/z3_rich.mli diff --git a/src/api/ml/z3_rich.ml b/src/api/ml/z3_rich.ml deleted file mode 100644 index 0c2f95b6b..000000000 --- a/src/api/ml/z3_rich.ml +++ /dev/null @@ -1,3399 +0,0 @@ -\(** - The Z3 ML/Ocaml Interface. - - Copyright (C) 2012 Microsoft Corporation - @author CM Wintersteiger (cwinter) 2012-12-17 -*) - -open Z3enums - -(* Some helpers. *) -let null = Z3native.mk_null() -let is_null o = (Z3native.is_null o) - -(* Internal types *) -type z3_native_context = { m_n_ctx : Z3native.z3_context; m_n_obj_cnt: int; } -type context = z3_native_context - -type z3_native_object = { - m_ctx : context ; - mutable m_n_obj : Z3native.ptr ; - inc_ref : Z3native.z3_context -> Z3native.ptr -> unit; - dec_ref : Z3native.z3_context -> Z3native.ptr -> unit } - - -(** Internal stuff *) -module Internal = -struct - let dispose_context ctx = - if ctx.m_n_obj_cnt == 0 then ( - (Z3native.del_context ctx.m_n_ctx) - ) else ( - Printf.printf "ERROR: NOT DISPOSING CONTEXT (because it still has %d objects alive)\n" ctx.m_n_obj_cnt; - ) - - let create_context settings = - let cfg = Z3native.mk_config in - let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in - (List.iter f settings) ; - let v = Z3native.mk_context_rc cfg in - Z3native.del_config(cfg) ; - Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; - Z3native.set_internal_error_handler v ; - let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in - let f = fun o -> dispose_context o in - Gc.finalise f res; - res - - let context_add1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt + 1) - let context_sub1 ctx = ignore (ctx.m_n_obj_cnt = ctx.m_n_obj_cnt - 1) - let context_gno ctx = ctx.m_n_ctx - - - let z3obj_gc o = o.m_ctx - let z3obj_gnc o = (context_gno o.m_ctx) - - let z3obj_gno o = o.m_n_obj - let z3obj_sno o ctx no = - (context_add1 ctx) ; - o.inc_ref (context_gno ctx) no ; - ( - if not (is_null o.m_n_obj) then - o.dec_ref (context_gno ctx) o.m_n_obj ; - (context_sub1 ctx) - ) ; - o.m_n_obj <- no - - let z3obj_dispose o = - if not (is_null o.m_n_obj) then - ( - o.dec_ref (z3obj_gnc o) o.m_n_obj ; - (context_sub1 (z3obj_gc o)) - ) ; - o.m_n_obj <- null - - let z3obj_create o = - let f = fun o -> (z3obj_dispose o) in - Gc.finalise f o - - let z3obj_nil_ref x y = () - - let z3_native_object_of_ast_ptr : context -> Z3native.ptr -> z3_native_object = fun ctx no -> - let res : z3_native_object = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res -end - -open Internal - -module Log = -struct - let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE) - let close = Z3native.close_log - let append s = Z3native.append_log s -end - - -module Version = -struct - let major = let (x, _, _, _) = Z3native.get_version in x - let minor = let (_, x, _, _) = Z3native.get_version in x - let build = let (_, _, x, _) = Z3native.get_version in x - let revision = let (_, _, _, x) = Z3native.get_version in x - let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in - string_of_int mj ^ "." ^ - string_of_int mn ^ "." ^ - string_of_int bld ^ "." ^ - string_of_int rev ^ "." -end - - -let mk_list ( f : int -> 'a ) ( n : int ) = - let rec mk_list' ( f : int -> 'a ) ( i : int ) ( n : int ) ( tail : 'a list ) : 'a list = - if (i >= n) then - tail - else - (mk_list' f (i+1) n ((f i) :: tail)) - in - mk_list' f 0 n [] - -let list_of_array ( x : _ array ) = - let f i = (Array.get x i) in - mk_list f (Array.length x) - -let mk_context ( cfg : ( string * string ) list ) = - create_context cfg - - -module Symbol = -struct - (* Symbol types *) - type int_symbol = z3_native_object - type string_symbol = z3_native_object - - type symbol = - | S_Int of int_symbol - | S_Str of string_symbol - - - let create_i ( ctx : context ) ( no : Z3native.ptr ) = - let res : int_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create_s ( ctx : context ) ( no : Z3native.ptr ) = - let res : string_symbol = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let create ( ctx : context ) ( no : Z3native.ptr ) = - match (symbol_kind_of_int (Z3native.get_symbol_kind (context_gno ctx) no)) with - | INT_SYMBOL -> S_Int (create_i ctx no) - | STRING_SYMBOL -> S_Str (create_s ctx no) - - let gc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gc n) - | S_Str(n) -> (z3obj_gc n) - - let gnc ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gnc n) - | S_Str(n) -> (z3obj_gnc n) - - let gno ( x : symbol ) = - match x with - | S_Int(n) -> (z3obj_gno n) - | S_Str(n) -> (z3obj_gno n) - - let symbol_lton ( a : symbol list ) = - let f ( e : symbol ) = (gno e) in - Array.of_list (List.map f a) - - let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) - let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL - let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL - let get_int (o : int_symbol) = Z3native.get_symbol_int (z3obj_gnc o) (z3obj_gno o) - let get_string (o : string_symbol) = Z3native.get_symbol_string (z3obj_gnc o) (z3obj_gno o) - let to_string ( o : symbol ) = - match (kind o) with - | INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int (gnc o) (gno o))) - | STRING_SYMBOL -> (Z3native.get_symbol_string (gnc o) (gno o)) - - let mk_int ( ctx : context ) ( i : int ) = - S_Int (create_i ctx (Z3native.mk_int_symbol (context_gno ctx) i)) - - let mk_string ( ctx : context ) ( s : string ) = - S_Str (create_s ctx (Z3native.mk_string_symbol (context_gno ctx) s)) - - let mk_ints ( ctx : context ) ( names : int list ) = - let f elem = mk_int ( ctx : context ) elem in - (List.map f names) - - let mk_strings ( ctx : context ) ( names : string list ) = - let f elem = mk_string ( ctx : context ) elem in - (List.map f names) -end - - -module AST = -struct - type ast = z3_native_object - - let context_of_ast ( x : ast ) = (z3obj_gc x) - let nc_of_ast ( x : ast ) = (z3obj_gnc x) - let ptr_of_ast ( x : ast ) = (z3obj_gno x) - - let rec ast_of_ptr : context -> Z3native.ptr -> ast = fun ctx no -> - match (ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) with - | FUNC_DECL_AST - | SORT_AST - | QUANTIFIER_AST - | APP_AST - | NUMERAL_AST - | VAR_AST -> z3_native_object_of_ast_ptr ctx no - | UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown") - - module ASTVector = - struct - type ast_vector = z3_native_object - - let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_vector = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_vector_inc_ref ; - dec_ref = Z3native.ast_vector_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_size ( x : ast_vector ) = - Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) - - let get ( x : ast_vector ) ( i : int ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_vector_get (z3obj_gnc x) (z3obj_gno x) i) - - let set ( x : ast_vector ) ( i : int ) ( value : ast ) = - Z3native.ast_vector_set (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno value) - - let resize ( x : ast_vector ) ( new_size : int ) = - Z3native.ast_vector_resize (z3obj_gnc x) (z3obj_gno x) new_size - - let push ( x : ast_vector ) ( a : ast ) = - Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) - - let translate ( x : ast_vector ) ( to_ctx : context ) = - ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let to_string ( x : ast_vector ) = - Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) - end - - module ASTMap = - struct - type ast_map = z3_native_object - - let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : ast_map = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.ast_map_inc_ref ; - dec_ref = Z3native.ast_map_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let contains ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_contains (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let find ( x : ast_map ) ( key : ast ) = - ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - - let insert ( x : ast_map ) ( key : ast ) ( value : ast) = - Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) - - let erase ( x : ast_map ) ( key : ast ) = - Z3native.ast_map_erase (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) - - let reset ( x : ast_map ) = - Z3native.ast_map_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : ast_map ) = - Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) - - let get_keys ( x : ast_map ) = - let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in - let f i = (ASTVector.get av i) in - mk_list f (ASTVector.get_size av) - - let to_string ( x : ast_map ) = - Z3native.ast_map_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let get_hash_code ( x : ast ) = Z3native.get_ast_hash (z3obj_gnc x) (z3obj_gno x) - let get_id ( x : ast ) = Z3native.get_ast_id (z3obj_gnc x) (z3obj_gno x) - let get_ast_kind ( x : ast ) = (ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc x) (z3obj_gno x))) - - let is_expr ( x : ast ) = - match get_ast_kind ( x : ast ) with - | APP_AST - | NUMERAL_AST - | QUANTIFIER_AST - | VAR_AST -> true - | _ -> false - - let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST - let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST - let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST - let is_func_decl ( x : ast ) = (get_ast_kind x) == FUNC_DECL_AST - - let to_string ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - let to_sexpr ( x : ast ) = Z3native.ast_to_string (z3obj_gnc x) (z3obj_gno x) - - - let ( = ) ( a : ast ) ( b : ast ) = (a == b) || - if (z3obj_gnc a) != (z3obj_gnc b) then - false - else - Z3native.is_eq_ast (z3obj_gnc a) (z3obj_gno a) (z3obj_gno b) - - let compare a b = - if (get_id a) < (get_id b) then -1 else - if (get_id a) > (get_id b) then 1 else - 0 - - let ( < ) (a : ast) (b : ast) = (compare a b) - - let translate ( x : ast ) ( to_ctx : context ) = - if (z3obj_gnc x) == (context_gno to_ctx) then - x - else - ast_of_ptr to_ctx (Z3native.translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let wrap_ast ( ctx : context ) ( ptr : Z3native.ptr ) = ast_of_ptr ctx ptr - let unwrap_ast ( x : ast ) = (z3obj_gno x) -end - -open AST - - -module Sort = -struct - type sort = Sort of AST.ast - type uninterpreted_sort = UninterpretedSort of sort - - let sort_of_ptr : context -> Z3native.ptr -> sort = fun ctx no -> - let q = (z3_native_object_of_ast_ptr ctx no) in - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.SORT_AST) then - raise (Z3native.Exception "Invalid coercion") - else - match (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) no)) with - | ARRAY_SORT - | BOOL_SORT - | BV_SORT - | DATATYPE_SORT - | INT_SORT - | REAL_SORT - | UNINTERPRETED_SORT - | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) - | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") - - let ast_of_sort s = match s with Sort(x) -> x - let sort_of_uninterpreted_sort s = match s with UninterpretedSort(x) -> x - - let uninterpreted_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.UNINTERPRETED_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - UninterpretedSort(s) - - let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) - let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) - let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) - - let sort_lton ( a : sort list ) = - let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let ( = ) : sort -> sort -> bool = fun a b -> - (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_sort (gnc a) (gno a) (gno b)) - - - let get_id ( x : sort ) = Z3native.get_sort_id (gnc x) (gno x) - let get_sort_kind ( x : sort ) = (sort_kind_of_int (Z3native.get_sort_kind (gnc x) (gno x))) - let get_name ( x : sort ) = (Symbol.create (gc x) (Z3native.get_sort_name (gnc x) (gno x))) - let to_string ( x : sort ) = Z3native.sort_to_string (gnc x) (gno x) - - let mk_uninterpreted ( ctx : context ) ( s : Symbol.symbol ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_uninterpreted_sort (context_gno ctx) (Symbol.gno s))) ; - (z3obj_create res) ; - UninterpretedSort(Sort(res)) - - let mk_uninterpreted_s ( ctx : context ) ( s : string ) = - mk_uninterpreted ctx (Symbol.mk_string ( ctx : context ) s) -end - -open Sort - - -module rec FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - val func_decl_of_ptr : context -> Z3native.ptr -> func_decl - val gc : func_decl -> context - val gnc : func_decl -> Z3native.ptr - val gno : func_decl -> Z3native.ptr - module Parameter : - sig - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - val get_kind : parameter -> Z3enums.parameter_kind - val get_int : parameter -> int - val get_float : parameter -> float - val get_symbol : parameter -> Symbol.symbol - val get_sort : parameter -> Sort.sort - val get_ast : parameter -> AST.ast - val get_func_decl : parameter -> func_decl - val get_rational : parameter -> string - end - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - val ( = ) : func_decl -> func_decl -> bool - val to_string : func_decl -> string - val get_id : func_decl -> int - val get_arity : func_decl -> int - val get_domain_size : func_decl -> int - val get_domain : func_decl -> Sort.sort list - val get_range : func_decl -> Sort.sort - val get_decl_kind : func_decl -> Z3enums.decl_kind - val get_name : func_decl -> Symbol.symbol - val get_num_parameters : func_decl -> int - val get_parameters : func_decl -> Parameter.parameter list - val apply : func_decl -> Expr.expr list -> Expr.expr -end = struct - type func_decl = FuncDecl of AST.ast - - let func_decl_of_ptr : context -> Z3native.ptr -> func_decl = fun ctx no -> - if ((Z3enums.ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no)) != Z3enums.FUNC_DECL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - FuncDecl(z3_native_object_of_ast_ptr ctx no) - - let ast_of_func_decl f = match f with FuncDecl(x) -> x - - let create_ndr ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_func_decl (context_gno ctx) (Symbol.gno name) (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let create_pdr ( ctx : context) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - let res = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.inc_ref ; - dec_ref = Z3native.dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fresh_func_decl (context_gno ctx) prefix (List.length domain) (sort_lton domain) (Sort.gno range))) ; - (z3obj_create res) ; - FuncDecl(res) - - let gc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gc a) - let gnc ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gnc a) - let gno ( x : func_decl ) = match x with FuncDecl(a) -> (z3obj_gno a) - - module Parameter = - struct - type parameter = - | P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - let get_kind ( x : parameter ) = - (match x with - | P_Int(_) -> PARAMETER_INT - | P_Dbl(_) -> PARAMETER_DOUBLE - | P_Sym(_) -> PARAMETER_SYMBOL - | P_Srt(_) -> PARAMETER_SORT - | P_Ast(_) -> PARAMETER_AST - | P_Fdl(_) -> PARAMETER_FUNC_DECL - | P_Rat(_) -> PARAMETER_RATIONAL) - - let get_int ( x : parameter ) = - match x with - | P_Int(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an int") - - let get_float ( x : parameter ) = - match x with - | P_Dbl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a double") - - let get_symbol ( x : parameter ) = - match x with - | P_Sym(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a symbol") - - let get_sort ( x : parameter ) = - match x with - | P_Srt(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a sort") - - let get_ast ( x : parameter ) = - match x with - | P_Ast(x) -> x - | _ -> raise (Z3native.Exception "parameter is not an ast") - - let get_func_decl ( x : parameter ) = - match x with - | P_Fdl(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a func_decl") - - let get_rational ( x : parameter ) = - match x with - | P_Rat(x) -> x - | _ -> raise (Z3native.Exception "parameter is not a rational string") - end - - let mk_func_decl ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort list ) ( range : sort ) = - create_ndr ctx name domain range - - let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort list ) ( range : sort ) = - mk_func_decl ctx (Symbol.mk_string ctx name) domain range - - let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort list ) ( range : sort ) = - create_pdr ctx prefix domain range - - let mk_const_decl ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - create_ndr ctx name [] range - - let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort ) = - create_ndr ctx (Symbol.mk_string ctx name) [] range - - let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort ) = - create_pdr ctx prefix [] range - - - let ( = ) ( a : func_decl ) ( b : func_decl ) = (a == b) || - if (gnc a) != (gnc b) then - false - else - (Z3native.is_eq_func_decl (gnc a) (gno a) (gno b)) - - let to_string ( x : func_decl ) = Z3native.func_decl_to_string (gnc x) (gno x) - - let get_id ( x : func_decl ) = Z3native.get_func_decl_id (gnc x) (gno x) - - let get_arity ( x : func_decl ) = Z3native.get_arity (gnc x) (gno x) - - let get_domain_size ( x : func_decl ) = Z3native.get_domain_size (gnc x) (gno x) - - let get_domain ( x : func_decl ) = - let n = (get_domain_size x) in - let f i = sort_of_ptr (gc x) (Z3native.get_domain (gnc x) (gno x) i) in - mk_list f n - - let get_range ( x : func_decl ) = - sort_of_ptr (gc x) (Z3native.get_range (gnc x) (gno x)) - - let get_decl_kind ( x : func_decl ) = (decl_kind_of_int (Z3native.get_decl_kind (gnc x) (gno x))) - - let get_name ( x : func_decl ) = (Symbol.create (gc x) (Z3native.get_decl_name (gnc x) (gno x))) - - let get_num_parameters ( x : func_decl ) = (Z3native.get_decl_num_parameters (gnc x) (gno x)) - - let get_parameters ( x : func_decl ) = - let n = (get_num_parameters x) in - let f i = (match (parameter_kind_of_int (Z3native.get_decl_parameter_kind (gnc x) (gno x) i)) with - | PARAMETER_INT -> Parameter.P_Int (Z3native.get_decl_int_parameter (gnc x) (gno x) i) - | PARAMETER_DOUBLE -> Parameter.P_Dbl (Z3native.get_decl_double_parameter (gnc x) (gno x) i) - | PARAMETER_SYMBOL-> Parameter.P_Sym (Symbol.create (gc x) (Z3native.get_decl_symbol_parameter (gnc x) (gno x) i)) - | PARAMETER_SORT -> Parameter.P_Srt (sort_of_ptr (gc x) (Z3native.get_decl_sort_parameter (gnc x) (gno x) i)) - | PARAMETER_AST -> Parameter.P_Ast (AST.ast_of_ptr (gc x) (Z3native.get_decl_ast_parameter (gnc x) (gno x) i)) - | PARAMETER_FUNC_DECL -> Parameter.P_Fdl (func_decl_of_ptr (gc x) (Z3native.get_decl_func_decl_parameter (gnc x) (gno x) i)) - | PARAMETER_RATIONAL -> Parameter.P_Rat (Z3native.get_decl_rational_parameter (gnc x) (gno x) i) - ) in - mk_list f n - - let apply ( x : func_decl ) ( args : Expr.expr list ) = Expr.expr_of_func_app (gc x) x args -end - - -and Params : -sig - type params = z3_native_object - module ParamDescrs : - sig - type param_descrs - val param_descrs_of_ptr : context -> Z3native.ptr -> param_descrs - val validate : param_descrs -> params -> unit - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - val get_names : param_descrs -> Symbol.symbol list - val get_size : param_descrs -> int - val to_string : param_descrs -> string - end - val add_bool : params -> Symbol.symbol -> bool -> unit - val add_int : params -> Symbol.symbol -> int -> unit - val add_double : params -> Symbol.symbol -> float -> unit - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - val add_s_bool : params -> string -> bool -> unit - val add_s_int : params -> string -> int -> unit - val add_s_double : params -> string -> float -> unit - val add_s_symbol : params -> string -> Symbol.symbol -> unit - val mk_params : context -> params - val to_string : params -> string -end = struct - type params = z3_native_object - - module ParamDescrs = - struct - type param_descrs = z3_native_object - - let param_descrs_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let res : param_descrs = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.param_descrs_inc_ref ; - dec_ref = Z3native.param_descrs_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let validate ( x : param_descrs ) ( p : params ) = - Z3native.params_validate (z3obj_gnc x) (z3obj_gno p) (z3obj_gno x) - - let get_kind ( x : param_descrs ) ( name : Symbol.symbol ) = - (param_kind_of_int (Z3native.param_descrs_get_kind (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name))) - - let get_names ( x : param_descrs ) = - let n = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) in - let f i = Symbol.create (z3obj_gc x) (Z3native.param_descrs_get_name (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_size ( x : param_descrs ) = Z3native.param_descrs_size (z3obj_gnc x) (z3obj_gno x) - let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let add_bool ( x : params ) ( name : Symbol.symbol ) ( value : bool ) = - Z3native.params_set_bool (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_int ( x : params ) (name : Symbol.symbol ) ( value : int ) = - Z3native.params_set_uint (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_double ( x : params ) ( name : Symbol.symbol ) ( value : float ) = - Z3native.params_set_double (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) value - - let add_symbol ( x : params ) ( name : Symbol.symbol ) ( value : Symbol.symbol ) = - Z3native.params_set_symbol (z3obj_gnc x) (z3obj_gno x) (Symbol.gno name) (Symbol.gno value) - - let add_s_bool ( x : params ) ( name : string ) ( value : bool ) = - add_bool x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_int ( x : params) ( name : string ) ( value : int ) = - add_int x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_double ( x : params ) ( name : string ) ( value : float ) = - add_double x (Symbol.mk_string (z3obj_gc x) name) value - - let add_s_symbol ( x : params ) ( name : string ) ( value : Symbol.symbol ) = - add_symbol x (Symbol.mk_string (z3obj_gc x) name) value - - let mk_params ( ctx : context ) = - let res : params = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.params_inc_ref ; - dec_ref = Z3native.params_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_params (context_gno ctx))) ; - (z3obj_create res) ; - res - - let to_string ( x : params ) = Z3native.params_to_string (z3obj_gnc x) (z3obj_gno x) -end - -(** General expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - val expr_of_ptr : context -> Z3native.ptr -> expr - val gc : expr -> context - val gnc : expr -> Z3native.ptr - val gno : expr -> Z3native.ptr - val expr_lton : expr list -> Z3native.ptr array - val ast_of_expr : expr -> AST.ast - val expr_of_ast : AST.ast -> expr - val expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr - val simplify : expr -> Params.params option -> expr - val get_simplify_help : context -> string - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - val get_func_decl : expr -> FuncDecl.func_decl - val get_bool_value : expr -> Z3enums.lbool - val get_num_args : expr -> int - val get_args : expr -> expr list - val update : expr -> expr list -> expr - val substitute : expr -> expr list -> expr list -> expr - val substitute_one : expr -> expr -> expr -> expr - val substitute_vars : expr -> expr list -> expr - val translate : expr -> context -> expr - val to_string : expr -> string - val is_numeral : expr -> bool - val is_well_sorted : expr -> bool - val get_sort : expr -> Sort.sort - val is_bool : expr -> bool - val is_const : expr -> bool - val is_true : expr -> bool - val is_false : expr -> bool - val is_eq : expr -> bool - val is_distinct : expr -> bool - val is_ite : expr -> bool - val is_and : expr -> bool - val is_or : expr -> bool - val is_iff : expr -> bool - val is_xor : expr -> bool - val is_not : expr -> bool - val is_implies : expr -> bool - val is_label : expr -> bool - val is_label_lit : expr -> bool - val is_oeq : expr -> bool - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - val mk_const_s : context -> string -> Sort.sort -> expr - val mk_const_f : context -> FuncDecl.func_decl -> expr - val mk_fresh_const : context -> string -> Sort.sort -> expr - val mk_app : context -> FuncDecl.func_decl -> expr list -> expr - val mk_numeral_string : context -> string -> Sort.sort -> expr - val mk_numeral_int : context -> int -> Sort.sort -> expr -end = struct - type expr = Expr of AST.ast - - let c_of_expr e = match e with Expr(a) -> (z3obj_gc a) - let nc_of_expr e = match e with Expr(a) -> (z3obj_gnc a) - let ptr_of_expr e = match e with Expr(a) -> (z3obj_gno a) - - let expr_of_ptr : context -> Z3native.ptr -> expr = fun ctx no -> - if ast_kind_of_int (Z3native.get_ast_kind (context_gno ctx) no) == QUANTIFIER_AST then - Expr(z3_native_object_of_ast_ptr ctx no) - else - let s = Z3native.get_sort (context_gno ctx) no in - let sk = (sort_kind_of_int (Z3native.get_sort_kind (context_gno ctx) s)) in - if (Z3native.is_algebraic_number (context_gno ctx) no) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then - Expr(z3_native_object_of_ast_ptr ctx no) - else - raise (Z3native.Exception "Unsupported numeral object") - else - Expr(z3_native_object_of_ast_ptr ctx no) - - let expr_of_ast a = - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.APP_AST && q != VAR_AST && q != QUANTIFIER_AST && q != NUMERAL_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Expr(a) - - let ast_of_expr e = match e with Expr(a) -> a - - let expr_lton ( a : expr list ) = - let f ( e : expr ) = match e with Expr(a) -> (AST.ptr_of_ast a) in - Array.of_list (List.map f a) - - let expr_of_func_app : context -> FuncDecl.func_decl -> expr list -> expr = fun ctx f args -> - match f with FuncDecl.FuncDecl(fa) -> - let o = Z3native.mk_app (context_gno ctx) (AST.ptr_of_ast fa) (List.length args) (expr_lton args) in - expr_of_ptr ctx o - - let simplify ( x : expr ) ( p : Params.params option ) = match p with - | None -> expr_of_ptr (Expr.gc x) (Z3native.simplify (Expr.gnc x) (Expr.gno x)) - | Some pp -> expr_of_ptr (Expr.gc x) (Z3native.simplify_ex (Expr.gnc x) (Expr.gno x) (z3obj_gno pp)) - - let get_simplify_help ( ctx : context ) = - Z3native.simplify_get_help (context_gno ctx) - - let get_simplify_parameter_descrs ( ctx : context ) = - Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (Expr.gnc x) (Expr.gno x)) - - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (Expr.gnc x) (Expr.gno x)) - - let get_num_args ( x : expr ) = Z3native.get_app_num_args (Expr.gnc x) (Expr.gno x) - - let get_args ( x : expr ) = let n = (get_num_args x) in - let f i = expr_of_ptr (Expr.gc x) (Z3native.get_app_arg (Expr.gnc x) (Expr.gno x) i) in - mk_list f n - - let update ( x : expr ) ( args : expr list ) = - if (List.length args <> (get_num_args x)) then - raise (Z3native.Exception "Number of arguments does not match") - else - expr_of_ptr (Expr.gc x) (Z3native.update_term (Expr.gnc x) (Expr.gno x) (List.length args) (expr_lton args)) - - let substitute ( x : expr ) from to_ = - if (List.length from) <> (List.length to_) then - raise (Z3native.Exception "Argument sizes do not match") - else - expr_of_ptr (Expr.gc x) (Z3native.substitute (Expr.gnc x) (Expr.gno x) (List.length from) (expr_lton from) (expr_lton to_)) - - let substitute_one ( x : expr ) from to_ = - substitute ( x : expr ) [ from ] [ to_ ] - - let substitute_vars ( x : expr ) to_ = - expr_of_ptr (Expr.gc x) (Z3native.substitute_vars (Expr.gnc x) (Expr.gno x) (List.length to_) (expr_lton to_)) - - let translate ( x : expr ) to_ctx = - if (Expr.gc x) == to_ctx then - x - else - expr_of_ptr to_ctx (Z3native.translate (Expr.gnc x) (Expr.gno x) (context_gno to_ctx)) - - let to_string ( x : expr ) = Z3native.ast_to_string (Expr.gnc x) (Expr.gno x) - - let is_numeral ( x : expr ) = (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) - - let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (Expr.gnc x) (Expr.gno x) - - let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)) - - let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (Expr.gnc x) - (Z3native.mk_bool_sort (Expr.gnc x)) - (Z3native.get_sort (Expr.gnc x) (Expr.gno x))) - - let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (get_num_args x) == 0 && - (FuncDecl.get_domain_size (get_func_decl x)) == 0 - - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL) - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) - - let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) range - - let mk_const_f ( ctx : context ) ( f : FuncDecl.func_decl ) = Expr.expr_of_func_app ctx f [] - - let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort ) = - expr_of_ptr ctx (Z3native.mk_fresh_const (context_gno ctx) prefix (Sort.gno range)) - - let mk_app ( ctx : context ) ( f : FuncDecl.func_decl ) ( args : expr list ) = expr_of_func_app ctx f args - - let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno ty)) - - let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) -end - -open FuncDecl -open Expr - -module Boolean = -struct - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - let bool_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let a = (AST.ast_of_ptr ctx no) in - BoolExpr(Expr.Expr(a)) - - let bool_expr_of_expr e = - match e with Expr.Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolExpr(e) - - let bool_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - BoolSort(sort_of_ptr ctx no) - - let sort_of_bool_sort s = match s with BoolSort(x) -> x - - let bool_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BOOL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BoolSort(s) - - let expr_of_bool_expr e = match e with BoolExpr(x) -> x - - let gc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.c_of_expr e) - let gnc ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.nc_of_expr e) - let gno ( x : bool_expr ) = match x with BoolExpr(e) -> (Expr.ptr_of_expr e) - - let mk_sort ( ctx : context ) = - BoolSort(sort_of_ptr ctx (Z3native.mk_bool_sort (context_gno ctx))) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - let s = (match (mk_sort ctx) with BoolSort(q) -> q) in - BoolExpr(Expr.mk_const ctx name s) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_true ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_true (context_gno ctx)) - - let mk_false ( ctx : context ) = - bool_expr_of_ptr ctx (Z3native.mk_false (context_gno ctx)) - - let mk_val ( ctx : context ) ( value : bool ) = - if value then mk_true ctx else mk_false ctx - - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - bool_expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) - - let mk_distinct ( ctx : context ) ( args : expr list ) = - bool_expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_not ( ctx : context ) ( a : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) - - let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_ite (context_gno ctx) (gno t1) (gno t2) (gno t3)) - - let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_iff (context_gno ctx) (gno t1) (gno t2)) - - let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_implies (context_gno ctx) (gno t1) (gno t2)) - - let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) = - bool_expr_of_ptr ctx (Z3native.mk_xor (context_gno ctx) (gno t1) (gno t2)) - - let mk_and ( ctx : context ) ( args : bool_expr list ) = - let f x = (Expr.gno (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_and (context_gno ctx) (List.length args) (Array.of_list (List.map f args))) - - let mk_or ( ctx : context ) ( args : bool_expr list ) = - let f x = (Expr.gno (expr_of_bool_expr x)) in - bool_expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) -end - - -module Quantifier = -struct - type quantifier = Quantifier of expr - - let expr_of_quantifier e = match e with Quantifier(x) -> x - - let quantifier_of_expr e = - match e with Expr.Expr(a) -> - let q = (Z3enums.ast_kind_of_int (Z3native.get_ast_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.QUANTIFIER_AST) then - raise (Z3native.Exception "Invalid coercion") - else - Quantifier(e) - - let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) - let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) - let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) - - module Pattern = - struct - type pattern = Pattern of ast - - let ast_of_pattern e = match e with Pattern(x) -> x - - let pattern_of_ast a = - (* CMW: Unchecked ok? *) - Pattern(a) - - let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) - let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) - let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) - - let get_num_terms ( x : pattern ) = - Z3native.get_pattern_num_terms (gnc x) (gno x) - - let get_terms ( x : pattern ) = - let n = (get_num_terms x) in - let f i = (expr_of_ptr (gc x) (Z3native.get_pattern (gnc x) (gno x) i)) in - mk_list f n - - let to_string ( x : pattern ) = Z3native.pattern_to_string (gnc x) (gno x) - end - - let get_index ( x : expr ) = - if not (AST.is_var (match x with Expr.Expr(a) -> a)) then - raise (Z3native.Exception "Term is not a bound variable.") - else - Z3native.get_index_value (Expr.gnc x) (Expr.gno x) - - let is_universal ( x : quantifier ) = - Z3native.is_quantifier_forall (gnc x) (gno x) - - let is_existential ( x : quantifier ) = not (is_universal x) - - let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight (gnc x) (gno x) - - let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns (gnc x) (gno x) - - let get_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns (gnc x) (gno x) - - let get_no_patterns ( x : quantifier ) = - let n = (get_num_patterns x) in - let f i = Pattern.Pattern (z3_native_object_of_ast_ptr (gc x) (Z3native.get_quantifier_no_pattern_ast (gnc x) (gno x) i)) in - mk_list f n - - let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound (gnc x) (gno x) - - let get_bound_variable_names ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (Symbol.create (gc x) (Z3native.get_quantifier_bound_name (gnc x) (gno x) i)) in - mk_list f n - - let get_bound_variable_sorts ( x : quantifier ) = - let n = (get_num_bound x) in - let f i = (sort_of_ptr (gc x) (Z3native.get_quantifier_bound_sort (gnc x) (gno x) i)) in - mk_list f n - - let get_body ( x : quantifier ) = - Boolean.bool_expr_of_ptr (gc x) (Z3native.get_quantifier_body (gnc x) (gno x)) - - let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) = - expr_of_ptr ctx (Z3native.mk_bound (context_gno ctx) index (Sort.gno ty)) - - let mk_pattern ( ctx : context ) ( terms : expr list ) = - if (List.length terms) == 0 then - raise (Z3native.Exception "Cannot create a pattern from zero terms") - else - Pattern.Pattern(z3_native_object_of_ast_ptr ctx (Z3native.mk_pattern (context_gno ctx) (List.length terms) (expr_lton terms))) - - let mk_forall ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_forall_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) true - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_exists ( ctx : context ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (List.length sorts) != (List.length names) then - raise (Z3native.Exception "Number of sorts does not match number of names") - else if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (List.length sorts) (sort_lton sorts) - (Symbol.symbol_lton names) - (Expr.gno body))) - - let mk_exists_const ( ctx : context ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if ((List.length nopatterns) == 0 && quantifier_id == None && skolem_id == None) then - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (Expr.gno body))) - else - Quantifier(expr_of_ptr ctx (Z3native.mk_quantifier_const_ex (context_gno ctx) false - (match weight with | None -> 1 | Some(x) -> x) - (match quantifier_id with | None -> null | Some(x) -> (Symbol.gno x)) - (match skolem_id with | None -> null | Some(x) -> (Symbol.gno x)) - (List.length bound_constants) (expr_lton bound_constants) - (List.length patterns) (let f x = (AST.ptr_of_ast (Pattern.ast_of_pattern x)) in (Array.of_list (List.map f patterns))) - (List.length nopatterns) (expr_lton nopatterns) - (Expr.gno body))) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort list ) ( names : Symbol.symbol list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - (mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - else - (mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id) - - let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr list ) ( body : expr ) ( weight : int option ) ( patterns : Pattern.pattern list ) ( nopatterns : expr list ) ( quantifier_id : Symbol.symbol option ) ( skolem_id : Symbol.symbol option ) = - if (universal) then - mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id - else - mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id -end - - -module Array_ = -struct - type array_sort = ArraySort of sort - type array_expr = ArrayExpr of expr - - let array_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let e = (expr_of_ptr ctx no) in - ArrayExpr(e) - - let array_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - ArraySort(s) - - let sort_of_array_sort s = match s with ArraySort(x) -> x - - let array_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArraySort(s) - - let array_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.ARRAY_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArrayExpr(e) - - let expr_of_array_expr e = match e with ArrayExpr(x) -> x - - let sgc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : array_sort ) = match (x) with ArraySort(Sort(s)) -> (z3obj_gno s) - - let egc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gc e) - let egnc ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gnc e) - let egno ( x : array_expr ) = match (x) with ArrayExpr(Expr(e)) -> (z3obj_gno e) - - let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = - array_sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) - let is_array ( x : expr ) = - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) - - let get_domain ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_domain (sgnc x) (sgno x)) - let get_range ( x : array_sort ) = Sort.sort_of_ptr (sgc x) (Z3native.get_array_sort_range (sgnc x) (sgno x)) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( domain : sort ) ( range : sort ) = - ArrayExpr(Expr.mk_const ctx name (match (mk_sort ctx domain range) with ArraySort(s) -> s)) - - let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) = - mk_const ctx (Symbol.mk_string ctx name) domain range - - let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) = - array_expr_of_ptr ctx (Z3native.mk_select (context_gno ctx) (egno a) (Expr.gno i)) - - let mk_store ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_store (context_gno ctx) (egno a) (Expr.gno i) (Expr.gno v)) - - let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) = - array_expr_of_ptr ctx (Z3native.mk_const_array (context_gno ctx) (Sort.gno domain) (Expr.gno v)) - - let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr list ) = - let m x = (Expr.gno (expr_of_array_expr x)) in - array_expr_of_ptr ctx (Z3native.mk_map (context_gno ctx) (FuncDecl.gno f) (List.length args) (Array.of_list (List.map m args))) - - let mk_term_array ( ctx : context ) ( arg : array_expr ) = - array_expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (egno arg)) -end - - -module Set = -struct - type set_sort = SetSort of sort - - let set_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - SetSort(s) - - let sort_of_set_sort s = match s with SetSort(x) -> x - - let mk_sort ( ctx : context ) ( ty : sort ) = - set_sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) - - - let mk_empty ( ctx : context ) ( domain : sort ) = - (expr_of_ptr ctx (Z3native.mk_empty_set (context_gno ctx) (Sort.gno domain))) - - let mk_full ( ctx : context ) ( domain : sort ) = - expr_of_ptr ctx (Z3native.mk_full_set (context_gno ctx) (Sort.gno domain)) - - let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_add (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) = - expr_of_ptr ctx (Z3native.mk_set_del (context_gno ctx) (Expr.gno set) (Expr.gno element)) - - let mk_union ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_union (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_intersection ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_set_intersect (context_gno ctx) (List.length args) (expr_lton args)) - - let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_difference (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) - - let mk_complement ( ctx : context ) ( arg : expr ) = - expr_of_ptr ctx (Z3native.mk_set_complement (context_gno ctx) (Expr.gno arg)) - - let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) = - expr_of_ptr ctx (Z3native.mk_set_member (context_gno ctx) (Expr.gno elem) (Expr.gno set)) - - let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr ) = - expr_of_ptr ctx (Z3native.mk_set_subset (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2)) - -end - - -module FiniteDomain = -struct - type finite_domain_sort = FiniteDomainSort of sort - - let sort_of_finite_domain_sort s = match s with FiniteDomainSort(x) -> x - - let finite_domain_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.FINITE_DOMAIN_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - FiniteDomainSort(s) - - let gc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : finite_domain_sort ) = match (x) with FiniteDomainSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - let s = (sort_of_ptr ctx (Z3native.mk_finite_domain_sort (context_gno ctx) (Symbol.gno name) size)) in - FiniteDomainSort(s) - - let mk_sort_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_sort ctx (Symbol.mk_string ctx name) size - - - let is_finite_domain ( x : expr ) = - let nc = (Expr.gnc x) in - (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) - - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) - - let get_size ( x : finite_domain_sort ) = - let (r, v) = (Z3native.get_finite_domain_sort_size (gnc x) (gno x)) in - if r then v - else raise (Z3native.Exception "Conversion failed.") -end - - -module Relation = -struct - type relation_sort = RelationSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - RelationSort(s) - - let sort_of_relation_sort s = match s with RelationSort(x) -> x - - let relation_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.RELATION_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RelationSort(s) - - let gc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gc s) - let gnc ( x : relation_sort ) = match (x) with RelationSort(Sort(s)) -> (z3obj_gnc s) - let gno ( x : relation_sort ) = match (x) with RelationSort(Sort(s))-> (z3obj_gno s) - - - let is_relation ( x : expr ) = - let nc = (Expr.gnc x) in - ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && - (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) - - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) - - let get_arity ( x : relation_sort ) = Z3native.get_relation_arity (gnc x) (gno x) - - let get_column_sorts ( x : relation_sort ) = - let n = get_arity x in - let f i = (sort_of_ptr (gc x) (Z3native.get_relation_column (gnc x) (gno x) i)) in - mk_list f n - -end - - -module Datatype = -struct - type datatype_sort = DatatypeSort of sort - type datatype_expr = DatatypeExpr of expr - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - DatatypeSort(s) - - let sort_of_datatype_sort s = match s with DatatypeSort(x) -> x - - let datatype_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeSort(s) - - let datatype_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.DATATYPE_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - DatatypeExpr(e) - - let expr_of_datatype_expr e = match e with DatatypeExpr(x) -> x - - let sgc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : datatype_sort ) = match (x) with DatatypeSort(Sort(s))-> (z3obj_gno s) - - module Constructor = - struct - type constructor = z3_native_object - - let _sizes = Hashtbl.create 0 - - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - let n = (List.length field_names) in - if n != (List.length sorts) then - raise (Z3native.Exception "Number of field names does not match number of sorts") - else - if n != (List.length sort_refs) then - raise (Z3native.Exception "Number of field names does not match number of sort refs") - else - let ptr = (Z3native.mk_constructor (context_gno ctx) (Symbol.gno name) - (Symbol.gno recognizer) - n - (Symbol.symbol_lton field_names) - (sort_lton sorts) - (Array.of_list sort_refs)) in - let no : constructor = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - (z3obj_sno no ctx ptr) ; - (z3obj_create no) ; - let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f no ; - Hashtbl.add _sizes no n ; - no - - let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x - - let get_constructor_decl ( x : constructor ) = - let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) a - - let get_tester_decl ( x : constructor ) = - let (_, b, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - func_decl_of_ptr (z3obj_gc x) b - - let get_accessor_decls ( x : constructor ) = - let (_, _, c) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in - let f i = func_decl_of_ptr (z3obj_gc x) (Array.get c i) in - mk_list f (Array.length c) - - end - - module ConstructorList = - struct - type constructor_list = z3_native_object - - let create ( ctx : context ) ( c : Constructor.constructor list ) = - let res : constructor_list = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = z3obj_nil_ref ; - dec_ref = z3obj_nil_ref} in - let f x =(z3obj_gno x) in - (z3obj_sno res ctx (Z3native.mk_constructor_list (context_gno ctx) (List.length c) (Array.of_list (List.map f c)))) ; - (z3obj_create res) ; - let f = fun o -> Z3native.del_constructor_list (z3obj_gnc o) (z3obj_gno o) in - Gc.finalise f res; - res - end - - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - Constructor.create ctx name recognizer field_names sorts sort_refs - - - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = - mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = - let f x = (z3obj_gno x) in - let (x,_) = (Z3native.mk_datatype (context_gno ctx) (Symbol.gno name) (List.length constructors) (Array.of_list (List.map f constructors))) in - sort_of_ptr ctx x - - let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : Constructor.constructor list ) = - mk_sort ctx (Symbol.mk_string ctx name) constructors - - let mk_sorts ( ctx : context ) ( names : Symbol.symbol list ) ( c : Constructor.constructor list list ) = - let n = (List.length names) in - let f e = (AST.ptr_of_ast (ConstructorList.create ctx e)) in - let cla = (Array.of_list (List.map f c)) in - let (r, a) = (Z3native.mk_datatypes (context_gno ctx) n (Symbol.symbol_lton names) cla) in - let g i = (sort_of_ptr ctx (Array.get r i)) in - mk_list g (Array.length r) - - let mk_sorts_s ( ctx : context ) ( names : string list ) ( c : Constructor.constructor list list ) = - mk_sorts ctx - ( - let f e = (Symbol.mk_string ctx e) in - List.map f names - ) - c - - let get_num_constructors ( x : datatype_sort ) = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) - - let get_constructors ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - mk_list f n - - let get_recognizers ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i) in - mk_list f n - - let get_accessors ( x : datatype_sort ) = - let n = (get_num_constructors x) in - let f i = ( - let fd = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i) in - let ds = Z3native.get_domain_size (FuncDecl.gnc fd) (FuncDecl.gno fd) in - let g j = func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) i j) in - mk_list g ds - ) in - mk_list f n -end - - -module Enumeration = -struct - type enum_sort = EnumSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( cdecls : Z3native.z3_func_decl list ) ( tdecls : Z3native.z3_func_decl list ) = - let s = (sort_of_ptr ctx no) in - let res = EnumSort(s) in - res - - let sort_of_enum_sort s = match s with EnumSort(x) -> x - - let sgc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : enum_sort ) = match (x) with EnumSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : enum_sort ) = match (x) with EnumSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( enum_names : Symbol.symbol list ) = - let (a, b, c) = (Z3native.mk_enumeration_sort (context_gno ctx) (Symbol.gno name) (List.length enum_names) (Symbol.symbol_lton enum_names)) in - sort_of_ptr ctx a (list_of_array b) (list_of_array c) - - let mk_sort_s ( ctx : context ) ( name : string ) ( enum_names : string list ) = - mk_sort ctx (Symbol.mk_string ctx name) (Symbol.mk_strings ctx enum_names) - - let get_const_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) i)) in - mk_list f n - - let get_tester_decls ( x : enum_sort ) = - let n = Z3native.get_datatype_sort_num_constructors (sgnc x) (sgno x) in - let f i = (func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) i)) in - mk_list f n - -end - - -module List_ = -struct - type list_sort = ListSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) ( nildecl : Z3native.ptr ) ( is_nildecl : Z3native.ptr ) ( consdecl : Z3native.ptr ) ( is_consdecl : Z3native.ptr ) ( headdecl : Z3native.ptr ) ( taildecl : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - let res = ListSort(s) in - res - - let sort_of_list_sort s = match s with ListSort(x) -> x - - let sgc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : list_sort ) = match (x) with ListSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : list_sort ) = match (x) with ListSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = - let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in - sort_of_ptr ctx r a b c d e f - - let mk_list_s ( ctx : context ) (name : string) elem_sort = - mk_sort ctx (Symbol.mk_string ctx name) elem_sort - - let get_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 0) - - let get_is_nil_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 0) - - let get_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor (sgnc x) (sgno x) 1) - - let get_is_cons_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_recognizer (sgnc x) (sgno x) 1) - - let get_head_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 0) - - let get_tail_decl ( x : list_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_datatype_sort_constructor_accessor (sgnc x) (sgno x) 1 1) - - let nil ( x : list_sort ) = expr_of_func_app (sgc x) (get_nil_decl x) [] -end - - -module Tuple = -struct - type tuple_sort = TupleSort of sort - - let sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - let s = (sort_of_ptr ctx no) in - TupleSort(s) - - let sort_of_tuple_sort s = match s with TupleSort(x) -> x - - let sgc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : tuple_sort ) = match (x) with TupleSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : tuple_sort ) = match (x) with TupleSort(Sort(s))-> (z3obj_gno s) - - let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( field_sorts : sort list ) = - let (r, _, _) = (Z3native.mk_tuple_sort (context_gno ctx) (Symbol.gno name) (List.length field_names) (Symbol.symbol_lton field_names) (sort_lton field_sorts)) in - sort_of_ptr ctx r - - let get_mk_decl ( x : tuple_sort ) = - func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_mk_decl (sgnc x) (sgno x)) - - let get_num_fields ( x : tuple_sort ) = Z3native.get_tuple_sort_num_fields (sgnc x) (sgno x) - - let get_field_decls ( x : tuple_sort ) = - let n = get_num_fields x in - let f i = func_decl_of_ptr (sgc x) (Z3native.get_tuple_sort_field_decl (sgnc x) (sgno x) i) in - mk_list f n -end - - -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> arith_sort - val expr_of_arith_expr : arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> arith_expr - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_const : context -> Symbol.symbol -> int_expr - val mk_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_numeral_s : context -> string -> int_num - val mk_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_const : context -> Symbol.symbol -> real_expr - val mk_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end - - val is_int : Expr.expr -> bool - val is_arithmetic_numeral : Expr.expr -> bool - val is_le : Expr.expr -> bool - val is_ge : Expr.expr -> bool - val is_lt : Expr.expr -> bool - val is_gt : Expr.expr -> bool - val is_add : Expr.expr -> bool - val is_sub : Expr.expr -> bool - val is_uminus : Expr.expr -> bool - val is_mul : Expr.expr -> bool - val is_div : Expr.expr -> bool - val is_idiv : Expr.expr -> bool - val is_remainder : Expr.expr -> bool - val is_modulus : Expr.expr -> bool - val is_inttoreal : Expr.expr -> bool - val is_real_to_int : Expr.expr -> bool - val is_real_is_int : Expr.expr -> bool - val is_real : Expr.expr -> bool - val is_int_numeral : Expr.expr -> bool - val is_rat_num : Expr.expr -> bool - val is_algebraic_number : Expr.expr -> bool - val mk_add : context -> arith_expr list -> arith_expr - val mk_mul : context -> arith_expr list -> arith_expr - val mk_sub : context -> arith_expr list -> arith_expr - val mk_unary_minus : context -> arith_expr -> arith_expr - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end = struct - type arith_sort = ArithSort of sort - type arith_expr = ArithExpr of expr - - let arith_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithExpr(e) - - let arith_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_expr_of_expr (expr_of_ptr ctx no) - - let sort_of_arith_sort s = match s with ArithSort(x) -> x - let expr_of_arith_expr e = match e with ArithExpr(x) -> x - - let arith_sort_of_sort s = match s with Sort(a) -> - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) in - if (q != Z3enums.INT_SORT && q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - ArithSort(s) - - let arith_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - arith_sort_of_sort (sort_of_ptr ctx no) - - let sgc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gc s) - let sgnc ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gnc s) - let sgno ( x : arith_sort ) = match (x) with ArithSort(Sort(s)) -> (z3obj_gno s) - let egc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gc e) - let egnc ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gnc e) - let egno ( x : arith_expr ) = match (x) with ArithExpr(e) -> (Expr.gno e) - - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val int_expr_of_ptr : context -> Z3native.ptr -> int_expr - val int_num_of_ptr : context -> Z3native.ptr -> int_num - - val arith_sort_of_int_sort : Integer.int_sort -> arith_sort - val int_sort_of_arith_sort : arith_sort -> int_sort - val arith_expr_of_int_expr : int_expr -> arith_expr - val int_expr_of_int_num : int_num -> int_expr - val int_expr_of_arith_expr : arith_expr -> int_expr - val int_num_of_int_expr : int_expr -> int_num - - val mk_sort : context -> int_sort - val get_int : int_num -> int - val to_string : int_num -> string - val mk_const : context -> Symbol.symbol -> int_expr - val mk_const_s : context -> string -> int_expr - val mk_mod : context -> int_expr -> int_expr -> int_expr - val mk_rem : context -> int_expr -> int_expr -> int_expr - val mk_numeral_s : context -> string -> int_num - val mk_numeral_i : context -> int -> int_num - val mk_int2real : context -> int_expr -> Real.real_expr - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end = struct - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - let int_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntExpr(e) - - let int_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let int_num_of_int_expr e = - match e with IntExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - IntNum(e) - - let int_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_num_of_int_expr (int_expr_of_ptr ctx no) - - let arith_sort_of_int_sort s = match s with IntSort(x) -> x - let arith_expr_of_int_expr e = match e with IntExpr(x) -> x - let int_expr_of_int_num e = match e with IntNum(x) -> x - - let int_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.INT_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - IntSort(s) - - let int_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - int_sort_of_arith_sort (arith_sort_of_sort (Sort.sort_of_ptr ctx no)) - - let sgc ( x : int_sort ) = match (x) with IntSort(s) -> (sgc s) - let sgnc ( x : int_sort ) = match (x) with IntSort(s) -> (sgnc s) - let sgno ( x : int_sort ) = match (x) with IntSort(s) -> (sgno s) - let egc ( x : int_expr ) = match (x) with IntExpr(e) -> (egc e) - let egnc ( x : int_expr ) = match (x) with IntExpr(e) -> (egnc e) - let egno ( x : int_expr ) = match (x) with IntExpr(e) -> (egno e) - let ngc ( x : int_num ) = match (x) with IntNum(e) -> (egc e) - let ngnc ( x : int_num ) = match (x) with IntNum(e) -> (egnc e) - let ngno ( x : int_num ) = match (x) with IntNum(e) -> (egno e) - - let mk_sort ( ctx : context ) = - int_sort_of_ptr ctx (Z3native.mk_int_sort (context_gno ctx)) - - let get_int ( x : int_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - - let to_string ( x : int_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - IntExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with IntSort(ArithSort(s)) -> s))) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_mod (context_gno ctx) (egno t1) (egno t2)) - - let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) = - int_expr_of_ptr ctx (Z3native.mk_rem (context_gno ctx) (egno t1) (egno t2)) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - int_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - int_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_int2real ( ctx : context ) ( t : int_expr ) = - Real.real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2real (context_gno ctx) (egno t)))) - - let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) = - BitVector.bitvec_expr_of_expr (Expr.expr_of_ptr ctx (Z3native.mk_int2bv (context_gno ctx) n (egno t))) - end - - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val real_expr_of_ptr : context -> Z3native.ptr -> real_expr - val rat_num_of_ptr : context -> Z3native.ptr -> rat_num - - val arith_sort_of_real_sort : real_sort -> arith_sort - val real_sort_of_arith_sort : arith_sort -> real_sort - val arith_expr_of_real_expr : real_expr -> arith_expr - val real_expr_of_rat_num : rat_num -> real_expr - val real_expr_of_arith_expr : arith_expr -> real_expr - val rat_num_of_real_expr : real_expr -> rat_num - - val mk_sort : context -> real_sort - val get_numerator : rat_num -> Integer.int_num - val get_denominator : rat_num -> Integer.int_num - val to_decimal_string : rat_num -> int -> string - val to_string : rat_num -> string - val mk_const : context -> Symbol.symbol -> real_expr - val mk_const_s : context -> string -> real_expr - val mk_numeral_nd : context -> int -> int -> rat_num - val mk_numeral_s : context -> string -> rat_num - val mk_numeral_i : context -> int -> rat_num - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - val mk_real2int : context -> real_expr -> Integer.int_expr - end = struct - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - let arith_sort_of_real_sort s = match s with RealSort(x) -> x - let arith_expr_of_real_expr e = match e with RealExpr(x) -> x - let real_expr_of_rat_num e = match e with RatNum(x) -> x - - let real_expr_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealExpr(e) - - let real_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_expr_of_arith_expr (arith_expr_of_expr (Expr.expr_of_ptr ctx no)) - - let rat_num_of_real_expr e = - match e with RealExpr(ArithExpr(Expr(a))) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - RatNum(e) - - let rat_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - rat_num_of_real_expr (real_expr_of_ptr ctx no) - - let real_sort_of_arith_sort s = match s with ArithSort(Sort(a)) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.REAL_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - RealSort(s) - - let real_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - real_sort_of_arith_sort (arith_sort_of_sort (sort_of_ptr ctx no)) - - let sgc ( x : real_sort ) = match (x) with RealSort(s) -> (sgc s) - let sgnc ( x : real_sort ) = match (x) with RealSort(s) -> (sgnc s) - let sgno ( x : real_sort ) = match (x) with RealSort(s) -> (sgno s) - let egc ( x : real_expr ) = match (x) with RealExpr(e) -> (egc e) - let egnc ( x : real_expr ) = match (x) with RealExpr(e) -> (egnc e) - let egno ( x : real_expr ) = match (x) with RealExpr(e) -> (egno e) - let ngc ( x : rat_num ) = match (x) with RatNum(e) -> (egc e) - let ngnc ( x : rat_num ) = match (x) with RatNum(e) -> (egnc e) - let ngno ( x : rat_num ) = match (x) with RatNum(e) -> (egno e) - - - let mk_sort ( ctx : context ) = - real_sort_of_ptr ctx (Z3native.mk_real_sort (context_gno ctx)) - - let get_numerator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_numerator (ngnc x) (ngno x)) - - let get_denominator ( x : rat_num ) = - Integer.int_num_of_ptr (ngc x) (Z3native.get_denominator (ngnc x) (ngno x)) - - let to_decimal_string ( x : rat_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - - let to_string ( x : rat_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - - let mk_const ( ctx : context ) ( name : Symbol.symbol ) = - RealExpr(ArithExpr(Expr.mk_const ctx name (match (mk_sort ctx) with RealSort(ArithSort(s)) -> s))) - - let mk_const_s ( ctx : context ) ( name : string ) = - mk_const ctx (Symbol.mk_string ctx name) - - let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = - if (den == 0) then - raise (Z3native.Exception "Denominator is zero") - else - rat_num_of_ptr ctx (Z3native.mk_real (context_gno ctx) num den) - - let mk_numeral_s ( ctx : context ) ( v : string ) = - rat_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_numeral_i ( ctx : context ) ( v : int ) = - rat_num_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (sgno (mk_sort ctx))) - - let mk_is_integer ( ctx : context ) ( t : real_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_is_int (context_gno ctx) (egno t))) - - let mk_real2int ( ctx : context ) ( t : real_expr ) = - Integer.int_expr_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_real2int (context_gno ctx) (egno t)))) - end - - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : algebraic_num -> arith_expr - val algebraic_num_of_arith_expr : arith_expr -> algebraic_num - - val to_upper : algebraic_num -> int -> Real.rat_num - val to_lower : algebraic_num -> int -> Real.rat_num - val to_decimal_string : algebraic_num -> int -> string - val to_string : algebraic_num -> string - end = struct - type algebraic_num = AlgebraicNum of arith_expr - - let arith_expr_of_algebraic_num e = match e with AlgebraicNum(x) -> x - - let algebraic_num_of_arith_expr e = - match e with ArithExpr(Expr(a)) -> - if (not (Z3native.is_algebraic_number (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - AlgebraicNum(e) - - let algebraic_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - algebraic_num_of_arith_expr (arith_expr_of_expr (expr_of_ptr ctx no)) - - let ngc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egc e) - let ngnc ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egnc e) - let ngno ( x : algebraic_num ) = match (x) with AlgebraicNum(e) -> (egno e) - - - let to_upper ( x : algebraic_num ) ( precision : int ) = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_upper (ngnc x) (ngno x) precision) - - let to_lower ( x : algebraic_num ) precision = - Real.rat_num_of_ptr (ngc x) (Z3native.get_algebraic_number_lower (ngnc x) (ngno x) precision) - - let to_decimal_string ( x : algebraic_num ) ( precision : int ) = - Z3native.get_numeral_decimal_string (ngnc x) (ngno x) precision - - let to_string ( x : algebraic_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - end - - let is_int ( x : expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - - let mk_add ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_mul ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_mul (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_sub ( ctx : context ) ( t : arith_expr list ) = - let f x = (Expr.gno (expr_of_arith_expr x)) in - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) - - let mk_unary_minus ( ctx : context ) ( t : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (egno t))) - - let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (egno t1) (egno t2))) - - let mk_power ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - arith_expr_of_expr (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (egno t1) (egno t2))) - - let mk_lt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (egno t1) (egno t2))) - - let mk_le ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_le (context_gno ctx) (egno t1) (egno t2))) - - let mk_gt ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_gt (context_gno ctx) (egno t1) (egno t2))) - - let mk_ge ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_ge (context_gno ctx) (egno t1) (egno t2))) -end - - -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - val mk_sort : context -> int -> bitvec_sort - val is_bv : Expr.expr -> bool - val is_bv_numeral : Expr.expr -> bool - val is_bv_bit1 : Expr.expr -> bool - val is_bv_bit0 : Expr.expr -> bool - val is_bv_uminus : Expr.expr -> bool - val is_bv_add : Expr.expr -> bool - val is_bv_sub : Expr.expr -> bool - val is_bv_mul : Expr.expr -> bool - val is_bv_sdiv : Expr.expr -> bool - val is_bv_udiv : Expr.expr -> bool - val is_bv_SRem : Expr.expr -> bool - val is_bv_urem : Expr.expr -> bool - val is_bv_smod : Expr.expr -> bool - val is_bv_sdiv0 : Expr.expr -> bool - val is_bv_udiv0 : Expr.expr -> bool - val is_bv_srem0 : Expr.expr -> bool - val is_bv_urem0 : Expr.expr -> bool - val is_bv_smod0 : Expr.expr -> bool - val is_bv_ule : Expr.expr -> bool - val is_bv_sle : Expr.expr -> bool - val is_bv_uge : Expr.expr -> bool - val is_bv_sge : Expr.expr -> bool - val is_bv_ult : Expr.expr -> bool - val is_bv_slt : Expr.expr -> bool - val is_bv_ugt : Expr.expr -> bool - val is_bv_sgt : Expr.expr -> bool - val is_bv_and : Expr.expr -> bool - val is_bv_or : Expr.expr -> bool - val is_bv_not : Expr.expr -> bool - val is_bv_xor : Expr.expr -> bool - val is_bv_nand : Expr.expr -> bool - val is_bv_nor : Expr.expr -> bool - val is_bv_xnor : Expr.expr -> bool - val is_bv_concat : Expr.expr -> bool - val is_bv_signextension : Expr.expr -> bool - val is_bv_zeroextension : Expr.expr -> bool - val is_bv_extract : Expr.expr -> bool - val is_bv_repeat : Expr.expr -> bool - val is_bv_reduceor : Expr.expr -> bool - val is_bv_reduceand : Expr.expr -> bool - val is_bv_comp : Expr.expr -> bool - val is_bv_shiftleft : Expr.expr -> bool - val is_bv_shiftrightlogical : Expr.expr -> bool - val is_bv_shiftrightarithmetic : Expr.expr -> bool - val is_bv_rotateleft : Expr.expr -> bool - val is_bv_rotateright : Expr.expr -> bool - val is_bv_rotateleftextended : Expr.expr -> bool - val is_bv_rotaterightextended : Expr.expr -> bool - val is_int_to_bv : Expr.expr -> bool - val is_bv_to_int : Expr.expr -> bool - val is_bv_carry : Expr.expr -> bool - val is_bv_xor3 : Expr.expr -> bool - val get_size : bitvec_sort -> int - val get_int : bitvec_num -> int - val to_string : bitvec_num -> string - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - val mk_const_s : context -> string -> int -> bitvec_expr - val mk_not : context -> bitvec_expr -> Expr.expr - val mk_redand : context -> bitvec_expr -> Expr.expr - val mk_redor : context -> bitvec_expr -> Expr.expr - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_neg : context -> bitvec_expr -> bitvec_expr - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - val mk_numeral : context -> string -> int -> bitvec_num -end = struct - type bitvec_sort = BitVecSort of sort - type bitvec_expr = BitVecExpr of expr - type bitvec_num = BitVecNum of bitvec_expr - - let sort_of_bitvec_sort s = match s with BitVecSort(x) -> x - - let bitvec_sort_of_sort s = match s with Sort(a) -> - if ((Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) (z3obj_gno a))) != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecSort(s) - - let bitvec_sort_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_sort_of_sort (sort_of_ptr ctx no) - - let bitvec_expr_of_expr e = - match e with Expr(a) -> - let s = Z3native.get_sort (z3obj_gnc a) (z3obj_gno a) in - let q = (Z3enums.sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc a) s)) in - if (q != Z3enums.BV_SORT) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecExpr(e) - - let bitvec_expr_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_expr_of_expr (expr_of_ptr ctx no) - - let bitvec_num_of_bitvec_expr e = - match e with BitVecExpr(Expr(a)) -> - if (not (Z3native.is_numeral_ast (z3obj_gnc a) (z3obj_gno a))) then - raise (Z3native.Exception "Invalid coercion") - else - BitVecNum(e) - - let bitvec_num_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = - bitvec_num_of_bitvec_expr (bitvec_expr_of_expr (expr_of_ptr ctx no)) - - let expr_of_bitvec_expr e = match e with BitVecExpr(x) -> x - let bitvec_expr_of_bitvec_num e = match e with BitVecNum(x) -> x - - - let sgc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gc s) - let sgnc ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gnc s) - let sgno ( x : bitvec_sort ) = match (x) with BitVecSort(s) -> (Sort.gno s) - let egc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gc e) - let egnc ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gnc e) - let egno ( x : bitvec_expr ) = match (x) with BitVecExpr(e) -> (Expr.gno e) - let ngc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egc e) - let ngnc ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egnc e) - let ngno ( x : bitvec_num ) = match (x) with BitVecNum(e) -> (egno e) - - - let mk_sort ( ctx : context ) size = - bitvec_sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) - let is_bv ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) - let get_size (x : bitvec_sort ) = Z3native.get_bv_sort_size (sgnc x) (sgno x) - let get_int ( x : bitvec_num ) = - let (r, v) = Z3native.get_numeral_int (ngnc x) (ngno x) in - if r then v - else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : bitvec_num ) = Z3native.get_numeral_string (ngnc x) (ngno x) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = - BitVecExpr(Expr.mk_const ctx name (match (BitVector.mk_sort ctx size) with BitVecSort(s) -> s)) - let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = - mk_const ctx (Symbol.mk_string ctx name) size - let mk_not ( ctx : context ) ( t : bitvec_expr ) = - expr_of_ptr ctx (Z3native.mk_bvnot (context_gno ctx) (egno t)) - let mk_redand ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredand (context_gno ctx) (egno t)) - let mk_redor ( ctx : context ) ( t : bitvec_expr) = - expr_of_ptr ctx (Z3native.mk_bvredor (context_gno ctx) (egno t)) - let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvand (context_gno ctx) (egno t1) (egno t2)) - let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvor (context_gno ctx) (egno t1) (egno t2)) - let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxor (context_gno ctx) (egno t1) (egno t2)) - let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnand (context_gno ctx) (egno t1) (egno t2)) - let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvnor (context_gno ctx) (egno t1) (egno t2)) - let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvxnor (context_gno ctx) (egno t1) (egno t2)) - let mk_neg ( ctx : context ) ( t : bitvec_expr) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvneg (context_gno ctx) (egno t)) - let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvadd (context_gno ctx) (egno t1) (egno t2)) - let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsub (context_gno ctx) (egno t1) (egno t2)) - let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvmul (context_gno ctx) (egno t1) (egno t2)) - let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvudiv (context_gno ctx) (egno t1) (egno t2)) - let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsdiv (context_gno ctx) (egno t1) (egno t2)) - let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvurem (context_gno ctx) (egno t1) (egno t2)) - let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsrem (context_gno ctx) (egno t1) (egno t2)) - let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvsmod (context_gno ctx) (egno t1) (egno t2)) - let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvult (context_gno ctx) (egno t1) (egno t2))) - let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvslt (context_gno ctx) (egno t1) (egno t2))) - let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvule (context_gno ctx) (egno t1) (egno t2))) - let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsle (context_gno ctx) (egno t1) (egno t2))) - let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvuge (context_gno ctx) (egno t1) (egno t2))) - let mk_sge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsge (context_gno ctx) (egno t1) (egno t2))) - let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvugt (context_gno ctx) (egno t1) (egno t2))) - let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsgt (context_gno ctx) (egno t1) (egno t2))) - let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_concat (context_gno ctx) (egno t1) (egno t2)) - let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_extract (context_gno ctx) high low (egno t)) - let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_sign_ext (context_gno ctx) i (egno t)) - let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_zero_ext (context_gno ctx) i (egno t)) - let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_repeat (context_gno ctx) i (egno t)) - let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvshl (context_gno ctx) (egno t1) (egno t2)) - let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvlshr (context_gno ctx) (egno t1) (egno t2)) - let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_bvashr (context_gno ctx) (egno t1) (egno t2)) - let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_left (context_gno ctx) i (egno t)) - let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_rotate_right (context_gno ctx) i (egno t)) - let mk_ext_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_left (context_gno ctx) (egno t1) (egno t2)) - let mk_ext_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - bitvec_expr_of_ptr ctx (Z3native.mk_ext_rotate_right (context_gno ctx) (egno t1) (egno t2)) - let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool ) = - Arithmetic.Integer.int_expr_of_ptr ctx (Z3native.mk_bv2int (context_gno ctx) (egno t) signed) - let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvadd_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsub_no_underflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvsdiv_no_overflow (context_gno ctx) (egno t1) (egno t2))) - let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvneg_no_overflow (context_gno ctx) (egno t))) - let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (egno t1) (egno t2) signed)) - let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) = - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (egno t1) (egno t2))) - let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = - bitvec_num_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (sgno (BitVector.mk_sort ctx size))) -end - - -module Proof = -struct - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) -end - - -module Goal = -struct - type goal = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : goal = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.goal_inc_ref ; - dec_ref = Z3native.goal_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_precision ( x : goal ) = - goal_prec_of_int (Z3native.goal_precision (z3obj_gnc x) (z3obj_gno x)) - - let is_precise ( x : goal ) = - (get_precision x) == GOAL_PRECISE - - let is_underapproximation ( x : goal ) = - (get_precision x) == GOAL_UNDER - - let is_overapproximation ( x : goal ) = - (get_precision x) == GOAL_OVER - - let is_garbage ( x : goal ) = - (get_precision x) == GOAL_UNDER_OVER - - let assert_ ( x : goal ) ( constraints : Boolean.bool_expr list ) = - let f e = Z3native.goal_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e) in - ignore (List.map f constraints) ; - () - - let is_inconsistent ( x : goal ) = - Z3native.goal_inconsistent (z3obj_gnc x) (z3obj_gno x) - - let get_depth ( x : goal ) = Z3native.goal_depth (z3obj_gnc x) (z3obj_gno x) - - let reset ( x : goal ) = Z3native.goal_reset (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : goal ) = Z3native.goal_size (z3obj_gnc x) (z3obj_gno x) - - let get_formulas ( x : goal ) = - let n = get_size x in - let f i = (Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) - (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in - mk_list f n - - let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) - - let is_decided_sat ( x : goal ) = - Z3native.goal_is_decided_sat (z3obj_gnc x) (z3obj_gno x) - - let is_decided_unsat ( x : goal ) = - Z3native.goal_is_decided_unsat (z3obj_gnc x) (z3obj_gno x) - - let translate ( x : goal ) ( to_ctx : context ) = - create to_ctx (Z3native.goal_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) - - let simplify ( x : goal ) ( p : Params.params option ) = - let tn = Z3native.mk_tactic (z3obj_gnc x) "simplify" in - Z3native.tactic_inc_ref (z3obj_gnc x) tn ; - let arn = match p with - | None -> Z3native.tactic_apply (z3obj_gnc x) tn (z3obj_gno x) - | Some(pn) -> Z3native.tactic_apply_ex (z3obj_gnc x) tn (z3obj_gno x) (z3obj_gno pn) - in - Z3native.apply_result_inc_ref (z3obj_gnc x) arn ; - let sg = Z3native.apply_result_get_num_subgoals (z3obj_gnc x) arn in - let res = if sg == 0 then - raise (Z3native.Exception "No subgoals") - else - Z3native.apply_result_get_subgoal (z3obj_gnc x) arn 0 in - Z3native.apply_result_dec_ref (z3obj_gnc x) arn ; - Z3native.tactic_dec_ref (z3obj_gnc x) tn ; - create (z3obj_gc x) res - - let mk_goal ( ctx : context ) ( models : bool ) ( unsat_cores : bool ) ( proofs : bool ) = - create ctx (Z3native.mk_goal (context_gno ctx) models unsat_cores proofs) - - let to_string ( x : goal ) = Z3native.goal_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Model = -struct - type model = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : model = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.model_inc_ref ; - dec_ref = Z3native.model_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncInterp = - struct - type func_interp = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_interp = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_interp_inc_ref ; - dec_ref = Z3native.func_interp_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module FuncEntry = - struct - type func_entry = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : func_entry = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.func_entry_inc_ref ; - dec_ref = Z3native.func_entry_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_value ( x : func_entry ) = - expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_value (z3obj_gnc x) (z3obj_gno x)) - - let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args (z3obj_gnc x) (z3obj_gno x) - - let get_args ( x : func_entry ) = - let n = (get_num_args x) in - let f i = (expr_of_ptr (z3obj_gc x) (Z3native.func_entry_get_arg (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let to_string ( x : func_entry ) = - let a = (get_args x) in - let f c p = (p ^ (Expr.to_string c) ^ ", ") in - "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]") - end - - let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : func_interp ) = - let n = (get_num_entries x) in - let f i = (FuncEntry.create (z3obj_gc x) (Z3native.func_interp_get_entry (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let get_else ( x : func_interp ) = expr_of_ptr (z3obj_gc x) (Z3native.func_interp_get_else (z3obj_gnc x) (z3obj_gno x)) - - let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity (z3obj_gnc x) (z3obj_gno x) - - let to_string ( x : func_interp ) = - let f c p = ( - let n = (FuncEntry.get_num_args c) in - p ^ - let g c p = (p ^ (Expr.to_string c) ^ ", ") in - (if n > 1 then "[" else "") ^ - (List.fold_right - g - (FuncEntry.get_args c) - ((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", ")) - ) in - List.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]") - end - - let get_const_interp ( x : model ) ( f : func_decl ) = - if (FuncDecl.get_arity f) != 0 || - (sort_kind_of_int (Z3native.get_sort_kind (FuncDecl.gnc f) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) == ARRAY_SORT then - raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.") - else - let np = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null np) then - None - else - Some (expr_of_ptr (z3obj_gc x) np) - - let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a) - - - let rec get_func_interp ( x : model ) ( f : func_decl ) = - let sk = (sort_kind_of_int (Z3native.get_sort_kind (z3obj_gnc x) (Z3native.get_range (FuncDecl.gnc f) (FuncDecl.gno f)))) in - if (FuncDecl.get_arity f) == 0 then - let n = Z3native.model_get_const_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) in - if (Z3native.is_null n) then - None - else - match sk with - | ARRAY_SORT -> - if not (Z3native.is_as_array (z3obj_gnc x) n) then - raise (Z3native.Exception "Argument was not an array constant") - else - let fd = Z3native.get_as_array_func_decl (z3obj_gnc x) n in - get_func_interp x (func_decl_of_ptr (z3obj_gc x) fd) - | _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp"); - else - let n = (Z3native.model_get_func_interp (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f)) in - if (Z3native.is_null n) then None else Some (FuncInterp.create (z3obj_gc x) n) - - (** The number of constants that have an interpretation in the model. *) - let get_num_consts ( x : model ) = Z3native.model_get_num_consts (z3obj_gnc x) (z3obj_gno x) - - let get_const_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) - - let get_func_decls ( x : model ) = - let n = (get_num_consts x) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_decls ( x : model ) = - let n_funcs = (get_num_funcs x) in - let n_consts = (get_num_consts x ) in - let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in - let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in - (mk_list f n_funcs) @ (mk_list g n_consts) - - exception ModelEvaluationFailedException of string - - let eval ( x : model ) ( t : expr ) ( completion : bool ) = - let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in - if not r then - raise (ModelEvaluationFailedException "evaluation failed") - else - expr_of_ptr (z3obj_gc x) v - - let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = - eval x t completion - - let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts (z3obj_gnc x) (z3obj_gno x) - - let get_sorts ( x : model ) = - let n = (get_num_sorts x) in - let f i = (sort_of_ptr (z3obj_gc x) (Z3native.model_get_sort (z3obj_gnc x) (z3obj_gno x) i)) in - mk_list f n - - let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in - let n = (AST.ASTVector.get_size n_univ) in - let f i = (AST.ASTVector.get n_univ i) in - mk_list f n - - let to_string ( x : model ) = Z3native.model_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Probe = -struct - type probe = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : probe = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.probe_inc_ref ; - dec_ref = Z3native.probe_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - let apply ( x : probe ) ( g : Goal.goal ) = - Z3native.probe_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) - - let get_num_probes ( ctx : context ) = - Z3native.get_num_probes (context_gno ctx) - - let get_probe_names ( ctx : context ) = - let n = (get_num_probes ctx) in - let f i = (Z3native.get_probe_name (context_gno ctx) i) in - mk_list f n - - let get_probe_description ( ctx : context ) ( name : string ) = - Z3native.probe_get_descr (context_gno ctx) name - - let mk_probe ( ctx : context ) ( name : string ) = - (create ctx (Z3native.mk_probe (context_gno ctx) name)) - - let const ( ctx : context ) ( v : float ) = - (create ctx (Z3native.probe_const (context_gno ctx) v)) - - let lt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_lt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let gt ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_gt (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let le ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_le (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let ge ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_ge (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let eq ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_eq (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let and_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_and (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let or_ ( ctx : context ) ( p1 : probe ) ( p2 : probe ) = - (create ctx (Z3native.probe_or (context_gno ctx) (z3obj_gno p1) (z3obj_gno p2))) - - let not_ ( ctx : context ) ( p : probe ) = - (create ctx (Z3native.probe_not (context_gno ctx) (z3obj_gno p))) -end - - -module Tactic = -struct - type tactic = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : tactic = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.tactic_inc_ref ; - dec_ref = Z3native.tactic_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - module ApplyResult = - struct - type apply_result = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : apply_result = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.apply_result_inc_ref ; - dec_ref = Z3native.apply_result_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let get_num_subgoals ( x : apply_result ) = - Z3native.apply_result_get_num_subgoals (z3obj_gnc x) (z3obj_gno x) - - let get_subgoals ( x : apply_result ) = - let n = (get_num_subgoals x) in - let f i = Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get_subgoal ( x : apply_result ) ( i : int ) = - Goal.create (z3obj_gc x) (Z3native.apply_result_get_subgoal (z3obj_gnc x) (z3obj_gno x) i) - - let convert_model ( x : apply_result ) ( i : int ) ( m : Model.model ) = - Model.create (z3obj_gc x) (Z3native.apply_result_convert_model (z3obj_gnc x) (z3obj_gno x) i (z3obj_gno m)) - - let to_string ( x : apply_result ) = Z3native.apply_result_to_string (z3obj_gnc x) (z3obj_gno x) - end - - let get_help ( x : tactic ) = Z3native.tactic_get_help (z3obj_gnc x) (z3obj_gno x) - - let get_param_descrs ( x : tactic ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.tactic_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let apply ( x : tactic ) ( g : Goal.goal ) ( p : Params.params option ) = - match p with - | None -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g))) - | Some (pn) -> (ApplyResult.create (z3obj_gc x) (Z3native.tactic_apply_ex (z3obj_gnc x) (z3obj_gno x) (z3obj_gno g) (z3obj_gno pn))) - - let get_num_tactics ( ctx : context ) = Z3native.get_num_tactics (context_gno ctx) - - let get_tactic_names ( ctx : context ) = - let n = (get_num_tactics ctx ) in - let f i = (Z3native.get_tactic_name (context_gno ctx) i) in - mk_list f n - - let get_tactic_description ( ctx : context ) ( name : string ) = - Z3native.tactic_get_descr (context_gno ctx) name - - let mk_tactic ( ctx : context ) ( name : string ) = - create ctx (Z3native.mk_tactic (context_gno ctx) name) - - let and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) ( ts : tactic list ) = - let f p c = (match p with - | None -> (Some (z3obj_gno c)) - | Some(x) -> (Some (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno c) x))) in - match (List.fold_left f None ts) with - | None -> - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - | Some(x) -> - let o = (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t2) x) in - create ctx (Z3native.tactic_and_then (context_gno ctx) (z3obj_gno t1) o) - - let or_else ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_or_else (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let try_for ( ctx : context ) ( t : tactic ) ( ms : int ) = - create ctx (Z3native.tactic_try_for (context_gno ctx) (z3obj_gno t) ms) - - let when_ ( ctx : context ) ( p : Probe.probe ) ( t : tactic ) = - create ctx (Z3native.tactic_when (context_gno ctx) (z3obj_gno p) (z3obj_gno t)) - - let cond ( ctx : context ) ( p : Probe.probe ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_cond (context_gno ctx) (z3obj_gno p) (z3obj_gno t1) (z3obj_gno t2)) - - let repeat ( ctx : context ) ( t : tactic ) ( max : int ) = - create ctx (Z3native.tactic_repeat (context_gno ctx) (z3obj_gno t) max) - - let skip ( ctx : context ) = - create ctx (Z3native.tactic_skip (context_gno ctx)) - - let fail ( ctx : context ) = - create ctx (Z3native.tactic_fail (context_gno ctx)) - - let fail_if ( ctx : context ) ( p : Probe.probe ) = - create ctx (Z3native.tactic_fail_if (context_gno ctx) (z3obj_gno p)) - - let fail_if_not_decided ( ctx : context ) = - create ctx (Z3native.tactic_fail_if_not_decided (context_gno ctx)) - - let using_params ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - create ctx (Z3native.tactic_using_params (context_gno ctx) (z3obj_gno t) (z3obj_gno p)) - - let with_ ( ctx : context ) ( t : tactic ) ( p : Params.params ) = - using_params ctx t p - - let par_or ( ctx : context ) ( t : tactic list ) = - let f e = (z3obj_gno e) in - create ctx (Z3native.tactic_par_or (context_gno ctx) (List.length t) (Array.of_list (List.map f t))) - - let par_and_then ( ctx : context ) ( t1 : tactic ) ( t2 : tactic ) = - create ctx (Z3native.tactic_par_and_then (context_gno ctx) (z3obj_gno t1) (z3obj_gno t2)) - - let interrupt ( ctx : context ) = - Z3native.interrupt (context_gno ctx) -end - - -module Solver = -struct - type solver = z3_native_object - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : solver = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.solver_inc_ref ; - dec_ref = Z3native.solver_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - let string_of_status ( s : status) = match s with - | UNSATISFIABLE -> "unsatisfiable" - | SATISFIABLE -> "satisfiable" - | _ -> "unknown" - - module Statistics = - struct - type statistics = z3_native_object - - let create ( ctx : context ) ( no : Z3native.ptr ) = - let res : statistics = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.stats_inc_ref ; - dec_ref = Z3native.stats_dec_ref } in - (z3obj_sno res ctx no) ; - (z3obj_create res) ; - res - - - module Entry = - struct - type statistics_entry = { - mutable m_key : string; - mutable m_is_int : bool ; - mutable m_is_float : bool ; - mutable m_int : int ; - mutable m_float : float } - - let create_si k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = true ; - m_is_float = false ; - m_int = v ; - m_float = 0.0 - } in - res - - let create_sd k v = - let res : statistics_entry = { - m_key = k ; - m_is_int = false ; - m_is_float = true ; - m_int = 0 ; - m_float = v - } in - res - - - let get_key (x : statistics_entry) = x.m_key - let get_int (x : statistics_entry) = x.m_int - let get_float (x : statistics_entry) = x.m_float - let is_int (x : statistics_entry) = x.m_is_int - let is_float (x : statistics_entry) = x.m_is_float - let to_string_value (x : statistics_entry) = - if (is_int x) then - string_of_int (get_int x) - else if (is_float x) then - string_of_float (get_float x) - else - raise (Z3native.Exception "Unknown statistical entry type") - let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x) - end - - let to_string ( x : statistics ) = Z3native.stats_to_string (z3obj_gnc x) (z3obj_gno x) - - let get_size ( x : statistics ) = Z3native.stats_size (z3obj_gnc x) (z3obj_gno x) - - let get_entries ( x : statistics ) = - let n = (get_size x ) in - let f i = ( - let k = Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i in - if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then - (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) - else - (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) - ) in - mk_list f n - - let get_keys ( x : statistics ) = - let n = (get_size x) in - let f i = (Z3native.stats_get_key (z3obj_gnc x) (z3obj_gno x) i) in - mk_list f n - - let get ( x : statistics ) ( key : string ) = - let f p c = (if ((Entry.get_key c) == key) then (Some c) else p) in - List.fold_left f None (get_entries x) - end - - let get_help ( x : solver ) = Z3native.solver_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_parameters ( x : solver ) ( p : Params.params )= - Z3native.solver_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : solver ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.solver_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes (z3obj_gnc x) (z3obj_gno x) - - let push ( x : solver ) = Z3native.solver_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : solver ) ( n : int ) = Z3native.solver_pop (z3obj_gnc x) (z3obj_gno x) n - - let reset ( x : solver ) = Z3native.solver_reset (z3obj_gnc x) (z3obj_gno x) - - let assert_ ( x : solver ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.solver_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (List.map f constraints) - - let assert_and_track_a ( x : solver ) ( cs : Boolean.bool_expr list ) ( ps : Boolean.bool_expr list ) = - if ((List.length cs) != (List.length ps)) then - raise (Z3native.Exception "Argument size mismatch") - else - let f a b = (Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno a) (Boolean.gno b)) in - ignore (List.iter2 f cs ps) - - let assert_and_track ( x : solver ) ( c : Boolean.bool_expr ) ( p : Boolean.bool_expr ) = - Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Boolean.gno c) (Boolean.gno p) - - let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - (AST.ASTVector.get_size a) - - let get_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size a) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in - mk_list f n - - let check ( x : solver ) ( assumptions : Boolean.bool_expr list ) = - let r = - if ((List.length assumptions) == 0) then - lbool_of_int (Z3native.solver_check (z3obj_gnc x) (z3obj_gno x)) - else - let f x = (Expr.gno (Boolean.expr_of_bool_expr x)) in - lbool_of_int (Z3native.solver_check_assumptions (z3obj_gnc x) (z3obj_gno x) (List.length assumptions) (Array.of_list (List.map f assumptions))) - in - match r with - | L_TRUE -> SATISFIABLE - | L_FALSE -> UNSATISFIABLE - | _ -> UNKNOWN - - let get_model ( x : solver ) = - let q = Z3native.solver_get_model (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (Model.create (z3obj_gc x) q) - - let get_proof ( x : solver ) = - let q = Z3native.solver_get_proof (z3obj_gnc x) (z3obj_gno x) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in - let n = (AST.ASTVector.get_size cn) in - let f i = (AST.ASTVector.get cn i) in - mk_list f n - - let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_statistics ( x : solver ) = - (Statistics.create (z3obj_gc x) (Z3native.solver_get_statistics (z3obj_gnc x) (z3obj_gno x))) - - let mk_solver ( ctx : context ) ( logic : Symbol.symbol option ) = - match logic with - | None -> (create ctx (Z3native.mk_solver (context_gno ctx))) - | Some (x) -> (create ctx (Z3native.mk_solver_for_logic (context_gno ctx) (Symbol.gno x))) - - let mk_solver_s ( ctx : context ) ( logic : string ) = - mk_solver ctx (Some (Symbol.mk_string ctx logic)) - - let mk_simple_solver ( ctx : context ) = - (create ctx (Z3native.mk_simple_solver (context_gno ctx))) - - let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) = - (create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))) - - let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x) -end - - -module Fixedpoint = -struct - type fixedpoint = z3_native_object - - let create ( ctx : context ) = - let res : fixedpoint = { m_ctx = ctx ; - m_n_obj = null ; - inc_ref = Z3native.fixedpoint_inc_ref ; - dec_ref = Z3native.fixedpoint_dec_ref } in - (z3obj_sno res ctx (Z3native.mk_fixedpoint (context_gno ctx))) ; - (z3obj_create res) ; - res - - - let get_help ( x : fixedpoint ) = - Z3native.fixedpoint_get_help (z3obj_gnc x) (z3obj_gno x) - - let set_params ( x : fixedpoint ) ( p : Params.params )= - Z3native.fixedpoint_set_params (z3obj_gnc x) (z3obj_gno x) (z3obj_gno p) - - let get_param_descrs ( x : fixedpoint ) = - Params.ParamDescrs.param_descrs_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_param_descrs (z3obj_gnc x) (z3obj_gno x)) - - let assert_ ( x : fixedpoint ) ( constraints : Boolean.bool_expr list ) = - let f e = (Z3native.fixedpoint_assert (z3obj_gnc x) (z3obj_gno x) (Boolean.gno e)) in - ignore (List.map f constraints) ; - () - - let register_relation ( x : fixedpoint ) ( f : func_decl ) = - Z3native.fixedpoint_register_relation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) - - let add_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol option ) = - match name with - | None -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) null - | Some(y) -> Z3native.fixedpoint_add_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno y) - - let add_fact ( x : fixedpoint ) ( pred : func_decl ) ( args : int list ) = - Z3native.fixedpoint_add_fact (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno pred) (List.length args) (Array.of_list args) - - let query ( x : fixedpoint ) ( query : Boolean.bool_expr ) = - match (lbool_of_int (Z3native.fixedpoint_query (z3obj_gnc x) (z3obj_gno x) (Boolean.gno query))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let query_r ( x : fixedpoint ) ( relations : func_decl list ) = - let f x = ptr_of_ast (ast_of_func_decl x) in - match (lbool_of_int (Z3native.fixedpoint_query_relations (z3obj_gnc x) (z3obj_gno x) (List.length relations) (Array.of_list (List.map f relations)))) with - | L_TRUE -> Solver.SATISFIABLE - | L_FALSE -> Solver.UNSATISFIABLE - | _ -> Solver.UNKNOWN - - let push ( x : fixedpoint ) = - Z3native.fixedpoint_push (z3obj_gnc x) (z3obj_gno x) - - let pop ( x : fixedpoint ) = - Z3native.fixedpoint_pop (z3obj_gnc x) (z3obj_gno x) - - let update_rule ( x : fixedpoint ) ( rule : Boolean.bool_expr ) ( name : Symbol.symbol ) = - Z3native.fixedpoint_update_rule (z3obj_gnc x) (z3obj_gno x) (Boolean.gno rule) (Symbol.gno name) - - let get_answer ( x : fixedpoint ) = - let q = (Z3native.fixedpoint_get_answer (z3obj_gnc x) (z3obj_gno x)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let get_reason_unknown ( x : fixedpoint ) = - Z3native.fixedpoint_get_reason_unknown (z3obj_gnc x) (z3obj_gno x) - - let get_num_levels ( x : fixedpoint ) ( predicate : func_decl ) = - Z3native.fixedpoint_get_num_levels (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno predicate) - - let get_cover_delta ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) = - let q = (Z3native.fixedpoint_get_cover_delta (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate)) in - if (Z3native.is_null q) then - None - else - Some (expr_of_ptr (z3obj_gc x) q) - - let add_cover ( x : fixedpoint ) ( level : int ) ( predicate : func_decl ) ( property : expr ) = - Z3native.fixedpoint_add_cover (z3obj_gnc x) (z3obj_gno x) level (FuncDecl.gno predicate) (Expr.gno property) - - let to_string ( x : fixedpoint ) = Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) 0 [||] - - let set_predicate_representation ( x : fixedpoint ) ( f : func_decl ) ( kinds : Symbol.symbol list ) = - Z3native.fixedpoint_set_predicate_representation (z3obj_gnc x) (z3obj_gno x) (FuncDecl.gno f) (List.length kinds) (Symbol.symbol_lton kinds) - - let to_string_q ( x : fixedpoint ) ( queries : Boolean.bool_expr list ) = - let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in - Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) - - let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in - let n = (AST.ASTVector.get_size v) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in - mk_list f n - - let mk_fixedpoint ( ctx : context ) = create ctx -end - -module Options = -struct - - let update_param_value ( ctx : context ) ( id : string) ( value : string )= - Z3native.update_param_value (context_gno ctx) id value - - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = - Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) - - let toggle_warning_messages ( enabled: bool ) = - Z3native.toggle_warning_messages enabled -end - - -module SMT = -struct - let benchmark_to_smtstring ( ctx : context ) ( name : string ) ( logic : string ) ( status : string ) ( attributes : string ) ( assumptions : Boolean.bool_expr list ) ( formula : Boolean.bool_expr ) = - Z3native.benchmark_to_smtlib_string (context_gno ctx) name logic status attributes - (List.length assumptions) (let f x = ptr_of_expr (Boolean.expr_of_bool_expr x) in (Array.of_list (List.map f assumptions))) - (Boolean.gno formula) - - let parse_smtlib_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let parse_smtlib_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Z3native.parse_smtlib_file (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))) - - let get_num_smtlib_formulas ( ctx : context ) = Z3native.get_smtlib_num_formulas (context_gno ctx) - - let get_smtlib_formulas ( ctx : context ) = - let n = (get_num_smtlib_formulas ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_formula (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_assumptions ( ctx : context ) = Z3native.get_smtlib_num_assumptions (context_gno ctx) - - let get_smtlib_assumptions ( ctx : context ) = - let n = (get_num_smtlib_assumptions ctx ) in - let f i = Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.get_smtlib_assumption (context_gno ctx) i)) in - mk_list f n - - let get_num_smtlib_decls ( ctx : context ) = Z3native.get_smtlib_num_decls (context_gno ctx) - - let get_smtlib_decls ( ctx : context ) = - let n = (get_num_smtlib_decls ctx) in - let f i = func_decl_of_ptr ctx (Z3native.get_smtlib_decl (context_gno ctx) i) in - mk_list f n - - let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - - let get_smtlib_sorts ( ctx : context ) = - let n = (get_num_smtlib_sorts ctx) in - let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in - mk_list f n - - let parse_smtlib2_string ( ctx : context ) ( str : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) str - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) - - let parse_smtlib2_file ( ctx : context ) ( file_name : string ) ( sort_names : Symbol.symbol list ) ( sorts : sort list ) ( decl_names : Symbol.symbol list ) ( decls : func_decl list ) = - let csn = (List.length sort_names) in - let cs = (List.length sorts) in - let cdn = (List.length decl_names) in - let cd = (List.length decls) in - if (csn != cs || cdn != cd) then - raise (Z3native.Exception "Argument size mismatch") - else - Boolean.bool_expr_of_expr (expr_of_ptr ctx (Z3native.parse_smtlib2_string (context_gno ctx) file_name - cs - (Symbol.symbol_lton sort_names) - (sort_lton sorts) - cd - (Symbol.symbol_lton decl_names) - (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) -end - - -let set_global_param ( id : string ) ( value : string ) = - (Z3native.global_param_set id value) - -let get_global_param ( id : string ) = - let (r, v) = (Z3native.global_param_get id) in - if not r then - None - else - Some v - -let global_param_reset_all = - Z3native.global_param_reset_all diff --git a/src/api/ml/z3_rich.mli b/src/api/ml/z3_rich.mli deleted file mode 100644 index f2ecd326d..000000000 --- a/src/api/ml/z3_rich.mli +++ /dev/null @@ -1,3071 +0,0 @@ -(** - The Z3 ML/Ocaml Interface. - - Copyright (C) 2012 Microsoft Corporation - @author CM Wintersteiger (cwinter) 2012-12-17 - - NOTE: This is the *rich* version of the interface, using more - type information directly in the type system. Coercion functions - are provided to tran coerce on type into another where applicable. -*) - -(** Context objects. - - Most interactions with Z3 are interpreted in some context; many users will only - require one such object, but power users may require more than one. To start using - Z3, do - - - let ctx = (mk_context []) in - (...) - - - where a list of pairs of strings may be passed to set options on - the context, e.g., like so: - - - let cfg = [("model", "true"); ("...", "...")] in - let ctx = (mk_context cfg) in - (...) - -*) -type context - -(** Create a context object *) -val mk_context : (string * string) list -> context - -(** Interaction logging for Z3 - Note that this is a global, static log and if multiple Context - objects are created, it logs the interaction with all of them. *) -module Log : -sig - (** Open an interaction log file. - @return True if opening the log file succeeds, false otherwise. *) - (* CMW: "open" seems to be a reserved keyword? *) - val open_ : string -> bool - - (** Closes the interaction log. *) - val close : unit - - (** Appends a user-provided string to the interaction log. *) - val append : string -> unit -end - -(** Version information *) -module Version : -sig - (** The major version. *) - val major : int - - (** The minor version. *) - val minor : int - - (** The build version. *) - val build : int - - (** The revision. *) - val revision : int - - (** A string representation of the version information. *) - val to_string : string -end - -(** Symbols are used to name several term and type constructors *) -module Symbol : -sig - (** Numbered Symbols *) - type int_symbol - - (** Named Symbols *) - type string_symbol - - (** Symbols *) - type symbol = S_Int of int_symbol | S_Str of string_symbol - - (** The kind of the symbol (int or string) *) - val kind : symbol -> Z3enums.symbol_kind - - (** Indicates whether the symbol is of Int kind *) - val is_int_symbol : symbol -> bool - - (** Indicates whether the symbol is of string kind. *) - val is_string_symbol : symbol -> bool - - (** The int value of the symbol. *) - val get_int : int_symbol -> int - - (** The string value of the symbol. *) - val get_string : string_symbol -> string - - (** A string representation of the symbol. *) - val to_string : symbol -> string - - (** Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. *) - val mk_int : context -> int -> symbol - - (** Creates a new symbol using a string. *) - val mk_string : context -> string -> symbol - - (** Create a list of symbols. *) - val mk_ints : context -> int list -> symbol list - - (** Create a list of symbols. *) - val mk_strings : context -> string list -> symbol list -end - -(** The abstract syntax tree (AST) module *) -module AST : -sig - type ast - - (** Vectors of ASTs *) - module ASTVector : - sig - type ast_vector - - (** The size of the vector *) - val get_size : ast_vector -> int - - (** - Retrieves the i-th object in the vector. - @return An AST *) - val get : ast_vector -> int -> ast - - (** Sets the i-th object in the vector. *) - val set : ast_vector -> int -> ast -> unit - - (** Resize the vector to a new size. *) - val resize : ast_vector -> int -> unit - - (** Add an ast to the back of the vector. The size - is increased by 1. *) - val push : ast_vector -> ast -> unit - - (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) - val translate : ast_vector -> context -> ast_vector - - (** Retrieves a string representation of the vector. *) - val to_string : ast_vector -> string - end - - (** Map from AST to AST *) - module ASTMap : - sig - type ast_map - - (** Checks whether the map contains a key. - @return True if the key in the map, false otherwise. *) - val contains : ast_map -> ast -> bool - - (** Finds the value associated with the key. - This function signs an error when the key is not a key in the map. *) - val find : ast_map -> ast -> ast - - (** Stores or replaces a new key/value pair in the map. *) - val insert : ast_map -> ast -> ast -> unit - - (** Erases the key from the map.*) - val erase : ast_map -> ast -> unit - - (** Removes all keys from the map. *) - val reset : ast_map -> unit - - (** The size of the map *) - val get_size : ast_map -> int - - (** The keys stored in the map. *) - val get_keys : ast_map -> ast list - - (** Retrieves a string representation of the map.*) - val to_string : ast_map -> string - end - - (** The AST's hash code. - @return A hash code *) - val get_hash_code : ast -> int - - (** A unique identifier for the AST (unique among all ASTs). *) - val get_id : ast -> int - - (** The kind of the AST. *) - val get_ast_kind : ast -> Z3enums.ast_kind - - (** Indicates whether the AST is an Expr *) - val is_expr : ast -> bool - - (** Indicates whether the AST is a bound variable*) - val is_var : ast -> bool - - (** Indicates whether the AST is a Quantifier *) - val is_quantifier : ast -> bool - - (** Indicates whether the AST is a Sort *) - val is_sort : ast -> bool - - (** Indicates whether the AST is a func_decl *) - val is_func_decl : ast -> bool - - (** A string representation of the AST. *) - val to_string : ast -> string - - (** A string representation of the AST in s-expression notation. *) - val to_sexpr : ast -> string - - (** Comparison operator. - @return True if the two ast's are from the same context - and represent the same sort; false otherwise. *) - val ( = ) : ast -> ast -> bool - - (** Object Comparison. - @return Negative if the first ast should be sorted before the second, positive if after else zero. *) - val compare : ast -> ast -> int - - (** Operator < *) - val ( < ) : ast -> ast -> int - - (** Translates (copies) the AST to another context. - @return A copy of the AST which is associated with the other context. *) - val translate : ast -> context -> ast - - (** Wraps an AST. - - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., - Z3native.inc_ref). *) - val wrap_ast : context -> Z3native.z3_ast -> ast - - (** Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - Z3native.inc_ref). - {!wrap_ast} *) - val unwrap_ast : ast -> Z3native.ptr -end - -(** The Sort module implements type information for ASTs *) -module Sort : -sig - (** Sorts *) - type sort = Sort of AST.ast - - (** Uninterpreted Sorts *) - type uninterpreted_sort = UninterpretedSort of sort - - val ast_of_sort : sort -> AST.ast - val sort_of_uninterpreted_sort : uninterpreted_sort -> sort - val uninterpreted_sort_of_sort : sort -> uninterpreted_sort - - (** Comparison operator. - @return True if the two sorts are from the same context - and represent the same sort; false otherwise. *) - val ( = ) : sort -> sort -> bool - - (** Returns a unique identifier for the sort. *) - val get_id : sort -> int - - (** The kind of the sort. *) - val get_sort_kind : sort -> Z3enums.sort_kind - - (** The name of the sort *) - val get_name : sort -> Symbol.symbol - - (** A string representation of the sort. *) - val to_string : sort -> string - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted : context -> Symbol.symbol -> uninterpreted_sort - - (** Create a new uninterpreted sort. *) - val mk_uninterpreted_s : context -> string -> uninterpreted_sort -end - -(** Function declarations *) -module rec FuncDecl : -sig - type func_decl = FuncDecl of AST.ast - - val ast_of_func_decl : FuncDecl.func_decl -> AST.ast - - (** Parameters of Func_Decls *) - module Parameter : - sig - (** Parameters of func_decls *) - type parameter = - P_Int of int - | P_Dbl of float - | P_Sym of Symbol.symbol - | P_Srt of Sort.sort - | P_Ast of AST.ast - | P_Fdl of func_decl - | P_Rat of string - - (** The kind of the parameter. *) - val get_kind : parameter -> Z3enums.parameter_kind - - (** The int value of the parameter.*) - val get_int : parameter -> int - - (** The double value of the parameter.*) - val get_float : parameter -> float - - (** The Symbol.Symbol value of the parameter.*) - val get_symbol : parameter -> Symbol.symbol - - (** The Sort value of the parameter.*) - val get_sort : parameter -> Sort.sort - - (** The AST value of the parameter.*) - val get_ast : parameter -> AST.ast - - (** The FunctionDeclaration value of the parameter.*) - val get_func_decl : parameter -> func_decl - - (** The rational string value of the parameter.*) - val get_rational : parameter -> string - end - - (** Creates a new function declaration. *) - val mk_func_decl : context -> Symbol.symbol -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new function declaration. *) - val mk_func_decl_s : context -> string -> Sort.sort list -> Sort.sort -> func_decl - (** Creates a fresh function declaration with a name prefixed with a prefix string. *) - - val mk_fresh_func_decl : context -> string -> Sort.sort list -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl : context -> Symbol.symbol -> Sort.sort -> func_decl - - (** Creates a new constant function declaration. *) - val mk_const_decl_s : context -> string -> Sort.sort -> func_decl - - (** Creates a fresh constant function declaration with a name prefixed with a prefix string. - {!mk_func_decl} - {!mk_func_decl} *) - val mk_fresh_const_decl : context -> string -> Sort.sort -> func_decl - - (** Comparison operator. - @return True if a and b are from the same context and represent the same func_decl; false otherwise. *) - val ( = ) : func_decl -> func_decl -> bool - - (** A string representations of the function declaration. *) - val to_string : func_decl -> string - - (** Returns a unique identifier for the function declaration. *) - val get_id : func_decl -> int - - (** The arity of the function declaration *) - val get_arity : func_decl -> int - - (** The size of the domain of the function declaration - {!get_arity} *) - val get_domain_size : func_decl -> int - - (** The domain of the function declaration *) - val get_domain : func_decl -> Sort.sort list - - (** The range of the function declaration *) - val get_range : func_decl -> Sort.sort - - (** The kind of the function declaration. *) - val get_decl_kind : func_decl -> Z3enums.decl_kind - - (** The name of the function declaration*) - val get_name : func_decl -> Symbol.symbol - - (** The number of parameters of the function declaration *) - val get_num_parameters : func_decl -> int - - (** The parameters of the function declaration *) - val get_parameters : func_decl -> Parameter.parameter list - - (** Create expression that applies function to arguments. *) - val apply : func_decl -> Expr.expr list -> Expr.expr -end - -(** Parameter sets (of Solvers, Tactics, ...) - - A Params objects represents a configuration in the form of Symbol.symbol/value pairs. *) -and Params : -sig - type params - - (** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *) - module ParamDescrs : - sig - type param_descrs - - (** Validate a set of parameters. *) - val validate : param_descrs -> params -> unit - - (** Retrieve kind of parameter. *) - val get_kind : param_descrs -> Symbol.symbol -> Z3enums.param_kind - - (** Retrieve all names of parameters. *) - val get_names : param_descrs -> Symbol.symbol list - - (** The size of the ParamDescrs. *) - val get_size : param_descrs -> int - - (** Retrieves a string representation of the ParamDescrs. *) - val to_string : param_descrs -> string - end - - (** Adds a parameter setting. *) - val add_bool : params -> Symbol.symbol -> bool -> unit - - (** Adds a parameter setting. *) - val add_int : params -> Symbol.symbol -> int -> unit - - (** Adds a parameter setting. *) - val add_double : params -> Symbol.symbol -> float -> unit - - (** Adds a parameter setting. *) - val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit - - (** Adds a parameter setting. *) - val add_s_bool : params -> string -> bool -> unit - - (** Adds a parameter setting. *) - val add_s_int : params -> string -> int -> unit - - (** Adds a parameter setting. *) - val add_s_double : params -> string -> float -> unit - - (** Adds a parameter setting. *) - val add_s_symbol : params -> string -> Symbol.symbol -> unit - - (** Creates a new parameter set *) - val mk_params : context -> params - - (** A string representation of the parameter set. *) - val to_string : params -> string -end - -(** General Expressions (terms) *) -and Expr : -sig - type expr = Expr of AST.ast - - val ast_of_expr : Expr.expr -> AST.ast - val expr_of_ast : AST.ast -> Expr.expr - - (** Returns a simplified version of the expression. - {!get_simplify_help} *) - val simplify : Expr.expr -> Params.params option -> expr - - (** A string describing all available parameters to Expr.Simplify. *) - val get_simplify_help : context -> string - - (** Retrieves parameter descriptions for simplifier. *) - val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs - - (** The function declaration of the function that is applied in this expression. *) - val get_func_decl : Expr.expr -> FuncDecl.func_decl - - (** Indicates whether the expression is the true or false expression - or something else (L_UNDEF). *) - val get_bool_value : Expr.expr -> Z3enums.lbool - - (** The number of arguments of the expression. *) - val get_num_args : Expr.expr -> int - - (** The arguments of the expression. *) - val get_args : Expr.expr -> Expr.expr list - - (** Update the arguments of the expression using an array of expressions. - The number of new arguments should coincide with the current number of arguments. *) - val update : Expr.expr -> Expr.expr list -> expr - - (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. - - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. *) - val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr - - (** Substitute every occurrence of from in the expression with to. - {!substitute} *) - val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr - - (** Substitute the free variables in the expression with the expressions in the expr array - - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) - val substitute_vars : Expr.expr -> Expr.expr list -> expr - - (** Translates (copies) the term to another context. - @return A copy of the term which is associated with the other context *) - val translate : Expr.expr -> context -> expr - - (** Returns a string representation of the expression. *) - val to_string : Expr.expr -> string - - (** Indicates whether the term is a numeral *) - val is_numeral : Expr.expr -> bool - - (** Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. *) - val is_well_sorted : Expr.expr -> bool - - (** The Sort of the term. *) - val get_sort : Expr.expr -> Sort.sort - - (** Indicates whether the term has Boolean sort. *) - val is_bool : Expr.expr -> bool - - (** Indicates whether the term represents a constant. *) - val is_const : Expr.expr -> bool - - (** Indicates whether the term is the constant true. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is the constant false. *) - val is_false : Expr.expr -> bool - - (** Indicates whether the term is an equality predicate. *) - val is_eq : Expr.expr -> bool - - (** Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct). *) - val is_distinct : Expr.expr -> bool - - (** Indicates whether the term is a ternary if-then-else term *) - val is_ite : Expr.expr -> bool - - (** Indicates whether the term is an n-ary conjunction *) - val is_and : Expr.expr -> bool - - (** Indicates whether the term is an n-ary disjunction *) - val is_or : Expr.expr -> bool - - (** Indicates whether the term is an if-and-only-if (Boolean equivalence, binary) *) - val is_iff : Expr.expr -> bool - - (** Indicates whether the term is an exclusive or *) - val is_xor : Expr.expr -> bool - - (** Indicates whether the term is a negation *) - val is_not : Expr.expr -> bool - - (** Indicates whether the term is an implication *) - val is_implies : Expr.expr -> bool - - (** Indicates whether the term is a label (used by the Boogie Verification condition generator). - The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula. *) - val is_label : Expr.expr -> bool - - (** Indicates whether the term is a label literal (used by the Boogie Verification condition generator). - A label literal has a set of string parameters. It takes no arguments. - let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT) *) - val is_label_lit : Expr.expr -> bool - - (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) - val is_oeq : Expr.expr -> bool - - (** Creates a new constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - - (** Creates a new constant. *) - val mk_const_s : context -> string -> Sort.sort -> expr - - (** Creates a constant from the func_decl. *) - val mk_const_f : context -> FuncDecl.func_decl -> expr - - (** Creates a fresh constant with a name prefixed with a string. *) - val mk_fresh_const : context -> string -> Sort.sort -> expr - - (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - - (** Create a numeral of a given sort. - @return A Term with the goven value and sort *) - val mk_numeral_string : context -> string -> Sort.sort -> expr - - (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @return A Term with the given value and sort *) - val mk_numeral_int : context -> int -> Sort.sort -> expr -end - -(** Boolean expressions *) -module Boolean : -sig - type bool_sort = BoolSort of Sort.sort - type bool_expr = BoolExpr of Expr.expr - - val expr_of_bool_expr : bool_expr -> Expr.expr - val sort_of_bool_sort : bool_sort -> Sort.sort - val bool_sort_of_sort : Sort.sort -> bool_sort - val bool_expr_of_expr : Expr.expr -> bool_expr - - (** Create a Boolean sort *) - val mk_sort : context -> bool_sort - - (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> bool_expr - - (** Create a Boolean constant. *) - val mk_const_s : context -> string -> bool_expr - - (** The true Term. *) - val mk_true : context -> bool_expr - - (** The false Term. *) - val mk_false : context -> bool_expr - - (** Creates a Boolean value. *) - val mk_val : context -> bool -> bool_expr - - (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> bool_expr - - (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr list -> bool_expr - - (** Mk an expression representing not(a). *) - val mk_not : context -> bool_expr -> bool_expr - - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) - val mk_ite : context -> bool_expr -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 iff t2. *) - val mk_iff : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 -> t2. *) - val mk_implies : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing t1 xor t2. *) - val mk_xor : context -> bool_expr -> bool_expr -> bool_expr - - (** Create an expression representing the AND of args *) - val mk_and : context -> bool_expr list -> bool_expr - - (** Create an expression representing the OR of args *) - val mk_or : context -> bool_expr list -> bool_expr -end - -(** Quantifier expressions *) -module Quantifier : -sig - type quantifier = Quantifier of Expr.expr - - val expr_of_quantifier : quantifier -> Expr.expr - val quantifier_of_expr : Expr.expr -> quantifier - - (** Quantifier patterns - - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is - also called a multi-pattern. *) - module Pattern : - sig - type pattern = Pattern of AST.ast - - val ast_of_pattern : pattern -> AST.ast - val pattern_of_ast : AST.ast -> pattern - - (** The number of terms in the pattern. *) - val get_num_terms : pattern -> int - - (** The terms in the pattern. *) - val get_terms : pattern -> Expr.expr list - - (** A string representation of the pattern. *) - val to_string : pattern -> string - end - - - (** The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. *) - val get_index : Expr.expr -> int - - (** Indicates whether the quantifier is universal. *) - val is_universal : quantifier -> bool - - (** Indicates whether the quantifier is existential. *) - val is_existential : quantifier -> bool - - (** The weight of the quantifier. *) - val get_weight : quantifier -> int - - (** The number of patterns. *) - val get_num_patterns : quantifier -> int - - (** The patterns. *) - val get_patterns : quantifier -> Pattern.pattern list - - (** The number of no-patterns. *) - val get_num_no_patterns : quantifier -> int - - (** The no-patterns. *) - val get_no_patterns : quantifier -> Pattern.pattern list - - (** The number of bound variables. *) - val get_num_bound : quantifier -> int - - (** The symbols for the bound variables. *) - val get_bound_variable_names : quantifier -> Symbol.symbol list - - (** The sorts of the bound variables. *) - val get_bound_variable_sorts : quantifier -> Sort.sort list - - (** The body of the quantifier. *) - val get_body : quantifier -> Boolean.bool_expr - - (** Creates a new bound variable. *) - val mk_bound : context -> int -> Sort.sort -> Expr.expr - - (** Create a quantifier pattern. *) - val mk_pattern : context -> Expr.expr list -> Pattern.pattern - - (** Create a universal Quantifier. *) - val mk_forall : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a universal Quantifier. *) - val mk_forall_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create an existential Quantifier. *) - val mk_exists_const : context -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> Sort.sort list -> Symbol.symbol list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - - (** Create a Quantifier. *) - val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier -end - -(** Functions to manipulate Array expressions *) -module Array_ : -sig - type array_sort = ArraySort of Sort.sort - type array_expr = ArrayExpr of Expr.expr - - val sort_of_array_sort : array_sort -> Sort.sort - val array_sort_of_sort : Sort.sort -> array_sort - val expr_of_array_expr : array_expr -> Expr.expr - - val array_expr_of_expr : Expr.expr -> array_expr - - (** Create a new array sort. *) - val mk_sort : context -> Sort.sort -> Sort.sort -> array_sort - - (** Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an array select. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. *) - val is_constant_array : Expr.expr -> bool - - (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. *) - val is_default_array : Expr.expr -> bool - - (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) - val is_array_map : Expr.expr -> bool - - (** Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. *) - val is_as_array : Expr.expr -> bool - - (** Indicates whether the term is of an array sort. *) - val is_array : Expr.expr -> bool - - (** The domain of the array sort. *) - val get_domain : array_sort -> Sort.sort - - (** The range of the array sort. *) - val get_range : array_sort -> Sort.sort - - (** Create an array constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> array_expr - - (** Create an array constant. *) - val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> array_expr - - (** Array read. - - The argument a is the array and i is the index - of the array that gets read. - - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. - {!Array_.mk_sort} - {!mk_store} *) - val mk_select : context -> array_expr -> Expr.expr -> array_expr - - (** Array update. - - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). - {!Array_.mk_sort} - {!mk_select} *) - val mk_store : context -> array_expr -> Expr.expr -> Expr.expr -> array_expr - - (** Create a constant array. - - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. - {!Array_.mk_sort} - {!mk_select} *) - val mk_const_array : context -> Sort.sort -> Expr.expr -> array_expr - - (** Maps f on the argument arrays. - - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. - {!Array_.mk_sort} - {!mk_select} - {!mk_store} *) - val mk_map : context -> FuncDecl.func_decl -> array_expr list -> array_expr - - (** Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. *) - val mk_term_array : context -> array_expr -> array_expr -end - -(** Functions to manipulate Set expressions *) -module Set : -sig - type set_sort = SetSort of Sort.sort - - val sort_of_set_sort : set_sort -> Sort.sort - - (** Create a set type. *) - val mk_sort : context -> Sort.sort -> set_sort - - (** Indicates whether the term is set union *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is set intersection *) - val is_intersect : Expr.expr -> bool - - (** Indicates whether the term is set difference *) - val is_difference : Expr.expr -> bool - - (** Indicates whether the term is set complement *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is set subset *) - val is_subset : Expr.expr -> bool - - (** Create an empty set. *) - val mk_empty : context -> Sort.sort -> Expr.expr - - (** Create the full set. *) - val mk_full : context -> Sort.sort -> Expr.expr - - (** Add an element to the set. *) - val mk_set_add : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Remove an element from a set. *) - val mk_del : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the union of a list of sets. *) - val mk_union : context -> Expr.expr list -> Expr.expr - - (** Take the intersection of a list of sets. *) - val mk_intersection : context -> Expr.expr list -> Expr.expr - - (** Take the difference between two sets. *) - val mk_difference : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Take the complement of a set. *) - val mk_complement : context -> Expr.expr -> Expr.expr - - (** Check for set membership. *) - val mk_membership : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Check for subsetness of sets. *) - val mk_subset : context -> Expr.expr -> Expr.expr -> Expr.expr -end - -(** Functions to manipulate Finite Domain expressions *) -module FiniteDomain : -sig - type finite_domain_sort = FiniteDomainSort of Sort.sort - - val sort_of_finite_domain_sort : finite_domain_sort -> Sort.sort - val finite_domain_sort_of_sort : Sort.sort -> finite_domain_sort - - (** Create a new finite domain sort. *) - val mk_sort : context -> Symbol.symbol -> int -> finite_domain_sort - - (** Create a new finite domain sort. *) - val mk_sort_s : context -> string -> int -> finite_domain_sort - - (** Indicates whether the term is of an array sort. *) - val is_finite_domain : Expr.expr -> bool - - (** Indicates whether the term is a less than predicate over a finite domain. *) - val is_lt : Expr.expr -> bool - - (** The size of the finite domain sort. *) - val get_size : finite_domain_sort -> int -end - - -(** Functions to manipulate Relation expressions *) -module Relation : -sig - type relation_sort = RelationSort of Sort.sort - - val sort_of_relation_sort : relation_sort -> Sort.sort - val relation_sort_of_sort : Sort.sort -> relation_sort - - (** Indicates whether the term is of a relation sort. *) - val is_relation : Expr.expr -> bool - - (** Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. *) - val is_store : Expr.expr -> bool - - (** Indicates whether the term is an empty relation *) - val is_empty : Expr.expr -> bool - - (** Indicates whether the term is a test for the emptiness of a relation *) - val is_is_empty : Expr.expr -> bool - - (** Indicates whether the term is a relational join *) - val is_join : Expr.expr -> bool - - (** Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. *) - val is_union : Expr.expr -> bool - - (** Indicates whether the term is the widening of two relations - The function takes two arguments. *) - val is_widen : Expr.expr -> bool - - (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. *) - val is_project : Expr.expr -> bool - - (** Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. *) - val is_filter : Expr.expr -> bool - - (** Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. *) - val is_negation_filter : Expr.expr -> bool - - (** Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. *) - val is_rename : Expr.expr -> bool - - (** Indicates whether the term is the complement of a relation *) - val is_complement : Expr.expr -> bool - - (** Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. *) - val is_select : Expr.expr -> bool - - (** Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind {!is_union} - to perform destructive updates to the first argument. *) - val is_clone : Expr.expr -> bool - - (** The arity of the relation sort. *) - val get_arity : relation_sort -> int - - (** The sorts of the columns of the relation sort. *) - val get_column_sorts : relation_sort -> relation_sort list -end - -(** Functions to manipulate Datatype expressions *) -module Datatype : -sig - type datatype_sort = DatatypeSort of Sort.sort - type datatype_expr = DatatypeExpr of Expr.expr - - val sort_of_datatype_sort : datatype_sort -> Sort.sort - val datatype_sort_of_sort : Sort.sort -> datatype_sort - val expr_of_datatype_expr : datatype_expr -> Expr.expr - val datatype_expr_of_expr : Expr.expr -> datatype_expr - - (** Datatype Constructors *) - module Constructor : - sig - type constructor - - (** The number of fields of the constructor. *) - val get_num_fields : constructor -> int - - (** The function declaration of the constructor. *) - val get_constructor_decl : constructor -> FuncDecl.func_decl - - (** The function declaration of the tester. *) - val get_tester_decl : constructor -> FuncDecl.func_decl - - (** The function declarations of the accessors *) - val get_accessor_decls : constructor -> FuncDecl.func_decl list - end - - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor - - (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor - - (** Create a new datatype sort. *) - val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> datatype_sort - - (** Create a new datatype sort. *) - val mk_sort_s : context -> string -> Constructor.constructor list -> datatype_sort - - (** Create mutually recursive datatypes. *) - val mk_sorts : context -> Symbol.symbol list -> Constructor.constructor list list -> datatype_sort list - - (** Create mutually recursive data-types. *) - val mk_sorts_s : context -> string list -> Constructor.constructor list list -> datatype_sort list - - - (** The number of constructors of the datatype sort. *) - val get_num_constructors : datatype_sort -> int - - (** The constructors. *) - val get_constructors : datatype_sort -> FuncDecl.func_decl list - - (** The recognizers. *) - val get_recognizers : datatype_sort -> FuncDecl.func_decl list - - (** The constructor accessors. *) - val get_accessors : datatype_sort -> FuncDecl.func_decl list list -end - -(** Functions to manipulate Enumeration expressions *) -module Enumeration : -sig - type enum_sort = EnumSort of Sort.sort - - val sort_of_enum_sort : enum_sort -> Sort.sort - - (** Create a new enumeration sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> enum_sort - - (** Create a new enumeration sort. *) - val mk_sort_s : context -> string -> string list -> enum_sort - - (** The function declarations of the constants in the enumeration. *) - val get_const_decls : enum_sort -> FuncDecl.func_decl list - - (** The test predicates for the constants in the enumeration. *) - val get_tester_decls : enum_sort -> FuncDecl.func_decl list -end - -(** Functions to manipulate List expressions *) -module List_ : -sig - type list_sort = ListSort of Sort.sort - - val sort_of_list_sort : list_sort -> Sort.sort - - (** Create a new list sort. *) - val mk_sort : context -> Symbol.symbol -> Sort.sort -> list_sort - - (** Create a new list sort. *) - val mk_list_s : context -> string -> Sort.sort -> list_sort - - (** The declaration of the nil function of this list sort. *) - val get_nil_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the isNil function of this list sort. *) - val get_is_nil_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the cons function of this list sort. *) - val get_cons_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the isCons function of this list sort. *) - val get_is_cons_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the head function of this list sort. *) - val get_head_decl : list_sort -> FuncDecl.func_decl - - (** The declaration of the tail function of this list sort. *) - val get_tail_decl : list_sort -> FuncDecl.func_decl - - (** The empty list. *) - val nil : list_sort -> Expr.expr -end - -(** Functions to manipulate Tuple expressions *) -module Tuple : -sig - type tuple_sort = TupleSort of Sort.sort - - val sort_of_tuple_sort : tuple_sort -> Sort.sort - - (** Create a new tuple sort. *) - val mk_sort : context -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> tuple_sort - - (** The constructor function of the tuple. *) - val get_mk_decl : tuple_sort -> FuncDecl.func_decl - - (** The number of fields in the tuple. *) - val get_num_fields : tuple_sort -> int - - (** The field declarations. *) - val get_field_decls : tuple_sort -> FuncDecl.func_decl list -end - -(** Functions to manipulate arithmetic expressions *) -module rec Arithmetic : -sig - type arith_sort = ArithSort of Sort.sort - type arith_expr = ArithExpr of Expr.expr - - val sort_of_arith_sort : Arithmetic.arith_sort -> Sort.sort - val arith_sort_of_sort : Sort.sort -> Arithmetic.arith_sort - val expr_of_arith_expr : Arithmetic.arith_expr -> Expr.expr - val arith_expr_of_expr : Expr.expr -> Arithmetic.arith_expr - - (** Integer Arithmetic *) - module rec Integer : - sig - type int_sort = IntSort of arith_sort - type int_expr = IntExpr of arith_expr - type int_num = IntNum of int_expr - - val arith_sort_of_int_sort : Arithmetic.Integer.int_sort -> Arithmetic.arith_sort - val int_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Integer.int_sort - val arith_expr_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.arith_expr - val int_expr_of_int_num : Arithmetic.Integer.int_num -> Arithmetic.Integer.int_expr - val int_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Integer.int_expr - val int_num_of_int_expr : Arithmetic.Integer.int_expr -> Arithmetic.Integer.int_num - - (** Create a new integer sort. *) - val mk_sort : context -> int_sort - - (** Retrieve the int value. *) - val get_int : int_num -> int - - (** Returns a string representation of the numeral. *) - val to_string : int_num -> string - - (** Creates an integer constant. *) - val mk_const : context -> Symbol.symbol -> int_expr - - (** Creates an integer constant. *) - val mk_const_s : context -> string -> int_expr - - (** Create an expression representing t1 mod t2. - The arguments must have int type. *) - val mk_mod : context -> int_expr -> int_expr -> int_expr - - (** Create an expression representing t1 rem t2. - The arguments must have int type. *) - val mk_rem : context -> int_expr -> int_expr -> int_expr - - (** Create an integer numeral. *) - val mk_numeral_s : context -> string -> int_num - - (** Create an integer numeral. - @return A Term with the given value and sort Integer *) - val mk_numeral_i : context -> int -> int_num - - (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. - The argument must be of integer sort. *) - val mk_int2real : context -> int_expr -> Real.real_expr - - (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) - val mk_int2bv : context -> int -> int_expr -> BitVector.bitvec_expr - end - - (** Real Arithmetic *) - and Real : - sig - type real_sort = RealSort of arith_sort - type real_expr = RealExpr of arith_expr - type rat_num = RatNum of real_expr - - val arith_sort_of_real_sort : Arithmetic.Real.real_sort -> Arithmetic.arith_sort - val real_sort_of_arith_sort : Arithmetic.arith_sort -> Arithmetic.Real.real_sort - val arith_expr_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.arith_expr - val real_expr_of_rat_num : Arithmetic.Real.rat_num -> Arithmetic.Real.real_expr - val real_expr_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.Real.real_expr - val rat_num_of_real_expr : Arithmetic.Real.real_expr -> Arithmetic.Real.rat_num - - (** Create a real sort. *) - val mk_sort : context -> real_sort - - (** The numerator of a rational numeral. *) - val get_numerator : rat_num -> Integer.int_num - - (** The denominator of a rational numeral. *) - val get_denominator : rat_num -> Integer.int_num - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as indicated by the int argument.*) - val to_decimal_string : rat_num -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : rat_num -> string - - (** Creates a real constant. *) - val mk_const : context -> Symbol.symbol -> real_expr - - (** Creates a real constant. *) - val mk_const_s : context -> string -> real_expr - - (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) - val mk_numeral_nd : context -> int -> int -> rat_num - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_s : context -> string -> rat_num - - (** Create a real numeral. - @return A Term with the given value and sort Real *) - val mk_numeral_i : context -> int -> rat_num - - (** Creates an expression that checks whether a real number is an integer. *) - val mk_is_integer : context -> real_expr -> Boolean.bool_expr - - (** Coerce a real to an integer. - - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) - val mk_real2int : context -> real_expr -> Integer.int_expr - end - - (** Algebraic Numbers *) - and AlgebraicNumber : - sig - type algebraic_num = AlgebraicNum of arith_expr - - val arith_expr_of_algebraic_num : Arithmetic.AlgebraicNumber.algebraic_num -> Arithmetic.arith_expr - val algebraic_num_of_arith_expr : Arithmetic.arith_expr -> Arithmetic.AlgebraicNumber.algebraic_num - - (** Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_upper : algebraic_num -> int -> Real.rat_num - - (** Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) - val to_lower : algebraic_num -> int -> Real.rat_num - - (** Returns a string representation in decimal notation. - The result has at most as many decimal places as the int argument provided.*) - val to_decimal_string : algebraic_num -> int -> string - - (** Returns a string representation of the numeral. *) - val to_string : algebraic_num -> string - end - - (** Indicates whether the term is of integer sort. *) - val is_int : Expr.expr -> bool - - (** Indicates whether the term is an arithmetic numeral. *) - val is_arithmetic_numeral : Expr.expr -> bool - - (** Indicates whether the term is a less-than-or-equal *) - val is_le : Expr.expr -> bool - - (** Indicates whether the term is a greater-than-or-equal *) - val is_ge : Expr.expr -> bool - - (** Indicates whether the term is a less-than *) - val is_lt : Expr.expr -> bool - - (** Indicates whether the term is a greater-than *) - val is_gt : Expr.expr -> bool - - (** Indicates whether the term is addition (binary) *) - val is_add : Expr.expr -> bool - - (** Indicates whether the term is subtraction (binary) *) - val is_sub : Expr.expr -> bool - - (** Indicates whether the term is a unary minus *) - val is_uminus : Expr.expr -> bool - - (** Indicates whether the term is multiplication (binary) *) - val is_mul : Expr.expr -> bool - - (** Indicates whether the term is division (binary) *) - val is_div : Expr.expr -> bool - - (** Indicates whether the term is integer division (binary) *) - val is_idiv : Expr.expr -> bool - - (** Indicates whether the term is remainder (binary) *) - val is_remainder : Expr.expr -> bool - - (** Indicates whether the term is modulus (binary) *) - val is_modulus : Expr.expr -> bool - - (** Indicates whether the term is a coercion of integer to real (unary) *) - val is_inttoreal : Expr.expr -> bool - - (** Indicates whether the term is a coercion of real to integer (unary) *) - val is_real_to_int : Expr.expr -> bool - - (** Indicates whether the term is a check that tests whether a real is integral (unary) *) - val is_real_is_int : Expr.expr -> bool - - (** Indicates whether the term is of sort real. *) - val is_real : Expr.expr -> bool - - (** Indicates whether the term is an integer numeral. *) - val is_int_numeral : Expr.expr -> bool - - (** Indicates whether the term is a real numeral. *) - val is_rat_num : Expr.expr -> bool - - (** Indicates whether the term is an algebraic number *) - val is_algebraic_number : Expr.expr -> bool - - (** Create an expression representing t[0] + t[1] + .... *) - val mk_add : context -> arith_expr list -> arith_expr - - (** Create an expression representing t[0] * t[1] * .... *) - val mk_mul : context -> arith_expr list -> arith_expr - - (** Create an expression representing t[0] - t[1] - .... *) - val mk_sub : context -> arith_expr list -> arith_expr - - (** Create an expression representing -t. *) - val mk_unary_minus : context -> arith_expr -> arith_expr - - (** Create an expression representing t1 / t2. *) - val mk_div : context -> arith_expr -> arith_expr -> arith_expr - - (** Create an expression representing t1 ^ t2. *) - val mk_power : context -> arith_expr -> arith_expr -> arith_expr - - (** Create an expression representing t1 < t2 *) - val mk_lt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 <= t2 *) - val mk_le : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 > t2 *) - val mk_gt : context -> arith_expr -> arith_expr -> Boolean.bool_expr - - (** Create an expression representing t1 >= t2 *) - val mk_ge : context -> arith_expr -> arith_expr -> Boolean.bool_expr -end - -(** Functions to manipulate bit-vector expressions *) -and BitVector : -sig - type bitvec_sort = BitVecSort of Sort.sort - type bitvec_expr = BitVecExpr of Expr.expr - type bitvec_num = BitVecNum of bitvec_expr - - val sort_of_bitvec_sort : BitVector.bitvec_sort -> Sort.sort - val bitvec_sort_of_sort : Sort.sort -> BitVector.bitvec_sort - val expr_of_bitvec_expr : BitVector.bitvec_expr -> Expr.expr - val bitvec_expr_of_bitvec_num : BitVector.bitvec_num -> BitVector.bitvec_expr - val bitvec_expr_of_expr : Expr.expr -> BitVector.bitvec_expr - val bitvec_num_of_bitvec_expr : BitVector.bitvec_expr -> BitVector.bitvec_num - - (** Create a new bit-vector sort. *) - val mk_sort : context -> int -> bitvec_sort - - (** Indicates whether the terms is of bit-vector sort. *) - val is_bv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector numeral *) - val is_bv_numeral : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value one *) - val is_bv_bit1 : Expr.expr -> bool - - (** Indicates whether the term is a one-bit bit-vector with value zero *) - val is_bv_bit0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unary minus *) - val is_bv_uminus : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector addition (binary) *) - val is_bv_add : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector subtraction (binary) *) - val is_bv_sub : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector multiplication (binary) *) - val is_bv_mul : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division (binary) *) - val is_bv_sdiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division (binary) *) - val is_bv_udiv : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder (binary) *) - val is_bv_SRem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder (binary) *) - val is_bv_urem : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus *) - val is_bv_smod : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed division by zero *) - val is_bv_sdiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned division by zero *) - val is_bv_udiv0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed remainder by zero *) - val is_bv_srem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector unsigned remainder by zero *) - val is_bv_urem0 : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector signed modulus by zero *) - val is_bv_smod0 : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than-or-equal *) - val is_bv_ule : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than-or-equal *) - val is_bv_sle : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than-or-equal *) - val is_bv_uge : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than-or-equal *) - val is_bv_sge : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector less-than *) - val is_bv_ult : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector less-than *) - val is_bv_slt : Expr.expr -> bool - - (** Indicates whether the term is an unsigned bit-vector greater-than *) - val is_bv_ugt : Expr.expr -> bool - - (** Indicates whether the term is a signed bit-vector greater-than *) - val is_bv_sgt : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise AND *) - val is_bv_and : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise OR *) - val is_bv_or : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOT *) - val is_bv_not : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XOR *) - val is_bv_xor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NAND *) - val is_bv_nand : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise NOR *) - val is_bv_nor : Expr.expr -> bool - - (** Indicates whether the term is a bit-wise XNOR *) - val is_bv_xnor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector concatenation (binary) *) - val is_bv_concat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector sign extension *) - val is_bv_signextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector zero extension *) - val is_bv_zeroextension : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector extraction *) - val is_bv_extract : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector repetition *) - val is_bv_repeat : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce OR *) - val is_bv_reduceor : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector reduce AND *) - val is_bv_reduceand : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector comparison *) - val is_bv_comp : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector shift left *) - val is_bv_shiftleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector logical shift right *) - val is_bv_shiftrightlogical : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector arithmetic shift left *) - val is_bv_shiftrightarithmetic : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left *) - val is_bv_rotateleft : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right *) - val is_bv_rotateright : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotateleftextended : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) - val is_bv_rotaterightextended : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - - (** Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_int_to_bv : Expr.expr -> bool - - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - val is_bv_to_int : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) - val is_bv_carry : Expr.expr -> bool - - (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) - val is_bv_xor3 : Expr.expr -> bool - - (** The size of a bit-vector sort. *) - val get_size : bitvec_sort -> int - - (** Retrieve the int value. *) - val get_int : bitvec_num -> int - - (** Returns a string representation of the numeral. *) - val to_string : bitvec_num -> string - - (** Creates a bit-vector constant. *) - val mk_const : context -> Symbol.symbol -> int -> bitvec_expr - - (** Creates a bit-vector constant. *) - val mk_const_s : context -> string -> int -> bitvec_expr - - (** Bitwise negation. - The argument must have a bit-vector sort. *) - val mk_not : context -> bitvec_expr -> Expr.expr - - (** Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redand : context -> bitvec_expr -> Expr.expr - - (** Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) - val mk_redor : context -> bitvec_expr -> Expr.expr - - (** Bitwise conjunction. - The arguments must have a bit-vector sort. *) - val mk_and : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise disjunction. - The arguments must have a bit-vector sort. *) - val mk_or : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise XOR. - The arguments must have a bit-vector sort. *) - val mk_xor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise NAND. - The arguments must have a bit-vector sort. *) - val mk_nand : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise NOR. - The arguments must have a bit-vector sort. *) - val mk_nor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bitwise XNOR. - The arguments must have a bit-vector sort. *) - val mk_xnor : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Standard two's complement unary minus. - The arguments must have a bit-vector sort. *) - val mk_neg : context -> bitvec_expr -> bitvec_expr - - (** Two's complement addition. - The arguments must have the same bit-vector sort. *) - val mk_add : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement subtraction. - The arguments must have the same bit-vector sort. *) - val mk_sub : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement multiplication. - The arguments must have the same bit-vector sort. *) - val mk_mul : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned division. - - - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. *) - val mk_udiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Signed division. - - It is defined in the following way: - - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. - - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_sdiv : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned remainder. - - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_urem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Signed remainder. - - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_srem : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Two's complement signed remainder (sign follows divisor). - - If t2 is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) - val mk_smod : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Unsigned less-than - - The arguments must have the same bit-vector sort. *) - val mk_ult : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed less-than - - The arguments must have the same bit-vector sort. *) - val mk_slt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_ule : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sle : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_uge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. *) - val mk_sge : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Unsigned greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_ugt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. *) - val mk_sgt : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). *) - val mk_concat : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Bit-vector extraction. - - Extract the bits between two limits from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. *) - val mk_extract : context -> int -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector sign extension. - - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. *) - val mk_sign_ext : context -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector zero extension. - - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the - given bit-vector. *) - val mk_zero_ext : context -> int -> bitvec_expr -> bitvec_expr - - (** Bit-vector repetition. *) - val mk_repeat : context -> int -> bitvec_expr -> bitvec_expr - - (** Shift left. - - It is equivalent to multiplication by 2^x where \c x is the value of third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling.*) - val mk_shl : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Logical shift right - - It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_lshr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. - - The arguments must have a bit-vector sort. *) - val mk_ashr : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Rotate Left. - Rotate bits of \c t to the left \c i times. *) - val mk_rotate_left : context -> int -> bitvec_expr -> bitvec_expr - - (** Rotate Right. - Rotate bits of \c t to the right \c i times.*) - val mk_rotate_right : context -> int -> bitvec_expr -> bitvec_expr - - (** Rotate Left. - Rotate bits of the second argument to the left.*) - val mk_ext_rotate_left : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Rotate Right. - Rotate bits of the second argument to the right. *) - val mk_ext_rotate_right : context -> bitvec_expr -> bitvec_expr -> bitvec_expr - - (** Create an integer from the bit-vector argument - - If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where - N are the number of bits in the argument. - If \c is_signed is true, \c t1 is treated as a signed bit-vector. - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function.*) - val mk_bv2int : context -> bitvec_expr -> bool -> Arithmetic.Integer.int_expr - - (** Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_add_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_sub_no_underflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_sdiv_no_overflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_neg_no_overflow : context -> bitvec_expr -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_overflow : context -> bitvec_expr -> bitvec_expr -> bool -> Boolean.bool_expr - - (** Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> bitvec_expr -> bitvec_expr -> Boolean.bool_expr - - (** Create a bit-vector numeral. *) - val mk_numeral : context -> string -> int -> bitvec_num -end - -(** Functions to manipulate proof expressions *) -module Proof : -sig - (** Indicates whether the term is a Proof for the expression 'true'. *) - val is_true : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact asserted by the user. *) - val is_asserted : Expr.expr -> bool - - (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) - val is_goal : Expr.expr -> bool - - (** Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). *) - val is_modus_ponens : Expr.expr -> bool - - (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. *) - val is_reflexivity : Expr.expr -> bool - - (** Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. *) - val is_symmetry : Expr.expr -> bool - - (** Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) *) - val is_transitivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. *) - val is_Transitivity_star : Expr.expr -> bool - - (** Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. *) - val is_monotonicity : Expr.expr -> bool - - (** Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) - val is_quant_intro : Expr.expr -> bool - - (** Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. *) - val is_distributivity : Expr.expr -> bool - - (** Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i *) - val is_and_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) *) - val is_or_elimination : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) *) - val is_rewrite : Expr.expr -> bool - - (** Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) - val is_rewrite_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) - val is_pull_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents *) - val is_pull_quant_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents *) - val is_push_quant : Expr.expr -> bool - - (** Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. *) - val is_elim_unused_vars : Expr.expr -> bool - - (** Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. *) - val is_der : Expr.expr -> bool - - (** Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) *) - val is_quant_inst : Expr.expr -> bool - - (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. *) - val is_hypothesis : Expr.expr -> bool - - (** Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. *) - val is_lemma : Expr.expr -> bool - - (** Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) - val is_unit_resolution : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) *) - val is_iff_true : Expr.expr -> bool - - (** Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) *) - val is_iff_false : Expr.expr -> bool - - (** Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. *) - val is_commutativity : Expr.expr -> bool - - (** Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). *) - val is_def_axiom : Expr.expr -> bool - - (** Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) *) - val is_def_intro : Expr.expr -> bool - - (** Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. *) - val is_apply_def : Expr.expr -> bool - - (** Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) *) - val is_iff_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. *) - val is_nnf_pos : Expr.expr -> bool - - (** Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) *) - val is_nnf_neg : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_nnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) - val is_cnf_star : Expr.expr -> bool - - (** Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. *) - val is_skolemize : Expr.expr -> bool - - (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q *) - val is_modus_ponens_oeq : Expr.expr -> bool - - (** Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) - val is_theory_lemma : Expr.expr -> bool -end - -(** Goals - - A goal (aka problem). A goal is essentially a - of formulas, that can be solved and/or transformed using - tactics and solvers. *) -module Goal : -sig - type goal - - (** The precision of the goal. - - Goals can be transformed using over and under approximations. - An under approximation is applied when the objective is to find a model for a given goal. - An over approximation is applied when the objective is to find a proof for a given goal. *) - val get_precision : goal -> Z3enums.goal_prec - - (** Indicates whether the goal is precise. *) - val is_precise : goal -> bool - - (** Indicates whether the goal is an under-approximation. *) - val is_underapproximation : goal -> bool - - (** Indicates whether the goal is an over-approximation. *) - val is_overapproximation : goal -> bool - - (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) - val is_garbage : goal -> bool - - (** Adds the constraints to the given goal. *) - val assert_ : goal -> Boolean.bool_expr list -> unit - - (** Indicates whether the goal contains `false'. *) - val is_inconsistent : goal -> bool - - (** The depth of the goal. - This tracks how many transformations were applied to it. *) - val get_depth : goal -> int - - (** Erases all formulas from the given goal. *) - val reset : goal -> unit - - (** The number of formulas in the goal. *) - val get_size : goal -> int - - (** The formulas in the goal. *) - val get_formulas : goal -> Boolean.bool_expr list - - (** The number of formulas, subformulas and terms in the goal. *) - val get_num_exprs : goal -> int - - (** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *) - val is_decided_sat : goal -> bool - - (** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *) - val is_decided_unsat : goal -> bool - - (** Translates (copies) the Goal to another context.. *) - val translate : goal -> context -> goal - - (** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *) - val simplify : goal -> Params.params option -> goal - - (** Creates a new Goal. - - Note that the Context must have been created with proof generation support if - the fourth argument is set to true here. *) - val mk_goal : context -> bool -> bool -> bool -> goal - - (** A string representation of the Goal. *) - val to_string : goal -> string -end - -(** Models - - A Model contains interpretations (assignments) of constants and functions. *) -module Model : -sig - type model - - (** Function interpretations - - A function interpretation is represented as a finite map and an 'else'. - Each entry in the finite map represents the value of a function given a set of arguments. *) - module FuncInterp : - sig - type func_interp - - (** Function interpretations entries - - An Entry object represents an element in the finite map used to a function interpretation. *) - module FuncEntry : - sig - type func_entry - - (** Return the (symbolic) value of this entry. - *) - val get_value : func_entry -> Expr.expr - - (** The number of arguments of the entry. - *) - val get_num_args : func_entry -> int - - (** The arguments of the function entry. - *) - val get_args : func_entry -> Expr.expr list - - (** A string representation of the function entry. - *) - val to_string : func_entry -> string - end - - (** The number of entries in the function interpretation. *) - val get_num_entries : func_interp -> int - - (** The entries in the function interpretation *) - val get_entries : func_interp -> FuncEntry.func_entry list - - (** The (symbolic) `else' value of the function interpretation. *) - val get_else : func_interp -> Expr.expr - - (** The arity of the function interpretation *) - val get_arity : func_interp -> int - - (** A string representation of the function interpretation. *) - val to_string : func_interp -> string - end - - (** Retrieves the interpretation (the assignment) of a func_decl in the model. - An expression if the function has an interpretation in the model, null otherwise. *) - val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of an expression in the model. - An expression if the constant has an interpretation in the model, null otherwise. *) - val get_const_interp_e : model -> Expr.expr -> Expr.expr option - - (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) - val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option - - (** The number of constant interpretations in the model. *) - val get_num_consts : model -> int - - (** The function declarations of the constants in the model. *) - val get_const_decls : model -> FuncDecl.func_decl list - - (** The number of function interpretations in the model. *) - val get_num_funcs : model -> int - - (** The function declarations of the function interpretations in the model. *) - val get_func_decls : model -> FuncDecl.func_decl list - - (** All symbols that have an interpretation in the model. *) - val get_decls : model -> FuncDecl.func_decl list - - (** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *) - exception ModelEvaluationFailedException of string - - (** Evaluates an expression in the current model. - - This function may fail if the argument contains quantifiers, - is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. - *) - val eval : model -> Expr.expr -> bool -> Expr.expr - - (** Alias for eval. *) - val evaluate : model -> Expr.expr -> bool -> Expr.expr - - (** The number of uninterpreted sorts that the model has an interpretation for. *) - val get_num_sorts : model -> int - - (** The uninterpreted sorts that the model has an interpretation for. - - Z3 also provides an intepretation for uninterpreted sorts used in a formula. - The interpretation for a sort is a finite set of distinct values. We say this finite set is - the "universe" of the sort. - {!get_num_sorts} - {!sort_universe} *) - val get_sorts : model -> Sort.sort list - - (** The finite set of distinct values that represent the interpretation of a sort. - {!get_sorts} - @returns A list of expressions, where each is an element of the universe of the sort *) - val sort_universe : model -> Sort.sort -> AST.ast list - - (** Conversion of models to strings. - A string representation of the model. *) - val to_string : model -> string -end - -(** Probes - - Probes are used to inspect a goal (aka problem) and collect information that may be used to decide - which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Probe : -sig - type probe - - (** Execute the probe over the goal. - A probe always produce a double value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) - val apply : probe -> Goal.goal -> float - - (** The number of supported Probes. *) - val get_num_probes : context -> int - - (** The names of all supported Probes. *) - val get_probe_names : context -> string list - - (** Returns a string containing a description of the probe with the given name. *) - val get_probe_description : context -> string -> string - - (** Creates a new Probe. *) - val mk_probe : context -> string -> probe - - (** Create a probe that always evaluates to a float value. *) - val const : context -> float -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than the value returned by second argument *) - val lt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than the value returned by second argument *) - val gt : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is less than or equal the value returned by second argument *) - val le : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is greater than or equal the value returned by second argument *) - val ge : context -> probe -> probe -> probe - - - (** Create a probe that evaluates to "true" when the value returned by the first argument - is equal the value returned by second argument *) - val eq : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when both of two probes evaluate to "true". *) - val and_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when either of two probes evaluates to "true". *) - val or_ : context -> probe -> probe -> probe - - (** Create a probe that evaluates to "true" when another probe does not evaluate to "true". *) - val not_ : context -> probe -> probe -end - -(** Tactics - - Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. -*) -module Tactic : -sig - type tactic - - (** Tactic application results - - ApplyResult objects represent the result of an application of a - tactic to a goal. It contains the subgoals that were produced. *) - module ApplyResult : - sig - type apply_result - - (** The number of Subgoals. *) - val get_num_subgoals : apply_result -> int - - (** Retrieves the subgoals from the apply_result. *) - val get_subgoals : apply_result -> Goal.goal list - - (** Retrieves a subgoal from the apply_result. *) - val get_subgoal : apply_result -> int -> Goal.goal - - (** Convert a model for a subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g *) - val convert_model : apply_result -> int -> Model.model -> Model.model - - (** A string representation of the ApplyResult. *) - val to_string : apply_result -> string - end - - (** A string containing a description of parameters accepted by the tactic. *) - val get_help : tactic -> string - - (** Retrieves parameter descriptions for Tactics. *) - val get_param_descrs : tactic -> Params.ParamDescrs.param_descrs - - (** Apply the tactic to the goal. *) - val apply : tactic -> Goal.goal -> Params.params option -> ApplyResult.apply_result - - (** The number of supported tactics. *) - val get_num_tactics : context -> int - - (** The names of all supported tactics. *) - val get_tactic_names : context -> string list - - (** Returns a string containing a description of the tactic with the given name. *) - val get_tactic_description : context -> string -> string - - (** Creates a new Tactic. *) - val mk_tactic : context -> string -> tactic - - (** Create a tactic that applies one tactic to a Goal and - then another one to every subgoal produced by the first one. *) - val and_then : context -> tactic -> tactic -> tactic list -> tactic - - (** Create a tactic that first applies one tactic to a Goal and - if it fails then returns the result of another tactic applied to the Goal. *) - val or_else : context -> tactic -> tactic -> tactic - - (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). - - If the tactic does not terminate within the timeout, then it fails. *) - val try_for : context -> tactic -> int -> tactic - - (** Create a tactic that applies one tactic to a given goal if the probe - evaluates to true. - - If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) - val when_ : context -> Probe.probe -> tactic -> tactic - - (** Create a tactic that applies a tactic to a given goal if the probe - evaluates to true and another tactic otherwise. *) - val cond : context -> Probe.probe -> tactic -> tactic -> tactic - - (** Create a tactic that keeps applying one tactic until the goal is not - modified anymore or the maximum number of iterations is reached. *) - val repeat : context -> tactic -> int -> tactic - - (** Create a tactic that just returns the given goal. *) - val skip : context -> tactic - - (** Create a tactic always fails. *) - val fail : context -> tactic - - (** Create a tactic that fails if the probe evaluates to false. *) - val fail_if : context -> Probe.probe -> tactic - - (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). *) - val fail_if_not_decided : context -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. *) - val using_params : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies a tactic using the given set of parameters. - Alias for UsingParams*) - val with_ : context -> tactic -> Params.params -> tactic - - (** Create a tactic that applies the given tactics in parallel. *) - val par_or : context -> tactic list -> tactic - - (** Create a tactic that applies a tactic to a given goal and then another tactic - to every subgoal produced by the first one. The subgoals are processed in parallel. *) - val par_and_then : context -> tactic -> tactic -> tactic - - (** Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. *) - val interrupt : context -> unit -end - -(** Solvers *) -module Solver : -sig - type solver - type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE - - val string_of_status : status -> string - - (** Objects that track statistical information about solvers. *) - module Statistics : - sig - type statistics - - (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - *) - module Entry : - sig - type statistics_entry - - (** The key of the entry. *) - val get_key : statistics_entry -> string - - (** The int-value of the entry. *) - val get_int : statistics_entry -> int - - (** The float-value of the entry. *) - val get_float : statistics_entry -> float - - (** True if the entry is uint-valued. *) - val is_int : statistics_entry -> bool - - (** True if the entry is double-valued. *) - val is_float : statistics_entry -> bool - - (** The string representation of the the entry's value. *) - val to_string_value : statistics_entry -> string - - (** The string representation of the entry (key and value) *) - val to_string : statistics_entry -> string - end - - (** A string representation of the statistical data. *) - val to_string : statistics -> string - - (** The number of statistical data. *) - val get_size : statistics -> int - - (** The data entries. *) - val get_entries : statistics -> Entry.statistics_entry list - - (** The statistical counters. *) - val get_keys : statistics -> string list - - (** The value of a particular statistical counter. *) - val get : statistics -> string -> Entry.statistics_entry option - end - - (** A string that describes all available solver parameters. *) - val get_help : solver -> string - - (** Sets the solver parameters. *) - val set_parameters : solver -> Params.params -> unit - - (** Retrieves parameter descriptions for solver. *) - val get_param_descrs : solver -> Params.ParamDescrs.param_descrs - - (** The current number of backtracking points (scopes). - {!pop} - {!push} *) - val get_num_scopes : solver -> int - - (** Creates a backtracking point. - {!pop} *) - val push : solver -> unit - - (** Backtracks a number of backtracking points. - Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} - {!push} *) - val pop : solver -> int -> unit - - (** Resets the Solver. - This removes all assertions from the solver. *) - val reset : solver -> unit - - (** Assert a constraint (or multiple) into the solver. *) - val assert_ : solver -> Boolean.bool_expr list -> unit - - (** * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track_a : solver -> Boolean.bool_expr list -> Boolean.bool_expr list -> unit - - (** * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) - val assert_and_track : solver -> Boolean.bool_expr -> Boolean.bool_expr -> unit - - (** The number of assertions in the solver. *) - val get_num_assertions : solver -> int - - (** The set of asserted formulas. *) - val get_assertions : solver -> Boolean.bool_expr list - - (** Checks whether the assertions in the solver are consistent or not. - - {!Model} - {!get_unsat_core} - {!Proof} *) - val check : solver -> Boolean.bool_expr list -> status - - (** The model of the last Check. - - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. *) - val get_model : solver -> Model.model option - - (** The proof of the last Check. - - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. *) - val get_proof : solver -> Expr.expr option - - (** The unsat core of the last Check. - - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. *) - val get_unsat_core : solver -> AST.ast list - - (** A brief justification of why the last call to Check returned UNKNOWN. *) - val get_reason_unknown : solver -> string - - (** Solver statistics. *) - val get_statistics : solver -> Statistics.statistics - - (** Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. *) - val mk_solver : context -> Symbol.symbol option -> solver - - (** Creates a new (incremental) solver. - {!mk_solver} *) - val mk_solver_s : context -> string -> solver - - (** Creates a new (incremental) solver. *) - val mk_simple_solver : context -> solver - - (** Creates a solver that is implemented using the given tactic. - - The solver supports the commands Push and Pop, but it - will always solve each check from scratch. *) - val mk_solver_t : context -> Tactic.tactic -> solver - - (** A string representation of the solver. *) - val to_string : solver -> string -end - -(** Fixedpoint solving *) -module Fixedpoint : -sig - type fixedpoint - - (** A string that describes all available fixedpoint solver parameters. *) - val get_help : fixedpoint -> string - - (** Sets the fixedpoint solver parameters. *) - val set_params : fixedpoint -> Params.params -> unit - - (** Retrieves parameter descriptions for Fixedpoint solver. *) - val get_param_descrs : fixedpoint -> Params.ParamDescrs.param_descrs - - (** Assert a constraints into the fixedpoint solver. *) - val assert_ : fixedpoint -> Boolean.bool_expr list -> unit - - (** Register predicate as recursive relation. *) - val register_relation : fixedpoint -> FuncDecl.func_decl -> unit - - (** Add rule into the fixedpoint solver. *) - val add_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol option -> unit - - (** Add table fact to the fixedpoint solver. *) - val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit - - (** Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. *) - val query : fixedpoint -> Boolean.bool_expr -> Solver.status - - (** Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. *) - val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status - - (** Creates a backtracking point. - {!pop} *) - val push : fixedpoint -> unit - - (** Backtrack one backtracking point. - - Note that an exception is thrown if Pop is called without a corresponding Push - {!push} *) - val pop : fixedpoint -> unit - - (** Update named rule into in the fixedpoint solver. *) - val update_rule : fixedpoint -> Boolean.bool_expr -> Symbol.symbol -> unit - - (** Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. *) - val get_answer : fixedpoint -> Expr.expr option - - (** Retrieve explanation why fixedpoint engine returned status Unknown. *) - val get_reason_unknown : fixedpoint -> string - - (** Retrieve the number of levels explored for a given predicate. *) - val get_num_levels : fixedpoint -> FuncDecl.func_decl -> int - - (** Retrieve the cover of a predicate. *) - val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option - - (** Add property about the predicate. - The property is added at level. *) - val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit - - (** Retrieve internal string representation of fixedpoint object. *) - val to_string : fixedpoint -> string - - (** Instrument the Datalog engine on which table representation to use for recursive predicate. *) - val set_predicate_representation : fixedpoint -> FuncDecl.func_decl -> Symbol.symbol list -> unit - - (** Convert benchmark given as set of axioms, rules and queries to a string. *) - val to_string_q : fixedpoint -> Boolean.bool_expr list -> string - - (** Retrieve set of rules added to fixedpoint context. *) - val get_rules : fixedpoint -> Boolean.bool_expr list - - (** Retrieve set of assertions added to fixedpoint context. *) - val get_assertions : fixedpoint -> Boolean.bool_expr list - - (** Create a Fixedpoint context. *) - val mk_fixedpoint : context -> fixedpoint -end - -(** Global and context options - - Note: This module contains functions that set parameters/options for context - objects as well as functions that set options that are used globally, across - contexts.*) -module Options : -sig - (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -ini? - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - {!get_param_value} *) - val update_param_value : context -> string -> string -> unit - - (** Get a configuration parameter. - - Returns None if the parameter value does not exist. - {!update_param_value} *) - val get_param_value : context -> string -> string option - - (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) - val set_print_mode : context -> Z3enums.ast_print_mode -> unit - - (** Enable/disable printing of warning messages to the console. - - Note that this function is static and effects the behaviour of - all contexts globally. *) - val toggle_warning_messages : bool -> unit -end - -(** Functions for handling SMT and SMT2 expressions and files *) -module SMT : -sig - (** Convert a benchmark into an SMT-LIB formatted string. - - @return A string representation of the benchmark. *) - val benchmark_to_smtstring : context -> string -> string -> string -> string -> Boolean.bool_expr list -> Boolean.bool_expr -> string - - (** Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays in the third and fifth argument - don't need to match the names of the sorts and declarations in the arrays in the fourth - and sixth argument. This is a useful feature since we can use arbitrary names to - reference sorts and declarations. *) - val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** Parse the given file using the SMT-LIB parser. - {!parse_smtlib_string} *) - val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - - (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_formulas : context -> int - - (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_formulas : context -> Boolean.bool_expr list - - (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_assumptions : context -> int - - (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_assumptions : context -> Boolean.bool_expr list - - (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_decls : context -> int - - (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_decls : context -> FuncDecl.func_decl list - - (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_num_smtlib_sorts : context -> int - - (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) - val get_smtlib_sorts : context -> Sort.sort list - - (** Parse the given string using the SMT-LIB2 parser. - - {!parse_smtlib_string} - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) - val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr - - (** Parse the given file using the SMT-LIB2 parser. - {!parse_smtlib2_string} *) - val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Boolean.bool_expr -end - -(** Set a global (or module) parameter, which is shared by all Z3 contexts. - - When a Z3 module is initialized it will use the value of these parameters - when Z3_params objects are not provided. - The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. - The character '.' is a delimiter (more later). - The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. - Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". - This function can be used to set parameters for a specific Z3 module. - This can be done by using .. - For example: - (set_global_param "pp.decimal" "true") - will set the parameter "decimal" in the module "pp" to true. -*) -val set_global_param : string -> string -> unit - -(** Get a global (or module) parameter. - - Returns None if the parameter does not exist. - The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. - This function cannot be invoked simultaneously from different threads without synchronization. - The result string stored in param_value is stored in a shared location. -*) -val get_global_param : string -> string option - -(** Restore the value of all global (and module) parameters. - - This command will not affect already created objects (such as tactics and solvers) - {!set_global_param} -*) -val global_param_reset_all : unit From 544a74f03493c73eea98f0414a927401294fd692 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 4 Jun 2013 18:00:48 +0100 Subject: [PATCH 436/646] ML API: bug and build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 28 ++++++++++++++++------------ scripts/update_api.py | 5 ++++- src/api/ml/z3.ml | 27 +++++++++++++++++---------- src/api/ml/z3.mli | 6 +++--- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4082bb2b8..d4221c05e 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1350,26 +1350,30 @@ class MLComponent(Component): mk_dir(os.path.join(BUILD_DIR, sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): - out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) - if IS_WINDOWS: str = str.replace('/','\\') + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) + out.write(str) + for f in filter(lambda f: f.endswith('.mli'), os.listdir(self.src_dir)): + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) for f in filter(lambda f: f.endswith('.c'), os.listdir(self.src_dir)): - out.write('%s/%s: %s/%s\n' % (sub_dir,f,src_dir,f)) - str = '\t%s %s/%s %s/%s\n' % (CP_CMD,src_dir,f,sub_dir,f) - if IS_WINDOWS: str = str.replace('/','\\') + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: - out.write('%s/%s.mli: %s/%s.ml %s\n' % (sub_dir,m,sub_dir,m,prev)) - out.write('\t%s -I %s -i -c %s/%s.ml > %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m,sub_dir,m)) - prev = prev + ' ' + sub_dir + '/' + m + '.mli' + fn = os.path.join(self.src_dir, ('%s.mli' % m)) + if not os.path.exists(fn): + out.write('%s.mli: %s.ml %s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) + prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = '' for m in modules: - out.write('%s/%s.cmi: %s/%s.mli\n' % (sub_dir,m,sub_dir,m)) - out.write('\t%s -I %s -c %s/%s.mli\n' % (OCAMLC,sub_dir,sub_dir,m)) - cmis = cmis + ' ' + sub_dir + '/' + m + '.cmi' + out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) + out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) + cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') diff --git a/scripts/update_api.py b/scripts/update_api.py index 44d871348..77a5bf7f2 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1185,7 +1185,8 @@ def mk_ml(): ip = inparams(params) op = outparams(params) if len(ip) == 0: - ml_native.write(' unit -> ') + ml_native.write(' unit -> ') + ml_i.write(' unit -> ') for p in ip: ml_native.write('%s -> ' % param2ml(p)) ml_i.write('%s -> ' % param2ml(p)) @@ -1233,6 +1234,8 @@ def mk_ml(): ml_native.write(' ') ml_native.write('a%d' % i) i = i + 1 + if len(ip) == 0: + ml_native.write('()') ml_native.write(' = \n') ml_native.write(' ') if result == VOID and len(op) == 0: diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 081433f1f..8b783d25d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -34,7 +34,7 @@ struct ) let create_context settings = - let cfg = Z3native.mk_config in + let cfg = Z3native.mk_config () in let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in (List.iter f settings) ; let v = Z3native.mk_context_rc cfg in @@ -101,12 +101,12 @@ end module Version = struct - let major = let (x, _, _, _) = Z3native.get_version in x - let minor = let (_, x, _, _) = Z3native.get_version in x - let build = let (_, _, x, _) = Z3native.get_version in x - let revision = let (_, _, _, x) = Z3native.get_version in x + let major = let (x, _, _, _) = Z3native.get_version () in x + let minor = let (_, x, _, _) = Z3native.get_version () in x + let build = let (_, _, x, _) = Z3native.get_version () in x + let revision = let (_, _, _, x) = Z3native.get_version () in x let to_string = - let (mj, mn, bld, rev) = Z3native.get_version in + let (mj, mn, bld, rev) = Z3native.get_version () in string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ @@ -609,6 +609,10 @@ sig val add_symbol : params -> Symbol.symbol -> Symbol.symbol -> unit val mk_params : context -> params val to_string : params -> string + + val update_param_value : context -> string -> string -> unit + val get_param_value : context -> string -> string option + val set_print_mode : context -> Z3enums.ast_print_mode -> unit end = struct type params = z3_native_object @@ -1099,7 +1103,7 @@ struct end -module Array = +module Z3Array = struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) @@ -1382,7 +1386,7 @@ struct end -module List = +module Z3List = struct let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( elem_sort : sort ) = let (r, _, _, _, _, _, _) = (Z3native.mk_list_sort (context_gno ctx) (Symbol.gno name) (Sort.gno elem_sort)) in @@ -2038,7 +2042,7 @@ struct if not r then None else - expr_of_ptr (z3obj_gc x) v + Some(expr_of_ptr (z3obj_gc x) v) let evaluate ( x : model ) ( t : expr ) ( completion : bool ) = eval x t completion @@ -2331,7 +2335,7 @@ struct if (Z3native.stats_is_uint (z3obj_gnc x) (z3obj_gno x) i) then (Entry.create_si k (Z3native.stats_get_uint_value (z3obj_gnc x) (z3obj_gno x) i)) else - (Entry.create_sd k (Z3native.stats_get_float_value (z3obj_gnc x) (z3obj_gno x) i)) + (Entry.create_sd k (Z3native.stats_get_double_value (z3obj_gnc x) (z3obj_gno x) i)) ) in mk_list f n @@ -2667,3 +2671,6 @@ let global_param_reset_all = let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled + +module Array = Z3Array +module List = Z3List diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 570ff8717..3f83ef6b2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -8,7 +8,7 @@ (** General Z3 exceptions Many functions in this API may throw an exception; if they do, it is this one.*) -exception Error +exception Error of string (** Context objects. @@ -55,11 +55,11 @@ module Log : sig (** Open an interaction log file. @return True if opening the log file succeeds, false otherwise. *) - (* CMW: "open" seems to be a reserved keyword? *) + (* CMW: "open" is a reserved keyword. *) val open_ : string -> bool (** Closes the interaction log. *) - val close : unit + val close : unit -> unit (** Appends a user-provided string to the interaction log. *) val append : string -> unit From 983a0fb16f7a7c0600e93b2213e7b61c58da5ac9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 21 Oct 2013 11:22:42 +0100 Subject: [PATCH 437/646] ML bindings: list/array are now called z3array/z3list to avoid confusion. Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 4 ---- src/api/ml/z3.mli | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 8b783d25d..ed815d720 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2670,7 +2670,3 @@ let global_param_reset_all = let toggle_warning_messages ( enabled: bool ) = Z3native.toggle_warning_messages enabled - - -module Array = Z3Array -module List = Z3List diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 3f83ef6b2..ff1898185 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -761,7 +761,7 @@ sig end (** Functions to manipulate Array expressions *) -module Array : +module Z3Array : sig (** Create a new array sort. *) val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort @@ -1093,7 +1093,7 @@ sig end (** Functions to manipulate List expressions *) -module List : +module Z3List : sig (** Create a new list sort. *) val mk_sort : context -> Symbol.symbol -> Sort.sort -> Sort.sort From b889b225a0d59a9abd4927417de91384f033a0c6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 21 Oct 2013 11:25:02 +0100 Subject: [PATCH 438/646] ML cleanup; makefile removed. The example is built by running make examples in the build directory. Signed-off-by: Christoph M. Wintersteiger --- examples/ml/Makefile | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 examples/ml/Makefile diff --git a/examples/ml/Makefile b/examples/ml/Makefile deleted file mode 100644 index 818f0cacc..000000000 --- a/examples/ml/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# This is a temporary support file for emacs annotations. -# It does not compile the Z3 ML example; this will be built -# in the top-level build directory. - -all: - source /cygdrive/c/cwinter/.msenv32 ; OCAML_COMPAT=c C:/ocamlw32/bin/ocamlc -g -custom -cclib '-L../../bld_dbg -lz3' -annot -o ml_example.byte -I ../../bld_dbg/api/ml z3.cma ml_example.ml - source /cygdrive/c/cwinter/.msenv32 ; C:/ocamlw32/bin/ocamlopt -g -annot -o ml_example -cclib '-L../../bld_dbg -lz3' -I ../../bld_dbg -I ../../bld_dbg/api/ml z3.cmxa ml_example.ml From c32e1304872f584a69f3ae6b8e410d88e30db7e3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 28 Oct 2013 12:17:58 +0000 Subject: [PATCH 439/646] ML API: bugfix for native function with more than 5 parameters. Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 77a5bf7f2..dd1e46c4f 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1211,9 +1211,11 @@ def mk_ml(): ml_i.write(')') ml_native.write('\n') ml_i.write('\n') - ml_native.write(' = "n_%s"\n' % ml_method_name(name)) if len(ip) > 5: - ml_native.write(' "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write(' = "n_%s_bytecode"\n' % ml_method_name(name)) + ml_native.write(' "n_%s"\n' % ml_method_name(name)) + else: + ml_native.write(' = "n_%s"\n' % ml_method_name(name)) ml_native.write('\n') ml_native.write(' end\n\n') ml_i.write('\n(**/**)\n'); From 54b7f8eec3b17ed012324d7a34c8846de32cb560 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 2 Apr 2014 19:08:59 +0100 Subject: [PATCH 440/646] ML API bugfix (Codeplex issue 102) Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 43 ++++++ src/api/ml/z3.ml | 289 +++++++++++++++++++------------------- src/api/ml/z3.mli | 3 + 3 files changed, 192 insertions(+), 143 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index c9ed1d948..0dd227784 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -196,6 +196,48 @@ let basic_tests ( ctx : context ) = Printf.printf "Exception caught, OK.\n" ) +(** + A basic example of how to use quantifiers. +**) +let quantifierExample1 ( ctx : context ) = + Printf.printf "QuantifierExample\n" ; + let is = (Integer.mk_sort ctx) in + let types = [ is; is; is ] in + let names = [ (Symbol.mk_string ctx "x_0"); + (Symbol.mk_string ctx "x_1"); + (Symbol.mk_string ctx "x_2") ] in + let vars = [ (Quantifier.mk_bound ctx 2 (List.nth types 0)); + (Quantifier.mk_bound ctx 2 (List.nth types 1)); + (Quantifier.mk_bound ctx 2 (List.nth types 2)) ] in + let xs = [ (Integer.mk_const ctx (List.nth names 0)); + (Integer.mk_const ctx (List.nth names 1)); + (Integer.mk_const ctx (List.nth names 2)) ] in + + let body_vars = (Boolean.mk_and ctx + [ (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth vars 0) ; (Integer.mk_numeral_i ctx 1)]) + (Integer.mk_numeral_i ctx 2)) ; + (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth vars 1); (Integer.mk_numeral_i ctx 2)]) + (Arithmetic.mk_add ctx [ (List.nth vars 2); (Integer.mk_numeral_i ctx 3)])) ]) in + let body_const = (Boolean.mk_and ctx + [ (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth xs 0); (Integer.mk_numeral_i ctx 1)]) + (Integer.mk_numeral_i ctx 2)) ; + (mk_eq ctx + (Arithmetic.mk_add ctx [ (List.nth xs 1); (Integer.mk_numeral_i ctx 2)]) + (Arithmetic.mk_add ctx [ (List.nth xs 2); (Integer.mk_numeral_i ctx 3)])) ]) in + + let x = (Quantifier.mk_forall ctx types names body_vars (Some 1) [] [] (Some (Symbol.mk_string ctx "Q1")) (Some (Symbol.mk_string ctx "skid1"))) in + Printf.printf "Quantifier X: %s\n" (Quantifier.to_string x) ; + let y = (Quantifier.mk_forall_const ctx xs body_const (Some 1) [] [] (Some (Symbol.mk_string ctx "Q2")) (Some (Symbol.mk_string ctx "skid2"))) in + Printf.printf "Quantifier Y: %s\n" (Quantifier.to_string y) ; + if (is_true (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) + else if (is_false (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) + else if (is_const (Quantifier.expr_of_quantifier x)) then + raise (TestFailedException "") (* unreachable *) let _ = try ( @@ -217,6 +259,7 @@ let _ = Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); basic_tests ctx ; + quantifierExample1 ctx ; Printf.printf "Disposing...\n"; Gc.full_major () ); diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index ed815d720..d91d3ca8d 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -297,6 +297,7 @@ struct | VAR_AST -> true | _ -> false + let is_app ( x : ast ) = (get_ast_kind x) == APP_AST let is_var ( x : ast ) = (get_ast_kind x) == VAR_AST let is_quantifier ( x : ast ) = (get_ast_kind x) == QUANTIFIER_AST let is_sort ( x : ast ) = (get_ast_kind x) == SORT_AST @@ -828,22 +829,22 @@ end = struct (Z3native.mk_bool_sort (gnc x)) (Z3native.get_sort (gnc x) (gno x))) - let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) + let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -1100,6 +1101,8 @@ struct mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id else mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id + + let to_string ( x : quantifier ) = (Expr.to_string (expr_of_quantifier x)) end @@ -1108,12 +1111,12 @@ struct let mk_sort ( ctx : context ) ( domain : sort ) ( range : sort ) = sort_of_ptr ctx (Z3native.mk_array_sort (context_gno ctx) (Sort.gno domain) (Sort.gno range)) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) - let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) - let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) - let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) - let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) + let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE) + let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT) + let is_constant_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY) + let is_default_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT) + let is_array_map ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP) + let is_as_array ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY) let is_array ( x : expr ) = (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == ARRAY_SORT) @@ -1150,11 +1153,11 @@ struct let mk_sort ( ctx : context ) ( ty : sort ) = sort_of_ptr ctx (Z3native.mk_set_sort (context_gno ctx) (Sort.gno ty)) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) - let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) - let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) - let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) + let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION) + let is_intersect ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT) + let is_difference ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE) + let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT) + let is_subset ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET) let mk_empty ( ctx : context ) ( domain : sort ) = @@ -1203,7 +1206,7 @@ struct (Z3native.is_app (Expr.gnc x) (Expr.gno x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == FINITE_DOMAIN_SORT) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT) let get_size ( x : sort ) = let (r, v) = (Z3native.get_finite_domain_sort_size (Sort.gnc x) (Sort.gno x)) in @@ -1219,19 +1222,19 @@ struct ((Z3native.is_app (Expr.gnc x) (Expr.gno x)) && (sort_kind_of_int (Z3native.get_sort_kind nc (Z3native.get_sort nc (Expr.gno x))) == RELATION_SORT)) - let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) - let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) - let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) - let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) - let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) - let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) - let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) - let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) - let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) - let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) - let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) - let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) - let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) + let is_store ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE) + let is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY) + let is_is_empty ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY) + let is_join ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN) + let is_union ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION) + let is_widen ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN) + let is_project ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT) + let is_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER) + let is_negation_filter ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER) + let is_rename ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME) + let is_complement ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT) + let is_select ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT) + let is_clone ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE) let get_arity ( x : sort ) = Z3native.get_relation_arity (Sort.gnc x) (Sort.gno x) @@ -1534,37 +1537,37 @@ struct (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) let is_real ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) @@ -1616,57 +1619,57 @@ struct sort_of_ptr ctx (Z3native.mk_bv_sort (context_gno ctx) size) let is_bv ( x : expr ) = ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == BV_SORT) - let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) - let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) - let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) - let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) - let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) - let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) - let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) - let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) - let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) - let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) - let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) - let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) - let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) - let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) - let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) - let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) - let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) - let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) - let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) - let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) - let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) - let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) - let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) - let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) - let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) - let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) - let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) - let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) - let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) - let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) - let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) - let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) - let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) - let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) - let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) - let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) - let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) - let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) - let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) - let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) - let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) - let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) - let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) - let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) - let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) - let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) - let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) - let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) - let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) + let is_bv_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM) + let is_bv_bit1 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1) + let is_bv_bit0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0) + let is_bv_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG) + let is_bv_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD) + let is_bv_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB) + let is_bv_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL) + let is_bv_sdiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV) + let is_bv_udiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV) + let is_bv_SRem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM) + let is_bv_urem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM) + let is_bv_smod ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD) + let is_bv_sdiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0) + let is_bv_udiv0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0) + let is_bv_srem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0) + let is_bv_urem0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0) + let is_bv_smod0 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0) + let is_bv_ule ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ) + let is_bv_sle ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ) + let is_bv_uge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ) + let is_bv_sge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ) + let is_bv_ult ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT) + let is_bv_slt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT) + let is_bv_ugt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT) + let is_bv_sgt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT) + let is_bv_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND) + let is_bv_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR) + let is_bv_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT) + let is_bv_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR) + let is_bv_nand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND) + let is_bv_nor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR) + let is_bv_xnor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR) + let is_bv_concat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT) + let is_bv_signextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT) + let is_bv_zeroextension ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT) + let is_bv_extract ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT) + let is_bv_repeat ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT) + let is_bv_reduceor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR) + let is_bv_reduceand ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND) + let is_bv_comp ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP) + let is_bv_shiftleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL) + let is_bv_shiftrightlogical ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR) + let is_bv_shiftrightarithmetic ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR) + let is_bv_rotateleft ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT) + let is_bv_rotateright ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) + let is_bv_rotateleftextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) + let is_bv_rotaterightextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) + let is_int_to_bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_bv_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_bv_carry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) + let is_bv_xor3 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) let get_int ( x : expr ) = let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in @@ -1778,44 +1781,44 @@ end module Proof = struct - let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) - let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) - let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) - let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) - let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) - let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) - let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) - let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) - let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) - let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) - let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) - let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) - let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) - let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) - let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) - let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) - let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) - let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) - let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) - let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) - let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) - let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) - let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) - let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) - let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) - let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) - let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) - let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) - let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) - let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) - let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) - let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) - let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) - let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) - let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) - let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) - let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) - let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) + let is_asserted ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) + let is_goal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_modus_ponens ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) + let is_reflexivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) + let is_symmetry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) + let is_transitivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY) + let is_Transitivity_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR) + let is_monotonicity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY) + let is_quant_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO) + let is_distributivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY) + let is_and_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM) + let is_or_elimination ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM) + let is_rewrite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE) + let is_rewrite_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR) + let is_pull_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT) + let is_pull_quant_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR) + let is_push_quant ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT) + let is_elim_unused_vars ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS) + let is_der ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER) + let is_quant_inst ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST) + let is_hypothesis ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS) + let is_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA) + let is_unit_resolution ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION) + let is_iff_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE) + let is_iff_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE) + let is_commutativity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *) + let is_def_axiom ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM) + let is_def_intro ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO) + let is_apply_def ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF) + let is_iff_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ) + let is_nnf_pos ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS) + let is_nnf_neg ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG) + let is_nnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR) + let is_cnf_star ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR) + let is_skolemize ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE) + let is_modus_ponens_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ) + let is_theory_lemma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index ff1898185..5c9c56dbf 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -758,6 +758,9 @@ sig (** Create a Quantifier. *) val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier + + (** A string representation of the quantifier. *) + val to_string : quantifier -> string end (** Functions to manipulate Array expressions *) From ee22d4054201afd40c9a7bf05fe9fb8ca808639f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 2 Apr 2014 19:18:43 +0100 Subject: [PATCH 441/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index d91d3ca8d..5f8d96d2a 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -793,7 +793,7 @@ end = struct mk_list f n let update ( x : expr ) ( args : expr list ) = - if (List.length args <> (get_num_args x)) then + if ((AST.is_app (ast_of_expr x)) && (List.length args <> (get_num_args x))) then raise (Z3native.Exception "Number of arguments does not match") else expr_of_ptr (Expr.gc x) (Z3native.update_term (gnc x) (gno x) (List.length args) (expr_lton args)) From 9dc802199503f8f120cb8bf1f5202238ba0e0383 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:17:22 +0100 Subject: [PATCH 442/646] Added facilities for ocamlfind in the ML API build Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 12 +++++++++++- scripts/mk_util.py | 31 ++++++++++++++++++++++++++++--- src/api/ml/README | 6 +++++- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index 3e1eb0d1c..f934aac80 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -1,4 +1,4 @@ -### This is work-in-progress and does not work yet. +### This is work-in-progress. Small example using the Z3 ML bindings. To build the example execute @@ -12,3 +12,13 @@ or LD_LIBRARY_PATH=. ./ml_example.byte for the byte-code version. +If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), +then we can compile this example as follows: + +ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg -verbose +ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg -verbose + +Note that the resulting binaries depend on the shared z3 library, which needs to be +in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was +installed into ocamlfind, the path that should be added is +`ocamlfind printconf destdir`/Z3 \ No newline at end of file diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d4221c05e..f6f95cf7d 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1338,7 +1338,25 @@ class MLComponent(Component): Component.__init__(self, name, path, deps) if lib_name == None: lib_name = name - self.lib_name = lib_name + self.lib_name = lib_name + + def mk_ml_meta(self, ml_meta_in, ml_meta_out, major, minor, build, revision): + ver_pat = re.compile('version = "VERSION"*') + fin = open(ml_meta_in, 'r') + fout = open(ml_meta_out, 'w') + num_updates = 0 + for line in fin: + if ver_pat.match(line): + fout.write('version = "%s.%s.%s.%s"\n' % (major, minor, build, revision)) + num_updates = num_updates + 1 + else: + fout.write(line) + assert num_updates == 1, "unexpected number of version number updates" + fin.close() + fout.close() + if VERBOSE: + print("Updated '%s'" % ml_meta_out) + def mk_makefile(self, out): if is_ml_enabled(): @@ -1377,7 +1395,7 @@ class MLComponent(Component): out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') - out.write('api/ml/z3.cmxa: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') @@ -1385,7 +1403,7 @@ class MLComponent(Component): if DEBUG_MODE: out.write('-g ') out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('api/ml/z3.cma: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) out.write('\n') @@ -1395,6 +1413,13 @@ class MLComponent(Component): out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') out.write('\n') + # Generate META file and package installation commands + self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('\tocamlfind remove Z3\n') + out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.lib api/ml/libz3ml.lib libz3.lib libz3.dll\n') + out.write('\n') + def main_component(self): return is_ml_enabled() diff --git a/src/api/ml/README b/src/api/ml/README index beee7d864..f697e5ff4 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -5,4 +5,8 @@ We are currently working on a brand new ML API. On Windows, there are no less than four different ports of OCaml. The Z3 build system assumes that either the win32 or the win64 port is installed. This means that OCaml will use `cl' as the underlying C compiler and not the cygwin or -mingw compilers. \ No newline at end of file +mingw compilers. + +By default, a make target called `ocamlfind_install' is added. This installs Z3 +into the ocamlfind package repository such that programs can be compiled via +ocamlfind. \ No newline at end of file From eb72afabfbf89c49be25bd5d1843d6297280b8ef Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:32:06 +0100 Subject: [PATCH 443/646] ML API `or' is deprecated, changed to `||' Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 5f8d96d2a..c037a9263 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -748,7 +748,7 @@ end = struct Expr(z3_native_object_of_ast_ptr ctx no) else if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then + if (sk == INT_SORT || sk == REAL_SORT || sk == BV_SORT) then Expr(z3_native_object_of_ast_ptr ctx no) else raise (Z3native.Exception "Unsupported numeral object") From 0465ad3ce6cdccf4e4be9c90954b683c44ec539e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:33:52 +0100 Subject: [PATCH 444/646] ML example; `or' is deprecated, changed to `||' Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 0dd227784..25862b2d7 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -168,7 +168,7 @@ let basic_tests ( ctx : context ) = let inum = (get_numerator rn) in let iden = get_denominator rn in Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; - if ((Real.to_string inum) <> "42" or (Real.to_string iden) <> "43") then + if ((Real.to_string inum) <> "42" || (Real.to_string iden) <> "43") then raise (TestFailedException "") else Printf.printf "Test passed.\n" From 133890be23c0d02186622fb3781ff6c987b6efae Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:38:29 +0100 Subject: [PATCH 445/646] ML API build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index f6f95cf7d..46229b20c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1417,7 +1417,10 @@ class MLComponent(Component): self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') out.write('\tocamlfind remove Z3\n') - out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.lib api/ml/libz3ml.lib libz3.lib libz3.dll\n') + out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)') + if IS_WINDOWS: + out.write(' libz3$(LIB_EXT)') + out.write('\n') out.write('\n') From f319a77a4c6c1f8c1620b34424bcbad9931b636c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 15 Apr 2014 18:49:05 +0100 Subject: [PATCH 446/646] ML API build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 46229b20c..418149dbe 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1415,13 +1415,14 @@ class MLComponent(Component): out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') - out.write('\tocamlfind remove Z3\n') - out.write('\tocamlfind install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)') - if IS_WINDOWS: - out.write(' libz3$(LIB_EXT)') - out.write('\n') - out.write('\n') + if OCAMLFIND != '': + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('\t%s remove Z3\n' % (OCAMLFIND)) + out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + if IS_WINDOWS: + out.write(' libz3$(LIB_EXT)') + out.write('\n') + out.write('\n') def main_component(self): From 3d9ad51aae97db8a8b2c5ef15163a2c46871ea8c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 12:55:23 +0100 Subject: [PATCH 447/646] ML API refactoring Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 72 ++++++++----------- src/api/ml/z3.mli | 180 +++++++++++++++++++++++----------------------- 2 files changed, 119 insertions(+), 133 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index c037a9263..051a54696 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1,5 +1,5 @@ (** - The Z3 ML/Ocaml Interface. + The Z3 ML/OCaml Interface. Copyright (C) 2012 Microsoft Corporation @author CM Wintersteiger (cwinter) 2012-12-17 @@ -698,7 +698,6 @@ sig val get_simplify_help : context -> string val get_simplify_parameter_descrs : context -> Params.ParamDescrs.param_descrs val get_func_decl : expr -> FuncDecl.func_decl - val get_bool_value : expr -> Z3enums.lbool val get_num_args : expr -> int val get_args : expr -> expr list val update : expr -> expr list -> expr @@ -710,20 +709,7 @@ sig val is_numeral : expr -> bool val is_well_sorted : expr -> bool val get_sort : expr -> Sort.sort - val is_bool : expr -> bool val is_const : expr -> bool - val is_true : expr -> bool - val is_false : expr -> bool - val is_eq : expr -> bool - val is_distinct : expr -> bool - val is_ite : expr -> bool - val is_and : expr -> bool - val is_or : expr -> bool - val is_iff : expr -> bool - val is_xor : expr -> bool - val is_not : expr -> bool - val is_implies : expr -> bool - val is_oeq : expr -> bool val mk_const : context -> Symbol.symbol -> Sort.sort -> expr val mk_const_s : context -> string -> Sort.sort -> expr val mk_const_f : context -> FuncDecl.func_decl -> expr @@ -782,9 +768,7 @@ end = struct let get_simplify_parameter_descrs ( ctx : context ) = Params.ParamDescrs.param_descrs_of_ptr ctx (Z3native.simplify_get_param_descrs (context_gno ctx)) - let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) - - let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + let get_func_decl ( x : expr ) = FuncDecl.func_decl_of_ptr (Expr.gc x) (Z3native.get_app_decl (gnc x) (gno x)) let get_num_args ( x : expr ) = Z3native.get_app_num_args (gnc x) (gno x) @@ -823,29 +807,11 @@ end = struct let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) - - let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && - (Z3native.is_eq_sort (gnc x) - (Z3native.mk_bool_sort (gnc x)) - (Z3native.get_sort (gnc x) (gno x))) - + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) - let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) - let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) - let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) - let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) - let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) - let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) - let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) - let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) - let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) - let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) - let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ) - let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -888,12 +854,6 @@ struct let mk_val ( ctx : context ) ( value : bool ) = if value then mk_true ctx else mk_false ctx - - let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = - expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) - - let mk_distinct ( ctx : context ) ( args : expr list ) = - expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) let mk_not ( ctx : context ) ( a : expr ) = expr_of_ptr ctx (Z3native.mk_not (context_gno ctx) (gno a)) @@ -917,6 +877,31 @@ struct let mk_or ( ctx : context ) ( args : expr list ) = let f x = (Expr.gno (x)) in expr_of_ptr ctx (Z3native.mk_or (context_gno ctx) (List.length args) (Array.of_list(List.map f args))) + + let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) = + expr_of_ptr ctx (Z3native.mk_eq (context_gno ctx) (Expr.gno x) (Expr.gno y)) + + let mk_distinct ( ctx : context ) ( args : expr list ) = + expr_of_ptr ctx (Z3native.mk_distinct (context_gno ctx) (List.length args) (expr_lton args)) + + let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value (gnc x) (gno x)) + + let is_bool ( x : expr ) = (match x with Expr(a) -> (AST.is_expr a)) && + (Z3native.is_eq_sort (gnc x) + (Z3native.mk_bool_sort (gnc x)) + (Z3native.get_sort (gnc x) (gno x))) + + let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE) + let is_false ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE) + let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ) + let is_distinct ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT) + let is_ite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE) + let is_and ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND) + let is_or ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR) + let is_iff ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF) + let is_xor ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR) + let is_not ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT) + let is_implies ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES) end @@ -1784,6 +1769,7 @@ struct let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) let is_asserted ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED) let is_goal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL) + let is_oeq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_OEQ) let is_modus_ponens ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS) let is_reflexivity ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY) let is_symmetry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 5c9c56dbf..c554d7564 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1,5 +1,5 @@ (** - The Z3 ML/Ocaml Interface. + The Z3 ML/OCaml Interface. Copyright (C) 2012 Microsoft Corporation @author CM Wintersteiger (cwinter) 2012-12-17 @@ -488,10 +488,6 @@ sig (** The function declaration of the function that is applied in this expression. *) val get_func_decl : Expr.expr -> FuncDecl.func_decl - (** Indicates whether the expression is the true or false expression - or something else (L_UNDEF). *) - val get_bool_value : Expr.expr -> Z3enums.lbool - (** The number of arguments of the expression. *) val get_num_args : Expr.expr -> int @@ -535,11 +531,88 @@ sig (** The Sort of the term. *) val get_sort : Expr.expr -> Sort.sort - (** Indicates whether the term has Boolean sort. *) - val is_bool : Expr.expr -> bool - (** Indicates whether the term represents a constant. *) val is_const : Expr.expr -> bool + + (** Creates a new constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> expr + + (** Creates a new constant. *) + val mk_const_s : context -> string -> Sort.sort -> expr + + (** Creates a constant from the func_decl. *) + val mk_const_f : context -> FuncDecl.func_decl -> expr + + (** Creates a fresh constant with a name prefixed with a string. *) + val mk_fresh_const : context -> string -> Sort.sort -> expr + + (** Create a new function application. *) + val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr + + (** Create a numeral of a given sort. + @return A Term with the given value and sort *) + val mk_numeral_string : context -> string -> Sort.sort -> expr + + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. + It is slightly faster than MakeNumeral since it is not necessary to parse a string. + @return A Term with the given value and sort *) + val mk_numeral_int : context -> int -> Sort.sort -> expr +end + +(** Boolean expressions; Propositional logic and equality *) +module Boolean : +sig + (** Create a Boolean sort *) + val mk_sort : context -> Sort.sort + + (** Create a Boolean constant. *) + val mk_const : context -> Symbol.symbol -> Expr.expr + + (** Create a Boolean constant. *) + val mk_const_s : context -> string -> Expr.expr + + (** The true Term. *) + val mk_true : context -> Expr.expr + + (** The false Term. *) + val mk_false : context -> Expr.expr + + (** Creates a Boolean value. *) + val mk_val : context -> bool -> Expr.expr + + (** Mk an expression representing not(a). *) + val mk_not : context -> Expr.expr -> Expr.expr + + (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 iff t2. *) + val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 -> t2. *) + val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing t1 xor t2. *) + val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create an expression representing the AND of args *) + val mk_and : context -> Expr.expr list -> Expr.expr + + (** Create an expression representing the OR of args *) + val mk_or : context -> Expr.expr list -> Expr.expr + + (** Creates the equality between two expr's. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Creates a distinct term. *) + val mk_distinct : context -> Expr.expr list -> Expr.expr + + (** Indicates whether the expression is the true or false expression + or something else (L_UNDEF). *) + val get_bool_value : Expr.expr -> Z3enums.lbool + + (** Indicates whether the term has Boolean sort. *) + val is_bool : Expr.expr -> bool (** Indicates whether the term is the constant true. *) val is_true : Expr.expr -> bool @@ -573,84 +646,6 @@ sig (** Indicates whether the term is an implication *) val is_implies : Expr.expr -> bool - - (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) - val is_oeq : Expr.expr -> bool - - (** Creates a new constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - - (** Creates a new constant. *) - val mk_const_s : context -> string -> Sort.sort -> expr - - (** Creates a constant from the func_decl. *) - val mk_const_f : context -> FuncDecl.func_decl -> expr - - (** Creates a fresh constant with a name prefixed with a string. *) - val mk_fresh_const : context -> string -> Sort.sort -> expr - - (** Create a new function application. *) - val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - - (** Create a numeral of a given sort. - @return A Term with the goven value and sort *) - val mk_numeral_string : context -> string -> Sort.sort -> expr - - (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. - @return A Term with the given value and sort *) - val mk_numeral_int : context -> int -> Sort.sort -> expr -end - -(** Boolean expressions *) -module Boolean : -sig - (** Create a Boolean sort *) - val mk_sort : context -> Sort.sort - - (** Create a Boolean constant. *) - val mk_const : context -> Symbol.symbol -> Expr.expr - - (** Create a Boolean constant. *) - val mk_const_s : context -> string -> Expr.expr - - (** The true Term. *) - val mk_true : context -> Expr.expr - - (** The false Term. *) - val mk_false : context -> Expr.expr - - (** Creates a Boolean value. *) - val mk_val : context -> bool -> Expr.expr - - (** Creates the equality between two expr's. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Creates a distinct term. *) - val mk_distinct : context -> Expr.expr list -> Expr.expr - - (** Mk an expression representing not(a). *) - val mk_not : context -> Expr.expr -> Expr.expr - - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) - val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 iff t2. *) - val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 -> t2. *) - val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing t1 xor t2. *) - val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create an expression representing the AND of args *) - val mk_and : context -> Expr.expr list -> Expr.expr - - (** Create an expression representing the OR of args *) - val mk_or : context -> Expr.expr list -> Expr.expr end (** Quantifier expressions *) @@ -817,7 +812,7 @@ sig The node a must have an array sort [domain -> range], and i must have the sort domain. The sort of the result is range. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -833,7 +828,7 @@ sig on all indices except for i, where it maps to v (and the select of a with respect to i may be a different value). - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr @@ -841,7 +836,7 @@ sig The resulting term is an array, such that a selecton an arbitrary index produces the value v. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr @@ -850,7 +845,7 @@ sig Eeach element of args must be of an array sort [domain_i -> range_i]. The function declaration f must have type range_1 .. range_n -> range. v must have sort range. The sort of the result is [domain_i -> range]. - {!Array.mk_sort} + {!Z3Array.mk_sort} {!mk_select} {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr @@ -1837,6 +1832,11 @@ sig (** Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user. *) val is_goal : Expr.expr -> bool + (** Indicates whether the term is a binary equivalence modulo namings. + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) + val is_oeq : Expr.expr -> bool + (** Indicates whether the term is proof via modus ponens Given a proof for p and a proof for (implies p q), produces a proof for q. From 555a3883b9544dc6603b2067e96f3b009c97e3f9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:05:22 +0100 Subject: [PATCH 448/646] ML example doc fix Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index f934aac80..a14cbeb63 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -15,8 +15,8 @@ for the byte-code version. If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), then we can compile this example as follows: -ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg -verbose -ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg -verbose +ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg +ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg Note that the resulting binaries depend on the shared z3 library, which needs to be in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was From 4687aa208de1071e0516f11a8811153187a016d9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:05:50 +0100 Subject: [PATCH 449/646] ML API refactoring (z3native.c -> z3native_stubs.c) Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++--- scripts/update_api.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 418149dbe..ab13bb943 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1392,9 +1392,9 @@ class MLComponent(Component): out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native.c $(CXX_OUT_FLAG)api/ml/z3native$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native$(OBJ_EXT)\n') + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) diff --git a/scripts/update_api.py b/scripts/update_api.py index dd1e46c4f..0ed9b29ca 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1148,7 +1148,7 @@ def mk_ml(): ml_dir = get_component('ml').src_dir ml_nativef = os.path.join(ml_dir, 'z3native.ml') ml_nativefi = os.path.join(ml_dir, 'z3native.mli') - ml_wrapperf = os.path.join(ml_dir, 'z3native.c') + ml_wrapperf = os.path.join(ml_dir, 'z3native_stubs.c') ml_native = open(ml_nativef, 'w') ml_i = open(ml_nativefi, 'w') ml_native.write('(* Automatically generated file *)\n\n') From ec0b12ecd16742edf1fcfaee41eedd832e952f15 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 13:06:29 +0100 Subject: [PATCH 450/646] ML API refactoring (z3native.c -> z3native_stubs.c) Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 648013ca1..3cd2d3ef3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ *~ *.pyc +*.pyo +# Ignore callgrind files +callgrind.out.* # .hpp files are automatically generated *.hpp .z3-trace @@ -42,7 +45,6 @@ bld_rel_x64/* # Auto generated files. config.log config.status -configure install_tactic.cpp mem_initializer.cpp gparams_register_modules.cpp @@ -54,6 +56,8 @@ src/api/api_log_macros.cpp src/api/dll/api_dll.def src/api/dotnet/Enumerations.cs src/api/dotnet/Native.cs +src/api/dotnet/Properties/AssemblyInfo.cs +src/api/dotnet/Microsoft.Z3.xml src/api/python/z3consts.py src/api/python/z3core.py src/ast/pattern/database.h @@ -61,21 +65,7 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java -*.bak -doc/api -doc/code -src/api/ml/z3_native.c -src/api/ml/z3_native.ml -src/api/ml/native.c -src/api/ml/z3.ml -src/api/ml/enumerations.ml -src/api/ml/z3native.c src/api/ml/z3native_stubs.c src/api/ml/z3native.ml src/api/ml/z3enums.ml src/api/ml/z3.mllib -src/api/ml/z3_native.c -src/api/ml/z3_native.ml -src/api/ml/native.c -src/api/ml/z3.ml -src/api/ml/enumerations.ml From 409a40a5627290a04ab6a60df25f58580c87b01c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 14:18:46 +0100 Subject: [PATCH 451/646] ML API: Added get_bit_int and get_ratio Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 +- src/api/ml/z3.ml | 101 +++++++++++++++++++++++++-------------------- src/api/ml/z3.mli | 12 ++++-- 3 files changed, 67 insertions(+), 50 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ab13bb943..8dcf3dda6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1553,7 +1553,7 @@ class MLExampleComponent(ExampleComponent): out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" z3.cma') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') @@ -1564,7 +1564,7 @@ class MLExampleComponent(ExampleComponent): out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" z3.cmxa') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 051a54696..dda8807c9 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1425,6 +1425,50 @@ end module Arithmetic = struct + let is_int ( x : expr ) = + (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) + + let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) + + let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) + + let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) + + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) + + let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) + + let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) + + let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) + + let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) + + let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) + + let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) + + let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) + + let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) + + let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) + + let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + + let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + + let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) + + let is_real ( x : expr ) = + ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) + + let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) + + let is_rat_numeral ( x : expr ) = (Expr.is_numeral x) && (is_real x) + + let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) module Integer = struct @@ -1435,6 +1479,12 @@ struct let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") + + let get_big_int ( x : expr ) = + if (is_int_numeral x) then + let s = to_string(x) in + (Big_int.big_int_of_string s) + else raise (Z3native.Exception "Conversion failed.") let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) @@ -1474,6 +1524,12 @@ struct let get_denominator ( x : expr ) = expr_of_ptr (Expr.gc x) (Z3native.get_denominator (Expr.gnc x) (Expr.gno x)) + let get_ratio ( x : expr ) = + if (is_rat_numeral x) then + let s = to_string(x) in + (Ratio.ratio_of_string s) + else raise (Z3native.Exception "Conversion failed.") + let to_decimal_string ( x : expr ) ( precision : int ) = Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision @@ -1518,51 +1574,6 @@ struct end end - let is_int ( x : expr ) = - (Z3native.is_numeral_ast (Expr.gnc x) (Expr.gno x)) && - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == INT_SORT) - - let is_arithmetic_numeral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM) - - let is_le ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE) - - let is_ge ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE) - - let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT) - - let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT) - - let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD) - - let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB) - - let is_uminus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS) - - let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL) - - let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV) - - let is_idiv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV) - - let is_remainder ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM) - - let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - - let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - - let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) - - let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) - - let is_real ( x : expr ) = - ((sort_kind_of_int (Z3native.get_sort_kind (Expr.gnc x) (Z3native.get_sort (Expr.gnc x) (Expr.gno x)))) == REAL_SORT) - - let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x) - - let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x) - - let is_algebraic_number ( x : expr ) = Z3native.is_algebraic_number (Expr.gnc x) (Expr.gno x) - let mk_add ( ctx : context ) ( t : expr list ) = let f x = (Expr.gno x) in (expr_of_ptr ctx (Z3native.mk_add (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index c554d7564..4122f40f2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1149,6 +1149,9 @@ sig (** Retrieve the int value. *) val get_int : Expr.expr -> int + (** Get a big_int from an integer numeral *) + val get_big_int : Expr.expr -> Big_int.big_int + (** Returns a string representation of the numeral. *) val to_string : Expr.expr -> string @@ -1201,10 +1204,13 @@ sig val mk_sort : context -> Sort.sort (** The numerator of a rational numeral. *) - val get_numerator : Expr.expr-> Expr.expr + val get_numerator : Expr.expr -> Expr.expr (** The denominator of a rational numeral. *) - val get_denominator : Expr.expr-> Expr.expr + val get_denominator : Expr.expr -> Expr.expr + + (** Get a ratio from a real numeral *) + val get_ratio : Expr.expr -> Ratio.ratio (** Returns a string representation in decimal notation. The result has at most as many decimal places as indicated by the int argument.*) @@ -1323,7 +1329,7 @@ sig val is_int_numeral : Expr.expr -> bool (** Indicates whether the term is a real numeral. *) - val is_rat_num : Expr.expr -> bool + val is_rat_numeral : Expr.expr -> bool (** Indicates whether the term is an algebraic number *) val is_algebraic_number : Expr.expr -> bool From 65ab6d537307c1680844fe1db6cd68e7146f9b66 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 15:33:07 +0100 Subject: [PATCH 452/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8dcf3dda6..f57763ff1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1393,7 +1393,7 @@ class MLComponent(Component): out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CXX) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): From 05af33ac7d4f0a7eb63d343ee39bf653563a4e46 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:10:18 +0100 Subject: [PATCH 453/646] ML API: ocamlfind installation fixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 4 ++-- scripts/mk_util.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index a14cbeb63..31d4b8e2e 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -15,8 +15,8 @@ for the byte-code version. If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), then we can compile this example as follows: -ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg -ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg +ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg ml_example.ml +ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml Note that the resulting binaries depend on the shared z3 library, which needs to be in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was diff --git a/scripts/mk_util.py b/scripts/mk_util.py index f57763ff1..a0c9213c9 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1419,6 +1419,9 @@ class MLComponent(Component): out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + for m in modules: + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmx' % (os.path.join(sub_dir, m))) if IS_WINDOWS: out.write(' libz3$(LIB_EXT)') out.write('\n') From 59371416050c6a2c38d8b893f65f09887114c73e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:10:29 +0100 Subject: [PATCH 454/646] ML API: bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 0ed9b29ca..8ce652ed5 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1254,7 +1254,7 @@ def mk_ml(): ml_native.write(' a%d' % i) i = i + 1 ml_native.write(') in\n') - if len(params) > 0 and param_type(params[0]) == CONTEXT: + if name not in Unwrapped and len(params) > 0 and param_type(params[0]) == CONTEXT: ml_native.write(' let err = (error_code_of_int (ML2C.n_get_error_code a0)) in \n') ml_native.write(' if err <> OK then\n') ml_native.write(' raise (Exception (ML2C.n_get_error_msg_ex a0 (int_of_error_code err)))\n') From cc4010591989908ab2f54a2a7fec7f5ec1ca1840 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:12:55 +0100 Subject: [PATCH 455/646] ML API doc fix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.mli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 4122f40f2..8a88a91bb 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -2404,7 +2404,7 @@ sig (** The finite set of distinct values that represent the interpretation of a sort. {!get_sorts} - @returns A list of expressions, where each is an element of the universe of the sort *) + @return A list of expressions, where each is an element of the universe of the sort *) val sort_universe : model -> Sort.sort -> AST.ast list (** Conversion of models to strings. From 83690a8fe3a64cc45f16a444f7b82e0d1c27f9fe Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 16 Apr 2014 16:16:40 +0100 Subject: [PATCH 456/646] ML API doc fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.mli | 220 +++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 8a88a91bb..ff45fb0f2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -241,7 +241,7 @@ sig AST objects are reference counted and unwrapping an AST disables automatic reference counting, i.e., all references to the IntPtr that is returned must be handled externally and through native calls (see e.g., - Z3native.inc_ref). + [Z3native.inc_ref]). {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr @@ -251,7 +251,7 @@ sig managed objects. Note that the native ast that is passed must be a native object obtained from Z3 (e.g., through {!unwrap_ast}) and that it must have a correct reference count (see e.g., - Z3native.inc_ref). *) + [Z3native.inc_ref]). *) val wrap_ast : context -> Z3native.z3_ast -> ast end @@ -439,7 +439,7 @@ sig (** Update a mutable configuration parameter. The list of all configuration parameters can be obtained using the Z3 executable: - z3.exe -p + [z3.exe -p] Only a few configuration parameters are mutable once the context is created. An exception is thrown when trying to modify an immutable parameter. {!get_param_value} *) @@ -479,7 +479,7 @@ sig {!get_simplify_help} *) val simplify : Expr.expr -> Params.params option -> expr - (** A string describing all available parameters to Expr.Simplify. *) + (** A string describing all available parameters to [Expr.Simplify]. *) val get_simplify_help : context -> string (** Retrieves parameter descriptions for simplifier. *) @@ -498,20 +498,20 @@ sig The number of new arguments should coincide with the current number of arguments. *) val update : Expr.expr -> Expr.expr list -> expr - (** Substitute every occurrence of from[i] in the expression with to[i], for i smaller than num_exprs. + (** Substitute every occurrence of [from[i]] in the expression with [to[i]], for [i] smaller than [num_exprs]. - The result is the new expression. The arrays from and to must have size num_exprs. - For every i smaller than num_exprs, we must have that - sort of from[i] must be equal to sort of to[i]. *) + The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. + For every [i] smaller than [num_exprs], we must have that + sort of [from[i]] must be equal to sort of [to[i]]. *) val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr - (** Substitute every occurrence of from in the expression with to. + (** Substitute every occurrence of [from] in the expression with [to]. {!substitute} *) val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr (** Substitute the free variables in the expression with the expressions in the expr array - For every i smaller than num_exprs, the variable with de-Bruijn index i is replaced with term to[i]. *) + For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) val substitute_vars : Expr.expr -> Expr.expr list -> expr (** Translates (copies) the term to another context. @@ -554,7 +554,7 @@ sig val mk_numeral_string : context -> string -> Sort.sort -> expr (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than MakeNumeral since it is not necessary to parse a string. + It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. @return A Term with the given value and sort *) val mk_numeral_int : context -> int -> Sort.sort -> expr end @@ -580,19 +580,19 @@ sig (** Creates a Boolean value. *) val mk_val : context -> bool -> Expr.expr - (** Mk an expression representing not(a). *) + (** Mk an expression representing [not(a)]. *) val mk_not : context -> Expr.expr -> Expr.expr - (** Create an expression representing an if-then-else: ite(t1, t2, t3). *) + (** Create an expression representing an if-then-else: [ite(t1, t2, t3)]. *) val mk_ite : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 iff t2. *) + (** Create an expression representing [t1 iff t2]. *) val mk_iff : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 -> t2. *) + (** Create an expression representing [t1 -> t2]. *) val mk_implies : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 xor t2. *) + (** Create an expression representing [t1 xor t2]. *) val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing the AND of args *) @@ -604,7 +604,7 @@ sig (** Creates the equality between two expr's. *) val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Creates a distinct term. *) + (** Creates a [distinct] term. *) val mk_distinct : context -> Expr.expr list -> Expr.expr (** Indicates whether the expression is the true or false expression @@ -806,45 +806,45 @@ sig (** Array read. - The argument a is the array and i is the index + The argument [a] is the array and [i] is the index of the array that gets read. - The node a must have an array sort [domain -> range], - and i must have the sort domain. - The sort of the result is range. + The node [a] must have an array sort [[domain -> range]], + and [i] must have the sort [domain]. + The sort of the result is [range]. {!Z3Array.mk_sort} {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr (** Array update. - The node a must have an array sort [domain -> range], - i must have sort domain, - v must have sort range. The sort of the result is [domain -> range]. + The node [a] must have an array sort [[domain -> range]], + [i] must have sort [domain], + [v] must have sort range. The sort of the result is [[domain -> range]]. The semantics of this function is given by the theory of arrays described in the SMT-LIB standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to a - (with respect to select) - on all indices except for i, where it maps to v - (and the select of a with - respect to i may be a different value). + The result of this function is an array that is equal to [a] + (with respect to [select]) + on all indices except for [i], where it maps to [v] + (and the [select] of [a] with + respect to [i] may be a different value). {!Z3Array.mk_sort} {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create a constant array. - The resulting term is an array, such that a selecton an arbitrary index - produces the value v. + The resulting term is an array, such that a [select]on an arbitrary index + produces the value [v]. {!Z3Array.mk_sort} {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr (** Maps f on the argument arrays. - Eeach element of args must be of an array sort [domain_i -> range_i]. - The function declaration f must have type range_1 .. range_n -> range. - v must have sort range. The sort of the result is [domain_i -> range]. + Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. + The function declaration [f] must have type [ range_1 .. range_n -> range]. + [v] must have sort range. The sort of the result is [[domain_i -> range]]. {!Z3Array.mk_sort} {!mk_select} {!mk_store} *) @@ -938,8 +938,8 @@ sig (** Indicates whether the term is an relation store Insert a record into a relation. - The function takes n+1 arguments, where the first argument is the relation and the remaining n elements - correspond to the n columns of the relation. *) + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + correspond to the [n] columns of the relation. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an empty relation *) @@ -997,8 +997,8 @@ sig (** Indicates whether the term is a relational select Check if a record is an element of the relation. - The function takes n+1 arguments, where the first argument is a relation, - and the remaining n arguments correspond to a record. *) + The function takes [n+1] arguments, where the first argument is a relation, + and the remaining [n] arguments correspond to a record. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a relational clone (copy) @@ -1161,11 +1161,11 @@ sig (** Creates an integer constant. *) val mk_const_s : context -> string -> Expr.expr - (** Create an expression representing t1 mod t2. + (** Create an expression representing [t1 mod t2]. The arguments must have int type. *) val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 rem t2. + (** Create an expression representing [t1 rem t2]. The arguments must have int type. *) val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1181,8 +1181,8 @@ sig There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - You can take the floor of a real by creating an auxiliary integer Term k and - and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. + You can take the floor of a real by creating an auxiliary integer Term [k] and + and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. The argument must be of integer sort. *) val mk_int2real : context -> Expr.expr -> Expr.expr @@ -1334,34 +1334,34 @@ sig (** Indicates whether the term is an algebraic number *) val is_algebraic_number : Expr.expr -> bool - (** Create an expression representing t[0] + t[1] + .... *) + (** Create an expression representing [t[0] + t[1] + ...]. *) val mk_add : context -> Expr.expr list -> Expr.expr - (** Create an expression representing t[0] * t[1] * .... *) + (** Create an expression representing [t[0] * t[1] * ...]. *) val mk_mul : context -> Expr.expr list -> Expr.expr - (** Create an expression representing t[0] - t[1] - .... *) + (** Create an expression representing [t[0] - t[1] - ...]. *) val mk_sub : context -> Expr.expr list -> Expr.expr - (** Create an expression representing -t. *) + (** Create an expression representing [-t]. *) val mk_unary_minus : context -> Expr.expr -> Expr.expr - (** Create an expression representing t1 / t2. *) + (** Create an expression representing [t1 / t2]. *) val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 ^ t2. *) + (** Create an expression representing [t1 ^ t2]. *) val mk_power : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 < t2 *) + (** Create an expression representing [t1 < t2] *) val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 <= t2 *) + (** Create an expression representing [t1 <= t2] *) val mk_le : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 > t2 *) + (** Create an expression representing [t1 > t2] *) val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr - (** Create an expression representing t1 >= t2 *) + (** Create an expression representing [t1 >= t2] *) val mk_ge : context -> Expr.expr -> Expr.expr -> Expr.expr end @@ -1610,8 +1610,8 @@ sig (** Unsigned division. - It is defined as the floor of t1/t2 if \c t2 is - different from zero. If t2 is zero, then the result + It is defined as the floor of [t1/t2] if \c t2 is + different from zero. If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1620,33 +1620,33 @@ sig It is defined in the following way: - - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. + - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. - - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. + - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned remainder. - It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. - If t2 is zero, then the result is undefined. + It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed remainder. - It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. + It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed remainder (sign follows divisor). - If t2 is zero, then the result is undefined. + If [t2] is zero, then the result is undefined. The arguments must have the same bit-vector sort. *) val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr @@ -1694,27 +1694,27 @@ sig The arguments must have a bit-vector sort. @return - The result is a bit-vector of size n1+n2, where n1 (n2) - is the size of t1 (t2). *) + The result is a bit-vector of size [n1+n2], where [n1] ([n2]) + is the size of [t1] ([t2]). *) val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector extraction. Extract the bits between two limits from a bitvector of - size m to yield a new bitvector of size n, where - n = high - low + 1. *) + size [m] to yield a new bitvector of size [n], where + [n = high - low + 1]. *) val mk_extract : context -> int -> int -> Expr.expr -> Expr.expr (** Bit-vector sign extension. Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size m+i, where \c m is the size of the given bit-vector. *) + size [m+i], where \c m is the size of the given bit-vector. *) val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector zero extension. Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size m+i, where \c m is the size of the + bitvector of size [m+i], where \c m is the size of the given bit-vector. *) val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr @@ -1723,7 +1723,7 @@ sig (** Shift left. - It is equivalent to multiplication by 2^x where \c x is the value of third argument. + It is equivalent to multiplication by [2^x] where \c x is the value of third argument. NB. The semantics of shift operations varies between environments. This definition does not necessarily capture directly the semantics of the @@ -1732,7 +1732,7 @@ sig (** Logical shift right - It is equivalent to unsigned division by 2^x where \c x is the value of the third argument. + It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. NB. The semantics of shift operations varies between environments. This definition does not necessarily capture directly the semantics of the @@ -1773,7 +1773,7 @@ sig (** Create an integer from the bit-vector argument If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. - So the result is non-negative and in the range [0..2^N-1], where + So the result is non-negative and in the range [[0..2^N-1]], where N are the number of bits in the argument. If \c is_signed is true, \c t1 is treated as a signed bit-vector. @@ -2353,15 +2353,15 @@ sig end (** Retrieves the interpretation (the assignment) of a func_decl in the model. - An expression if the function has an interpretation in the model, null otherwise. *) + @return An expression if the function has an interpretation in the model, null otherwise. *) val get_const_interp : model -> FuncDecl.func_decl -> Expr.expr option (** Retrieves the interpretation (the assignment) of an expression in the model. - An expression if the constant has an interpretation in the model, null otherwise. *) + @return An expression if the constant has an interpretation in the model, null otherwise. *) val get_const_interp_e : model -> Expr.expr -> Expr.expr option (** Retrieves the interpretation (the assignment) of a non-constant func_decl in the model. - A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) + @return A FunctionInterpretation if the function has an interpretation in the model, null otherwise. *) val get_func_interp : model -> FuncDecl.func_decl -> FuncInterp.func_interp option (** The number of constant interpretations in the model. *) @@ -2383,11 +2383,11 @@ sig This function may fail if the argument contains quantifiers, is partial (MODEL_PARTIAL enabled), or if it is not well-sorted. - In this case a ModelEvaluationFailedException is thrown. + In this case a [ModelEvaluationFailedException] is thrown. *) val eval : model -> Expr.expr -> bool -> Expr.expr option - (** Alias for eval. *) + (** Alias for [eval]. *) val evaluate : model -> Expr.expr -> bool -> Expr.expr option (** The number of uninterpreted sorts that the model has an interpretation for. *) @@ -2408,7 +2408,7 @@ sig val sort_universe : model -> Sort.sort -> AST.ast list (** Conversion of models to strings. - A string representation of the model. *) + @return A string representation of the model. *) val to_string : model -> string end @@ -2416,17 +2416,17 @@ end Probes are used to inspect a goal (aka problem) and collect information that may be used to decide which solver and/or preprocessing step will be used. - The complete list of probes may be obtained using the procedures Context.NumProbes - and Context.ProbeNames. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. + The complete list of probes may be obtained using the procedures [Context.NumProbes] + and [Context.ProbeNames]. + It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. *) module Probe : sig type probe (** Execute the probe over the goal. - A probe always produce a float value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + @return A probe always produce a float value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float (** The number of supported Probes. *) @@ -2478,9 +2478,9 @@ end (** Tactics Tactics are the basic building block for creating custom solvers for specific problem domains. - The complete list of tactics may be obtained using Context.get_num_tactics - and Context.get_tactic_names. - It may also be obtained using the command (help-tactics) in the SMT 2.0 front-end. + The complete list of tactics may be obtained using [Context.get_num_tactics] + and [Context.get_tactic_names]. + It may also be obtained using the command [(help-tactics)] in the SMT 2.0 front-end. *) module Tactic : sig @@ -2504,8 +2504,8 @@ sig val get_subgoal : apply_result -> int -> Goal.goal (** Convert a model for a subgoal into a model for the original - goal g, that the ApplyResult was obtained from. - #return A model for g *) + goal [g], that the ApplyResult was obtained from. + #return A model for [g] *) val convert_model : apply_result -> int -> Model.model -> Model.model (** A string representation of the ApplyResult. *) @@ -2549,7 +2549,7 @@ sig (** Create a tactic that applies one tactic to a given goal if the probe evaluates to true. - If the probe evaluates to false, then the new tactic behaves like the skip tactic. *) + If the probe evaluates to false, then the new tactic behaves like the [skip] tactic. *) val when_ : context -> Probe.probe -> tactic -> tactic (** Create a tactic that applies a tactic to a given goal if the probe @@ -2577,7 +2577,7 @@ sig val using_params : context -> tactic -> Params.params -> tactic (** Create a tactic that applies a tactic using the given set of parameters. - Alias for UsingParams*) + Alias for [UsingParams]*) val with_ : context -> tactic -> Params.params -> tactic (** Create a tactic that applies the given tactics in parallel. *) @@ -2718,26 +2718,26 @@ sig {!Proof} *) val check : solver -> Expr.expr list -> status - (** The model of the last Check. + (** The model of the last [Check]. - The result is None if Check was not invoked before, - if its results was not SATISFIABLE, or if model production is not enabled. *) + The result is [None] if [Check] was not invoked before, + if its results was not [SATISFIABLE], or if model production is not enabled. *) val get_model : solver -> Model.model option - (** The proof of the last Check. + (** The proof of the last [Check]. - The result is null if Check was not invoked before, - if its results was not UNSATISFIABLE, or if proof production is disabled. *) + The result is [null] if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if proof production is disabled. *) val get_proof : solver -> Expr.expr option - (** The unsat core of the last Check. + (** The unsat core of the last [Check]. - The unsat core is a subset of Assertions - The result is empty if Check was not invoked before, - if its results was not UNSATISFIABLE, or if core production is disabled. *) + The unsat core is a subset of [Assertions] + The result is empty if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if core production is disabled. *) val get_unsat_core : solver -> AST.ast list - (** A brief justification of why the last call to Check returned UNKNOWN. *) + (** A brief justification of why the last call to [Check] returned [UNKNOWN]. *) val get_reason_unknown : solver -> string (** Solver statistics. *) @@ -2759,7 +2759,7 @@ sig (** Creates a solver that is implemented using the given tactic. - The solver supports the commands Push and Pop, but it + The solver supports the commands [Push] and [Pop], but it will always solve each check from scratch. *) val mk_solver_t : context -> Tactic.tactic -> solver @@ -2811,7 +2811,7 @@ sig (** Backtrack one backtracking point. - Note that an exception is thrown if Pop is called without a corresponding Push + Note that an exception is thrown if Pop is called without a corresponding [Push] {!push} *) val pop : fixedpoint -> unit @@ -2875,28 +2875,28 @@ sig {!parse_smtlib_string} *) val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit - (** The number of SMTLIB formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_formulas : context -> int - (** The formulas parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_formulas : context -> Expr.expr list - (** The number of SMTLIB assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_assumptions : context -> int - (** The assumptions parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The assumptions parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_assumptions : context -> Expr.expr list - (** The number of SMTLIB declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_decls : context -> int - (** The declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_decls : context -> FuncDecl.func_decl list - (** The number of SMTLIB sorts parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The number of SMTLIB sorts parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_num_smtlib_sorts : context -> int - (** The sort declarations parsed by the last call to ParseSMTLIBString or ParseSMTLIBFile. *) + (** The sort declarations parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) val get_smtlib_sorts : context -> Sort.sort list (** Parse the given string using the SMT-LIB2 parser. From e7345f5ea809049d56705635208ffac8b93ab87a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 17 Apr 2014 15:06:32 +0100 Subject: [PATCH 457/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index dda8807c9..e2fa01478 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1482,7 +1482,7 @@ struct let get_big_int ( x : expr ) = if (is_int_numeral x) then - let s = to_string(x) in + let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in (Big_int.big_int_of_string s) else raise (Z3native.Exception "Conversion failed.") @@ -1526,7 +1526,7 @@ struct let get_ratio ( x : expr ) = if (is_rat_numeral x) then - let s = to_string(x) in + let s = (Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x)) in (Ratio.ratio_of_string s) else raise (Z3native.Exception "Conversion failed.") From a73a66b79c64971109ab3425654a8299ff1332bf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 22 Apr 2014 11:49:47 +0100 Subject: [PATCH 458/646] ML API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index e2fa01478..dafd255f8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -119,7 +119,7 @@ let mk_list ( f : int -> 'a ) ( n : int ) = if (i >= n) then tail else - (mk_list' f (i+1) n ((f i) :: tail)) + (f i) :: (mk_list' f (i+1) n tail) in mk_list' f 0 n [] From 9160925c28fbcc3586dc15dad249096f06bec148 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 15:15:59 +0100 Subject: [PATCH 459/646] ML API: added Expr.equal and Expr.compare Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 6 ++++++ src/api/ml/z3.mli | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index dafd255f8..3f40b288c 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -717,6 +717,8 @@ sig val mk_app : context -> FuncDecl.func_decl -> expr list -> expr val mk_numeral_string : context -> string -> Sort.sort -> expr val mk_numeral_int : context -> int -> Sort.sort -> expr + val equal : expr -> expr -> bool + val compare : expr -> expr -> int end = struct type expr = Expr of AST.ast @@ -830,6 +832,10 @@ end = struct let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) = expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) + + let equal ( a : expr ) ( b : expr ) = AST.equal (ast_of_expr a) (ast_of_expr b) + + let compare a b = AST.compare (ast_of_expr a) (ast_of_expr b) end open FuncDecl diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index ff45fb0f2..84f230d95 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -554,9 +554,17 @@ sig val mk_numeral_string : context -> string -> Sort.sort -> expr (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. - It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. - @return A Term with the given value and sort *) + It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. + @return A Term with the given value and sort *) val mk_numeral_int : context -> int -> Sort.sort -> expr + + (** Comparison operator. + @return True if the two expr's are equal; false otherwise. *) + val equal : expr -> expr -> bool + + (** Object Comparison. + @return Negative if the first expr should be sorted before the second, positive if after, else zero. *) + val compare : expr -> expr -> int end (** Boolean expressions; Propositional logic and equality *) From 5e2a7e06fd21ce14e3ff33042fbec7562307d3a4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 23 Apr 2014 15:25:08 +0100 Subject: [PATCH 460/646] ML API: added constructors for ast_map and ast_vector Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 31 ++++++++++++++++++++++--------- src/api/ml/z3.mli | 20 ++++++++++++-------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 3f40b288c..b48681b87 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -214,7 +214,7 @@ struct struct type ast_vector = z3_native_object - let ast_vector_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; inc_ref = Z3native.ast_vector_inc_ref ; @@ -223,6 +223,8 @@ struct (z3obj_create res) ; res + let mk_ast_vector ( ctx : context ) = (create ctx (Z3native.mk_ast_vector (context_gno ctx))) + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) @@ -239,7 +241,7 @@ struct Z3native.ast_vector_push (z3obj_gnc x) (z3obj_gno x) (z3obj_gno a) let translate ( x : ast_vector ) ( to_ctx : context ) = - ast_vector_of_ptr to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) + create to_ctx (Z3native.ast_vector_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx)) let to_string ( x : ast_vector ) = Z3native.ast_vector_to_string (z3obj_gnc x) (z3obj_gno x) @@ -248,7 +250,18 @@ struct module ASTMap = struct type ast_map = z3_native_object + + let create ( ctx : context ) ( no : Z3native.ptr ) = + let res : ast_map = { m_ctx = ctx ; + m_n_obj = null ; + inc_ref = Z3native.ast_map_inc_ref ; + dec_ref = Z3native.ast_map_dec_ref } in + (z3obj_sno res ctx no) ; + (z3obj_create res) ; + res + let mk_ast_map ( ctx : context ) = (create ctx (Z3native.mk_ast_map (context_gno ctx))) + let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_map = { m_ctx = ctx ; m_n_obj = null ; @@ -277,7 +290,7 @@ struct Z3native.ast_map_size (z3obj_gnc x) (z3obj_gno x) let get_keys ( x : ast_map ) = - let av = ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in + let av = ASTVector.create (z3obj_gc x) (Z3native.ast_map_keys (z3obj_gnc x) (z3obj_gno x)) in let f i = (ASTVector.get av i) in mk_list f (ASTVector.get_size av) @@ -2061,7 +2074,7 @@ struct mk_list f n let sort_universe ( x : model ) ( s : sort ) = - let n_univ = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in + let n_univ = AST.ASTVector.create (z3obj_gc x) (Z3native.model_get_sort_universe (z3obj_gnc x) (z3obj_gno x) (Sort.gno s)) in let n = (AST.ASTVector.get_size n_univ) in let f i = (AST.ASTVector.get n_univ i) in mk_list f n @@ -2386,11 +2399,11 @@ struct Z3native.solver_assert_and_track (z3obj_gnc x) (z3obj_gno x) (Expr.gno c) (Expr.gno p) let get_num_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in (AST.ASTVector.get_size a) let get_assertions ( x : solver ) = - let a = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in + let a = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_assertions (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size a) in let f i = (expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get a i))) in mk_list f n @@ -2423,7 +2436,7 @@ struct Some (expr_of_ptr (z3obj_gc x) q) let get_unsat_core ( x : solver ) = - let cn = AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in + let cn = AST.ASTVector.create (z3obj_gc x) (Z3native.solver_get_unsat_core (z3obj_gnc x) (z3obj_gno x)) in let n = (AST.ASTVector.get_size cn) in let f i = (AST.ASTVector.get cn i) in mk_list f n @@ -2545,13 +2558,13 @@ struct Z3native.fixedpoint_to_string (z3obj_gnc x) (z3obj_gno x) (List.length queries) (Array.of_list (List.map f queries)) let get_rules ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_rules (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n let get_assertions ( x : fixedpoint ) = - let v = (AST.ASTVector.ast_vector_of_ptr (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in + let v = (AST.ASTVector.create (z3obj_gc x) (Z3native.fixedpoint_get_assertions (z3obj_gnc x) (z3obj_gno x))) in let n = (AST.ASTVector.get_size v) in let f i =(expr_of_ptr (z3obj_gc x) (z3obj_gno (AST.ASTVector.get v i))) in mk_list f n diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 84f230d95..4347c7431 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -107,10 +107,9 @@ sig (** A string representation of the symbol. *) val to_string : symbol -> string - (** Creates a new symbol using an integer. - - Not all integers can be passed to this function. - The legal range of unsigned integers is 0 to 2^30-1. *) + (** Creates a new symbol using an integer. + Not all integers can be passed to this function. + The legal range of unsigned integers is 0 to 2^30-1. *) val mk_int : context -> int -> symbol (** Creates a new symbol using a string. *) @@ -132,12 +131,14 @@ sig module ASTVector : sig type ast_vector + + (** Create an empty AST vector *) + val mk_ast_vector : context -> ast_vector (** The size of the vector *) val get_size : ast_vector -> int - (** - Retrieves the i-th object in the vector. + (** Retrieves the i-th object in the vector. @return An AST *) val get : ast_vector -> int -> ast @@ -162,7 +163,10 @@ sig (** Map from AST to AST *) module ASTMap : sig - type ast_map + type ast_map + + (** Create an empty mapping from AST to AST *) + val mk_ast_map : context -> ast_map (** Checks whether the map contains a key. @return True if the key in the map, false otherwise. *) @@ -2297,7 +2301,7 @@ sig (** Creates a new Goal. - Note that the Context must have been created with proof generation support if + Note that the Context must have been created with proof generation support if the fourth argument is set to true here. *) val mk_goal : context -> bool -> bool -> bool -> goal From a8f703e0344812ee94b037bda9a17802415ff03d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 18:50:11 +0100 Subject: [PATCH 461/646] ML API bugfix. Thanks to Martin Neuhaeusser for reporting this one! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index b48681b87..bdcf1a26b 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2045,7 +2045,7 @@ struct let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs (z3obj_gnc x) (z3obj_gno x) let get_func_decls ( x : model ) = - let n = (get_num_consts x) in + let n = (get_num_funcs x) in let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in mk_list f n From 7ec8c81c3369613a3baf5272b1973344997a9927 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 18:59:03 +0100 Subject: [PATCH 462/646] ML API fix for datatype construction (Issue #121). Thanks to Elarnon for reporting this one! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 12 ++++++++---- src/api/ml/z3.mli | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index bdcf1a26b..f34ce0ca7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -374,6 +374,10 @@ struct let sort_lton ( a : sort list ) = let f ( e : sort ) = match e with Sort(a) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) + + let sort_option_lton ( a : sort option list ) = + let f ( e : sort option ) = match e with None -> null | Some(Sort(a)) -> (AST.ptr_of_ast a) in + Array.of_list (List.map f a) let equal : sort -> sort -> bool = fun a b -> (a == b) || @@ -1257,7 +1261,7 @@ struct let _sizes = Hashtbl.create 0 - let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = let n = (List.length field_names) in if n != (List.length sorts) then raise (Z3native.Exception "Number of field names does not match number of sorts") @@ -1269,7 +1273,7 @@ struct (Symbol.gno recognizer) n (Symbol.symbol_lton field_names) - (sort_lton sorts) + (sort_option_lton sorts) (Array.of_list sort_refs)) in let no : constructor = { m_ctx = ctx ; m_n_obj = null ; @@ -1316,11 +1320,11 @@ struct res end - let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let mk_constructor ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = Constructor.create ctx name recognizer field_names sorts sort_refs - let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort list ) ( sort_refs : int list ) = + let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = mk_constructor ctx (Symbol.mk_string ctx name) recognizer field_names sorts sort_refs let mk_sort ( ctx : context ) ( name : Symbol.symbol ) ( constructors : Constructor.constructor list ) = diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 4347c7431..1342bb4bc 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1053,12 +1053,12 @@ sig (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a datatype constructor. if the corresponding sort reference is 0, then the value in sort_refs should be an index referring to one of the recursive datatypes that is declared. *) - val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort list -> int list -> Constructor.constructor + val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a new datatype sort. *) val mk_sort : context -> Symbol.symbol -> Constructor.constructor list -> Sort.sort From 84b7644305c64475c0aedb72f202c384342a6155 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 19:16:16 +0100 Subject: [PATCH 463/646] ML API bugfix (Issue #119). Thanks to user Elarnon for reporting this! Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 8ce652ed5..fba194bac 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1464,7 +1464,7 @@ def mk_ml(): for p in params: if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) - ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) + ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s_val, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 From 94a8c271d4fb3c47086dacc27ae789e80867d951 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 24 Jul 2014 19:29:06 +0100 Subject: [PATCH 464/646] ML API bugfix for datatype module (Issue #120). Thanks to user Elarnon for reporting this! Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/z3.ml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index f34ce0ca7..013101398 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -277,7 +277,7 @@ struct let find ( x : ast_map ) ( key : ast ) = ast_of_ptr (z3obj_gc x) (Z3native.ast_map_find (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key)) - let insert ( x : ast_map ) ( key : ast ) ( value : ast) = + let insert ( x : ast_map ) ( key : ast ) ( value : ast ) = Z3native.ast_map_insert (z3obj_gnc x) (z3obj_gno x) (z3obj_gno key) (z3obj_gno value) let erase ( x : ast_map ) ( key : ast ) = @@ -1259,7 +1259,13 @@ struct struct type constructor = z3_native_object - let _sizes = Hashtbl.create 0 + module FieldNumTable = Hashtbl.Make(struct + type t = AST.ast + let equal x y = AST.compare x y = 0 + let hash = AST.hash + end) + + let _field_nums = FieldNumTable.create 0 let create ( ctx : context ) ( name : Symbol.symbol ) ( recognizer : Symbol.symbol ) ( field_names : Symbol.symbol list ) ( sorts : sort option list ) ( sort_refs : int list ) = let n = (List.length field_names) in @@ -1283,10 +1289,10 @@ struct (z3obj_create no) ; let f = fun o -> Z3native.del_constructor (z3obj_gnc o) (z3obj_gno o) in Gc.finalise f no ; - Hashtbl.add _sizes no n ; + FieldNumTable.add _field_nums no n ; no - let get_num_fields ( x : constructor ) = Hashtbl.find _sizes x + let get_num_fields ( x : constructor ) = FieldNumTable.find _field_nums x let get_constructor_decl ( x : constructor ) = let (a, _, _) = (Z3native.query_constructor (z3obj_gnc x) (z3obj_gno x) (get_num_fields x)) in From fa4dab48522f4d9e96f4f7456cc57c9208cf622f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 14 Aug 2014 18:58:52 +0100 Subject: [PATCH 465/646] ML API: added .cmxs to the distribution. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a0c9213c9..bf1f5e471 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1402,7 +1402,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('\t%s ' % (OCAMLOPT)) + if DEBUG_MODE: + out.write('-g ') + out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1410,15 +1415,15 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L../.. -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('ml: api/ml/z3.cmxa api/ml/z3.cma\n') + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa\n') + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) - out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) for m in modules: out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) From fe0b579426cdb98ebe6f24324eb98fc0b8cddb0c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:02:00 +0100 Subject: [PATCH 466/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index bf1f5e471..784d47cee 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1402,12 +1402,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('-shared -o %s %s -linkall\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1415,7 +1415,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From a1bb307dd18bb02ba375e570805b36bbe5107f15 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:09:01 +0100 Subject: [PATCH 467/646] ML API: bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 784d47cee..3e9bd8eb2 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1402,7 +1402,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: @@ -1415,7 +1415,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib -lz3ml -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 7bd8dda766fa01a23b83367b27335d744af0c9e8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:18:40 +0100 Subject: [PATCH 468/646] ML API: bugfixes --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3e9bd8eb2..ef01ccc10 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1402,12 +1402,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-shared -o %s %s -linkall\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + out.write('-shared -cclib "-L%s -lz3ml" -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir,'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1415,7 +1415,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-Lapi/ml -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 8cd74a825d8c148566848835924dccb15c3982f6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 19 Aug 2014 19:32:33 +0100 Subject: [PATCH 469/646] ML API: Undoing earlier changes. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ef01ccc10..bf1f5e471 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1402,12 +1402,12 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('\t%s ' % (OCAMLOPT)) if DEBUG_MODE: out.write('-g ') - out.write('-shared -cclib "-L%s -lz3ml" -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir,'z3.cmxa'))) + out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) @@ -1415,7 +1415,7 @@ class MLComponent(Component): out.write('\t%s ' % (OCAMLC)) if DEBUG_MODE: out.write('-g ') - out.write('-cclib "-L%s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir,sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) out.write('\n') # Generate META file and package installation commands From 42f12ed75216d891550b879a987ef5e9036ee47a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 19:39:13 +0000 Subject: [PATCH 470/646] ML API: added interpolation, bugfixes. Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 10 +- src/api/ml/z3.ml | 121 ++-- src/api/ml/z3.mli | 1386 +++++++++++++++++++++-------------------- 3 files changed, 806 insertions(+), 711 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index fba194bac..4669b78fc 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -334,6 +334,8 @@ def param2ml(p): return "ptr" elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: return "%s array" % type2ml(param_type(p)) + elif k == OUT_MANAGED_ARRAY: + return "%s array" % type2ml(param_type(p)); else: return type2ml(param_type(p)) @@ -1067,7 +1069,7 @@ def ml_method_name(name): return name[3:] # Remove Z3_ def is_out_param(p): - if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: + if param_kind(p) == OUT or param_kind(p) == INOUT or param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT_MANAGED_ARRAY: return True else: return False @@ -1411,6 +1413,8 @@ def mk_ml(): type2str(param_type(param)), type2str(param_type(param)), param_array_capacity_pos(param))) + elif k == OUT_MANAGED_ARRAY: + ml_wrapper.write(' %s * _a%s = 0;\n' % (type2str(param_type(param)), i)) elif k == IN_ARRAY or k == INOUT_ARRAY: t = param_type(param) ts = type2str(t) @@ -1449,7 +1453,7 @@ def mk_ml(): else: ml_wrapper.write(', ') k = param_kind(param) - if k == OUT or k == INOUT: + if k == OUT or k == INOUT or k == OUT_MANAGED_ARRAY: ml_wrapper.write('&_a%s' % i) else: ml_wrapper.write('_a%i' % i) @@ -1465,6 +1469,8 @@ def mk_ml(): if param_kind(p) == OUT_ARRAY or param_kind(p) == INOUT_ARRAY: ml_wrapper.write(' _a%s_val = caml_alloc(_a%s, 0);\n' % (i, param_array_capacity_pos(p))) ml_wrapper.write(' for (_i = 0; _i < _a%s; _i++) { value t; %s Store_field(_a%s_val, _i, t); }\n' % (param_array_capacity_pos(p), ml_set_wrap(param_type(p), 't', '_a' + str(i) + '[_i]'), i)) + elif param_kind(p) == OUT_MANAGED_ARRAY: + ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) elif is_out_param(p): ml_wrapper.write(' %s\n' % ml_set_wrap(param_type(p), "_a" + str(i) + "_val", "_a" + str(i) )) i = i + 1 diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 013101398..2b54a1113 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -165,7 +165,7 @@ struct let symbol_lton ( a : symbol list ) = let f ( e : symbol ) = (gno e) in Array.of_list (List.map f a) - + let kind ( o : symbol ) = (symbol_kind_of_int (Z3native.get_symbol_kind (gnc o) (gno o))) let is_int_symbol ( o : symbol ) = (kind o) == INT_SYMBOL let is_string_symbol ( o : symbol ) = (kind o) == STRING_SYMBOL @@ -213,7 +213,7 @@ struct module ASTVector = struct type ast_vector = z3_native_object - + let create ( ctx : context ) ( no : Z3native.ptr ) = let res : ast_vector = { m_ctx = ctx ; m_n_obj = null ; @@ -224,7 +224,7 @@ struct res let mk_ast_vector ( ctx : context ) = (create ctx (Z3native.mk_ast_vector (context_gno ctx))) - + let get_size ( x : ast_vector ) = Z3native.ast_vector_size (z3obj_gnc x) (z3obj_gno x) @@ -259,7 +259,7 @@ struct (z3obj_sno res ctx no) ; (z3obj_create res) ; res - + let mk_ast_map ( ctx : context ) = (create ctx (Z3native.mk_ast_map (context_gno ctx))) let astmap_of_ptr ( ctx : context ) ( no : Z3native.ptr ) = @@ -330,7 +330,7 @@ struct if (get_id a) < (get_id b) then -1 else if (get_id a) > (get_id b) then 1 else 0 - + let translate ( x : ast ) ( to_ctx : context ) = if (z3obj_gnc x) == (context_gno to_ctx) then x @@ -366,7 +366,7 @@ struct | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") let ast_of_sort s = match s with Sort(x) -> x - + let gc ( x : sort ) = (match x with Sort(a) -> (z3obj_gc a)) let gnc ( x : sort ) = (match x with Sort(a) -> (z3obj_gnc a)) let gno ( x : sort ) = (match x with Sort(a) -> (z3obj_gno a)) @@ -378,7 +378,7 @@ struct let sort_option_lton ( a : sort option list ) = let f ( e : sort option ) = match e with None -> null | Some(Sort(a)) -> (AST.ptr_of_ast a) in Array.of_list (List.map f a) - + let equal : sort -> sort -> bool = fun a b -> (a == b) || if (gnc a) != (gnc b) then @@ -629,7 +629,6 @@ sig val to_string : params -> string val update_param_value : context -> string -> string -> unit - val get_param_value : context -> string -> string option val set_print_mode : context -> Z3enums.ast_print_mode -> unit end = struct type params = z3_native_object @@ -688,13 +687,6 @@ end = struct let update_param_value ( ctx : context ) ( id : string) ( value : string )= Z3native.update_param_value (context_gno ctx) id value - let get_param_value ( ctx : context ) ( id : string ) = - let (r, v) = (Z3native.get_param_value (context_gno ctx) id) in - if not r then - None - else - Some v - let set_print_mode ( ctx : context ) ( value : ast_print_mode ) = Z3native.set_ast_print_mode (context_gno ctx) (int_of_ast_print_mode value) end @@ -826,11 +818,11 @@ end = struct let is_well_sorted ( x : expr ) = Z3native.is_well_sorted (gnc x) (gno x) let get_sort ( x : expr ) = sort_of_ptr (Expr.gc x) (Z3native.get_sort (gnc x) (gno x)) - + let is_const ( x : expr ) = (match x with Expr(a) -> (AST.is_app a)) && (get_num_args x) == 0 && (FuncDecl.get_domain_size (get_func_decl x)) == 0 - + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( range : sort ) = expr_of_ptr ctx (Z3native.mk_const (context_gno ctx) (Symbol.gno name) (Sort.gno range)) @@ -851,7 +843,7 @@ end = struct expr_of_ptr ctx (Z3native.mk_int (context_gno ctx) v (Sort.gno ty)) let equal ( a : expr ) ( b : expr ) = AST.equal (ast_of_expr a) (ast_of_expr b) - + let compare a b = AST.compare (ast_of_expr a) (ast_of_expr b) end @@ -941,7 +933,7 @@ struct raise (Z3native.Exception "Invalid coercion") else Quantifier(e) - + let gc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gc e) let gnc ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gnc e) let gno ( x : quantifier ) = match (x) with Quantifier(e) -> (Expr.gno e) @@ -949,13 +941,13 @@ struct module Pattern = struct type pattern = Pattern of ast - + let ast_of_pattern e = match e with Pattern(x) -> x let pattern_of_ast a = - (* CMW: Unchecked ok? *) + (* CMW: Unchecked ok? *) Pattern(a) - + let gc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gc a) let gnc ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gnc a) let gno ( x : pattern ) = match (x) with Pattern(a) -> (z3obj_gno a) @@ -1258,11 +1250,11 @@ struct module Constructor = struct type constructor = z3_native_object - + module FieldNumTable = Hashtbl.Make(struct - type t = AST.ast - let equal x y = AST.compare x y = 0 - let hash = AST.hash + type t = AST.ast + let equal x y = AST.compare x y = 0 + let hash = AST.hash end) let _field_nums = FieldNumTable.create 0 @@ -1291,7 +1283,7 @@ struct Gc.finalise f no ; FieldNumTable.add _field_nums no n ; no - + let get_num_fields ( x : constructor ) = FieldNumTable.find _field_nums x let get_constructor_decl ( x : constructor ) = @@ -1613,16 +1605,16 @@ struct let mk_sub ( ctx : context ) ( t : expr list ) = let f x = (Expr.gno x) in - (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) + (expr_of_ptr ctx (Z3native.mk_sub (context_gno ctx) (List.length t) (Array.of_list (List.map f t)))) let mk_unary_minus ( ctx : context ) ( t : expr ) = - (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) + (expr_of_ptr ctx (Z3native.mk_unary_minus (context_gno ctx) (Expr.gno t))) let mk_div ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + (expr_of_ptr ctx (Z3native.mk_div (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_power ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = - (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) + (expr_of_ptr ctx (Z3native.mk_power (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = (expr_of_ptr ctx (Z3native.mk_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) @@ -1893,7 +1885,7 @@ struct let get_formulas ( x : goal ) = let n = get_size x in let f i = ((expr_of_ptr (z3obj_gc x) - (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in + (Z3native.goal_formula (z3obj_gnc x) (z3obj_gno x) i))) in mk_list f n let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs (z3obj_gnc x) (z3obj_gno x) @@ -2065,7 +2057,7 @@ struct let f i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_func_decl (z3obj_gnc x) (z3obj_gno x) i) in let g i = func_decl_of_ptr (z3obj_gc x) (Z3native.model_get_const_decl (z3obj_gnc x) (z3obj_gno x) i) in (mk_list f n_funcs) @ (mk_list g n_consts) - + let eval ( x : model ) ( t : expr ) ( completion : bool ) = let (r, v) = (Z3native.model_eval (z3obj_gnc x) (z3obj_gno x) (Expr.gno t) completion) in if not r then @@ -2316,7 +2308,7 @@ struct mutable m_is_float : bool ; mutable m_int : int ; mutable m_float : float } - + let create_si k v = let res : statistics_entry = { m_key = k ; @@ -2644,7 +2636,7 @@ struct mk_list f n let get_num_smtlib_sorts ( ctx : context ) = Z3native.get_smtlib_num_sorts (context_gno ctx) - + let get_smtlib_sorts ( ctx : context ) = let n = (get_num_smtlib_sorts ctx) in let f i = (sort_of_ptr ctx (Z3native.get_smtlib_sort (context_gno ctx) i)) in @@ -2683,6 +2675,65 @@ struct (let f x = FuncDecl.gno x in (Array.of_list (List.map f decls))))) end +module Interpolation = +struct + let mk_interpolant ( ctx : context ) ( a : expr ) = + (expr_of_ptr ctx (Z3native.mk_interpolant (context_gno ctx) (Expr.gno a))) + + let mk_interpolation_context ( settings : ( string * string ) list ) = + let cfg = Z3native.mk_config () in + let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in + (List.iter f settings) ; + let v = Z3native.mk_interpolation_context cfg in + Z3native.del_config(cfg) ; + Z3native.set_ast_print_mode v (int_of_ast_print_mode PRINT_SMTLIB2_COMPLIANT) ; + Z3native.set_internal_error_handler v ; + let res = { m_n_ctx = v; m_n_obj_cnt = 0 } in + let f = fun o -> dispose_context o in + Gc.finalise f res; + res + + let get_interpolant ( ctx : context ) ( pf : expr ) ( pat: expr ) ( p : Params.params ) = + (ASTVector.create ctx (Z3native.get_interpolant (context_gno ctx) (Expr.gno pf) (Expr.gno pat) (z3obj_gno p))) + + let compute_interpolant ( ctx : context ) ( pat : expr ) ( p : Params.params ) = + let (r, interp, model) = (Z3native.compute_interpolant (context_gno ctx) (Expr.gno pat) (z3obj_gno p)) in + match (lbool_of_int r) with + | L_TRUE -> ((ASTVector.create ctx interp), (Model.create ctx model)) + | _ -> raise (Z3native.Exception "Error computing interpolant.") + + let get_interpolation_profile ( ctx : context ) = + (Z3native.interpolation_profile (context_gno ctx)) + + let read_interpolation_problem ( ctx : context ) ( filename : string ) = + let (r, num, cnsts, parents, error, num_theory, theory) = (Z3native.read_interpolation_problem (context_gno ctx) filename) in + match r with + | 0 -> raise (Z3native.Exception "Interpolation problem could not be read.") + | _ -> + let f1 i = (expr_of_ptr ctx (Array.get cnsts i)) in + let f2 i = (Array.get parents i) in + let f3 i = (expr_of_ptr ctx (Array.get theory i)) in + ((mk_list f1 num), + (mk_list f2 num), + (mk_list f3 num_theory)) + + let check_interpolant ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( interps : Expr.expr list ) ( num_theory : int ) ( theory : Expr.expr list ) = + let (r, str) = (Z3native.check_interpolant (context_gno ctx) + num + (let f x = Expr.gno x in (Array.of_list (List.map f cnsts))) + (Array.of_list parents) + (let f x = Expr.gno x in (Array.of_list (List.map f interps))) + num_theory + (let f x = Expr.gno x in (Array.of_list (List.map f theory)))) in + match (lbool_of_int r) with + | L_UNDEF -> raise (Z3native.Exception "Interpolant could not be verified.") + | L_FALSE -> raise (Z3native.Exception "Interpolant could not be verified.") + | _ -> () + + let write_interpolation_problem ( ctx : context ) ( num : int ) ( cnsts : Expr.expr list ) ( parents : int list ) ( filename : string ) ( num_theory : int ) ( theory : Expr.expr list ) = + (Z3native.write_interpolation_problem (context_gno ctx) num (expr_lton cnsts) (Array.of_list parents) filename num_theory (expr_lton theory)) ; + () +end let set_global_param ( id : string ) ( value : string ) = (Z3native.global_param_set id value) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 1342bb4bc..b2f0939d0 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -149,11 +149,11 @@ sig val resize : ast_vector -> int -> unit (** Add an ast to the back of the vector. The size - is increased by 1. *) + is increased by 1. *) val push : ast_vector -> ast -> unit (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) + @return A new ASTVector *) val translate : ast_vector -> context -> ast_vector (** Retrieves a string representation of the vector. *) @@ -196,7 +196,7 @@ sig end (** The AST's hash code. - @return A hash code *) + @return A hash code *) val hash : ast -> int (** A unique identifier for the AST (unique among all ASTs). *) @@ -227,34 +227,34 @@ sig val to_sexpr : ast -> string (** Comparison operator. - @return True if the two ast's are from the same context - and represent the same sort; false otherwise. *) + @return True if the two ast's are from the same context + and represent the same sort; false otherwise. *) val equal : ast -> ast -> bool (** Object Comparison. - @return Negative if the first ast should be sorted before the second, positive if after else zero. *) + @return Negative if the first ast should be sorted before the second, positive if after else zero. *) val compare : ast -> ast -> int (** Translates (copies) the AST to another context. - @return A copy of the AST which is associated with the other context. *) + @return A copy of the AST which is associated with the other context. *) val translate : ast -> context -> ast (** Unwraps an AST. - This function is used for transitions between native and - managed objects. It returns the native pointer to the AST. Note that - AST objects are reference counted and unwrapping an AST disables automatic - reference counting, i.e., all references to the IntPtr that is returned - must be handled externally and through native calls (see e.g., - [Z3native.inc_ref]). - {!wrap_ast} *) + This function is used for transitions between native and + managed objects. It returns the native pointer to the AST. Note that + AST objects are reference counted and unwrapping an AST disables automatic + reference counting, i.e., all references to the IntPtr that is returned + must be handled externally and through native calls (see e.g., + [Z3native.inc_ref]). + {!wrap_ast} *) val unwrap_ast : ast -> Z3native.ptr (** Wraps an AST. - This function is used for transitions between native and - managed objects. Note that the native ast that is passed must be a - native object obtained from Z3 (e.g., through {!unwrap_ast}) - and that it must have a correct reference count (see e.g., + This function is used for transitions between native and + managed objects. Note that the native ast that is passed must be a + native object obtained from Z3 (e.g., through {!unwrap_ast}) + and that it must have a correct reference count (see e.g., [Z3native.inc_ref]). *) val wrap_ast : context -> Z3native.z3_ast -> ast end @@ -267,8 +267,8 @@ sig val ast_of_sort : sort -> AST.ast (** Comparison operator. - @return True if the two sorts are from the same context - and represent the same sort; false otherwise. *) + @return True if the two sorts are from the same context + and represent the same sort; false otherwise. *) val equal : sort -> sort -> bool (** Returns a unique identifier for the sort. *) @@ -441,33 +441,26 @@ sig val to_string : params -> string (** Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - [z3.exe -p] - Only a few configuration parameters are mutable once the context is created. - An exception is thrown when trying to modify an immutable parameter. - {!get_param_value} *) + + The list of all configuration parameters can be obtained using the Z3 executable: + [z3.exe -p] + Only a few configuration parameters are mutable once the context is created. + An exception is thrown when trying to modify an immutable parameter. *) val update_param_value : context -> string -> string -> unit - - (** Get a configuration parameter. - - Returns None if the parameter value does not exist. - {!update_param_value} *) - val get_param_value : context -> string -> string option - + (** Selects the format used for pretty-printing expressions. - - The default mode for pretty printing expressions is to produce - SMT-LIB style output where common subexpressions are printed - at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, - use the PRINT_LOW_LEVEL mode. - To print in way that conforms to SMT-LIB standards and uses let - expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - {!AST.to_string} - {!Quantifier.Pattern.to_string} - {!FuncDecl.to_string} - {!Sort.to_string} *) + + The default mode for pretty printing expressions is to produce + SMT-LIB style output where common subexpressions are printed + at each occurrence. The mode is called PRINT_SMTLIB_FULL. + To print shared common subexpressions only once, + use the PRINT_LOW_LEVEL mode. + To print in way that conforms to SMT-LIB standards and uses let + expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. + {!AST.to_string} + {!Quantifier.Pattern.to_string} + {!FuncDecl.to_string} + {!Sort.to_string} *) val set_print_mode : context -> Z3enums.ast_print_mode -> unit end @@ -480,7 +473,7 @@ sig val expr_of_ast : AST.ast -> Expr.expr (** Returns a simplified version of the expression. - {!get_simplify_help} *) + {!get_simplify_help} *) val simplify : Expr.expr -> Params.params option -> expr (** A string describing all available parameters to [Expr.Simplify]. *) @@ -503,23 +496,23 @@ sig val update : Expr.expr -> Expr.expr list -> expr (** Substitute every occurrence of [from[i]] in the expression with [to[i]], for [i] smaller than [num_exprs]. - - The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. - For every [i] smaller than [num_exprs], we must have that - sort of [from[i]] must be equal to sort of [to[i]]. *) + + The result is the new expression. The arrays [from] and [to] must have size [num_exprs]. + For every [i] smaller than [num_exprs], we must have that + sort of [from[i]] must be equal to sort of [to[i]]. *) val substitute : Expr.expr -> Expr.expr list -> Expr.expr list -> expr (** Substitute every occurrence of [from] in the expression with [to]. - {!substitute} *) + {!substitute} *) val substitute_one : Expr.expr -> Expr.expr -> Expr.expr -> expr (** Substitute the free variables in the expression with the expressions in the expr array - For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) + For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term [to[i]]. *) val substitute_vars : Expr.expr -> Expr.expr list -> expr (** Translates (copies) the term to another context. - @return A copy of the term which is associated with the other context *) + @return A copy of the term which is associated with the other context *) val translate : Expr.expr -> context -> expr (** Returns a string representation of the expression. *) @@ -529,7 +522,7 @@ sig val is_numeral : Expr.expr -> bool (** Indicates whether the term is well-sorted. - @return True if the term is well-sorted, false otherwise. *) + @return True if the term is well-sorted, false otherwise. *) val is_well_sorted : Expr.expr -> bool (** The Sort of the term. *) @@ -537,26 +530,26 @@ sig (** Indicates whether the term represents a constant. *) val is_const : Expr.expr -> bool - + (** Creates a new constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> expr - + (** Creates a new constant. *) val mk_const_s : context -> string -> Sort.sort -> expr - + (** Creates a constant from the func_decl. *) val mk_const_f : context -> FuncDecl.func_decl -> expr - + (** Creates a fresh constant with a name prefixed with a string. *) val mk_fresh_const : context -> string -> Sort.sort -> expr - + (** Create a new function application. *) val mk_app : context -> FuncDecl.func_decl -> Expr.expr list -> expr - + (** Create a numeral of a given sort. - @return A Term with the given value and sort *) + @return A Term with the given value and sort *) val mk_numeral_string : context -> string -> Sort.sort -> expr - + (** Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer. It is slightly faster than [MakeNumeral] since it is not necessary to parse a string. @return A Term with the given value and sort *) @@ -692,21 +685,21 @@ sig (** The de-Burijn index of a bound variable. - - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain - the meaning of de-Bruijn indices by indicating the compilation process from - non-de-Bruijn formulas to de-Bruijn format. - - abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) - abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) - abs1(x, x, n) = b_n - abs1(y, x, n) = y - abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) - abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) - - The last line is significant: the index of a bound variable is different depending - on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its - index. *) + + Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain + the meaning of de-Bruijn indices by indicating the compilation process from + non-de-Bruijn formulas to de-Bruijn format. + + abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0) + abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi)) + abs1(x, x, n) = b_n + abs1(y, x, n) = y + abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n)) + abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1)) + + The last line is significant: the index of a bound variable is different depending + on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its + index. *) val get_index : Expr.expr -> int (** Indicates whether the quantifier is universal. *) @@ -723,19 +716,19 @@ sig (** The patterns. *) val get_patterns : quantifier -> Pattern.pattern list - - (** The number of no-patterns. *) + + (** The number of no-patterns. *) val get_num_no_patterns : quantifier -> int (** The no-patterns. *) val get_no_patterns : quantifier -> Pattern.pattern list - (** The number of bound variables. *) - val get_num_bound : quantifier -> int - - (** The symbols for the bound variables. *) + (** The number of bound variables. *) + val get_num_bound : quantifier -> int + + (** The symbols for the bound variables. *) val get_bound_variable_names : quantifier -> Symbol.symbol list - + (** The sorts of the bound variables. *) val get_bound_variable_sorts : quantifier -> Sort.sort list @@ -767,7 +760,7 @@ sig val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier (** A string representation of the quantifier. *) - val to_string : quantifier -> string + val to_string : quantifier -> string end (** Functions to manipulate Array expressions *) @@ -777,28 +770,28 @@ sig val mk_sort : context -> Sort.sort -> Sort.sort -> Sort.sort (** Indicates whether the term is an array store. - It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. *) + It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). + Array store takes at least 3 arguments. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an array select. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a constant array. - For example, select(const(v),i) = v holds for every v and i. The function is unary. *) + For example, select(const(v),i) = v holds for every v and i. The function is unary. *) val is_constant_array : Expr.expr -> bool (** Indicates whether the term is a default array. - For example default(const(v)) = v. The function is unary. *) + For example default(const(v)) = v. The function is unary. *) val is_default_array : Expr.expr -> bool (** Indicates whether the term is an array map. - It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) + It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. *) val is_array_map : Expr.expr -> bool (** Indicates whether the term is an as-array term. - An as-array term is n array value that behaves as the function graph of the - function passed as parameter. *) + An as-array term is n array value that behaves as the function graph of the + function passed as parameter. *) val is_as_array : Expr.expr -> bool (** Indicates whether the term is of an array sort. *) @@ -806,66 +799,66 @@ sig (** The domain of the array sort. *) val get_domain : Sort.sort -> Sort.sort - + (** The range of the array sort. *) val get_range : Sort.sort -> Sort.sort - + (** Create an array constant. *) val mk_const : context -> Symbol.symbol -> Sort.sort -> Sort.sort -> Expr.expr - + (** Create an array constant. *) val mk_const_s : context -> string -> Sort.sort -> Sort.sort -> Expr.expr - + (** Array read. - - The argument [a] is the array and [i] is the index - of the array that gets read. - - The node [a] must have an array sort [[domain -> range]], - and [i] must have the sort [domain]. - The sort of the result is [range]. - {!Z3Array.mk_sort} - {!mk_store} *) + + The argument [a] is the array and [i] is the index + of the array that gets read. + + The node [a] must have an array sort [[domain -> range]], + and [i] must have the sort [domain]. + The sort of the result is [range]. + {!Z3Array.mk_sort} + {!mk_store} *) val mk_select : context -> Expr.expr -> Expr.expr -> Expr.expr (** Array update. - - The node [a] must have an array sort [[domain -> range]], - [i] must have sort [domain], - [v] must have sort range. The sort of the result is [[domain -> range]]. - The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http://smtlib.org for more details. - The result of this function is an array that is equal to [a] - (with respect to [select]) - on all indices except for [i], where it maps to [v] - (and the [select] of [a] with - respect to [i] may be a different value). - {!Z3Array.mk_sort} - {!mk_select} *) + + The node [a] must have an array sort [[domain -> range]], + [i] must have sort [domain], + [v] must have sort range. The sort of the result is [[domain -> range]]. + The semantics of this function is given by the theory of arrays described in the SMT-LIB + standard. See http://smtlib.org for more details. + The result of this function is an array that is equal to [a] + (with respect to [select]) + on all indices except for [i], where it maps to [v] + (and the [select] of [a] with + respect to [i] may be a different value). + {!Z3Array.mk_sort} + {!mk_select} *) val mk_store : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr (** Create a constant array. - - The resulting term is an array, such that a [select]on an arbitrary index - produces the value [v]. - {!Z3Array.mk_sort} - {!mk_select} *) + + The resulting term is an array, such that a [select]on an arbitrary index + produces the value [v]. + {!Z3Array.mk_sort} + {!mk_select} *) val mk_const_array : context -> Sort.sort -> Expr.expr -> Expr.expr (** Maps f on the argument arrays. - - Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. - The function declaration [f] must have type [ range_1 .. range_n -> range]. - [v] must have sort range. The sort of the result is [[domain_i -> range]]. - {!Z3Array.mk_sort} - {!mk_select} - {!mk_store} *) + + Eeach element of [args] must be of an array sort [[domain_i -> range_i]]. + The function declaration [f] must have type [ range_1 .. range_n -> range]. + [v] must have sort range. The sort of the result is [[domain_i -> range]]. + {!Z3Array.mk_sort} + {!mk_select} + {!mk_store} *) val mk_map : context -> FuncDecl.func_decl -> Expr.expr list -> Expr.expr (** Access the array default value. - - Produces the default range value, for arrays that can be represented as - finite maps with a default range value. *) + + Produces the default range value, for arrays that can be represented as + finite maps with a default range value. *) val mk_term_array : context -> Expr.expr -> Expr.expr end @@ -948,10 +941,10 @@ sig val is_relation : Expr.expr -> bool (** Indicates whether the term is an relation store - - Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements - correspond to the [n] columns of the relation. *) + + Insert a record into a relation. + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + correspond to the [n] columns of the relation. *) val is_store : Expr.expr -> bool (** Indicates whether the term is an empty relation *) @@ -964,62 +957,62 @@ sig val is_join : Expr.expr -> bool (** Indicates whether the term is the union or convex hull of two relations. - The function takes two arguments. *) + The function takes two arguments. *) val is_union : Expr.expr -> bool (** Indicates whether the term is the widening of two relations - The function takes two arguments. *) + The function takes two arguments. *) val is_widen : Expr.expr -> bool (** Indicates whether the term is a projection of columns (provided as numbers in the parameters). - The function takes one argument. *) + The function takes one argument. *) val is_project : Expr.expr -> bool (** Indicates whether the term is a relation filter - - Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. - The second argument is a predicate with free de-Brujin indices - corresponding to the columns of the relation. - So the first column in the relation has index 0. *) + + Filter (restrict) a relation with respect to a predicate. + The first argument is a relation. + The second argument is a predicate with free de-Brujin indices + corresponding to the columns of the relation. + So the first column in the relation has index 0. *) val is_filter : Expr.expr -> bool (** Indicates whether the term is an intersection of a relation with the negation of another. - - Intersect the first relation with respect to negation - of the second relation (the function takes two arguments). - Logically, the specification can be described by a function - - target = filter_by_negation(pos, neg, columns) - - where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that - target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with - ( x : expr ) on the columns c1, d1, .., cN, dN. *) + + Intersect the first relation with respect to negation + of the second relation (the function takes two arguments). + Logically, the specification can be described by a function + + target = filter_by_negation(pos, neg, columns) + + where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that + target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with + ( x : expr ) on the columns c1, d1, .., cN, dN. *) val is_negation_filter : Expr.expr -> bool (** Indicates whether the term is the renaming of a column in a relation - - The function takes one argument. - The parameters contain the renaming as a cycle. *) + + The function takes one argument. + The parameters contain the renaming as a cycle. *) val is_rename : Expr.expr -> bool (** Indicates whether the term is the complement of a relation *) val is_complement : Expr.expr -> bool (** Indicates whether the term is a relational select - - Check if a record is an element of the relation. - The function takes [n+1] arguments, where the first argument is a relation, - and the remaining [n] arguments correspond to a record. *) + + Check if a record is an element of the relation. + The function takes [n+1] arguments, where the first argument is a relation, + and the remaining [n] arguments correspond to a record. *) val is_select : Expr.expr -> bool (** Indicates whether the term is a relational clone (copy) - - Create a fresh copy (clone) of a relation. - The function is logically the identity, but - in the context of a register machine allows - for terms of kind {!is_union} - to perform destructive updates to the first argument. *) + + Create a fresh copy (clone) of a relation. + The function is logically the identity, but + in the context of a register machine allows + for terms of kind {!is_union} + to perform destructive updates to the first argument. *) val is_clone : Expr.expr -> bool (** The arity of the relation sort. *) @@ -1039,25 +1032,25 @@ sig (** The number of fields of the constructor. *) val get_num_fields : constructor -> int - + (** The function declaration of the constructor. *) val get_constructor_decl : constructor -> FuncDecl.func_decl (** The function declaration of the tester. *) val get_tester_decl : constructor -> FuncDecl.func_decl - + (** The function declarations of the accessors *) val get_accessor_decls : constructor -> FuncDecl.func_decl list end (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor : context -> Symbol.symbol -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a datatype constructor. - if the corresponding sort reference is 0, then the value in sort_refs should be an index - referring to one of the recursive datatypes that is declared. *) + if the corresponding sort reference is 0, then the value in sort_refs should be an index + referring to one of the recursive datatypes that is declared. *) val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor (** Create a new datatype sort. *) @@ -1078,7 +1071,7 @@ sig (** The constructors. *) val get_constructors : Sort.sort -> FuncDecl.func_decl list - + (** The recognizers. *) val get_recognizers : Sort.sort -> FuncDecl.func_decl list @@ -1174,38 +1167,38 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create an expression representing [t1 mod t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing [t1 rem t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer numeral. *) val mk_numeral_s : context -> string -> Expr.expr (** Create an integer numeral. - @return A Term with the given value and sort Integer *) + @return A Term with the given value and sort Integer *) val mk_numeral_i : context -> int -> Expr.expr (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term [k] and - and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. - The argument must be of integer sort. *) + + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term [k] and + and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. + The argument must be of integer sort. *) val mk_int2real : context -> Expr.expr -> Expr.expr (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) + + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) val mk_int2bv : context -> int -> Expr.expr -> Expr.expr end @@ -1238,16 +1231,16 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) + @return A Term with rational value and sort Real + {!mk_numeral_s} *) val mk_numeral_nd : context -> int -> int -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_s : context -> string -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_i : context -> int -> Expr.expr (** Creates an expression that checks whether a real number is an integer. *) @@ -1255,8 +1248,8 @@ sig (** Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) val mk_real2int : context -> Expr.expr -> Expr.expr (** Algebraic Numbers *) @@ -1522,34 +1515,34 @@ sig val is_bv_rotateright : Expr.expr -> bool (** Indicates whether the term is a bit-vector rotate left (extended) - Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) + Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. *) val is_bv_rotateleftextended : Expr.expr -> bool (** Indicates whether the term is a bit-vector rotate right (extended) - Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) + Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) val is_bv_rotaterightextended : Expr.expr -> bool - + (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) (** Indicates whether the term is a coercion from bit-vector to integer - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_int_to_bv : Expr.expr -> bool (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) + This function is not supported by the decision procedures. Only the most + rudimentary simplification rules are applied to this function. *) val is_bv_to_int : Expr.expr -> bool (** Indicates whether the term is a bit-vector carry - Compute the carry bit in a full-adder. The meaning is given by the - equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) + Compute the carry bit in a full-adder. The meaning is given by the + equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3))) *) val is_bv_carry : Expr.expr -> bool - + (** Indicates whether the term is a bit-vector ternary XOR - The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) + The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) *) val is_bv_xor3 : Expr.expr -> bool (** The size of a bit-vector sort. *) @@ -1557,7 +1550,7 @@ sig (** Retrieve the int value. *) val get_int : Expr.expr -> int - + (** Returns a string representation of the numeral. *) val to_string : Expr.expr -> string @@ -1568,146 +1561,145 @@ sig val mk_const_s : context -> string -> int -> Expr.expr (** Bitwise negation. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_not : context -> Expr.expr -> Expr.expr (** Take conjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_redand : context -> Expr.expr -> Expr.expr (** Take disjunction of bits in a vector,vector of length 1. - The argument must have a bit-vector sort. *) + The argument must have a bit-vector sort. *) val mk_redor : context -> Expr.expr -> Expr.expr (** Bitwise conjunction. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_and : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise disjunction. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_or : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_xor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NAND. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_nand : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise NOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_nor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bitwise XNOR. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_xnor : context -> Expr.expr -> Expr.expr -> Expr.expr (** Standard two's complement unary minus. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_neg : context -> Expr.expr -> Expr.expr (** Two's complement addition. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement subtraction. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement multiplication. - The arguments must have the same bit-vector sort. *) + The arguments must have the same bit-vector sort. *) val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned division. - - - It is defined as the floor of [t1/t2] if \c t2 is - different from zero. If [t2] is zero, then the result - is undefined. - The arguments must have the same bit-vector sort. *) + + It is defined as the floor of [t1/t2] if \c t2 is + different from zero. If [t2] is zero, then the result + is undefined. + The arguments must have the same bit-vector sort. *) val mk_udiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed division. - - It is defined in the following way: + + It is defined in the following way: - - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. + - The \c floor of [t1/t2] if \c t2 is different from zero, and [t1*t2 >= 0]. - - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. + - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned remainder. - - It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + + It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Signed remainder. - - It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. - The most significant bit (sign) of the result is equal to the most significant bit of \c t1. + + It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. + The most significant bit (sign) of the result is equal to the most significant bit of \c t1. - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed remainder (sign follows divisor). - - If [t2] is zero, then the result is undefined. - The arguments must have the same bit-vector sort. *) + + If [t2] is zero, then the result is undefined. + The arguments must have the same bit-vector sort. *) val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ult : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed less-than - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_slt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned less-than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ule : context -> Expr.expr -> Expr.expr -> Expr.expr - + (** Two's complement signed less-than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sle : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_uge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater than or equal to. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sge : context -> Expr.expr -> Expr.expr -> Expr.expr (** Unsigned greater-than. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_ugt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Two's complement signed greater-than. - - The arguments must have the same bit-vector sort. *) + + The arguments must have the same bit-vector sort. *) val mk_sgt : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector concatenation. - - The arguments must have a bit-vector sort. - @return - The result is a bit-vector of size [n1+n2], where [n1] ([n2]) - is the size of [t1] ([t2]). *) + + The arguments must have a bit-vector sort. + @return + The result is a bit-vector of size [n1+n2], where [n1] ([n2]) + is the size of [t1] ([t2]). *) val mk_concat : context -> Expr.expr -> Expr.expr -> Expr.expr (** Bit-vector extraction. @@ -1719,17 +1711,17 @@ sig (** Bit-vector sign extension. - Sign-extends the given bit-vector to the (signed) equivalent bitvector of - size [m+i], where \c m is the size of the given bit-vector. *) + Sign-extends the given bit-vector to the (signed) equivalent bitvector of + size [m+i], where \c m is the size of the given bit-vector. *) val mk_sign_ext : context -> int -> Expr.expr -> Expr.expr (** Bit-vector zero extension. - Extend the given bit-vector with zeros to the (unsigned) equivalent - bitvector of size [m+i], where \c m is the size of the - given bit-vector. *) + Extend the given bit-vector with zeros to the (unsigned) equivalent + bitvector of size [m+i], where \c m is the size of the + given bit-vector. *) val mk_zero_ext : context -> int -> Expr.expr -> Expr.expr - + (** Bit-vector repetition. *) val mk_repeat : context -> int -> Expr.expr -> Expr.expr @@ -1743,27 +1735,27 @@ sig val mk_shl : context -> Expr.expr -> Expr.expr -> Expr.expr (** Logical shift right - - It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. + + It is equivalent to unsigned division by [2^x] where \c x is the value of the third argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_lshr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Arithmetic shift right - - It is like logical shift right except that the most significant - bits of the result always copy the most significant bit of the - second argument. + + It is like logical shift right except that the most significant + bits of the result always copy the most significant bit of the + second argument. - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the - programming language or assembly architecture you are modeling. + NB. The semantics of shift operations varies between environments. This + definition does not necessarily capture directly the semantics of the + programming language or assembly architecture you are modeling. - The arguments must have a bit-vector sort. *) + The arguments must have a bit-vector sort. *) val mk_ashr : context -> Expr.expr -> Expr.expr -> Expr.expr (** Rotate Left. @@ -1783,7 +1775,7 @@ sig val mk_ext_rotate_right : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer from the bit-vector argument - + If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. So the result is non-negative and in the range [[0..2^N-1]], where N are the number of bits in the argument. @@ -1795,45 +1787,45 @@ sig val mk_bv2int : context -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_add_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise addition does not underflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_add_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sub_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise subtraction does not underflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sub_no_underflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise signed division does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_sdiv_no_overflow : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise negation does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_neg_no_overflow : context -> Expr.expr -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not overflow. - - The arguments must be of bit-vector sort. *) + + The arguments must be of bit-vector sort. *) val mk_mul_no_overflow : context -> Expr.expr -> Expr.expr -> bool -> Expr.expr (** Create a predicate that checks that the bit-wise multiplication does not underflow. - - The arguments must be of bit-vector sort. *) - val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + The arguments must be of bit-vector sort. *) + val mk_mul_no_underflow : context -> Expr.expr -> Expr.expr -> Expr.expr + (** Create a bit-vector numeral. *) val mk_numeral : context -> string -> int -> Expr.expr end @@ -1851,389 +1843,389 @@ sig val is_goal : Expr.expr -> bool (** Indicates whether the term is a binary equivalence modulo namings. - This binary predicate is used in proof terms. - It captures equisatisfiability and equivalence modulo renamings. *) + This binary predicate is used in proof terms. + It captures equisatisfiability and equivalence modulo renamings. *) val is_oeq : Expr.expr -> bool (** Indicates whether the term is proof via modus ponens - - Given a proof for p and a proof for (implies p q), produces a proof for q. - T1: p - T2: (implies p q) - [mp T1 T2]: q - The second antecedents may also be a proof for (iff p q). *) + + Given a proof for p and a proof for (implies p q), produces a proof for q. + T1: p + T2: (implies p q) + [mp T1 T2]: q + The second antecedents may also be a proof for (iff p q). *) val is_modus_ponens : Expr.expr -> bool (** Indicates whether the term is a proof for (R t t), where R is a reflexive relation. - This proof object has no antecedents. - The only reflexive relations that are used are - equivalence modulo namings, equality and equivalence. - That is, R is either '~', '=' or 'iff'. *) + This proof object has no antecedents. + The only reflexive relations that are used are + equivalence modulo namings, equality and equivalence. + That is, R is either '~', '=' or 'iff'. *) val is_reflexivity : Expr.expr -> bool (** Indicates whether the term is proof by symmetricity of a relation - - Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). - T1: (R t s) - [symmetry T1]: (R s t) - T1 is the antecedent of this proof object. *) + + Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). + T1: (R t s) + [symmetry T1]: (R s t) + T1 is the antecedent of this proof object. *) val is_symmetry : Expr.expr -> bool (** Indicates whether the term is a proof by transitivity of a relation - - Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof - for (R t u). - T1: (R t s) - T2: (R s u) - [trans T1 T2]: (R t u) *) + + Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof + for (R t u). + T1: (R t s) + T2: (R s u) + [trans T1 T2]: (R t u) *) val is_transitivity : Expr.expr -> bool (** Indicates whether the term is a proof by condensed transitivity of a relation - - Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - Example: - T1: (R a b) - T2: (R c b) - T3: (R c d) - [trans* T1 T2 T3]: (R a d) - R must be a symmetric and transitive relation. - - Assuming that this proof object is a proof for (R s t), then - a proof checker must check if it is possible to prove (R s t) - using the antecedents, symmetry and transitivity. That is, - if there is a path from s to t, if we view every - antecedent (R a b) as an edge between a and b. *) + + Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. + It combines several symmetry and transitivity proofs. + Example: + T1: (R a b) + T2: (R c b) + T3: (R c d) + [trans* T1 T2 T3]: (R a d) + R must be a symmetric and transitive relation. + + Assuming that this proof object is a proof for (R s t), then + a proof checker must check if it is possible to prove (R s t) + using the antecedents, symmetry and transitivity. That is, + if there is a path from s to t, if we view every + antecedent (R a b) as an edge between a and b. *) val is_Transitivity_star : Expr.expr -> bool (** Indicates whether the term is a monotonicity proof object. - - T1: (R t_1 s_1) - ... - Tn: (R t_n s_n) - [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) - Remark: if t_i == s_i, then the antecedent Ti is suppressed. - That is, reflexivity proofs are supressed to save space. *) + + T1: (R t_1 s_1) + ... + Tn: (R t_n s_n) + [monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n)) + Remark: if t_i == s_i, then the antecedent Ti is suppressed. + That is, reflexivity proofs are supressed to save space. *) val is_monotonicity : Expr.expr -> bool (** Indicates whether the term is a quant-intro proof - - Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). - T1: (~ p q) - [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) + + Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)). + T1: (~ p q) + [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) *) val is_quant_intro : Expr.expr -> bool (** Indicates whether the term is a distributivity proof object. - - Given that f (= or) distributes over g (= and), produces a proof for - (= (f a (g c d)) - (g (f a c) (f a d))) - If f and g are associative, this proof also justifies the following equality: - (= (f (g a b) (g c d)) - (g (f a c) (f a d) (f b c) (f b d))) - where each f and g can have arbitrary number of arguments. - - This proof object has no antecedents. - Remark. This rule is used by the CNF conversion pass and - instantiated by f = or, and g = and. *) + + Given that f (= or) distributes over g (= and), produces a proof for + (= (f a (g c d)) + (g (f a c) (f a d))) + If f and g are associative, this proof also justifies the following equality: + (= (f (g a b) (g c d)) + (g (f a c) (f a d) (f b c) (f b d))) + where each f and g can have arbitrary number of arguments. + + This proof object has no antecedents. + Remark. This rule is used by the CNF conversion pass and + instantiated by f = or, and g = and. *) val is_distributivity : Expr.expr -> bool (** Indicates whether the term is a proof by elimination of AND - - Given a proof for (and l_1 ... l_n), produces a proof for l_i - T1: (and l_1 ... l_n) - [and-elim T1]: l_i *) + + Given a proof for (and l_1 ... l_n), produces a proof for l_i + T1: (and l_1 ... l_n) + [and-elim T1]: l_i *) val is_and_elimination : Expr.expr -> bool (** Indicates whether the term is a proof by eliminiation of not-or - - Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - T1: (not (or l_1 ... l_n)) - [not-or-elim T1]: (not l_i) *) + + Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). + T1: (not (or l_1 ... l_n)) + [not-or-elim T1]: (not l_i) *) val is_or_elimination : Expr.expr -> bool (** Indicates whether the term is a proof by rewriting - - A proof for a local rewriting step (= t s). - The head function symbol of t is interpreted. - - This proof object has no antecedents. - The conclusion of a rewrite rule is either an equality (= t s), - an equivalence (iff t s), or equi-satisfiability (~ t s). - Remark: if f is bool, then = is iff. - - Examples: - (= (+ ( x : expr ) 0) x) - (= (+ ( x : expr ) 1 2) (+ 3 x)) - (iff (or ( x : expr ) false) x) *) + + A proof for a local rewriting step (= t s). + The head function symbol of t is interpreted. + + This proof object has no antecedents. + The conclusion of a rewrite rule is either an equality (= t s), + an equivalence (iff t s), or equi-satisfiability (~ t s). + Remark: if f is bool, then = is iff. + + Examples: + (= (+ ( x : expr ) 0) x) + (= (+ ( x : expr ) 1 2) (+ 3 x)) + (iff (or ( x : expr ) false) x) *) val is_rewrite : Expr.expr -> bool (** Indicates whether the term is a proof by rewriting - - A proof for rewriting an expression t into an expression s. - This proof object is used if the parameter PROOF_MODE is 1. - This proof object can have n antecedents. - The antecedents are proofs for equalities used as substitution rules. - The object is also used in a few cases if the parameter PROOF_MODE is 2. - The cases are: - - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) - - When converting bit-vectors to Booleans (BIT2BOOL=true) - - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) + + A proof for rewriting an expression t into an expression s. + This proof object is used if the parameter PROOF_MODE is 1. + This proof object can have n antecedents. + The antecedents are proofs for equalities used as substitution rules. + The object is also used in a few cases if the parameter PROOF_MODE is 2. + The cases are: + - When applying contextual simplification (CONTEXT_SIMPLIFIER=true) + - When converting bit-vectors to Booleans (BIT2BOOL=true) + - When pulling ite expression up (PULL_CHEAP_ITE_TREES=true) *) val is_rewrite_star : Expr.expr -> bool (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) + + A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. *) val is_pull_quant : Expr.expr -> bool (** Indicates whether the term is a proof for pulling quantifiers out. - - A proof for (iff P Q) where Q is in prenex normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object has no antecedents *) + + A proof for (iff P Q) where Q is in prenex normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object has no antecedents *) val is_pull_quant_star : Expr.expr -> bool (** Indicates whether the term is a proof for pushing quantifiers in. - - A proof for: - (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) - (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) - ... - (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) - This proof object has no antecedents *) + + A proof for: + (iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m])) + (and (forall (x_1 ... x_m) p_1[x_1 ... x_m]) + ... + (forall (x_1 ... x_m) p_n[x_1 ... x_m]))) + This proof object has no antecedents *) val is_push_quant : Expr.expr -> bool (** Indicates whether the term is a proof for elimination of unused variables. - - A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) - (forall (x_1 ... x_n) p[x_1 ... x_n])) - - It is used to justify the elimination of unused variables. - This proof object has no antecedents. *) + + A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n]) + (forall (x_1 ... x_n) p[x_1 ... x_n])) + + It is used to justify the elimination of unused variables. + This proof object has no antecedents. *) val is_elim_unused_vars : Expr.expr -> bool (** Indicates whether the term is a proof for destructive equality resolution - - A proof for destructive equality resolution: - (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) - if ( x : expr ) does not occur in t. - - This proof object has no antecedents. - - Several variables can be eliminated simultaneously. *) + + A proof for destructive equality resolution: + (iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t]) + if ( x : expr ) does not occur in t. + + This proof object has no antecedents. + + Several variables can be eliminated simultaneously. *) val is_der : Expr.expr -> bool - + (** Indicates whether the term is a proof for quantifier instantiation - - A proof of (or (not (forall (x) (P x))) (P a)) *) + + A proof of (or (not (forall (x) (P x))) (P a)) *) val is_quant_inst : Expr.expr -> bool (** Indicates whether the term is a hypthesis marker. - Mark a hypothesis in a natural deduction style proof. *) + Mark a hypothesis in a natural deduction style proof. *) val is_hypothesis : Expr.expr -> bool (** Indicates whether the term is a proof by lemma - - T1: false - [lemma T1]: (or (not l_1) ... (not l_n)) - - This proof object has one antecedent: a hypothetical proof for false. - It converts the proof in a proof for (or (not l_1) ... (not l_n)), - when T1 contains the hypotheses: l_1, ..., l_n. *) + + T1: false + [lemma T1]: (or (not l_1) ... (not l_n)) + + This proof object has one antecedent: a hypothetical proof for false. + It converts the proof in a proof for (or (not l_1) ... (not l_n)), + when T1 contains the hypotheses: l_1, ..., l_n. *) val is_lemma : Expr.expr -> bool (** Indicates whether the term is a proof by unit resolution - - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) - ... - T(n+1): (not l_n) - [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) + + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) + ... + T(n+1): (not l_n) + [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') *) val is_unit_resolution : Expr.expr -> bool (** Indicates whether the term is a proof by iff-true - - T1: p - [iff-true T1]: (iff p true) *) + + T1: p + [iff-true T1]: (iff p true) *) val is_iff_true : Expr.expr -> bool (** Indicates whether the term is a proof by iff-false - - T1: (not p) - [iff-false T1]: (iff p false) *) + + T1: (not p) + [iff-false T1]: (iff p false) *) val is_iff_false : Expr.expr -> bool (** Indicates whether the term is a proof by commutativity - - [comm]: (= (f a b) (f b a)) - - f is a commutative operator. - - This proof object has no antecedents. - Remark: if f is bool, then = is iff. *) + + [comm]: (= (f a b) (f b a)) + + f is a commutative operator. + + This proof object has no antecedents. + Remark: if f is bool, then = is iff. *) val is_commutativity : Expr.expr -> bool (** Indicates whether the term is a proof for Tseitin-like axioms - - Proof object used to justify Tseitin's like axioms: - - (or (not (and p q)) p) - (or (not (and p q)) q) - (or (not (and p q r)) p) - (or (not (and p q r)) q) - (or (not (and p q r)) r) - ... - (or (and p q) (not p) (not q)) - (or (not (or p q)) p q) - (or (or p q) (not p)) - (or (or p q) (not q)) - (or (not (iff p q)) (not p) q) - (or (not (iff p q)) p (not q)) - (or (iff p q) (not p) (not q)) - (or (iff p q) p q) - (or (not (ite a b c)) (not a) b) - (or (not (ite a b c)) a c) - (or (ite a b c) (not a) (not b)) - (or (ite a b c) a (not c)) - (or (not (not a)) (not a)) - (or (not a) a) - - This proof object has no antecedents. - Note: all axioms are propositional tautologies. - Note also that 'and' and 'or' can take multiple arguments. - You can recover the propositional tautologies by - unfolding the Boolean connectives in the axioms a small - bounded number of steps (=3). *) + + Proof object used to justify Tseitin's like axioms: + + (or (not (and p q)) p) + (or (not (and p q)) q) + (or (not (and p q r)) p) + (or (not (and p q r)) q) + (or (not (and p q r)) r) + ... + (or (and p q) (not p) (not q)) + (or (not (or p q)) p q) + (or (or p q) (not p)) + (or (or p q) (not q)) + (or (not (iff p q)) (not p) q) + (or (not (iff p q)) p (not q)) + (or (iff p q) (not p) (not q)) + (or (iff p q) p q) + (or (not (ite a b c)) (not a) b) + (or (not (ite a b c)) a c) + (or (ite a b c) (not a) (not b)) + (or (ite a b c) a (not c)) + (or (not (not a)) (not a)) + (or (not a) a) + + This proof object has no antecedents. + Note: all axioms are propositional tautologies. + Note also that 'and' and 'or' can take multiple arguments. + You can recover the propositional tautologies by + unfolding the Boolean connectives in the axioms a small + bounded number of steps (=3). *) val is_def_axiom : Expr.expr -> bool (** Indicates whether the term is a proof for introduction of a name - - Introduces a name for a formula/term. - Suppose e is an expression with free variables x, and def-intro - introduces the name n(x). The possible cases are: - - When e is of Boolean type: - [def-intro]: (and (or n (not e)) (or (not n) e)) - - or: - [def-intro]: (or (not n) e) - when e only occurs positively. - - When e is of the form (ite cond th el): - [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) - - Otherwise: - [def-intro]: (= n e) *) + + Introduces a name for a formula/term. + Suppose e is an expression with free variables x, and def-intro + introduces the name n(x). The possible cases are: + + When e is of Boolean type: + [def-intro]: (and (or n (not e)) (or (not n) e)) + + or: + [def-intro]: (or (not n) e) + when e only occurs positively. + + When e is of the form (ite cond th el): + [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) + + Otherwise: + [def-intro]: (= n e) *) val is_def_intro : Expr.expr -> bool (** Indicates whether the term is a proof for application of a definition - - [apply-def T1]: F ~ n - F is 'equivalent' to n, given that T1 is a proof that - n is a name for F. *) + + [apply-def T1]: F ~ n + F is 'equivalent' to n, given that T1 is a proof that + n is a name for F. *) val is_apply_def : Expr.expr -> bool (** Indicates whether the term is a proof iff-oeq - - T1: (iff p q) - [iff~ T1]: (~ p q) *) + + T1: (iff p q) + [iff~ T1]: (~ p q) *) val is_iff_oeq : Expr.expr -> bool (** Indicates whether the term is a proof for a positive NNF step - - Proof for a (positive) NNF step. Example: - - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) - (and (or r_1 r_2') (or r_1' r_2))) - - The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: - (a) When creating the NNF of a positive force quantifier. - The quantifier is retained (unless the bound variables are eliminated). - Example - T1: q ~ q_new - [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) - - (b) When recursively creating NNF over Boolean formulas, where the top-level - connective is changed during NNF conversion. The relevant Boolean connectives - for NNF_POS are 'implies', 'iff', 'xor', 'ite'. - NNF_NEG furthermore handles the case where negation is pushed - over Boolean connectives 'and' and 'or'. *) + + Proof for a (positive) NNF step. Example: + + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2) + (and (or r_1 r_2') (or r_1' r_2))) + + The negation normal form steps NNF_POS and NNF_NEG are used in the following cases: + (a) When creating the NNF of a positive force quantifier. + The quantifier is retained (unless the bound variables are eliminated). + Example + T1: q ~ q_new + [nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new)) + + (b) When recursively creating NNF over Boolean formulas, where the top-level + connective is changed during NNF conversion. The relevant Boolean connectives + for NNF_POS are 'implies', 'iff', 'xor', 'ite'. + NNF_NEG furthermore handles the case where negation is pushed + over Boolean connectives 'and' and 'or'. *) val is_nnf_pos : Expr.expr -> bool (** Indicates whether the term is a proof for a negative NNF step - - Proof for a (negative) NNF step. Examples: - - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - ... - Tn: (not s_n) ~ r_n - [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) - and - T1: (not s_1) ~ r_1 - T2: (not s_2) ~ r_2 - T3: s_1 ~ r_1' - T4: s_2 ~ r_2' - [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) - (and (or r_1 r_2) (or r_1' r_2'))) *) + + Proof for a (negative) NNF step. Examples: + + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + ... + Tn: (not s_n) ~ r_n + [nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n) + and + T1: (not s_1) ~ r_1 + T2: (not s_2) ~ r_2 + T3: s_1 ~ r_1' + T4: s_2 ~ r_2' + [nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2)) + (and (or r_1 r_2) (or r_1' r_2'))) *) val is_nnf_neg : Expr.expr -> bool (** Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form. - - A proof for (~ P Q) where Q is in negation normal form. - - This proof object is only used if the parameter PROOF_MODE is 1. - - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + + A proof for (~ P Q) where Q is in negation normal form. + + This proof object is only used if the parameter PROOF_MODE is 1. + + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_nnf_star : Expr.expr -> bool (** Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form. - - A proof for (~ P Q) where Q is in conjunctive normal form. - This proof object is only used if the parameter PROOF_MODE is 1. - This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) + + A proof for (~ P Q) where Q is in conjunctive normal form. + This proof object is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. *) val is_cnf_star : Expr.expr -> bool (** Indicates whether the term is a proof for a Skolemization step - - Proof for: - - [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) - [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) - - This proof object has no antecedents. *) + + Proof for: + + [sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y))) + [sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y)) + + This proof object has no antecedents. *) val is_skolemize : Expr.expr -> bool (** Indicates whether the term is a proof by modus ponens for equi-satisfiability. - - Modus ponens style rule for equi-satisfiability. - T1: p - T2: (~ p q) - [mp~ T1 T2]: q *) + + Modus ponens style rule for equi-satisfiability. + T1: p + T2: (~ p q) + [mp~ T1 T2]: q *) val is_modus_ponens_oeq : Expr.expr -> bool (** Indicates whether the term is a proof for theory lemma - - Generic proof for theory lemmas. - - The theory lemma function comes with one or more parameters. - The first parameter indicates the name of the theory. - For the theory of arithmetic, additional parameters provide hints for - checking the theory lemma. - The hints for arithmetic are: - - farkas - followed by rational coefficients. Multiply the coefficients to the - inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. - - triangle-eq - Indicates a lemma related to the equivalence: - (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) - - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) + + Generic proof for theory lemmas. + + The theory lemma function comes with one or more parameters. + The first parameter indicates the name of the theory. + For the theory of arithmetic, additional parameters provide hints for + checking the theory lemma. + The hints for arithmetic are: + - farkas - followed by rational coefficients. Multiply the coefficients to the + inequalities in the lemma, add the (negated) inequalities and obtain a contradiction. + - triangle-eq - Indicates a lemma related to the equivalence: + (iff (= t1 t2) (and (<= t1 t2) (<= t2 t1))) + - gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test. *) val is_theory_lemma : Expr.expr -> bool end @@ -2265,12 +2257,12 @@ sig (** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *) val is_garbage : goal -> bool - (** Adds the constraints to the given goal. *) + (** Adds the constraints to the given goal. *) val add : goal -> Expr.expr list -> unit - + (** Indicates whether the goal contains `false'. *) val is_inconsistent : goal -> bool - + (** The depth of the goal. This tracks how many transformations were applied to it. *) val get_depth : goal -> int @@ -2300,7 +2292,7 @@ sig val simplify : goal -> Params.params option -> goal (** Creates a new Goal. - + Note that the Context must have been created with proof generation support if the fourth argument is set to true here. *) val mk_goal : context -> bool -> bool -> bool -> goal @@ -2323,7 +2315,7 @@ sig module FuncInterp : sig type func_interp - + (** Function interpretations entries An Entry object represents an element in the finite map used to a function interpretation. *) @@ -2418,7 +2410,7 @@ sig {!get_sorts} @return A list of expressions, where each is an element of the universe of the sort *) val sort_universe : model -> Sort.sort -> AST.ast list - + (** Conversion of models to strings. @return A string representation of the model. *) val to_string : model -> string @@ -2437,8 +2429,8 @@ sig type probe (** Execute the probe over the goal. - @return A probe always produce a float value. - "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) + @return A probe always produce a float value. + "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. *) val apply : probe -> Goal.goal -> float (** The number of supported Probes. *) @@ -2546,21 +2538,21 @@ sig val mk_tactic : context -> string -> tactic (** Create a tactic that applies one tactic to a Goal and - then another one to every subgoal produced by the first one. *) + then another one to every subgoal produced by the first one. *) val and_then : context -> tactic -> tactic -> tactic list -> tactic (** Create a tactic that first applies one tactic to a Goal and - if it fails then returns the result of another tactic applied to the Goal. *) + if it fails then returns the result of another tactic applied to the Goal. *) val or_else : context -> tactic -> tactic -> tactic (** Create a tactic that applies one tactic to a goal for some time (in milliseconds). - - If the tactic does not terminate within the timeout, then it fails. *) + + If the tactic does not terminate within the timeout, then it fails. *) val try_for : context -> tactic -> int -> tactic (** Create a tactic that applies one tactic to a given goal if the probe evaluates to true. - + If the probe evaluates to false, then the new tactic behaves like the [skip] tactic. *) val when_ : context -> Probe.probe -> tactic -> tactic @@ -2569,7 +2561,7 @@ sig val cond : context -> Probe.probe -> tactic -> tactic -> tactic (** Create a tactic that keeps applying one tactic until the goal is not - modified anymore or the maximum number of iterations is reached. *) + modified anymore or the maximum number of iterations is reached. *) val repeat : context -> tactic -> int -> tactic (** Create a tactic that just returns the given goal. *) @@ -2582,14 +2574,14 @@ sig val fail_if : context -> Probe.probe -> tactic (** Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty) - or trivially unsatisfiable (i.e., contains `false'). *) + or trivially unsatisfiable (i.e., contains `false'). *) val fail_if_not_decided : context -> tactic (** Create a tactic that applies a tactic using the given set of parameters. *) val using_params : context -> tactic -> Params.params -> tactic (** Create a tactic that applies a tactic using the given set of parameters. - Alias for [UsingParams]*) + Alias for [UsingParams]*) val with_ : context -> tactic -> Params.params -> tactic (** Create a tactic that applies the given tactics in parallel. *) @@ -2600,7 +2592,7 @@ sig val par_and_then : context -> tactic -> tactic -> tactic (** Interrupt the execution of a Z3 procedure. - This procedure can be used to interrupt: solvers, simplifiers and tactics. *) + This procedure can be used to interrupt: solvers, simplifiers and tactics. *) val interrupt : context -> unit end @@ -2618,8 +2610,8 @@ sig type statistics (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. - *) + Entry is either a floating point or integer value. + *) module Entry : sig type statistics_entry @@ -2641,7 +2633,7 @@ sig (** The string representation of the the entry's value. *) val to_string_value : statistics_entry -> string - + (** The string representation of the entry (key and value) *) val to_string : statistics_entry -> string end @@ -2672,49 +2664,49 @@ sig val get_param_descrs : solver -> Params.ParamDescrs.param_descrs (** The current number of backtracking points (scopes). - {!pop} - {!push} *) + {!pop} + {!push} *) val get_num_scopes : solver -> int (** Creates a backtracking point. - {!pop} *) + {!pop} *) val push : solver -> unit (** Backtracks a number of backtracking points. - Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} - {!push} *) + Note that an exception is thrown if the integer is not smaller than {!get_num_scopes} + {!push} *) val pop : solver -> int -> unit (** Resets the Solver. - This removes all assertions from the solver. *) + This removes all assertions from the solver. *) val reset : solver -> unit (** Assert a constraint (or multiple) into the solver. *) val add : solver -> Expr.expr list -> unit (** * Assert multiple constraints (cs) into the solver, and track them (in the - * unsat) core - * using the Boolean constants in ps. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) + * unsat) core + * using the Boolean constants in ps. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) val assert_and_track_l : solver -> Expr.expr list -> Expr.expr list -> unit (** * Assert a constraint (c) into the solver, and track it (in the unsat) core - * using the Boolean constant p. - * - * This API is an alternative to {!check} with assumptions for - * extracting unsat cores. - * Both APIs can be used in the same solver. The unsat core will contain a - * combination - * of the Boolean variables provided using {!assert_and_track} - * and the Boolean literals - * provided using {!check} with assumptions. *) + * using the Boolean constant p. + * + * This API is an alternative to {!check} with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using {!assert_and_track} + * and the Boolean literals + * provided using {!check} with assumptions. *) val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit (** The number of assertions in the solver. *) @@ -2724,29 +2716,29 @@ sig val get_assertions : solver -> Expr.expr list (** Checks whether the assertions in the solver are consistent or not. - - {!Model} - {!get_unsat_core} - {!Proof} *) + + {!Model} + {!get_unsat_core} + {!Proof} *) val check : solver -> Expr.expr list -> status (** The model of the last [Check]. - - The result is [None] if [Check] was not invoked before, - if its results was not [SATISFIABLE], or if model production is not enabled. *) + + The result is [None] if [Check] was not invoked before, + if its results was not [SATISFIABLE], or if model production is not enabled. *) val get_model : solver -> Model.model option (** The proof of the last [Check]. - - The result is [null] if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if proof production is disabled. *) + + The result is [null] if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if proof production is disabled. *) val get_proof : solver -> Expr.expr option (** The unsat core of the last [Check]. - - The unsat core is a subset of [Assertions] - The result is empty if [Check] was not invoked before, - if its results was not [UNSATISFIABLE], or if core production is disabled. *) + + The unsat core is a subset of [Assertions] + The result is empty if [Check] was not invoked before, + if its results was not [UNSATISFIABLE], or if core production is disabled. *) val get_unsat_core : solver -> AST.ast list (** A brief justification of why the last call to [Check] returned [UNKNOWN]. *) @@ -2756,23 +2748,23 @@ sig val get_statistics : solver -> Statistics.statistics (** Creates a new (incremental) solver. - - This solver also uses a set of builtin tactics for handling the first - check-sat command, and check-sat commands that take more than a given - number of milliseconds to be solved. *) + + This solver also uses a set of builtin tactics for handling the first + check-sat command, and check-sat commands that take more than a given + number of milliseconds to be solved. *) val mk_solver : context -> Symbol.symbol option -> solver (** Creates a new (incremental) solver. - {!mk_solver} *) + {!mk_solver} *) val mk_solver_s : context -> string -> solver (** Creates a new (incremental) solver. *) val mk_simple_solver : context -> solver (** Creates a solver that is implemented using the given tactic. - - The solver supports the commands [Push] and [Pop], but it - will always solve each check from scratch. *) + + The solver supports the commands [Push] and [Pop], but it + will always solve each check from scratch. *) val mk_solver_t : context -> Tactic.tactic -> solver (** A string representation of the solver. *) @@ -2806,32 +2798,32 @@ sig val add_fact : fixedpoint -> FuncDecl.func_decl -> int list -> unit (** Query the fixedpoint solver. - A query is a conjunction of constraints. The constraints may include the recursively defined relations. - The query is satisfiable if there is an instance of the query variables and a derivation for it. - The query is unsatisfiable if there are no derivations satisfying the query variables. *) + A query is a conjunction of constraints. The constraints may include the recursively defined relations. + The query is satisfiable if there is an instance of the query variables and a derivation for it. + The query is unsatisfiable if there are no derivations satisfying the query variables. *) val query : fixedpoint -> Expr.expr -> Solver.status (** Query the fixedpoint solver. - A query is an array of relations. - The query is satisfiable if there is an instance of some relation that is non-empty. - The query is unsatisfiable if there are no derivations satisfying any of the relations. *) + A query is an array of relations. + The query is satisfiable if there is an instance of some relation that is non-empty. + The query is unsatisfiable if there are no derivations satisfying any of the relations. *) val query_r : fixedpoint -> FuncDecl.func_decl list -> Solver.status (** Creates a backtracking point. - {!pop} *) + {!pop} *) val push : fixedpoint -> unit (** Backtrack one backtracking point. - Note that an exception is thrown if Pop is called without a corresponding [Push] - {!push} *) + Note that an exception is thrown if Pop is called without a corresponding [Push] + {!push} *) val pop : fixedpoint -> unit (** Update named rule into in the fixedpoint solver. *) val update_rule : fixedpoint -> Expr.expr -> Symbol.symbol -> unit (** Retrieve satisfying instance or instances of solver, - or definitions for the recursive predicates that show unsatisfiability. *) + or definitions for the recursive predicates that show unsatisfiability. *) val get_answer : fixedpoint -> Expr.expr option (** Retrieve explanation why fixedpoint engine returned status Unknown. *) @@ -2844,7 +2836,7 @@ sig val get_cover_delta : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr option (** Add property about the predicate. - The property is added at level. *) + The property is added at level. *) val add_cover : fixedpoint -> int -> FuncDecl.func_decl -> Expr.expr -> unit (** Retrieve internal string representation of fixedpoint object. *) @@ -2871,7 +2863,7 @@ module SMT : sig (** Convert a benchmark into an SMT-LIB formatted string. - @return A string representation of the benchmark. *) + @return A string representation of the benchmark. *) val benchmark_to_smtstring : context -> string -> string -> string -> string -> Expr.expr list -> Expr.expr -> string (** Parse the given string using the SMT-LIB parser. @@ -2884,7 +2876,7 @@ sig val parse_smtlib_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** Parse the given file using the SMT-LIB parser. - {!parse_smtlib_string} *) + {!parse_smtlib_string} *) val parse_smtlib_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> unit (** The number of SMTLIB formulas parsed by the last call to [ParseSMTLIBString] or [ParseSMTLIBFile]. *) @@ -2913,15 +2905,61 @@ sig (** Parse the given string using the SMT-LIB2 parser. - {!parse_smtlib_string} - @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) + {!parse_smtlib_string} + @return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *) val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr (** Parse the given file using the SMT-LIB2 parser. - {!parse_smtlib2_string} *) + {!parse_smtlib2_string} *) val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr end +(** Interpolation *) +module Interpolation : +sig + + (** Create an AST node marking a formula position for interpolation. + The expression must have Boolean sort. *) + val mk_interpolant : context -> Expr.expr -> Expr.expr + + (** The interpolation context is suitable for generation of interpolants. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val mk_interpolation_context : (string * string) list -> context + + (** Gets an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val get_interpolant : context -> Expr.expr -> Expr.expr -> Params.params -> AST.ASTVector.ast_vector + + (** Computes an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val compute_interpolant : context -> Expr.expr -> Params.params -> (AST.ASTVector.ast_vector * Model.model) + + (** Retrieves an interpolation profile. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val get_interpolation_profile : context -> string + + (** Read an interpolation problem from file. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val read_interpolation_problem : context -> string -> (Expr.expr list * int list * Expr.expr list) + + (** Check the correctness of an interpolant. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val check_interpolant : context -> int -> Expr.expr list -> int list -> Expr.expr list -> int -> Expr.expr list -> unit + + (** Write an interpolation problem to file suitable for reading with + Z3_read_interpolation_problem. + For more information on interpolation please refer + too the C/C++ API, which is well documented. *) + val write_interpolation_problem : context -> int -> Expr.expr list -> int list -> string -> int -> Expr.expr list -> unit + +end + (** Set a global (or module) parameter, which is shared by all Z3 contexts. When a Z3 module is initialized it will use the value of these parameters @@ -2939,9 +2977,9 @@ end val set_global_param : string -> string -> unit (** Get a global (or module) parameter. - + Returns None if the parameter does not exist. - The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + The caller must invoke #Z3_global_param_del_value to delete the value returned at param_value. This function cannot be invoked simultaneously from different threads without synchronization. The result string stored in param_value is stored in a shared location. *) From 5092ceec7d04476e668d26690a54a38c8f246111 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 20:21:30 +0000 Subject: [PATCH 471/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index bf1f5e471..ad60fa1e1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1379,6 +1379,10 @@ class MLComponent(Component): out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) + for f in filter(lambda f: f=='META', os.listdir(self.src_dir)): + out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) + str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) + out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: @@ -1421,7 +1425,7 @@ class MLComponent(Component): # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs\n') + out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/META\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) for m in modules: From b85c3e12f4fbf2b3f16531972577b07acaae1d51 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 20:31:16 +0000 Subject: [PATCH 472/646] ML API build fix --- scripts/mk_util.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ad60fa1e1..d42e6af29 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1379,10 +1379,6 @@ class MLComponent(Component): out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) - for f in filter(lambda f: f=='META', os.listdir(self.src_dir)): - out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) - str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) - out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! prev = '' for m in modules: From 93d74129508b159aeeeb687fb9780257df44ced4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 22:00:58 +0000 Subject: [PATCH 473/646] ML API build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d42e6af29..b1b3445ec 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1392,9 +1392,14 @@ class MLComponent(Component): out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('api/ml/z3native_stubs$(OBJ_EXT): %s/z3native_stubs.c\n' % (sub_dir)); out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') + out.write('api/ml/libz3mldyn$(SO_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) for mlfile in get_ml_files(self.src_dir): out.write(' %s' % os.path.join(sub_dir, mlfile)) From 40c6be0baa6010a628408d5959ee385d4fa11d66 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 13:45:49 +0000 Subject: [PATCH 474/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 98 ++++++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b1b3445ec..5e412c892 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1384,58 +1384,80 @@ class MLComponent(Component): for m in modules: fn = os.path.join(self.src_dir, ('%s.mli' % m)) if not os.path.exists(fn): - out.write('%s.mli: %s.ml %s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = '' for m in modules: - out.write('%s.cmi: %s.mli\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m))) + out.write('%s.cmi: %s.mli%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m), cmis)) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - out.write('api/ml/z3native_stubs$(OBJ_EXT): %s/z3native_stubs.c\n' % (sub_dir)); - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') - out.write('api/ml/libz3mldyn$(SO_EXT): api/ml/z3native_stubs.c %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s/z3native_stubs.c $(CXX_OUT_FLAG)api/ml/z3native_stubs$(OBJ_EXT)\n' % (OCAML_LIB, api_src, sub_dir)) - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + + out.write('%s: %s %s\n' % + (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), + os.path.join(sub_dir, 'z3native_stubs.c'), + get_component(Z3_DLL_COMPONENT).dll_name+'$(SO_EXT)')); + out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % + (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) - out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLOPT)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('\t%s ' % (OCAMLOPT)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLC)) - if DEBUG_MODE: - out.write('-g ') - out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - out.write('ml: %s %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) - out.write('\n') + # out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + # out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') + + # out.write('api/ml/libz3ml$(SO_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) + # out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) + + + # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + + # for mlfile in get_ml_files(self.src_dir): + # out.write(' %s' % os.path.join(sub_dir, mlfile)) + # out.write('\n') + # out.write('\t%s ' % (OCAMLOPT)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + + # out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + # out.write('\t%s ' % (OCAMLOPT)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) + # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + # for mlfile in get_ml_files(self.src_dir): + # out.write(' %s' % os.path.join(sub_dir, mlfile)) + # out.write('\n') + # out.write('\t%s ' % (OCAMLC)) + # if DEBUG_MODE: + # out.write('-g ') + # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + + out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) + for m in modules: + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write('%s/z3native_stubs.o\n' % (sub_dir)) + out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) + for m in modules: + out.write(' ' + m) + out.write('z3native_stubs$(OBJ_EXT) ; cd -' ) + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) + #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('ocamlfind_install: api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/META\n') + out.write('\nocamlfind_install: api/ml/z3.cmxa api/ml/META\n') out.write('\t%s remove Z3\n' % (OCAMLFIND)) - out.write('\t%s install Z3 api/ml/META api/ml/z3.cma api/ml/z3.cmxa api/ml/z3.cmxs api/ml/z3$(LIB_EXT) api/ml/libz3ml$(LIB_EXT) libz3$(SO_EXT)' % (OCAMLFIND)) + out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: + out.write(' %s.cma' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxx' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - if IS_WINDOWS: - out.write(' libz3$(LIB_EXT)') - out.write('\n') - out.write('\n') + out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3$(SO_EXT)')))) + out.write('\n\n') def main_component(self): From 2ee4409962405dbef86874398ad4197332b5cd73 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 13:51:17 +0000 Subject: [PATCH 475/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5e412c892..bd60feaa8 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1440,8 +1440,9 @@ class MLComponent(Component): out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: out.write(' ' + m) - out.write('z3native_stubs$(OBJ_EXT) ; cd -' ) - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) + out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) + # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) From ceabafa01cdbb66c6b6c465fd62e5c8c6f87d774 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:11:19 +0000 Subject: [PATCH 476/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index bd60feaa8..38cbb32f5 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1434,8 +1434,8 @@ class MLComponent(Component): out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) for m in modules: out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) out.write('%s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: @@ -1453,11 +1453,15 @@ class MLComponent(Component): for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) + out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) + out.write(' %s.cmi' % (os.path.join(sub_dir, m))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'dllz3$(SO_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3')))) + if IS_WINDOWS: + out.write('.lib') + else: + out.write('.so') # .so also on OSX! out.write('\n\n') From 4c28085022419176c3b4cd4b8227a283ee024cae Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:14:14 +0000 Subject: [PATCH 477/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 38cbb32f5..24c9def9c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1436,7 +1436,7 @@ class MLComponent(Component): out.write(' %s.cmi' % (os.path.join(sub_dir, m))) # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) - out.write('%s/z3native_stubs.o\n' % (sub_dir)) + out.write(' %s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: out.write(' ' + m) From 198c6ef930d3684fca1ed15aee7cd327bb653a7a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 14:18:03 +0000 Subject: [PATCH 478/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 24c9def9c..3f53266e2 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1439,7 +1439,7 @@ class MLComponent(Component): out.write(' %s/z3native_stubs.o\n' % (sub_dir)) out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) for m in modules: - out.write(' ' + m) + out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) From d47f143591f3fe7e9f0ada321841b292e393c3fc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 15:03:10 +0000 Subject: [PATCH 479/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3f53266e2..0625e9c68 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1436,28 +1436,28 @@ class MLComponent(Component): out.write(' %s.cmi' % (os.path.join(sub_dir, m))) # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) - out.write(' %s/z3native_stubs.o\n' % (sub_dir)) - out.write('\tcd %s ; ocamlmklib -verbose -o z3' % (sub_dir)) + out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) + out.write('\tcd %s ; ocamlmklib -o z3ml' % (sub_dir)) for m in modules: out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) #out.write('\n') # Generate META file and package installation commands self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('\nocamlfind_install: api/ml/z3.cmxa api/ml/META\n') + out.write('\nocamlfind_install: %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) + #out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - out.write(' %s' % ((os.path.join(sub_dir, 'libz3$(LIB_EXT)')))) - out.write(' %s' % ((os.path.join(sub_dir, 'dllz3')))) + out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) + out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: out.write('.lib') else: From ea9fc43544bdf2f9b24bbfca92a923561869d35f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 15:38:15 +0000 Subject: [PATCH 480/646] ML API: build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 0625e9c68..ce8abd4ce 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1422,14 +1422,19 @@ class MLComponent(Component): # if DEBUG_MODE: # out.write('-g ') # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cma'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - # for mlfile in get_ml_files(self.src_dir): - # out.write(' %s' % os.path.join(sub_dir, mlfile)) - # out.write('\n') - # out.write('\t%s ' % (OCAMLC)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cma -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) + out.write('%s: %s %s$(SO_EXT) %s' % ( + os.path.join(sub_dir, 'z3.cma'), + os.path.join(sub_dir, 'libz3ml$(LIB_EXT)'), + get_component(Z3_DLL_COMPONENT).dll_name, cmis)) + for mlfile in get_ml_files(self.src_dir): + out.write(' %s' % os.path.join(sub_dir, mlfile)) + out.write('\n') + out.write('\t%s ' % (OCAMLC)) + if DEBUG_MODE: + out.write('-g ') + out.write('-I %s -a -o %s -linkall' % (sub_dir, os.path.join(sub_dir, 'z3.cma'))) + for m in modules: + out.write(' %s.ml' % (os.path.join(sub_dir, m))) out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) for m in modules: From 93a20d90740c2112fb5cac5f11ebbe2097503762 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 19:22:23 +0000 Subject: [PATCH 481/646] ML API: build fixes --- scripts/mk_util.py | 94 +++++++++++++++++----------------------------- src/api/ml/META | 6 +-- src/api/ml/z3.ml | 2 +- 3 files changed, 38 insertions(+), 64 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ce8abd4ce..b674d106f 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1380,19 +1380,25 @@ class MLComponent(Component): str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) out.write(str) modules = ["z3enums", "z3native", "z3"] # dependencies in this order! - prev = '' + mls = '' + mlis = '' + cmis = '' + archives = '' + for m in modules: fn = os.path.join(self.src_dir, ('%s.mli' % m)) if not os.path.exists(fn): - out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),prev)) + out.write('%s.mli: %s.ml%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),mlis)) out.write('\t%s -I %s -i -c %s.ml > %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir, m),os.path.join(sub_dir, m))) - prev = prev + ' ' + os.path.join(sub_dir, m) + '.mli' - cmis = '' - for m in modules: out.write('%s.cmi: %s.mli%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m), cmis)) out.write('\t%s -I %s -c %s.mli\n' % (OCAMLC,sub_dir,os.path.join(sub_dir,m))) + out.write('%s.cma: %s.ml %s.cmi%s\n' % (os.path.join(sub_dir,m),os.path.join(sub_dir,m),os.path.join(sub_dir,m), archives)) + out.write('\t%s -a -o %s.ml -o %s.cma\n' % (OCAMLC,os.path.join(sub_dir,m), os.path.join(sub_dir,m))) + mlis = mlis + ' ' + os.path.join(sub_dir, m) + '.mli' cmis = cmis + ' ' + os.path.join(sub_dir,m) + '.cmi' - + archives = archives + ' ' + os.path.join(sub_dir,m) + '.cma' + mls = mls + ' ' + os.path.join(sub_dir, m) + '.ml' + out.write('%s: %s %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), os.path.join(sub_dir, 'z3native_stubs.c'), @@ -1400,73 +1406,43 @@ class MLComponent(Component): out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) - # out.write('api/ml/libz3ml$(LIB_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - # out.write('\t$(AR) $(AR_FLAGS) $(AR_OUTFLAG)api/ml/libz3ml$(LIB_EXT) api/ml/z3native_stubs$(OBJ_EXT)\n') - - # out.write('api/ml/libz3ml$(SO_EXT): api/ml/z3native_stubs$(OBJ_EXT) %s$(SO_EXT)\n' % get_component(Z3_DLL_COMPONENT).dll_name) - # out.write('\t$(SLINK) $(SLINK_OUT_FLAG)api/ml/libz3ml$(SO_EXT) $(SLINK_FLAGS) -I %s -I %s api/ml/z3native_stubs$(OBJ_EXT) %s$(LIB_EXT)\n' % (OCAML_LIB, api_src, get_component(Z3_DLL_COMPONENT).dll_name)) - - - # out.write('%s: api/ml/libz3ml$(LIB_EXT) %s$(SO_EXT) %s' % (os.path.join(sub_dir, 'z3.cmxa'), get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - - # for mlfile in get_ml_files(self.src_dir): - # out.write(' %s' % os.path.join(sub_dir, mlfile)) - # out.write('\n') - # out.write('\t%s ' % (OCAMLOPT)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -I %s %s/z3enums.ml %s/z3native.ml %s/z3.ml -a -o api/ml/z3.cmxa -linkall\n' % (sub_dir, sub_dir,sub_dir,sub_dir,sub_dir)) - - # out.write('%s: %s\n' % (os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - # out.write('\t%s ' % (OCAMLOPT)) - # if DEBUG_MODE: - # out.write('-g ') - # out.write('-cclib "-L %s -lz3ml" -shared -o %s %s -linkall\n' % (sub_dir, os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cmxa'))) - out.write('%s: %s %s$(SO_EXT) %s' % ( - os.path.join(sub_dir, 'z3.cma'), - os.path.join(sub_dir, 'libz3ml$(LIB_EXT)'), - get_component(Z3_DLL_COMPONENT).dll_name, cmis)) - for mlfile in get_ml_files(self.src_dir): - out.write(' %s' % os.path.join(sub_dir, mlfile)) - out.write('\n') - out.write('\t%s ' % (OCAMLC)) - if DEBUG_MODE: - out.write('-g ') - out.write('-I %s -a -o %s -linkall' % (sub_dir, os.path.join(sub_dir, 'z3.cma'))) - for m in modules: - out.write(' %s.ml' % (os.path.join(sub_dir, m))) - - out.write('%s:' % (os.path.join(sub_dir, "z3.cmxa"))) - for m in modules: - out.write(' %s.cmi' % (os.path.join(sub_dir, m))) - # out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - # out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write('%s: %s %s %s$(SO_EXT)' % ( + os.path.join(sub_dir, "z3ml.cmxa"), + cmis, + archives, + get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tcd %s ; ocamlmklib -o z3ml' % (sub_dir)) + out.write('\tcd %s ; ocamlmklib -o z3ml -ldopt \'-L../.. -lz3\' ' % (sub_dir)) for m in modules: out.write(' %s.ml' % m) out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') - out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3.cmxa'))) - # , os.path.join(sub_dir, 'z3.cmxs'), os.path.join(sub_dir, 'z3.cma'))) - #out.write('\n') - # Generate META file and package installation commands + out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': - out.write('\nocamlfind_install: %s %s\n' % (os.path.join(sub_dir, 'z3.cmxa'), os.path.join(sub_dir, 'META'))) + out.write('\nocamlfind_install: %s %s %s\n' % ( + get_component(Z3_DLL_COMPONENT).dll_name)+'$(SO_EXT)', + os.path.join(sub_dir, 'z3ml.cmxa'), + os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) for m in modules: out.write(' %s.cma' % (os.path.join(sub_dir, m))) - out.write(' %s.cmxa' % (os.path.join(sub_dir, m))) out.write(' %s.cmx' % (os.path.join(sub_dir, m))) - #out.write(' %s.cmxs' % (os.path.join(sub_dir, m))) out.write(' %s.cmi' % (os.path.join(sub_dir, m))) + out.write(' %s.cmo' % (os.path.join(sub_dir, m))) + out.write(' %s.ml' % (os.path.join(sub_dir, m))) + out.write(' %s.mli' % (os.path.join(sub_dir, m))) + out.write(' %s$(OBJ_EXT)' % (os.path.join(sub_dir, m))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.a')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cma')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cmxa')))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: out.write('.lib') else: out.write('.so') # .so also on OSX! + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name) + '$(SO_EXT)')))) out.write('\n\n') @@ -1591,25 +1567,25 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: api/ml/z3.cma ') + out.write('ml_example.byte: api/ml/z3ml.cma ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLC) if DEBUG_MODE: out.write('-g ') - out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3.cma') + out.write('-custom -o ml_example.byte -I api/ml -cclib "-L. -lz3" nums.cma z3ml.cma') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') - out.write('ml_example$(EXE_EXT): api/ml/z3.cmxa ml_example.byte') + out.write('ml_example$(EXE_EXT): api/ml/z3ml.cmxa ml_example.byte') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') out.write('\t%s ' % OCAMLOPT) if DEBUG_MODE: out.write('-g ') - out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3.cmxa') + out.write('-o ml_example$(EXE_EXT) -I api/ml -cclib "-L. -lz3" nums.cmxa z3ml.cmxa') for mlfile in get_ml_files(self.ex_dir): out.write(' %s/%s' % (self.to_ex_dir, mlfile)) out.write('\n') diff --git a/src/api/ml/META b/src/api/ml/META index 635de613c..8634b53b1 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -4,8 +4,6 @@ description = "Z3 Theorem Prover (OCaml API)" requires = "num" archive(byte) = "z3ml.cma" archive(native) = "z3ml.cmxa" -archive(byte,plugin) = "z3ml.cma" -archive(native,plugin) = "z3ml.cmxa" -archive(byte,toploop) = "z3ml.cma" -archive(native,toploop) = "z3ml.cmxa" +archive(byte, plugin) = "z3ml.cma" +archive(native, plugin) = "z3ml.cmxs" linkopts = "-cclib -lz3" diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 2b54a1113..350457525 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -110,7 +110,7 @@ struct string_of_int mj ^ "." ^ string_of_int mn ^ "." ^ string_of_int bld ^ "." ^ - string_of_int rev ^ "." + string_of_int rev end From 05f42b0073d50c20dff4a3fa229d09897ba580c5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 4 Dec 2014 19:42:03 +0000 Subject: [PATCH 482/646] ML API: build fixes? --- scripts/mk_util.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index b674d106f..4ccf23932 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1412,16 +1412,18 @@ class MLComponent(Component): archives, get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tcd %s ; ocamlmklib -o z3ml -ldopt \'-L../.. -lz3\' ' % (sub_dir)) + out.write('\tocamlmklib -o %s -I %s -ldopt \'-L. -lz3\' ' % ( + os.path.join(sub_dir, 'z3ml'), + sub_dir)) for m in modules: - out.write(' %s.ml' % m) - out.write(' z3native_stubs$(OBJ_EXT) ; cd -\n') + out.write(' %s' % (os.path.join(sub_dir, m+'.ml'))) + out.write(' z3native_stubs$(OBJ_EXT)\n') out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': out.write('\nocamlfind_install: %s %s %s\n' % ( - get_component(Z3_DLL_COMPONENT).dll_name)+'$(SO_EXT)', - os.path.join(sub_dir, 'z3ml.cmxa'), + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)', + os.path.join(sub_dir, 'z3ml.cmxa'), os.path.join(sub_dir, 'META'))) out.write('\t%s remove Z3\n' % (OCAMLFIND)) out.write('\t%s install Z3 %s' % (OCAMLFIND, (os.path.join(sub_dir, 'META')))) @@ -1442,7 +1444,7 @@ class MLComponent(Component): out.write('.lib') else: out.write('.so') # .so also on OSX! - out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name) + '$(SO_EXT)')))) + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') out.write('\n\n') From 5c67b596857524db527fad2aa0361c948f434305 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 5 Dec 2014 16:40:40 +0000 Subject: [PATCH 483/646] ML API: Windows build fixes Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4ccf23932..8c6d35a0a 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1412,12 +1412,10 @@ class MLComponent(Component): archives, get_component(Z3_DLL_COMPONENT).dll_name)) out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) - out.write('\tocamlmklib -o %s -I %s -ldopt \'-L. -lz3\' ' % ( - os.path.join(sub_dir, 'z3ml'), - sub_dir)) + out.write('\tocamlmklib -o %s -I %s -ldopt \"-L. -lz3\" ' % (os.path.join(sub_dir, 'z3ml'), sub_dir)) for m in modules: out.write(' %s' % (os.path.join(sub_dir, m+'.ml'))) - out.write(' z3native_stubs$(OBJ_EXT)\n') + out.write(' %s\n' % (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'))) out.write('ml: %s\n' % (os.path.join(sub_dir, 'z3ml.cmxa'))) self.mk_ml_meta(os.path.join('src/api/ml/META'), os.path.join(BUILD_DIR, sub_dir, 'META'), VER_MAJOR, VER_MINOR, VER_BUILD, VER_REVISION) if OCAMLFIND != '': @@ -1435,13 +1433,13 @@ class MLComponent(Component): out.write(' %s.ml' % (os.path.join(sub_dir, m))) out.write(' %s.mli' % (os.path.join(sub_dir, m))) out.write(' %s$(OBJ_EXT)' % (os.path.join(sub_dir, m))) - out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.a')))) + out.write(' %s' % ((os.path.join(sub_dir, 'z3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cma')))) out.write(' %s' % ((os.path.join(sub_dir, 'z3ml.cmxa')))) out.write(' %s' % ((os.path.join(sub_dir, 'libz3ml$(LIB_EXT)')))) out.write(' %s' % ((os.path.join(sub_dir, 'dllz3ml')))) if IS_WINDOWS: - out.write('.lib') + out.write('.dll') else: out.write('.so') # .so also on OSX! out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') @@ -1569,7 +1567,7 @@ class MLExampleComponent(ExampleComponent): def mk_makefile(self, out): if ML_ENABLED: - out.write('ml_example.byte: api/ml/z3ml.cma ') + out.write('ml_example.byte: api/ml/z3ml.cmxa ') for mlfile in get_ml_files(self.ex_dir): out.write(' %s' % os.path.join(self.to_ex_dir, mlfile)) out.write('\n') From 011b700c20aadf000fceb5da9b4630f8939b033a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:14:26 +0000 Subject: [PATCH 484/646] ML API: build fix --- src/api/ml/META | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/ml/META b/src/api/ml/META index 8634b53b1..635de613c 100644 --- a/src/api/ml/META +++ b/src/api/ml/META @@ -4,6 +4,8 @@ description = "Z3 Theorem Prover (OCaml API)" requires = "num" archive(byte) = "z3ml.cma" archive(native) = "z3ml.cmxa" -archive(byte, plugin) = "z3ml.cma" -archive(native, plugin) = "z3ml.cmxs" +archive(byte,plugin) = "z3ml.cma" +archive(native,plugin) = "z3ml.cmxa" +archive(byte,toploop) = "z3ml.cma" +archive(native,toploop) = "z3ml.cmxa" linkopts = "-cclib -lz3" From 10c153bfe46fa74d58995dc392ac1ef89de9bc76 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:21:27 +0000 Subject: [PATCH 485/646] ML API: build fix --- examples/ml/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index 31d4b8e2e..b7aa187fa 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -15,10 +15,10 @@ for the byte-code version. If Z3 was installed into the ocamlfind package repository (see src/api/ml/README), then we can compile this example as follows: -ocamlfind ocamlc -o ml_example.byte -custom -package Z3 -linkpkg ml_example.ml +ocamlfind ocamlc -o ml_example.byte -package Z3 -linkpkg ml_example.ml ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml Note that the resulting binaries depend on the shared z3 library, which needs to be in the PATH (Windows), LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX). If Z3 was installed into ocamlfind, the path that should be added is -`ocamlfind printconf destdir`/Z3 \ No newline at end of file +`ocamlfind printconf destdir`/Z3 From bb310144175221fd1dd7d885d139ec65b14b03b0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 6 Dec 2014 18:37:09 +0000 Subject: [PATCH 486/646] ML API: build fix Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8c6d35a0a..86035b94b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1443,6 +1443,8 @@ class MLComponent(Component): else: out.write('.so') # .so also on OSX! out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(SO_EXT)') + if IS_WINDOWS: + out.write(' ' + get_component(Z3_DLL_COMPONENT).dll_name + '$(LIB_EXT)') out.write('\n\n') From e754aa1c1169b61904b3fce21aeb286ce641aec4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 16 Jan 2015 19:25:21 +0000 Subject: [PATCH 487/646] Minor adjustments after rebasing ml-ng onto unstable. Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 5 +++++ scripts/mk_util.py | 9 ++++++--- src/api/ml/README-test-win | 23 ----------------------- 3 files changed, 11 insertions(+), 26 deletions(-) delete mode 100644 src/api/ml/README-test-win diff --git a/.gitignore b/.gitignore index 3cd2d3ef3..93194fc1b 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,9 @@ src/api/java/enumerations/*.java src/api/ml/z3native_stubs.c src/api/ml/z3native.ml src/api/ml/z3enums.ml +src/api/ml/z3native.mli +src/api/ml/z3enums.mli src/api/ml/z3.mllib +*.bak +doc/api +doc/code diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 86035b94b..5f2b846a0 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -357,6 +357,7 @@ def check_ml(): rmf('hello.cmo') rmf('hello.cmx') rmf('a.out') + rmf('hello.o') find_ml_lib() find_ocaml_find() @@ -384,6 +385,8 @@ def find_ml_lib(): OCAML_LIB = line[:-1] if is_verbose(): print 'OCAML_LIB=%s' % OCAML_LIB + t.close() + rmf('output') return def is64(): @@ -1737,10 +1740,10 @@ def mk_config(): # End of Windows VS config.mk if is_verbose(): print('64-bit: %s' % is64()) - print('ML API: %s' % is_ml_enabled()) if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) + print('ML API: %s' % is_ml_enabled()) if is_ml_enabled(): print('OCaml Compiler: %s' % OCAMLC) print('OCaml Native: %s' % OCAMLOPT) @@ -1859,11 +1862,11 @@ def mk_config(): print('64-bit: %s' % is64()) if GPROF: print('gprof: enabled') - print('Python version: %s' % distutils.sysconfig.get_python_version()) - print('ML API: %s' % is_ml_enabled()) + print('Python version: %s' % distutils.sysconfig.get_python_version()) if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) + print('ML API: %s' % is_ml_enabled()) if is_ml_enabled(): print('Ocaml Compiler: %s' % OCAMLC) print('Ocaml Native: %s' % OCAMLOPT) diff --git a/src/api/ml/README-test-win b/src/api/ml/README-test-win deleted file mode 100644 index 0e8b73ccd..000000000 --- a/src/api/ml/README-test-win +++ /dev/null @@ -1,23 +0,0 @@ -This directory contains scripts to build the test application using -OCaml. You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- One must build the OCaml library before compiling the example. - Go to directory ../ocaml - -- Use 'build-test.cmd' to build the test application using the OCaml compiler. - -Remark: The OCaml and C compiler tool chains must be configured in your environment. -Running from the Visual Studio Command Prompt configures the Microsoft C compiler. - -- The script 'exec.cmd' adds the bin directory to the path. So, - test_mlapi.exe can find z3.dll. - - - - From c9fa77cc70e1d7cd0953743d12202f93fd3b9387 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 15:29:50 +0000 Subject: [PATCH 488/646] ML API: fixed Python 3.4 issues in the build scripts Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 14 +++++++------- scripts/update_api.py | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5f2b846a0..49ff79824 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -344,12 +344,12 @@ def check_ml(): t.add('print_string "Hello world!\n";;') t.commit() if is_verbose(): - print "Testing %s..." % OCAMLC + print ('Testing %s...' % OCAMLC) r = exec_cmd([OCAMLC, '-o', 'a.out', 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlc compiler. Set environment variable OCAMLC with the path to the Ocaml compiler') if is_verbose(): - print "Testing %s..." % OCAMLOPT + print ('Testing %s...' % OCAMLOPT) r = exec_cmd([OCAMLOPT, '-o', 'a.out', 'hello.ml']) if r != 0: raise MKException('Failed testing ocamlopt compiler. Set environment variable OCAMLOPT with the path to the Ocaml native compiler. Note that ocamlopt may require flexlink to be in your path.') @@ -364,7 +364,7 @@ def check_ml(): def find_ocaml_find(): global OCAMLFIND if is_verbose(): - print "Testing %s..." % OCAMLFIND + print ('Testing %s...' % OCAMLFIND) r = exec_cmd([OCAMLFIND, 'printconf']) if r != 0: OCAMLFIND='' @@ -372,7 +372,7 @@ def find_ocaml_find(): def find_ml_lib(): global OCAML_LIB if is_verbose(): - print "Finding OCAML_LIB..." + print ('Finding OCAML_LIB...') t = TempFile('output') null = open(os.devnull, 'wb') try: @@ -384,7 +384,7 @@ def find_ml_lib(): for line in t: OCAML_LIB = line[:-1] if is_verbose(): - print 'OCAML_LIB=%s' % OCAML_LIB + print ('OCAML_LIB=%s' % OCAML_LIB) t.close() rmf('output') return @@ -2810,7 +2810,7 @@ def mk_z3consts_ml(api_files): linenum = linenum + 1 efile.write('end\n') if VERBOSE: - print "Generated '%s/z3enums.ml'" % ('%s' % gendir) + print ('Generated "%s/z3enums.ml"' % ('%s' % gendir)) efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') efile.write('(* Automatically generated file *)\n\n') efile.write('(** The enumeration types of Z3. *)\n\n') @@ -2880,7 +2880,7 @@ def mk_z3consts_ml(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s/z3enums.mli'" % ('%s' % gendir) + print ('Generated "%s/z3enums.mli"' % ('%s' % gendir)) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id diff --git a/scripts/update_api.py b/scripts/update_api.py index 4669b78fc..a70214971 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -276,7 +276,7 @@ def param2dotnet(p): elif k == OUT_ARRAY: return "[Out] %s[]" % type2dotnet(param_type(p)) elif k == OUT_MANAGED_ARRAY: - return "[Out] out %s[]" % type2dotnet(param_type(p)) + return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) @@ -1517,7 +1517,7 @@ def mk_ml(): ml_wrapper.write('}\n') ml_wrapper.write('#endif\n') if is_verbose(): - print "Generated '%s'" % ml_nativef + print ('Generated "%s"' % ml_nativef) # Collect API(...) commands from def def_APIs(): From ed0fa9324592293e97f8a0da267cc3eb384a1e03 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 17:35:19 +0000 Subject: [PATCH 489/646] Minor adjustments after rebase Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 2 +- scripts/mk_util.py | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 25862b2d7..33334930e 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -190,7 +190,7 @@ let basic_tests ( ctx : context ) = (* Error handling test. *) try ( let i = Integer.mk_numeral_s ctx "1/2" in - raise (TestFailedException "") (* unreachable *) + raise (TestFailedException (to_string i)) (* unreachable *) ) with Z3native.Exception(_) -> ( Printf.printf "Exception caught, OK.\n" diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 49ff79824..30c305047 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -357,14 +357,13 @@ def check_ml(): rmf('hello.cmo') rmf('hello.cmx') rmf('a.out') - rmf('hello.o') find_ml_lib() find_ocaml_find() def find_ocaml_find(): global OCAMLFIND if is_verbose(): - print ('Testing %s...' % OCAMLFIND) + print ("Testing %s..." % OCAMLFIND) r = exec_cmd([OCAMLFIND, 'printconf']) if r != 0: OCAMLFIND='' @@ -1743,7 +1742,6 @@ def mk_config(): if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) - print('ML API: %s' % is_ml_enabled()) if is_ml_enabled(): print('OCaml Compiler: %s' % OCAMLC) print('OCaml Native: %s' % OCAMLOPT) @@ -1866,11 +1864,10 @@ def mk_config(): if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) - print('ML API: %s' % is_ml_enabled()) if is_ml_enabled(): - print('Ocaml Compiler: %s' % OCAMLC) - print('Ocaml Native: %s' % OCAMLOPT) - print('Ocaml Library: %s' % OCAML_LIB) + print('OCaml Compiler: %s' % OCAMLC) + print('OCaml Native: %s' % OCAMLOPT) + print('OCaml Library: %s' % OCAML_LIB) def mk_install(out): out.write('install: ') @@ -2437,9 +2434,6 @@ def mk_bindings(api_files): if is_java_enabled(): check_java() mk_z3consts_java(api_files) - if is_ml_enabled(): - check_ml() - mk_z3consts_ml(api_files) _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3py_to_build() if is_ml_enabled(): @@ -2808,7 +2802,6 @@ def mk_z3consts_ml(api_files): decls[words[1]] = idx idx = idx + 1 linenum = linenum + 1 - efile.write('end\n') if VERBOSE: print ('Generated "%s/z3enums.ml"' % ('%s' % gendir)) efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') From d8f90802c0933be09377e30fec724e24252c2253 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 18:14:22 +0000 Subject: [PATCH 490/646] Added FPA setup to default kernel setup Signed-off-by: Christoph M. Wintersteiger --- src/smt/smt_setup.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 68e960fb8..d17e4b803 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -813,6 +813,7 @@ namespace smt { setup_AUFLIA(false); setup_datatypes(); setup_bv(); + setup_fpa(); return; } From a8d8e3e9e59b1f726399462bde034edae1e63aaf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 18:16:51 +0000 Subject: [PATCH 491/646] formatting Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 2fbf42cca..d53bc5de3 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -266,7 +266,7 @@ def param2dotnet(p): elif k == OUT_ARRAY: return "[Out] %s[]" % type2dotnet(param_type(p)) elif k == OUT_MANAGED_ARRAY: - return "[Out] out %s[]" % type2dotnet(param_type(p)) + return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) From d20c7bc9eeaf952fd40f4604dac3c1a748507f56 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 19 Jan 2015 18:19:43 +0000 Subject: [PATCH 492/646] Added is_qfaufbv_probe and is_qfauflia_probe. Potential performance disruption for some users: Changed default_tactic to call the respective tactics, where previously they would have run the default 'smt' tactic. Signed-off-by: Christoph M. Wintersteiger --- src/tactic/arith/probe_arith.cpp | 75 +++++++++++++++++++++++++ src/tactic/arith/probe_arith.h | 2 + src/tactic/portfolio/default_tactic.cpp | 6 +- src/tactic/probe.cpp | 38 +++++++++++++ src/tactic/probe.h | 2 + 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/tactic/arith/probe_arith.cpp b/src/tactic/arith/probe_arith.cpp index 45fc868ac..770281923 100644 --- a/src/tactic/arith/probe_arith.cpp +++ b/src/tactic/arith/probe_arith.cpp @@ -198,11 +198,75 @@ struct is_non_qflira_functor { } }; +struct is_non_qfauflira_functor { + struct found {}; + ast_manager & m; + arith_util m_arith_util; + array_util m_array_util; + bool m_int; + bool m_real; + + is_non_qfauflira_functor(ast_manager & _m, bool _int, bool _real) : + m(_m), m_arith_util(_m), m_array_util(_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 && m_arith_util.is_int(n)) + return true; + if (m_real && m_arith_util.is_real(n)) + return true; + if (m_array_util.is_array(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 == m_arith_util.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 (!m_arith_util.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(n)) + return; + throw found(); + } +}; + static bool is_qflia(goal const & g) { is_non_qflira_functor p(g.m(), true, false); return !test(g, p); } +static bool is_qfauflia(goal const & g) { + is_non_qfauflira_functor p(g.m(), true, false); + return !test(g, p); +} + class is_qflia_probe : public probe { public: virtual result operator()(goal const & g) { @@ -210,6 +274,13 @@ public: } }; +class is_qfauflia_probe : public probe { +public: + virtual result operator()(goal const & g) { + return is_qfauflia(g); + } +}; + static bool is_qflra(goal const & g) { is_non_qflira_functor p(g.m(), false, true); return !test(g, p); @@ -289,6 +360,10 @@ probe * mk_is_qflia_probe() { return alloc(is_qflia_probe); } +probe * mk_is_qfauflia_probe() { + return alloc(is_qfauflia_probe); +} + probe * mk_is_qflra_probe() { return alloc(is_qflra_probe); } diff --git a/src/tactic/arith/probe_arith.h b/src/tactic/arith/probe_arith.h index 17e9efb28..83179098d 100644 --- a/src/tactic/arith/probe_arith.h +++ b/src/tactic/arith/probe_arith.h @@ -33,6 +33,7 @@ probe * mk_arith_max_degree_probe(); */ probe * mk_is_qflia_probe(); +probe * mk_is_qfauflia_probe(); probe * mk_is_qflra_probe(); probe * mk_is_qflira_probe(); probe * mk_is_ilp_probe(); @@ -40,6 +41,7 @@ probe * mk_is_mip_probe(); /* ADD_PROBE("is-qflia", "true if the goal is in QF_LIA.", "mk_is_qflia_probe()") + ADD_PROBE("is-qfauflia", "true if the goal is in QF_AUFLIA.", "mk_is_qfauflia_probe()") ADD_PROBE("is-qflra", "true if the goal is in QF_LRA.", "mk_is_qflra_probe()") ADD_PROBE("is-qflira", "true if the goal is in QF_LIRA.", "mk_is_qflira_probe()") ADD_PROBE("is-ilp", "true if the goal is ILP.", "mk_is_ilp_probe()") diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 9ecc16ecf..4bd82b969 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -28,10 +28,14 @@ Notes: #include"probe_arith.h" #include"quant_tactics.h" #include"qffpa_tactic.h" +#include"qfaufbv_tactic.h" +#include"qfauflia_tactic.h" tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { tactic * st = using_params(and_then(mk_simplify_tactic(m), cond(mk_is_qfbv_probe(), mk_qfbv_tactic(m), + cond(mk_is_qfaufbv_probe(), mk_qfaufbv_tactic(m), + cond(mk_is_qfauflia_probe(), mk_qfauflia_tactic(m), cond(mk_is_qflia_probe(), mk_qflia_tactic(m), cond(mk_is_qflra_probe(), mk_qflra_tactic(m), cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m), @@ -39,7 +43,7 @@ tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { cond(mk_is_nra_probe(), mk_nra_tactic(m), cond(mk_is_lira_probe(), mk_lira_tactic(m, p), cond(mk_is_qffpabv_probe(), mk_qffpa_tactic(m, p), - mk_smt_tactic()))))))))), + mk_smt_tactic()))))))))))), p); return st; } diff --git a/src/tactic/probe.cpp b/src/tactic/probe.cpp index 1a696dc78..30a62fb5c 100644 --- a/src/tactic/probe.cpp +++ b/src/tactic/probe.cpp @@ -316,6 +316,44 @@ probe * mk_is_qfbv_probe() { return alloc(is_qfbv_probe); } +struct is_non_qfaufbv_predicate { + struct found {}; + ast_manager & m; + bv_util m_bv_util; + array_util m_array_util; + + is_non_qfaufbv_predicate(ast_manager & _m) : m(_m), m_bv_util(_m), m_array_util(_m) {} + + void operator()(var *) { throw found(); } + + void operator()(quantifier *) { throw found(); } + + void operator()(app * n) { + if (!m.is_bool(n) && !m_bv_util.is_bv(n) && !m_array_util.is_array(n)) + throw found(); + family_id fid = n->get_family_id(); + if (fid == m.get_basic_family_id()) + return; + if (fid == m_bv_util.get_family_id() || fid == m_array_util.get_family_id()) + return; + if (is_uninterp(n)) + return; + + throw found(); + } +}; + +class is_qfaufbv_probe : public probe { +public: + virtual result operator()(goal const & g) { + return !test(g); + } +}; + +probe * mk_is_qfaufbv_probe() { + return alloc(is_qfaufbv_probe); +} + class num_consts_probe : public probe { bool m_bool; // If true, track only boolean constants. Otherwise, track only non boolean constants. char const * m_family; // (Ignored if m_bool == true), if != 0 and m_bool == true, then track only constants of the given family. diff --git a/src/tactic/probe.h b/src/tactic/probe.h index 2f61b340f..0cf8122e4 100644 --- a/src/tactic/probe.h +++ b/src/tactic/probe.h @@ -111,10 +111,12 @@ probe * mk_div(probe * p1, probe * p2); probe * mk_is_propositional_probe(); probe * mk_is_qfbv_probe(); +probe * mk_is_qfaufbv_probe(); /* ADD_PROBE("is-propositional", "true if the goal is in propositional logic.", "mk_is_propositional_probe()") ADD_PROBE("is-qfbv", "true if the goal is in QF_BV.", "mk_is_qfbv_probe()") + ADD_PROBE("is-qfaufbv", "true if the goal is in QF_AUFBV.", "mk_is_qfaufbv_probe()") */ #endif From 074ff311c072a8c240b515a54b9be2f705d9edd1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jan 2015 15:19:31 +0000 Subject: [PATCH 493/646] BV-SLS final integration. Signed-off-by: Christoph M. Wintersteiger --- versions/z3-crsat-0.01.txt | 12 ------------ versions/z3-gsat-0.01.txt | 10 ---------- versions/z3-gsat-res-0.01.txt | 10 ---------- versions/z3-wsat-0.01.txt | 14 -------------- versions/z3-wsat-0.01b.txt | 14 -------------- versions/z3-wsat-0.01c.txt | 12 ------------ versions/z3-wsat-0.01d.txt | 11 ----------- versions/z3-wsat-0.01e.txt | 11 ----------- versions/z3-wsat-0.02.txt | 13 ------------- versions/z3-wsat-res-0.01.txt | 13 ------------- 10 files changed, 120 deletions(-) delete mode 100644 versions/z3-crsat-0.01.txt delete mode 100644 versions/z3-gsat-0.01.txt delete mode 100644 versions/z3-gsat-res-0.01.txt delete mode 100644 versions/z3-wsat-0.01.txt delete mode 100644 versions/z3-wsat-0.01b.txt delete mode 100644 versions/z3-wsat-0.01c.txt delete mode 100644 versions/z3-wsat-0.01d.txt delete mode 100644 versions/z3-wsat-0.01e.txt delete mode 100644 versions/z3-wsat-0.02.txt delete mode 100644 versions/z3-wsat-res-0.01.txt diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt deleted file mode 100644 index 49e1a1525..000000000 --- a/versions/z3-crsat-0.01.txt +++ /dev/null @@ -1,12 +0,0 @@ -More focused (_FOCUS_ == 2) WalkSAT version. -Variables are chosen among candidates in only one unsatisfied bit-vector term. -Flip rate slightly slower; probably due to larger hash-table and recursive formula structure. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 1 -#define _FOCUS_ 3 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt deleted file mode 100644 index eb806a67f..000000000 --- a/versions/z3-gsat-0.01.txt +++ /dev/null @@ -1,10 +0,0 @@ -Basic GSAT version. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 0 -#define _FOCUS_ 0 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt deleted file mode 100644 index 6a211f2bc..000000000 --- a/versions/z3-gsat-res-0.01.txt +++ /dev/null @@ -1,10 +0,0 @@ -Basic GSAT version corresponding to Christoph's original code. -Restarts after 100 plateaus. - -#define _CNF_ 0 -#define _BFS_ 0 -#define _FOCUS_ 0 -#define _RESTARTS_ 1 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt deleted file mode 100644 index fec38518d..000000000 --- a/versions/z3-wsat-0.01.txt +++ /dev/null @@ -1,14 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion. -Flip rate increased by roughly 10%-300%. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 1 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 - -BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt deleted file mode 100644 index 8bcf2ffeb..000000000 --- a/versions/z3-wsat-0.01b.txt +++ /dev/null @@ -1,14 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion. -Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0). -No restarts. - -#define _CNF_ 0 -#define _BFS_ 0 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 - -BUGGY VERSION! Uses wrong value for modulo operation in assertion selection. \ No newline at end of file diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt deleted file mode 100644 index 223560e08..000000000 --- a/versions/z3-wsat-0.01c.txt +++ /dev/null @@ -1,12 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion. -AND is scored by average; OR is scored by inverse multiplication. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 1 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 1 -#define _SCORE_OR_MUL_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt deleted file mode 100644 index 072191370..000000000 --- a/versions/z3-wsat-0.01d.txt +++ /dev/null @@ -1,11 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 2 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt deleted file mode 100644 index b018c5e0d..000000000 --- a/versions/z3-wsat-0.01e.txt +++ /dev/null @@ -1,11 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 3 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt deleted file mode 100644 index 34dcb157c..000000000 --- a/versions/z3-wsat-0.02.txt +++ /dev/null @@ -1,13 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion. -Score function reduced to 0/1. -No restarts. - -#define _CNF_ 0 -#define _BFS_ 1 -#define _FOCUS_ 1 -#define _RESTARTS_ 0 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 -#define _WEIGHTED_DIST_ 1 \ No newline at end of file diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt deleted file mode 100644 index 575180a59..000000000 --- a/versions/z3-wsat-res-0.01.txt +++ /dev/null @@ -1,13 +0,0 @@ -Basic WalkSAT version. -Variables are chosen among candidates in only ONE top level assertion. -Flip rate increased by roughly 10%-300% compared to GSAT. -Restarts after 100 plateaus. -Fps slightly decreased due to restarts. - -#define _CNF_ 0 -#define _BFS_ 1 -#define _FOCUS_ 1 -#define _RESTARTS_ 1 -#define _TIMELIMIT_ 300 -#define _SCORE_AND_AVG_ 0 -#define _SCORE_OR_MUL_ 0 \ No newline at end of file From 0746ede53733c6a4191dd588cba14ec83236e490 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jan 2015 15:59:25 +0000 Subject: [PATCH 494/646] BV SLS: Final adjustments Signed-off-by: Christoph M. Wintersteiger --- src/tactic/portfolio/smt_strategic_solver.cpp | 5 +--- src/tactic/sls/sls_tactic.cpp | 3 +-- src/tactic/sls/sls_tactic.h | 2 +- src/tactic/smtlogics/qfbv_tactic.cpp | 26 ------------------- 4 files changed, 3 insertions(+), 33 deletions(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index f63b4fd8c..586c3a349 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -37,14 +37,11 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -#include"sls_tactic.h" - tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") - // return mk_qfbv_tactic(m, p); - return mk_qfbv_sls_tactic(m, p); + return mk_qfbv_tactic(m, p); else if (logic=="QF_IDL") return mk_qfidl_tactic(m, p); else if (logic=="QF_LIA") diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp index 9bbed20bb..b06a047f7 100644 --- a/src/tactic/sls/sls_tactic.cpp +++ b/src/tactic/sls/sls_tactic.cpp @@ -158,8 +158,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) { } tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) { - tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m)); - //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m)); + tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m, p)); t->updt_params(p); return t; } diff --git a/src/tactic/sls/sls_tactic.h b/src/tactic/sls/sls_tactic.h index 50b8f0d5b..82ac1ce88 100644 --- a/src/tactic/sls/sls_tactic.h +++ b/src/tactic/sls/sls_tactic.h @@ -23,8 +23,8 @@ Notes: class ast_manager; class tactic; -tactic * mk_sls_tactic(ast_manager & m, params_ref const & p = params_ref()); tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p = params_ref()); + /* ADD_TACTIC("qfbv-sls", "(try to) solve using stochastic local search for QF_BV.", "mk_qfbv_sls_tactic(m, p)") */ diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp index 3b4da2f2d..ac53ca0c8 100644 --- a/src/tactic/smtlogics/qfbv_tactic.cpp +++ b/src/tactic/smtlogics/qfbv_tactic.cpp @@ -93,32 +93,6 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) { mk_sat_tactic(m)); #endif - /* use full sls - tactic * st = using_params(and_then(preamble_st, - cond(mk_is_qfbv_probe(), - cond(mk_is_qfbv_eq_probe(), - and_then(mk_bv1_blaster_tactic(m), - using_params(mk_smt_tactic(), solver_p)), - and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))), - mk_smt_tactic())), - main_p);*/ - - /* use pure dpll - tactic * st = using_params(and_then(mk_simplify_tactic(m), - cond(mk_is_qfbv_probe(), - and_then(mk_bit_blaster_tactic(m), - when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)), - and_then(using_params(and_then(mk_simplify_tactic(m), - mk_solve_eqs_tactic(m)), - local_ctx_p), - if_no_proofs(cond(mk_produce_unsat_cores_probe(), - mk_aig_tactic(), - using_params(mk_aig_tactic(), - big_aig_p))))), - new_sat), - mk_smt_tactic())), - main_p);*/ - tactic * st = using_params(and_then(preamble_st, // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function // symbols. In this case, we should not use From 237577acc8e0d4fae8e57b4e48c3c086e70c23d1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jan 2015 15:59:54 +0000 Subject: [PATCH 495/646] Bumping version to 4.4 Added to release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 8 ++++++-- scripts/mk_project.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index ad2dcaf00..f185983a3 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,9 +1,13 @@ RELEASE NOTES -Version 4.3.3 +Version 4.4 ============= -- Fixed bug in floating point models +- New feature: Stochastic local search engine for bit-vector formulas (see the qfbv-sls tactic). + See also: Froehlich, Biere, Wintersteiger, Hamadi: Stochastic Local Search + for Satisfiability Modulo Theories, AAAI 2015. + +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, and Codeplex users rsas, clockish, Heizmann. Version 4.3.2 ============= diff --git a/scripts/mk_project.py b/scripts/mk_project.py index b30bba609..225ef6413 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -9,7 +9,7 @@ from mk_util import * # Z3 Project definition def init_project_def(): - set_version(4, 3, 3, 0) + set_version(4, 4, 0, 0) add_lib('util', []) add_lib('polynomial', ['util'], 'math/polynomial') add_lib('sat', ['util']) From 5e6ea4e5704babcf6502d8deb925f29134df3767 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 20 Jan 2015 19:03:49 +0000 Subject: [PATCH 496/646] added --x86 build flag --- scripts/mk_util.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 4641a7b1b..96bc1c273 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -59,6 +59,7 @@ VERBOSE=True DEBUG_MODE=False SHOW_CPPS = True VS_X64 = False +LINUX_X64 = True ONLY_MAKEFILES = False Z3PY_SRC_DIR=None VS_PROJ = False @@ -334,7 +335,8 @@ def check_java(): raise MKException("Failed to detect jni.h. Possible solution: set JNI_HOME with the path to JDK.") def is64(): - return sys.maxsize >= 2**32 + global LINUX_X64 + return LINUX_X64 and sys.maxsize >= 2**32 def check_ar(): if is_verbose(): @@ -450,6 +452,8 @@ def display_help(exit_code): print(" -t, --trace enable tracing in release mode.") if IS_WINDOWS: print(" -x, --x64 create 64 binary when using Visual Studio.") + else: + print(" --x86 force 32-bit x86 build on x64 systems.") print(" -m, --makefiles generate only makefiles.") if IS_WINDOWS: print(" -v, --vsproj generate Visual Studio Project Files.") @@ -477,12 +481,13 @@ def display_help(exit_code): def parse_options(): global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP, FOCI2, FOCI2LIB, PYTHON_PACKAGE_DIR, GPROF, GIT_HASH + global LINUX_X64 try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:df:sxhmcvtnp:gj', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof', - 'githash=']) + 'githash=', 'x86']) except: print("ERROR: Invalid command line option") display_help(1) @@ -501,6 +506,8 @@ def parse_options(): if not IS_WINDOWS: raise MKException('x64 compilation mode can only be specified when using Visual Studio') VS_X64 = True + elif opt in ('--x86'): + LINUX_X64=False elif opt in ('-h', '--help'): display_help(0) elif opt in ('-m', '--onlymakefiles'): @@ -1593,6 +1600,10 @@ def mk_config(): CPPFLAGS = '%s -D_AMD64_' % CPPFLAGS if sysname == 'Linux': CPPFLAGS = '%s -D_USE_THREAD_LOCAL' % CPPFLAGS + elif not LINUX_X64: + CXXFLAGS = '%s -m32' % CXXFLAGS + LDFLAGS = '%s -m32' % LDFLAGS + SLIBFLAGS = '%s -m32' % SLIBFLAGS if DEBUG_MODE: CPPFLAGS = '%s -DZ3DEBUG' % CPPFLAGS if TRACE or DEBUG_MODE: From 83023c72116670742c8e6b1f470e08d1b80de158 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 13:02:18 +0000 Subject: [PATCH 497/646] build fixes Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_tracker.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 89ef57871..798a03761 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -20,6 +20,8 @@ Notes: #ifndef _SLS_TRACKER_H_ #define _SLS_TRACKER_H_ +#include + #include"for_each_expr.h" #include"ast_smt2_pp.h" #include"bv_decl_plugin.h" @@ -39,7 +41,7 @@ class sls_tracker { mpz m_zero, m_one, m_two; struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { }; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), touched(1) {}; ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; From 71e5f03b441cec399dae25cd15f6dd5fc4b657f8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 13:04:05 +0000 Subject: [PATCH 498/646] build fix --- src/tactic/sls/sls_tracker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h index 798a03761..87c0f962c 100644 --- a/src/tactic/sls/sls_tracker.h +++ b/src/tactic/sls/sls_tracker.h @@ -41,7 +41,7 @@ class sls_tracker { mpz m_zero, m_one, m_two; struct value_score { - value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), touched(1) {}; + value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), distance(0), touched(1) {}; ~value_score() { if (m) m->del(value); } unsynch_mpz_manager * m; mpz value; From e20dc9f9a474e1228795c07cf6a1c8c522ba70c5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 13:35:25 +0000 Subject: [PATCH 499/646] typo Signed-off-by: Christoph M. Wintersteiger --- src/smt/smt_case_split_queue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/smt_case_split_queue.cpp b/src/smt/smt_case_split_queue.cpp index 7a03224cf..5a4a6ff25 100644 --- a/src/smt/smt_case_split_queue.cpp +++ b/src/smt/smt_case_split_queue.cpp @@ -1091,7 +1091,7 @@ namespace smt { case_split_queue * mk_case_split_queue(context & ctx, smt_params & p) { if (p.m_relevancy_lvl < 2 && (p.m_case_split_strategy == CS_RELEVANCY || p.m_case_split_strategy == CS_RELEVANCY_ACTIVITY || p.m_case_split_strategy == CS_RELEVANCY_GOAL)) { - warning_msg("relevacy must be enabled to use option CASE_SPLIT=3, 4 or 5"); + warning_msg("relevancy must be enabled to use option CASE_SPLIT=3, 4 or 5"); p.m_case_split_strategy = CS_ACTIVITY; } if (p.m_auto_config && (p.m_case_split_strategy == CS_RELEVANCY || p.m_case_split_strategy == CS_RELEVANCY_ACTIVITY || From ae792f18917d34ad02279999bbdf29d132f94a97 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 13:47:32 +0000 Subject: [PATCH 500/646] avoid spurious warning message Signed-off-by: Christoph M. Wintersteiger --- src/smt/smt_model_checker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index 7053d63ec..163003c01 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -282,6 +282,7 @@ namespace smt { if (!m_fparams) { m_fparams = alloc(smt_params, m_context->get_fparams()); m_fparams->m_relevancy_lvl = 0; // no relevancy since the model checking problems are quantifier free + m_fparams->m_case_split_strategy = CS_ACTIVITY; // avoid warning messages about smt.case_split >= 3. } if (!m_aux_context) { symbol logic; From 052baaabe40d321aea5ec644cefa58ee36788305 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 14:22:35 +0000 Subject: [PATCH 501/646] FPA API bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- src/ast/fpa/fpa2bv_converter.cpp | 34 +++++++++++++++++++++----------- src/util/mpf.cpp | 2 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index a47835904..499cc1a32 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -267,7 +267,7 @@ def param2dotnet(p): elif k == OUT_ARRAY: return "[Out] %s[]" % type2dotnet(param_type(p)) elif k == OUT_MANAGED_ARRAY: - return "[Out] out %s[]" % type2dotnet(param_type(p)) + return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 1f7ea1186..110311c4c 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2982,12 +2982,11 @@ void fpa2bv_converter::mk_is_rm(expr * e, BV_RM_VAL rm, expr_ref & result) { case BV_RM_TIES_TO_AWAY: case BV_RM_TIES_TO_EVEN: case BV_RM_TO_NEGATIVE: - case BV_RM_TO_POSITIVE: return m_simp.mk_eq(e, rm_num, result); + case BV_RM_TO_POSITIVE: case BV_RM_TO_ZERO: + return m_simp.mk_eq(e, rm_num, result); default: - rm_num = m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3); - expr_ref r(m); r = m_bv_util.mk_ule(e, rm_num); - return m_simp.mk_not(r, result); + UNREACHABLE(); } } @@ -3182,7 +3181,7 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { #ifdef Z3DEBUG - return; + // return; // CMW: This works only for quantifier-free formulas. expr_ref new_e(m); new_e = m.mk_fresh_const(prefix, m.get_sort(e)); @@ -3485,9 +3484,14 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_is_to_pos); m_simp.mk_or(rm_is_to_zero, rm_is_to_neg, rm_zero_or_neg); m_simp.mk_or(rm_is_to_zero, rm_is_to_pos, rm_zero_or_pos); + dbg_decouple("fpa2bv_rnd_rm_is_to_zero", rm_is_to_zero); + dbg_decouple("fpa2bv_rnd_rm_is_to_neg", rm_is_to_neg); + dbg_decouple("fpa2bv_rnd_rm_is_to_pos", rm_is_to_pos); + expr_ref sgn_is_zero(m); m_simp.mk_eq(sgn, m_bv_util.mk_numeral(0, 1), sgn_is_zero); + dbg_decouple("fpa2bv_rnd_sgn_is_zero", sgn_is_zero); expr_ref max_sig(m), max_exp(m), inf_sig(m), inf_exp(m); max_sig = m_bv_util.mk_numeral(fu().fm().m_powers2.m1(sbits-1, false), sbits-1); @@ -3497,22 +3501,30 @@ void fpa2bv_converter::round(sort * s, expr_ref & rm, expr_ref & sgn, expr_ref & inf_exp = top_exp; dbg_decouple("fpa2bv_rnd_max_exp", max_exp); + dbg_decouple("fpa2bv_rnd_max_sig", max_sig); + dbg_decouple("fpa2bv_rnd_inf_sig", inf_sig); + dbg_decouple("fpa2bv_rnd_inf_exp", inf_exp); expr_ref ovfl_exp(m), max_inf_exp_neg(m), max_inf_exp_pos(m), n_d_check(m), n_d_exp(m); - m_simp.mk_ite(rm_zero_or_neg, max_exp, inf_exp, max_inf_exp_neg); - m_simp.mk_ite(rm_zero_or_pos, max_exp, inf_exp, max_inf_exp_pos); - m_simp.mk_ite(sgn_is_zero, max_inf_exp_neg, max_inf_exp_pos, ovfl_exp); + m_simp.mk_ite(rm_zero_or_pos, max_exp, inf_exp, max_inf_exp_neg); + m_simp.mk_ite(rm_zero_or_neg, max_exp, inf_exp, max_inf_exp_pos); + m_simp.mk_ite(sgn_is_zero, max_inf_exp_pos, max_inf_exp_neg, ovfl_exp); t_sig = m_bv_util.mk_extract(sbits-1, sbits-1, sig); m_simp.mk_eq(t_sig, nil_1, n_d_check); m_simp.mk_ite(n_d_check, bot_exp /* denormal */, biased_exp, n_d_exp); m_simp.mk_ite(OVF, ovfl_exp, n_d_exp, exp); expr_ref max_inf_sig_neg(m), max_inf_sig_pos(m), ovfl_sig(m), rest_sig(m); - m_simp.mk_ite(rm_zero_or_neg, max_sig, inf_sig, max_inf_sig_neg); - m_simp.mk_ite(rm_zero_or_pos, max_sig, inf_sig, max_inf_sig_pos); - m_simp.mk_ite(sgn_is_zero, max_inf_sig_neg, max_inf_sig_pos, ovfl_sig); + m_simp.mk_ite(rm_zero_or_pos, max_sig, inf_sig, max_inf_sig_neg); + m_simp.mk_ite(rm_zero_or_neg, max_sig, inf_sig, max_inf_sig_pos); + m_simp.mk_ite(sgn_is_zero, max_inf_sig_pos, max_inf_sig_neg, ovfl_sig); rest_sig = m_bv_util.mk_extract(sbits-2, 0, sig); m_simp.mk_ite(OVF, ovfl_sig, rest_sig, sig); + + dbg_decouple("fpa2bv_rnd_max_inf_sig_neg", max_inf_sig_neg); + dbg_decouple("fpa2bv_rnd_max_inf_sig_pos", max_inf_sig_pos); + dbg_decouple("fpa2bv_rnd_rm_zero_or_neg", rm_zero_or_neg); + dbg_decouple("fpa2bv_rnd_rm_zero_or_pos", rm_zero_or_pos); dbg_decouple("fpa2bv_rnd_sgn_final", sgn); dbg_decouple("fpa2bv_rnd_sig_final", sig); diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 511bdb03c..acf6eae39 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1221,7 +1221,7 @@ std::string mpf_manager::to_string(mpf const & x) { m_mpq_manager.display_decimal(ss, r, x.sbits); if (m_mpq_manager.is_int(r)) ss << ".0"; - ss << "p" << exponent; + ss << " " << exponent; res += ss.str(); } } From 079204d1aace9c3a2c239b5ef82370d954871d82 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 14:22:47 +0000 Subject: [PATCH 502/646] FPA Python API cosmetics Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 16 ++++++++-------- src/api/python/z3printer.py | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 82002c4f7..fd3d1bdc8 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -7749,7 +7749,7 @@ class FPRMRef(ExprRef): return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) -def RoundNearestTiesToEven (ctx=None): +def RoundNearestTiesToEven(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) @@ -7757,7 +7757,7 @@ def RNE (ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_even(ctx.ref()), ctx) -def RoundNearestTiesToAway (ctx=None): +def RoundNearestTiesToAway(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) @@ -7765,27 +7765,27 @@ def RNA (ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_nearest_ties_to_away(ctx.ref()), ctx) -def RoundTowardPositive (ctx=None): +def RoundTowardPositive(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) -def RTP (ctx=None): +def RTP(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_positive(ctx.ref()), ctx) -def RoundTowardNegative (ctx=None): +def RoundTowardNegative(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) -def RTN (ctx=None): +def RTN(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_negative(ctx.ref()), ctx) -def RoundTowardZero (ctx=None): +def RoundTowardZero(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) -def RTZ (ctx=None): +def RTZ(ctx=None): ctx = _get_ctx(ctx) return FPRMRef(Z3_mk_fpa_round_toward_zero(ctx.ref()), ctx) diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index da49f1719..ac1607dda 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -64,9 +64,9 @@ _z3_precedence = { # FPA operators _z3_op_to_fpa_normal_str = { - Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RNE()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RNA()', - Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RTP()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RTN()', - Z3_OP_FPA_RM_TOWARD_ZERO : 'RTZ()', + Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN : 'RoundNearestTiesToEven()', Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY : 'RoundNearestTiesToAway()', + Z3_OP_FPA_RM_TOWARD_POSITIVE : 'RoundTowardPositive()', Z3_OP_FPA_RM_TOWARD_NEGATIVE : 'RoundTowardNegative()', + Z3_OP_FPA_RM_TOWARD_ZERO : 'RoundTowardZero()', Z3_OP_FPA_PLUS_INF : '+oo', Z3_OP_FPA_MINUS_INF : '-oo', Z3_OP_FPA_NAN : 'NaN', Z3_OP_FPA_PLUS_ZERO : 'PZero', Z3_OP_FPA_MINUS_ZERO : 'NZero', Z3_OP_FPA_ADD : 'fpAdd', Z3_OP_FPA_SUB : 'fpSub', Z3_OP_FPA_NEG : 'fpNeg', Z3_OP_FPA_MUL : 'fpMul', @@ -580,7 +580,7 @@ class Formatter: if self.fpa_pretty and a.decl().kind() in _z3_op_to_fpa_pretty_str: return to_format(_z3_op_to_fpa_pretty_str.get(a.decl().kind())) else: - return to_format(a.as_string()) + return to_format(_z3_op_to_fpa_normal_str.get(a.decl().kind())) def pp_fp_value(self, a): z3._z3_assert(isinstance(a, z3.FPNumRef), 'type mismatch') From e5c5c801c725147f8a966b0671dde26c61b96e82 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 14:40:18 +0000 Subject: [PATCH 503/646] fixed botched merge Signed-off-by: Christoph M. Wintersteiger --- src/tactic/portfolio/default_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp index 6419098bc..5a18e0830 100644 --- a/src/tactic/portfolio/default_tactic.cpp +++ b/src/tactic/portfolio/default_tactic.cpp @@ -43,7 +43,7 @@ tactic * mk_default_tactic(ast_manager & m, params_ref const & p) { cond(mk_is_nra_probe(), mk_nra_tactic(m), cond(mk_is_lira_probe(), mk_lira_tactic(m, p), cond(mk_is_qffp_probe(), mk_qffp_tactic(m, p), - mk_smt_tactic()))))))))), + mk_smt_tactic()))))))))))), p); return st; } From 74e60fc9558f6eefd77a8911dc3406743ec76974 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 15:01:35 +0000 Subject: [PATCH 504/646] disabled debug output Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 110311c4c..dd0fa76fc 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -3181,7 +3181,7 @@ void fpa2bv_converter::mk_rounding_mode(func_decl * f, expr_ref & result) void fpa2bv_converter::dbg_decouple(const char * prefix, expr_ref & e) { #ifdef Z3DEBUG - // return; + return; // CMW: This works only for quantifier-free formulas. expr_ref new_e(m); new_e = m.mk_fresh_const(prefix, m.get_sort(e)); @@ -3564,4 +3564,4 @@ void fpa2bv_converter::reset(void) { m_uf23bvuf.reset(); m_extra_assertions.reset(); -} \ No newline at end of file +} From 1a6af4385ef2ae1363165e080faf0562a398c3f2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 15:01:50 +0000 Subject: [PATCH 505/646] Fixed C example Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 117 ++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 920fdeb8c..817ada98e 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2605,7 +2605,8 @@ void fpa_example() { Z3_sort double_sort, rm_sort; Z3_symbol s_rm, s_x, s_y, s_x_plus_y; Z3_ast rm, x, y, n, x_plus_y, c1, c2, c3, c4, c5, c6; - + Z3_ast args[2], args2[2], and_args[3], args3[3]; + printf("\nFPA-example\n"); LOG_MSG("FPA-example"); @@ -2616,76 +2617,72 @@ void fpa_example() { double_sort = Z3_mk_fpa_sort(ctx, 11, 53); rm_sort = Z3_mk_fpa_rounding_mode_sort(ctx); - { - // Show that there are x, y s.t. (x + y) = 42.0 (with rounding mode). - s_rm = Z3_mk_string_symbol(ctx, "rm"); - rm = Z3_mk_const(ctx, s_rm, rm_sort); - s_x = Z3_mk_string_symbol(ctx, "x"); - s_y = Z3_mk_string_symbol(ctx, "y"); - x = Z3_mk_const(ctx, s_x, double_sort); - y = Z3_mk_const(ctx, s_y, double_sort); - n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort); + // Show that there are x, y s.t. (x + y) = 42.0 (with rounding mode). + s_rm = Z3_mk_string_symbol(ctx, "rm"); + rm = Z3_mk_const(ctx, s_rm, rm_sort); + s_x = Z3_mk_string_symbol(ctx, "x"); + s_y = Z3_mk_string_symbol(ctx, "y"); + x = Z3_mk_const(ctx, s_x, double_sort); + y = Z3_mk_const(ctx, s_y, double_sort); + n = Z3_mk_fpa_numeral_double(ctx, 42.0, double_sort); - s_x_plus_y = Z3_mk_string_symbol(ctx, "x_plus_y"); - x_plus_y = Z3_mk_const(ctx, s_x_plus_y, double_sort); - c1 = Z3_mk_eq(ctx, x_plus_y, Z3_mk_fpa_add(ctx, rm, x, y)); + s_x_plus_y = Z3_mk_string_symbol(ctx, "x_plus_y"); + x_plus_y = Z3_mk_const(ctx, s_x_plus_y, double_sort); + c1 = Z3_mk_eq(ctx, x_plus_y, Z3_mk_fpa_add(ctx, rm, x, y)); - Z3_ast args[2] = { c1, Z3_mk_eq(ctx, x_plus_y, n) }; - c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args); + args[0] = c1; + args[1] = Z3_mk_eq(ctx, x_plus_y, n); + c2 = Z3_mk_and(ctx, 2, (Z3_ast*)&args); - Z3_ast args2[2] = { c2, Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_rtz(ctx))) }; - c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2); + args2[0] = c2; + args2[1] = Z3_mk_not(ctx, Z3_mk_eq(ctx, rm, Z3_mk_fpa_rtz(ctx))); + c3 = Z3_mk_and(ctx, 2, (Z3_ast*)&args2); - Z3_ast and_args[3] = { - Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)), - Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)), - Z3_mk_not(ctx, Z3_mk_fpa_is_infinite(ctx, y)) }; - Z3_ast args3[2] = { c3, Z3_mk_and(ctx, 3, and_args) }; - c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3); + and_args[0] = Z3_mk_not(ctx, Z3_mk_fpa_is_zero(ctx, y)); + and_args[1] = Z3_mk_not(ctx, Z3_mk_fpa_is_nan(ctx, y)); + and_args[2] = Z3_mk_not(ctx, Z3_mk_fpa_is_infinite(ctx, y)); + args3[0] = c3; + args3[1] = Z3_mk_and(ctx, 3, and_args); + c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3); - printf("c4: %s\n", Z3_ast_to_string(ctx, c4)); - Z3_push(ctx); - Z3_assert_cnstr(ctx, c4); - check(ctx, Z3_L_TRUE); - Z3_pop(ctx, 1); - } + printf("c4: %s\n", Z3_ast_to_string(ctx, c4)); + Z3_push(ctx); + Z3_assert_cnstr(ctx, c4); + check(ctx, Z3_L_TRUE); + Z3_pop(ctx, 1); - - { - // Show that the following are equal: - // (fp #b0 #b10000000001 #xc000000000000) - // ((_ to_fp 11 53) #x401c000000000000)) - // ((_ to_fp 11 53) RTZ 1.75 2))) - // ((_ to_fp 11 53) RTZ 7.0))) - Z3_ast args3[3]; - - Z3_push(ctx); - c1 = Z3_mk_fpa_fp(ctx, - Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)), - Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11)), - Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52))); - c2 = Z3_mk_fpa_to_fp_bv(ctx, - Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), - Z3_mk_fpa_sort(ctx, 11, 53)); - c3 = Z3_mk_fpa_to_fp_real_int(ctx, + // Show that the following are equal: + // (fp #b0 #b10000000001 #xc000000000000) + // ((_ to_fp 11 53) #x401c000000000000)) + // ((_ to_fp 11 53) RTZ 1.75 2))) + // ((_ to_fp 11 53) RTZ 7.0))) + + Z3_push(ctx); + c1 = Z3_mk_fpa_fp(ctx, + Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)), + Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)), + Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11))); + c2 = Z3_mk_fpa_to_fp_bv(ctx, + Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), + Z3_mk_fpa_sort(ctx, 11, 53)); + c3 = Z3_mk_fpa_to_fp_real_int(ctx, Z3_mk_fpa_rtz(ctx), Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), Z3_mk_fpa_sort(ctx, 11, 53)); - c4 = Z3_mk_fpa_to_fp_real(ctx, - Z3_mk_fpa_rtz(ctx), - Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)), - Z3_mk_fpa_sort(ctx, 11, 53)); - args3[0] = Z3_mk_eq(ctx, c1, c2); - args3[1] = Z3_mk_eq(ctx, c1, c3); - args3[2] = Z3_mk_eq(ctx, c1, c4); - c5 = Z3_mk_and(ctx, 3, args3); + c4 = Z3_mk_fpa_to_fp_real(ctx, + Z3_mk_fpa_rtz(ctx), + Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)), + Z3_mk_fpa_sort(ctx, 11, 53)); + args3[0] = Z3_mk_eq(ctx, c1, c2); + args3[1] = Z3_mk_eq(ctx, c1, c3); + args3[2] = Z3_mk_eq(ctx, c1, c4); + c5 = Z3_mk_and(ctx, 3, args3); - printf("c5: %s\n", Z3_ast_to_string(ctx, c5)); - Z3_assert_cnstr(ctx, c5); - check(ctx, Z3_L_TRUE); - Z3_pop(ctx, 1); - } + printf("c5: %s\n", Z3_ast_to_string(ctx, c5)); + Z3_assert_cnstr(ctx, c5); + check(ctx, Z3_L_TRUE); + Z3_pop(ctx, 1); Z3_del_context(ctx); } From 9a53fe43e6ee3d22366e515526cdccfc166d6cd9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 15:31:12 +0000 Subject: [PATCH 506/646] Removed unnecessary #includes Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index c0c319ab4..162866ed6 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,9 +16,6 @@ Author: Notes: --*/ -#include -#include - #include"map.h" #include"ast_smt2_pp.h" #include"ast_pp.h" @@ -575,7 +572,7 @@ lbool sls_engine::operator()() { } } while (res != l_true && m_stats.m_restarts++ < m_max_restarts); - verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; + verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl; return res; } From 1209302fe6c2d5fc1205f4f7b2bb5880f801e5d5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 15:34:21 +0000 Subject: [PATCH 507/646] Fixed integration issues Signed-off-by: Christoph M. Wintersteiger --- src/muz/duality/duality_dl_interface.cpp | 2 +- src/qe/nlarith_util.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 0ab9762b0..aa186bd0a 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -82,7 +82,7 @@ namespace Duality { if(rpfp) dealloc(rpfp); if(ls) - (ls); + dealloc(ls); } }; diff --git a/src/qe/nlarith_util.cpp b/src/qe/nlarith_util.cpp index fce54aaa4..c555b71f1 100644 --- a/src/qe/nlarith_util.cpp +++ b/src/qe/nlarith_util.cpp @@ -1492,11 +1492,11 @@ namespace nlarith { } fml = mk_and(equivs.size(), equivs.c_ptr()); } - void mk_pinf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { + void mk_plus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { plus_inf_subst sub(*this); mk_inf_sign(sub, literals, fml, new_atoms); } - void mk_ninf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { + void mk_minus_inf_sign(util::literal_set const& literals, app_ref& fml, app_ref_vector& new_atoms) { minus_inf_subst sub(*this); mk_inf_sign(sub, literals, fml, new_atoms); } @@ -1704,10 +1704,10 @@ namespace nlarith { app_ref fml(m()); app_ref_vector new_atoms(m()); if (is_pos) { - mk_pinf_sign(literals, fml, new_atoms); + mk_plus_inf_sign(literals, fml, new_atoms); } else { - mk_ninf_sign(literals, fml, new_atoms); + mk_minus_inf_sign(literals, fml, new_atoms); } simple_branch* br = alloc(simple_branch, m(), fml); swap_atoms(br, literals.lits(), new_atoms); From 2cb84280d811229ec60418eed5de0b08c903d09a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 17:58:31 +0000 Subject: [PATCH 508/646] Final adjustments for the FP integration Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 4 +- doc/mk_api_doc.py | 2 + doc/z3api.dox | 33 +--- src/api/java/Context.java | 23 +-- src/api/java/Fixedpoint.java | 2 +- src/api/z3_api.h | 2 +- src/api/z3_fpa.h | 342 ++++++++++++++++++----------------- 7 files changed, 192 insertions(+), 216 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index f185983a3..f8cac4c8b 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,11 +3,13 @@ RELEASE NOTES Version 4.4 ============= +- New feature: Support for the theory of floating-point numbers. This comes in the form of logics (QF_FP and QF_FPBV), tactics (qffp and qffpbv), as well as a theory plugin that allows theory combinations. Z3 supports the official SMT theory definition of FP (see http://smtlib.cs.uiowa.edu/theories/FloatingPoint.smt2) in SMT2 files, as well as all APIs. + - New feature: Stochastic local search engine for bit-vector formulas (see the qfbv-sls tactic). See also: Froehlich, Biere, Wintersteiger, Hamadi: Stochastic Local Search for Satisfiability Modulo Theories, AAAI 2015. -- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, and Codeplex users rsas, clockish, Heizmann. +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, and Codeplex users rsas, clockish, Heizmann. Version 4.3.2 ============= diff --git a/doc/mk_api_doc.py b/doc/mk_api_doc.py index 633f96c6b..476f2c8c7 100644 --- a/doc/mk_api_doc.py +++ b/doc/mk_api_doc.py @@ -31,6 +31,7 @@ try: cleanup_API('../src/api/z3_polynomial.h', 'tmp/z3_polynomial.h') cleanup_API('../src/api/z3_rcf.h', 'tmp/z3_rcf.h') cleanup_API('../src/api/z3_interp.h', 'tmp/z3_interp.h') + cleanup_API('../src/api/z3_fpa.h', 'tmp/z3_fpa.h') print "Removed annotations from z3_api.h." try: @@ -46,6 +47,7 @@ try: os.remove('tmp/z3_polynomial.h') os.remove('tmp/z3_rcf.h') os.remove('tmp/z3_interp.h') + os.remove('tmp/z3_fpa.h') print "Removed temporary file z3_api.h." os.remove('tmp/website.dox') print "Removed temporary file website.dox" diff --git a/doc/z3api.dox b/doc/z3api.dox index dbaa3c8b8..cb4569dc4 100644 --- a/doc/z3api.dox +++ b/doc/z3api.dox @@ -713,39 +713,10 @@ FILE_PATTERNS = website.dox \ z3_polynomial.h \ z3_rcf.h \ z3_interp.h \ + z3_fpa.h \ z3++.h \ z3py.py \ - ApplyResult.cs \ - AST.cs \ - ASTMap.cs \ - ASTVector.cs \ - Config.cs \ - Constructor.cs \ - Context.cs \ - DecRefQUeue.cs \ - Enumerations.cs \ - Expr.cs \ - FuncDecl.cs \ - FuncInterp.cs \ - Goal.cs \ - Log.cs \ - Model.cs \ - Native.cs \ - Numeral.cs \ - Params.cs \ - Pattern.cs \ - Probe.cs \ - Quantifier.cs \ - Solver.cs \ - Sort.cs \ - Statistics.cs \ - Status.cs \ - Symbol.cs \ - Tactic.cs \ - Util.cs \ - Version.cs \ - Z3Exception.cs \ - Z3Object.cs \ + *.cs \ *.java # The RECURSIVE tag can be used to turn specify whether or not subdirectories diff --git a/src/api/java/Context.java b/src/api/java/Context.java index f7fa471fb..26a54b9c6 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -2000,25 +2000,22 @@ public class Context extends IDisposable /** * Create a universal Quantifier. + * @param sorts the sorts of the bound variables. + * @param names names of the bound variables + * @param body the body of the quantifier. + * @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + * @param patterns array containing the patterns created using {@code MkPattern}. + * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. + * @param quantifierID optional symbol to track quantifier. + * @param skolemID optional symbol to track skolem constants. + * * Remarks: Creates a forall formula, where * {@code weight"/> is the weight, Date: Wed, 21 Jan 2015 18:24:36 +0000 Subject: [PATCH 509/646] fixed build errors and warnings Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 19 ++++++++----------- src/ast/rewriter/fpa_rewriter.cpp | 4 +--- src/ast/simplifier/fpa_simplifier_plugin.cpp | 4 ---- src/ast/simplifier/fpa_simplifier_plugin.h | 1 - src/util/mpf.cpp | 1 - 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index dd0fa76fc..f8f283ee6 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -16,7 +16,8 @@ Author: Notes: --*/ -#include +#include + #include"ast_smt2_pp.h" #include"well_sorted.h" #include"th_rewriter.h" @@ -688,8 +689,7 @@ void fpa2bv_converter::mk_mul(func_decl * f, unsigned num, expr * const * args, m_simp.mk_xor(x_is_pos, y_is_pos, sign_xor); mk_ite(sign_xor, nzero, pzero, v6); - // else comes the actual multiplication. - unsigned ebits = m_util.get_ebits(f->get_range()); + // else comes the actual multiplication. unsigned sbits = m_util.get_sbits(f->get_range()); expr_ref a_sgn(m), a_sig(m), a_exp(m), a_lz(m), b_sgn(m), b_sig(m), b_exp(m), b_lz(m); @@ -2037,7 +2037,8 @@ void fpa2bv_converter::mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr * dbg_decouple("fpa2bv_to_float_res_exp", res_exp); expr_ref rounded(m); - round(s, expr_ref (rm, m), res_sgn, res_sig, res_exp, rounded); + expr_ref rm_e(rm, m); + round(s, rm_e, res_sgn, res_sig, res_exp, rounded); expr_ref is_neg(m), sig_inf(m); m_simp.mk_eq(sgn, one1, is_neg); @@ -2098,7 +2099,6 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * mk_fp(sgn, e, s, result); } else { - mpf_manager & fm = fu().fm(); bv_util & bu = m_bv_util; arith_util & au = m_arith_util; @@ -2333,7 +2333,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const expr_ref sig_rest(m); sig_4 = m_bv_util.mk_extract(bv_sz - 1, bv_sz - sig_sz + 1, shifted_sig); // one short sig_rest = m_bv_util.mk_extract(bv_sz - sig_sz, 0, shifted_sig); - sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest); + sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest.get()); sig_4 = m_bv_util.mk_concat(sig_4, sticky); } else { @@ -2496,7 +2496,7 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits. // exp < bv_sz (+sign bit which is [0]) - unsigned exp_worst_case_sz = (unsigned)((log((double)bv_sz) / log((double)2)) + 1.0); + unsigned exp_worst_case_sz = (unsigned)((log((double)bv_sz) / log((double)2)) + 1.0); if (exp_sz < exp_worst_case_sz) { // exp_sz < exp_worst_case_sz and exp >= 0. @@ -2558,7 +2558,6 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg unsigned ebits = m_util.get_ebits(xs); unsigned sbits = m_util.get_sbits(xs); unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); - unsigned rounding_sz = bv_sz + 3; expr_ref bv0(m), bv1(m); bv0 = m_bv_util.mk_numeral(0, 1); @@ -2575,7 +2574,6 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg expr_ref c1(m), v1(m); c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero))); v1 = mk_to_ubv_unspecified(bv_sz); - dbg_decouple("fpa2bv_to_ubv_c1", c1); // +-Zero -> 0 expr_ref c2(m), v2(m); @@ -2682,8 +2680,7 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg unsigned ebits = m_util.get_ebits(xs); unsigned sbits = m_util.get_sbits(xs); - unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); - unsigned rounding_sz = bv_sz + 3; + unsigned bv_sz = (unsigned)f->get_parameter(0).get_int(); expr_ref bv0(m), bv1(m), bv0_2(m), bv1_2(m), bv3_2(m); bv0 = m_bv_util.mk_numeral(0, 1); diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index ce7fe5ed6..9a8ab7da0 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -160,9 +160,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); - SASSERT(f->get_parameter(1).is_int()); - unsigned ebits = f->get_parameter(0).get_int(); - unsigned sbits = f->get_parameter(1).get_int(); + SASSERT(f->get_parameter(1).is_int()); return BR_FAILED; } diff --git a/src/ast/simplifier/fpa_simplifier_plugin.cpp b/src/ast/simplifier/fpa_simplifier_plugin.cpp index d2f7a3e58..4aba9c76c 100644 --- a/src/ast/simplifier/fpa_simplifier_plugin.cpp +++ b/src/ast/simplifier/fpa_simplifier_plugin.cpp @@ -19,7 +19,6 @@ Author: fpa_simplifier_plugin::fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b) : simplifier_plugin(symbol("fpa"), m), m_util(m), -m_bsimp(b), m_rw(m) {} fpa_simplifier_plugin::~fpa_simplifier_plugin() {} @@ -28,9 +27,6 @@ bool fpa_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * cons set_reduce_invoked(); SASSERT(f->get_family_id() == get_family_id()); - /*switch (f->get_decl_kind()) { - case OP_FPA_FP: break; - }*/ return m_rw.mk_app_core(f, num_args, args, result) == BR_DONE; } diff --git a/src/ast/simplifier/fpa_simplifier_plugin.h b/src/ast/simplifier/fpa_simplifier_plugin.h index 36e315737..13a235091 100644 --- a/src/ast/simplifier/fpa_simplifier_plugin.h +++ b/src/ast/simplifier/fpa_simplifier_plugin.h @@ -23,7 +23,6 @@ Author: class fpa_simplifier_plugin : public simplifier_plugin { fpa_util m_util; - basic_simplifier_plugin & m_bsimp; fpa_rewriter m_rw; public: diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index acf6eae39..de4107746 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -203,7 +203,6 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode m_mpq_manager.abs(x); m_mpz_manager.set(o.significand, 0); - const mpz & p = m_powers2(sbits+3); scoped_mpq v(m_mpq_manager); m_mpq_manager.set(v, x); From b6a7d600430642fb3b9b0b9b121af4cdb5868cef Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:09:22 +0000 Subject: [PATCH 510/646] Added FPA functions to Java API Signed-off-by: Christoph M. Wintersteiger --- src/api/java/Context.java | 780 +++++++++++++++++++++++++++++++++++++- src/api/java/FPNum.java | 2 - 2 files changed, 776 insertions(+), 6 deletions(-) diff --git a/src/api/java/Context.java b/src/api/java/Context.java index f7fa471fb..46a76f50f 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -85,7 +85,7 @@ public class Context extends IDisposable /** * Create an array of symbols. **/ - Symbol[] MkSymbols(String[] names) throws Z3Exception + Symbol[] mkSymbols(String[] names) throws Z3Exception { if (names == null) return null; @@ -218,7 +218,7 @@ public class Context extends IDisposable public EnumSort mkEnumSort(String name, String... enumNames) throws Z3Exception { - return new EnumSort(this, mkSymbol(name), MkSymbols(enumNames)); + return new EnumSort(this, mkSymbol(name), mkSymbols(enumNames)); } /** @@ -295,7 +295,7 @@ public class Context extends IDisposable { return new Constructor(this, mkSymbol(name), mkSymbol(recognizer), - MkSymbols(fieldNames), sorts, sortRefs); + mkSymbols(fieldNames), sorts, sortRefs); } /** @@ -358,7 +358,7 @@ public class Context extends IDisposable public DatatypeSort[] mkDatatypeSorts(String[] names, Constructor[][] c) throws Z3Exception { - return mkDatatypeSorts(MkSymbols(names), c); + return mkDatatypeSorts(mkSymbols(names), c); } /** @@ -2789,6 +2789,778 @@ public class Context extends IDisposable return new Fixedpoint(this); } + + /** + * Create the floating-point RoundingMode sort. + * @throws Z3Exception + **/ + public FPRMSort mkFPRoundingModeSort() throws Z3Exception + { + return new FPRMSort(this); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. + * @throws Z3Exception + **/ + public FPRMExpr mkFPRoundNearestTiesToEven() throws Z3Exception + { + return new FPRMExpr(this, Native.mkFpaRoundNearestTiesToEven(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRNE() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRne(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundNearestTiesToAway() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundNearestTiesToAway(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRNA() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRna(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardPositive() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardPositive(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTP() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtp(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardNegative() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardNegative(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTN() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtn(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRoundTowardZero() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRoundTowardZero(nCtx())); + } + + /** + * Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. + * @throws Z3Exception + **/ + public FPRMNum mkFPRTZ() throws Z3Exception + { + return new FPRMNum(this, Native.mkFpaRtz(nCtx())); + } + + /** + * Create a FloatingPoint sort. + * @param ebits exponent bits in the FloatingPoint sort. + * @param sbits significand bits in the FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort(int ebits, int sbits) throws Z3Exception + { + return new FPSort(this, ebits, sbits); + } + + /** + * Create the half-precision (16-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortHalf() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortHalf(nCtx())); + } + + /** + * Create the half-precision (16-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort16() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort16(nCtx())); + } + + /** + * Create the single-precision (32-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortSingle() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortSingle(nCtx())); + } + + /** + * Create the single-precision (32-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort32() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort32(nCtx())); + } + + /** + * Create the double-precision (64-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortDouble() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortDouble(nCtx())); + } + + /** + * Create the double-precision (64-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort64() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort64(nCtx())); + } + + /** + * Create the quadruple-precision (128-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSortQuadruple() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSortQuadruple(nCtx())); + } + + /** + * Create the quadruple-precision (128-bit) FloatingPoint sort. + * @throws Z3Exception + **/ + public FPSort mkFPSort128() throws Z3Exception + { + return new FPSort(this, Native.mkFpaSort128(nCtx())); + } + + + /** + * Create a NaN of sort s. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNaN(FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNan(nCtx(), s.getNativeObject())); + } + + /** + * Create a floating-point infinity of sort s. + * @param s FloatingPoint sort. + * @param negative indicates whether the result should be negative. + * @throws Z3Exception + **/ + public FPNum mkFPInf(FPSort s, boolean negative) throws Z3Exception + { + return new FPNum(this, Native.mkFpaInf(nCtx(), s.getNativeObject(), negative)); + } + + /** + * Create a floating-point zero of sort s. + * @param s FloatingPoint sort. + * @param negative indicates whether the result should be negative. + * @throws Z3Exception + **/ + public FPNum mkFPZero(FPSort s, boolean negative) throws Z3Exception + { + return new FPNum(this, Native.mkFpaZero(nCtx(), s.getNativeObject(), negative)); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(float v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralFloat(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(double v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralDouble(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from an int. + * * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(int v, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralInt(nCtx(), v, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(boolean sgn, int sig, int exp, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralUintInt(nCtx(), sgn, sig, exp, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + * @param sgn the sign. + * @param sig the significand. + * @param exp the exponent. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFPNumeral(boolean sgn, long sig, long exp, FPSort s) throws Z3Exception + { + return new FPNum(this, Native.mkFpaNumeralUint64Int64(nCtx(), sgn, sig, exp, s.getNativeObject())); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(float v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from a float. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(double v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from an int. + * @param v numeral value. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + + public FPNum mkFP(int v, FPSort s) throws Z3Exception + { + return mkFPNumeral(v, s); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two integers. + * @param sgn the sign. + * @param exp the exponent. + * @param sig the significand. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(boolean sgn, int exp, int sig, FPSort s) throws Z3Exception + { + return mkFPNumeral(sgn, sig, exp, s); + } + + /** + * Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. + * @param sgn the sign. + * @param exp the exponent. + * @param sig the significand. + * @param s FloatingPoint sort. + * @throws Z3Exception + **/ + public FPNum mkFP(boolean sgn, long exp, long sig, FPSort s) throws Z3Exception + { + return mkFPNumeral(sgn, sig, exp, s); + } + + + /** + * Floating-point absolute value + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPAbs(FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaAbs(nCtx(), t.getNativeObject())); + } + + /** + * Floating-point negation + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPNeg(FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaNeg(nCtx(), t.getNativeObject())); + } + + /** + * Floating-point addition + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaAdd(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point subtraction + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaSub(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point multiplication + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMul(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point division + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaDiv(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point fused multiply-add + * @param rm rounding mode term + * @param t1 floating-point term + * @param t2 floating-point term + * @param t3">floating-point term + * Remarks: + * The result is round((t1 * t2) + t3) + * @throws Z3Exception + **/ + public FPExpr mkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaFma(nCtx(), rm.getNativeObject(), t1.getNativeObject(), t2.getNativeObject(), t3.getNativeObject())); + } + + /** + * Floating-point square root + * @param rm rounding mode term + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPSqrt(FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaSqrt(nCtx(), rm.getNativeObject(), t.getNativeObject())); + } + + /** + * Floating-point remainder + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPRem(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaRem(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point roundToIntegral. Rounds a floating-point number to + * the closest integer, again represented as a floating-point number. + * @param rm">term of RoundingMode sort + * @param t floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPRoundToIntegral(FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaRoundToIntegral(nCtx(), rm.getNativeObject(), t.getNativeObject())); + } + + /** + * Minimum of floating-point numbers. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMin(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMin(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Maximum of floating-point numbers. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public FPExpr mkFPMax(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaMax(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point less than or equal. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPLEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaLeq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point less than. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPLt(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaLt(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point greater than or equal. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPGEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaGeq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point greater than. + * @param t1 floating-point term + * @param t2 floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPGt(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaGt(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Floating-point equality. + * @param t1 floating-point term + * @param t2 floating-point term + * Remarks: + * Note that this is IEEE 754 equality (as opposed to standard =). + * @throws Z3Exception + **/ + public BoolExpr mkFPEq(FPExpr t1, FPExpr t2) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaEq(nCtx(), t1.getNativeObject(), t2.getNativeObject())); + } + + /** + * Predicate indicating whether t is a normal floating-point number.\ + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNormal(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsNormal(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a subnormal floating-point number.\ + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsSubnormal(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsSubnormal(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a floating-point number with zero value, i.e., +0 or -0. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsZero(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsZero(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a floating-point number representing +oo or -oo. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsInfinite(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsInfinite(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a NaN. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNaN(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsNan(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a negative floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsNegative(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsNegative(nCtx(), t.getNativeObject())); + } + + /** + * Predicate indicating whether t is a positive floating-point number. + * @param t floating-point term + * @throws Z3Exception + **/ + public BoolExpr mkFPIsPositive(FPExpr t) throws Z3Exception + { + return new BoolExpr(this, Native.mkFpaIsPositive(nCtx(), t.getNativeObject())); + } + + /** + * Create an expression of FloatingPoint sort from three bit-vector expressions. + * @param sgn bit-vector term (of size 1) representing the sign. + * @param sig bit-vector term representing the significand. + * @param exp bit-vector term representing the exponent. + * Remarks: + * This is the operator named `fp' in the SMT FP theory definition. + * Note that sgn is required to be a bit-vector of size 1. Significand and exponent + * are required to be greater than 1 and 2 respectively. The FloatingPoint sort + * of the resulting expression is automatically determined from the bit-vector sizes + * of the arguments. + * @throws Z3Exception + **/ + public FPExpr mkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaFp(nCtx(), sgn.getNativeObject(), sig.getNativeObject(), exp.getNativeObject())); + } + + /** + * Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. + * @param bv">bit-vector value (of size m). + * @param s FloatingPoint sort (ebits+sbits == m) + * Remarks: + * Produces a term that represents the conversion of a bit-vector term bv to a + * floating-point term of sort s. The bit-vector size of bv (m) must be equal + * to ebits+sbits of s. The format of the bit-vector is as defined by the + * IEEE 754-2008 interchange format. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(BitVecExpr bv, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpBv(nCtx(), bv.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a FloatingPoint term into another term of different FloatingPoint sort. + * @param rm RoundingMode term. + * @param t FloatingPoint term. + * @param s FloatingPoint sort. + * Remarks: + * Produces a term that represents the conversion of a floating-point term t to a + * floating-point term of sort s. If necessary, the result will be rounded according + * to rounding mode rm. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, FPExpr t, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpFloat(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a term of real sort into a term of FloatingPoint sort. + * @param rm RoundingMode term. + * @param t term of Real sort. + * @param s FloatingPoint sort. + * Remarks: + * Produces a term that represents the conversion of term t of real sort into a + * floating-point term of sort s. If necessary, the result will be rounded according + * to rounding mode rm. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, RealExpr t, FPSort s) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpReal(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. + * @param rm RoundingMode term. + * @param t term of bit-vector sort. + * @param s FloatingPoint sort. + * @param signed flag indicating whether t is interpreted as signed or unsigned bit-vector. + * Remarks: + * Produces a term that represents the conversion of the bit-vector term t into a + * floating-point term of sort s. The bit-vector t is taken to be in signed + * 2's complement format (when signed==true, otherwise unsigned). If necessary, the + * result will be rounded according to rounding mode rm. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, boolean signed) throws Z3Exception + { + if (signed) + return new FPExpr(this, Native.mkFpaToFpSigned(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + else + return new FPExpr(this, Native.mkFpaToFpUnsigned(nCtx(), rm.getNativeObject(), t.getNativeObject(), s.getNativeObject())); + } + + /** + * Conversion of a floating-point number to another FloatingPoint sort s. + * @param s FloatingPoint sort + * @param rm floating-point rounding mode term + * @param t floating-point term + * Remarks: + * Produces a term that represents the conversion of a floating-point term t to a different + * FloatingPoint sort s. If necessary, rounding according to rm is applied. + * @throws Z3Exception + **/ + public FPExpr mkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) throws Z3Exception + { + return new FPExpr(this, Native.mkFpaToFpFloat(nCtx(), s.getNativeObject(), rm.getNativeObject(), t.getNativeObject())); + } + + /** + * Conversion of a floating-point term into a bit-vector. + * @param rm RoundingMode term. + * @param t FloatingPoint term + * @param sz Size of the resulting bit-vector. + * @param signed Indicates whether the result is a signed or unsigned bit-vector. + * Remarks: + * Produces a term that represents the conversion of the floating-poiunt term t into a + * bit-vector term of size sz in 2's complement format (signed when signed==true). If necessary, + * the result will be rounded according to rounding mode rm. + * @throws Z3Exception + **/ + public BitVecExpr mkFPToBV(FPRMExpr rm, FPExpr t, int sz, boolean signed) throws Z3Exception + { + if (signed) + return new BitVecExpr(this, Native.mkFpaToSbv(nCtx(), rm.getNativeObject(), t.getNativeObject(), sz)); + else + return new BitVecExpr(this, Native.mkFpaToUbv(nCtx(), rm.getNativeObject(), t.getNativeObject(), sz)); + } + + /** + * Conversion of a floating-point term into a real-numbered term. + * @param t FloatingPoint term + * Remarks: + * Produces a term that represents the conversion of the floating-poiunt term t into a + * real number. Note that this type of conversion will often result in non-linear + * constraints over real terms. + * @throws Z3Exception + **/ + public RealExpr mkFPToReal(FPExpr t) throws Z3Exception + { + return new RealExpr(this, Native.mkFpaToReal(nCtx(), t.getNativeObject())); + } + + /** + * Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. + * @param t FloatingPoint term. + * Remarks: + * The size of the resulting bit-vector is automatically determined. Note that + * IEEE 754-2008 allows multiple different representations of NaN. This conversion + * knows only one NaN and it will always produce the same bit-vector represenatation of + * that NaN. + * @throws Z3Exception + **/ + public BitVecExpr mkFPToIEEEBV(FPExpr t) throws Z3Exception + { + return new BitVecExpr(this, Native.mkFpaToIeeeBv(nCtx(), t.getNativeObject())); + } + + /** + * Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. + * @param rm RoundingMode term. + * @param sig Significand term of Real sort. + * @param exp Exponent term of Int sort. + * @param s FloatingPoint sort. + * Remarks: + * Produces a term that represents the conversion of sig * 2^exp into a + * floating-point term of sort s. If necessary, the result will be rounded + * according to rounding mode rm. + * @throws Z3Exception + **/ + + public BitVecExpr mkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s) throws Z3Exception + { + return new BitVecExpr(this, Native.mkFpaToFpRealInt(nCtx(), rm.getNativeObject(), sig.getNativeObject(), exp.getNativeObject(), s.getNativeObject())); + } + + /** * Wraps an AST. * Remarks: This function is used for transitions between diff --git a/src/api/java/FPNum.java b/src/api/java/FPNum.java index f2c9b7f98..037fe63a4 100644 --- a/src/api/java/FPNum.java +++ b/src/api/java/FPNum.java @@ -31,8 +31,6 @@ public class FPNum extends FPExpr if (Native.fpaGetNumeralSign(getContext().nCtx(), getNativeObject(), res) ^ true) throw new Z3Exception("Sign is not a Boolean value"); return res.value != 0; - - } /** From 84ed1c19a077a3ef607b427062fa12b26fa80632 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:20:43 +0000 Subject: [PATCH 511/646] Bugfixes for the Java FPA API Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable Signed-off-by: Christoph M. Wintersteiger --- src/api/java/AST.java | 12 ++++-------- src/api/java/Expr.java | 8 ++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 30d303d6c..0cdfd025c 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -227,10 +227,8 @@ public class AST extends Z3Object void incRef(long o) throws Z3Exception { // Console.WriteLine("AST IncRef()"); - if (getContext() == null) - throw new Z3Exception("inc() called on null context"); - if (o == 0) - throw new Z3Exception("inc() called on null AST"); + if (getContext() == null || o == 0) + return; getContext().ast_DRQ().incAndClear(getContext(), o); super.incRef(o); } @@ -238,10 +236,8 @@ public class AST extends Z3Object void decRef(long o) throws Z3Exception { // Console.WriteLine("AST DecRef()"); - if (getContext() == null) - throw new Z3Exception("dec() called on null context"); - if (o == 0) - throw new Z3Exception("dec() called on null AST"); + if (getContext() == null || o == 0) + return; getContext().ast_DRQ().add(o); super.decRef(o); } diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index f94eb12cb..762a4b672 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -2161,6 +2161,10 @@ public class Expr extends AST return new RatNum(ctx, obj); case Z3_BV_SORT: return new BitVecNum(ctx, obj); + case Z3_FLOATING_POINT_SORT: + return new FPNum(ctx, obj); + case Z3_ROUNDING_MODE_SORT: + return new FPRMNum(ctx, obj); default: ; } } @@ -2179,6 +2183,10 @@ public class Expr extends AST return new ArrayExpr(ctx, obj); case Z3_DATATYPE_SORT: return new DatatypeExpr(ctx, obj); + case Z3_FLOATING_POINT_SORT: + return new FPExpr(ctx, obj); + case Z3_ROUNDING_MODE_SORT: + return new FPRMExpr(ctx, obj); default: ; } From 826d2959813cfc97ebe6285159b83fd2f9c184b6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:29:31 +0000 Subject: [PATCH 512/646] build fixes and removed unused variables --- src/api/api_fpa.cpp | 4 +--- src/ast/fpa/fpa2bv_converter.cpp | 2 -- src/smt/theory_fpa.h | 4 ++-- src/tactic/sls/sls_engine.cpp | 2 ++ 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 67ffe12d9..96c3e2eb6 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -723,8 +723,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_exponent_string(c, t); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); @@ -749,7 +748,6 @@ extern "C" { RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index f8f283ee6..9f0591134 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2283,7 +2283,6 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); - unsigned f_sz = sbits + ebits; unsigned bv_sz = m_bv_util.get_bv_size(x); SASSERT(m_bv_util.get_bv_size(rm) == 3); @@ -2425,7 +2424,6 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con unsigned ebits = m_util.get_ebits(f->get_range()); unsigned sbits = m_util.get_sbits(f->get_range()); - unsigned f_sz = sbits + ebits; unsigned bv_sz = m_bv_util.get_bv_size(x); SASSERT(m_bv_util.get_bv_size(rm) == 3); diff --git a/src/smt/theory_fpa.h b/src/smt/theory_fpa.h index 33733d7d9..c3d574179 100644 --- a/src/smt/theory_fpa.h +++ b/src/smt/theory_fpa.h @@ -97,7 +97,7 @@ namespace smt { public: fpa_value_proc(theory_fpa * th, unsigned ebits, unsigned sbits) : - m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()), + m_th(*th), m(th->get_manager()), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m_ebits(ebits), m_sbits(sbits) {} virtual ~fpa_value_proc() {} @@ -120,7 +120,7 @@ namespace smt { public: fpa_rm_value_proc(theory_fpa * th) : - m_th(*th), m_fu(th->m_fpa_util), m_bu(th->m_bv_util), m(th->get_manager()) {} + m_th(*th), m(th->get_manager()), m_fu(th->m_fpa_util), m_bu(th->m_bv_util) {} void add_dependency(enode * e) { m_deps.push_back(model_value_dependency(e)); } diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 162866ed6..98f659fe0 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -16,6 +16,8 @@ Author: Notes: --*/ +#include // Need DBL_MAX + #include"map.h" #include"ast_smt2_pp.h" #include"ast_pp.h" From 25011bc034164432c5c30b06632416398524242d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:35:29 +0000 Subject: [PATCH 513/646] eliminated unused variables --- src/smt/theory_fpa.cpp | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index ac9bd5141..e76594ded 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -153,9 +153,9 @@ namespace smt { r = m_bu.is_numeral(values[2], sig_r, bv_sz); SASSERT(r && bv_sz == m_sbits - 1); - SASSERT(sgn_r.to_mpq().denominator() == mpz(1)); - SASSERT(exp_r.to_mpq().denominator() == mpz(1)); - SASSERT(sig_r.to_mpq().denominator() == mpz(1)); + SASSERT(mpzm.is_one(sgn_r.to_mpq().denominator())); + SASSERT(mpzm.is_one(exp_r.to_mpq().denominator())); + SASSERT(mpzm.is_one(sig_r.to_mpq().denominator())); mpzm.set(sgn_z, sgn_r.to_mpq().numerator()); mpzm.set(exp_z, exp_r.to_mpq().numerator()); @@ -187,8 +187,7 @@ namespace smt { TRACE("t_fpa_detail", for (unsigned i = 0; i < values.size(); i++) tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;); - app * result = 0; - sort * s = m.get_sort(values[0]); + app * result = 0; unsigned bv_sz; rational val(0); @@ -215,7 +214,6 @@ namespace smt { app_ref theory_fpa::wrap(expr * e) { SASSERT(!m_fpa_util.is_wrap(e)); ast_manager & m = get_manager(); - context & ctx = get_context(); sort * e_srt = m.get_sort(e); func_decl *w; @@ -245,8 +243,7 @@ namespace smt { app_ref theory_fpa::unwrap(expr * e, sort * s) { SASSERT(!m_fpa_util.is_unwrap(e)); - ast_manager & m = get_manager(); - context & ctx = get_context(); + ast_manager & m = get_manager(); sort * bv_srt = m.get_sort(e); func_decl *u; @@ -276,8 +273,7 @@ namespace smt { expr_ref theory_fpa::convert_term(expr * e) { ast_manager & m = get_manager(); - - context & ctx = get_context(); + expr_ref e_conv(m), res(m); proof_ref pr(m); m_rw(e, e_conv); @@ -304,8 +300,7 @@ namespace smt { expr_ref theory_fpa::convert_conversion_term(expr * e) { /* This is for the conversion functions fp.to_* */ - ast_manager & m = get_manager(); - context & ctx = get_context(); + ast_manager & m = get_manager(); expr_ref res(m); proof_ref pr(m); @@ -326,7 +321,6 @@ namespace smt { } else { SASSERT(m_fpa_util.is_float(srt)); - unsigned ebits = m_fpa_util.get_ebits(srt); unsigned sbits = m_fpa_util.get_sbits(srt); expr_ref bv(m); bv = to_app(e)->get_arg(0); @@ -342,7 +336,6 @@ namespace smt { expr_ref theory_fpa::convert(expr * e) { ast_manager & m = get_manager(); - context & ctx = get_context(); expr_ref res(m); if (m_conversions.contains(e)) { @@ -524,10 +517,7 @@ namespace smt { TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " = " << mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); - context & ctx = get_context(); fpa_util & fu = m_fpa_util; - bv_util & bu = m_bv_util; - mpf_manager & mpfm = fu.fm(); expr_ref xe(m), ye(m); xe = get_enode(x)->get_owner(); @@ -575,9 +565,6 @@ namespace smt { TRACE("t_fpa_detail", tout << mk_ismt2_pp(get_enode(x)->get_owner(), m) << " != " << mk_ismt2_pp(get_enode(y)->get_owner(), m) << std::endl;); - context & ctx = get_context(); - mpf_manager & mpfm = m_fpa_util.fm(); - expr_ref xe(m), ye(m); xe = get_enode(x)->get_owner(); ye = get_enode(y)->get_owner(); @@ -588,13 +575,15 @@ namespace smt { return; } + fpa_util & fu = m_fpa_util; + expr_ref xc(m), yc(m); xc = convert(xe); yc = convert(ye); expr_ref c(m); - if (m_fpa_util.is_float(xe) && m_fpa_util.is_float(ye)) + if (fu.is_float(xe) && fu.is_float(ye)) { expr *x_sgn, *x_sig, *x_exp; m_converter.split_fp(xc, x_sgn, x_exp, x_sig); @@ -645,12 +634,9 @@ namespace smt { ast_manager & m = get_manager(); TRACE("t_fpa", tout << "relevant_eh for: " << mk_ismt2_pp(n, m) << "\n";); - mpf_manager & mpfm = m_fpa_util.fm(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); + mpf_manager & mpfm = m_fpa_util.fm(); if (m_fpa_util.is_float(n) || m_fpa_util.is_rm(n)) { - sort * s = m.get_sort(n); - if (!m_fpa_util.is_unwrap(n)) { expr_ref wrapped(m), c(m); wrapped = wrap(n); @@ -661,7 +647,6 @@ namespace smt { assert_cnstr(c); } else if (m_fpa_util.is_numeral(n, val)) { - unsigned sz = val.get().get_ebits() + val.get().get_sbits(); expr_ref bv_val_e(m); bv_val_e = convert(n); SASSERT(is_app(bv_val_e)); From 560fa79d1ff217326e7c63fce7eda69729691539 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:36:41 +0000 Subject: [PATCH 514/646] eliminated unused variable --- src/smt/theory_fpa.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index e76594ded..45cd60332 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -111,7 +111,6 @@ namespace smt { tout << "value[" << i << "] = " << mk_ismt2_pp(values[i], m) << std::endl;); mpf_manager & mpfm = m_fu.fm(); - unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); app * result; From 880cbb936e14d9535de51644f24dff343cfd1eaf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:37:49 +0000 Subject: [PATCH 515/646] fixed portability issue --- src/ast/fpa/fpa2bv_converter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 9f0591134..bdaf2017e 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2467,7 +2467,7 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con expr_ref sig_rest(m); sig_4 = m_bv_util.mk_extract(bv_sz - 1, bv_sz - sig_sz + 1, shifted_sig); // one short sig_rest = m_bv_util.mk_extract(bv_sz - sig_sz, 0, shifted_sig); - sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest); + sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, sig_rest.get()); sig_4 = m_bv_util.mk_concat(sig_4, sticky); } else { From 0ab54b9e0c3321c4dfca543b890b63df1576fdd2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 21 Jan 2015 19:43:26 +0000 Subject: [PATCH 516/646] bugfix for FPA numerals Signed-off-by: Christoph M. Wintersteiger --- src/api/api_numeral.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index d5a25dfc2..277e80c20 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -68,8 +68,8 @@ extern "C" { (' ' == *m) || ('\n' == *m) || ('.' == *m) || ('e' == *m) || ('E' == *m) || - (('p' == *m) && is_float) || - (('P' == *m)) && is_float)) { + ('p' == *m && is_float) || + ('P' == *m && is_float))) { SET_ERROR_CODE(Z3_PARSER_ERROR); return 0; } From c3ff342bea64d6868e615c0c51766d82e67ce5a6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 22 Jan 2015 18:31:30 +0000 Subject: [PATCH 517/646] Bugfixes for the Python FPA API Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 328 ++++++++++++++++++++++++------------ src/api/python/z3printer.py | 23 ++- 2 files changed, 229 insertions(+), 122 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index fd3d1bdc8..414aeb2af 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -7509,7 +7509,7 @@ class FPSortRef(SortRef): def sbits(self): """Retrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`. - >>> b = FloatingPointSort(8, 24) + >>> b = FPSort(8, 24) >>> b.sbits() 24 """ @@ -7520,9 +7520,9 @@ class FPSortRef(SortRef): >>> b = FPSort(8, 24) >>> b.cast(1.0) - 1.0 + 1 >>> b.cast(1.0).sexpr() - '1.0' + '(fp #b0 #x7f #b00000000000000000000000)' """ if is_expr(val): if __debug__: @@ -7579,7 +7579,7 @@ class FPRMSortRef(SortRef): def is_fp_sort(s): """Return True if `s` is a Z3 floating-point sort. - >>> is_fp_sort(FloatingPointSort(8, 24)) + >>> is_fp_sort(FPSort(8, 24)) True >>> is_fp_sort(IntSort()) False @@ -7591,10 +7591,10 @@ def is_fprm_sort(s): >>> is_fprm_sort(FPSort(8, 24)) False - >>> is_fprm_sort() - False + >>> is_fprm_sort(RNE().sort()) + True """ - return isinstance(s, FPSortRef) + return isinstance(s, FPRMSortRef) ### FP Expressions @@ -7606,15 +7606,15 @@ class FPRef(ExprRef): >>> x = FP('1.0', FPSort(8, 24)) >>> x.sort() - (_ FloatingPoint 8 24) - >>> x.sort() == FloatingPointSort(8, 24) + FPSort(8, 24) + >>> x.sort() == FPSort(8, 24) True """ return FPSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) def ebits(self): """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. - >>> b = FloatingPointSort(8, 24) + >>> b = FPSort(8, 24) >>> b.ebits() 8 """ @@ -7622,7 +7622,7 @@ class FPRef(ExprRef): def sbits(self): """Retrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`. - >>> b = FloatingPointSort(8, 24) + >>> b = FPSort(8, 24) >>> b.sbits() 24 """ @@ -7651,12 +7651,12 @@ class FPRef(ExprRef): def __add__(self, other): """Create the Z3 expression `self + other`. - >>> x = FP('x', 8, 24) - >>> y = FP('y', 8, 24) + >>> x = FP('x', FPSort(8, 24)) + >>> y = FP('y', FPSort(8, 24)) >>> x + y x + y >>> (x + y).sort() - FloatingPoint(8 24) + FPSort(8, 24) """ a, b = z3._coerce_exprs(self, other) return fpAdd(_dflt_rm(), self, other) @@ -7666,7 +7666,7 @@ class FPRef(ExprRef): >>> x = FP('x', FPSort(8, 24)) >>> 10 + x - 10 + x + 1.25*(2**3) + x """ a, b = _coerce_exprs(self, other) return fpAdd(_dflt_rm(), other, self) @@ -7674,12 +7674,12 @@ class FPRef(ExprRef): def __sub__(self, other): """Create the Z3 expression `self - other`. - >>> x = FP('x', 8, 24) - >>> y = FP('y', 8, 24) + >>> x = FP('x', FPSort(8, 24)) + >>> y = FP('y', FPSort(8, 24)) >>> x - y x - y >>> (x - y).sort() - FloatingPoint(8 24) + FPSort(8, 24) """ a, b = z3._coerce_exprs(self, other) return fpSub(_dflt_rm(), self, other) @@ -7689,7 +7689,7 @@ class FPRef(ExprRef): >>> x = FP('x', FPSort(8, 24)) >>> 10 - x - 10 - x + 1.25*(2**3) - x """ a, b = _coerce_exprs(self, other) return fpSub(_dflt_rm(), other, self) @@ -7697,22 +7697,27 @@ class FPRef(ExprRef): def __mul__(self, other): """Create the Z3 expression `self * other`. - >>> x = FP('x', 8, 24) - >>> y = FP('y', 8, 24) + >>> x = FP('x', FPSort(8, 24)) + >>> y = FP('y', FPSort(8, 24)) >>> x * y x * y >>> (x * y).sort() - FloatingPoint(8 24) + FPSort(8, 24) + >>> 10 * y + 1.25*(2**3) * y """ a, b = z3._coerce_exprs(self, other) return fpMul(_dflt_rm(), self, other) - def __rmul_(self, other): + def __rmul__(self, other): """Create the Z3 expression `other * self`. >>> x = FP('x', FPSort(8, 24)) - >>> 10 * x - 10 * x + >>> y = FP('y', FPSort(8, 24)) + >>> x * y + x * y + >>> x * 10 + x * 1.25*(2**3) """ a, b = _coerce_exprs(self, other) return fpMul(_dflt_rm(), other, self) @@ -7792,7 +7797,12 @@ def RTZ(ctx=None): def is_fprm(a): """Return `True` if `a` is a Z3 floating-point rounding mode expression. - >>> rm = ? + >>> rm = RNE() + >>> is_fprm(rm) + True + >>> rm = 1.0 + >>> is_fprm(rm) + False """ return isinstance(a, FPRMRef) @@ -7814,7 +7824,65 @@ class FPNumRef(FPRef): def isNegative(self): k = self.decl().kind() - return (self.num_args() == 0 and (k == Z3_OP_FPA_MINUS_INF or k == Z3_OP_FPA_MINUS_ZERO)) or (self.num_args() == 3 and self.arg(0) == BitVecVal(1)) + return (self.num_args() == 0 and (k == Z3_OP_FPA_MINUS_INF or k == Z3_OP_FPA_MINUS_ZERO)) or (self.sign() == True) + + """ + The sign of the numeral + + >>> x = FPNumRef(+1.0, FPSort(8, 24)) + >>> x.sign() + False + >>> x = FPNumRef(-1.0, FPSort(8, 24)) + >>> x.sign() + True + """ + def sign(self): + l = (ctypes.c_int)() + if Z3_fpa_get_numeral_sign(self.ctx.ref(), self.as_ast(), byref(l)) == False: + raise Z3Exception("error retrieving the sign of a numeral.") + return l.value != 0 + + """ + The significand of the numeral + + >>> x = FPNumRef(2.5, FPSort(8, 24)) + 1.25 + """ + def significand(self): + return Z3_fpa_get_numeral_significand_string(self.ctx.ref(), self.as_ast()) + + """ + The exponent of the numeral + + >>> x = FPNumRef(2.5, FPSort(8, 24)) + >>> + 1 + """ + def exponent(self): + return Z3_fpa_get_numeral_exponent_string(self.ctx.ref(), self.as_ast()) + + """ + The exponent of the numeral as a long + + >>> x = FPNumRef(2.5, FPSort(8, 24)) + 1 + """ + def exponent_as_long(self): + ptr = (ctypes.c_longlong * 1)() + if not Z3_fpa_get_numeral_exponent_int64(self.ctx.ref(), self.as_ast(), ptr): + raise Z3Exception("error retrieving the exponent of a numeral.") + return ptr[0] + + """ + The string representation of the numeral + + >>> x = FPNumRef(20, FPSort(8, 24)) + 1.25*(2**4) + """ + def as_string(self): + s = Z3_fpa_get_numeral_string(self.ctx.ref(), self.as_ast()) + return ("FPVal(%s, %s)" % (s, FPSortRef(self.sort()).as_string())) + def _to_fpnum(num, ctx=None): if isinstance(num, FPNum): @@ -7843,7 +7911,7 @@ def is_fp_value(a): False >>> b = FPVal(1.0, FPSort(8, 24)) >>> b - 1.0p0 + 1 >>> is_fp_value(b) True """ @@ -7855,9 +7923,9 @@ def FPSort(ebits, sbits, ctx=None): >>> Single = FPSort(8, 24) >>> Double = FPSort(11, 53) >>> Single - (_ FloatingPoint 8 24) + FPSort(8, 24) >>> x = Const('x', Single) - >>> eq(x, FP('x', 8, 24)) + >>> eq(x, FP('x', FPSort(8, 24))) True """ ctx = z3._get_ctx(ctx) @@ -7911,11 +7979,17 @@ def fpZero(s, negative): def FPVal(sig, exp=None, fps=None, ctx=None): """Return a floating-point value of value `val` and sort `fps`. If `ctx=None`, then the global context is used. - >>> v = FPVal(1.0, FPSort(8, 24))) + >>> v = FPVal(20.0, FPSort(8, 24)) >>> v - 1.0 - >>> print("0x%.8x" % v.as_long()) - 0x0000000a + 1.25*(2**4) + >>> print("0x%.8x" % v.exponent_as_long()) + 0x00000004 + >>> v = FPVal(2.25, FPSort(8, 24)) + >>> v + 1.125*(2**1) + >>> v = FPVal(-2.25, FPSort(8, 24)) + >>> v + -1.125*(2**1) """ ctx = _get_ctx(ctx) if is_fp_sort(exp): @@ -7923,7 +7997,7 @@ def FPVal(sig, exp=None, fps=None, ctx=None): exp = None elif fps == None: fps = _dflt_fps(ctx) - _z3_assert(is_fp_sort(fps), "sort mismatch") + _z3_assert(is_fp_sort(fps), "sort mismatch") if exp == None: exp = 0 val = _to_float_str(sig) @@ -7942,7 +8016,7 @@ def FP(name, fpsort, ctx=None): >>> x.ebits() 8 >>> x.sort() - (_ FloatingPoint 8 24) + FPSort(8, 24) >>> word = FPSort(8, 24) >>> x2 = FP('x', word) >>> eq(x, x2) @@ -7975,17 +8049,28 @@ def fpAbs(a): """Create a Z3 floating-point absolute value expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FPVal(1.0, s) >>> fpAbs(x) - 1.0 - >>> x = FPVal(-1.0, s) - >>> fpAbs(x) - 1.0 + fpAbs(1) + >>> y = FPVal(-20.0, s) + >>> y + -1.25*(2**4) + >>> fpAbs(y) + fpAbs(-1.25*(2**4)) + >>> fpAbs(-1.25*(2**4)) + fpAbs(-1.25*(2**4)) >>> fpAbs(x).sort() - FloatingPoint(8, 24) + FPSort(8, 24) """ - if __debug__: + ctx = None + if not is_expr(a): + ctx =_get_ctx(ctx) + s = get_default_fp_sort(ctx) + a = FPVal(a, s) + else: + ctx = a.ctx + if __debug__: _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression") return FPRef(Z3_mk_fpa_abs(a.ctx_ref(), a.as_ast()), a.ctx) @@ -7993,13 +8078,20 @@ def fpNeg(a): """Create a Z3 floating-point addition expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FP('x', s) - >>> y = FP('y', s) - fp.add(rm, x, y) - >>> fp.add(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpNeg(x) + -x + >>> fpNeg(x).sort() + FPSort(8, 24) """ + ctx = None + if not is_expr(a): + ctx =_get_ctx(ctx) + s = get_default_fp_sort(ctx) + a = FPVal(a, s) + else: + ctx = a.ctx if __debug__: _z3_assert(is_fp(a), "First argument must be Z3 floating-point expression") return FPRef(Z3_mk_fpa_neg(a.ctx_ref(), a.as_ast()), a.ctx) @@ -8008,79 +8100,88 @@ def fpAdd(rm, a, b): """Create a Z3 floating-point addition expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) - fp.add(rm, x, y) - >>> fp.add(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpAdd(rm, x, y) + fpAdd(RNE(), x, y) + >>> fpAdd(rm, x, y).sort() + FPSort(8, 24) """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_add(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) def fpSub(rm, a, b): """Create a Z3 floating-point subtraction expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) - fp.add(rm, x, y) - >>> fp.add(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpSub(rm, x, y) + fpSub(RNE(), x, y) + >>> fpSub(rm, x, y).sort() + FPSort(8, 24) """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_sub(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) def fpMul(rm, a, b): """Create a Z3 floating-point multiplication expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) - fp.add(rm, x, y) - >>> fp.add(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpMul(rm, x, y) + fpMul(RNE(), x, y) + >>> fpMul(rm, x, y).sort() + FPSort(8, 24) """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_mul(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) def fpDiv(rm, a, b): """Create a Z3 floating-point divison expression. >>> s = FPSort(8, 24) - >>> rm = FPRM.RNE + >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) - fpAdd(rm, x, y) - >>> fp.add(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpDiv(rm, x, y) + fpDiv(RNE(), x, y) + >>> fpDiv(rm, x, y).sort() + FPSort(8, 24) """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a) and is_fp(b), "Second and third argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_div(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast()), rm.ctx) def fpRem(a, b): """Create a Z3 floating-point remainder expression. >>> s = FPSort(8, 24) - >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) + >>> fpRem(x, y) fpRem(x, y) - >>> fpRem(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpRem(x, y).sort() + FPSort(8, 24) """ if __debug__: - _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_rem(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) def fpMin(a, b): @@ -8090,12 +8191,14 @@ def fpMin(a, b): >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) + >>> fpMin(x, y) fpMin(x, y) - >>> fpMin(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpMin(x, y).sort() + FPSort(8, 24) """ if __debug__: - _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_min(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) def fpMax(a, b): @@ -8105,12 +8208,14 @@ def fpMax(a, b): >>> rm = RNE() >>> x = FP('x', s) >>> y = FP('y', s) - fpMin(x, y) - >>> fpMin(rm, x, y).sort() - FloatingPoint(8, 24) + >>> fpMax(x, y) + fpMax(x, y) + >>> fpMax(x, y).sort() + FPSort(8, 24) """ if __debug__: - _z3_assert(is_fp(a) and is_fp(b), "Both arguments must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b), "Second or third argument must be a Z3 floating-point expression") + a, b = _coerce_exprs(a, b) return FPRef(Z3_mk_fpa_max(a.ctx_ref(), a.as_ast(), b.as_ast()), a.ctx) def fpFMA(rm, a, b, c): @@ -8118,23 +8223,38 @@ def fpFMA(rm, a, b, c): """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a) and is_fp(b) and is_fp(c), "Second, third, and fourth argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a) or is_fp(b) or is_fp(c), "Second, third, or fourth argument must be a Z3 floating-point expression") + a, b, c = _coerce_expr_list([a, b, c]) return FPRef(Z3_mk_fpa_fma(rm.ctx_ref(), rm.as_ast(), a.as_ast(), b.as_ast(), c.as_ast()), rm.ctx) def fpSqrt(rm, a): """Create a Z3 floating-point square root expression. """ + ctx = None + if not is_expr(a): + ctx =_get_ctx(ctx) + s = get_default_fp_sort(ctx) + a = FPVal(a, s) + else: + ctx = a.ctx if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a), "Second argument must be a Z3 floating-point expressions") return FPRef(Z3_mk_fpa_sqrt(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx) def fpRoundToIntegral(rm, a): """Create a Z3 floating-point roundToIntegral expression. """ + ctx = None + if not is_expr(a): + ctx =_get_ctx(ctx) + s = get_default_fp_sort(ctx) + a = FPVal(a, s) + else: + ctx = a.ctx if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") - _z3_assert(is_fp(a), "Second argument must be Z3 floating-point expressions") + _z3_assert(is_fp(a), "Second argument must be a Z3 floating-point expressions") return FPRef(Z3_mk_fpa_round_to_integral(rm.ctx_ref(), rm.as_ast(), a.as_ast()), rm.ctx) def fpIsNaN(a): @@ -8195,11 +8315,9 @@ def fpLT(a, b): >>> x, y = FPs('x y', FPSort(8, 24)) >>> fpLT(x, y) - x <= y + x < y >>> (x <= y).sexpr() - '?' - >>> fpLT(x, y).sexpr() - '?' + '(fp.leq x y)' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) @@ -8212,9 +8330,7 @@ def fpLEQ(a, b): >>> fpLEQ(x, y) x <= y >>> (x <= y).sexpr() - '?' - >>> fpLEQ(x, y).sexpr() - '?' + '(fp.leq x y)' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) @@ -8225,11 +8341,9 @@ def fpGT(a, b): >>> x, y = FPs('x y', FPSort(8, 24)) >>> fpGT(x, y) - x <= y - >>> (x <= y).sexpr() - '?' - >>> fpGT(x, y).sexpr() - '?' + x > y + >>> (x > y).sexpr() + '(fp.gt x y)' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) @@ -8240,12 +8354,12 @@ def fpGEQ(a, b): """Create the Z3 floating-point expression `other <= self`. >>> x, y = FPs('x y', FPSort(8, 24)) - >>> fp_geq(x, y) - x <= y - >>> (x <= y).sexpr() - '?' - >>> fp_geq(x, y).sexpr() - '?' + >>> x + y + x + y + >>> fpGEQ(x, y) + x >= y + >>> (x >= y).sexpr() + '(fp.geq x y)' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) @@ -8256,11 +8370,9 @@ def fpEQ(a, b): >>> x, y = FPs('x y', FPSort(8, 24)) >>> fpEQ(x, y) - x <= y - >>> (x <= y).sexpr() - '?' + fpEQ(x, y) >>> fpEQ(x, y).sexpr() - '?' + '(fp.eq x y)' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) @@ -8271,11 +8383,9 @@ def fpNEQ(a, b): >>> x, y = FPs('x y', FPSort(8, 24)) >>> fpNEQ(x, y) - x <= y - >>> (x <= y).sexpr() - '?' - >>> fpNEQ(x, y).sexpr() - '?' + Not(fpEQ(x, y)) + >>> (x != y).sexpr() + '(not (fp.eq x y))' """ _check_fp_args(a, b) a, b = _coerce_exprs(a, b) diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index ac1607dda..242d72c0b 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -182,9 +182,6 @@ _infix_map = {} _unary_map = {} _infix_compact_map = {} -for (_k,_v) in _z3_op_to_fpa_normal_str.items(): - _z3_op_to_str[_k] = _v - for _k in _z3_infix: _infix_map[_k] = True for _k in _z3_unary: @@ -515,7 +512,7 @@ class Formatter: self.precision = 10 self.ellipses = to_format(_ellipses) self.max_visited = 10000 - self.fpa_pretty = False + self.fpa_pretty = True def pp_ellipses(self): return self.ellipses @@ -576,8 +573,8 @@ class Formatter: return to_format(a.as_string()) def pp_fprm_value(self, a): - z3._z3_assert(z3.is_fprm_value(a), 'expected FPRMNumRef') - if self.fpa_pretty and a.decl().kind() in _z3_op_to_fpa_pretty_str: + z3._z3_assert(z3.is_fprm_value(a), 'expected FPRMNumRef') + if self.fpa_pretty and (a.decl().kind() in _z3_op_to_fpa_pretty_str): return to_format(_z3_op_to_fpa_pretty_str.get(a.decl().kind())) else: return to_format(_z3_op_to_fpa_normal_str.get(a.decl().kind())) @@ -600,12 +597,12 @@ class Formatter: else: z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast') r = [] - sgn = c_long(0) + sgn = c_int(0) sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast) r.append(to_format('FPVal(')) - if not sgnb and sgn: + if sgnb and sgn.value != 0: r.append(to_format('-')) r.append(to_format(sig)) r.append(to_format('*(2**')) @@ -634,17 +631,17 @@ class Formatter: sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast) - if not sgnb and sgn != 0: + if sgnb and sgn.value != 0: r.append(to_format('-')) r.append(to_format(sig)) if (exp != '0'): r.append(to_format('*(2**')) r.append(to_format(exp)) - r.append(to_format(')')) + r.append(to_format(')')) return compose(r) - def pp_fp(self, a, d, xs): + def pp_fp(self, a, d, xs): z3._z3_assert(isinstance(a, z3.FPRef), "type mismatch") k = a.decl().kind() op = '?' @@ -653,7 +650,7 @@ class Formatter: elif k in _z3_op_to_fpa_normal_str: op = _z3_op_to_fpa_normal_str[k] elif k in _z3_op_to_str: - op = _z3_op_to_str[k] + op = _z3_op_to_str[k] n = a.num_args() @@ -1164,7 +1161,7 @@ def set_fpa_pretty(flag=True): for _k in _z3_fpa_infix: _infix_map[_k] = False - +set_fpa_pretty(True) def in_html_mode(): return isinstance(_Formatter, HTMLFormatter) From 034e4f469ee5aeb9e538d5dc9a2a38a12cde3811 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 22 Jan 2015 18:43:23 +0000 Subject: [PATCH 518/646] Fixed memory leak --- src/api/api_fpa.cpp | 5 ++++- src/util/mpf.h | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 96c3e2eb6..d9f534499 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -696,6 +696,7 @@ extern "C" { RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); @@ -709,7 +710,9 @@ extern "C" { } unsigned sbits = val.get().get_sbits(); scoped_mpq q(mpqm); - mpqm.set(q, mpfm.sig_normalized(val)); + scoped_mpz sn(mpzm); + mpfm.sig_normalized(val, sn); + mpqm.set(q, sn); mpqm.div(q, mpfm.m_powers2(sbits - 1), q); std::stringstream ss; mpqm.display_decimal(ss, q, sbits); diff --git a/src/util/mpf.h b/src/util/mpf.h index 599e8e743..39eb7330e 100644 --- a/src/util/mpf.h +++ b/src/util/mpf.h @@ -146,14 +146,12 @@ public: bool sgn(mpf const & x) const { return x.sign; } const mpz & sig(mpf const & x) const { return x.significand; } - mpz sig_normalized(mpf const & x) { + void sig_normalized(mpf const & x, mpz & res) { mpf t; set(t, x); unpack(t, true); - mpz r; - mpz_manager().set(r, t.significand); + mpz_manager().set(res, t.significand); del(t); - return r; } const mpf_exp_t & exp(mpf const & x) const { return x.exponent; } mpf_exp_t exp_normalized(mpf const & x) { From 0c2e2d78dd3f167a93080af5a6c39c46c9e8fa42 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 22 Jan 2015 18:52:28 +0000 Subject: [PATCH 519/646] renamed function to avoid compilation issues Signed-off-by: Christoph M. Wintersteiger --- src/api/api_context.h | 2 +- src/api/api_fpa.cpp | 162 ++++++++++++++++++++-------------------- src/api/api_numeral.cpp | 14 ++-- 3 files changed, 89 insertions(+), 89 deletions(-) diff --git a/src/api/api_context.h b/src/api/api_context.h index 6312b3f69..58394c028 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -118,7 +118,7 @@ namespace api { arith_util & autil() { return m_arith_util; } bv_util & bvutil() { return m_bv_util; } datalog::dl_decl_util & datalog_util() { return m_datalog_util; } - fpa_util & fpa_util() { return m_fpa_util; } + fpa_util & fpautil() { return m_fpa_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; } diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index d9f534499..9d47e152a 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -29,7 +29,7 @@ extern "C" { LOG_Z3_mk_fpa_rounding_mode_sort(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->fpa_util().mk_rm_sort()); + Z3_sort r = of_sort(ctx->fpautil().mk_rm_sort()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -40,7 +40,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_even()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -50,7 +50,7 @@ extern "C" { LOG_Z3_mk_fpa_rne(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_even()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_even()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -61,7 +61,7 @@ extern "C" { LOG_Z3_mk_fpa_round_nearest_ties_to_away(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_away()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -71,7 +71,7 @@ extern "C" { LOG_Z3_mk_fpa_rna(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_nearest_ties_to_away()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_away()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -82,7 +82,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_positive(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_positive()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -92,7 +92,7 @@ extern "C" { LOG_Z3_mk_fpa_rtp(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_positive()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_positive()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -103,7 +103,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_negative(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_negative()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -113,7 +113,7 @@ extern "C" { LOG_Z3_mk_fpa_rtn(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_negative()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_negative()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -124,7 +124,7 @@ extern "C" { LOG_Z3_mk_fpa_round_toward_zero(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_zero()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -134,7 +134,7 @@ extern "C" { LOG_Z3_mk_fpa_rtz(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_toward_zero()); + Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_zero()); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -148,7 +148,7 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); } api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->fpa_util().mk_float_sort(ebits, sbits)); + Z3_sort r = of_sort(ctx->fpautil().mk_float_sort(ebits, sbits)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -190,7 +190,7 @@ extern "C" { LOG_Z3_mk_fpa_nan(c, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_nan(to_sort(s))); + Z3_ast r = of_ast(ctx->fpautil().mk_nan(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -200,8 +200,8 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_ninf(to_sort(s)) : - ctx->fpa_util().mk_pinf(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpautil().mk_ninf(to_sort(s)) : + ctx->fpautil().mk_pinf(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -211,8 +211,8 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpa_util().mk_nzero(to_sort(s)) : - ctx->fpa_util().mk_pzero(to_sort(s))); + Z3_ast r = of_ast(negative != 0 ? ctx->fpautil().mk_nzero(to_sort(s)) : + ctx->fpautil().mk_pzero(to_sort(s))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -222,7 +222,7 @@ extern "C" { LOG_Z3_mk_fpa_fp(c, sgn, sig, exp); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); + Z3_ast r = of_ast(ctx->fpautil().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -232,12 +232,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_float(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, - ctx->fpa_util().get_ebits(to_sort(ty)), - ctx->fpa_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpautil().fm()); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -247,9 +247,9 @@ extern "C" { LOG_Z3_mk_fpa_numeral_double(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, ctx->fpa_util().get_ebits(to_sort(ty)), ctx->fpa_util().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); + scoped_mpf tmp(ctx->fpautil().fm()); + ctx->fpautil().fm().set(tmp, ctx->fpautil().get_ebits(to_sort(ty)), ctx->fpautil().get_sbits(to_sort(ty)), v); + Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -259,12 +259,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_int(c, v, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, - ctx->fpa_util().get_ebits(to_sort(ty)), - ctx->fpa_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpautil().fm()); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -274,12 +274,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, - ctx->fpa_util().get_ebits(to_sort(ty)), - ctx->fpa_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpautil().fm()); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -289,12 +289,12 @@ extern "C" { LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - scoped_mpf tmp(ctx->fpa_util().fm()); - ctx->fpa_util().fm().set(tmp, - ctx->fpa_util().get_ebits(to_sort(ty)), - ctx->fpa_util().get_sbits(to_sort(ty)), + scoped_mpf tmp(ctx->fpautil().fm()); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->fpa_util().mk_value(tmp)); + Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -304,7 +304,7 @@ extern "C" { LOG_Z3_mk_fpa_abs(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_abs(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_abs(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -314,7 +314,7 @@ extern "C" { LOG_Z3_mk_fpa_neg(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_neg(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_neg(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -324,7 +324,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -334,7 +334,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -344,7 +344,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -354,7 +354,7 @@ extern "C" { LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -364,7 +364,7 @@ extern "C" { LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); + Z3_ast r = of_ast(ctx->fpautil().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -374,7 +374,7 @@ extern "C" { LOG_Z3_mk_fpa_sqrt(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_sqrt(to_expr(rm), to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_sqrt(to_expr(rm), to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -384,7 +384,7 @@ extern "C" { LOG_Z3_mk_fpa_rem(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_rem(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_rem(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -394,7 +394,7 @@ extern "C" { LOG_Z3_mk_fpa_round_to_integral(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_round_to_integral(to_expr(rm), to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_round_to_integral(to_expr(rm), to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -404,7 +404,7 @@ extern "C" { LOG_Z3_mk_fpa_min(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_min(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_min(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -414,7 +414,7 @@ extern "C" { LOG_Z3_mk_fpa_max(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_max(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_max(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -424,7 +424,7 @@ extern "C" { LOG_Z3_mk_fpa_leq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_le(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_le(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -434,7 +434,7 @@ extern "C" { LOG_Z3_mk_fpa_lt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_lt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_lt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -444,7 +444,7 @@ extern "C" { LOG_Z3_mk_fpa_geq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_ge(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_ge(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -454,7 +454,7 @@ extern "C" { LOG_Z3_mk_fpa_gt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_gt(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_gt(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -464,7 +464,7 @@ extern "C" { LOG_Z3_mk_fpa_eq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_float_eq(to_expr(t1), to_expr(t2))); + Z3_ast r = of_ast(ctx->fpautil().mk_float_eq(to_expr(t1), to_expr(t2))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -474,7 +474,7 @@ extern "C" { LOG_Z3_mk_fpa_is_normal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_normal(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_normal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -484,7 +484,7 @@ extern "C" { LOG_Z3_mk_fpa_is_subnormal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_subnormal(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_subnormal(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -494,7 +494,7 @@ extern "C" { LOG_Z3_mk_fpa_is_zero(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_zero(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_zero(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -504,7 +504,7 @@ extern "C" { LOG_Z3_mk_fpa_is_infinite(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_inf(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_inf(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -514,7 +514,7 @@ extern "C" { LOG_Z3_mk_fpa_is_nan(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_nan(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_nan(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -524,7 +524,7 @@ extern "C" { LOG_Z3_mk_fpa_is_negative(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_negative(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_negative(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -534,7 +534,7 @@ extern "C" { LOG_Z3_mk_fpa_is_positive(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_is_positive(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_is_positive(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -545,7 +545,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_bv(c, bv, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!ctx->bvutil().is_bv(to_expr(bv)) || !fu.is_float(to_sort(s))) { SET_ERROR_CODE(Z3_INVALID_ARG); @@ -561,7 +561,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_float(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!fu.is_rm(to_expr(rm)) || !fu.is_float(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -578,7 +578,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_real(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!fu.is_rm(to_expr(rm)) || !ctx->autil().is_real(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -595,7 +595,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_signed(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!fu.is_rm(to_expr(rm)) || !ctx->bvutil().is_bv(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -612,7 +612,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_unsigned(c, rm, t, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!fu.is_rm(to_expr(rm)) || !ctx->bvutil().is_bv(to_expr(t)) || !fu.is_float(to_sort(s))) { @@ -629,7 +629,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ubv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_to_ubv(to_expr(rm), to_expr(t), sz)); + Z3_ast r = of_ast(ctx->fpautil().mk_to_ubv(to_expr(rm), to_expr(t), sz)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -639,7 +639,7 @@ extern "C" { LOG_Z3_mk_fpa_to_sbv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_to_sbv(to_expr(rm), to_expr(t), sz)); + Z3_ast r = of_ast(ctx->fpautil().mk_to_sbv(to_expr(rm), to_expr(t), sz)); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -649,7 +649,7 @@ extern "C" { LOG_Z3_mk_fpa_to_real(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_to_real(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_to_real(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -659,7 +659,7 @@ extern "C" { LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); CHECK_NON_NULL(s, 0); - return mk_c(c)->fpa_util().get_ebits(to_sort(s)); + return mk_c(c)->fpautil().get_ebits(to_sort(s)); Z3_CATCH_RETURN(0); } @@ -668,7 +668,7 @@ extern "C" { LOG_Z3_fpa_get_ebits(c, s); RESET_ERROR_CODE(); CHECK_NON_NULL(s, 0); - return mk_c(c)->fpa_util().get_sbits(to_sort(s)); + return mk_c(c)->fpautil().get_sbits(to_sort(s)); Z3_CATCH_RETURN(0); } @@ -677,7 +677,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_sign(c, t, sgn); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + mpf_manager & mpfm = mk_c(c)->fpautil().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); @@ -695,7 +695,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_significand_string(c, t); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + mpf_manager & mpfm = mk_c(c)->fpautil().fm(); unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); @@ -726,7 +726,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_exponent_string(c, t); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + mpf_manager & mpfm = mk_c(c)->fpautil().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); @@ -750,7 +750,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_exponent_string(c, t); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpa_util().fm(); + mpf_manager & mpfm = mk_c(c)->fpautil().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); @@ -768,7 +768,7 @@ extern "C" { LOG_Z3_mk_fpa_to_ieee_bv(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpa_util().mk_float_to_ieee_bv(to_expr(t))); + Z3_ast r = of_ast(ctx->fpautil().mk_float_to_ieee_bv(to_expr(t))); RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -778,7 +778,7 @@ extern "C" { LOG_Z3_mk_fpa_to_fp_real_int(c, rm, sig, exp, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - fpa_util & fu = ctx->fpa_util(); + fpa_util & fu = ctx->fpautil(); if (!fu.is_rm(to_expr(rm)) || !ctx->autil().is_real(to_expr(sig)) || !ctx->autil().is_int(to_expr(exp)) || diff --git a/src/api/api_numeral.cpp b/src/api/api_numeral.cpp index 277e80c20..446a66bc5 100644 --- a/src/api/api_numeral.cpp +++ b/src/api/api_numeral.cpp @@ -59,7 +59,7 @@ extern "C" { RETURN_Z3(0); } sort * _ty = to_sort(ty); - bool is_float = mk_c(c)->fpa_util().is_float(_ty); + bool is_float = mk_c(c)->fpautil().is_float(_ty); std::string fixed_num; char const* m = n; while (*m) { @@ -78,7 +78,7 @@ extern "C" { ast * a = 0; if (_ty->get_family_id() == mk_c(c)->get_fpa_fid()) { // avoid expanding floats into huge rationals. - fpa_util & fu = mk_c(c)->fpa_util(); + fpa_util & fu = mk_c(c)->fpautil(); scoped_mpf t(fu.fm()); fu.fm().set(t, fu.get_ebits(_ty), fu.get_sbits(_ty), MPF_ROUND_TOWARD_ZERO, n); a = fu.mk_value(t); @@ -148,8 +148,8 @@ extern "C" { return mk_c(c)->autil().is_numeral(e) || mk_c(c)->bvutil().is_numeral(e) || - mk_c(c)->fpa_util().is_numeral(e) || - mk_c(c)->fpa_util().is_rm_numeral(e); + mk_c(c)->fpautil().is_numeral(e) || + mk_c(c)->fpautil().is_rm_numeral(e); Z3_CATCH_RETURN(Z3_FALSE); } @@ -191,10 +191,10 @@ extern "C" { } else { // floats are separated from all others to avoid huge rationals. - fpa_util & fu = mk_c(c)->fpa_util(); + fpa_util & fu = mk_c(c)->fpautil(); scoped_mpf tmp(fu.fm()); mpf_rounding_mode rm; - if (mk_c(c)->fpa_util().is_rm_numeral(to_expr(a), rm)) { + if (mk_c(c)->fpautil().is_rm_numeral(to_expr(a), rm)) { switch (rm) { case OP_FPA_RM_NEAREST_TIES_TO_EVEN: return mk_c(c)->mk_external_string("roundNearestTiesToEven"); @@ -214,7 +214,7 @@ extern "C" { break; } } - else if (mk_c(c)->fpa_util().is_numeral(to_expr(a), tmp)) { + else if (mk_c(c)->fpautil().is_numeral(to_expr(a), tmp)) { return mk_c(c)->mk_external_string(fu.fm().to_string(tmp)); } else { From 8cd69acacafbfe60d0b1c9d11e4310219b39b547 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 11:34:08 +0000 Subject: [PATCH 520/646] build fix --- src/api/python/z3printer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index 242d72c0b..2cc29bd5d 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -627,7 +627,7 @@ class Formatter: else: z3._z3_assert(z3.is_fp_value(a), 'expecting FP num ast') r = [] - sgn = c_long(0) + sgn = (ctypes.c_int)(0) sgnb = Z3_fpa_get_numeral_sign(a.ctx_ref(), a.ast, byref(sgn)) sig = Z3_fpa_get_numeral_significand_string(a.ctx_ref(), a.ast) exp = Z3_fpa_get_numeral_exponent_string(a.ctx_ref(), a.ast) From 3d915105658c8e4690100017fa817031d5f2c788 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 17:03:56 +0000 Subject: [PATCH 521/646] FPA API: naming consistency fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 8 ++++---- src/api/z3_fpa.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 9d47e152a..2d4529309 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -269,9 +269,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(Z3_context c, Z3_bool sgn, unsigned sig, signed exp, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_numeral_int_uint(Z3_context c, Z3_bool sgn, signed exp, unsigned sig, Z3_sort ty) { Z3_TRY; - LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); + LOG_Z3_mk_fpa_numeral_int64_uint64(c, sgn, exp, sig, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); @@ -284,9 +284,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(Z3_context c, Z3_bool sgn, __uint64 sig, __int64 exp, Z3_sort ty) { + Z3_ast Z3_API Z3_mk_fpa_numeral_int64_uint64(Z3_context c, Z3_bool sgn, __int64 exp, __uint64 sig, Z3_sort ty) { Z3_TRY; - LOG_Z3_mk_fpa_numeral_uint64_int64(c, sgn, sig, exp, ty); + LOG_Z3_mk_fpa_numeral_int64_uint64(c, sgn, exp, sig, ty); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 10a7dc4cf..275c30fe0 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -337,9 +337,9 @@ extern "C" { \sa Z3_mk_numeral - def_API('Z3_mk_fpa_numeral_uint_int', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(INT), _in(SORT))) + def_API('Z3_mk_fpa_numeral_int_uint', AST, (_in(CONTEXT), _in(BOOL), _in(INT), _in(UINT), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_numeral_uint_int(__in Z3_context c, __in Z3_bool sgn, __in unsigned sig, __in signed exp, Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_numeral_int_uint(__in Z3_context c, __in Z3_bool sgn, __in signed exp, __in unsigned sig, Z3_sort ty); /** \brief Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. @@ -354,9 +354,9 @@ extern "C" { \sa Z3_mk_numeral - def_API('Z3_mk_fpa_numeral_uint64_int64', AST, (_in(CONTEXT), _in(BOOL), _in(UINT64), _in(INT64), _in(SORT))) + def_API('Z3_mk_fpa_numeral_int64_uint64', AST, (_in(CONTEXT), _in(BOOL), _in(INT64), _in(UINT64), _in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_numeral_uint64_int64(__in Z3_context c, __in Z3_bool sgn, __in __uint64 sig, __in __int64 exp, Z3_sort ty); + Z3_ast Z3_API Z3_mk_fpa_numeral_int64_uint64(__in Z3_context c, __in Z3_bool sgn, __in __int64 exp, __in __uint64 sig, Z3_sort ty); /** \brief Floating-point absolute value From 06051989be4369e4a98707cb04610ee9ecadf5b5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 17:11:12 +0000 Subject: [PATCH 522/646] FPA API: Naming consistency Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Context.cs | 10 +++++----- src/api/java/Context.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 1a36a35dc..96999d2d9 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3706,7 +3706,7 @@ namespace Microsoft.Z3 public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s) { Contract.Ensures(Contract.Result() != null); - return new FPNum(this, Native.Z3_mk_fpa_numeral_uint_int(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); + return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, sgn ? 1 : 0, exp, sig, s.NativeObject)); } /// @@ -3716,10 +3716,10 @@ namespace Microsoft.Z3 /// the significand. /// the exponent. /// FloatingPoint sort. - public FPNum MkFPNumeral(bool sgn, UInt64 sig, Int64 exp, FPSort s) + public FPNum MkFPNumeral(bool sgn, Int64 exp, UInt64 sig, FPSort s) { Contract.Ensures(Contract.Result() != null); - return new FPNum(this, Native.Z3_mk_fpa_numeral_uint64_int64(nCtx, sgn ? 1 : 0, sig, exp, s.NativeObject)); + return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, sgn ? 1 : 0, exp, sig, s.NativeObject)); } /// @@ -3765,7 +3765,7 @@ namespace Microsoft.Z3 public FPNum MkFP(bool sgn, int exp, uint sig, FPSort s) { Contract.Ensures(Contract.Result() != null); - return MkFPNumeral(sgn, sig, exp, s); + return MkFPNumeral(sgn, exp, sig, s); } /// @@ -3778,7 +3778,7 @@ namespace Microsoft.Z3 public FPNum MkFP(bool sgn, Int64 exp, UInt64 sig, FPSort s) { Contract.Ensures(Contract.Result() != null); - return MkFPNumeral(sgn, sig, exp, s); + return MkFPNumeral(sgn, exp, sig, s); } #endregion diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 18e1b7b2c..baa84f60a 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3043,9 +3043,9 @@ public class Context extends IDisposable * @param s FloatingPoint sort. * @throws Z3Exception **/ - public FPNum mkFPNumeral(boolean sgn, int sig, int exp, FPSort s) throws Z3Exception + public FPNum mkFPNumeral(boolean sgn, int exp, int sig, FPSort s) throws Z3Exception { - return new FPNum(this, Native.mkFpaNumeralUintInt(nCtx(), sgn, sig, exp, s.getNativeObject())); + return new FPNum(this, Native.mkFpaNumeralIntUint(nCtx(), sgn, exp, sig, s.getNativeObject())); } /** @@ -3056,9 +3056,9 @@ public class Context extends IDisposable * @param s FloatingPoint sort. * @throws Z3Exception **/ - public FPNum mkFPNumeral(boolean sgn, long sig, long exp, FPSort s) throws Z3Exception + public FPNum mkFPNumeral(boolean sgn, long exp, long sig, FPSort s) throws Z3Exception { - return new FPNum(this, Native.mkFpaNumeralUint64Int64(nCtx(), sgn, sig, exp, s.getNativeObject())); + return new FPNum(this, Native.mkFpaNumeralInt64Uint64(nCtx(), sgn, exp, sig, s.getNativeObject())); } /** From 145e0259590cb39bee591a02dd46b6a656a663c3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 18:14:49 +0000 Subject: [PATCH 523/646] FPA API naming consistency Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 4 ++-- src/api/dotnet/Context.cs | 6 +++--- src/api/java/Context.java | 6 +++--- src/api/z3_fpa.h | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 2d4529309..86166a5cf 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -773,9 +773,9 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(Z3_context c, Z3_ast rm, Z3_ast sig, Z3_ast exp, Z3_sort s) { + Z3_ast Z3_API Z3_mk_fpa_to_fp_int_real(Z3_context c, Z3_ast rm, Z3_ast exp, Z3_ast sig, Z3_sort s) { Z3_TRY; - LOG_Z3_mk_fpa_to_fp_real_int(c, rm, sig, exp, s); + LOG_Z3_mk_fpa_to_fp_int_real(c, rm, exp, sig, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); fpa_util & fu = ctx->fpautil(); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 96999d2d9..65ec87bc6 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4227,13 +4227,13 @@ namespace Microsoft.Z3 /// according to rounding mode rm. /// /// RoundingMode term. - /// Significand term of Real sort. /// Exponent term of Int sort. + /// Significand term of Real sort. /// FloatingPoint sort. - public BitVecExpr MkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s) + public BitVecExpr MkFPToFP(FPRMExpr rm, IntExpr exp, RealExpr sig, FPSort s) { Contract.Ensures(Contract.Result() != null); - return new BitVecExpr(this, Native.Z3_mk_fpa_to_fp_real_int(this.nCtx, rm.NativeObject, sig.NativeObject, exp.NativeObject, s.NativeObject)); + return new BitVecExpr(this, Native.Z3_mk_fpa_to_fp_int_real(this.nCtx, rm.NativeObject, exp.NativeObject, sig.NativeObject, s.NativeObject)); } #endregion #endregion // Floating-point Arithmetic diff --git a/src/api/java/Context.java b/src/api/java/Context.java index baa84f60a..294826f55 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3542,8 +3542,8 @@ public class Context extends IDisposable /** * Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. * @param rm RoundingMode term. - * @param sig Significand term of Real sort. * @param exp Exponent term of Int sort. + * @param sig Significand term of Real sort. * @param s FloatingPoint sort. * Remarks: * Produces a term that represents the conversion of sig * 2^exp into a @@ -3552,9 +3552,9 @@ public class Context extends IDisposable * @throws Z3Exception **/ - public BitVecExpr mkFPToFP(FPRMExpr rm, RealExpr sig, IntExpr exp, FPSort s) throws Z3Exception + public BitVecExpr mkFPToFP(FPRMExpr rm, IntExpr exp, RealExpr sig, FPSort s) throws Z3Exception { - return new BitVecExpr(this, Native.mkFpaToFpRealInt(nCtx(), rm.getNativeObject(), sig.getNativeObject(), exp.getNativeObject(), s.getNativeObject())); + return new BitVecExpr(this, Native.mkFpaToFpIntReal(nCtx(), rm.getNativeObject(), exp.getNativeObject(), sig.getNativeObject(), s.getNativeObject())); } diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index 275c30fe0..ca5ffebf7 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -501,10 +501,10 @@ extern "C" { t1, t2 must have the same FloatingPoint sort. def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) - */ - Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); + */ + Z3_ast Z3_API Z3_mk_fpa_min(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2); - /** + /** \brief Maximum of floating-point numbers. \param c logical context @@ -905,15 +905,15 @@ extern "C" { \param c logical context \param rm term of RoundingMode sort - \param sig significand term of Real sort \param exp exponent term of Int sort + \param sig significand term of Real sort \param s FloatingPoint sort - s must be a FloatingPoint sort, rm must be of RoundingMode sort, t must be of real sort. + s must be a FloatingPoint sort, rm must be of RoundingMode sort, exp must be of int sort, sig must be of real sort. - def_API('Z3_mk_fpa_to_fp_real_int', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(SORT))) + def_API('Z3_mk_fpa_to_fp_int_real', AST, (_in(CONTEXT),_in(AST),_in(AST),_in(AST),_in(SORT))) */ - Z3_ast Z3_API Z3_mk_fpa_to_fp_real_int(__in Z3_context c, __in Z3_ast rm, __in Z3_ast sig, __in Z3_ast exp, __in Z3_sort s); + Z3_ast Z3_API Z3_mk_fpa_to_fp_int_real(__in Z3_context c, __in Z3_ast rm, __in Z3_ast exp, __in Z3_ast sig, __in Z3_sort s); /*@}*/ From 48c72d2c38bc0d1da9d2627e9b933bb65f4de5a6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 18:18:26 +0000 Subject: [PATCH 524/646] FPA API: naming consistency Signed-off-by: Christoph M. Wintersteiger --- examples/c/test_capi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c index 817ada98e..c0ea70453 100644 --- a/examples/c/test_capi.c +++ b/examples/c/test_capi.c @@ -2665,10 +2665,10 @@ void fpa_example() { c2 = Z3_mk_fpa_to_fp_bv(ctx, Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), Z3_mk_fpa_sort(ctx, 11, 53)); - c3 = Z3_mk_fpa_to_fp_real_int(ctx, + c3 = Z3_mk_fpa_to_fp_int_real(ctx, Z3_mk_fpa_rtz(ctx), - Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), - Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), + Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), + Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), Z3_mk_fpa_sort(ctx, 11, 53)); c4 = Z3_mk_fpa_to_fp_real(ctx, Z3_mk_fpa_rtz(ctx), From 65ccc9a8eadfb5fbebe95bd76c6323818d091398 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 23 Jan 2015 19:36:47 +0000 Subject: [PATCH 525/646] added FPA ML API Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 89 +++++++++- scripts/update_api.py | 2 +- src/api/ml/z3.ml | 210 ++++++++++++++++++++++- src/api/ml/z3.mli | 352 +++++++++++++++++++++++++++++++++++++- 4 files changed, 630 insertions(+), 23 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 33334930e..8a2d71d82 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -19,6 +19,7 @@ open Z3.Arithmetic.Integer open Z3.Arithmetic.Real open Z3.BitVector + exception TestFailedException of string (** @@ -73,7 +74,6 @@ let model_converter_test ( ctx : context ) = *) let basic_tests ( ctx : context ) = Printf.printf "BasicTests\n" ; -(* let qi = (mk_int ctx 1) in *) let fname = (mk_string ctx "f") in let x = (mk_string ctx "x") in let y = (mk_string ctx "y") in @@ -167,8 +167,8 @@ let basic_tests ( ctx : context ) = let rn = Real.mk_numeral_nd ctx 42 43 in let inum = (get_numerator rn) in let iden = get_denominator rn in - Printf.printf "Numerator: %s Denominator: %s\n" (Real.to_string inum) (Real.to_string iden) ; - if ((Real.to_string inum) <> "42" || (Real.to_string iden) <> "43") then + Printf.printf "Numerator: %s Denominator: %s\n" (Real.numeral_to_string inum) (Real.numeral_to_string iden) ; + if ((Real.numeral_to_string inum) <> "42" || (Real.numeral_to_string iden) <> "43") then raise (TestFailedException "") else Printf.printf "Test passed.\n" @@ -190,7 +190,7 @@ let basic_tests ( ctx : context ) = (* Error handling test. *) try ( let i = Integer.mk_numeral_s ctx "1/2" in - raise (TestFailedException (to_string i)) (* unreachable *) + raise (TestFailedException (numeral_to_string i)) (* unreachable *) ) with Z3native.Exception(_) -> ( Printf.printf "Exception caught, OK.\n" @@ -199,7 +199,7 @@ let basic_tests ( ctx : context ) = (** A basic example of how to use quantifiers. **) -let quantifierExample1 ( ctx : context ) = +let quantifier_example1 ( ctx : context ) = Printf.printf "QuantifierExample\n" ; let is = (Integer.mk_sort ctx) in let types = [ is; is; is ] in @@ -239,6 +239,82 @@ let quantifierExample1 ( ctx : context ) = else if (is_const (Quantifier.expr_of_quantifier x)) then raise (TestFailedException "") (* unreachable *) + +open Z3.FloatingPoint + +(** + A basic example of floating point arithmetic +**) +let fpa_example ( ctx : context ) = + Printf.printf "FPAExample\n" ; + let double_sort = (FloatingPoint.mk_sort_double ctx) in + let rm_sort = (FloatingPoint.RoundingMode.mk_sort ctx) in + + (** Show that there are x, y s.t. (x + y) = 42.0 (with rounding mode). *) + let s_rm = (mk_string ctx "rm") in + let rm = (mk_const ctx s_rm rm_sort) in + let s_x = (mk_string ctx "x") in + let s_y = (mk_string ctx "y") in + let x = (mk_const ctx s_x double_sort) in + let y = (mk_const ctx s_y double_sort)in + Printf.printf "A\n" ; + let n = (mk_numeral_f ctx 42.0 double_sort) in + Printf.printf "B\n" ; + let s_x_plus_y = (mk_string ctx "x_plus_y") in + let x_plus_y = (mk_const ctx s_x_plus_y double_sort) in + let c1 = (mk_eq ctx x_plus_y (mk_add ctx rm x y)) in + let args = [ c1 ; (mk_eq ctx x_plus_y n) ] in + let c2 = (Boolean.mk_and ctx args) in + let args2 = [ c2 ; (Boolean.mk_not ctx (mk_eq ctx rm (RoundingMode.mk_rtz ctx))) ] in + let c3 = (Boolean.mk_and ctx args2) in + let and_args = [ (Boolean.mk_not ctx (mk_is_zero ctx y)) ; + (Boolean.mk_not ctx (mk_is_nan ctx y)) ; + (Boolean.mk_not ctx (mk_is_infinite ctx y)) ] in + let args3 = [ c3 ; (Boolean.mk_and ctx and_args) ] in + let c4 = (Boolean.mk_and ctx args3) in + + (Printf.printf "c4: %s\n" (Expr.to_string c4)) + (* push(ctx); *) + (* Z3_assert_cnstr(ctx, c4); *) + (* check(ctx, Z3_L_TRUE); *) + (* Z3_pop(ctx, 1); *) + + (* // Show that the following are equal: *) + (* // (fp #b0 #b10000000001 #xc000000000000) *) + (* // ((_ to_fp 11 53) #x401c000000000000)) *) + (* // ((_ to_fp 11 53) RTZ 1.75 2))) *) + (* // ((_ to_fp 11 53) RTZ 7.0))) *) + + (* Z3_push(ctx); *) + (* c1 = Z3_mk_fpa_fp(ctx, *) + (* Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)), *) + (* Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)), *) + (* Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11))); *) + (* c2 = Z3_mk_fpa_to_fp_bv(ctx, *) + (* Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), *) + (* Z3_mk_fpa_sort(ctx, 11, 53)); *) + (* c3 = Z3_mk_fpa_to_fp_real_int(ctx, *) + (* Z3_mk_fpa_rtz(ctx), *) + (* Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), *) + (* Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), *) + (* Z3_mk_fpa_sort(ctx, 11, 53)); *) + (* c4 = Z3_mk_fpa_to_fp_real(ctx, *) + (* Z3_mk_fpa_rtz(ctx), *) + (* Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)), *) + (* Z3_mk_fpa_sort(ctx, 11, 53)); *) + (* args3[0] = Z3_mk_eq(ctx, c1, c2); *) + (* args3[1] = Z3_mk_eq(ctx, c1, c3); *) + (* args3[2] = Z3_mk_eq(ctx, c1, c4); *) + (* c5 = Z3_mk_and(ctx, 3, args3); *) + + (* printf("c5: %s\n", Z3_ast_to_string(ctx, c5)); *) + (* Z3_assert_cnstr(ctx, c5); *) + (* check(ctx, Z3_L_TRUE); *) + (* Z3_pop(ctx, 1); *) + + (* Z3_del_context(ctx); *) + + let _ = try ( if not (Log.open_ "z3.log") then @@ -259,7 +335,8 @@ let _ = Printf.printf "int sort: %s\n" (Sort.to_string ints); Printf.printf "real sort: %s\n" (Sort.to_string rs); basic_tests ctx ; - quantifierExample1 ctx ; + quantifier_example1 ctx ; + fpa_example ctx ; Printf.printf "Disposing...\n"; Gc.full_major () ); diff --git a/scripts/update_api.py b/scripts/update_api.py index 79b34c315..889044d1f 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -159,7 +159,7 @@ Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', I # Mapping to ML types Type2ML = { VOID : 'unit', VOID_PTR : 'VOIDP', INT : 'int', UINT : 'int', INT64 : 'int', UINT64 : 'int', DOUBLE : 'float', - STRING : 'string', STRING_PTR : 'char**', + FLOAT : 'float', STRING : 'string', STRING_PTR : 'char**', BOOL : 'bool', SYMBOL : 'z3_symbol', PRINT_MODE : 'int', ERROR_CODE : 'int' } next_type_id = FIRST_OBJ_ID diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 350457525..601da1cbc 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -362,7 +362,9 @@ struct | REAL_SORT | UNINTERPRETED_SORT | FINITE_DOMAIN_SORT - | RELATION_SORT -> Sort(q) + | RELATION_SORT + | FLOATING_POINT_SORT + | ROUNDING_MODE_SORT -> Sort(q) | UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered") let ast_of_sort s = match s with Sort(x) -> x @@ -745,7 +747,8 @@ end = struct Expr(z3_native_object_of_ast_ptr ctx no) else if (Z3native.is_numeral_ast (context_gno ctx) no) then - if (sk == INT_SORT || sk == REAL_SORT || sk == BV_SORT) then + if (sk == INT_SORT || sk == REAL_SORT || sk == BV_SORT || + sk == FLOATING_POINT_SORT || sk == ROUNDING_MODE_SORT) then Expr(z3_native_object_of_ast_ptr ctx no) else raise (Z3native.Exception "Unsupported numeral object") @@ -1507,7 +1510,7 @@ struct (Big_int.big_int_of_string s) else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) @@ -1554,7 +1557,7 @@ struct let to_decimal_string ( x : expr ) ( precision : int ) = Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_const ( ctx : context ) ( name : Symbol.symbol ) = Expr.mk_const ctx name (mk_sort ctx) @@ -1562,7 +1565,7 @@ struct let mk_const_s ( ctx : context ) ( name : string ) = mk_const ctx (Symbol.mk_string ctx name) - let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int) = + let mk_numeral_nd ( ctx : context ) ( num : int ) ( den : int ) = if (den == 0) then raise (Z3native.Exception "Denominator is zero") else @@ -1591,7 +1594,7 @@ struct let to_decimal_string ( x : expr ) ( precision : int ) = Z3native.get_numeral_decimal_string (Expr.gnc x) (Expr.gno x) precision - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) end end @@ -1692,7 +1695,7 @@ struct let (r, v) = Z3native.get_numeral_int (Expr.gnc x) (Expr.gno x) in if r then v else raise (Z3native.Exception "Conversion failed.") - let to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( size : int ) = Expr.mk_const ctx name (mk_sort ctx size) let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) = @@ -1791,11 +1794,202 @@ struct (expr_of_ptr ctx (Z3native.mk_bvmul_no_overflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2) signed)) let mk_mul_no_underflow ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = (expr_of_ptr ctx (Z3native.mk_bvmul_no_underflow (context_gno ctx) (Expr.gno t1) (Expr.gno t2))) - let mk_numeral ( ctx : context ) ( v : string ) ( size : int) = + let mk_numeral ( ctx : context ) ( v : string ) ( size : int ) = expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno (mk_sort ctx size))) end +module FloatingPoint = +struct + module RoundingMode = + struct + let mk_sort ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_rounding_mode_sort (context_gno ctx))) + let is_fprm ( x : expr ) = + (Sort.get_sort_kind (Expr.get_sort(x))) == ROUNDING_MODE_SORT + let mk_round_nearest_ties_to_even ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_round_nearest_ties_to_even (context_gno ctx))) + let mk_rne ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_rne (context_gno ctx))) + let mk_round_nearest_ties_to_away ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_round_nearest_ties_to_away (context_gno ctx))) + let mk_rna ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_rna (context_gno ctx))) + let mk_round_toward_positive ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_round_toward_positive (context_gno ctx))) + let mk_rtp ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_rtp (context_gno ctx))) + let mk_round_toward_negative ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_round_toward_negative (context_gno ctx))) + let mk_rtn ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_rtn (context_gno ctx))) + let mk_round_toward_zero ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_round_toward_zero (context_gno ctx))) + let mk_rtz ( ctx : context ) = + (expr_of_ptr ctx (Z3native.mk_fpa_rtz (context_gno ctx))) + end + + let mk_sort ( ctx : context ) ( ebits : int ) ( sbits : int ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort (context_gno ctx) ebits sbits)) + let mk_sort_half ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_half (context_gno ctx))) + let mk_sort_16 ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_16 (context_gno ctx))) + let mk_sort_single ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_single (context_gno ctx))) + let mk_sort_32 ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_32 (context_gno ctx))) + let mk_sort_double ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_double (context_gno ctx))) + let mk_sort_64 ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_64 (context_gno ctx))) + let mk_sort_quadruple ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_quadruple (context_gno ctx))) + let mk_sort_128 ( ctx : context ) = + (sort_of_ptr ctx (Z3native.mk_fpa_sort_128 (context_gno ctx))) + let mk_nan ( ctx : context ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_fpa_nan (context_gno ctx) (Sort.gno s))) + let mk_inf ( ctx : context ) ( s : sort ) ( negative : bool ) = + (expr_of_ptr ctx (Z3native.mk_fpa_inf (context_gno ctx) (Sort.gno s) negative)) + let mk_zero ( ctx : context ) ( s : sort ) ( negative : bool ) = + (expr_of_ptr ctx (Z3native.mk_fpa_zero (context_gno ctx) (Sort.gno s) negative)) + + let mk_fp ( ctx : context ) ( sign : expr ) ( exponent : expr ) ( significand : expr ) = + (expr_of_ptr ctx (Z3native.mk_fpa_fp (context_gno ctx) (Expr.gno sign) (Expr.gno exponent) (Expr.gno significand))) + let mk_numeral_f ( ctx : context ) ( value : float ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_double (context_gno ctx) value (Sort.gno s))) + let mk_numeral_i ( ctx : context ) ( value : int ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int (context_gno ctx) value (Sort.gno s))) + let mk_numeral_i_u ( ctx : context ) ( sign : bool ) ( exponent : int ) ( significand : int ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int64_uint64 (context_gno ctx) sign exponent significand (Sort.gno s))) + let mk_numeral_s ( ctx : context ) ( v : string ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno s))) + + let is_fp ( x : expr ) = (Sort.get_sort_kind (Expr.get_sort x)) == FLOATING_POINT_SORT + let is_abs ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_ABS) + let is_neg ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_NEG) + let is_add ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_ADD) + let is_sub ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_SUB) + let is_mul ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_MUL) + let is_div ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_DIV) + let is_fma ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_FMA) + let is_sqrt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_SQRT) + let is_rem ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_REM) + let is_round_to_integral ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_ROUND_TO_INTEGRAL) + let is_min ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_MIN) + let is_max ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_MAX) + let is_leq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_LE) + let is_lt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_LT) + let is_geq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_GE) + let is_gt ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_GT) + let is_eq ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_EQ) + let is_is_normal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_NORMAL) + let is_is_subnormal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_SUBNORMAL) + let is_is_zero ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_ZERO) + let is_is_infinite ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_INF) + let is_is_nan ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_NAN) + let is_is_negative ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_NEGATIVE) + let is_is_positive ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_IS_POSITIVE) + let is_to_fp ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_FP) + let is_to_fp_unsigned ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_FP_UNSIGNED) + let is_to_ubv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_UBV) + let is_to_sbv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_SBV) + let is_to_real ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_REAL) + let is_to_ieee_bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FPA_TO_IEEE_BV) + + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) + let mk_const ( ctx : context ) ( name : Symbol.symbol ) ( s : sort ) = + Expr.mk_const ctx name s + let mk_const_s ( ctx : context ) ( name : string ) ( s : sort ) = + mk_const ctx (Symbol.mk_string ctx name) s + + let mk_abs ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_abs (context_gno ctx) (Expr.gno t)) + let mk_neg ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_neg (context_gno ctx) (Expr.gno t)) + let mk_add ( ctx : context ) ( rm : expr ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_add (context_gno ctx) (Expr.gno rm) (Expr.gno t1) (Expr.gno t2)) + let mk_sub ( ctx : context ) ( rm : expr ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_sub (context_gno ctx) (Expr.gno rm) (Expr.gno t1) (Expr.gno t2)) + let mk_mul ( ctx : context ) ( rm : expr ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_mul (context_gno ctx) (Expr.gno rm) (Expr.gno t1) (Expr.gno t2)) + let mk_div ( ctx : context ) ( rm : expr ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_div (context_gno ctx) (Expr.gno rm) (Expr.gno t1) (Expr.gno t2)) + let mk_fma ( ctx : context ) ( rm : expr ) ( t1 : expr ) ( t2 : expr ) ( t3 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_fma (context_gno ctx) (Expr.gno rm) (Expr.gno t1) (Expr.gno t2) (Expr.gno t3)) + let mk_sqrt ( ctx : context ) ( rm : expr ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_sqrt (context_gno ctx) (Expr.gno rm) (Expr.gno t)) + let mk_rem ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_rem (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_round_to_integral ( ctx : context ) ( rm : expr ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_round_to_integral (context_gno ctx) (Expr.gno rm) (Expr.gno t)) + let mk_min ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_min (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_max ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_max (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_leq ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_leq (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_lt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_lt (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_geq ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_geq (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_gt ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_gt (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_eq ( ctx : context ) ( t1 : expr ) ( t2 : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_eq (context_gno ctx) (Expr.gno t1) (Expr.gno t2)) + let mk_is_normal ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_normal (context_gno ctx) (Expr.gno t)) + let mk_is_subnormal ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_subnormal (context_gno ctx) (Expr.gno t)) + let mk_is_zero ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_zero (context_gno ctx) (Expr.gno t)) + let mk_is_infinite ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_infinite (context_gno ctx) (Expr.gno t)) + let mk_is_nan ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_nan (context_gno ctx) (Expr.gno t)) + let mk_is_negative ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_negative (context_gno ctx) (Expr.gno t)) + let mk_is_positive ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_is_positive (context_gno ctx) (Expr.gno t)) + let mk_to_fp_bv ( ctx : context ) ( t : expr ) ( s : sort ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_fp_bv (context_gno ctx) (Expr.gno t) (Sort.gno s)) + let mk_to_fp_float ( ctx : context ) ( rm : expr) ( t : expr ) ( s : sort ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_fp_float (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) + let mk_to_fp_real ( ctx : context ) ( rm : expr ) ( t : expr ) ( s : sort ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_fp_real (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) + let mk_to_fp_signed ( ctx : context ) ( rm : expr) ( t : expr ) ( s : sort ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_fp_signed (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) + let mk_to_fp_unsigned ( ctx : context ) ( rm : expr) ( t : expr ) ( s : sort ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_fp_unsigned (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) + let mk_to_fp_ubv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_ubv (context_gno ctx) (Expr.gno rm) (Expr.gno t) size) + let mk_to_fp_sbv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_sbv (context_gno ctx) (Expr.gno rm) (Expr.gno t) size) + let mk_to_fp_real ( ctx : context ) ( t : expr ) = + expr_of_ptr ctx (Z3native.mk_fpa_to_real (context_gno ctx) (Expr.gno t)) + + let get_ebits ( ctx : context ) ( s : sort ) = + (Z3native.fpa_get_ebits (context_gno ctx) (Sort.gno s)) + let get_sbits ( ctx : context ) ( s : sort ) = + (Z3native.fpa_get_sbits (context_gno ctx) (Sort.gno s)) + let get_numeral_sign ( ctx : context ) ( t : expr ) = + (Z3native.fpa_get_numeral_sign (context_gno ctx) (Expr.gno t)) + let get_numeral_significand_string ( ctx : context ) ( t : expr ) = + (Z3native.fpa_get_numeral_significand_string (context_gno ctx) (Expr.gno t)) + let get_numeral_exponent_string ( ctx : context ) ( t : expr ) = + (Z3native.fpa_get_numeral_exponent_string (context_gno ctx) (Expr.gno t)) + let get_numeral_exponent_int ( ctx : context ) ( t : expr ) = + (Z3native.fpa_get_numeral_exponent_int64 (context_gno ctx) (Expr.gno t)) + + let mk_to_ieee_bv ( ctx : context ) ( t : expr ) = + (expr_of_ptr ctx (Z3native.mk_fpa_to_ieee_bv (context_gno ctx) (Expr.gno t))) + let mk_to_fp_real_int ( ctx : context ) ( rm : expr ) ( exponent : expr ) ( significand : expr ) ( s : sort) = + (expr_of_ptr ctx (Z3native.mk_fpa_to_fp_real_int (context_gno ctx) (Expr.gno rm) (Expr.gno exponent) (Expr.gno significand) (Sort.gno s))) + + let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) +end + + module Proof = struct let is_true ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE) diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index b2f0939d0..ab2a14725 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1157,8 +1157,8 @@ sig (** Get a big_int from an integer numeral *) val get_big_int : Expr.expr -> Big_int.big_int - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr -> string (** Creates an integer constant. *) val mk_const : context -> Symbol.symbol -> Expr.expr @@ -1221,8 +1221,8 @@ sig The result has at most as many decimal places as indicated by the int argument.*) val to_decimal_string : Expr.expr-> int -> string - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr-> string + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr-> string (** Creates a real constant. *) val mk_const : context -> Symbol.symbol -> Expr.expr @@ -1271,8 +1271,8 @@ sig The result has at most as many decimal places as the int argument provided.*) val to_decimal_string : Expr.expr -> int -> string - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr -> string end end @@ -1551,8 +1551,8 @@ sig (** Retrieve the int value. *) val get_int : Expr.expr -> int - (** Returns a string representation of the numeral. *) - val to_string : Expr.expr -> string + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr -> string (** Creates a bit-vector constant. *) val mk_const : context -> Symbol.symbol -> int -> Expr.expr @@ -1830,6 +1830,342 @@ sig val mk_numeral : context -> string -> int -> Expr.expr end +(** Floating-Point Arithmetic *) +module FloatingPoint : + sig + + (** Rounding Modes *) + module RoundingMode : + sig + (** Create the RoundingMode sort. *) + val mk_sort : context -> Sort.sort + + (** Indicates whether the terms is of floating-point rounding mode sort. *) + val is_fprm : Expr.expr -> bool + + (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) + val mk_round_nearest_ties_to_even : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) + val mk_rne : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) + val mk_round_nearest_ties_to_away : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) + val mk_rna : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) + val mk_round_toward_positive : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) + val mk_rtp : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) + val mk_round_toward_negative : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) + val mk_rtn : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) + val mk_round_toward_zero : context -> Expr.expr + + (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) + val mk_rtz : context -> Expr.expr + end + + (** Create a FloatingPoint sort. *) + val mk_sort : context -> int -> int -> Sort.sort + + (** Create the half-precision (16-bit) FloatingPoint sort.*) + val mk_sort_half : context -> Sort.sort + + (** Create the half-precision (16-bit) FloatingPoint sort. *) + val mk_sort_16 : context -> Sort.sort + + (** Create the single-precision (32-bit) FloatingPoint sort.*) + val mk_sort_single : context -> Sort.sort + + (** Create the single-precision (32-bit) FloatingPoint sort. *) + val mk_sort_32 : context -> Sort.sort + + (** Create the double-precision (64-bit) FloatingPoint sort. *) + val mk_sort_double : context -> Sort.sort + + (** Create the double-precision (64-bit) FloatingPoint sort. *) + val mk_sort_64 : context -> Sort.sort + + (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) + val mk_sort_quadruple : context -> Sort.sort + + (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) + val mk_sort_128 : context -> Sort.sort + + (** Create a floating-point NaN of a given FloatingPoint sort. *) + val mk_nan : context -> Sort.sort -> Expr.expr + + (** Create a floating-point infinity of a given FloatingPoint sort. *) + val mk_inf : context -> Sort.sort -> bool -> Expr.expr + + (** Create a floating-point zero of a given FloatingPoint sort. *) + val mk_zero : context -> Sort.sort -> bool -> Expr.expr + + (** Create an expression of FloatingPoint sort from three bit-vector expressions. + + This is the operator named `fp' in the SMT FP theory definition. + Note that \c sign is required to be a bit-vector of size 1. Significand and exponent + are required to be greater than 1 and 2 respectively. The FloatingPoint sort + of the resulting expression is automatically determined from the bit-vector sizes + of the arguments. *) + val mk_fp : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a float. + + This function is used to create numerals that fit in a float value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. *) + val mk_numeral_f : context -> float -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a signed integer. *) + val mk_numeral_i : context -> int -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a sign bit and two integers. *) + val mk_numeral_i_u : context -> bool -> int -> int -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a string *) + val mk_numeral_s : context -> string -> Sort.sort -> Expr.expr + + (** Indicates whether the terms is of floating-point sort. *) + val is_fp : Expr.expr -> bool + + + (** Indicates whether an expression is a floating-point abs expression *) + val is_abs : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point neg expression *) + val is_neg : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point add expression *) + val is_add : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point sub expression *) + val is_sub : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point mul expression *) + val is_mul : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point div expression *) + val is_div : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point fma expression *) + val is_fma : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point sqrt expression *) + val is_sqrt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point rem expression *) + val is_rem : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point round_to_integral expression *) + val is_round_to_integral : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point min expression *) + val is_min : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point max expression *) + val is_max : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point leq expression *) + val is_leq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point lt expression *) + val is_lt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point geqexpression *) + val is_geq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point gt expression *) + val is_gt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point eq expression *) + val is_eq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_normal expression *) + val is_is_normal : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_subnormal expression *) + val is_is_subnormal : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_zero expression *) + val is_is_zero : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_infinite expression *) + val is_is_infinite : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_nan expression *) + val is_is_nan : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_negative expression *) + val is_is_negative : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_positive expression *) + val is_is_positive : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_fp expression *) + val is_to_fp : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_fp_unsigned expression *) + val is_to_fp_unsigned : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_ubv expression *) + val is_to_ubv : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_sbv expression *) + val is_to_sbv : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_real expression *) + val is_to_real : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_ieee_bv expression *) + val is_to_ieee_bv : Expr.expr -> bool + + + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr -> string + + (** Creates a floating-point constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> Expr.expr + + (** Creates a floating-point constant. *) + val mk_const_s : context -> string -> Sort.sort -> Expr.expr + + (** Floating-point absolute value *) + val mk_abs : context -> Expr.expr -> Expr.expr + + (** Floating-point negation *) + val mk_neg : context -> Expr.expr -> Expr.expr + + (** Floating-point addition *) + val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point subtraction *) + val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point multiplication *) + val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point division *) + val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point fused multiply-add. *) + val mk_fma : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point square root *) + val mk_sqrt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point remainder *) + val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point roundToIntegral. + + Rounds a floating-point number to the closest integer, + again represented as a floating-point number. *) + val mk_round_to_integral : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Minimum of floating-point numbers. *) + val mk_min : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Maximum of floating-point numbers. *) + val mk_max : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point less than or equal. *) + val mk_leq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point less than. *) + val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point greater than or equal. *) + val mk_geq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point greater than. *) + val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point equality. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a normal floating-point number. *) + val mk_is_normal : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a subnormal floating-point number. *) + val mk_is_subnormal : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a floating-point number with zero value, i.e., +zero or -zero. *) + val mk_is_zero : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a floating-point number representing +oo or -oo. *) + val mk_is_infinite : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a NaN. *) + val mk_is_nan : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a negative floating-point number. *) + val mk_is_negative : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a positive floating-point number. *) + val mk_is_positive : context -> Expr.expr -> Expr.expr + + (** Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. *) + val mk_to_fp_bv : context -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a FloatingPoint term into another term of different FloatingPoint sort. *) + val mk_to_fp_float : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a term of real sort into a term of FloatingPoint sort. *) + val mk_to_fp_real : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. *) + val mk_to_fp_signed : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a 2's complement unsigned bit-vector term into a term of FloatingPoint sort. *) + val mk_to_fp_unsigned : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** C1onversion of a floating-point term into an unsigned bit-vector. *) + val mk_to_fp_ubv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr + + (** Conversion of a floating-point term into a signed bit-vector. *) + val mk_to_fp_sbv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr + + (** Conversion of a floating-point term into a real-numbered term. *) + val mk_to_fp_real : context -> Expr.expr -> Expr.expr + + (** Retrieves the number of bits reserved for the exponent in a FloatingPoint sort. *) + val get_ebits : context -> Sort.sort -> int + + (** Retrieves the number of bits reserved for the significand in a FloatingPoint sort. *) + val get_sbits : context -> Sort.sort -> int + + (** Retrieves the sign of a floating-point literal. *) + val get_numeral_sign : context -> Expr.expr -> bool * int + + (** Return the significand value of a floating-point numeral as a string. *) + val get_numeral_significand_string : context -> Expr.expr -> string + + (** Return the exponent value of a floating-point numeral as a string *) + val get_numeral_exponent_string : context -> Expr.expr -> string + + (** Return the exponent value of a floating-point numeral as a signed integer *) + val get_numeral_exponent_int : context -> Expr.expr -> bool * int + + (** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *) + val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr + + (** Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. *) + val mk_to_fp_real_int : context -> Expr.expr -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** The string representation of a numeral *) + val numeral_to_string : Expr.expr -> string + end + + (** Functions to manipulate proof expressions *) module Proof : sig From 5f527fa5626dd800db956267e089c782fd18f031 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 15:54:32 +0000 Subject: [PATCH 526/646] documentation fixes Signed-off-by: Christoph M. Wintersteiger --- src/api/z3_fpa.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/api/z3_fpa.h b/src/api/z3_fpa.h index ca5ffebf7..e1bd67d66 100644 --- a/src/api/z3_fpa.h +++ b/src/api/z3_fpa.h @@ -274,7 +274,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_fp(__in Z3_context c, __in Z3_ast sgn, __in Z3_ast exp, __in Z3_ast sig); /** - \brief Create a numeral of FloatingPoint sort from a float. + \brief Create a numeral of FloatingPoint sort from a float. This function is used to create numerals that fit in a float value. It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. @@ -292,20 +292,20 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_numeral_float(__in Z3_context c, __in float v, __in Z3_sort ty); /** - \brief Create a numeral of FloatingPoint sort from a double. + \brief Create a numeral of FloatingPoint sort from a double. - This function is used to create numerals that fit in a double value. - It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. + This function is used to create numerals that fit in a double value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. - \param c logical context - \param v value - \param ty sort + \param c logical context + \param v value + \param ty sort - ty must be a FloatingPoint sort + ty must be a FloatingPoint sort - \sa Z3_mk_numeral + \sa Z3_mk_numeral - def_API('Z3_mk_fpa_numeral_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) + def_API('Z3_mk_fpa_numeral_double', AST, (_in(CONTEXT), _in(DOUBLE), _in(SORT))) */ Z3_ast Z3_API Z3_mk_fpa_numeral_double(__in Z3_context c, __in double v, __in Z3_sort ty); From 9cb50c9f2833a708b1da3c828f0781f6c600554c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 17:33:26 +0000 Subject: [PATCH 527/646] FPA API bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/api_fpa.cpp | 384 +++++++++++++++++++++++++------------------- 1 file changed, 216 insertions(+), 168 deletions(-) diff --git a/src/api/api_fpa.cpp b/src/api/api_fpa.cpp index 86166a5cf..e7ae685fc 100644 --- a/src/api/api_fpa.cpp +++ b/src/api/api_fpa.cpp @@ -14,7 +14,7 @@ Author: Christoph M. Wintersteiger (cwinter) 2013-06-05 Notes: - + --*/ #include #include"z3.h" @@ -27,21 +27,22 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_rounding_mode_sort(c); - RESET_ERROR_CODE(); - api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->fpautil().mk_rm_sort()); - RETURN_Z3(r); + RESET_ERROR_CODE(); + api::context * ctx = mk_c(c); + sort * s = ctx->fpautil().mk_rm_sort(); + mk_c(c)->save_ast_trail(s); + RETURN_Z3(of_sort(s)); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c) - { + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_even(c); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_even()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_nearest_ties_to_even(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -50,19 +51,20 @@ extern "C" { LOG_Z3_mk_fpa_rne(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_even()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_nearest_ties_to_even(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c) - { + Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_nearest_ties_to_away(c); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_away()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_nearest_ties_to_away(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -71,19 +73,20 @@ extern "C" { LOG_Z3_mk_fpa_rna(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_nearest_ties_to_away()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_nearest_ties_to_away(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c) - { + Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_toward_positive(c); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_positive()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_positive(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -92,19 +95,20 @@ extern "C" { LOG_Z3_mk_fpa_rtp(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_positive()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_positive(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c) - { + Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_toward_negative(c); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_negative()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_negative(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -113,19 +117,20 @@ extern "C" { LOG_Z3_mk_fpa_rtn(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_negative()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_negative(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c) - { + Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c) { Z3_TRY; LOG_Z3_mk_fpa_round_toward_zero(c); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_zero()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_zero(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -134,8 +139,9 @@ extern "C" { LOG_Z3_mk_fpa_rtz(c); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_toward_zero()); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_toward_zero(); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -143,13 +149,14 @@ extern "C" { Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits) { Z3_TRY; LOG_Z3_mk_fpa_sort(c, ebits, sbits); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); if (ebits < 2 || sbits < 3) { SET_ERROR_CODE(Z3_INVALID_ARG); - } - api::context * ctx = mk_c(c); - Z3_sort r = of_sort(ctx->fpautil().mk_float_sort(ebits, sbits)); - RETURN_Z3(r); + } + api::context * ctx = mk_c(c); + sort * s = ctx->fpautil().mk_float_sort(ebits, sbits); + ctx->save_ast_trail(s); + RETURN_Z3(of_sort(s)); Z3_CATCH_RETURN(0); } @@ -188,21 +195,23 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_nan(Z3_context c, Z3_sort s) { Z3_TRY; LOG_Z3_mk_fpa_nan(c, s); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_nan(to_sort(s))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_nan(to_sort(s)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_inf(Z3_context c, Z3_sort s, Z3_bool negative) { Z3_TRY; LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpautil().mk_ninf(to_sort(s)) : - ctx->fpautil().mk_pinf(to_sort(s))); - RETURN_Z3(r); + expr * a = negative != 0 ? ctx->fpautil().mk_ninf(to_sort(s)) : + ctx->fpautil().mk_pinf(to_sort(s)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -211,9 +220,10 @@ extern "C" { LOG_Z3_mk_fpa_inf(c, s, negative); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(negative != 0 ? ctx->fpautil().mk_nzero(to_sort(s)) : - ctx->fpautil().mk_pzero(to_sort(s))); - RETURN_Z3(r); + expr * a = negative != 0 ? ctx->fpautil().mk_nzero(to_sort(s)) : + ctx->fpautil().mk_pzero(to_sort(s)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -222,8 +232,9 @@ extern "C" { LOG_Z3_mk_fpa_fp(c, sgn, sig, exp); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_fp(to_expr(sgn), to_expr(sig), to_expr(exp)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -233,12 +244,13 @@ extern "C" { RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); - ctx->fpautil().fm().set(tmp, - ctx->fpautil().get_ebits(to_sort(ty)), - ctx->fpautil().get_sbits(to_sort(ty)), - v); - Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); - RETURN_Z3(r); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), + v); + expr * a = ctx->fpautil().mk_value(tmp); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -249,8 +261,9 @@ extern "C" { api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); ctx->fpautil().fm().set(tmp, ctx->fpautil().get_ebits(to_sort(ty)), ctx->fpautil().get_sbits(to_sort(ty)), v); - Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_value(tmp); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -261,11 +274,12 @@ extern "C" { api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); ctx->fpautil().fm().set(tmp, - ctx->fpautil().get_ebits(to_sort(ty)), - ctx->fpautil().get_sbits(to_sort(ty)), - v); - Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); - RETURN_Z3(r); + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), + v); + expr * a = ctx->fpautil().mk_value(tmp); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -275,12 +289,13 @@ extern "C" { RESET_ERROR_CODE(); api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); - ctx->fpautil().fm().set(tmp, - ctx->fpautil().get_ebits(to_sort(ty)), - ctx->fpautil().get_sbits(to_sort(ty)), - sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); - RETURN_Z3(r); + ctx->fpautil().fm().set(tmp, + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), + sgn != 0, sig, exp); + expr * a = ctx->fpautil().mk_value(tmp); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -291,111 +306,122 @@ extern "C" { api::context * ctx = mk_c(c); scoped_mpf tmp(ctx->fpautil().fm()); ctx->fpautil().fm().set(tmp, - ctx->fpautil().get_ebits(to_sort(ty)), - ctx->fpautil().get_sbits(to_sort(ty)), - sgn != 0, sig, exp); - Z3_ast r = of_ast(ctx->fpautil().mk_value(tmp)); - RETURN_Z3(r); + ctx->fpautil().get_ebits(to_sort(ty)), + ctx->fpautil().get_sbits(to_sort(ty)), + sgn != 0, sig, exp); + expr * a = ctx->fpautil().mk_value(tmp); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_abs(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_abs(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_abs(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_neg(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_neg(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_neg(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_neg(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_add(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_add(to_expr(rm), to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_add(to_expr(rm), to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_sub(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_sub(to_expr(rm), to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_mul(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_mul(to_expr(rm), to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_div(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_add(c, rm, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_div(to_expr(rm), to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_div(to_expr(rm), to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_fma(Z3_context c, Z3_ast rm, Z3_ast t1, Z3_ast t2, Z3_ast t3) { Z3_TRY; LOG_Z3_mk_fpa_fma(c, rm, t1, t2, t3); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_fma(to_expr(rm), to_expr(t1), to_expr(t2), to_expr(t3)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_sqrt(Z3_context c, Z3_ast rm, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_sqrt(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_sqrt(to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_sqrt(to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_rem(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_rem(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_rem(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_rem(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_round_to_integral(Z3_context c, Z3_ast rm, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_round_to_integral(c, rm, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_round_to_integral(to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_round_to_integral(to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -404,8 +430,9 @@ extern "C" { LOG_Z3_mk_fpa_min(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_min(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_min(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -418,14 +445,15 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_leq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_le(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_le(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -434,18 +462,20 @@ extern "C" { LOG_Z3_mk_fpa_lt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_lt(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_lt(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; LOG_Z3_mk_fpa_geq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_ge(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_ge(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -454,8 +484,9 @@ extern "C" { LOG_Z3_mk_fpa_gt(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_gt(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_gt(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -464,18 +495,20 @@ extern "C" { LOG_Z3_mk_fpa_eq(c, t1, t2); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_float_eq(to_expr(t1), to_expr(t2))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_float_eq(to_expr(t1), to_expr(t2)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_fpa_is_normal(Z3_context c, Z3_ast t) { Z3_TRY; LOG_Z3_mk_fpa_is_normal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_normal(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_normal(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -484,8 +517,9 @@ extern "C" { LOG_Z3_mk_fpa_is_subnormal(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_subnormal(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_subnormal(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -494,8 +528,9 @@ extern "C" { LOG_Z3_mk_fpa_is_zero(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_zero(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_zero(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -504,8 +539,9 @@ extern "C" { LOG_Z3_mk_fpa_is_infinite(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_inf(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_inf(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -514,8 +550,9 @@ extern "C" { LOG_Z3_mk_fpa_is_nan(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_nan(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_nan(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -524,8 +561,9 @@ extern "C" { LOG_Z3_mk_fpa_is_negative(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_negative(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_negative(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -534,8 +572,9 @@ extern "C" { LOG_Z3_mk_fpa_is_positive(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_is_positive(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_is_positive(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -551,8 +590,9 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(bv))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp(to_sort(s), to_expr(bv)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -562,14 +602,15 @@ extern "C" { RESET_ERROR_CODE(); api::context * ctx = mk_c(c); fpa_util & fu = ctx->fpautil(); - if (!fu.is_rm(to_expr(rm)) || + if (!fu.is_rm(to_expr(rm)) || !fu.is_float(to_expr(t)) || !fu.is_float(to_sort(s))) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -585,8 +626,9 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -602,8 +644,9 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -613,14 +656,15 @@ extern "C" { RESET_ERROR_CODE(); api::context * ctx = mk_c(c); fpa_util & fu = ctx->fpautil(); - if (!fu.is_rm(to_expr(rm)) || + if (!fu.is_rm(to_expr(rm)) || !ctx->bvutil().is_bv(to_expr(t)) || !fu.is_float(to_sort(s))) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp_unsigned(to_sort(s), to_expr(rm), to_expr(t))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp_unsigned(to_sort(s), to_expr(rm), to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -629,8 +673,9 @@ extern "C" { LOG_Z3_mk_fpa_to_ubv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_to_ubv(to_expr(rm), to_expr(t), sz)); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_to_ubv(to_expr(rm), to_expr(t), sz); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -639,8 +684,9 @@ extern "C" { LOG_Z3_mk_fpa_to_sbv(c, rm, t, sz); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_to_sbv(to_expr(rm), to_expr(t), sz)); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_to_sbv(to_expr(rm), to_expr(t), sz); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -649,8 +695,9 @@ extern "C" { LOG_Z3_mk_fpa_to_real(c, t); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); - Z3_ast r = of_ast(ctx->fpautil().mk_to_real(to_expr(t))); - RETURN_Z3(r); + expr * a = ctx->fpautil().mk_to_real(to_expr(t)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } @@ -689,7 +736,7 @@ extern "C" { return r; Z3_CATCH_RETURN(0); } - + Z3_string Z3_API Z3_fpa_get_numeral_significand_string(__in Z3_context c, __in Z3_ast t) { Z3_TRY; LOG_Z3_fpa_get_numeral_significand_string(c, t); @@ -699,14 +746,14 @@ extern "C" { unsynch_mpz_manager & mpzm = mpfm.mpz_manager(); unsynch_mpq_manager & mpqm = mpfm.mpq_manager(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); - scoped_mpf val(mpfm); - if (!plugin->is_numeral(to_expr(t), val)) { + scoped_mpf val(mpfm); + if (!plugin->is_numeral(to_expr(t), val)) { SET_ERROR_CODE(Z3_INVALID_ARG); return ""; } else if (!mpfm.is_regular(val)) { SET_ERROR_CODE(Z3_INVALID_ARG) - return ""; + return ""; } unsigned sbits = val.get().get_sbits(); scoped_mpq q(mpqm); @@ -726,7 +773,7 @@ extern "C" { LOG_Z3_fpa_get_numeral_exponent_string(c, t); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); - mpf_manager & mpfm = mk_c(c)->fpautil().fm(); + mpf_manager & mpfm = mk_c(c)->fpautil().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); bool r = plugin->is_numeral(to_expr(t), val); @@ -738,7 +785,7 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG) return ""; } - mpf_exp_t exp = mpfm.exp_normalized(val); + mpf_exp_t exp = mpfm.exp_normalized(val); std::stringstream ss; ss << exp; return mk_c(c)->mk_external_string(ss.str()); @@ -753,7 +800,7 @@ extern "C" { mpf_manager & mpfm = mk_c(c)->fpautil().fm(); fpa_decl_plugin * plugin = (fpa_decl_plugin*)m.get_plugin(mk_c(c)->get_fpa_fid()); scoped_mpf val(mpfm); - bool r = plugin->is_numeral(to_expr(t), val); + bool r = plugin->is_numeral(to_expr(t), val); if (!r) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; @@ -775,7 +822,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_fpa_to_fp_int_real(Z3_context c, Z3_ast rm, Z3_ast exp, Z3_ast sig, Z3_sort s) { Z3_TRY; - LOG_Z3_mk_fpa_to_fp_int_real(c, rm, exp, sig, s); + LOG_Z3_mk_fpa_to_fp_int_real(c, rm, sig, exp, s); RESET_ERROR_CODE(); api::context * ctx = mk_c(c); fpa_util & fu = ctx->fpautil(); @@ -786,8 +833,9 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - Z3_ast r = of_ast(fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(sig), to_expr(exp))); - RETURN_Z3(r); + expr * a = fu.mk_to_fp(to_sort(s), to_expr(rm), to_expr(sig), to_expr(exp)); + ctx->save_ast_trail(a); + RETURN_Z3(of_expr(a)); Z3_CATCH_RETURN(0); } From 5c7d0380d3c2d5fba59d0da2f62f870feaf279cc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 18:29:52 +0000 Subject: [PATCH 528/646] Fixes in the OCaml FPA API and example --- examples/ml/ml_example.ml | 93 ++--- scripts/mk_util.py | 2 +- src/api/ml/z3.ml | 25 +- src/api/ml/z3.mli | 754 +++++++++++++++++++------------------- 4 files changed, 436 insertions(+), 438 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 8a2d71d82..127a973aa 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -247,6 +247,8 @@ open Z3.FloatingPoint **) let fpa_example ( ctx : context ) = Printf.printf "FPAExample\n" ; + (* let str = ref "" in *) + (* (read_line ()) ; *) let double_sort = (FloatingPoint.mk_sort_double ctx) in let rm_sort = (FloatingPoint.RoundingMode.mk_sort ctx) in @@ -257,63 +259,64 @@ let fpa_example ( ctx : context ) = let s_y = (mk_string ctx "y") in let x = (mk_const ctx s_x double_sort) in let y = (mk_const ctx s_y double_sort)in - Printf.printf "A\n" ; - let n = (mk_numeral_f ctx 42.0 double_sort) in - Printf.printf "B\n" ; + let n = (FloatingPoint.mk_numeral_f ctx 42.0 double_sort) in let s_x_plus_y = (mk_string ctx "x_plus_y") in let x_plus_y = (mk_const ctx s_x_plus_y double_sort) in let c1 = (mk_eq ctx x_plus_y (mk_add ctx rm x y)) in let args = [ c1 ; (mk_eq ctx x_plus_y n) ] in let c2 = (Boolean.mk_and ctx args) in - let args2 = [ c2 ; (Boolean.mk_not ctx (mk_eq ctx rm (RoundingMode.mk_rtz ctx))) ] in + let args2 = [ c2 ; (Boolean.mk_not ctx (Boolean.mk_eq ctx rm (RoundingMode.mk_rtz ctx))) ] in let c3 = (Boolean.mk_and ctx args2) in let and_args = [ (Boolean.mk_not ctx (mk_is_zero ctx y)) ; (Boolean.mk_not ctx (mk_is_nan ctx y)) ; (Boolean.mk_not ctx (mk_is_infinite ctx y)) ] in let args3 = [ c3 ; (Boolean.mk_and ctx and_args) ] in - let c4 = (Boolean.mk_and ctx args3) in - - (Printf.printf "c4: %s\n" (Expr.to_string c4)) - (* push(ctx); *) - (* Z3_assert_cnstr(ctx, c4); *) - (* check(ctx, Z3_L_TRUE); *) - (* Z3_pop(ctx, 1); *) + let c4 = (Boolean.mk_and ctx args3) in + (Printf.printf "c4: %s\n" (Expr.to_string c4)) ; + ( + let solver = (mk_solver ctx None) in + (Solver.add solver [ c4 ]) ; + if (check solver []) != SATISFIABLE then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ); - (* // Show that the following are equal: *) - (* // (fp #b0 #b10000000001 #xc000000000000) *) - (* // ((_ to_fp 11 53) #x401c000000000000)) *) - (* // ((_ to_fp 11 53) RTZ 1.75 2))) *) - (* // ((_ to_fp 11 53) RTZ 7.0))) *) +(* Show that the following are equal: *) +(* (fp #b0 #b10000000001 #xc000000000000) *) +(* ((_ to_fp 11 53) #x401c000000000000)) *) +(* ((_ to_fp 11 53) RTZ 1.75 2))) *) +(* ((_ to_fp 11 53) RTZ 7.0))) *) - (* Z3_push(ctx); *) - (* c1 = Z3_mk_fpa_fp(ctx, *) - (* Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)), *) - (* Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)), *) - (* Z3_mk_numeral(ctx, "1025", Z3_mk_bv_sort(ctx, 11))); *) - (* c2 = Z3_mk_fpa_to_fp_bv(ctx, *) - (* Z3_mk_numeral(ctx, "4619567317775286272", Z3_mk_bv_sort(ctx, 64)), *) - (* Z3_mk_fpa_sort(ctx, 11, 53)); *) - (* c3 = Z3_mk_fpa_to_fp_real_int(ctx, *) - (* Z3_mk_fpa_rtz(ctx), *) - (* Z3_mk_numeral(ctx, "1.75", Z3_mk_real_sort(ctx)), *) - (* Z3_mk_numeral(ctx, "2", Z3_mk_int_sort(ctx)), *) - (* Z3_mk_fpa_sort(ctx, 11, 53)); *) - (* c4 = Z3_mk_fpa_to_fp_real(ctx, *) - (* Z3_mk_fpa_rtz(ctx), *) - (* Z3_mk_numeral(ctx, "7.0", Z3_mk_real_sort(ctx)), *) - (* Z3_mk_fpa_sort(ctx, 11, 53)); *) - (* args3[0] = Z3_mk_eq(ctx, c1, c2); *) - (* args3[1] = Z3_mk_eq(ctx, c1, c3); *) - (* args3[2] = Z3_mk_eq(ctx, c1, c4); *) - (* c5 = Z3_mk_and(ctx, 3, args3); *) - - (* printf("c5: %s\n", Z3_ast_to_string(ctx, c5)); *) - (* Z3_assert_cnstr(ctx, c5); *) - (* check(ctx, Z3_L_TRUE); *) - (* Z3_pop(ctx, 1); *) - - (* Z3_del_context(ctx); *) - + let solver = (mk_solver ctx None) in + let c1 = (mk_fp ctx + (mk_numeral_string ctx "0" (BitVector.mk_sort ctx 1)) + (mk_numeral_string ctx "3377699720527872" (BitVector.mk_sort ctx 52)) + (mk_numeral_string ctx "1025" (BitVector.mk_sort ctx 11))) in + let c2 = (mk_to_fp_bv ctx + (mk_numeral_string ctx "4619567317775286272" (BitVector.mk_sort ctx 64)) + (mk_sort ctx 11 53)) in + let c3 = (mk_to_fp_int_real ctx + (RoundingMode.mk_rtz ctx) + (mk_numeral_string ctx "2" (Integer.mk_sort ctx)) + (mk_numeral_string ctx "1.75" (Real.mk_sort ctx)) + (FloatingPoint.mk_sort ctx 11 53)) in + let c4 = (mk_to_fp_real ctx (RoundingMode.mk_rtz ctx) + (mk_numeral_string ctx "7.0" (Real.mk_sort ctx)) + (FloatingPoint.mk_sort ctx 11 53)) in + let args3 = [ (mk_eq ctx c1 c2) ; + (mk_eq ctx c1 c3) ; + (mk_eq ctx c1 c4) ] in + let c5 = (Boolean.mk_and ctx args3) in + (Printf.printf "c5: %s\n" (Expr.to_string c5)) ; + ( + let solver = (mk_solver ctx None) in + (Solver.add solver [ c5 ]) ; + if (check solver []) != SATISFIABLE then + raise (TestFailedException "") + else + Printf.printf "Test passed.\n" + ) let _ = try ( diff --git a/scripts/mk_util.py b/scripts/mk_util.py index af0c59355..2ed420c20 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -546,7 +546,7 @@ def parse_options(): 'b:df:sxhmcvtnp:gj', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'foci2=', 'java', 'parallel=', 'gprof', - 'githash=', 'x86']) + 'githash=', 'x86', 'ml']) except: print("ERROR: Invalid command line option") display_help(1) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 601da1cbc..fe78b65a6 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1479,9 +1479,9 @@ struct let is_modulus ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD) - let is_inttoreal ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) + let is_int2real ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL) - let is_real_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) + let is_real2int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT) let is_real_is_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT) @@ -1686,8 +1686,8 @@ struct let is_bv_rotateright ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT) let is_bv_rotateleftextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT) let is_bv_rotaterightextended ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT) - let is_int_to_bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) - let is_bv_to_int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) + let is_int2bv ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV) + let is_bv2int ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT) let is_bv_carry ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY) let is_bv_xor3 ( x : expr ) = (AST.is_app (Expr.ast_of_expr x)) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3) let get_size (x : sort ) = Z3native.get_bv_sort_size (Sort.gnc x) (Sort.gno x) @@ -1847,6 +1847,7 @@ struct (sort_of_ptr ctx (Z3native.mk_fpa_sort_quadruple (context_gno ctx))) let mk_sort_128 ( ctx : context ) = (sort_of_ptr ctx (Z3native.mk_fpa_sort_128 (context_gno ctx))) + let mk_nan ( ctx : context ) ( s : sort ) = (expr_of_ptr ctx (Z3native.mk_fpa_nan (context_gno ctx) (Sort.gno s))) let mk_inf ( ctx : context ) ( s : sort ) ( negative : bool ) = @@ -1857,11 +1858,11 @@ struct let mk_fp ( ctx : context ) ( sign : expr ) ( exponent : expr ) ( significand : expr ) = (expr_of_ptr ctx (Z3native.mk_fpa_fp (context_gno ctx) (Expr.gno sign) (Expr.gno exponent) (Expr.gno significand))) let mk_numeral_f ( ctx : context ) ( value : float ) ( s : sort ) = - (expr_of_ptr ctx (Z3native.mk_fpa_numeral_double (context_gno ctx) value (Sort.gno s))) + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_double (context_gno ctx) value (Sort.gno s))) let mk_numeral_i ( ctx : context ) ( value : int ) ( s : sort ) = - (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int (context_gno ctx) value (Sort.gno s))) + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int (context_gno ctx) value (Sort.gno s))) let mk_numeral_i_u ( ctx : context ) ( sign : bool ) ( exponent : int ) ( significand : int ) ( s : sort ) = - (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int64_uint64 (context_gno ctx) sign exponent significand (Sort.gno s))) + (expr_of_ptr ctx (Z3native.mk_fpa_numeral_int64_uint64 (context_gno ctx) sign exponent significand (Sort.gno s))) let mk_numeral_s ( ctx : context ) ( v : string ) ( s : sort ) = (expr_of_ptr ctx (Z3native.mk_numeral (context_gno ctx) v (Sort.gno s))) @@ -1961,11 +1962,11 @@ struct expr_of_ptr ctx (Z3native.mk_fpa_to_fp_signed (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) let mk_to_fp_unsigned ( ctx : context ) ( rm : expr) ( t : expr ) ( s : sort ) = expr_of_ptr ctx (Z3native.mk_fpa_to_fp_unsigned (context_gno ctx) (Expr.gno rm) (Expr.gno t) (Sort.gno s)) - let mk_to_fp_ubv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = + let mk_to_ubv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = expr_of_ptr ctx (Z3native.mk_fpa_to_ubv (context_gno ctx) (Expr.gno rm) (Expr.gno t) size) - let mk_to_fp_sbv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = + let mk_to_sbv ( ctx : context ) ( rm : expr) ( t : expr ) ( size : int ) = expr_of_ptr ctx (Z3native.mk_fpa_to_sbv (context_gno ctx) (Expr.gno rm) (Expr.gno t) size) - let mk_to_fp_real ( ctx : context ) ( t : expr ) = + let mk_to_real ( ctx : context ) ( t : expr ) = expr_of_ptr ctx (Z3native.mk_fpa_to_real (context_gno ctx) (Expr.gno t)) let get_ebits ( ctx : context ) ( s : sort ) = @@ -1983,8 +1984,8 @@ struct let mk_to_ieee_bv ( ctx : context ) ( t : expr ) = (expr_of_ptr ctx (Z3native.mk_fpa_to_ieee_bv (context_gno ctx) (Expr.gno t))) - let mk_to_fp_real_int ( ctx : context ) ( rm : expr ) ( exponent : expr ) ( significand : expr ) ( s : sort) = - (expr_of_ptr ctx (Z3native.mk_fpa_to_fp_real_int (context_gno ctx) (Expr.gno rm) (Expr.gno exponent) (Expr.gno significand) (Sort.gno s))) + let mk_to_fp_int_real ( ctx : context ) ( rm : expr ) ( exponent : expr ) ( significand : expr ) ( s : sort ) = + (expr_of_ptr ctx (Z3native.mk_fpa_to_fp_int_real (context_gno ctx) (Expr.gno rm) (Expr.gno exponent) (Expr.gno significand) (Sort.gno s))) let numeral_to_string ( x : expr ) = Z3native.get_numeral_string (Expr.gnc x) (Expr.gno x) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index ab2a14725..aa526417e 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -139,7 +139,7 @@ sig val get_size : ast_vector -> int (** Retrieves the i-th object in the vector. - @return An AST *) + @return An AST *) val get : ast_vector -> int -> ast (** Sets the i-th object in the vector. *) @@ -149,11 +149,11 @@ sig val resize : ast_vector -> int -> unit (** Add an ast to the back of the vector. The size - is increased by 1. *) + is increased by 1. *) val push : ast_vector -> ast -> unit (** Translates all ASTs in the vector to another context. - @return A new ASTVector *) + @return A new ASTVector *) val translate : ast_vector -> context -> ast_vector (** Retrieves a string representation of the vector. *) @@ -169,11 +169,11 @@ sig val mk_ast_map : context -> ast_map (** Checks whether the map contains a key. - @return True if the key in the map, false otherwise. *) + @return True if the key in the map, false otherwise. *) val contains : ast_map -> ast -> bool (** Finds the value associated with the key. - This function signs an error when the key is not a key in the map. *) + This function signs an error when the key is not a key in the map. *) val find : ast_map -> ast -> ast (** Stores or replaces a new key/value pair in the map. *) @@ -302,14 +302,14 @@ sig sig (** Parameters of func_decls *) type parameter = - P_Int of int + P_Int of int | P_Dbl of float | P_Sym of Symbol.symbol | P_Srt of Sort.sort | P_Ast of AST.ast | P_Fdl of func_decl | P_Rat of string - + (** The kind of the parameter. *) val get_kind : parameter -> Z3enums.parameter_kind @@ -723,7 +723,7 @@ sig (** The no-patterns. *) val get_no_patterns : quantifier -> Pattern.pattern list - (** The number of bound variables. *) + (** The number of bound variables. *) val get_num_bound : quantifier -> int (** The symbols for the bound variables. *) @@ -759,7 +759,7 @@ sig (** Create a Quantifier. *) val mk_quantifier : context -> bool -> Expr.expr list -> Expr.expr -> int option -> Pattern.pattern list -> Expr.expr list -> Symbol.symbol option -> Symbol.symbol option -> quantifier - (** A string representation of the quantifier. *) + (** A string representation of the quantifier. *) val to_string : quantifier -> string end @@ -1167,38 +1167,36 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create an expression representing [t1 mod t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an expression representing [t1 rem t2]. - The arguments must have int type. *) + The arguments must have int type. *) val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr (** Create an integer numeral. *) val mk_numeral_s : context -> string -> Expr.expr (** Create an integer numeral. - @return A Term with the given value and sort Integer *) + @return A Term with the given value and sort Integer *) val mk_numeral_i : context -> int -> Expr.expr - (** Coerce an integer to a real. - - - There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. - - You can take the floor of a real by creating an auxiliary integer Term [k] and - and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. - The argument must be of integer sort. *) + (** Coerce an integer to a real. + + There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. + + You can take the floor of a real by creating an auxiliary integer Term [k] and + and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1]. + The argument must be of integer sort. *) val mk_int2real : context -> Expr.expr -> Expr.expr - (** Create an n-bit bit-vector from an integer argument. - - - NB. This function is essentially treated as uninterpreted. - So you cannot expect Z3 to precisely reflect the semantics of this function - when solving constraints with this function. - - The argument must be of integer sort. *) + (** Create an n-bit bit-vector from an integer argument. + + NB. This function is essentially treated as uninterpreted. + So you cannot expect Z3 to precisely reflect the semantics of this function + when solving constraints with this function. + + The argument must be of integer sort. *) val mk_int2bv : context -> int -> Expr.expr -> Expr.expr end @@ -1218,7 +1216,7 @@ sig val get_ratio : Expr.expr -> Ratio.ratio (** Returns a string representation in decimal notation. - The result has at most as many decimal places as indicated by the int argument.*) + The result has at most as many decimal places as indicated by the int argument.*) val to_decimal_string : Expr.expr-> int -> string (** Returns a string representation of a numeral. *) @@ -1231,16 +1229,16 @@ sig val mk_const_s : context -> string -> Expr.expr (** Create a real numeral from a fraction. - @return A Term with rational value and sort Real - {!mk_numeral_s} *) + @return A Term with rational value and sort Real + {!mk_numeral_s} *) val mk_numeral_nd : context -> int -> int -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_s : context -> string -> Expr.expr (** Create a real numeral. - @return A Term with the given value and sort Real *) + @return A Term with the given value and sort Real *) val mk_numeral_i : context -> int -> Expr.expr (** Creates an expression that checks whether a real number is an integer. *) @@ -1248,29 +1246,29 @@ sig (** Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard for the function to_int. - The argument must be of real sort. *) + The semantics of this function follows the SMT-LIB standard for the function to_int. + The argument must be of real sort. *) val mk_real2int : context -> Expr.expr -> Expr.expr (** Algebraic Numbers *) module AlgebraicNumber : sig (** Return a upper bound for a given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) val to_upper : Expr.expr -> int -> Expr.expr - + (** Return a lower bound for the given real algebraic number. - The interval isolating the number is smaller than 1/10^precision. - {!is_algebraic_number} - @return A numeral Expr of sort Real *) + The interval isolating the number is smaller than 1/10^precision. + {!is_algebraic_number} + @return A numeral Expr of sort Real *) val to_lower : Expr.expr -> int -> Expr.expr - + (** Returns a string representation in decimal notation. - The result has at most as many decimal places as the int argument provided.*) + The result has at most as many decimal places as the int argument provided.*) val to_decimal_string : Expr.expr -> int -> string - + (** Returns a string representation of a numeral. *) val numeral_to_string : Expr.expr -> string end @@ -1319,10 +1317,10 @@ sig val is_modulus : Expr.expr -> bool (** Indicates whether the term is a coercion of integer to real (unary) *) - val is_inttoreal : Expr.expr -> bool + val is_int2real : Expr.expr -> bool (** Indicates whether the term is a coercion of real to integer (unary) *) - val is_real_to_int : Expr.expr -> bool + val is_real2int : Expr.expr -> bool (** Indicates whether the term is a check that tests whether a real is integral (unary) *) val is_real_is_int : Expr.expr -> bool @@ -1522,19 +1520,15 @@ sig Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. *) val is_bv_rotaterightextended : Expr.expr -> bool - (** Indicates whether the term is a coercion from integer to bit-vector - This function is not supported by the decision procedures. Only the most - rudimentary simplification rules are applied to this function. *) - (** Indicates whether the term is a coercion from bit-vector to integer This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - val is_int_to_bv : Expr.expr -> bool + val is_int2bv : Expr.expr -> bool (** Indicates whether the term is a coercion from integer to bit-vector This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. *) - val is_bv_to_int : Expr.expr -> bool + val is_bv2int : Expr.expr -> bool (** Indicates whether the term is a bit-vector carry Compute the carry bit in a full-adder. The meaning is given by the @@ -1832,339 +1826,339 @@ end (** Floating-Point Arithmetic *) module FloatingPoint : +sig + + (** Rounding Modes *) + module RoundingMode : sig + (** Create the RoundingMode sort. *) + val mk_sort : context -> Sort.sort - (** Rounding Modes *) - module RoundingMode : - sig - (** Create the RoundingMode sort. *) - val mk_sort : context -> Sort.sort + (** Indicates whether the terms is of floating-point rounding mode sort. *) + val is_fprm : Expr.expr -> bool - (** Indicates whether the terms is of floating-point rounding mode sort. *) - val is_fprm : Expr.expr -> bool - - (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) - val mk_round_nearest_ties_to_even : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) - val mk_rne : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) - val mk_round_nearest_ties_to_away : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) - val mk_rna : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) - val mk_round_toward_positive : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) - val mk_rtp : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) - val mk_round_toward_negative : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) - val mk_rtn : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) - val mk_round_toward_zero : context -> Expr.expr - - (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) - val mk_rtz : context -> Expr.expr - end - - (** Create a FloatingPoint sort. *) - val mk_sort : context -> int -> int -> Sort.sort - - (** Create the half-precision (16-bit) FloatingPoint sort.*) - val mk_sort_half : context -> Sort.sort - - (** Create the half-precision (16-bit) FloatingPoint sort. *) - val mk_sort_16 : context -> Sort.sort - - (** Create the single-precision (32-bit) FloatingPoint sort.*) - val mk_sort_single : context -> Sort.sort - - (** Create the single-precision (32-bit) FloatingPoint sort. *) - val mk_sort_32 : context -> Sort.sort - - (** Create the double-precision (64-bit) FloatingPoint sort. *) - val mk_sort_double : context -> Sort.sort - - (** Create the double-precision (64-bit) FloatingPoint sort. *) - val mk_sort_64 : context -> Sort.sort + (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) + val mk_round_nearest_ties_to_even : context -> Expr.expr - (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) - val mk_sort_quadruple : context -> Sort.sort + (** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *) + val mk_rne : context -> Expr.expr - (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) - val mk_sort_128 : context -> Sort.sort - - (** Create a floating-point NaN of a given FloatingPoint sort. *) - val mk_nan : context -> Sort.sort -> Expr.expr - - (** Create a floating-point infinity of a given FloatingPoint sort. *) - val mk_inf : context -> Sort.sort -> bool -> Expr.expr - - (** Create a floating-point zero of a given FloatingPoint sort. *) - val mk_zero : context -> Sort.sort -> bool -> Expr.expr - - (** Create an expression of FloatingPoint sort from three bit-vector expressions. - - This is the operator named `fp' in the SMT FP theory definition. - Note that \c sign is required to be a bit-vector of size 1. Significand and exponent - are required to be greater than 1 and 2 respectively. The FloatingPoint sort - of the resulting expression is automatically determined from the bit-vector sizes - of the arguments. *) - val mk_fp : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Create a numeral of FloatingPoint sort from a float. - - This function is used to create numerals that fit in a float value. - It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. *) - val mk_numeral_f : context -> float -> Sort.sort -> Expr.expr - - (** Create a numeral of FloatingPoint sort from a signed integer. *) - val mk_numeral_i : context -> int -> Sort.sort -> Expr.expr + (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) + val mk_round_nearest_ties_to_away : context -> Expr.expr - (** Create a numeral of FloatingPoint sort from a sign bit and two integers. *) - val mk_numeral_i_u : context -> bool -> int -> int -> Sort.sort -> Expr.expr - - (** Create a numeral of FloatingPoint sort from a string *) - val mk_numeral_s : context -> string -> Sort.sort -> Expr.expr - - (** Indicates whether the terms is of floating-point sort. *) - val is_fp : Expr.expr -> bool - - - (** Indicates whether an expression is a floating-point abs expression *) - val is_abs : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point neg expression *) - val is_neg : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point add expression *) - val is_add : Expr.expr -> bool + (** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *) + val mk_rna : context -> Expr.expr - (** Indicates whether an expression is a floating-point sub expression *) - val is_sub : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point mul expression *) - val is_mul : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point div expression *) - val is_div : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point fma expression *) - val is_fma : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point sqrt expression *) - val is_sqrt : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point rem expression *) - val is_rem : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point round_to_integral expression *) - val is_round_to_integral : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point min expression *) - val is_min : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point max expression *) - val is_max : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point leq expression *) - val is_leq : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point lt expression *) - val is_lt : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point geqexpression *) - val is_geq : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point gt expression *) - val is_gt : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point eq expression *) - val is_eq : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_normal expression *) - val is_is_normal : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_subnormal expression *) - val is_is_subnormal : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_zero expression *) - val is_is_zero : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_infinite expression *) - val is_is_infinite : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_nan expression *) - val is_is_nan : Expr.expr -> bool + (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) + val mk_round_toward_positive : context -> Expr.expr - (** Indicates whether an expression is a floating-point is_negative expression *) - val is_is_negative : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point is_positive expression *) - val is_is_positive : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_fp expression *) - val is_to_fp : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_fp_unsigned expression *) - val is_to_fp_unsigned : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_ubv expression *) - val is_to_ubv : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_sbv expression *) - val is_to_sbv : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_real expression *) - val is_to_real : Expr.expr -> bool - - (** Indicates whether an expression is a floating-point to_ieee_bv expression *) - val is_to_ieee_bv : Expr.expr -> bool - - - (** Returns a string representation of a numeral. *) - val numeral_to_string : Expr.expr -> string - - (** Creates a floating-point constant. *) - val mk_const : context -> Symbol.symbol -> Sort.sort -> Expr.expr - - (** Creates a floating-point constant. *) - val mk_const_s : context -> string -> Sort.sort -> Expr.expr - - (** Floating-point absolute value *) - val mk_abs : context -> Expr.expr -> Expr.expr - - (** Floating-point negation *) - val mk_neg : context -> Expr.expr -> Expr.expr - - (** Floating-point addition *) - val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point subtraction *) - val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point multiplication *) - val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point division *) - val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point fused multiply-add. *) - val mk_fma : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + (** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *) + val mk_rtp : context -> Expr.expr - (** Floating-point square root *) - val mk_sqrt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point remainder *) - val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr + (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) + val mk_round_toward_negative : context -> Expr.expr - (** Floating-point roundToIntegral. - - Rounds a floating-point number to the closest integer, - again represented as a floating-point number. *) - val mk_round_to_integral : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Minimum of floating-point numbers. *) - val mk_min : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Maximum of floating-point numbers. *) - val mk_max : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point less than or equal. *) - val mk_leq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point less than. *) - val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point greater than or equal. *) - val mk_geq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point greater than. *) - val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Floating-point equality. *) - val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a normal floating-point number. *) - val mk_is_normal : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a subnormal floating-point number. *) - val mk_is_subnormal : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a floating-point number with zero value, i.e., +zero or -zero. *) - val mk_is_zero : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a floating-point number representing +oo or -oo. *) - val mk_is_infinite : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a NaN. *) - val mk_is_nan : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a negative floating-point number. *) - val mk_is_negative : context -> Expr.expr -> Expr.expr - - (** Predicate indicating whether t is a positive floating-point number. *) - val mk_is_positive : context -> Expr.expr -> Expr.expr - - (** Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. *) - val mk_to_fp_bv : context -> Expr.expr -> Sort.sort -> Expr.expr - - (** Conversion of a FloatingPoint term into another term of different FloatingPoint sort. *) - val mk_to_fp_float : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr - - (** Conversion of a term of real sort into a term of FloatingPoint sort. *) - val mk_to_fp_real : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr - - (** Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. *) - val mk_to_fp_signed : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr - - (** Conversion of a 2's complement unsigned bit-vector term into a term of FloatingPoint sort. *) - val mk_to_fp_unsigned : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr - - (** C1onversion of a floating-point term into an unsigned bit-vector. *) - val mk_to_fp_ubv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr - - (** Conversion of a floating-point term into a signed bit-vector. *) - val mk_to_fp_sbv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr - - (** Conversion of a floating-point term into a real-numbered term. *) - val mk_to_fp_real : context -> Expr.expr -> Expr.expr + (** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *) + val mk_rtn : context -> Expr.expr - (** Retrieves the number of bits reserved for the exponent in a FloatingPoint sort. *) - val get_ebits : context -> Sort.sort -> int - - (** Retrieves the number of bits reserved for the significand in a FloatingPoint sort. *) - val get_sbits : context -> Sort.sort -> int + (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) + val mk_round_toward_zero : context -> Expr.expr - (** Retrieves the sign of a floating-point literal. *) - val get_numeral_sign : context -> Expr.expr -> bool * int - - (** Return the significand value of a floating-point numeral as a string. *) - val get_numeral_significand_string : context -> Expr.expr -> string - - (** Return the exponent value of a floating-point numeral as a string *) - val get_numeral_exponent_string : context -> Expr.expr -> string - - (** Return the exponent value of a floating-point numeral as a signed integer *) - val get_numeral_exponent_int : context -> Expr.expr -> bool * int - - (** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *) - val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr - - (** Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. *) - val mk_to_fp_real_int : context -> Expr.expr -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr - - (** The string representation of a numeral *) - val numeral_to_string : Expr.expr -> string + (** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *) + val mk_rtz : context -> Expr.expr end + (** Create a FloatingPoint sort. *) + val mk_sort : context -> int -> int -> Sort.sort + + (** Create the half-precision (16-bit) FloatingPoint sort.*) + val mk_sort_half : context -> Sort.sort + + (** Create the half-precision (16-bit) FloatingPoint sort. *) + val mk_sort_16 : context -> Sort.sort + + (** Create the single-precision (32-bit) FloatingPoint sort.*) + val mk_sort_single : context -> Sort.sort + + (** Create the single-precision (32-bit) FloatingPoint sort. *) + val mk_sort_32 : context -> Sort.sort + + (** Create the double-precision (64-bit) FloatingPoint sort. *) + val mk_sort_double : context -> Sort.sort + + (** Create the double-precision (64-bit) FloatingPoint sort. *) + val mk_sort_64 : context -> Sort.sort + + (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) + val mk_sort_quadruple : context -> Sort.sort + + (** Create the quadruple-precision (128-bit) FloatingPoint sort. *) + val mk_sort_128 : context -> Sort.sort + + (** Create a floating-point NaN of a given FloatingPoint sort. *) + val mk_nan : context -> Sort.sort -> Expr.expr + + (** Create a floating-point infinity of a given FloatingPoint sort. *) + val mk_inf : context -> Sort.sort -> bool -> Expr.expr + + (** Create a floating-point zero of a given FloatingPoint sort. *) + val mk_zero : context -> Sort.sort -> bool -> Expr.expr + + (** Create an expression of FloatingPoint sort from three bit-vector expressions. + + This is the operator named `fp' in the SMT FP theory definition. + Note that \c sign is required to be a bit-vector of size 1. Significand and exponent + are required to be greater than 1 and 2 respectively. The FloatingPoint sort + of the resulting expression is automatically determined from the bit-vector sizes + of the arguments. *) + val mk_fp : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a float. + + This function is used to create numerals that fit in a float value. + It is slightly faster than #Z3_mk_numeral since it is not necessary to parse a string. *) + val mk_numeral_f : context -> float -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a signed integer. *) + val mk_numeral_i : context -> int -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a sign bit and two integers. *) + val mk_numeral_i_u : context -> bool -> int -> int -> Sort.sort -> Expr.expr + + (** Create a numeral of FloatingPoint sort from a string *) + val mk_numeral_s : context -> string -> Sort.sort -> Expr.expr + + (** Indicates whether the terms is of floating-point sort. *) + val is_fp : Expr.expr -> bool + + + (** Indicates whether an expression is a floating-point abs expression *) + val is_abs : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point neg expression *) + val is_neg : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point add expression *) + val is_add : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point sub expression *) + val is_sub : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point mul expression *) + val is_mul : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point div expression *) + val is_div : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point fma expression *) + val is_fma : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point sqrt expression *) + val is_sqrt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point rem expression *) + val is_rem : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point round_to_integral expression *) + val is_round_to_integral : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point min expression *) + val is_min : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point max expression *) + val is_max : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point leq expression *) + val is_leq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point lt expression *) + val is_lt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point geqexpression *) + val is_geq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point gt expression *) + val is_gt : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point eq expression *) + val is_eq : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_normal expression *) + val is_is_normal : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_subnormal expression *) + val is_is_subnormal : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_zero expression *) + val is_is_zero : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_infinite expression *) + val is_is_infinite : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_nan expression *) + val is_is_nan : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_negative expression *) + val is_is_negative : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point is_positive expression *) + val is_is_positive : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_fp expression *) + val is_to_fp : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_fp_unsigned expression *) + val is_to_fp_unsigned : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_ubv expression *) + val is_to_ubv : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_sbv expression *) + val is_to_sbv : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_real expression *) + val is_to_real : Expr.expr -> bool + + (** Indicates whether an expression is a floating-point to_ieee_bv expression *) + val is_to_ieee_bv : Expr.expr -> bool + + + (** Returns a string representation of a numeral. *) + val numeral_to_string : Expr.expr -> string + + (** Creates a floating-point constant. *) + val mk_const : context -> Symbol.symbol -> Sort.sort -> Expr.expr + + (** Creates a floating-point constant. *) + val mk_const_s : context -> string -> Sort.sort -> Expr.expr + + (** Floating-point absolute value *) + val mk_abs : context -> Expr.expr -> Expr.expr + + (** Floating-point negation *) + val mk_neg : context -> Expr.expr -> Expr.expr + + (** Floating-point addition *) + val mk_add : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point subtraction *) + val mk_sub : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point multiplication *) + val mk_mul : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point division *) + val mk_div : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point fused multiply-add. *) + val mk_fma : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point square root *) + val mk_sqrt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point remainder *) + val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point roundToIntegral. + + Rounds a floating-point number to the closest integer, + again represented as a floating-point number. *) + val mk_round_to_integral : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Minimum of floating-point numbers. *) + val mk_min : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Maximum of floating-point numbers. *) + val mk_max : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point less than or equal. *) + val mk_leq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point less than. *) + val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point greater than or equal. *) + val mk_geq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point greater than. *) + val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Floating-point equality. *) + val mk_eq : context -> Expr.expr -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a normal floating-point number. *) + val mk_is_normal : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a subnormal floating-point number. *) + val mk_is_subnormal : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a floating-point number with zero value, i.e., +zero or -zero. *) + val mk_is_zero : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a floating-point number representing +oo or -oo. *) + val mk_is_infinite : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a NaN. *) + val mk_is_nan : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a negative floating-point number. *) + val mk_is_negative : context -> Expr.expr -> Expr.expr + + (** Predicate indicating whether t is a positive floating-point number. *) + val mk_is_positive : context -> Expr.expr -> Expr.expr + + (** Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. *) + val mk_to_fp_bv : context -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a FloatingPoint term into another term of different FloatingPoint sort. *) + val mk_to_fp_float : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a term of real sort into a term of FloatingPoint sort. *) + val mk_to_fp_real : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. *) + val mk_to_fp_signed : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** Conversion of a 2's complement unsigned bit-vector term into a term of FloatingPoint sort. *) + val mk_to_fp_unsigned : context -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** C1onversion of a floating-point term into an unsigned bit-vector. *) + val mk_to_ubv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr + + (** Conversion of a floating-point term into a signed bit-vector. *) + val mk_to_sbv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr + + (** Conversion of a floating-point term into a real-numbered term. *) + val mk_to_real : context -> Expr.expr -> Expr.expr + + (** Retrieves the number of bits reserved for the exponent in a FloatingPoint sort. *) + val get_ebits : context -> Sort.sort -> int + + (** Retrieves the number of bits reserved for the significand in a FloatingPoint sort. *) + val get_sbits : context -> Sort.sort -> int + + (** Retrieves the sign of a floating-point literal. *) + val get_numeral_sign : context -> Expr.expr -> bool * int + + (** Return the significand value of a floating-point numeral as a string. *) + val get_numeral_significand_string : context -> Expr.expr -> string + + (** Return the exponent value of a floating-point numeral as a string *) + val get_numeral_exponent_string : context -> Expr.expr -> string + + (** Return the exponent value of a floating-point numeral as a signed integer *) + val get_numeral_exponent_int : context -> Expr.expr -> bool * int + + (** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *) + val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr + + (** Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. *) + val mk_to_fp_int_real : context -> Expr.expr -> Expr.expr -> Expr.expr -> Sort.sort -> Expr.expr + + (** The string representation of a numeral *) + val numeral_to_string : Expr.expr -> string +end + (** Functions to manipulate proof expressions *) module Proof : @@ -2654,7 +2648,7 @@ sig (** Function interpretations entries - An Entry object represents an element in the finite map used to a function interpretation. *) + An Entry object represents an element in the finite map used to a function interpretation. *) module FuncEntry : sig type func_entry @@ -2844,8 +2838,8 @@ sig val get_subgoal : apply_result -> int -> Goal.goal (** Convert a model for a subgoal into a model for the original - goal [g], that the ApplyResult was obtained from. - #return A model for [g] *) + goal [g], that the ApplyResult was obtained from. + #return A model for [g] *) val convert_model : apply_result -> int -> Model.model -> Model.model (** A string representation of the ApplyResult. *) @@ -2946,7 +2940,7 @@ sig type statistics (** Statistical data is organized into pairs of \[Key, Entry\], where every - Entry is either a floating point or integer value. + Entry is either a floating point or integer value. *) module Entry : sig @@ -2960,16 +2954,16 @@ sig (** The float-value of the entry. *) val get_float : statistics_entry -> float - + (** True if the entry is uint-valued. *) val is_int : statistics_entry -> bool - + (** True if the entry is float-valued. *) val is_float : statistics_entry -> bool - + (** The string representation of the the entry's value. *) val to_string_value : statistics_entry -> string - + (** The string representation of the entry (key and value) *) val to_string : statistics_entry -> string end From e29abefb12330ee4c6a053a95c28f7ab129ae5c0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 18:44:59 +0000 Subject: [PATCH 529/646] Merge branch 'unstable' of https://git01.codeplex.com/z3 into ml-ng Conflicts: scripts/mk_util.py + Cosmetics Signed-off-by: Christoph M. Wintersteiger --- examples/ml/ml_example.ml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/ml/ml_example.ml b/examples/ml/ml_example.ml index 127a973aa..df062bde4 100644 --- a/examples/ml/ml_example.ml +++ b/examples/ml/ml_example.ml @@ -282,13 +282,11 @@ let fpa_example ( ctx : context ) = Printf.printf "Test passed.\n" ); -(* Show that the following are equal: *) -(* (fp #b0 #b10000000001 #xc000000000000) *) -(* ((_ to_fp 11 53) #x401c000000000000)) *) -(* ((_ to_fp 11 53) RTZ 1.75 2))) *) -(* ((_ to_fp 11 53) RTZ 7.0))) *) - - let solver = (mk_solver ctx None) in + (* Show that the following are equal: *) + (* (fp #b0 #b10000000001 #xc000000000000) *) + (* ((_ to_fp 11 53) #x401c000000000000)) *) + (* ((_ to_fp 11 53) RTZ 1.75 2))) *) + (* ((_ to_fp 11 53) RTZ 7.0))) *) let c1 = (mk_fp ctx (mk_numeral_string ctx "0" (BitVector.mk_sort ctx 1)) (mk_numeral_string ctx "3377699720527872" (BitVector.mk_sort ctx 52)) From 2f3ea1f39d2f700120f34d40fdcc4d4626e8f808 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 18:48:51 +0000 Subject: [PATCH 530/646] removed legacy ML API Signed-off-by: Christoph M. Wintersteiger --- src/api/ml/old/Makefile | 14 - src/api/ml/old/Makefile.build | 69 - src/api/ml/old/README-linux | 22 - src/api/ml/old/README-osx | 22 - src/api/ml/old/README-test-linux | 17 - src/api/ml/old/README-test-osx | 17 - src/api/ml/old/add_error_checking.V3.sed | 2 - src/api/ml/old/add_error_checking.sed | 113 - src/api/ml/old/build-lib.cmd | 3 - src/api/ml/old/build-lib.sh | 31 - src/api/ml/old/build-test.cmd | 19 - src/api/ml/old/build-test.sh | 6 - src/api/ml/old/build.cmd | 53 - src/api/ml/old/clean.cmd | 13 - src/api/ml/old/cleantmp.cmd | 15 - src/api/ml/old/compile_mlapi.cmd | 98 - src/api/ml/old/error_handling.idl | 165 - src/api/ml/old/exec.cmd | 5 - src/api/ml/old/exec.sh | 4 - src/api/ml/old/generate_mlapi.cmd | 72 - src/api/ml/old/generate_mlapi.sh | 53 - src/api/ml/old/import.cmd | 55 - src/api/ml/old/mlx_get_app_args.idl | 11 - src/api/ml/old/mlx_get_array_sort.idl | 11 - src/api/ml/old/mlx_get_datatype_sort.idl | 13 - src/api/ml/old/mlx_get_domains.idl | 11 - src/api/ml/old/mlx_get_error_msg.idl | 6 - src/api/ml/old/mlx_get_pattern_terms.idl | 11 - src/api/ml/old/mlx_get_tuple_sort.idl | 12 - src/api/ml/old/mlx_mk_context_x.idl | 36 - src/api/ml/old/mlx_mk_datatypes.idl | 28 - src/api/ml/old/mlx_mk_numeral.idl | 21 - src/api/ml/old/mlx_mk_sort.idl | 69 - src/api/ml/old/mlx_mk_symbol.idl | 22 - src/api/ml/old/mlx_model.idl | 19 - src/api/ml/old/mlx_numeral_refine.idl | 10 - src/api/ml/old/mlx_parse_smtlib.idl | 40 - src/api/ml/old/mlx_sort_refine.idl | 8 - src/api/ml/old/mlx_statistics.idl | 10 - src/api/ml/old/mlx_symbol_refine.idl | 8 - src/api/ml/old/mlx_term_refine.idl | 37 - src/api/ml/old/postprocess.sed | 8 - src/api/ml/old/preprocess.sed | 82 - src/api/ml/old/queen.ml | 112 - src/api/ml/old/queen.regress.err | 0 src/api/ml/old/queen.regress.out | 1852 -- src/api/ml/old/reverse.sed | 3 - src/api/ml/old/test_mlapi.cmd | 61 - src/api/ml/old/test_mlapi.ml | 209 - src/api/ml/old/test_mlapiV3.ml | 1418 -- src/api/ml/old/test_theory.ml | 42 - src/api/ml/old/update-ml-doc.cmd | 38 - src/api/ml/old/x3.ml | 366 - src/api/ml/old/x3V3.ml | 378 - src/api/ml/old/x3V3.mli | 361 - src/api/ml/old/z3.0.idl | 597 - src/api/ml/old/z3_stubs.c | 19044 --------------------- src/api/ml/old/z3_theory_stubs.c | 339 - 58 files changed, 26161 deletions(-) delete mode 100644 src/api/ml/old/Makefile delete mode 100644 src/api/ml/old/Makefile.build delete mode 100644 src/api/ml/old/README-linux delete mode 100644 src/api/ml/old/README-osx delete mode 100644 src/api/ml/old/README-test-linux delete mode 100644 src/api/ml/old/README-test-osx delete mode 100644 src/api/ml/old/add_error_checking.V3.sed delete mode 100644 src/api/ml/old/add_error_checking.sed delete mode 100755 src/api/ml/old/build-lib.cmd delete mode 100644 src/api/ml/old/build-lib.sh delete mode 100755 src/api/ml/old/build-test.cmd delete mode 100644 src/api/ml/old/build-test.sh delete mode 100755 src/api/ml/old/build.cmd delete mode 100755 src/api/ml/old/clean.cmd delete mode 100755 src/api/ml/old/cleantmp.cmd delete mode 100755 src/api/ml/old/compile_mlapi.cmd delete mode 100644 src/api/ml/old/error_handling.idl delete mode 100755 src/api/ml/old/exec.cmd delete mode 100644 src/api/ml/old/exec.sh delete mode 100755 src/api/ml/old/generate_mlapi.cmd delete mode 100755 src/api/ml/old/generate_mlapi.sh delete mode 100755 src/api/ml/old/import.cmd delete mode 100644 src/api/ml/old/mlx_get_app_args.idl delete mode 100644 src/api/ml/old/mlx_get_array_sort.idl delete mode 100644 src/api/ml/old/mlx_get_datatype_sort.idl delete mode 100644 src/api/ml/old/mlx_get_domains.idl delete mode 100644 src/api/ml/old/mlx_get_error_msg.idl delete mode 100644 src/api/ml/old/mlx_get_pattern_terms.idl delete mode 100644 src/api/ml/old/mlx_get_tuple_sort.idl delete mode 100644 src/api/ml/old/mlx_mk_context_x.idl delete mode 100644 src/api/ml/old/mlx_mk_datatypes.idl delete mode 100644 src/api/ml/old/mlx_mk_numeral.idl delete mode 100644 src/api/ml/old/mlx_mk_sort.idl delete mode 100644 src/api/ml/old/mlx_mk_symbol.idl delete mode 100644 src/api/ml/old/mlx_model.idl delete mode 100644 src/api/ml/old/mlx_numeral_refine.idl delete mode 100644 src/api/ml/old/mlx_parse_smtlib.idl delete mode 100644 src/api/ml/old/mlx_sort_refine.idl delete mode 100644 src/api/ml/old/mlx_statistics.idl delete mode 100644 src/api/ml/old/mlx_symbol_refine.idl delete mode 100644 src/api/ml/old/mlx_term_refine.idl delete mode 100644 src/api/ml/old/postprocess.sed delete mode 100644 src/api/ml/old/preprocess.sed delete mode 100644 src/api/ml/old/queen.ml delete mode 100644 src/api/ml/old/queen.regress.err delete mode 100644 src/api/ml/old/queen.regress.out delete mode 100644 src/api/ml/old/reverse.sed delete mode 100755 src/api/ml/old/test_mlapi.cmd delete mode 100644 src/api/ml/old/test_mlapi.ml delete mode 100644 src/api/ml/old/test_mlapiV3.ml delete mode 100644 src/api/ml/old/test_theory.ml delete mode 100755 src/api/ml/old/update-ml-doc.cmd delete mode 100644 src/api/ml/old/x3.ml delete mode 100644 src/api/ml/old/x3V3.ml delete mode 100644 src/api/ml/old/x3V3.mli delete mode 100644 src/api/ml/old/z3.0.idl delete mode 100644 src/api/ml/old/z3_stubs.c delete mode 100644 src/api/ml/old/z3_theory_stubs.c diff --git a/src/api/ml/old/Makefile b/src/api/ml/old/Makefile deleted file mode 100644 index 55f89fe1c..000000000 --- a/src/api/ml/old/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# to set ARGS, invoke as e.g.: $ make ARGS='-DUNSAFE_ERRORS -DLEAK_CONTEXTS' -ARGS= - - -default: z3.ml z3.mli z3_stubs.c - - -%.ml %.mli %_stubs.c: ../%_api.h %.0.idl x3.ml x3V3.ml x3V3.mli \ - error_handling.idl mlx_get_app_args.idl mlx_get_array_sort.idl mlx_get_datatype_sort.idl mlx_get_domains.idl mlx_get_error_msg.idl mlx_get_pattern_terms.idl mlx_get_tuple_sort.idl mlx_mk_context_x.idl mlx_mk_datatypes.idl mlx_mk_numeral.idl mlx_mk_sort.idl mlx_mk_symbol.idl mlx_model.idl mlx_numeral_refine.idl mlx_parse_smtlib.idl mlx_sort_refine.idl mlx_statistics.idl mlx_symbol_refine.idl mlx_term_refine.idl \ - generate_mlapi.sh add_error_checking.V3.sed add_error_checking.sed preprocess.sed postprocess.sed reverse.sed - ./generate_mlapi.sh $(ARGS) - -clean: - rm -f z3.ml z3.mli z3_stubs.c diff --git a/src/api/ml/old/Makefile.build b/src/api/ml/old/Makefile.build deleted file mode 100644 index 0a737e356..000000000 --- a/src/api/ml/old/Makefile.build +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile to compile OCaml interface to Z3 -# -# Parameters: ARGS and DEPS environment variables -# ARGS is passed through to the Makefile that generates the OCaml interface -# DEPS is a sequence of files that are deleted when the OCaml interface changes - -SRC_ML=../../../src/api/ml -ifeq (${OS}, Windows_NT) -# the BLD_ML path ends up stored in z3.cm{,x}a, so it must be in windows format -BLD_ML=$(shell cygpath -m $(CURDIR)) -CFLAGS=-ccopt -wd4090 -ccopt -I$(SRC_ML)/.. -XCDBG=-g $(CFLAGS) -XCOPT=-ccopt -Ox -ccopt -Oy- $(CFLAGS) -# ole32 is needed by camlidl (COM support) -XLIB=-cclib ole32.lib -AR=lib /nologo /LIBPATH:../../build ../../libz3.lib /out: -O=obj -A=lib -else -BLD_ML=$(CURDIR) -CFLAGS=-ccopt -Wno-discard-qual -ccopt -Wno-unused-variable -ccopt -I$(SRC_ML)/.. -XCDBG=-g -ccopt -g $(CFLAGS) -XCOPT=-ccopt -O3 -ccopt -fomit-frame-pointer $(CFLAGS) -XLIB= -AR=ar rcs # note trailing space is significant -O=o -A=a -endif - - -all: z3.cma z3.cmxa ocamlz3 - - -# keep these files to avoid repeatedly rebuilding them -.PRECIOUS: $(SRC_ML)/z3.ml $(SRC_ML)/z3.mli $(SRC_ML)/z3_stubs.c z3.ml z3.mli z3_stubs.c z3_theory_stubs.c - -# regenerate OCaml API if needed -$(SRC_ML)/%.mli $(SRC_ML)/%.ml $(SRC_ML)/%_stubs.c: $(SRC_ML)/Makefile - make -C $(SRC_ML) z3.mli z3.ml z3_stubs.c - -# copy OCaml API from src to build directories -%.mli %.ml %_stubs.c %_theory_stubs.c: $(SRC_ML)/%.mli $(SRC_ML)/%.ml $(SRC_ML)/%_stubs.c Makefile - cp $(SRC_ML)/z3.mli $(SRC_ML)/z3.ml $(SRC_ML)/z3_stubs.c $(SRC_ML)/z3_theory_stubs.c . - -# OCaml library module for native code clients -%.cmxa %.cmi lib%stubs.a %.a: %.mli %.ml %_stubs.c %_theory_stubs.c Makefile - rm -f $(DEPS) - ocamlopt.opt -c $(XCOPT) z3.mli z3.ml z3_stubs.c z3_theory_stubs.c - $(AR)libz3stubs.$(A) z3.$(O) z3_stubs.$(O) z3_theory_stubs.$(O) - ocamlopt.opt -a -cclib -L$(BLD_ML)/../.. $(XLIB) -cclib -lcamlidl -cclib -lz3 -cclib -lz3stubs z3.cmx -o z3.cmxa - rm -f z3_theory_stubs.$(O) z3_stubs.$(O) z3.$(O) z3.cmx - -# OCaml library module for byte code clients -%.cma %.cmi lib%stubs_dbg.a: %.mli %.ml %_stubs.c %_theory_stubs.c Makefile - rm -f $(DEPS) - ocamlc.opt -c $(XCDBG) z3.mli z3.ml z3_stubs.c z3_theory_stubs.c - $(AR)libz3stubs_dbg.$(A) z3_stubs.$(O) z3_theory_stubs.$(O) - ocamlc.opt -custom -a $(CXDBG) -cclib -L$(BLD_ML)/../.. $(XLIB) -cclib -lcamlidl -cclib -lz3 -cclib -lz3stubs_dbg z3.cmo -o z3.cma - rm -f z3_theory_stubs.$(O) z3_stubs.$(O) z3.cmo - - -# OCaml custom toplevel system pre-linked with Z3 -ocamlz3: z3.cma Makefile - ocamlmktop -o ocamlz3 z3.cma -cclib -L. - - -clean: Makefile - make -C $(SRC_ML) clean - rm -rf Makefile libz3stubs.$(A) libz3stubs_dbg.$(A) ocamlz3 ocamlz3.dSYM z3.$(O) z3.$(A) z3.cma z3.cmi z3.cmo z3.cmx z3.cmxa z3.ml z3.mli z3_stubs.$(O) z3_stubs.c z3_theory_stubs.$(O) z3_theory_stubs.c diff --git a/src/api/ml/old/README-linux b/src/api/ml/old/README-linux deleted file mode 100644 index 5ee20bb27..000000000 --- a/src/api/ml/old/README-linux +++ /dev/null @@ -1,22 +0,0 @@ -The OCaml API for Z3 was tested using OCaml 3.12.1. -You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- To build the OCaml API for Z3: - ./build-lib.sh - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -Remark: Building the OCaml API copies some pathnames into files, -so the OCaml API must be recompiled if the Z3 library files are moved. - -See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. - -Acknowledgements: -The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. -Many thanks to them! diff --git a/src/api/ml/old/README-osx b/src/api/ml/old/README-osx deleted file mode 100644 index 5ee20bb27..000000000 --- a/src/api/ml/old/README-osx +++ /dev/null @@ -1,22 +0,0 @@ -The OCaml API for Z3 was tested using OCaml 3.12.1. -You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- To build the OCaml API for Z3: - ./build-lib.sh - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -Remark: Building the OCaml API copies some pathnames into files, -so the OCaml API must be recompiled if the Z3 library files are moved. - -See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. - -Acknowledgements: -The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. -Many thanks to them! diff --git a/src/api/ml/old/README-test-linux b/src/api/ml/old/README-test-linux deleted file mode 100644 index fc15fb2a2..000000000 --- a/src/api/ml/old/README-test-linux +++ /dev/null @@ -1,17 +0,0 @@ -This directory contains scripts to build the test application using -OCaml. You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- One must build the OCaml library before compiling the example. - Go to directory ../ocaml - -- Use 'build-test.sh' to build the test application using the OCaml compiler. - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -- Use 'exec.sh' to execute test_mlapi. The script sets LD_LIBRARY_PATH, and invokes test_mlapi. diff --git a/src/api/ml/old/README-test-osx b/src/api/ml/old/README-test-osx deleted file mode 100644 index 3a20d1f1d..000000000 --- a/src/api/ml/old/README-test-osx +++ /dev/null @@ -1,17 +0,0 @@ -This directory contains scripts to build the test application using -OCaml. You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- One must build the OCaml library before compiling the example. - Go to directory ../ocaml - -- Use 'build-test.sh' to build the test application using the OCaml compiler. - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -- Use 'exec.sh' to execute test_mlapi. The script sets DYLD_LIBRARY_PATH, and invokes test_mlapi. diff --git a/src/api/ml/old/add_error_checking.V3.sed b/src/api/ml/old/add_error_checking.V3.sed deleted file mode 100644 index 7df291520..000000000 --- a/src/api/ml/old/add_error_checking.V3.sed +++ /dev/null @@ -1,2 +0,0 @@ -# Customize error handling for contexts created in ML: -s/Z3_API Z3_mk_context(\(.*\))/Z3_API Z3_mk_context(\1) quote(dealloc,\"Z3_set_error_handler(_res, (void*)caml_z3_error_handler);\")/g diff --git a/src/api/ml/old/add_error_checking.sed b/src/api/ml/old/add_error_checking.sed deleted file mode 100644 index 71c06b9e4..000000000 --- a/src/api/ml/old/add_error_checking.sed +++ /dev/null @@ -1,113 +0,0 @@ -# Do not add epilogue to Z3_del_context -/Z3_API .*Z3_del_context.*/b endt - -# Add error checking epilogue for all Z3_API functions that accept two Z3_contexts -:begincc -# add epilogue for two Z3_context parameters and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3);\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3);\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3);\")/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3);\")/g -t endt - -# if complete prototype, done with two Z3_contexts -/Z3_API .*(.*);[ ]*$/b endcc -/Z3_API .*(.*)[ ]*$/b endcc - -# if incomplete prototype -/Z3_API .*(.*/{ - - # read another line - N - - # add epilogue for two Z3_context parameters and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\")/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\")/g - t endt - - # else keep looking for two Z3_contexts - b begincc -} -:endcc - -# Add error checking epilogue for all Z3_API functions that accept one Z3_context -:beginc -# add epilogue for one Z3_context parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\")/g -t endt - -# if complete prototype, done with all Z3_contexts -/Z3_API .*(.*);[ ]*$/b endc -/Z3_API .*(.*)[ ]*$/b endc - -# if incomplete prototype -/Z3_API .*(.*/{ - - # read another line - N - - # add epilogue for one Z3_context parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\")/g - t endt - - # else keep looking for one Z3_context - b beginc -} -:endc - - -# Add error checking epilogue for all Z3_API functions that accept a Z3_theory -:begint -# add epilogue for one Z3_theory parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt -s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g -t endt -s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g -t endt - -# if complete prototype, done with all Z3_theorys -/Z3_API .*(.*);[ ]*$/b endt -/Z3_API .*(.*)[ ]*$/b endt - -/Z3_API .*(.*/{ - - # read another line - N - - # add epilogue for one Z3_theory parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt - s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g - t endt - s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g - t endt - - # else keep looking for one Z3_theory - b begint -} -:endt diff --git a/src/api/ml/old/build-lib.cmd b/src/api/ml/old/build-lib.cmd deleted file mode 100755 index 7cf1bbcbd..000000000 --- a/src/api/ml/old/build-lib.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -call .\compile_mlapi.cmd ..\include ..\bin ..\bin diff --git a/src/api/ml/old/build-lib.sh b/src/api/ml/old/build-lib.sh deleted file mode 100644 index 93c7262b1..000000000 --- a/src/api/ml/old/build-lib.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Script to compile the Z3 OCaml API -# Expects to find ../lib/libz3{,_dbg}.{a,so,dylib} - -CFLAGS="-ccopt -Wno-discard-qual -ccopt -I../include" -XCDBG="-g -ccopt -g $CFLAGS" -XCOPT="-ccopt -O3 -ccopt -fomit-frame-pointer $CFLAGS" - - -ocamlc -c $XCDBG z3_stubs.c z3_theory_stubs.c z3.mli z3.ml - -ocamlopt -c $XCDBG z3_stubs.c z3_theory_stubs.c z3.mli z3.ml - -ar rcs libz3stubs_dbg.a z3.o z3_stubs.o z3_theory_stubs.o - -ocamlopt -c $XCOPT z3_stubs.c z3_theory_stubs.c z3.mli z3.ml - -ar rcs libz3stubs.a z3.o z3_stubs.o z3_theory_stubs.o - -ocamlc -custom -a $XCDBG -cclib -L$PWD/../lib -cclib -lz3_dbg -cclib -lcamlidl -cclib -lz3stubs_dbg z3.cmo -o z3_dbg.cma - -ocamlc -custom -a $XCDBG -cclib -L$PWD/../lib -cclib -lz3 -cclib -lcamlidl -cclib -lz3stubs z3.cmo -o z3.cma - -ocamlopt -a $XCDBG -cclib -L$PWD/../lib -cclib -lz3_dbg -cclib -lcamlidl -cclib -lz3stubs_dbg z3.cmx -o z3_dbg.cmxa - -ocamlopt -a $XCOPT -cclib -L$PWD/../lib -cclib -lz3 -cclib -lcamlidl -cclib -lz3stubs z3.cmx -o z3.cmxa - -ocamlmktop -o ocamlz3 z3.cma -cclib -L. - -rm z3.cm{o,x} *.o diff --git a/src/api/ml/old/build-test.cmd b/src/api/ml/old/build-test.cmd deleted file mode 100755 index 13a752dbb..000000000 --- a/src/api/ml/old/build-test.cmd +++ /dev/null @@ -1,19 +0,0 @@ -@echo off - -if not exist ..\..\ocaml\z3.cmxa ( - echo "YOU MUST BUILD OCAML API! Go to directory ..\ocaml" - goto :EOF -) - -REM ocaml (>= 3.11) calls the linker through flexlink -ocamlc -version >> ocaml_version -set /p OCAML_VERSION= NUL z3_stubs.c z3.mli z3.ml z3V3_stubs.*.c z3V3.*.mli z3V3.*.ml - -REM files produced by update-ml-doc.cmd -rd 2>NUL /s /q doc - -exit /B 0 diff --git a/src/api/ml/old/cleantmp.cmd b/src/api/ml/old/cleantmp.cmd deleted file mode 100755 index 257e26a96..000000000 --- a/src/api/ml/old/cleantmp.cmd +++ /dev/null @@ -1,15 +0,0 @@ -@echo off - -REM Script to delete intermediate temporary files from generating Z3 OCaml API - -REM files produced by generate_mlapi.cmd -del /q 2>NUL z3_api.idl - -REM files produced by compile_mlapi.cmd -del /q 2>NUL *.cmi *.cmo *.cmx *.cma *.cmxa *.obj *.lib *.pdb ocamlz3.exe - -REM files produced by test_mlapi.cmd -del /q 2>NUL test*.exe queen*.exe test_*api.out test_*apiV3.out test_*api.err test_*apiV3.err queen.out queen.err z3.log ml.log test_mlapi.log .z3-trace - -REM backup files -del /q 2>NUL *~ diff --git a/src/api/ml/old/compile_mlapi.cmd b/src/api/ml/old/compile_mlapi.cmd deleted file mode 100755 index 17776b6b8..000000000 --- a/src/api/ml/old/compile_mlapi.cmd +++ /dev/null @@ -1,98 +0,0 @@ -@echo off -SETLOCAL - -REM Script to compile the Z3 OCaml API -REM -REM Compiles byte and debug native code versions with debug info, optimized native code versions without -REM -REM Assumes that environment variables are set to provide access to the C and OCaml compilers - -REM directory containing z3_api.h -set Z3SRC=%1 - -REM directory containing z3.dll -set Z3BIN=%2 - -REM directory containing debug z3.dll -set Z3BINDBG=%3 - -REM link Z3 statically or dynamically -set STATIC=false -REM set STATIC=true - -if %STATIC% == true ( - set Z3LIB=z3lib.lib - set Z3DBGLIB=z3lib.lib -) else ( - set Z3LIB=z3.lib - set Z3DBGLIB=z3.lib -) - -REM ocaml 3.11 and later calls the linker through flexlink -ocamlc -version >> ocaml_version -set /p OCAML_VERSION= DBG z3_stubs.obj z3.{cmi,cmo,obj} -ocamlc -c %XCDBG% z3_stubs.c z3_theory_stubs.c z3.mli z3.ml -if errorlevel 1 goto :EOF - -REM z3_stubs.c z3_theory_stubs.c z3.mli z3.ml -> DBG z3_stubs.obj z3.{cmi,cmx,obj} -ocamlopt -c %XCDBG% z3_stubs.c z3_theory_stubs.c z3.mli z3.ml -if errorlevel 1 goto :EOF - -REM %Z3DBGLIB% z3.obj z3_stubs.obj z3_theory_stubs.obj -> libz3_dbg.lib: -lib /nologo %XLIBPATH% /out:libz3_dbg.lib %Z3BINDBG%\%Z3DBGLIB% z3.obj z3_stubs.obj z3_theory_stubs.obj -if errorlevel 1 goto :EOF - -REM z3_stubs.c z3_theory_stubs.c z3.mli z3.ml -> OPT z3_stubs.obj z3.{cmi,cmx,obj} -ocamlopt -c %XCOPT% z3_stubs.c z3_theory_stubs.c z3.mli z3.ml -if errorlevel 1 goto :EOF - -REM %Z3LIB% z3.obj z3_stubs.obj z3_theory_stubs.obj -> libz3.lib: -lib /nologo %XLIBPATH% /out:libz3.lib %Z3BIN%\%Z3LIB% z3.obj z3_stubs.obj z3_theory_stubs.obj -if errorlevel 1 goto :EOF - - -REM ole32.lib is needed by camlidl -REM camlidl.lib is the runtime library for camlidl -REM psapi.lib is needed when statically linking Z3 for process statistics functions - -REM libz3_dbg.lib ole32.lib camlidl.lib z3.cmo -> z3_dbg.cma -ocamlc -custom -a %XCDBG% -cclib -L"%CD%\..\bin" -cclib -lz3_dbg -cclib ole32.lib -cclib -lcamlidl -cclib psapi.lib z3.cmo -o z3_dbg.cma -if errorlevel 1 goto :EOF - -REM libz3.lib ole32.lib camlidl.lib z3.cmo -> z3.cma -ocamlc -custom -a -cclib -L"%CD%\..\bin" -cclib -lz3 -cclib ole32.lib -cclib -lcamlidl -cclib psapi.lib z3.cmo -o z3.cma -if errorlevel 1 goto :EOF - - -REM libz3_dbg.lib ole32.lib camlidl.lib z3.cmx -> z3_dbg.cmxa -ocamlopt -a -cclib -L"%CD%\..\bin" -cclib -lz3_dbg -cclib ole32.lib -cclib -lcamlidl -cclib psapi.lib z3.cmx -o z3_dbg.cmxa -if errorlevel 1 goto :EOF - -REM libz3.lib ole32.lib camlidl.lib z3.cmx -> z3.cmxa -ocamlopt -a -cclib -L"%CD%\..\bin" -cclib -lz3 -cclib ole32.lib -cclib -lcamlidl -cclib psapi.lib z3.cmx -o z3.cmxa -if errorlevel 1 goto :EOF - - -REM build OCaml toplevel 'ocamlz3' pre-linked with Z3 -ocamlmktop -o ocamlz3 z3.cma -if errorlevel 1 goto :EOF - - -del /q 2>NUL z3.cmo z3.cmx *.obj - -ENDLOCAL diff --git a/src/api/ml/old/error_handling.idl b/src/api/ml/old/error_handling.idl deleted file mode 100644 index 5a2ec9915..000000000 --- a/src/api/ml/old/error_handling.idl +++ /dev/null @@ -1,165 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation - -Module Name: - - error_handling - -Abstract: - - Error handling in the OCaml API for Z3. - - The wrapper of each Z3 API routine that takes a Z3_context or a Z3_theory - argument calls check_error_code before returning. (These calls are added - in generate_mlapi.cmd using the build.sed script.) - - There are two error handling schemes implemented, depending on whether - (UN)SAFE_ERRORS is set. - - - SAFE_ERRORS checks Z3_error_code after each call and raises an OCaml - exception in error conditions. Z3_set_error_handler is not exposed by - the SAFE_ERRORS version. - - - UNSAFE_ERRORS sets a Z3 error handler routine that either calls a - globally registered OCaml function or, by default, raises an OCaml - exception. This avoids overhead of repeatedly checking - Z3_get_error_code, but leaves Z3 in a broken state. - -Notes: - - The current SAFE_ERRORS implementation interacts badly with theory plugin - callbacks. Z3 errors are converted into OCaml exceptions, which the - wrappers of theory plugin callbacks are not expecting. Therefore, if a - theory plugin calls a Z3 API routine that triggers an error, an OCaml - exception will be raised and bypass any C++ destructors pushed onto the - stack by Z3 before the call to the plugin and after the preceding OCaml - exception handler. One solution to this would be to modify the theory - plugin callback registration functions to wrap callbacks in an OCaml - exception handler. Since OCaml exceptions are cheap to raise at the - expense of some cost to install a handler, this may not be desirable. - Another solution would be to modify check_error_code to detect if it is - executing in a plugin callback and simply maintain the Z3_error_code, or - raise a C++ exception, instead of raising an OCaml exception. - -Author: - - Josh Berdine (jjb) 2012-03-21 - ---*/ - - -#if !defined(UNSAFE_ERRORS) && !defined(SAFE_ERRORS) -#define SAFE_ERRORS -#endif - - -// The V3 API uses a single handler irregardless of UNSAFE_ERRORS -quote(c," -/* All contexts share the same handler */ -static value caml_z3_error_handler = 0; -"); - -#ifdef SAFE_ERRORS - -quote(mlmli," -(** Exceptions raised by Z3. It is safe to continue interacting with Z3 after - catching [Error] exceptions. - - - {b See also}: {!get_error_msg} -*) -exception Error of context * error_code -"); -quote(ml," -(* Register dynamically-generated exception tag for use from C *) -let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) -"); - -quote(c," -value camlidl_c2ml_z3_Z3_error_code(Z3_error_code * _c2, camlidl_ctx _ctx); - -/* Error checking routine that raises OCaml Error exceptions */ -void check_error_code (Z3_context c) -{ - static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - value* exn_tag = NULL; - value ctx_err[2]; - Z3_error_code e; - e = Z3_get_error_code(c); - if (e != Z3_OK) { - ctx_err[0] = c2ml_Z3_context(&c); - ctx_err[1] = camlidl_c2ml_z3_Z3_error_code(&e, &_ctxs); - exn_tag = caml_named_value(\"Z3.Error\"); - if (*exn_tag == 0) { - fprintf(stderr, \"Z3.Error not found\"); - exit(1); - } - caml_raise_with_args(*exn_tag, 2, ctx_err); - } -} - -/* Disable default error handler, all error checking is done by check_error_code */ -void* error_handler_static = NULL; -"); - -#else - -quote(mlmli," -(** Exceptions raised by Z3. {b Warning}: It is unsafe to continue - interacting with Z3 after catching [Error] exceptions. To recover from - error conditions, use {!set_error_handler} to set an error handler that - does nothing, and then test {!get_error_code} after every call to Z3. - - - {b See also}: {!get_error_msg} -*) -exception Error of context * error_code -"); -quote(ml," -(* Register dynamically-generated exception tag for use from C *) -let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) -"); - -quote(c," -/* Error checking routine that does nothing */ -void check_error_code(Z3_context c) {} - -static void error_handler_static (Z3_context c, Z3_error_code e) -{ - static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - value* exn_tag = NULL; - value ctx_err[2]; - ctx_err[0] = c2ml_Z3_context(&c); - ctx_err[1] = camlidl_c2ml_z3_Z3_error_code(&e, &_ctxs); - if (caml_z3_error_handler) { - caml_callback2(caml_z3_error_handler, ctx_err[0], ctx_err[1]); - } else { - /* if no handler set, raise OCaml Error exception */ - exn_tag = caml_named_value(\"Z3.Error\"); - if (*exn_tag == 0) { - fprintf(stderr, \"Z3.Error not found\"); - exit(1); - } - caml_raise_with_args(*exn_tag, 2, ctx_err); - } -} - -void ml2c_Z3_error_handler (value ml_handler, void* c_handler) -{ - caml_z3_error_handler = ml_handler; - c_handler = (void*)error_handler_static; -} - -/* Never called */ -value c2ml_Z3_error_handler (void* _) -{ - return 0; -} -"); - -typedef [mltype("context -> error_code -> unit"), - ml2c(ml2c_Z3_error_handler), - c2ml(c2ml_Z3_error_handler) - ] void Z3_error_handler; - -quote(c,"#define Z3_error_handler void*"); - -#endif diff --git a/src/api/ml/old/exec.cmd b/src/api/ml/old/exec.cmd deleted file mode 100755 index 2bb632ef6..000000000 --- a/src/api/ml/old/exec.cmd +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -SETLOCAL -set PATH=..\..\bin;%PATH% -test_mlapi.exe -ENDLOCAL diff --git a/src/api/ml/old/exec.sh b/src/api/ml/old/exec.sh deleted file mode 100644 index 573ec6ddf..000000000 --- a/src/api/ml/old/exec.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH # for linux -export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH # for osx -./test_mlapi diff --git a/src/api/ml/old/generate_mlapi.cmd b/src/api/ml/old/generate_mlapi.cmd deleted file mode 100755 index 6a796a401..000000000 --- a/src/api/ml/old/generate_mlapi.cmd +++ /dev/null @@ -1,72 +0,0 @@ -@echo off - -REM Script to generate the Z3 OCaml API -REM -REM Assumes that environment variables are set to provide access to the following commands: camlidl, dos2unix, grep, sed, unix2dos -REM -REM Invoke with "-D UNSAFE_ERRORS" to build version that does not support recoverable errors, but avoids some error-checking overhead. -REM Invoke with "-D LEAK_CONTEXTS" to build version that leaks Z3_context objects, but avoids some garbage-collection overhead. - -REM ../lib/z3_api.h -> z3V3_api.idl using add_error_checking.V3.sed and build.sed -sed -f add_error_checking.V3.sed ../lib/z3_api.h | sed -f build.sed >z3V3_api.idl -if errorlevel 1 goto :EOF - -REM z3.idl -> z3V3_stubs.c, z3V3.mli, z3V3.ml -camlidl -D MLAPIV3 %* z3.idl -move >NUL z3_stubs.c z3V3_stubs.c -move >NUL z3.ml z3V3.ml -move >NUL z3.mli z3V3.mli -if errorlevel 1 goto :EOF - -REM ../lib/z3_api.h -> z3_api.idl -REM add calls to error checking routine -REM convert from doxygen to ocamldoc markup and other syntactic munging -sed <../lib/z3_api.h -f add_error_checking.sed | ^ -sed -f build.sed >z3_api.idl -if errorlevel 1 goto :EOF - -REM z3.idl -> z3_stubs.c, z3.mli, z3.ml -camlidl %* z3.idl -if errorlevel 1 goto :EOF - -REM sometimes z3_stubs.c can be generated with mixed line endings, which can confuse sed and grep -dos2unix 2>NUL z3V3_stubs.c ; unix2dos 2>NUL z3V3_stubs.c -dos2unix 2>NUL z3_stubs.c ; unix2dos 2>NUL z3_stubs.c - -REM modify generated z3.ml{,i} to remove "Z3_" prefix from names -move >NUL z3V3.mli z3V3.1.mli && sed "s/{\!Z3\./{!/g;s/\<[zZ]3_//g" z3V3.1.mli >z3V3.mli && del z3V3.1.mli -move >NUL z3V3.ml z3V3.1.ml && sed "s/{\!Z3\./{!/g;s/\<[zZ]3_//g" z3V3.1.ml >z3V3.ml && del z3V3.1.ml -move >NUL z3.mli z3.1.mli && sed "s/{\!Z3\./{!/g;s/\<[zZ]3_//g" z3.1.mli >z3.mli && del z3.1.mli -move >NUL z3.ml z3.1.ml && sed "s/{\!Z3\./{!/g;s/\<[zZ]3_//g" z3.1.ml >z3.ml && del z3.1.ml - -REM modify generated z3V3 files to rename z3_ to z3V3_ -move >NUL z3V3.mli z3V3.2.mli && sed "s/camlidl\(.*\)_z3_/camlidl\1_z3V3_/g" z3V3.2.mli >z3V3.mli && del z3V3.2.mli -move >NUL z3V3.ml z3V3.2.ml && sed "s/camlidl\(.*\)_z3_/camlidl\1_z3V3_/g" z3V3.2.ml >z3V3.ml && del z3V3.2.ml -move >NUL z3V3_stubs.c z3V3_stubs.2.c && sed "s/camlidl\(.*\)_z3_/camlidl\1_z3V3_/g" z3V3_stubs.2.c >z3V3_stubs.c && del z3V3_stubs.2.c - - -REM substitute out type equations for enums and options -REM reverse order of substitution of enums to avoid matching prefixes such as enum_1 of enum_10 -grep "^and \([a-z][a-zA-Z_]*\) = \([a-z][a-zA-Z_]*[0-9]*\)$" z3.mli | sed "s|and \([a-zA-Z_]*\) = \([ a-zA-Z_0-9]*\)|s/\2/\1/g|g" | sed "1!G;h;$!d" >rename.sed -grep "^and \([a-z][a-zA-Z_]*\) = \([a-z][a-zA-Z_]* option*\)$" z3.mli | sed "s|and \([a-zA-Z_]*\) = \([ a-zA-Z_0-9]*\)|s/\1/\2/g|g" >>rename.sed -move >NUL z3.mli z3.3.mli && sed -f rename.sed z3.3.mli >z3.mli && del z3.3.mli -move >NUL z3.ml z3.3.ml && sed -f rename.sed z3.3.ml >z3.ml && del z3.3.ml -del rename.sed - -grep "^and \([a-z][a-zA-Z_]*\) = \([a-z][a-zA-Z_]*[0-9]*\)$" z3V3.mli | sed "s|and \([a-zA-Z_]*\) = \([ a-zA-Z_0-9]*\)|s/\2/\1/g|g" | sed "1!G;h;$!d" >rename.sed -grep "^and \([a-z][a-zA-Z_]*\) = \([a-z][a-zA-Z_]* option*\)$" z3V3.mli | sed "s|and \([a-zA-Z_]*\) = \([ a-zA-Z_0-9]*\)|s/\1/\2/g|g" >>rename.sed -move >NUL z3V3.mli z3V3.3.mli && sed -f rename.sed z3V3.3.mli >z3V3.mli && del z3V3.3.mli -move >NUL z3V3.ml z3V3.3.ml && sed -f rename.sed z3V3.3.ml >z3V3.ml && del z3V3.3.ml -del rename.sed - -REM remove cyclic definitions introduced by substituting type equations -move >NUL z3V3.mli z3V3.4.mli && sed "s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g" z3V3.4.mli >z3V3.mli && del z3V3.4.mli -move >NUL z3V3.ml z3V3.4.ml && sed "s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g" z3V3.4.ml >z3V3.ml && del z3V3.4.ml -move >NUL z3.mli z3.4.mli && sed "s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g" z3.4.mli >z3.mli && del z3.4.mli -move >NUL z3.ml z3.4.ml && sed "s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g" z3.4.ml >z3.ml && del z3.4.ml - -REM append Z3.V3 module onto Z3 module -type z3V3.ml >> z3.ml -type z3V3.mli >> z3.mli -sed "1,22d" z3V3_stubs.c >> z3_stubs.c -del /q 2>NUL z3V3_api.idl z3V3.ml z3V3.mli z3V3_stubs.c diff --git a/src/api/ml/old/generate_mlapi.sh b/src/api/ml/old/generate_mlapi.sh deleted file mode 100755 index dd8692833..000000000 --- a/src/api/ml/old/generate_mlapi.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# Script to generate the Z3 OCaml API -# -# Assumes that environment variables are set to provide access to the following commands: camlidl, gcc, grep, sed -# -# This script uses 'gcc -E' as the C preprocessor, other C preprocessors may work but have not been tested. -# -# Invoke with "-DUNSAFE_ERRORS" to build version that does not support recoverable errors, but avoids some error-checking overhead. -# Invoke with "-DLEAK_CONTEXTS" to build version that leaks Z3_context objects, but avoids some garbage-collection overhead. - - -# add calls to error checking routine -# convert from doxygen to ocamldoc markup and other syntactic munging -# ../z3_api.h -> z3V3_api.idl -sed -f add_error_checking.V3.sed -f preprocess.sed ../z3_api.h > z3V3_api.idl - -# z3.idl (z3V3_api.idl x3V3.mli x3V3.ml) -> z3V3_stubs.c, z3V3.mli, z3V3.ml -gcc -E -w -P -CC -xc -DCAMLIDL -DMLAPIV3 $@ z3.0.idl > z3V3.idl -camlidl -nocpp z3V3.idl - -# reverse.sed to reverse order of substitution of enums to avoid matching prefixes such as enum_1 of enum_10 -grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_]*$" z3V3.mli | sed -e "s|and z3_\([a-zA-Z0-9_]*\) = \([a-zA-Z0-9_]*\)|s/\2/\1/g|g" -f reverse.sed > /tmp/renameV3.sed -grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_ ]* option$" z3V3.mli | sed -e "s|and \(z3_[a-zA-Z0-9_]*\) = \([a-zA-Z0-9_ ]*\)|s/\1/\2/g|g" >> /tmp/renameV3.sed - -# rename.sed to substitute out type equations for enums and options, then postprocess -cp -f z3V3.mli z3V3.ml /tmp -sed -f /tmp/renameV3.sed -f postprocess.sed /tmp/z3V3.mli > z3V3.mli -sed -f /tmp/renameV3.sed -f postprocess.sed /tmp/z3V3.ml > z3V3.ml - -# ../z3_api.h -> z3_api.idl -sed -f add_error_checking.sed -f preprocess.sed ../z3_api.h > z3_api.idl - -# z3.idl (z3_api.idl x3.ml) -> z3_stubs.c, z3.mli, z3.ml -gcc -E -w -P -CC -xc -I. -DCAMLIDL $@ z3.0.idl > z3.idl -camlidl -nocpp z3.idl - -# reverse.sed to reverse order of substitution of enums to avoid matching prefixes such as enum_1 of enum_10 -grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_]*$" z3.mli | sed -e "s|and z3_\([a-zA-Z0-9_]*\) = \([a-zA-Z0-9_]*\)|s/\2/\1/g|g" -f reverse.sed > /tmp/rename.sed -grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_ ]* option$" z3.mli | sed -e "s|and \(z3_[a-zA-Z0-9_]*\) = \([a-zA-Z0-9_ ]*\)|s/\1/\2/g|g" >> /tmp/rename.sed - -# rename.sed to substitute out type equations for enums and options, then postprocess -cp z3.mli z3.ml /tmp -sed -f /tmp/rename.sed -f postprocess.sed /tmp/z3.mli > z3.mli -sed -f /tmp/rename.sed -f postprocess.sed /tmp/z3.ml > z3.ml - - -# append Z3.V3 module onto Z3 module -cat z3V3.mli >> z3.mli -cat z3V3.ml >> z3.ml -sed "1,22d" z3V3_stubs.c >> z3_stubs.c - -rm -f z3V3_api.idl z3V3.idl z3V3.ml z3V3.mli z3V3_stubs.c z3_api.idl z3.idl diff --git a/src/api/ml/old/import.cmd b/src/api/ml/old/import.cmd deleted file mode 100755 index b5239e011..000000000 --- a/src/api/ml/old/import.cmd +++ /dev/null @@ -1,55 +0,0 @@ -@echo off -SETLOCAL - -:CHECKARG1 -if not "%1"=="" ( - set SDTROOT=%1 - goto :CHECKARG2 -) - -goto :FAIL - - -:CHECKARG2 -if "%2"=="" ( - goto :IMPORT -) - -goto :FAIL - - -:IMPORT -cd import -sd edit ... -del z3.h z3_api.h z3_macros.h z3lib.lib msbig_rational.lib z3.exe test_capi.c test_mlapi_header.html z3_mlapi_header.html mldoc_footer.html tabs.css z3.png z3_ml.css -copy %SDTROOT%\lib\z3.h -copy %SDTROOT%\lib\z3_api.h -copy %SDTROOT%\lib\z3_macros.h -copy %SDTROOT%\release_mt\z3lib.lib -copy %SDTROOT%\release_mt\msbig_rational.lib -copy %SDTROOT%\release_mt\z3.exe -copy %SDTROOT%\test_capi\test_capi.c -copy %SDTROOT%\doc\test_mlapi_header.html -copy %SDTROOT%\doc\z3_mlapi_header.html -copy %SDTROOT%\doc\mldoc_footer.html -copy %SDTROOT%\doc\html\tabs.css -copy %SDTROOT%\doc\z3.png -copy %SDTROOT%\doc\z3_ml.css -sd add ... -sd revert -a ... -cd .. -goto :END - -:FAIL -echo "Usage:" -echo " %0 SDTROOT" -echo "" -echo "Examples:" -echo " %0 \\risebuild\drops\z32\2.0.51220.7" -echo " %0 \\risebuild\drops\z32\latest" -echo " %0 J:\SD\other\sdt1\src\z3_2" -echo "" -goto :END - -:END -ENDLOCAL diff --git a/src/api/ml/old/mlx_get_app_args.idl b/src/api/ml/old/mlx_get_app_args.idl deleted file mode 100644 index fe3407af8..000000000 --- a/src/api/ml/old/mlx_get_app_args.idl +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - - {b See also}: {!get_app_num_args} - - {b See also}: {!get_app_arg} -*) -val get_app_args: context -> app -> ast array -"); diff --git a/src/api/ml/old/mlx_get_array_sort.idl b/src/api/ml/old/mlx_get_array_sort.idl deleted file mode 100644 index 81bf6e00f..000000000 --- a/src/api/ml/old/mlx_get_array_sort.idl +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_array_sort c t ] \] is the domain and the range of [t]. - - - {b See also}: {!get_array_sort_domain} - - {b See also}: {!get_array_sort_range} -*) -val get_array_sort: context -> sort -> sort * sort -"); diff --git a/src/api/ml/old/mlx_get_datatype_sort.idl b/src/api/ml/old/mlx_get_datatype_sort.idl deleted file mode 100644 index 3466a9050..000000000 --- a/src/api/ml/old/mlx_get_datatype_sort.idl +++ /dev/null @@ -1,13 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_datatype_sort c ty ] \] is the array of triples [(constructor, recognizer, fields)] where [constructor] is the constructor declaration of [ty], [recognizer] is the recognizer for the [constructor], and [fields] is the array of fields in [ty]. - - - {b See also}: {!get_datatype_sort_num_constructors} - - {b See also}: {!get_datatype_sort_constructor} - - {b See also}: {!get_datatype_sort_recognizer} - - {b See also}: {!get_datatype_sort_constructor_accessor} -*) -val get_datatype_sort: context -> sort -> datatype_constructor array -"); diff --git a/src/api/ml/old/mlx_get_domains.idl b/src/api/ml/old/mlx_get_domains.idl deleted file mode 100644 index ebc6d8556..000000000 --- a/src/api/ml/old/mlx_get_domains.idl +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_domains c d ] \] is the array of parameters of [d]. - - - {b See also}: {!get_domain_size} - - {b See also}: {!get_domain} -*) -val get_domains: context -> func_decl -> sort array -"); diff --git a/src/api/ml/old/mlx_get_error_msg.idl b/src/api/ml/old/mlx_get_error_msg.idl deleted file mode 100644 index b8ea97e03..000000000 --- a/src/api/ml/old/mlx_get_error_msg.idl +++ /dev/null @@ -1,6 +0,0 @@ -quote(mli," -(** - Summary: Return a string describing the given error code. -*) -val get_error_msg: context -> error_code -> string -"); diff --git a/src/api/ml/old/mlx_get_pattern_terms.idl b/src/api/ml/old/mlx_get_pattern_terms.idl deleted file mode 100644 index 749a90f3a..000000000 --- a/src/api/ml/old/mlx_get_pattern_terms.idl +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_pattern_terms c p ] \] is the ast's in pattern. - - - {b See also}: {!get_pattern_num_terms} - - {b See also}: {!get_pattern} -*) -val get_pattern_terms: context -> pattern -> ast array;; -"); diff --git a/src/api/ml/old/mlx_get_tuple_sort.idl b/src/api/ml/old/mlx_get_tuple_sort.idl deleted file mode 100644 index 1555f6c8a..000000000 --- a/src/api/ml/old/mlx_get_tuple_sort.idl +++ /dev/null @@ -1,12 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ get_tuple_sort c ty ] \] is the pair [(mk_decl, fields)] where [mk_decl] is the constructor declaration of [ty], and [fields] is the array of fields in [ty]. - - - {b See also}: {!get_tuple_sort_mk_decl} - - {b See also}: {!get_tuple_sort_num_fields} - - {b See also}: {!get_tuple_sort_field_decl} -*) -val get_tuple_sort: context -> sort -> (func_decl * func_decl array) -"); diff --git a/src/api/ml/old/mlx_mk_context_x.idl b/src/api/ml/old/mlx_mk_context_x.idl deleted file mode 100644 index 7e4fd25c9..000000000 --- a/src/api/ml/old/mlx_mk_context_x.idl +++ /dev/null @@ -1,36 +0,0 @@ -quote(mlmli,"external mk_context: (string * string) list -> context = \"caml_z3_mk_context\" -"); -// Note: lack of whitespace and comments in the previous 2 lines is important for the documentation generation -quote(c," -value caml_z3_mk_context(value key_val_list) -{ - CAMLparam1( key_val_list ); - CAMLlocal4( item, vkey, vval, _vres ); - char * ckey; - char * cval; - Z3_config cfg; - Z3_context _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - - cfg = Z3_mk_config(); - - while (key_val_list != Val_emptylist) - { - item = Field(key_val_list, 0); - vkey = Field(item, 0); - vval = Field(item, 1); - ckey = camlidl_malloc_string(vkey, _ctx); - cval = camlidl_malloc_string(vval, _ctx); - Z3_set_param_value(cfg, ckey, cval); - key_val_list = Field(key_val_list, 1); - } - - _res = Z3_mk_context_rc(cfg); - Z3_del_config(cfg); - _vres = camlidl_c2ml_z3_Z3_context(&_res, _ctx); - camlidl_free(_ctx); - Z3_set_error_handler(_res, error_handler_static); - CAMLreturn(_vres); -} -"); diff --git a/src/api/ml/old/mlx_mk_datatypes.idl b/src/api/ml/old/mlx_mk_datatypes.idl deleted file mode 100644 index 21bdcdbc7..000000000 --- a/src/api/ml/old/mlx_mk_datatypes.idl +++ /dev/null @@ -1,28 +0,0 @@ -quote(mlmli," -(** A constructor of a datatype is described by: *) -type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) -} - -(** A datatype is described by a name and constructor descriptors. *) -type datatype_desc = symbol * datatype_constructor_desc array - -(** A constructor of a datatype is represented by: *) -type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) -} - -(** A datatype is represented by a sort and constructors. *) -type datatype = sort * datatype_constructor array -"); - -quote(mli," -(** [mk_datatypes ctx sorts_to_descriptors] creates mutually recursive datatypes described by - [sorts_to_descriptors], which is a function from the sorts of the datatypes to be created to - descriptors of the datatypes' constructors. {b See also}: {!Test_mlapi.forest_example} *) -val mk_datatypes: context -> (sort array -> (datatype_desc array) option) -> datatype array -"); diff --git a/src/api/ml/old/mlx_mk_numeral.idl b/src/api/ml/old/mlx_mk_numeral.idl deleted file mode 100644 index 0fa9caf39..000000000 --- a/src/api/ml/old/mlx_mk_numeral.idl +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mlmli," -(** - Summary: \[ [ numeral_refined ] \] is the refined view of a numeral . -*) -type numeral_refined = - | Numeral_int of int * sort - | Numeral_int64 of int64 * sort - | Numeral_large of string * sort - | Numeral_rational of numeral_refined * numeral_refined -"); - -quote(mli," -(** - Summary: \[ [ embed_numeral c nr ] \] constructs the numeral described by [nr]. - - - {b See also}: {!numeral_refine} -*) -val embed_numeral: context -> numeral_refined -> ast -"); diff --git a/src/api/ml/old/mlx_mk_sort.idl b/src/api/ml/old/mlx_mk_sort.idl deleted file mode 100644 index dd4222f81..000000000 --- a/src/api/ml/old/mlx_mk_sort.idl +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mlmli," -(** - A datatype constructor descriptor. -*) -type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) -} - -(** - A datatype is described by a name and constructor descriptors. -*) -type datatype_desc = symbol * datatype_constructor_desc array - -(** - A datatype constructor representation. -*) -type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) -} - -(** - A datatype is represented by a sort and constructors. -*) -type datatype = sort * datatype_constructor array - -(** - Refined view of a {!sort}. - - - {b See also}: {!mk_sort} - - {b See also}: {!sort_refine} -*) -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_bv of int - | Sort_finite_domain of symbol * int64 - | Sort_real - | Sort_array of sort * sort - | Sort_datatype of datatype_constructor array - | Sort_relation of sort array - | Sort_unknown -"); - -quote(mli," -(** - Summary: \[ [ mk_sort c sr ] \] constructs the sort described by [sr]. - - - {b Precondition}: [sr] is not of form [Sort_relation] or [Sort_unknown], which cannot be directly constructed - - {b See also}: {!mk_datatypes} - - {b See also}: {!sort_refine} -*) -val mk_sort: context -> sort_refined -> sort - -(** - \[ [mk_datatypes ctx sorts_to_descriptors] \] creates mutually recursive datatypes described by - [sorts_to_descriptors], which is a function from the sorts of the datatypes to be created to - descriptors of the datatypes' constructors. - - - {b See also}: {!Test_mlapi.forest_example} -*) -val mk_datatypes: context -> (sort array -> (datatype_desc array) option) -> datatype array -"); diff --git a/src/api/ml/old/mlx_mk_symbol.idl b/src/api/ml/old/mlx_mk_symbol.idl deleted file mode 100644 index 6969c7380..000000000 --- a/src/api/ml/old/mlx_mk_symbol.idl +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mlmli," -(** - Refined view of a {!symbol}. - - - {b See also}: {!mk_symbol} - - {b See also}: {!symbol_refine} -*) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string -"); - -quote(mli," -(** - Summary: \[ [ mk_symbol c sr ] \] constructs the symbol described by [sr]. - - - {b See also}: {!symbol_refine} -*) -val mk_symbol: context -> symbol_refined -> symbol -"); diff --git a/src/api/ml/old/mlx_model.idl b/src/api/ml/old/mlx_model.idl deleted file mode 100644 index 192a982b3..000000000 --- a/src/api/ml/old/mlx_model.idl +++ /dev/null @@ -1,19 +0,0 @@ -quote(mlmli," -(** - A model assigns uninterpreted sorts to finite universes of distinct values, constants to values, - and arrays and functions to finite maps from argument values to result values plus a default - value for all other arguments. -*) -type model_refined = { - sorts : (sort, ast_vector) Hashtbl.t; - consts : (func_decl, ast) Hashtbl.t; - arrays : (func_decl, (ast, ast) Hashtbl.t * ast) Hashtbl.t; - funcs : (func_decl, (ast array, ast) Hashtbl.t * ast) Hashtbl.t; -} -"); -quote(mli," -(** - Summary: [model_refine c m] is the refined model of [m]. -*) -val model_refine : context -> model -> model_refined -"); diff --git a/src/api/ml/old/mlx_numeral_refine.idl b/src/api/ml/old/mlx_numeral_refine.idl deleted file mode 100644 index 8b2f0a07f..000000000 --- a/src/api/ml/old/mlx_numeral_refine.idl +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ numeral_refine c a ] \] is the refined view of [a]. - - - {b Precondition}: [get_ast_kind c a = NUMERAL_AST] -*) -val numeral_refine : context -> ast -> numeral_refined -"); diff --git a/src/api/ml/old/mlx_parse_smtlib.idl b/src/api/ml/old/mlx_parse_smtlib.idl deleted file mode 100644 index dbc2e42da..000000000 --- a/src/api/ml/old/mlx_parse_smtlib.idl +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ parse_smtlib_string_x c str sort_names sorts decl_names decls ] \] - - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. - The symbols in the arrays [sort_names] and [decl_names] don't need to match the names - of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature - since we can use arbitrary names to reference sorts and declarations defined using the API. - - - {b See also}: {!parse_smtlib_file_x} -*) -val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - -(** - Summary: Similar to {!parse_smtlib_string_x}, but reads the benchmark from a file. - - - {b See also}: {!parse_smtlib_string_x} -*) -val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - -(** - Summary: \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - - - {b See also}: {!parse_smtlib_file_formula} - - {b See also}: {!parse_smtlib_string_x} -*) -val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - -(** - Summary: \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - - - {b See also}: {!parse_smtlib_string_formula} - - {b See also}: {!parse_smtlib_file_x} -*) -val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast -"); diff --git a/src/api/ml/old/mlx_sort_refine.idl b/src/api/ml/old/mlx_sort_refine.idl deleted file mode 100644 index 1f2ba8eab..000000000 --- a/src/api/ml/old/mlx_sort_refine.idl +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ sort_refine c s ] \] is the refined view of [s]. -*) -val sort_refine: context -> sort -> sort_refined -"); diff --git a/src/api/ml/old/mlx_statistics.idl b/src/api/ml/old/mlx_statistics.idl deleted file mode 100644 index 47028f012..000000000 --- a/src/api/ml/old/mlx_statistics.idl +++ /dev/null @@ -1,10 +0,0 @@ -quote(mlmli," -type stat_datum = Stat_int of int | Stat_float of float -type stats_refined = (string, stat_datum) Hashtbl.t -"); -quote(mli," -(** - Summary: [stats_refine c s] is the refined stats of [s]. -*) -val stats_refine : context -> stats -> stats_refined -"); diff --git a/src/api/ml/old/mlx_symbol_refine.idl b/src/api/ml/old/mlx_symbol_refine.idl deleted file mode 100644 index 0d74e9cd9..000000000 --- a/src/api/ml/old/mlx_symbol_refine.idl +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mli," -(** - Summary: \[ [ symbol_refine c s ] \] is the refined view of [s]. -*) -val symbol_refine: context -> symbol -> symbol_refined -"); diff --git a/src/api/ml/old/mlx_term_refine.idl b/src/api/ml/old/mlx_term_refine.idl deleted file mode 100644 index 2fa8fd36f..000000000 --- a/src/api/ml/old/mlx_term_refine.idl +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote(mlmli," -(** - Summary: \[ [ binder_type ] \] is a universal or existential quantifier. - - - {b See also}: {!term_refined} -*) -type binder_type = Forall | Exists - -(** - Summary: \[ [ term_refined ] \] is the refinement of a {!ast} . - - - {b See also}: {!term_refine} -*) -type term_refined = - | Term_numeral of numeral_refined - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_var of int * sort -"); - -quote(mli," -(** - Summary: \[ [ mk_term c tr ] \] constructs the term described by [tr]. - - - {b Precondition}: [tr] is not of form - - {b See also}: {!term_refine} -*) -(* val mk_term: context -> term_refined -> ast *) - - -(** - Summary: \[ [ term_refine c a ] \] is the refined view of [a]. -*) -val term_refine : context -> ast -> term_refined -"); diff --git a/src/api/ml/old/postprocess.sed b/src/api/ml/old/postprocess.sed deleted file mode 100644 index f25f70cb7..000000000 --- a/src/api/ml/old/postprocess.sed +++ /dev/null @@ -1,8 +0,0 @@ -# remove 'z3_' and 'Z3_' prefixes on names - -s/{\!Z3\./{\!/g -s/\([^_]\)[zZ]3_/\1/g - -# remove cyclic definitions introduced by substituting type equations - -s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g diff --git a/src/api/ml/old/preprocess.sed b/src/api/ml/old/preprocess.sed deleted file mode 100644 index c7d1fc804..000000000 --- a/src/api/ml/old/preprocess.sed +++ /dev/null @@ -1,82 +0,0 @@ -# attempt to clean up the mess with 'unsigned' -s/ unsigned/ unsigned int/g -s/unsigned int long/unsigned long/g -s/unsigned int __/unsigned __/g - - -# '@name ' -> 'Section: ' -# '\sa ' -> 'See also: ' -# '\brief ' -> 'Summary: ' -# '\remark ' -> 'Remark: ' -# '\pre ' -> 'Precondition: ' -# '\param ' -> '@param' -# '\warning ' -> 'Warning: ' -# '\code' -> 'C Example:' -# '\endcode' -> '' -/\\pre/s/(/ /g;/\\pre/s/,//g;/\\pre/s/)//g;s/\\pre /- {b Precondition}: /g -/\\ccode/s/(/ /g;/\\ccode/s/\\,//g;/\\ccode/s/)//g;s/\\ccode{\(.*\)}/\[\1\]/g -s/\\defgroup .*//g -s/@name \(.*\)/{2 {L \1}}/g -s/\\sa \(.*\)/- {b See also}: {!Z3.\1}/g -s/\\see \(.*\)/- {b See}: {!Z3.\1}/g -s//{e /g -s|| }|g -s/\\nicebox{/{e/g -s/\\brief /Summary: /g -s/\\remark /- {b Remarks}: /g -s/\\pre /- {b Precondition}: /g -s/\\param /@param /g -s/\\conly .*//g -s/\\warning /- {b Warning}: /g -s/\\code/{v /g -s/\\endcode/ v}/g -s/\\verbatim/{v /g -s/\\endverbatim/ v}/g -s/\\mlonly//g -s/\\endmlonly//g -s/\\mlh/\\\[ \[/g -s/\\endmlh/\] \\\]/g -s/\\deprecated/@deprecated/g -s/\\ / /g - -# '\c code ' -> '[code]' -s/\\c \([^ .,:]*\)/[\1]/g - -# '#Z3_' -> 'Z3.' -s/#Z3_\([^ \.,) ]*\)/{!Z3.\1}/g - -# '/*@}*/' -> '' -s/\/\*@{\*\///g - -# '/*@{*/' -> '' -s/\/\*@}\*\///g - -# '/*...*/' -> '' -s/\/\*.*\*\///g - -s|(\*\*/\*\*)|(\*\*%\*\*)|g - -# '/**' -> 'quote(mli,"(**' -s|/\*\*|quote(mli,\"(**|g - -# '...*/' -> '*)");' -s|[ ]*\*/|*)\");|g - -s|(\*\*%\*\*)|(\*\*/\*\*)|g - -# 'extern "C"' -> 'extern ~~C~~' -# 'quote(foo,"bar")' -> quote(foo,~~bar~~) -# mltype("foo") -> mltype(~~foo~~) -s/extern \"C\"/extern ~~C~~/g -s/quote(\(.*\),\"\(.*\)\")/quote(\1,~~\2~~)/g -s/quote(\(.*\),\"/quote(\1,~~/g -s/\")\;/~~);/g -s/\;\"/;~~/g -s/mltype(\"\(.*\)\")/mltype(~~\1~~)/g - -# '"' -> '\"' -s/\\\"/\"/g -s/\"/\\\"/g - -# '~~' -> '"' -s/~~/\"/g diff --git a/src/api/ml/old/queen.ml b/src/api/ml/old/queen.ml deleted file mode 100644 index e22db9cfb..000000000 --- a/src/api/ml/old/queen.ml +++ /dev/null @@ -1,112 +0,0 @@ -(* - queen.exe - JakobL@2007-09-22 - - Demonstration of how Z3 can be used to find solutions to the - N-Queens problem. - - See: http://en.wikipedia.org/wiki/Eight_queens_puzzle - - Problem specification: Is the following constraint system satisfiable, - for increasing n>=1, what are the models? - - constant - n: 8; - - variable - row: array n of [0..n-1]; - - rule - forall i in [0..n-2]: - (forall j in [i+1..n-1]: - ((row[i] <> row[j]) and - (i+row[i]) <> (j+row[j]) and - (i+row[j]) <> (j+row[i]))); - - The answer is yes for n different from 2 and 3. The number of solutions are: - * n=1: 1 - * n=2: 0 - * n=3: 0 - * n=4: 2 - * n=5: 10 - * n=6: 4 - * n=7: 40 - * n=8: 92 - * n=9: 352 - * n=10: 724 - ... -*) - -module Z3 = Z3.V3 - -(* Auxillary functions *) -let ( |> ) x f = f x;; -let printf = Printf.printf;; -let mk_var ctx name ty = Z3.mk_const ctx (Z3.mk_int_symbol ctx name) ty;; -let mk_int_var ctx name = Z3.mk_int_sort ctx |> mk_var ctx name;; -let mk_int ctx v = Z3.mk_int ctx v (Z3.mk_int_sort ctx);; -let checkreturn v = match v with | (true,r) -> r | _ -> failwith "checkreturn";; -let get_numeral_value_int a1 a2 = Z3.get_numeral_int a1 a2 |> checkreturn;; -let iterate_x lower upper f = for i = lower to upper do f i done;; -let forall_x ctx lower upper f = Z3.mk_and ctx (Array.init (1+upper-lower) (fun i->f (i+lower))) -let exist_x ctx lower upper f = Z3.mk_or ctx (Array.init (1+upper-lower) (fun i->f (i+lower))) -let get_value ctx model f = let (ok, v) = Z3.eval_func_decl ctx model f in (assert ok; v) - -let queen_n n = - let ctx = Z3.mk_context_x - [|("MODEL","true"); - ("RELEVANCY","0")|] in - let ( &&& ) x y = Z3.mk_and ctx [|x;y|] in - let ( <~> ) x y = Z3.mk_not ctx (Z3.mk_eq ctx x y) in - let ( <<= ) x y = Z3.mk_le ctx x y in - let ( +++ ) x y = Z3.mk_add ctx [|x;y|] in - let row = Array.init n (fun i->mk_int_var ctx i) in - let c x = mk_int ctx x in (* make constant *) - let v x = row.(x) in (* make variable *) - let constraint_domain=forall_x ctx (0) (n-1) (fun x-> ((c 0) <<= (v x)) &&& ((v x) <<= (c (n-1)))) in - let constraint_queen= - forall_x ctx (0) (n-2) (fun i-> - forall_x ctx (i+1) (n-1) (fun j-> - ((v i) <~> (v j)) &&& - (((c i)+++(v i)) <~> ((c j)+++(v j))) &&& - (((c i)+++(v j)) <~> ((c j)+++(v i))) - ) - ) in - let res = constraint_domain &&& constraint_queen in - Z3.assert_cnstr ctx res; - let rec f i = - (match Z3.check_and_get_model ctx with - | (Z3.L_FALSE,_) -> - printf "queen %d, total models: %d\n" n i; - flush stdout; - | (Z3.L_UNDEF,_) -> failwith "Z3.L_UNDEF" - | (Z3.L_TRUE,model) -> - begin - let model_constants=Z3.get_model_constants ctx model in - let vars=Array.map (fun mc->Z3.mk_app ctx mc [||]) model_constants in - let vals=Array.map (fun mc->get_value ctx model mc |> get_numeral_value_int ctx) model_constants in - Z3.del_model ctx model; - - let line = String.make n '-' in - let q_line i = let r = String.make n ' ' in String.set r i 'Q'; r in - printf "queen %d, model #%d:\n" n (i+1); - printf "\n"; - printf " /%s\\\n" line; - iterate_x 0 (n-1) (fun x->printf " |%s|\n" (q_line (vals.(x)))); - printf " \\%s/\n" line; - printf "\n"; - flush stdout; - let negated_model = exist_x ctx 0 (n-1) (fun x->(vars.(x)) <~> (c (vals.(x)))) in - Z3.assert_cnstr ctx negated_model; - f (i+1); - end - ) in - f 0; - Z3.del_context ctx; - ();; - -let queen() = - for n = 1 to 8 do - queen_n n - done;; - -let _ = queen();; diff --git a/src/api/ml/old/queen.regress.err b/src/api/ml/old/queen.regress.err deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/api/ml/old/queen.regress.out b/src/api/ml/old/queen.regress.out deleted file mode 100644 index 30e713386..000000000 --- a/src/api/ml/old/queen.regress.out +++ /dev/null @@ -1,1852 +0,0 @@ -queen 1, model #1: - - /-\ - |Q| - \-/ - -queen 1, total models: 1 -queen 2, total models: 0 -queen 3, total models: 0 -queen 4, model #1: - - /----\ - | Q | - | Q| - |Q | - | Q | - \----/ - -queen 4, model #2: - - /----\ - | Q | - |Q | - | Q| - | Q | - \----/ - -queen 4, total models: 2 -queen 5, model #1: - - /-----\ - | Q | - | Q | - |Q | - | Q | - | Q| - \-----/ - -queen 5, model #2: - - /-----\ - | Q | - | Q| - | Q | - |Q | - | Q | - \-----/ - -queen 5, model #3: - - /-----\ - | Q| - | Q | - |Q | - | Q | - | Q | - \-----/ - -queen 5, model #4: - - /-----\ - |Q | - | Q | - | Q | - | Q| - | Q | - \-----/ - -queen 5, model #5: - - /-----\ - | Q | - | Q| - | Q | - | Q | - |Q | - \-----/ - -queen 5, model #6: - - /-----\ - | Q | - |Q | - | Q | - | Q| - | Q | - \-----/ - -queen 5, model #7: - - /-----\ - | Q| - | Q | - | Q | - |Q | - | Q | - \-----/ - -queen 5, model #8: - - /-----\ - | Q | - | Q | - | Q| - | Q | - |Q | - \-----/ - -queen 5, model #9: - - /-----\ - |Q | - | Q | - | Q| - | Q | - | Q | - \-----/ - -queen 5, model #10: - - /-----\ - | Q | - |Q | - | Q | - | Q | - | Q| - \-----/ - -queen 5, total models: 10 -queen 6, model #1: - - /------\ - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - \------/ - -queen 6, model #2: - - /------\ - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - \------/ - -queen 6, model #3: - - /------\ - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - \------/ - -queen 6, model #4: - - /------\ - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - \------/ - -queen 6, total models: 4 -queen 7, model #1: - - /-------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - \-------/ - -queen 7, model #2: - - /-------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #3: - - /-------\ - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - \-------/ - -queen 7, model #4: - - /-------\ - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #5: - - /-------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \-------/ - -queen 7, model #6: - - /-------\ - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #7: - - /-------\ - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #8: - - /-------\ - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #9: - - /-------\ - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \-------/ - -queen 7, model #10: - - /-------\ - |Q | - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #11: - - /-------\ - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #12: - - /-------\ - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \-------/ - -queen 7, model #13: - - /-------\ - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #14: - - /-------\ - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #15: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - | Q| - \-------/ - -queen 7, model #16: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #17: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #18: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #19: - - /-------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #20: - - /-------\ - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #21: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - \-------/ - -queen 7, model #22: - - /-------\ - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - \-------/ - -queen 7, model #23: - - /-------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - \-------/ - -queen 7, model #24: - - /-------\ - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #25: - - /-------\ - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - \-------/ - -queen 7, model #26: - - /-------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #27: - - /-------\ - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \-------/ - -queen 7, model #28: - - /-------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - \-------/ - -queen 7, model #29: - - /-------\ - | Q| - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #30: - - /-------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \-------/ - -queen 7, model #31: - - /-------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \-------/ - -queen 7, model #32: - - /-------\ - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - \-------/ - -queen 7, model #33: - - /-------\ - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #34: - - /-------\ - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #35: - - /-------\ - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - \-------/ - -queen 7, model #36: - - /-------\ - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - \-------/ - -queen 7, model #37: - - /-------\ - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - |Q | - \-------/ - -queen 7, model #38: - - /-------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \-------/ - -queen 7, model #39: - - /-------\ - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - \-------/ - -queen 7, model #40: - - /-------\ - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - \-------/ - -queen 7, total models: 40 -queen 8, model #1: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #2: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - \--------/ - -queen 8, model #3: - - /--------\ - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #4: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #5: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #6: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - | Q| - \--------/ - -queen 8, model #7: - - /--------\ - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #8: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #9: - - /--------\ - |Q | - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #10: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #11: - - /--------\ - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #12: - - /--------\ - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #13: - - /--------\ - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #14: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #15: - - /--------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #16: - - /--------\ - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #17: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #18: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #19: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - |Q | - \--------/ - -queen 8, model #20: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #21: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - \--------/ - -queen 8, model #22: - - /--------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #23: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - \--------/ - -queen 8, model #24: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #25: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #26: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #27: - - /--------\ - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #28: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #29: - - /--------\ - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #30: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #31: - - /--------\ - | Q| - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #32: - - /--------\ - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #33: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #34: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - \--------/ - -queen 8, model #35: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - \--------/ - -queen 8, model #36: - - /--------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #37: - - /--------\ - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #38: - - /--------\ - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #39: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #40: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #41: - - /--------\ - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #42: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #43: - - /--------\ - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #44: - - /--------\ - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #45: - - /--------\ - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #46: - - /--------\ - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #47: - - /--------\ - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #48: - - /--------\ - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #49: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - \--------/ - -queen 8, model #50: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #51: - - /--------\ - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #52: - - /--------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #53: - - /--------\ - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #54: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #55: - - /--------\ - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #56: - - /--------\ - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #57: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #58: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #59: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #60: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #61: - - /--------\ - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #62: - - /--------\ - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #63: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #64: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #65: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #66: - - /--------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #67: - - /--------\ - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #68: - - /--------\ - | Q | - |Q | - | Q| - | Q | - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #69: - - /--------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #70: - - /--------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #71: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #72: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #73: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #74: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #75: - - /--------\ - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - \--------/ - -queen 8, model #76: - - /--------\ - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #77: - - /--------\ - |Q | - | Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #78: - - /--------\ - | Q | - |Q | - | Q | - | Q| - | Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #79: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #80: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - \--------/ - -queen 8, model #81: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #82: - - /--------\ - | Q | - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - \--------/ - -queen 8, model #83: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - \--------/ - -queen 8, model #84: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - |Q | - | Q| - | Q | - \--------/ - -queen 8, model #85: - - /--------\ - | Q | - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - \--------/ - -queen 8, model #86: - - /--------\ - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #87: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q| - | Q | - \--------/ - -queen 8, model #88: - - /--------\ - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #89: - - /--------\ - | Q | - | Q| - | Q | - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #90: - - /--------\ - | Q | - | Q | - | Q| - | Q | - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, model #91: - - /--------\ - | Q | - | Q | - | Q | - | Q | - |Q | - | Q | - | Q | - | Q| - \--------/ - -queen 8, model #92: - - /--------\ - | Q | - | Q | - | Q | - | Q| - |Q | - | Q | - | Q | - | Q | - \--------/ - -queen 8, total models: 92 diff --git a/src/api/ml/old/reverse.sed b/src/api/ml/old/reverse.sed deleted file mode 100644 index 31ac563d2..000000000 --- a/src/api/ml/old/reverse.sed +++ /dev/null @@ -1,3 +0,0 @@ -# output lines of input in reverse order - -1!G;h;$!d diff --git a/src/api/ml/old/test_mlapi.cmd b/src/api/ml/old/test_mlapi.cmd deleted file mode 100755 index 64315e3f7..000000000 --- a/src/api/ml/old/test_mlapi.cmd +++ /dev/null @@ -1,61 +0,0 @@ -@echo off -SETLOCAL - -REM Script to test the Z3 OCaml API -REM -REM Assumes that environment variables are set to provide access to the C and OCaml compilers, as well as the following commands: diff, dos2unix, sed - -REM directory containing z3_api.h -set Z3SRC=%1 - -REM directory containing z3.dll and z3.lib -set Z3BIN=%2 - -REM directory containing debug z3.dll -set Z3BINDBG=%3 - -set PATH=.;%2;%3;%PATH% - -echo Build test_capi -cl /nologo /I %Z3SRC% %Z3BIN%\z3.lib ..\test_capi\test_capi.c - -echo Build test_mlapi -ocamlc -w -a -o test_mlapi.byte.exe z3.cma test_mlapi.ml -ocamlopt -w -a -o test_mlapi.exe z3.cmxa test_mlapi.ml -ocamlc -g -w -a -o test_mlapi.byte.dbg.exe z3_dbg.cma test_mlapi.ml -ocamlopt -g -w -a -o test_mlapi.dbg.exe z3_dbg.cmxa test_mlapi.ml - -echo Build test_mlapiV3 -ocamlopt -g -w -a -o test_mlapiV3.dbg.exe z3_dbg.cmxa test_mlapiV3.ml - -echo Build test_theory -ocamlopt -g -w -a -o test_theory.dbg.exe z3_dbg.cmxa test_theory.ml - -echo Build queen -ocamlopt -g -w -a -o queen.exe z3_dbg.cmxa queen.ml - -echo Execute test_capi, test_mlapi, test_mlapiV3 and queen -test_capi.exe >test_capi.out 2>test_capi.orig.err -test_mlapi.dbg.exe >test_mlapi.out 2>test_mlapi.orig.err -test_mlapiV3.dbg.exe >test_mlapiV3.out 2>test_mlapiV3.orig.err -queen.exe >queen.out 2>queen.orig.err - -REM Strip pointers as they will always differ -sed test_capi.err "s/ \[.*\]/ [...]/g" -sed test_mlapi.err "s/ \[.*\]/ [...]/g" -sed test_mlapiV3.err "s/ \[.*\]/ [...]/g" -sed queen.err "s/ \[.*\]/ [...]/g" -del test_capi.orig.err test_mlapi.orig.err test_mlapiV3.orig.err queen.orig.err - -REM Compare with regressions -dos2unix *.out *.err 2>NUL -diff test_capi.regress.out test_capi.out >NUL || echo Regression failed, see: diff test_capi.regress.out test_capi.out -diff test_mlapi.regress.out test_mlapi.out >NUL || echo Regression failed, see: diff test_mlapi.regress.out test_mlapi.out -diff test_mlapiV3.regress.out test_mlapiV3.out >NUL || echo Regression failed, see: diff test_mlapiV3.regress.out test_mlapiV3.out -diff test_capi.regress.err test_capi.err >NUL || echo Regression failed, see: diff test_capi.regress.err test_capi.err -diff test_mlapi.regress.err test_mlapi.err >NUL || echo Regression failed, see: diff test_mlapi.regress.err test_mlapi.err -diff test_mlapiV3.regress.err test_mlapiV3.err >NUL || echo Regression failed, see: diff test_mlapiV3.regress.err test_mlapiV3.err -diff queen.regress.out queen.out >NUL || echo Regression failed, see: diff queen.regress.out queen.out -diff queen.regress.err queen.err >NUL || echo Regression failed, see: diff queen.regress.err queen.err - -ENDLOCAL diff --git a/src/api/ml/old/test_mlapi.ml b/src/api/ml/old/test_mlapi.ml deleted file mode 100644 index 149ae27f8..000000000 --- a/src/api/ml/old/test_mlapi.ml +++ /dev/null @@ -1,209 +0,0 @@ -(** Examples of using the OCaml API for Z3. *) - -(**/**) -(* pause documentation *) - -(* - @name Auxiliary Functions -*) - -(** - printf -*) -let printf = Printf.printf -;; - -(** - fprintf -*) -let fprintf = Printf.fprintf -;; - -(** - Exit gracefully in case of error. -*) -let exitf message = fprintf stderr "BUG: %s.\n" message ; exit 1 -;; - -(** - Create and print datatypes -*) -let mk_datatypes ctx generator = - let datatypes = Z3.mk_datatypes ctx generator in - printf "datatype created:\n%!" ; - Array.iter (fun (sort, ctors) -> - printf "sort: %s\n%!" (Z3.sort_to_string ctx sort) ; - Array.iter (fun {Z3.constructor; recognizer; accessors} -> - printf "constructor: %s%! recognizer: %s%! accessors:" - (Z3.func_decl_to_string ctx constructor) - (Z3.func_decl_to_string ctx recognizer) ; - Array.iter (fun accessor -> - printf " %s%!" (Z3.func_decl_to_string ctx accessor) - ) accessors ; - printf "\n" - ) ctors - ) datatypes ; - printf "\n" ; - datatypes -;; - - -(** - Create a variable using the given name and type. -*) -let mk_var ctx name ty = Z3.mk_const ctx (Z3.mk_string_symbol ctx name) ty -;; - -(* resume documentation *) -(**/**) - - -(** - Prove that the constraints already asserted into the logical - context implies the given formula. The result of the proof is - displayed. - Z3 is a satisfiability checker. So, one can prove {e f } by showing - that {e (not f) } is unsatisfiable. - The context {e ctx } is not modified by this function. -*) -let prove ctx slv f is_valid = - (* save the current state of the context *) - Z3.solver_push ctx slv ; - - let not_f = Z3.mk_not ctx f in - Z3.solver_assert ctx slv not_f ; - - (match Z3.solver_check ctx slv with - | Z3.L_FALSE -> - (* proved *) - printf "valid\n" ; - if not is_valid then exitf "unexpected result" - | Z3.L_UNDEF -> - (* Z3 failed to prove/disprove f. *) - printf "unknown\n" ; - let m = Z3.solver_get_model ctx slv in - (* m should be viewed as a potential counterexample. *) - printf "potential counterexample:\n%s\n" (Z3.model_to_string ctx m) ; - if is_valid then exitf "unexpected result" - | Z3.L_TRUE -> - (* disproved *) - printf "invalid\n" ; - let m = Z3.solver_get_model ctx slv in - (* the model returned by Z3 is a counterexample *) - printf "counterexample:\n%s\n" (Z3.model_to_string ctx m) ; - if is_valid then exitf "unexpected result" - ); - (* restore context *) - Z3.solver_pop ctx slv 1 -;; - - -(* n-ary trees and forests in OCaml *) -type tree = Leaf of int | Node of forest -and forest = tree list - -(** - Demonstrates the usage of {!Z3.mk_datatypes} with an example of forests of trees. -*) -let forest_example () = - let ctx = Z3.mk_context [] in - let slv = Z3.mk_solver ctx - in - let int_sort = Z3.mk_int_sort ctx in - let sym name = Z3.mk_string_symbol ctx name - in - (* n-ary trees and forests in Z3 *) - match - mk_datatypes ctx - (function [|tree; forest|] -> Some - [|(sym"tree", - [|{Z3.constructor_desc= sym"leaf"; recognizer_desc= sym"is_leaf"; accessor_descs= [|(sym"data", int_sort)|]}; - {Z3.constructor_desc= sym"node"; recognizer_desc= sym"is_node"; accessor_descs= [|(sym"children", forest)|]}|]); - (sym"forest", - [|{Z3.constructor_desc= sym"nil" ; recognizer_desc= sym"is_nil" ; accessor_descs= [||]}; - {Z3.constructor_desc= sym"cons"; recognizer_desc= sym"is_cons"; accessor_descs= [|(sym"hd", tree); (sym"tl", forest)|]}|])|] - | _ -> None - ) - with - [|(tree, - [|{Z3.constructor= leaf; recognizer= is_leaf; accessors= [|data|]}; - {Z3.constructor= node; recognizer= is_node; accessors= [|children|]}|]); - (forest, - [|{Z3.constructor= nil ; recognizer= is_nil ; accessors= [||]}; - {Z3.constructor= cons; recognizer= is_cons; accessors= [|hd; tl|]}|])|] - -> - (* translate from OCaml to Z3 *) - let rec ml2z3_tree = function - | Leaf(i) -> Z3.mk_app ctx leaf [|Z3.mk_int ctx i (Z3.mk_int_sort ctx)|] - | Node(f) -> Z3.mk_app ctx node [|ml2z3_forest f|] - - and ml2z3_forest = function - | [] -> Z3.mk_app ctx nil [||] - | t :: f -> Z3.mk_app ctx cons [|ml2z3_tree t; ml2z3_forest f|] - in - - (* construct some OCaml trees *) - let t0 = Leaf 0 in - let t12 = Node [Leaf 1; Leaf 2] in - let t123 = Node [t12; Leaf 3] in - let t1212 = Node [t12; t12] in - let t412 = Node [Leaf 4; t12] in - - (* construct some Z3 trees using the translation from OCaml *) - let t1 = ml2z3_tree t12 in printf "t1: %s\n%!" (Z3.ast_to_string ctx t1) ; - let t2 = ml2z3_tree t123 in printf "t2: %s\n%!" (Z3.ast_to_string ctx t2) ; - let t3 = ml2z3_tree t1212 in printf "t3: %s\n%!" (Z3.ast_to_string ctx t3) ; - let t4 = ml2z3_tree t412 in printf "t4: %s\n%!" (Z3.ast_to_string ctx t4) ; - let f1 = ml2z3_forest [t0] in printf "f1: %s\n%!" (Z3.ast_to_string ctx f1) ; - let f2 = ml2z3_forest [t12] in printf "f2: %s\n%!" (Z3.ast_to_string ctx f2) ; - let f3 = ml2z3_forest [t12; t0] in printf "f3: %s\n%!" (Z3.ast_to_string ctx f3) ; - - (* or using the Z3 API *) - let nil = Z3.mk_app ctx nil [||] in - let cons t f = Z3.mk_app ctx cons [|t; f|] in - let leaf i = Z3.mk_app ctx leaf [|Z3.mk_int ctx i (Z3.mk_int_sort ctx)|] in - let node f = Z3.mk_app ctx node [|f|] in - - let t0 = leaf 0 in - let t12 = node (cons (leaf 1) (cons (leaf 2) nil)) in - let t123 = node (cons t12 (cons (leaf 3) nil)) in - let t1212 = node (cons t12 (cons t12 nil)) in - let t412 = node (cons (leaf 4) (cons t12 nil)) in - - let t1 = t12 in printf "t1: %s\n%!" (Z3.ast_to_string ctx t1) ; - let t2 = t123 in printf "t2: %s\n%!" (Z3.ast_to_string ctx t2) ; - let t3 = t1212 in printf "t3: %s\n%!" (Z3.ast_to_string ctx t3) ; - let t4 = t412 in printf "t4: %s\n%!" (Z3.ast_to_string ctx t4) ; - let f1 = cons t0 nil in printf "f1: %s\n%!" (Z3.ast_to_string ctx f1) ; - let f2 = cons t12 nil in printf "f2: %s\n%!" (Z3.ast_to_string ctx f2) ; - let f3 = cons t12 f1 in printf "f3: %s\n%!" (Z3.ast_to_string ctx f3) ; - - (* nil != cons(nil,nil) *) - prove ctx slv (Z3.mk_not ctx (Z3.mk_eq ctx nil f1)) true ; - prove ctx slv (Z3.mk_not ctx (Z3.mk_eq ctx (leaf 5) t1)) true ; - - (* cons(x,u) = cons(x, v) => u = v *) - let u = mk_var ctx "u" forest in - let v = mk_var ctx "v" forest in - let x = mk_var ctx "x" tree in - let y = mk_var ctx "y" tree in - let l1 = cons x u in printf "l1: %s\n%!" (Z3.ast_to_string ctx l1) ; - let l2 = cons y v in printf "l2: %s\n%!" (Z3.ast_to_string ctx l2) ; - - prove ctx slv (Z3.mk_implies ctx (Z3.mk_eq ctx l1 l2) (Z3.mk_eq ctx u v)) true ; - prove ctx slv (Z3.mk_implies ctx (Z3.mk_eq ctx l1 l2) (Z3.mk_eq ctx x y)) true ; - - (* is_nil(u) or is_cons(u) *) - prove ctx slv (Z3.mk_or ctx [|Z3.mk_app ctx is_nil [|u|]; Z3.mk_app ctx is_cons [|u|]|]) true ; - - (* occurs check u != cons(x,u) *) - prove ctx slv (Z3.mk_not ctx (Z3.mk_eq ctx u l1)) true ; - - | _ -> - exitf "unexpected datatype signature" -;; - -let _ = - ignore( Z3.open_log "test_mlapi.log" ); - forest_example () ; -;; diff --git a/src/api/ml/old/test_mlapiV3.ml b/src/api/ml/old/test_mlapiV3.ml deleted file mode 100644 index a88d13000..000000000 --- a/src/api/ml/old/test_mlapiV3.ml +++ /dev/null @@ -1,1418 +0,0 @@ -(** Module test_mlapi - ML test and demo program for Z3. Matches test_capi.ml - JakobL@2007-09-08 *) - -module Z3 = Z3.V3 - -(* - @name Auxiliary Functions -*) - -(** - printf -*) -let printf = Printf.printf;; - -(** - fprintf -*) -let fprintf = Printf.fprintf;; - -(** - Exit gracefully in case of error. -*) -let exitf message = fprintf stderr "BUG: %s.\n" message; exit 1;; - -(** - Create a logical context. Enable model construction. - Also enable tracing to stderr. -*) -let mk_context ctx = - let ctx = Z3.mk_context_x (Array.append [|("MODEL", "true")|] ctx) in - (* You may comment out the following line to disable tracing: *) - (* Z3.trace_to_stderr ctx; *) - ctx;; - -(** - Create a variable using the given name and type. -*) -let mk_var ctx name ty = Z3.mk_const ctx (Z3.mk_string_symbol ctx name) ty;; - -(** - Create a boolean variable using the given name. -*) -let mk_bool_var ctx name = mk_var ctx name (Z3.mk_bool_sort ctx);; - -(** - Create an integer variable using the given name. -*) -let mk_int_var ctx name = mk_var ctx name (Z3.mk_int_sort ctx);; - -(** - Create a Z3 integer node using a C int. -*) -let mk_int ctx v = Z3.mk_int ctx v (Z3.mk_int_sort ctx);; - -(** - Create a real variable using the given name. -*) -let mk_real_var ctx name = mk_var ctx name (Z3.mk_real_sort ctx);; - -(** - Create the unary function application: {e (f x) }. -*) -let mk_unary_app ctx f x = Z3.mk_app ctx f [|x|];; - -(** - Create the binary function application: {e (f x y) }. -*) -let mk_binary_app ctx f x y = Z3.mk_app ctx f [|x;y|];; - -(** - Auxiliary function to check whether two Z3 types are equal or not. -*) -let equal_sorts ctx t1 t2 = Z3.is_eq_sort ctx t1 t2;; - -(** - Check whether the logical context is satisfiable, and compare the result with the expected result. - If the context is satisfiable, then display the model. -*) -let check ctx expected_result = - begin - let (result, m) = Z3.check_and_get_model ctx in - (match result with - | Z3.L_FALSE -> printf "unsat\n"; - | Z3.L_UNDEF -> - printf "unknown\n"; - printf "potential model:\n%s\n" (Z3.model_to_string ctx m); - (Z3.del_model ctx m); - | Z3.L_TRUE -> printf "sat\n%s\n" (Z3.model_to_string ctx m); - (Z3.del_model ctx m); - ); - if result != expected_result then exitf "unexpected result"; - end;; - -(** - Prove that the constraints already asserted into the logical - context implies the given formula. The result of the proof is - displayed. - Z3 is a satisfiability checker. So, one can prove {e f } by showing - that {e (not f) } is unsatisfiable. - The context {e ctx } is not modified by this function. -*) -let prove ctx f is_valid = - begin - (* save the current state of the context *) - Z3.push ctx; - - let not_f = Z3.mk_not ctx f in - Z3.assert_cnstr ctx not_f; - - (match Z3.check_and_get_model ctx with - | (Z3.L_FALSE,_) -> - (* proved *) - printf "valid\n"; - if not is_valid then exitf "unexpected result"; - | (Z3.L_UNDEF,m) -> - (* Z3 failed to prove/disprove f. *) - printf "unknown\n"; - (* m should be viewed as a potential counterexample. *) - printf "potential counterexample:\n%s\n" (Z3.model_to_string ctx m); - if is_valid then exitf "unexpected result"; - (Z3.del_model ctx m); - | (Z3.L_TRUE,m) -> - (* disproved *) - printf "invalid\n"; - (* the model returned by Z3 is a counterexample *) - printf "counterexample:\n%s\n" (Z3.model_to_string ctx m); - if is_valid then exitf "unexpected result"; - (Z3.del_model ctx m); - ); - (* restore context *) - Z3.pop ctx 1; - end;; - -(** - Assert the axiom: function f is injective in the i-th argument. - - The following axiom is asserted into the logical context: - - forall (x_1, ..., x_n) finv(f(x_1, ..., x_i, ..., x_n)) = x_i - - Where, {e finv } is a fresh function declaration. -*) -let assert_inj_axiom ctx f i = - begin - let sz = Z3.get_domain_size ctx f in - if i >= sz then exitf "failed to create inj axiom"; - - (* declare the i-th inverse of f: finv *) - let finv_domain = Z3.get_range ctx f in - let finv_range = Z3.get_domain ctx f i in - let finv = Z3.mk_fresh_func_decl ctx "inv" [|finv_domain|] finv_range in - - (* allocate temporary arrays *) - (* fill types, names and xs *) - let types = Z3.get_domains ctx f in - let names = Array.init sz (Z3.mk_int_symbol ctx) in - let xs = Array.init sz (fun j->Z3.mk_bound ctx j (types.(j))) in - - (* create f(x_0, ..., x_i, ..., x_{n-1}) *) - let fxs = Z3.mk_app ctx f xs in - - (* create f_inv(f(x_0, ..., x_i, ..., x_{n-1})) *) - let finv_fxs = mk_unary_app ctx finv fxs in - - (* create finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i *) - let eq = Z3.mk_eq ctx finv_fxs (xs.(i)) in - - (* use f(x_0, ..., x_i, ..., x_{n-1}) as the pattern for the quantifier *) - let p = Z3.mk_pattern ctx [|fxs|] in - printf "pattern: %s\n" (Z3.pattern_to_string ctx p); - printf "\n"; - - (* create & assert quantifier *) - let q = Z3.mk_forall ctx - 0 (* using default weight *) - [|p|] (* the "array" of patterns *) - types - names - eq - in - printf "assert axiom:\n%s\n" (Z3.ast_to_string ctx q); - Z3.assert_cnstr ctx q; - end;; - -(** - Assert the axiom: function f is commutative. - - This example uses the SMT-LIB parser to simplify the axiom construction. -*) -let assert_comm_axiom ctx f = - begin - let t = Z3.get_range ctx f in - if Z3.get_domain_size ctx f != 2 || not (equal_sorts ctx (Z3.get_domain ctx f 0) t) || not (equal_sorts ctx (Z3.get_domain ctx f 1) t) then - exitf "function must be binary, and argument types must be equal to return type"; - (* Inside the parser, function f will be referenced using the symbol 'f'. *) - let f_name = Z3.mk_string_symbol ctx "f" in - (* Inside the parser, type t will be referenced using the symbol 'T'. *) - let t_name = Z3.mk_string_symbol ctx "T" in - let str = "(benchmark comm :formula (forall (x T) (y T) (= (f x y) (f y x))))" in - let q = Z3.parse_smtlib_string_formula ctx str [|t_name|] [|t|] [|f_name|] [|f|] in - printf "assert axiom:\n%s\n" (Z3.ast_to_string ctx q); - Z3.assert_cnstr ctx q; - end;; - -(** - Z3 does not support explicitly tuple updates. They can be easily implemented - as macros. The argument {e t } must have tuple type. - A tuple update is a new tuple where field {e i } has value {e new_val }, and all - other fields have the value of the respective field of {e t }. - - {e update(t, i, new_val) } is equivalent to - {e mk_tuple(proj_0(t), ..., new_val, ..., proj_n(t)) } -*) -let mk_tuple_update c t i new_val = - begin - let ty = Z3.get_sort c t in - let (mk_tuple_decl,fields)=Z3.get_tuple_sort c ty in - if i>=Array.length fields then exitf "invalid tuple update, index is too big"; - let f j = - if i = j then (* use new_val at position i: *) new_val - else (* use field j of t: *) (mk_unary_app c (fields.(j)) t) - in let new_fields = Array.init (Array.length fields) f in - Z3.mk_app c (Z3.get_tuple_sort_mk_decl c ty) new_fields; - end;; - -(** - Display a symbol in the given output stream. -*) -let display_symbol c out s = - match Z3.symbol_refine c s with - | Z3.Symbol_int i -> fprintf out "#%d" i; - | Z3.Symbol_string r ->fprintf out "%s" r; - | Z3.Symbol_unknown -> ();; - -(** - Display the given type. -*) -let rec display_sort c out ty = - begin - match Z3.sort_refine c ty with - | Z3.Sort_uninterpreted s -> display_symbol c out s; - | Z3.Sort_bool -> fprintf out "bool"; - | Z3.Sort_int -> fprintf out "int"; - | Z3.Sort_real -> fprintf out "real"; - | Z3.Sort_relation -> fprintf out "relation"; - | Z3.Sort_finite_domain -> fprintf out "finite-domain"; - | Z3.Sort_bv sz -> fprintf out "bv%d" sz; - | Z3.Sort_array (domain, range) -> - fprintf out "["; - display_sort c out domain; - fprintf out "->"; - display_sort c out range; - fprintf out "]"; - | Z3.Sort_datatype cons -> - Array.iter (fun (dt_con : Z3.datatype_constructor_refined) -> - let fields = dt_con.Z3.accessors in - fprintf out "("; - let f i v = - if i>0 then fprintf out ", "; - display_sort c out (Z3.get_range c v); - in Array.iteri f fields; - fprintf out ")") cons - | Z3.Sort_unknown s -> - fprintf out "unknown["; - display_symbol c out s; - fprintf out "unknown]"; - end;; - -(** - Custom ast pretty printer. - - This function demonstrates how to use the API to navigate terms. -*) - -let rec display_numeral c out nm = - match nm with - | Z3.Numeral_small(n,1L) -> - Printf.fprintf out "%Ld" n - | Z3.Numeral_small(n,d) -> - Printf.fprintf out "%Ld/%Ld" n d - | Z3.Numeral_large s -> - Printf.fprintf out "%s" s - -let rec display_ast c out v = - begin - match Z3.term_refine c v with - | Z3.Term_app(k, f, args) -> - let num_fields = Array.length args in - let a = Z3.to_app c v in - let d = Z3.get_app_decl c a in - Printf.fprintf out "%s" (Z3.func_decl_to_string c d); - if num_fields > 0 then - begin - Printf.fprintf out "["; - for i = 0 to num_fields - 1 do - if i > 0 then Printf.fprintf out ", "; - display_ast c out (Z3.get_app_arg c a i) - done; - Printf.fprintf out "]" - end - | Z3.Term_numeral(nm, s) -> - display_numeral c out nm; - Printf.fprintf out ":"; - display_sort c out s - | Z3.Term_var(idx, s) -> - printf "#unknown" - | Z3.Term_quantifier(b, w, pats, bound, body) -> - printf "quantifier" - end;; - -(** - Custom function for traversing a term and replacing the constant - 'x' by the bound variable having index 'idx'. - This function illustrates how to walk Z3 terms and - reconstruct them. -**) - -let rec abstract c x idx term = - if Z3.is_eq_ast c term x then Z3.mk_bound c idx (Z3.get_sort c x) else - match Z3.term_refine c term with - | Z3.Term_app(k, f, args) -> Z3.mk_app c f (Array.map (abstract c x idx) args) - | Z3.Term_numeral(nm, s) -> term - | Z3.Term_var(idx, s) -> term - | Z3.Term_quantifier(b, w, pats, bound, body) -> - let idx = (idx + Array.length bound) in - let body = abstract c x idx body in - let is_forall = b = Z3.Forall in - let mk_pattern terms = Z3.mk_pattern c (Array.map (abstract c x idx) terms) in - let patterns = Array.map mk_pattern pats in - Z3.mk_quantifier c is_forall w patterns - (Array.map snd bound) (Array.map fst bound) body - -(** - Example abstraction function. -**) - - -let abstract_example() = - begin - printf "\nabstract_example\n"; - let ctx = mk_context [||] in - let x = mk_int_var ctx "x" in - let x_decl = Z3.get_app_decl ctx (Z3.to_app ctx x) in - let y = mk_int_var ctx "y" in - let y_decl = Z3.get_app_decl ctx (Z3.to_app ctx y) in - let decls = [| x_decl; y_decl |] in - let a = Z3.mk_string_symbol ctx "a" in - let b = Z3.mk_string_symbol ctx "b" in - let names = [| a; b |] in - let str = "(benchmark tst :formula (> a b))" in - let f = Z3.parse_smtlib_string_formula ctx str [||] [||] names decls in - printf "formula: %s\n" (Z3.ast_to_string ctx f); - - let f2 = abstract ctx x 0 f in - - printf "abstracted formula: %s\n" (Z3.ast_to_string ctx f2); - (* delete logical context *) - Z3.del_context ctx; - - end;; - -(** - Custom function interpretations pretty printer. -*) -let display_function_interpretations c out m = - begin - fprintf out "function interpretations:\n"; - let display_function (name, entries, func_else) = - begin - display_symbol c out name; - fprintf out " = {"; - let display_entry j (args,valu) = - if j > 0 then fprintf out ", "; - fprintf out "("; - let f k arg = - if k > 0 then fprintf out ", "; - display_ast c out arg - in Array.iteri f args; - fprintf out "|->"; - display_ast c out valu; - fprintf out ")"; - in Array.iteri display_entry entries; - if Array.length entries > 0 then fprintf out ", "; - fprintf out "(else|->"; - display_ast c out func_else; - fprintf out ")}\n"; - end; - in - Array.iter display_function (Z3.get_model_funcs c m); - end;; - -(** - Custom model pretty printer. -*) -let display_model c out m = - begin - let constants=Z3.get_model_constants c m in - let f i e = - let name = Z3.get_decl_name c e in - let (ok, v) = Z3.eval_func_decl c m e in - display_symbol c out name; - fprintf out " = "; - display_ast c out v; - fprintf out "\n" - in Array.iteri f constants; - display_function_interpretations c out m; - end;; - -(** - Similar to #check, but uses #display_model instead of #Z3_model_to_string. -*) -let check2 ctx expected_result = - begin - let (result,m) = Z3.check_and_get_model ctx in - (match result with - | Z3.L_FALSE -> - printf "unsat\n"; - | Z3.L_UNDEF -> - printf "unknown\n"; - printf "potential model:\n"; - display_model ctx stdout m; - (Z3.del_model ctx m); - | Z3.L_TRUE -> - printf "sat\n"; - display_model ctx stdout m; - (Z3.del_model ctx m); - ); - if result != expected_result then exitf "unexpected result"; - end;; - -(** - Display Z3 version in the standard output. -*) -let display_version() = - begin - let (major, minor, build, revision)=Z3.get_version() in - printf "Z3 %d.%d.%d.%d\n" major minor build revision; - end;; - -(* - @name Examples -*) - -(** - "Hello world" example: create a Z3 logical context, and delete it. -*) -let simple_example() = - begin - printf "\nsimple_example\n"; - let ctx = mk_context [||] in - (* do something with the context *) - printf "CONTEXT:\n%sEND OF CONTEXT\n" (Z3.context_to_string ctx); - (* delete logical context *) - Z3.del_context ctx; - end;; - -(** - Demonstration of how Z3 can be used to prove validity of - De Morgan's Duality Law: {e not(x and y) <-> (not x) or ( not y) } -*) -let demorgan() = - begin - printf "\nDeMorgan\n"; - let ctx = mk_context [||] in - let bool_sort = Z3.mk_bool_sort ctx in - let symbol_x = Z3.mk_int_symbol ctx 0 in - let symbol_y = Z3.mk_int_symbol ctx 1 in - let x = Z3.mk_const ctx symbol_x bool_sort in - let y = Z3.mk_const ctx symbol_y bool_sort in - - (* De Morgan - with a negation around: *) - (* !(!(x && y) <-> (!x || !y)) *) - let not_x = Z3.mk_not ctx x in - let not_y = Z3.mk_not ctx y in - let x_and_y = Z3.mk_and ctx [|x;y|] in - let ls = Z3.mk_not ctx x_and_y in - let rs = Z3.mk_or ctx [|not_x;not_y|] in - let conjecture = Z3.mk_iff ctx ls rs in - let negated_conjecture = Z3.mk_not ctx conjecture in - - Z3.assert_cnstr ctx negated_conjecture; - (match Z3.check ctx with - | Z3.L_FALSE -> - (* The negated conjecture was unsatisfiable, hence the conjecture is valid *) - printf "DeMorgan is valid\n" - | Z3.L_UNDEF -> - (* Check returned undef *) - printf "Undef\n" - | Z3.L_TRUE -> - (* The negated conjecture was satisfiable, hence the conjecture is not valid *) - Printf.printf "DeMorgan is not valid\n"); - Z3.del_context ctx; - end;; - -(** - Find a model for {e x xor y }. -*) -let find_model_example1() = - begin - printf "\nfind_model_example1\n"; - let ctx = mk_context [||] in - let x = mk_bool_var ctx "x" in - let y = mk_bool_var ctx "y" in - let x_xor_y = Z3.mk_xor ctx x y in - Z3.assert_cnstr ctx x_xor_y; - printf "model for: x xor y\n"; - check ctx Z3.L_TRUE; - Z3.del_context ctx; - end;; - -(** - Find a model for {e x < y + 1, x > 2 }. - Then, assert {e not(x = y) }, and find another model. -*) -let find_model_example2() = - begin - printf "\nfind_model_example2\n"; - let ctx = mk_context [||] in - let x = mk_int_var ctx "x" in - let y = mk_int_var ctx "y" in - let one = mk_int ctx 1 in - let two = mk_int ctx 2 in - let y_plus_one = Z3.mk_add ctx [|y;one|] in - let c1 = Z3.mk_lt ctx x y_plus_one in - let c2 = Z3.mk_gt ctx x two in - Z3.assert_cnstr ctx c1; - Z3.assert_cnstr ctx c2; - printf "model for: x < y + 1, x > 2\n"; - check ctx Z3.L_TRUE; - - (* assert not(x = y) *) - let x_eq_y = Z3.mk_eq ctx x y in - let c3 = Z3.mk_not ctx x_eq_y in - Z3.assert_cnstr ctx c3; - printf "model for: x < y + 1, x > 2, not(x = y)\n"; - check ctx Z3.L_TRUE; - Z3.del_context ctx; - end;; - -(** - Prove {e x = y implies g(x) = g(y) }, and - disprove {e x = y implies g(g(x)) = g(y) }. - - This function demonstrates how to create uninterpreted types and - functions. -*) -let prove_example1() = - begin - printf "\nprove_example1\n"; - - let ctx = mk_context [||] in - - (* create uninterpreted type. *) - let u_name = Z3.mk_string_symbol ctx "U" in - let u = Z3.mk_uninterpreted_sort ctx u_name in - - (* declare function g *) - let g_name = Z3.mk_string_symbol ctx "g" in - let g = Z3.mk_func_decl ctx g_name [|u|] u in - - (* create x and y *) - let x_name = Z3.mk_string_symbol ctx "x" in - let y_name = Z3.mk_string_symbol ctx "y" in - let x = Z3.mk_const ctx x_name u in - let y = Z3.mk_const ctx y_name u in - (* create g(x), g(y) *) - let gx = mk_unary_app ctx g x in - let gy = mk_unary_app ctx g y in - - (* assert x = y *) - let eq = Z3.mk_eq ctx x y in - Z3.assert_cnstr ctx eq; - - (* prove g(x) = g(y) *) - let f = Z3.mk_eq ctx gx gy in - printf "prove: x = y implies g(x) = g(y)\n"; - prove ctx f true; - - (* create g(g(x)) *) - let ggx = mk_unary_app ctx g gx in - - (* disprove g(g(x)) = g(y) *) - let f = Z3.mk_eq ctx ggx gy in - printf "disprove: x = y implies g(g(x)) = g(y)\n"; - prove ctx f false; - - Z3.del_context ctx; - end;; - -(** - Prove {e not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 }. - Then, show that {e z < -1 } is not implied. - - This example demonstrates how to combine uninterpreted functions and arithmetic. -*) -let prove_example2() = - begin - printf "\nprove_example2\n"; - - let ctx = mk_context [||] in - - (* declare function g *) - let int_sort = Z3.mk_int_sort ctx in - let g_name = Z3.mk_string_symbol ctx "g" in - let g = Z3.mk_func_decl ctx g_name [|int_sort|] int_sort in - - (* create x, y, and z *) - let x = mk_int_var ctx "x" in - let y = mk_int_var ctx "y" in - let z = mk_int_var ctx "z" in - - (* create gx, gy, gz *) - let gx = mk_unary_app ctx g x in - let gy = mk_unary_app ctx g y in - let gz = mk_unary_app ctx g z in - - (* create zero *) - let zero = mk_int ctx 0 in - - (* assert not(g(g(x) - g(y)) = g(z)) *) - let gx_gy = Z3.mk_sub ctx [|gx;gy|] in - let ggx_gy = mk_unary_app ctx g gx_gy in - let eq = Z3.mk_eq ctx ggx_gy gz in - let c1 = Z3.mk_not ctx eq in - Z3.assert_cnstr ctx c1; - - (* assert x + z <= y *) - let x_plus_z = Z3.mk_add ctx [|x;z|] in - let c2 = Z3.mk_le ctx x_plus_z y in - Z3.assert_cnstr ctx c2; - - (* assert y <= x *) - let c3 = Z3.mk_le ctx y x in - Z3.assert_cnstr ctx c3; - - (* prove z < 0 *) - let f = Z3.mk_lt ctx z zero in - printf "prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0\n"; - prove ctx f true; - - (* disprove z < -1 *) - let minus_one = mk_int ctx (-1) in - let f = Z3.mk_lt ctx z minus_one in - printf "disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1\n"; - prove ctx f false; - - Z3.del_context ctx; - end;; - -(** - Show how push & pop can be used to create "backtracking" - points. - - This example also demonstrates how big numbers can be created in Z3. -*) -let push_pop_example1() = - begin - printf "\npush_pop_example1\n"; - let ctx = mk_context [||] in - - (* create a big number *) - let int_sort = Z3.mk_int_sort ctx in - let big_number = Z3.mk_numeral ctx "1000000000000000000000000000000000000000000000000000000" int_sort in - - (* create number 3 *) - let three = Z3.mk_numeral ctx "3" int_sort in - - (* create x *) - let x_sym = Z3.mk_string_symbol ctx "x" in - let x = Z3.mk_const ctx x_sym int_sort in - - (* assert x >= "big number" *) - let c1 = Z3.mk_ge ctx x big_number in - printf "assert: x >= 'big number'\n"; - Z3.assert_cnstr ctx c1; - - (* create a backtracking point *) - printf "push\n"; - Z3.push ctx; - - printf "number of scopes: %d\n" (Z3.get_num_scopes ctx); - - (* assert x <= 3 *) - let c2 = Z3.mk_le ctx x three in - printf "assert: x <= 3\n"; - Z3.assert_cnstr ctx c2; - - (* context is inconsistent at this point *) - check2 ctx Z3.L_FALSE; - - (* backtrack: the constraint x <= 3 will be removed, since it was - asserted after the last push. *) - printf "pop\n"; - Z3.pop ctx 1; - - printf "number of scopes: %d\n" (Z3.get_num_scopes ctx); - - (* the context is consistent again. *) - check2 ctx Z3.L_TRUE; - - (* new constraints can be asserted... *) - - (* create y *) - let y_sym = Z3.mk_string_symbol ctx "y" in - let y = Z3.mk_const ctx y_sym int_sort in - - (* assert y > x *) - let c3 = Z3.mk_gt ctx y x in - printf "assert: y > x\n"; - Z3.assert_cnstr ctx c3; - - (* the context is still consistent. *) - check2 ctx Z3.L_TRUE; - - Z3.del_context ctx; - end;; - -(** - Prove that {e f(x, y) = f(w, v) implies y = v } when - {e f } is injective in the second argument. -*) -let quantifier_example1() = - begin - printf "\nquantifier_example1\n"; - - (* If quantified formulas are asserted in a logical context, then - Z3 may return L_UNDEF. In this case, the model produced by Z3 should be viewed as a potential/candidate model. - Limiting the number of iterations of the model finder for quantified formulas. - *) - let ctx = mk_context [|("MBQI_MAX_ITERATIONS", "10")|] in - - (* declare function f *) - let int_sort = Z3.mk_int_sort ctx in - let f_name = Z3.mk_string_symbol ctx "f" in - let f = Z3.mk_func_decl ctx f_name [|int_sort; int_sort|] int_sort in - - (* assert that f is injective in the second argument. *) - assert_inj_axiom ctx f 1; - - (* create x, y, v, w, fxy, fwv *) - let x = mk_int_var ctx "x" in - let y = mk_int_var ctx "y" in - let v = mk_int_var ctx "v" in - let w = mk_int_var ctx "w" in - let fxy = mk_binary_app ctx f x y in - let fwv = mk_binary_app ctx f w v in - - (* assert f(x, y) = f(w, v) *) - let p1 = Z3.mk_eq ctx fxy fwv in - Z3.assert_cnstr ctx p1; - - (* prove f(x, y) = f(w, v) implies y = v *) - let p2 = Z3.mk_eq ctx y v in - printf "prove: f(x, y) = f(w, v) implies y = v\n"; - prove ctx p2 true; - - (* disprove f(x, y) = f(w, v) implies x = w *) - (* using check2 instead of prove *) - let p3 = Z3.mk_eq ctx x w in - let not_p3 = Z3.mk_not ctx p3 in - Z3.assert_cnstr ctx not_p3; - printf "disprove: f(x, y) = f(w, v) implies x = w\n"; - printf "that is: not(f(x, y) = f(w, v) implies x = w) is satisfiable\n"; - check2 ctx Z3.L_UNDEF; - Printf.printf - "reason for last failure: %d (7 = quantifiers)\n" - (if Z3.get_search_failure(ctx) = Z3.QUANTIFIERS then 7 else -1); - - - Z3.del_context ctx; - end;; - -(** - Prove {e store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)) }. - - This example demonstrates how to use the array theory. -*) -let array_example1() = - begin - printf "\narray_example1\n"; - - let ctx = mk_context [||] in - - let int_sort = Z3.mk_int_sort ctx in - let array_sort = Z3.mk_array_sort ctx int_sort int_sort in - - let a1 = mk_var ctx "a1" array_sort in - let a2 = mk_var ctx "a2" array_sort in - let i1 = mk_var ctx "i1" int_sort in - let i2 = mk_var ctx "i2" int_sort in - let i3 = mk_var ctx "i3" int_sort in - let v1 = mk_var ctx "v1" int_sort in - let v2 = mk_var ctx "v2" int_sort in - - let st1 = Z3.mk_store ctx a1 i1 v1 in - let st2 = Z3.mk_store ctx a2 i2 v2 in - - let sel1 = Z3.mk_select ctx a1 i3 in - let sel2 = Z3.mk_select ctx a2 i3 in - - (* create antecedent *) - let antecedent = Z3.mk_eq ctx st1 st2 in - - (* create consequent: i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3) *) - let ds = [| - Z3.mk_eq ctx i1 i3; - Z3.mk_eq ctx i2 i3; - Z3.mk_eq ctx sel1 sel2; - |] in - - let consequent = Z3.mk_or ctx ds in - - (* prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)) *) - let thm = Z3.mk_implies ctx antecedent consequent in - printf "prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3))\n"; - printf "%s\n" (Z3.ast_to_string ctx thm); - prove ctx thm true; - - Z3.del_context ctx; - end;; - -(** - Show that {e distinct(a_0, ... , a_n) } is - unsatisfiable when {e a_i's } are arrays from boolean to - boolean and n > 4. - - This example also shows how to use the {e distinct } construct. -*) -let array_example2() = - begin - printf "\narray_example2\n"; - - for n = 2 to 5 do - printf "n = %d\n" n; - let ctx = mk_context [||] in - - let bool_sort = Z3.mk_bool_sort ctx in - let array_sort = Z3.mk_array_sort ctx bool_sort bool_sort in - - (* create arrays *) - let a = Array.init n - (fun i->Z3.mk_const ctx (Z3.mk_int_symbol ctx i) array_sort) in - - (* assert distinct(a[0], ..., a[n]) *) - let d = Z3.mk_distinct ctx a in - printf "%s\n" (Z3.ast_to_string ctx d); - Z3.assert_cnstr ctx d; - - (* context is satisfiable if n < 5 *) - check2 ctx (if n < 5 then Z3.L_TRUE else Z3.L_FALSE); - - Z3.del_context ctx; - done - end;; - -(** - Simple array type construction/deconstruction example. -*) -let array_example3() = - begin - printf "\narray_example3\n"; - - let ctx = mk_context [||] in - - let bool_sort = Z3.mk_bool_sort ctx in - let int_sort = Z3.mk_int_sort ctx in - let array_sort = Z3.mk_array_sort ctx int_sort bool_sort in - - let (domain,range) = Z3.get_array_sort ctx array_sort in - printf "domain: "; - display_sort ctx stdout domain; - printf "\n"; - printf "range: "; - display_sort ctx stdout range; - printf "\n"; - - if (not (Z3.is_eq_sort ctx int_sort domain)) || - (not (Z3.is_eq_sort ctx bool_sort range)) then - exitf "invalid array type"; - Z3.del_context ctx; - end;; - -(** - Simple tuple type example. It creates a tuple that is a pair of real numbers. -*) -let tuple_example1() = - begin - printf "\ntuple_example1\n"; - let ctx = mk_context [||] in - - let real_sort = Z3.mk_real_sort ctx in - - (* Create pair (tuple) type *) - let mk_tuple_name = Z3.mk_string_symbol ctx "mk_pair" in - let proj_names_0 = Z3.mk_string_symbol ctx "get_x" in - let proj_names_1 = Z3.mk_string_symbol ctx "get_y" in - let proj_names = [|proj_names_0; proj_names_1|] in - let proj_sorts = [|real_sort;real_sort|] in - (* Z3_mk_tuple_sort will set mk_tuple_decl and proj_decls *) - let (pair_sort,mk_tuple_decl,proj_decls) = Z3.mk_tuple_sort ctx mk_tuple_name proj_names proj_sorts in - let get_x_decl = proj_decls.(0) in (* function that extracts the first element of a tuple. *) - let get_y_decl = proj_decls.(1) in (* function that extracts the second element of a tuple. *) - - printf "tuple_sort: "; - display_sort ctx stdout pair_sort; - printf "\n"; - - begin - (* prove that get_x(mk_pair(x,y)) == 1 implies x = 1*) - let x = mk_real_var ctx "x" in - let y = mk_real_var ctx "y" in - let app1 = mk_binary_app ctx mk_tuple_decl x y in - let app2 = mk_unary_app ctx get_x_decl app1 in - let one = Z3.mk_numeral ctx "1" real_sort in - let eq1 = Z3.mk_eq ctx app2 one in - let eq2 = Z3.mk_eq ctx x one in - let thm = Z3.mk_implies ctx eq1 eq2 in - printf "prove: get_x(mk_pair(x, y)) = 1 implies x = 1\n"; - prove ctx thm true; - - (* disprove that get_x(mk_pair(x,y)) == 1 implies y = 1*) - let eq3 = Z3.mk_eq ctx y one in - let thm = Z3.mk_implies ctx eq1 eq3 in - printf "disprove: get_x(mk_pair(x, y)) = 1 implies y = 1\n"; - prove ctx thm false; - end; - - begin - (* prove that get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2 *) - let p1 = mk_var ctx "p1" pair_sort in - let p2 = mk_var ctx "p2" pair_sort in - let x1 = mk_unary_app ctx get_x_decl p1 in - let y1 = mk_unary_app ctx get_y_decl p1 in - let x2 = mk_unary_app ctx get_x_decl p2 in - let y2 = mk_unary_app ctx get_y_decl p2 in - let antecedents_0 = Z3.mk_eq ctx x1 x2 in - let antecedents_1 = Z3.mk_eq ctx y1 y2 in - let antecedents = [|antecedents_0; antecedents_1|] in - let antecedent = Z3.mk_and ctx antecedents in - let consequent = Z3.mk_eq ctx p1 p2 in - let thm = Z3.mk_implies ctx antecedent consequent in - printf "prove: get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2\n"; - prove ctx thm true; - - (* disprove that get_x(p1) = get_x(p2) implies p1 = p2 *) - let thm = Z3.mk_implies ctx (antecedents.(0)) consequent in - printf "disprove: get_x(p1) = get_x(p2) implies p1 = p2\n"; - prove ctx thm false; - end; - - begin - (* demonstrate how to use the mk_tuple_update function *) - (* prove that p2 = update(p1, 0, 10) implies get_x(p2) = 10 *) - let p1 = mk_var ctx "p1" pair_sort in - let p2 = mk_var ctx "p2" pair_sort in - let one = Z3.mk_numeral ctx "1" real_sort in - let ten = Z3.mk_numeral ctx "10" real_sort in - let updt = mk_tuple_update ctx p1 0 ten in - let antecedent = Z3.mk_eq ctx p2 updt in - let x = mk_unary_app ctx get_x_decl p2 in - let consequent = Z3.mk_eq ctx x ten in - let thm = Z3.mk_implies ctx antecedent consequent in - printf "prove: p2 = update(p1, 0, 10) implies get_x(p2) = 10\n"; - prove ctx thm true; - - (* disprove that p2 = update(p1, 0, 10) implies get_y(p2) = 10 *) - let y = mk_unary_app ctx get_y_decl p2 in - let consequent = Z3.mk_eq ctx y ten in - let thm = Z3.mk_implies ctx antecedent consequent in - printf "disprove: p2 = update(p1, 0, 10) implies get_y(p2) = 10\n"; - prove ctx thm false; - end; - - Z3.del_context ctx; - end;; - -(** - Simple bit-vector example. This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers - *) -let bitvector_example1() = - begin - printf "\nbitvector_example1\n"; - - let ctx = mk_context [||] in - - let bv_sort = Z3.mk_bv_sort ctx 32 in - - let x = mk_var ctx "x" bv_sort in - let zero = Z3.mk_numeral ctx "0" bv_sort in - let ten = Z3.mk_numeral ctx "10" bv_sort in - let x_minus_ten = Z3.mk_bvsub ctx x ten in - (* bvsle is signed less than or equal to *) - let c1 = Z3.mk_bvsle ctx x ten in - let c2 = Z3.mk_bvsle ctx x_minus_ten zero in - let thm = Z3.mk_iff ctx c1 c2 in - printf "disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers\n"; - prove ctx thm false; - - Z3.del_context ctx; - end;; - -(** - Find x and y such that: x ^ y - 103 == x * y - *) -let bitvector_example2() = - begin - printf "\nbitvector_example2\n"; - let ctx = mk_context [||] in - (* construct x ^ y - 103 == x * y *) - let bv_sort = Z3.mk_bv_sort ctx 32 in - let x = mk_var ctx "x" bv_sort in - let y = mk_var ctx "y" bv_sort in - let x_xor_y = Z3.mk_bvxor ctx x y in - let c103 = Z3.mk_numeral ctx "103" bv_sort in - let lhs = Z3.mk_bvsub ctx x_xor_y c103 in - let rhs = Z3.mk_bvmul ctx x y in - let ctr = Z3.mk_eq ctx lhs rhs in - printf "find values of x and y, such that x ^ y - 103 == x * y\n"; - Z3.assert_cnstr ctx ctr; - check ctx Z3.L_TRUE; - Z3.del_context ctx; - end;; - -(** - Demonstrate how to use #Z3_eval. -*) -let eval_example1() = - begin - printf "\neval_example1\n"; - - let ctx = mk_context [||] in - let x = mk_int_var ctx "x" in - let y = mk_int_var ctx "y" in - let two = mk_int ctx 2 in - - (* assert x < y *) - let c1 = Z3.mk_lt ctx x y in - Z3.assert_cnstr ctx c1; - - (* assert x > 2 *) - let c2 = Z3.mk_gt ctx x two in - Z3.assert_cnstr ctx c2; - - (* find model for the constraints above *) - (match Z3.check_and_get_model ctx with - | (Z3.L_TRUE, m) -> - begin - let args = [|x; y|] in - printf "MODEL:\n%s" (Z3.model_to_string ctx m); - let x_plus_y = Z3.mk_add ctx args in - printf "\nevaluating x+y\n"; - (match Z3.eval ctx m x_plus_y with - | (true,v) -> - printf "result = "; - display_ast ctx stdout v; - printf "\n"; - | _ -> - exitf "failed to evaluate: x+y"; - ); - (Z3.del_model ctx m); - end; - | (_,_) -> - exitf "the constraints are satisfiable"; - ); - Z3.del_context ctx; - end;; - -(** - Several logical context can be used simultaneously. -*) -let two_contexts_example1() = - begin - printf "\ntwo_contexts_example1\n"; - (* using the same (default) configuration to initialized both logical contexts. *) - let ctx1 = mk_context [||] in - let ctx2 = mk_context [||] in - let x1 = Z3.mk_const ctx1 (Z3.mk_int_symbol ctx1 0) (Z3.mk_bool_sort ctx1) in - let x2 = Z3.mk_const ctx2 (Z3.mk_int_symbol ctx2 0) (Z3.mk_bool_sort ctx2) in - Z3.del_context ctx1; - (* ctx2 can still be used. *) - printf "%s\n" (Z3.ast_to_string ctx2 x2); - Z3.del_context ctx2; - end;; - -(** - Demonstrates how error codes can be read insted of registering an error handler. - *) -let error_code_example1() = - begin - printf "\nerror_code_example1\n"; - - let ctx = mk_context [||] in - let x = mk_bool_var ctx "x" in - let x_decl = Z3.get_app_decl ctx (Z3.to_app ctx x) in - Z3.assert_cnstr ctx x; - - match Z3.check_and_get_model ctx with - | (Z3.L_TRUE,m) -> - begin - let (ok, v) = Z3.eval_func_decl ctx m x_decl in - printf "last call succeeded.\n"; - - (* The following call will fail since the value of x is a boolean *) - (try ignore(Z3.get_numeral_string ctx v) - with | _ -> printf "last call failed.\n"); - (Z3.del_model ctx m); - Z3.del_context ctx; - end - | (_,_) -> exitf "unexpected result"; - end;; - -(** - Demonstrates how Z3 exceptions can be used. -*) -let error_code_example2() = - begin - printf "\nerror_code_example2\n%!"; - - let ctx = mk_context [||] in - try - let x = mk_int_var ctx "x" in - let y = mk_bool_var ctx "y" in - printf "before Z3_mk_iff\n"; - let app = Z3.mk_iff ctx x y in - printf "unreachable"; - with | _ -> printf "Z3 error: type error.\n"; - Z3.del_context ctx; - end;; - -(** - Demonstrates how to use the SMTLIB parser. - *) -let parser_example1() = - begin - printf "\nparser_example1\n"; - - let ctx = mk_context [||] in - let str = "(benchmark tst :extrafuns ((x Int) (y Int)) :formula (> x y) :formula (> x 0))" in - let (formulas,_,_) = Z3.parse_smtlib_string_x ctx str [||] [||] [||] [||] in - let f i c = - printf "formula %d: %s\n" i (Z3.ast_to_string ctx c); - Z3.assert_cnstr ctx c; - in Array.iteri f formulas; - check ctx Z3.L_TRUE; - Z3.del_context ctx; - end;; - -(** - Demonstrates how to initialize the parser symbol table. - *) -let parser_example2() = - begin - printf "\nparser_example2\n%!"; - - let ctx = mk_context [||] in - let x = mk_int_var ctx "x" in - let x_decl = Z3.get_app_decl ctx (Z3.to_app ctx x) in - let y = mk_int_var ctx "y" in - let y_decl = Z3.get_app_decl ctx (Z3.to_app ctx y) in - let decls = [| x_decl; y_decl |] in - let a = Z3.mk_string_symbol ctx "a" in - let b = Z3.mk_string_symbol ctx "b" in - let names = [| a; b |] in - let str = "(benchmark tst :formula (> a b))" in - let f = Z3.parse_smtlib_string_formula ctx str [||] [||] names decls in - printf "formula: %s\n" (Z3.ast_to_string ctx f); - Z3.assert_cnstr ctx f; - check ctx Z3.L_TRUE; - Z3.del_context ctx; - end;; - -(** - Demonstrates how to initialize the parser symbol table. - *) -let parser_example3() = - begin - printf "\nparser_example3\n%!"; - - let ctx = mk_context [| |] in - let int_sort = Z3.mk_int_sort ctx in - let g_name = Z3.mk_string_symbol ctx "g" in - let g = Z3.mk_func_decl ctx g_name [| int_sort; int_sort |] int_sort in - let str = "(benchmark tst :formula (forall (x Int) (y Int) (implies (= x y) (= (g x 0) (g 0 y)))))" in - assert_comm_axiom ctx g; - let thm = Z3.parse_smtlib_string_formula ctx str [||] [||] [|g_name|] [|g|] in - printf "formula: %s\n" (Z3.ast_to_string ctx thm); - prove ctx thm true; - Z3.del_context ctx; - end;; - -(** - Display the declarations, assumptions and formulas in a SMT-LIB string. - *) -let parser_example4() = - begin - printf "\nparser_example4\n%!"; - - let ctx = mk_context [||] in - let str = "(benchmark tst :extrafuns ((x Int) (y Int)) :assumption (= x 20) :formula (> x y) :formula (> x 0))" in - (* arithmetic theory is automatically initialized, when an - int/real variable or arith operation is created using the API. - Since no such function is invoked in this example, we should do - that manually. - *) - let (formulas, assumptions, decls) = Z3.parse_smtlib_string_x ctx str [||] [||] [||] [||] in - let f prefix i n = printf "%s %d: %s\n" prefix i (Z3.ast_to_string ctx n) in - Array.iteri (fun i n -> printf "declaration %d: %s\n" i (Z3.func_decl_to_string ctx n)) decls; - Array.iteri (f "assumption") assumptions; - Array.iteri (f "formula") formulas; - Z3.del_context ctx; - end;; - -(** - Demonstrates how to handle parser errors using Z3 exceptions. - *) -let parser_example5() = - begin - printf "\nparser_example5\n"; - let ctx = mk_context [||] in - try - (* the following string has a parsing error: missing parenthesis *) - let str = "(benchmark tst :extrafuns ((x Int (y Int)) :formula (> x y) :formula (> x 0))" in - ignore(Z3.parse_smtlib_string_x ctx str [||] [||] [||] [||]); - with | _ -> (printf "Z3 error: parser error.\n"; - printf "Error message: '%s'.\n" (Z3.get_smtlib_error ctx) - ); - Z3.del_context ctx; - end;; - -(** - Example for creating an if-then-else expression. - *) -let ite_example() = - begin - printf "\nite_example\n%!"; - let ctx = mk_context [||] in - let f = Z3.mk_false ctx in - let one = mk_int ctx 1 in - let zero = mk_int ctx 0 in - let ite = Z3.mk_ite ctx f one zero in - printf "term: %s\n" (Z3.ast_to_string ctx ite); - Z3.del_context ctx; - end;; - - -(** - Create an enumeration data type. - - Several more examples of creating and using data-types (lists, trees, records) - are provided for the C-based API. - The translation from the examples in C to use the OCaml API follow the same pattern - that is used here. -*) -let enum_example() = - begin - printf "\nenum_example\n"; - let ctx = mk_context [||] in - let name = Z3.mk_string_symbol ctx "fruit" in - let enum_names = [| Z3.mk_string_symbol ctx "apple"; - Z3.mk_string_symbol ctx "banana"; - Z3.mk_string_symbol ctx "orange" |] in - let (fruit, enum_consts, enum_testers) = Z3.mk_enumeration_sort ctx name enum_names in - - printf "%s\n" (Z3.func_decl_to_string ctx enum_consts.(0)); - printf "%s\n" (Z3.func_decl_to_string ctx enum_consts.(1)); - printf "%s\n" (Z3.func_decl_to_string ctx enum_consts.(2)); - printf "%s\n" (Z3.func_decl_to_string ctx enum_testers.(0)); - printf "%s\n" (Z3.func_decl_to_string ctx enum_testers.(1)); - printf "%s\n" (Z3.func_decl_to_string ctx enum_testers.(2)); - - let apple = Z3.mk_app ctx (enum_consts.(0)) [||] in - let banana = Z3.mk_app ctx (enum_consts.(1)) [||] in - let orange = Z3.mk_app ctx (enum_consts.(2)) [||] in - - (* Apples are different from oranges *) - prove ctx (Z3.mk_not ctx (Z3.mk_eq ctx apple orange)) true; - - (* Apples pass the apple test *) - prove ctx (Z3.mk_app ctx enum_testers.(0) [| apple |]) true; - - (* Oranges fail the apple test *) - prove ctx (Z3.mk_app ctx enum_testers.(0) [| orange |]) false; - prove ctx (Z3.mk_not ctx (Z3.mk_app ctx enum_testers.(0) [| orange |])) true; - - let fruity = mk_var ctx "fruity" fruit in - - (* If something is fruity, then it is an apple, banana, or orange *) - let ors = [| Z3.mk_eq ctx fruity apple; - Z3.mk_eq ctx fruity banana; - Z3.mk_eq ctx fruity orange |] in - - prove ctx (Z3.mk_or ctx ors) true; - Z3.del_context ctx; - end;; - -(** - Example for extracting unsatisfiable core and proof. - The example uses the function check_assumptions which allows passing in additional - hypotheses. The unsatisfiable core is a subset of these additional hypotheses. - *) -let unsat_core_and_proof_example() = - begin - printf "\nunsat_core_and_proof_example\n%!"; - let ctx = mk_context [| ("PROOF_MODE","2") |] in - let pa = mk_bool_var ctx "PredA" in - let pb = mk_bool_var ctx "PredB" in - let pc = mk_bool_var ctx "PredC" in - let pd = mk_bool_var ctx "PredD" in - let p1 = mk_bool_var ctx "P1" in - let p2 = mk_bool_var ctx "P2" in - let p3 = mk_bool_var ctx "P3" in - let p4 = mk_bool_var ctx "P4" in - let assumptions = [| Z3.mk_not ctx p1; Z3.mk_not ctx p2; Z3.mk_not ctx p3; Z3.mk_not ctx p4 |] in - let f1 = Z3.mk_and ctx [| pa; pb; pc |] in - let f2 = Z3.mk_and ctx [| pa; Z3.mk_not ctx pc; pb |] in - let f3 = Z3.mk_or ctx [| Z3.mk_not ctx pa; Z3.mk_not ctx pc |] in - let f4 = pd in - let core_dummy = [| pa; pa; pa; pa |] in - Z3.assert_cnstr ctx (Z3.mk_or ctx [| f1; p1 |]); - Z3.assert_cnstr ctx (Z3.mk_or ctx [| f2; p2 |]); - Z3.assert_cnstr ctx (Z3.mk_or ctx [| f3; p3 |]); - Z3.assert_cnstr ctx (Z3.mk_or ctx [| f4; p4 |]); - let result = Z3.check_assumptions ctx assumptions 4 core_dummy in - (match result with - | (Z3.L_FALSE, _, proof, core_size, core) -> - printf "unsat\n"; - printf "proof: %s\n" (Z3.ast_to_string ctx proof); - printf("\ncore:\n"); - for i = 0 to core_size - 1 do - printf "%s\n" (Z3.ast_to_string ctx (core.(i))); - done; - printf("\n") - | (_,_,_,_,_)-> assert false; - ); - (* delete logical context *) - Z3.del_context(ctx); - end - -(** - -*) - -let get_implied_equalities_example() = - begin - printf "\nget_implied_equalities example\n%!"; - let ctx = mk_context [| |] in - let int_ty = Z3.mk_int_sort ctx in - let a = mk_int_var ctx "a" in - let b = mk_int_var ctx "b" in - let c = mk_int_var ctx "c" in - let d = mk_int_var ctx "d" in - let f = Z3.mk_func_decl ctx (Z3.mk_string_symbol ctx "f") [| int_ty |] int_ty in - let fa = Z3.mk_app ctx f [| a |] in - let fb = Z3.mk_app ctx f [| b |] in - let fc = Z3.mk_app ctx f [| c |] in - let terms = [| a; b; c; d; fa; fb; fc |] in - Z3.assert_cnstr ctx (Z3.mk_eq ctx a b); - Z3.assert_cnstr ctx (Z3.mk_eq ctx b c); - Z3.assert_cnstr ctx (Z3.mk_le ctx fc b); - Z3.assert_cnstr ctx (Z3.mk_le ctx b fa); - let is_sat, class_ids = Z3.get_implied_equalities ctx terms in - for i = 0 to 6 do - printf "Class %s |-> %d\n" (Z3.ast_to_string ctx (terms.(i))) (class_ids.(i)); - done; - printf "asserting f(a) <= b\n"; - Z3.assert_cnstr ctx (Z3.mk_le ctx fa b); - let is_sat, class_ids = Z3.get_implied_equalities ctx terms in - for i = 0 to 6 do - printf "Class %s |-> %d\n" (Z3.ast_to_string ctx (terms.(i))) (class_ids.(i)); - done; - (* delete logical context *) - Z3.del_context(ctx) - end;; - -let main() = - begin - ignore (Z3.open_log("ml.log")); - display_version(); - simple_example(); - demorgan(); - find_model_example1(); - find_model_example2(); - prove_example1(); - prove_example2(); - push_pop_example1(); - quantifier_example1(); - array_example1(); - array_example2(); - array_example3(); - tuple_example1(); - bitvector_example1(); - bitvector_example2(); - eval_example1(); - two_contexts_example1(); - error_code_example1(); - error_code_example2(); - parser_example1(); - parser_example2(); - parser_example3(); - parser_example4(); - parser_example5(); -(* numeral_example(); *) - ite_example(); -(* list_example(); *) -(* tree_example(); *) -(* forest_example(); *) -(* binary_tree_example(); *) - enum_example(); - unsat_core_and_proof_example(); - abstract_example(); - get_implied_equalities_example(); -(* incremental_example1(); *) -(* reference_counter_example(); *) -(* smt2parser_example(); *) -(* substitute_example(); *) -(* substitute_vars_example(); *) - end;; - -let _ = main();; diff --git a/src/api/ml/old/test_theory.ml b/src/api/ml/old/test_theory.ml deleted file mode 100644 index 8732bf220..000000000 --- a/src/api/ml/old/test_theory.ml +++ /dev/null @@ -1,42 +0,0 @@ -module Z3 = Z3.V3 - -let print_lbool lb = - match lb with - | Z3.L_FALSE -> Printf.printf "false\n" - | Z3.L_TRUE -> Printf.printf "true\n" - | Z3.L_UNDEF -> Printf.printf "undef\n" - -(* simple sanity test of theory plugin *) -let test_theory() = - let ctx = Z3.mk_context_x [| |] in - let th = Z3.mk_theory ctx "test-theory" in - let _ = Z3.set_push_callback th (fun () -> Printf.printf "push\n") in - let _ = Z3.set_pop_callback th (fun () -> Printf.printf "pop\n") in - let _ = Z3.set_delete_callback th (fun () -> Printf.printf "delete\n") in - let _ = Z3.set_final_check_callback th (fun () -> (Printf.printf "final\n"; true)) in - let _ = Z3.set_delete_callback th (fun () -> Printf.printf "deleted\n") in - let f_sym = Z3.mk_string_symbol ctx "f" in - let a_sym = Z3.mk_string_symbol ctx "a" in - let b_sym = Z3.mk_string_symbol ctx "b" in - let int_sort = Z3.mk_int_sort ctx in - let f = Z3.theory_mk_func_decl ctx th f_sym [|int_sort |] int_sort in - let a = Z3.theory_mk_constant ctx th a_sym int_sort in - let b = Z3.theory_mk_constant ctx th b_sym int_sort in - let reduce_f g args = - Printf.printf "reduce %s\n" (Z3.func_decl_to_string ctx g); - match g, args with - | _, [| a' |] when Z3.is_eq_func_decl ctx g f && Z3.is_eq_ast ctx a' a -> Some b - | _, _ -> None - in - let _ = Z3.set_reduce_app_callback th reduce_f in - (* b != f(b) is consistent *) - let _ = Z3.assert_cnstr ctx (Z3.mk_not ctx (Z3.mk_eq ctx b (Z3.mk_app ctx f [| b |]))) in - let res = Z3.check ctx in - print_lbool res; - (* b != f(a) is not consistent *) - let _ = Z3.assert_cnstr ctx (Z3.mk_not ctx (Z3.mk_eq ctx b (Z3.mk_app ctx f [| a |]))) in - let res = Z3.check ctx in - print_lbool res; - Z3.del_context ctx - -let _ = test_theory() diff --git a/src/api/ml/old/update-ml-doc.cmd b/src/api/ml/old/update-ml-doc.cmd deleted file mode 100755 index 32c39109e..000000000 --- a/src/api/ml/old/update-ml-doc.cmd +++ /dev/null @@ -1,38 +0,0 @@ -@echo off -SETLOCAL - -REM Script to generate Z3 OCaml API documentation -REM -REM Assumes that environment variables are set to provide access to the OCaml compilers, as well as the following commands: sed - -rd 2>NUL /s /q doc -md doc -cd doc -set MLDIR=.. -set DOCDIR=..\%1 - -ocamldoc.opt -hide Z3,Z3.V3,Test_mlapi -html -css-style z3_ml.css -I %MLDIR% %MLDIR%\test_mlapi.ml %MLDIR%\z3.mli - -sed "s|
val\(.*\)
|
val\1
|g;s|
type\(.*\)
|
type\1
|g;s|type\(.*\) = |
type\1 =
|g" Z3.html > Z3.new.html -move >NUL Z3.new.html Z3.html - -sed "s|
val\(.*\)
|
val\1
|g" Test_mlapi.html > Test_mlapi.new.html -move >NUL Test_mlapi.new.html Test_mlapi.html - -sed "s|

Index of values

|

OCaml: Index

|" Index_values.html > Index_values.new.html -move >NUL Index_values.new.html Index_values.html - -copy >NUL %DOCDIR%\tabs.css -copy >NUL %DOCDIR%\z3.png -copy >NUL %DOCDIR%\z3_ml.css - -sed "1,23d" Test_mlapi.html | sed "$d" > Test_mlapi.new.html - -type 2>NUL %DOCDIR%\test_mlapi_header.html Test_mlapi.new.html %DOCDIR%\mldoc_footer.html >Test_mlapi.html - -sed "1,37d" Z3.html > Z3.new.html - -type 2>NUL %DOCDIR%\z3_mlapi_header.html Z3.new.html >Z3.html - -exit /B 0 -ENDLOCAL diff --git a/src/api/ml/old/x3.ml b/src/api/ml/old/x3.ml deleted file mode 100644 index 6ca5d49eb..000000000 --- a/src/api/ml/old/x3.ml +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright (c) Microsoft Corporation */ - -quote (ml," - -(* Internal auxiliary functions: *) -(* -(* Transform a pair of arrays into an array of pairs *) -let array_combine a b = - if Array.length a <> Array.length b then raise (Invalid_argument \"array_combine\"); - Array.init (Array.length a) (fun i -> (a.(i), b.(i))) - -(* [a |> b] is the pipeline operator for [b(a)] *) -let ( |> ) x f = f x -*) - -(* Find the index of an element in an array, raises Not_found is missing *) -let find equal x a = - let len = Array.length a in - let rec find_ i = - if i >= len then - raise Not_found - else - if equal x a.(i) then - i - else - find_ (i+1) - in - find_ 0 - - -(* Symbols *) - -let symbol_refine c s = - match get_symbol_kind c s with - | INT_SYMBOL -> Symbol_int (get_symbol_int c s) - | STRING_SYMBOL -> Symbol_string (get_symbol_string c s) - -let mk_symbol c = function - | Symbol_int(i) -> mk_int_symbol c i - | Symbol_string(s) -> mk_string_symbol c s - - -(* Sorts *) - -let get_datatype_sort c s = - Array.init (get_datatype_sort_num_constructors c s) (fun i -> - let constructor = get_datatype_sort_constructor c s i in - let recognizer = get_datatype_sort_recognizer c s i in - let accessors = - Array.init (get_domain_size c constructor) (fun j -> - get_datatype_sort_constructor_accessor c s i j - ) in - {constructor; recognizer; accessors} - ) - -let sort_refine c s = - match get_sort_kind c s with - | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c s) - | BOOL_SORT -> Sort_bool - | INT_SORT -> Sort_int - | BV_SORT -> Sort_bv (get_bv_sort_size c s) - | FINITE_DOMAIN_SORT -> - (match get_finite_domain_sort_size c s with - | Some(sz) -> Sort_finite_domain (get_sort_name c s, sz) - | None -> failwith \"Z3.sort_refine: failed to get size of finite-domain sort\" - ) - | REAL_SORT -> Sort_real - | ARRAY_SORT -> Sort_array (get_array_sort_domain c s, get_array_sort_range c s) - | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c s) - | RELATION_SORT -> Sort_relation (Array.init (get_relation_arity c s) (fun i -> get_relation_column c s i)) - | UNKNOWN_SORT -> Sort_unknown - -let mk_sort c = function - | Sort_uninterpreted(s) -> mk_uninterpreted_sort c s - | Sort_bool -> mk_bool_sort c - | Sort_int -> mk_int_sort c - | Sort_bv(size) -> mk_bv_sort c size - | Sort_finite_domain(name,size) -> mk_finite_domain_sort c name size - | Sort_real -> mk_real_sort c - | Sort_array(domain,range) -> mk_array_sort c domain range - | Sort_datatype(constructors) -> get_range c constructors.(0).constructor - | Sort_relation(_) -> invalid_arg \"Z3.mk_sort: cannot construct relation sorts\" - | Sort_unknown(_) -> invalid_arg \"Z3.mk_sort: cannot construct unknown sorts\" - - -(* Replacement datatypes creation API *) - -let mk_datatypes ctx generator = - let usort0 = mk_uninterpreted_sort ctx (mk_int_symbol ctx 0) - in - let rec find_num_sorts i = - if i = max_int then invalid_arg \"mk_datatypes: too many sorts\" - else - match generator (Array.make i usort0) with - | None -> find_num_sorts (i+1) - | Some(a) when Array.length a = i -> i - | Some _ -> invalid_arg \"mk_datatypes: number of sorts and datatype descriptors must be equal\" - in - let num_sorts = find_num_sorts 0 - in - let sorts0 = Array.init num_sorts (fun i -> mk_uninterpreted_sort ctx (mk_int_symbol ctx i)) - in - let ctorss_descriptors = - match generator sorts0 with - | Some(ctorss_descriptors) -> ctorss_descriptors - | None -> invalid_arg \"mk_datatypes: generator failed\" - in - let names = Array.map fst ctorss_descriptors - in - let ctorss = - Array.map (fun (_, ctors_descriptor) -> - Array.map (fun {constructor_desc; recognizer_desc; accessor_descs} -> - let field_names = Array.map fst accessor_descs - in - let sort_refs = Array.make (Array.length accessor_descs) 0 - in - let field_sorts = - Array.mapi (fun i (_, sort) -> - try - let j = find (fun s t -> is_eq_sort ctx s t) sort sorts0 in - sort_refs.(i) <- j ; - None - with Not_found -> - Some(sort) - ) accessor_descs - in - mk_constructor ctx constructor_desc recognizer_desc field_names field_sorts sort_refs - ) ctors_descriptor - ) ctorss_descriptors - in - let constructor_lists = Array.map (mk_constructor_list ctx) ctorss - in - let sorts,_ = mk_datatypes ctx names constructor_lists - in - let datatypes = - Array.mapi (fun i sort -> - (sort, - Array.mapi (fun j ctor -> - let num_fields = Array.length (snd ctorss_descriptors.(i)).(j).accessor_descs in - let constructor, recognizer, accessors = query_constructor ctx ctor num_fields in - {constructor; recognizer; accessors} - ) ctorss.(i)) - ) sorts - in - Array.iter (fun ctor_list -> - del_constructor_list ctx ctor_list - ) constructor_lists - ; - Array.iter (fun ctors -> - Array.iter (fun ctor -> - del_constructor ctx ctor - ) ctors - ) ctorss - ; - datatypes - - -(* Numerals *) - -let rec numeral_refine c t = - assert( get_ast_kind c t = NUMERAL_AST ); - let sort = get_sort c t in - let is_int, i = get_numeral_int c t in - if is_int then - Numeral_int (i, sort) - else - let is_int64, i = get_numeral_int64 c t in - if is_int64 then - Numeral_int64 (i, sort) - else - if get_sort_kind c sort <> REAL_SORT then - Numeral_large (get_numeral_string c t, sort) - else - let n = numeral_refine c (get_numerator c t) in - let d = numeral_refine c (get_denominator c t) in - Numeral_rational (n, d) - - -let to_real c x = - if get_sort_kind c (get_sort c x) = REAL_SORT then - x - else - mk_int2real c x - -let rec embed_numeral c = function - | Numeral_int (i, s) -> mk_int c i s - | Numeral_int64 (i, s) -> mk_int64 c i s - | Numeral_large (l, s) -> mk_numeral c l s - | Numeral_rational (Numeral_int(n,_), Numeral_int(d,_)) -> mk_real c n d - | Numeral_rational (n, d) -> - mk_div c (to_real c (embed_numeral c n)) (to_real c (embed_numeral c d)) - (* Or should the following be used instead? - let n_str = get_numeral_string c (embed_numeral c n) in - let d_str = get_numeral_string c (embed_numeral c d) in - mk_numeral c (n_str ^ \" / \" ^ d_str) (mk_real_sort c) - *) - -(* Terms *) - -let get_app_args c a = - Array.init (get_app_num_args c a) (get_app_arg c a);; - -let get_domains c d = - Array.init (get_domain_size c d) (get_domain c d);; - - -let get_pattern_terms c p = - Array.init (get_pattern_num_terms c p) (get_pattern c p) - - -let term_refine c t = - match get_ast_kind c t with - | NUMERAL_AST -> - Term_numeral (numeral_refine c t) - | APP_AST -> - let t' = to_app c t in - let f = get_app_decl c t' in - let num_args = get_app_num_args c t' in - let args = Array.init num_args (get_app_arg c t') in - let k = get_decl_kind c f in - Term_app (k, f, args) - | QUANTIFIER_AST -> - let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in - let bound = - Array.init nb (fun i -> - (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i) - ) in - let body = get_quantifier_body c t in - Term_quantifier (bt, w, pats, bound, body) - | VAR_AST -> - Term_var (get_index_value c t, get_sort c t) - | _ -> - assert false - - -(* let mk_term c = function *) -(* | Term_numeral (numeral, sort) -> mk_numeral c numeral sort *) -(* | Term_app (kind, decl, args) -> *) -(* | Term_quantifier (strength, weight, pats, bound, body) -> *) -(* | Term_var (index, sort) -> *) - - - -(* Refined model API *) - -let model_refine c m = - let num_sorts = model_get_num_sorts c m in - let sorts = Hashtbl.create num_sorts in - for i = 0 to num_sorts - 1 do - let sort = model_get_sort c m i in - let universe = model_get_sort_universe c m sort in - Hashtbl.add sorts sort universe - done; - let num_consts = model_get_num_consts c m in - let consts = Hashtbl.create num_consts in - let arrays = Hashtbl.create 0 in - for i = 0 to num_consts - 1 do - let const_decl = model_get_const_decl c m i in - match model_get_const_interp c m const_decl with - | Some(const_interp) -> - if is_as_array c const_interp then - let array_decl = get_as_array_func_decl c const_interp in - match model_get_func_interp c m array_decl with - | Some(array_interp) -> - let num_entries = func_interp_get_num_entries c array_interp in - let tbl = Hashtbl.create num_entries in - for i = 0 to num_entries - 1 do - let entry = func_interp_get_entry c array_interp i in - assert( func_entry_get_num_args c entry = 1 ); - let arg = func_entry_get_arg c entry 0 in - let value = func_entry_get_value c entry in - Hashtbl.add tbl arg value - done; - let default = func_interp_get_else c array_interp in - Hashtbl.add arrays const_decl (tbl, default) - | None -> - () - else - Hashtbl.add consts const_decl const_interp - | None -> - () - done; - let num_funcs = model_get_num_funcs c m in - let funcs = Hashtbl.create num_funcs in - for i = 0 to num_funcs - 1 do - let func_decl = model_get_func_decl c m i in - if not (Hashtbl.mem arrays func_decl) then - match model_get_func_interp c m func_decl with - | Some(func_interp) -> - let num_entries = func_interp_get_num_entries c func_interp in - let tbl = Hashtbl.create num_entries in - for i = 0 to num_entries - 1 do - let entry = func_interp_get_entry c func_interp i in - let num_args = func_entry_get_num_args c entry in - let args = Array.init num_args (fun i -> func_entry_get_arg c entry i) in - let value = func_entry_get_value c entry in - Hashtbl.add tbl args value - done; - let default = func_interp_get_else c func_interp in - Hashtbl.add funcs func_decl (tbl, default) - | None -> - () - done; - {sorts; consts; arrays; funcs} - - -(* Extended parser API *) - -let get_smtlib_formulas c = - Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c) - -let get_smtlib_assumptions c = - Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c) - -let get_smtlib_decls c = - Array.init (get_smtlib_num_decls c) (get_smtlib_decl c) - -let get_smtlib_parse_results c = - (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c) - -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = - parse_smtlib_string c a1 a2 a3 a4 a5 ; - get_smtlib_parse_results c - -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = - parse_smtlib_file c a1 a2 a3 a4 a5 ; - get_smtlib_parse_results c - -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = - parse_smtlib_string c a1 a2 a3 a4 a5 ; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith \"Z3: parse_smtlib_string_formula\" - -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = - parse_smtlib_file c a1 a2 a3 a4 a5 ; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith \"Z3: parse_smtlib_file_formula\" - - -(* Error handling *) - -let get_error_msg c e = - match e with - | PARSER_ERROR -> (get_error_msg_ex c e) ^ \": \" ^ (get_smtlib_error c) - | _ -> get_error_msg_ex c e - - -(* Refined stats API *) - -let stats_refine c s = - let num_stats = stats_size c s in - let tbl = Hashtbl.create num_stats in - for i = 0 to num_stats - 1 do - let key = stats_get_key c s i in - let datum = - if stats_is_uint c s i then - Stat_int(stats_get_uint_value c s i) - else - Stat_float(stats_get_double_value c s i) in - Hashtbl.add tbl key datum - done; - tbl -"); diff --git a/src/api/ml/old/x3V3.ml b/src/api/ml/old/x3V3.ml deleted file mode 100644 index 96156f0a8..000000000 --- a/src/api/ml/old/x3V3.ml +++ /dev/null @@ -1,378 +0,0 @@ -quote (ml," - - -(* Internal auxillary functions: *) - -(* Transform a pair of arrays into an array of pairs *) -let array_combine a b = - if Array.length a <> Array.length b then raise (Invalid_argument \"array_combine\"); - Array.init (Array.length a) (fun i->(a.(i),b.(i)));; - -(* [a |> b] is the pipeline operator for [b(a)] *) -let ( |> ) x f = f x;; - - -(* Extensions, except for refinement: *) -let mk_context_x configs = - let config = mk_config() in - let f(param_id,param_value) = set_param_value config param_id param_value in - Array.iter f configs; - let context = mk_context config in - del_config config; - context;; - -let get_app_args c a = - Array.init (get_app_num_args c a) (get_app_arg c a);; - -let get_domains c d = - Array.init (get_domain_size c d) (get_domain c d);; - -let get_array_sort c t = (get_array_sort_domain c t, get_array_sort_range c t);; - -let get_tuple_sort c ty = - (get_tuple_sort_mk_decl c ty, - Array.init (get_tuple_sort_num_fields c ty) (get_tuple_sort_field_decl c ty));; - -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array -} - -let get_datatype_sort c ty = - Array.init (get_datatype_sort_num_constructors c ty) - (fun idx_c -> - let constr = get_datatype_sort_constructor c ty idx_c in - let recog = get_datatype_sort_recognizer c ty idx_c in - let num_acc = get_domain_size c constr in - { constructor = constr; - recognizer = recog; - accessors = Array.init num_acc (get_datatype_sort_constructor_accessor c ty idx_c); - }) - -let get_model_constants c m = - Array.init (get_model_num_constants c m) (get_model_constant c m);; - - -let get_model_func_entry c m i j = - (Array.init - (get_model_func_entry_num_args c m i j) - (get_model_func_entry_arg c m i j), - get_model_func_entry_value c m i j);; - -let get_model_func_entries c m i = - Array.init (get_model_func_num_entries c m i) (get_model_func_entry c m i);; - -let get_model_funcs c m = - Array.init (get_model_num_funcs c m) - (fun i->(get_model_func_decl c m i |> get_decl_name c, - get_model_func_entries c m i, - get_model_func_else c m i));; - -let get_smtlib_formulas c = - Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c);; - -let get_smtlib_assumptions c = - Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c);; - -let get_smtlib_decls c = - Array.init (get_smtlib_num_decls c) (get_smtlib_decl c);; - -let get_smtlib_parse_results c = - (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c);; - -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = - (parse_smtlib_string c a1 a2 a3 a4 a5; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith \"Z3: parse_smtlib_string_formula\");; - -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = - (parse_smtlib_file c a1 a2 a3 a4 a5; - match get_smtlib_formulas c with [|f|] -> f | _ -> failwith \"Z3: parse_smtlib_file_formula\");; - -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = - (parse_smtlib_string c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; - -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = - (parse_smtlib_file c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; - -(* Refinement: *) - -type symbol_refined = - | Symbol_int of int - | Symbol_string of string - | Symbol_unknown;; - -let symbol_refine c s = - match get_symbol_kind c s with - | INT_SYMBOL -> Symbol_int (get_symbol_int c s) - | STRING_SYMBOL -> Symbol_string (get_symbol_string c s);; - -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_real - | Sort_bv of int - | Sort_array of (sort * sort) - | Sort_datatype of datatype_constructor_refined array - | Sort_relation - | Sort_finite_domain - | Sort_unknown of symbol;; - -let sort_refine c ty = - match get_sort_kind c ty with - | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c ty) - | BOOL_SORT -> Sort_bool - | INT_SORT -> Sort_int - | REAL_SORT -> Sort_real - | BV_SORT -> Sort_bv (get_bv_sort_size c ty) - | ARRAY_SORT -> Sort_array (get_array_sort_domain c ty, get_array_sort_range c ty) - | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c ty) - | RELATION_SORT -> Sort_relation - | FINITE_DOMAIN_SORT -> Sort_finite_domain - | UNKNOWN_SORT -> Sort_unknown (get_sort_name c ty);; - -let get_pattern_terms c p = - Array.init (get_pattern_num_terms c p) (get_pattern c p) - -type binder_type = | Forall | Exists - -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string - -type term_refined = - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol *sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort - -let term_refine c t = - match get_ast_kind c t with - | NUMERAL_AST -> - let (is_small, n, d) = get_numeral_small c t in - if is_small then - Term_numeral(Numeral_small(n,d), get_sort c t) - else - Term_numeral(Numeral_large(get_numeral_string c t), get_sort c t) - | APP_AST -> - let t' = to_app c t in - let f = get_app_decl c t' in - let num_args = get_app_num_args c t' in - let args = Array.init num_args (get_app_arg c t') in - let k = get_decl_kind c f in - Term_app (k, f, args) - | QUANTIFIER_AST -> - let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in - let bound = Array.init nb - (fun i -> (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i)) in - let body = get_quantifier_body c t in - Term_quantifier(bt, w, pats, bound, body) - | VAR_AST -> - Term_var(get_index_value c t, get_sort c t) - | _ -> assert false - -type theory_callbacks = - { - mutable delete_theory : unit -> unit; - mutable reduce_eq : ast -> ast -> ast option; - mutable reduce_app : func_decl -> ast array -> ast option; - mutable reduce_distinct : ast array -> ast option; - mutable final_check : unit -> bool; - mutable new_app : ast -> unit; - mutable new_elem : ast -> unit; - mutable init_search: unit -> unit; - mutable push: unit -> unit; - mutable pop: unit -> unit; - mutable restart : unit -> unit; - mutable reset: unit -> unit; - mutable new_eq : ast -> ast -> unit; - mutable new_diseq : ast -> ast -> unit; - mutable new_assignment: ast -> bool -> unit; - mutable new_relevant : ast -> unit; - } - -let mk_theory_callbacks() = - { - delete_theory = (fun () -> ()); - reduce_eq = (fun _ _ -> None); - reduce_app = (fun _ _ -> None); - reduce_distinct = (fun _ -> None); - final_check = (fun _ -> true); - new_app = (fun _ -> ()); - new_elem = (fun _ -> ()); - init_search= (fun () -> ()); - push= (fun () -> ()); - pop= (fun () -> ()); - restart = (fun () -> ()); - reset= (fun () -> ()); - new_eq = (fun _ _ -> ()); - new_diseq = (fun _ _ -> ()); - new_assignment = (fun _ _ -> ()); - new_relevant = (fun _ -> ()); - } - - -external get_theory_callbacks : theory -> theory_callbacks = \"get_theory_callbacks\" -external mk_theory_register : context -> string -> theory_callbacks -> theory = \"mk_theory_register\" -external set_delete_callback_register : theory -> unit = \"set_delete_callback_register\" -external set_reduce_app_callback_register : theory -> unit = \"set_reduce_app_callback_register\" -external set_reduce_eq_callback_register : theory -> unit = \"set_reduce_eq_callback_register\" -external set_reduce_distinct_callback_register : theory -> unit = \"set_reduce_distinct_callback_register\" -external set_new_app_callback_register : theory -> unit = \"set_new_app_callback_register\" -external set_new_elem_callback_register : theory -> unit = \"set_new_elem_callback_register\" -external set_init_search_callback_register : theory -> unit = \"set_init_search_callback_register\" -external set_push_callback_register : theory -> unit = \"set_push_callback_register\" -external set_pop_callback_register : theory -> unit = \"set_pop_callback_register\" -external set_restart_callback_register : theory -> unit = \"set_restart_callback_register\" -external set_reset_callback_register : theory -> unit = \"set_reset_callback_register\" -external set_final_check_callback_register : theory -> unit = \"set_final_check_callback_register\" -external set_new_eq_callback_register : theory -> unit = \"set_new_eq_callback_register\" -external set_new_diseq_callback_register : theory -> unit = \"set_new_diseq_callback_register\" -external set_new_assignment_callback_register : theory -> unit = \"set_new_assignment_callback_register\" -external set_new_relevant_callback_register : theory -> unit = \"set_new_relevant_callback_register\" - -let is_some opt = - match opt with - | Some v -> true - | None -> false - -let get_some opt = - match opt with - | Some v -> v - | None -> failwith \"None unexpected\" - - - - -let apply_delete (th:theory_callbacks) = th.delete_theory () -let set_delete_callback th cb = - let cbs = get_theory_callbacks th in - cbs.delete_theory <- cb; - set_delete_callback_register th - -let mk_theory context name = - Callback.register \"is_some\" is_some; - Callback.register \"get_some\" get_some; - Callback.register \"apply_delete\" apply_delete; - let cbs = mk_theory_callbacks() in - mk_theory_register context name cbs - - -let apply_reduce_app (th:theory_callbacks) f args = th.reduce_app f args -let set_reduce_app_callback th cb = - Callback.register \"apply_reduce_app\" apply_reduce_app; - let cbs = get_theory_callbacks th in - cbs.reduce_app <- cb; - set_reduce_app_callback_register th - -let apply_reduce_eq (th:theory_callbacks) a b = th.reduce_eq a b -let set_reduce_eq_callback th cb = - Callback.register \"apply_reduce_eq\" apply_reduce_eq; - let cbs = get_theory_callbacks th in - cbs.reduce_eq <- cb; - set_reduce_eq_callback_register th - -let apply_reduce_distinct (th:theory_callbacks) args = th.reduce_distinct args -let set_reduce_distinct_callback th cb = - Callback.register \"apply_reduce_distinct\" apply_reduce_distinct; - let cbs = get_theory_callbacks th in - cbs.reduce_distinct <- cb; - set_reduce_distinct_callback_register th - - -let apply_new_app (th:theory_callbacks) a = th.new_app a -let set_new_app_callback th cb = - Callback.register \"apply_new_app\" apply_new_app; - let cbs = get_theory_callbacks th in - cbs.new_app <- cb; - set_new_app_callback_register th - -let apply_new_elem (th:theory_callbacks) a = th.new_elem a -let set_new_elem_callback th cb = - Callback.register \"apply_new_elem\" apply_new_elem; - let cbs = get_theory_callbacks th in - cbs.new_elem <- cb; - set_new_elem_callback_register th - - -let apply_init_search (th:theory_callbacks) = th.init_search() -let set_init_search_callback th cb = - Callback.register \"apply_init_search\" apply_init_search; - let cbs = get_theory_callbacks th in - cbs.init_search <- cb; - set_init_search_callback_register th - - -let apply_push (th:theory_callbacks) = th.push() -let set_push_callback th cb = - Callback.register \"apply_push\" apply_push; - let cbs = get_theory_callbacks th in - cbs.push <- cb; - set_push_callback_register th - -let apply_pop (th:theory_callbacks) = th.pop() -let set_pop_callback th cb = - Callback.register \"apply_pop\" apply_pop; - let cbs = get_theory_callbacks th in - cbs.pop <- cb; - set_pop_callback_register th - - -let apply_restart (th:theory_callbacks) = th.restart() -let set_restart_callback th cb = - Callback.register \"apply_restart\" apply_restart; - let cbs = get_theory_callbacks th in - cbs.restart <- cb; - set_restart_callback_register th - - -let apply_reset (th:theory_callbacks) = th.reset() -let set_reset_callback th cb = - Callback.register \"apply_reset\" apply_reset; - let cbs = get_theory_callbacks th in - cbs.reset <- cb; - set_reset_callback_register th - -let apply_final_check (th:theory_callbacks) = th.final_check() -let set_final_check_callback th cb = - Callback.register \"apply_final_check\" apply_final_check; - let cbs = get_theory_callbacks th in - cbs.final_check <- cb; - set_final_check_callback_register th - -let apply_new_eq (th:theory_callbacks) a b = th.new_eq a b -let set_new_eq_callback th cb = - Callback.register \"apply_new_eq\" apply_new_eq; - let cbs = get_theory_callbacks th in - cbs.new_eq <- cb; - set_new_eq_callback_register th - - -let apply_new_diseq (th:theory_callbacks) a b = th.new_diseq a b -let set_new_diseq_callback th cb = - Callback.register \"apply_new_diseq\" apply_new_diseq; - let cbs = get_theory_callbacks th in - cbs.new_diseq <- cb; - set_new_diseq_callback_register th - -let apply_new_assignment (th:theory_callbacks) a b = th.new_assignment a b -let set_new_assignment_callback th cb = - Callback.register \"apply_new_assignment\" apply_new_assignment; - let cbs = get_theory_callbacks th in - cbs.new_assignment <- cb; - set_new_assignment_callback_register th - -let apply_new_relevant (th:theory_callbacks) a = th.new_relevant a -let set_new_relevant_callback th cb = - Callback.register \"apply_new_relevant\" apply_new_relevant; - let cbs = get_theory_callbacks th in - cbs.new_relevant <- cb; - set_new_relevant_callback_register th - -"); diff --git a/src/api/ml/old/x3V3.mli b/src/api/ml/old/x3V3.mli deleted file mode 100644 index 2aa2ba4e7..000000000 --- a/src/api/ml/old/x3V3.mli +++ /dev/null @@ -1,361 +0,0 @@ - -quote (mli," - -(** {2 {L ML Extensions}} *) - -(** - \[ [ mk_context_x configs] \] is a shorthand for the context with configurations in [configs]. -*) -val mk_context_x: (string * string) array -> context;; - -(** - \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - - {b See also}: {!Z3.get_app_num_args} - - {b See also}: {!Z3.get_app_arg} -*) -val get_app_args: context -> app -> ast array - -(** - \[ [ get_app_args c d ] \] is the array of parameters of [d]. - - - {b See also}: {!Z3.get_domain_size} - - {b See also}: {!Z3.get_domain} -*) -val get_domains: context -> func_decl -> sort array - -(** - \[ [ get_array_sort c t ] \] is the domain and the range of [t]. - - - {b See also}: {!Z3.get_array_sort_domain} - - {b See also}: {!Z3.get_array_sort_range} -*) -val get_array_sort: context -> sort -> sort * sort - -(** - \[ [ get_tuple_sort c ty ] \] is the pair [(mk_decl, fields)] where [mk_decl] is the constructor declaration of [ty], and [fields] is the array of fields in [ty]. - - - {b See also}: {!Z3.get_tuple_sort_mk_decl} - - {b See also}: {!Z3.get_tuple_sort_num_fields} - - {b See also}: {!Z3.get_tuple_sort_field_decl} -*) -val get_tuple_sort: context -> sort -> (func_decl * func_decl array) - -(** - \[ [ datatype_constructor_refined ] \] is the refinement of a datatype constructor. - - It contains the constructor declaration, recognizer, and list of accessor functions. -*) -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array -} - -(** - \[ [ get_datatype_sort c ty ] \] is the array of triples [(constructor, recognizer, fields)] where [constructor] is the constructor declaration of [ty], [recognizer] is the recognizer for the [constructor], and [fields] is the array of fields in [ty]. - - - {b See also}: {!Z3.get_datatype_sort_num_constructors} - - {b See also}: {!Z3.get_datatype_sort_constructor} - - {b See also}: {!Z3.get_datatype_sort_recognizer} - - {b See also}: {!Z3.get_datatype_sort_constructor_accessor} -*) - - -val get_datatype_sort: context -> sort -> datatype_constructor_refined array - -(** - \[ [ get_model_constants c m ] \] is the array of constants in the model [m]. - - - {b See also}: {!Z3.get_model_num_constants} - - {b See also}: {!Z3.get_model_constant} -*) -val get_model_constants: context -> model -> func_decl array - - -(** - \[ [ get_model_func_entry c m i j ] \] is the [j]'th entry in the [i]'th function in the model [m]. - - - {b See also}: {!Z3.get_model_func_entry_num_args} - - {b See also}: {!Z3.get_model_func_entry_arg} - - {b See also}: {!Z3.get_model_func_entry_value} -*) -val get_model_func_entry: context -> model -> int -> int -> (ast array * ast);; - -(** - \[ [ get_model_func_entries c m i ] \] is the array of entries in the [i]'th function in the model [m]. - - - {b See also}: {!Z3.get_model_func_num_entries} - - {b See also}: {!Z3.get_model_func_entry} -*) -val get_model_func_entries: context -> model -> int -> (ast array * ast) array;; - -(** - \[ [ get_model_funcs c m ] \] is the array of functions in the model [m]. Each function is represented by the triple [(decl, entries, else)], where [decl] is the declaration name for the function, [entries] is the array of entries in the function, and [else] is the default (else) value for the function. - - - {b See also}: {!Z3.get_model_num_funcs} - - {b See also}: {!Z3.get_model_func_decl} - - {b See also}: {!Z3.get_model_func_entries} - - {b See also}: {!Z3.get_model_func_else} -*) -val get_model_funcs: context -> model -> - (symbol * - (ast array * ast) array * - ast) array - -(** - \[ [ get_smtlib_formulas c ] \] is the array of formulas created by a preceding call to {!Z3.parse_smtlib_string} or {!Z3.parse_smtlib_file}. - - Recommend use {!Z3.parse_smtlib_string_x} or {!Z3.parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - {b See also}: {!Z3.parse_smtlib_string_x} - - {b See also}: {!Z3.parse_smtlib_file_x} - - {b See also}: {!Z3.parse_smtlib_string} - - {b See also}: {!Z3.parse_smtlib_file} - - {b See also}: {!Z3.get_smtlib_num_formulas} - - {b See also}: {!Z3.get_smtlib_formula} -*) -val get_smtlib_formulas: context -> ast array - -(** - \[ [get_smtlib_assumptions c] \] is the array of assumptions created by a preceding call to {!Z3.parse_smtlib_string} or {!Z3.parse_smtlib_file}. - - Recommend use {!Z3.parse_smtlib_string_x} or {!Z3.parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - - {b See also}: {!Z3.parse_smtlib_string_x} - - {b See also}: {!Z3.parse_smtlib_file_x} - - {b See also}: {!Z3.parse_smtlib_string} - - {b See also}: {!Z3.parse_smtlib_file} - - {b See also}: {!Z3.get_smtlib_num_assumptions} - - {b See also}: {!Z3.get_smtlib_assumption} -*) -val get_smtlib_assumptions: context -> ast array - -(** - \[ [ get_smtlib_decls c ] \] is the array of declarations created by a preceding call to {!Z3.parse_smtlib_string} or {!Z3.parse_smtlib_file}. - - Recommend use {!Z3.parse_smtlib_string_x} or {!Z3.parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - - {b See also}: {!Z3.parse_smtlib_string_x} - - {b See also}: {!Z3.parse_smtlib_file_x} - - {b See also}: {!Z3.parse_smtlib_string} - - {b See also}: {!Z3.parse_smtlib_file} - - {b See also}: {!Z3.get_smtlib_num_decls} - - {b See also}: {!Z3.get_smtlib_decl} -*) -val get_smtlib_decls: context -> func_decl array - -(** - \[ [ get_smtlib_parse_results c ] \] is the triple [(get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c)]. - - Recommend use {!Z3.parse_smtlib_string_x} or {!Z3.parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - - {b See also}: {!Z3.parse_smtlib_string_x} - - {b See also}: {!Z3.parse_smtlib_file_x} - - {b See also}: {!Z3.parse_smtlib_string} - - {b See also}: {!Z3.parse_smtlib_file} - - {b See also}: {!Z3.get_smtlib_formulas} - - {b See also}: {!Z3.get_smtlib_assumptions} - - {b See also}: {!Z3.get_smtlib_decls} -*) -val get_smtlib_parse_results: context -> (ast array * ast array * func_decl array) - -(** - \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - - Recommended for functional style interface to the SMT-LIB parser. - - - {b See also}: {!Z3.parse_smtlib_file_formula} - - {b See also}: {!Z3.parse_smtlib_string_x} -*) -val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - -(** - \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - - Recommended for functional style interface to the SMT-LIB parser. - - - {b See also}: {!Z3.parse_smtlib_file_formula} - - {b See also}: {!Z3.parse_smtlib_file_x} -*) -val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - -(** - \[ [ parse_smtlib_string_x c ... ] \] is [(parse_smtlib_string c ...; get_smtlib_parse_results c)] - - Recommended for functional style interface to the SMT-LIB parser. - - - {b See also}: {!Z3.parse_smtlib_file_x} - - {b See also}: {!Z3.parse_smtlib_string} - - {b See also}: {!Z3.get_smtlib_parse_results} -*) -val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - -(** - \[ [ parse_smtlib_file_x c ... ] \] is [(parse_smtlib_file c ...; get_smtlib_parse_results c)] - - Recommended for functional style interface to the SMT-LIB parser. - - - {b See also}: {!Z3.parse_smtlib_string_x} - - {b See also}: {!Z3.parse_smtlib_file} - - {b See also}: {!Z3.get_smtlib_parse_results} -*) -val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - -(** - \[ [ symbol_refined ] \] is the refinement of a {!Z3.symbol} . - - - {b See also}: {!Z3.symbol_refine} - - {b See also}: {!Z3.get_symbol_kind} -*) -type symbol_refined = - | Symbol_int of int - | Symbol_string of string - | Symbol_unknown;; - -(** - \[ [ symbol_refine c s ] \] is the refined symbol of [s]. - - - {b See also}: {!Z3.symbol_refined} - - {b See also}: {!Z3.get_symbol_kind} -*) -val symbol_refine: context -> symbol -> symbol_refined;; - -(** - \[ [ sort_refined ] \] is the refinement of a {!Z3.sort} . - - - {b See also}: {!Z3.sort_refine} - - {b See also}: {!Z3.get_sort_kind} -*) - - -type sort_refined = - | Sort_uninterpreted of symbol - | Sort_bool - | Sort_int - | Sort_real - | Sort_bv of int - | Sort_array of (sort * sort) - | Sort_datatype of datatype_constructor_refined array - | Sort_relation - | Sort_finite_domain - | Sort_unknown of symbol - -(** - \[ [ sort_refine c t ] \] is the refined sort of [t]. - - - {b See also}: {!Z3.sort_refined} - - {b See also}: {!Z3.get_sort_kind} -*) -val sort_refine: context -> sort -> sort_refined;; - -(** - \[ [ binder_type ] \] is a universal or existential quantifier. - - - {b See also}: {!Z3.term_refined} -*) -type binder_type = | Forall | Exists - -(** - \[ [ numeral_refined ] \] is the refinement of a numeral . - - Numerals whose fractional representation can be fit with - 64 bit integers are treated as small. - -*) -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string - -(** - \[ [ term_refined ] \] is the refinement of a {!Z3.ast} . - - - {b See also}: {!Z3.term_refine} -*) -type term_refined = - | Term_app of decl_kind * func_decl * ast array - | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort - -(** - \[ [ term_refine c a ] \] is the refined term of [a]. - - - {b See also}: {!Z3.term_refined} -*) -val term_refine : context -> ast -> term_refined - -(** - \[ [mk_theory c name ] \] create a custom theory. - -*) -val mk_theory : context -> string -> theory - -(** - \[ [set_delete_callback th cb] \] set callback when theory gets deleted. -*) -val set_delete_callback : theory -> (unit -> unit) -> unit - -(** - \[ [set_reduce_app_callback th cb] \] set callback for simplifying theory terms. -*) -val set_reduce_app_callback : theory -> (func_decl -> ast array -> ast option) -> unit - -(** - \[ [set_reduce_eq_callback th cb] \] set callback for simplifying equalities over theory terms. -*) -val set_reduce_eq_callback : theory -> (ast -> ast -> ast option) -> unit - -(** - \[ [set_reduce_distinct_callback th cb] \] set callback for simplifying disequalities over theory terms. -*) -val set_reduce_distinct_callback : theory -> (ast array -> ast option) -> unit - -(** - \[ [set_new_app_callback th cb] \] set callback for registering new application. -*) -val set_new_app_callback : theory -> (ast -> unit) -> unit - -(** - \[ [set_new_elem_callback th cb] \] set callback for registering new element. - - - {b See also}: the help for the corresponding C API function. -*) -val set_new_elem_callback : theory -> (ast -> unit) -> unit - -(** - \[ [set_init_search_callback th cb] \] set callback when Z3 starts searching for a satisfying assignment. -*) -val set_init_search_callback : theory -> (unit -> unit) -> unit - -(** - \[ [set_push_callback th cb] \] set callback for a logical context push. -*) -val set_push_callback : theory -> (unit -> unit) -> unit - -(** - \[ [set_pop_callback th cb] \] set callback for a logical context pop. -*) -val set_pop_callback : theory -> (unit -> unit) -> unit - -(** - \[ [set_restart_callback th cb] \] set callback for search restart. -*) -val set_restart_callback : theory -> (unit -> unit) -> unit - -val set_reset_callback : theory -> (unit -> unit) -> unit - -val set_final_check_callback : theory -> (unit -> bool) -> unit - -val set_new_eq_callback : theory -> (ast -> ast -> unit) -> unit - -val set_new_diseq_callback : theory -> (ast -> ast -> unit) -> unit - -val set_new_assignment_callback : theory -> (ast -> bool -> unit) -> unit - -val set_new_relevant_callback : theory -> (ast -> unit) -> unit - -"); diff --git a/src/api/ml/old/z3.0.idl b/src/api/ml/old/z3.0.idl deleted file mode 100644 index 3773a28e3..000000000 --- a/src/api/ml/old/z3.0.idl +++ /dev/null @@ -1,597 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation - -Module Name: - - Z3 - -Abstract: - - OCaml API for Z3. - - The following design is used for the treatment of reference counting: - - - The conversion of Z3_context from ML to C remembers the Z3 context, and - registers a finalizer using Gc.finalize that calls Z3_del_context. - - - The conversion of Z3_ast and other reference counted types from C to ML: - - + stores the last translated context with the Z3_ast in the wrapper - object; - - + registers a finalizer using Gc.finalize that decrements the reference - counter of the Z3_ast; - - + increments the reference count of the Z3_ast. - - The finalizers are registered using (the C interface to) Gc.finalize, - not attaching a finalizer to a custom block. The finalizers registered - by Gc.finalize are guaranteed to be called in reverse - registration-order, which is necessary to ensure that Z3_context's are - finalized only after all the Z3_ast's within them. - - - ML Z3.ast (and subtypes) are given generic hash and comparison - operations using Z3_get_ast_hash and Z3_get_ast_id. Other types could - be handled similarly if analogous hash and id operations were exported - by the C API. - - - The wrapper for Z3_mk_context is customized (using quote(call,...) in - z3_api.patched.h) to call Z3_mk_context_rc, and the ML API does not - include mk_context_rc. - - This scheme relies on the property that all reference counted values - returned from C to ML are in the Z3_context that was last sent from ML to - C. This is normally straightforward, but note that it depends on the - argument order of e.g. the Z3_*translate functions. - - Non-reference counted Z3 types that have delete operations have finalizers - that call the delete operations. The exposed delete operations are - shadowed by nop functions. The types whose delete operation accepts a - context use Gc.finalize while those that do not use custom block - finalizers. - - Custom c2ml functions check the Z3 error code prior to allocating ML - values or registering finalizers. Other functions check the Z3 error code - after making a Z3 library call. - - Some operations return NULL pointers when operations fail, or accept NULL - pointers. To handle these cases Z3_{ast,func_interp,sort}_opt types are - introduced. These are synonyms of Z3_{ast,func_interp,sort} but are - translated into OCaml option types. If the NULL pointers were passed to - ML, even if the user does not access them, they will have finalizers - registered, so when they die the OCaml GC will crash trying to call - dec_ref on NULL. - - There is an alternate implementation, enabled by setting LEAK_CONTEXTS, - that avoids the overhead of Gc.finalize finalizers, but at the price of - leaking Z3_context objects. - -Notes: - - OCaml does not support unsigned types, so CamlIDL conflates signed and - unsigned types of the same size. Therefore, functions in the C API - operating on unsigned values that become redundant after this conflation - are excluded from the ML API using [#ifndef CAMLIDL] in z3_api.h. - - CamlIDL does not support function pointers, so functions in the C API with - function pointer arguments are handled manually. - -Author: - - Jakob Lichtenberg (JakobL) 2007-08-08 - Josh Berdine (jjb) 2012-03-21 - ---*/ - - -// cpp trick to include expanded macro arguments in string literals -#define xstr(s) str(s) -#define str(s) #s -quote(c,"#define xstr(s) str(s)"); -quote(c,"#define str(s) #s"); - - -#ifndef MLAPIV3 - -#define DEFINE_TYPE(T) typedef [abstract] void* T -#define DEFINE_VOID(T) typedef [abstract] void* T - -#define BEGIN_MLAPI_EXCLUDE quote(mli,"(*"); -#define END_MLAPI_EXCLUDE quote(mli,"*)"); - -#ifdef LEAK_CONTEXTS - - // Declare pointer type with custom conversion functions. - #define DEFINE_CUST_TYPE(T) \ - typedef [abstract, ml2c(ml2c_Z3_ ## T), c2ml(c2ml_Z3_ ## T)] void* Z3_ ## T - -#else - - // Declare pointer type with custom conversion functions. - // Register an OCaml closure that just calls a C finalization function. - #define DEFINE_CUST_TYPE(T) \ - quote(ml,xstr(\ - external finalize_Z3_ ## T : T -> unit = xstr(finalize_Z3_ ## T);; \ - let _ = Callback.register xstr(finalize_Z3_ ## T) finalize_Z3_ ## T \ - )); \ - typedef [abstract, ml2c(ml2c_Z3_ ## T), c2ml(c2ml_Z3_ ## T)] void* Z3_ ## T - -#endif - - -// Z3_context -quote(c," -void check_error_code (Z3_context c); - -Z3_context last_ctx; -"); - -#ifdef LEAK_CONTEXTS - - quote(c," - value c2ml_Z3_context(Z3_context* c) - { - value v; - v = caml_alloc_small(1, Abstract_tag); - *((Z3_context *) Bp_val(v)) = *c; - return v; - } - - void ml2c_Z3_context(value v, Z3_context* c) - { - *c = *((Z3_context *) Bp_val(v)); - last_ctx = *c; - } - "); - -#else - - quote(c," - // caml_final_register is the implementation of Gc.finalize - value caml_final_register (value f, value v); - - void register_finalizer(value** closure, char* name, Z3_context ctx, value v) - { - if (*closure == NULL) { - *closure = caml_named_value(name); - if (*closure == NULL) { - Z3_set_error(ctx, Z3_INTERNAL_FATAL); - return; - } - } - caml_final_register(**closure, v); - } - - value c2ml_Z3_context (Z3_context* c) - { - static value* finalize_Z3_context_closure = NULL; - value v; - v = caml_alloc_small(1, Abstract_tag); - Field(v, 0) = (value) *c; - register_finalizer(&finalize_Z3_context_closure, \"finalize_Z3_context\", - (Z3_context) *c, v); - return v; - } - - void ml2c_Z3_context (value v, Z3_context* c) - { - *c = (Z3_context) Field(v, 0); - last_ctx = *c; - } - - value finalize_Z3_context (value v) - { - Z3_context c; - c = (Z3_context) Field(v, 0); - Z3_del_context(c); - return Val_unit; - } - "); - -#endif - -DEFINE_CUST_TYPE(context); - - -// Z3_symbol -typedef [abstract] void* Z3_symbol; - - -// Z3_ast: reference counted type with hashing and comparison -quote(c," -typedef struct _Z3_ast_context { - Z3_ast ast; - Z3_context ctx; -} Z3_ast_context; - -void ml2c_Z3_ast (value v, Z3_ast* c) -{ - *c = ((Z3_ast_context*) Data_custom_val(v))->ast; -} - -static int compare_Z3_ast (value v1, value v2) -{ - Z3_ast_context* ac1; - Z3_ast_context* ac2; - unsigned id1, id2; - ac1 = Data_custom_val(v1); - ac2 = Data_custom_val(v2); - id1 = Z3_get_ast_id(ac1->ctx, ac1->ast); - check_error_code(ac1->ctx); - id2 = Z3_get_ast_id(ac2->ctx, ac2->ast); - check_error_code(ac2->ctx); - return id2 - id1; -} - -static intnat hash_Z3_ast (value v) -{ - Z3_ast_context* ac; - unsigned hash; - ac = Data_custom_val(v); - hash = Z3_get_ast_hash(ac->ctx, ac->ast); - check_error_code(ac->ctx); - return hash; -} -"); - -#ifdef LEAK_CONTEXTS - - quote(c," - static void finalize_Z3_ast (value v) - { - Z3_ast_context* ac; - ac = Data_custom_val(v); - Z3_dec_ref(ac->ctx, ac->ast); - check_error_code(ac->ctx); - } - - static struct custom_operations cops_Z3_ast = { - NULL, - finalize_Z3_ast, - compare_Z3_ast, - hash_Z3_ast, - custom_serialize_default, - custom_deserialize_default - }; - - value c2ml_Z3_ast (Z3_ast* c) - { - value v; - Z3_ast_context* ac; - check_error_code(last_ctx); - v = alloc_custom(&cops_Z3_ast, sizeof(Z3_ast_context), 0, 1); - ac = Data_custom_val(v); - ac->ctx = last_ctx; - ac->ast = *c; - Z3_inc_ref(ac->ctx, ac->ast); - return v; - } - "); - -#else - - quote(c," - value finalize_Z3_ast (value v) - { - Z3_ast_context* ac; - ac = Data_custom_val(v); - Z3_dec_ref(ac->ctx, ac->ast); - check_error_code(ac->ctx); - return Val_unit; - } - - static struct custom_operations cops_Z3_ast = { - NULL, - custom_finalize_default, - compare_Z3_ast, - hash_Z3_ast, - custom_serialize_default, - custom_deserialize_default - }; - - value c2ml_Z3_ast (Z3_ast* c) - { - static value* finalize_Z3_ast_closure = NULL; - value v; - Z3_ast_context* ac; - check_error_code(last_ctx); - v = caml_alloc_custom(&cops_Z3_ast, sizeof(Z3_ast_context), 0, 1); - ac = Data_custom_val(v); - ac->ast = *c; - ac->ctx = last_ctx; - register_finalizer(&finalize_Z3_ast_closure, \"finalize_Z3_ast\", - (Z3_context) *c, v); - Z3_inc_ref(last_ctx, *c); - return v; - } - "); - -#endif - -DEFINE_CUST_TYPE(ast); - - -// subtypes of Z3_ast -quote(c,"\ -#define DEFINE_SUBAST_OPS(T) \ - void ml2c_ ## T (value v, T * a) \ - { \ - ml2c_Z3_ast(v, (Z3_ast*) a); \ - } \ - \ - value c2ml_ ## T (T * a) \ - { \ - return c2ml_Z3_ast((Z3_ast*) a); \ - } \ -"); - -#define DEFINE_SUBAST(T) \ - typedef [mltype("private ast"), ml2c(ml2c_ ## T), c2ml(c2ml_ ## T)] Z3_ast T - -quote(c,"DEFINE_SUBAST_OPS(Z3_sort)"); DEFINE_SUBAST(Z3_sort); -quote(c,"DEFINE_SUBAST_OPS(Z3_func_decl)"); DEFINE_SUBAST(Z3_func_decl); -quote(c,"DEFINE_SUBAST_OPS(Z3_app)"); DEFINE_SUBAST(Z3_app); -quote(c,"DEFINE_SUBAST_OPS(Z3_pattern)"); DEFINE_SUBAST(Z3_pattern); - - -// reference counted types without hashing and comparison -#ifdef LEAK_CONTEXTS - - quote(c,"\ - #define DEFINE_RC_OPS(T) \ - typedef struct _ ## T ## _context { \ - T dat; \ - Z3_context ctx; \ - } T ## _context; \ - \ - static void finalize_ ## T (value v) \ - { \ - T ## _context* ac; \ - ac = Data_custom_val(v); \ - T ## _dec_ref(ac->ctx, ac->dat); \ - check_error_code(ac->ctx); \ - } \ - \ - static struct custom_operations cops_ ## T = { \ - NULL, \ - finalize_ ## T, \ - custom_compare_default, \ - custom_hash_default, \ - custom_serialize_default, \ - custom_deserialize_default \ - }; \ - \ - value c2ml_ ## T (T * c) \ - { \ - value v; \ - T ## _context* ac; \ - check_error_code(last_ctx); \ - v = alloc_custom(&cops_ ## T, sizeof(T ## _context), 0, 1); \ - ac = Data_custom_val(v); \ - ac->dat = *c; \ - ac->ctx = last_ctx; \ - T ## _inc_ref(ac->ctx, ac->dat); \ - return v; \ - } \ - \ - void ml2c_ ## T (value v, T * c) \ - { \ - *c = ((T ## _context*) Data_custom_val(v))->dat; \ - } \ - "); - -#else - - quote(c,"\ - #define DEFINE_RC_OPS(T) \ - value c2ml_ ## T (T * c) \ - { \ - static value* finalize_ ## T ## _closure = NULL; \ - value v; \ - check_error_code(last_ctx); \ - v = caml_alloc_small(2, Abstract_tag); \ - Field(v, 0) = (value) *c; \ - Field(v, 1) = (value) last_ctx; \ - register_finalizer(&finalize_ ## T ## _closure, xstr(finalize_ ## T), \ - (Z3_context) *c, v); \ - T ## _inc_ref(last_ctx, *c); \ - return v; \ - } \ - \ - void ml2c_ ## T (value v, T * c) \ - { \ - *c = (T) Field(v, 0); \ - } \ - \ - value finalize_ ## T (value v) \ - { \ - Z3_context c; \ - c = (Z3_context) Field(v, 1); \ - T ## _dec_ref(c, (T) Field(v, 0)); \ - check_error_code(c); \ - return Val_unit; \ - } \ - "); - -#endif - -quote(c,"DEFINE_RC_OPS(Z3_params)"); DEFINE_CUST_TYPE(params); -quote(c,"DEFINE_RC_OPS(Z3_param_descrs)"); DEFINE_CUST_TYPE(param_descrs); -quote(c,"DEFINE_RC_OPS(Z3_model)"); DEFINE_CUST_TYPE(model); -quote(c,"DEFINE_RC_OPS(Z3_func_interp)"); DEFINE_CUST_TYPE(func_interp); -quote(c,"DEFINE_RC_OPS(Z3_func_entry)"); DEFINE_CUST_TYPE(func_entry); -quote(c,"DEFINE_RC_OPS(Z3_fixedpoint)"); DEFINE_CUST_TYPE(fixedpoint); -quote(c,"DEFINE_RC_OPS(Z3_ast_vector)"); DEFINE_CUST_TYPE(ast_vector); -quote(c,"DEFINE_RC_OPS(Z3_ast_map)"); DEFINE_CUST_TYPE(ast_map); -quote(c,"DEFINE_RC_OPS(Z3_goal)"); DEFINE_CUST_TYPE(goal); -quote(c,"DEFINE_RC_OPS(Z3_tactic)"); DEFINE_CUST_TYPE(tactic); -quote(c,"DEFINE_RC_OPS(Z3_probe)"); DEFINE_CUST_TYPE(probe); -quote(c,"DEFINE_RC_OPS(Z3_apply_result)"); DEFINE_CUST_TYPE(apply_result); -quote(c,"DEFINE_RC_OPS(Z3_solver)"); DEFINE_CUST_TYPE(solver); -quote(c,"DEFINE_RC_OPS(Z3_stats)"); DEFINE_CUST_TYPE(stats); - - -// possibly-NULL pointer types, translated to OCaml option types -quote(c,"\ -#define DEFINE_OPT_OPS(T) \ - void ml2c_ ## T ## _opt (value v, T* c) \ - { \ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; \ - camlidl_ctx _ctx = &_ctxs; \ - if (v != Val_int(0)) { \ - camlidl_ml2c_z3_ ## T(Field(v, 0), c, _ctx); \ - } else { \ - *c = NULL; \ - } \ - } \ - \ - value c2ml_ ## T ## _opt (T* c) \ - { \ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; \ - camlidl_ctx _ctx = &_ctxs; \ - value v; \ - value a; \ - if (*c) { \ - a = camlidl_c2ml_z3_ ## T(c, _ctx); \ - Begin_root(a) \ - v = caml_alloc_small(1, 0); \ - Field(v, 0) = a; \ - End_roots(); \ - } else { \ - v = Val_int(0); \ - } \ - return v; \ - } -"); - -#define DEFINE_OPT_TYPE(T) \ - typedef [mltype(xstr(T option)), \ - ml2c(ml2c_Z3_ ## T ## _opt), \ - c2ml(c2ml_Z3_ ## T ## _opt) \ - ] Z3_ ## T Z3_ ## T ## _opt - -quote(c,"DEFINE_OPT_OPS(Z3_ast)"); -DEFINE_OPT_TYPE(ast); - -quote(c,"DEFINE_OPT_OPS(Z3_sort)"); -DEFINE_OPT_TYPE(sort); - -quote(c,"DEFINE_OPT_OPS(Z3_func_interp)"); -DEFINE_OPT_TYPE(func_interp); - - -// ToDo: these unnecessarily appear in the API documentation -DEFINE_TYPE(Z3_constructor); -DEFINE_TYPE(Z3_constructor_list); - - -// shadow delete operations with nops -quote(ml," -let del_constructor _ _ = () -let del_constructor_list _ _ = () -let del_model _ _ = () -let del_context _ = () -let reset_memory () = () -"); - - -#else // MLAPIV3 - -// Provide custom error handler: -quote (c,"Z3_error_handler caml_z3_error_handler;"); -quote (c,"void caml_z3_error_handler(Z3_context c, Z3_error_code e) { static char buffer[128]; char * msg = Z3_get_error_msg_ex(c, e); if (strlen(msg) > 100) { failwith(\"Z3: error message is too big to fit in buffer\"); } else { sprintf(buffer, \"Z3: %s\", msg); failwith(buffer); } }"); - - -#define DEFINE_TYPE(T) typedef [abstract] void* T -#define DEFINE_VOID(T) typedef [abstract] void* T - -#define BEGIN_MLAPI_EXCLUDE -#define END_MLAPI_EXCLUDE - -#endif // MLAPIV3 - - - -#ifndef __in -#define __in [in] -#endif - -#ifndef __out -#define __out [out] -#endif - -#ifndef __out_opt -#define __out_opt [out,unique] -#endif - -#ifndef __ecount -#define __ecount(num_args) [NOT_SUPPORTED] -#endif - -#ifndef __in_ecount -#define __in_ecount(num_args) [in, size_is(num_args), length_is(num_args)] -#endif - -#ifndef __out_ecount -#define __out_ecount(num_args) [out, size_is(num_args), length_is(num_args)] -#endif - -#ifndef __inout_ecount -#define __inout_ecount(num_args) [in, out, size_is(num_args), length_is(num_args)] -#endif - -#ifndef __inout -#define __inout [in, out] -#endif - -#ifndef Z3_bool_opt -#define Z3_bool_opt void -#endif - - -#define Z3_API - -#ifdef MLAPIV3 - -#include "z3V3_api.idl" -#include "x3V3.mli" -#include "x3V3.ml" - -#else - -#include "z3_api.idl" -#include "x3.ml" - -quote(ml," -let _ = - Printexc.register_printer (function - | Error(c,e) -> Some (\"Z3 \"^(get_error_msg c e)) - | _ -> None - ) -"); - - -quote(mli," -(** - {2 {L Legacy V3 API}} -*) - -module V3 : sig -(** - {2 {L Legacy V3 API}} -*) -"); - -quote(ml," -module V3 = struct -"); - -#endif - -#ifdef MLAPIV3 - -quote(mlmli," -end -"); - -#endif diff --git a/src/api/ml/old/z3_stubs.c b/src/api/ml/old/z3_stubs.c deleted file mode 100644 index bad4338de..000000000 --- a/src/api/ml/old/z3_stubs.c +++ /dev/null @@ -1,19044 +0,0 @@ -/* File generated from z3.idl */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef Custom_tag -#include -#include -#endif -#include - - -#include "z3.h" - -#define xstr(s) str(s) -#define str(s) #s - -void check_error_code (Z3_context c); -Z3_context last_ctx; - - - // caml_final_register is the implementation of Gc.finalize - value caml_final_register (value f, value v); - void register_finalizer(value** closure, char* name, Z3_context ctx, value v) - { - if (*closure == NULL) { - *closure = caml_named_value(name); - if (*closure == NULL) { - Z3_set_error(ctx, Z3_INTERNAL_FATAL); - return; - } - } - caml_final_register(**closure, v); - } - value c2ml_Z3_context (Z3_context* c) - { - static value* finalize_Z3_context_closure = NULL; - value v; - v = caml_alloc_small(1, Abstract_tag); - Field(v, 0) = (value) *c; - register_finalizer(&finalize_Z3_context_closure, "finalize_Z3_context", - (Z3_context) *c, v); - return v; - } - void ml2c_Z3_context (value v, Z3_context* c) - { - *c = (Z3_context) Field(v, 0); - last_ctx = *c; - } - value finalize_Z3_context (value v) - { - Z3_context c; - c = (Z3_context) Field(v, 0); - Z3_del_context(c); - return Val_unit; - } - -#define camlidl_ml2c_z3_Z3_context(v,c,ctx) ml2c_Z3_context(v,c) - -#define camlidl_c2ml_z3_Z3_context(c,ctx) c2ml_Z3_context(c) - -void camlidl_ml2c_z3_Z3_symbol(value _v1, Z3_symbol * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_symbol *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3_Z3_symbol(Z3_symbol * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_symbol) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_symbol *) Bp_val(_v1)) = *_c2; - return _v1; -} - - -typedef struct _Z3_ast_context { - Z3_ast ast; - Z3_context ctx; -} Z3_ast_context; -void ml2c_Z3_ast (value v, Z3_ast* c) -{ - *c = ((Z3_ast_context*) Data_custom_val(v))->ast; -} -static int compare_Z3_ast (value v1, value v2) -{ - Z3_ast_context* ac1; - Z3_ast_context* ac2; - unsigned id1, id2; - ac1 = Data_custom_val(v1); - ac2 = Data_custom_val(v2); - id1 = Z3_get_ast_id(ac1->ctx, ac1->ast); - check_error_code(ac1->ctx); - id2 = Z3_get_ast_id(ac2->ctx, ac2->ast); - check_error_code(ac2->ctx); - return id2 - id1; -} -static intnat hash_Z3_ast (value v) -{ - Z3_ast_context* ac; - unsigned hash; - ac = Data_custom_val(v); - hash = Z3_get_ast_hash(ac->ctx, ac->ast); - check_error_code(ac->ctx); - return hash; -} - - - value finalize_Z3_ast (value v) - { - Z3_ast_context* ac; - ac = Data_custom_val(v); - Z3_dec_ref(ac->ctx, ac->ast); - check_error_code(ac->ctx); - return Val_unit; - } - static struct custom_operations cops_Z3_ast = { - NULL, - custom_finalize_default, - compare_Z3_ast, - hash_Z3_ast, - custom_serialize_default, - custom_deserialize_default - }; - value c2ml_Z3_ast (Z3_ast* c) - { - static value* finalize_Z3_ast_closure = NULL; - value v; - Z3_ast_context* ac; - check_error_code(last_ctx); - v = caml_alloc_custom(&cops_Z3_ast, sizeof(Z3_ast_context), 0, 1); - ac = Data_custom_val(v); - ac->ast = *c; - ac->ctx = last_ctx; - register_finalizer(&finalize_Z3_ast_closure, "finalize_Z3_ast", - (Z3_context) *c, v); - Z3_inc_ref(last_ctx, *c); - return v; - } - -#define camlidl_ml2c_z3_Z3_ast(v,c,ctx) ml2c_Z3_ast(v,c) - -#define camlidl_c2ml_z3_Z3_ast(c,ctx) c2ml_Z3_ast(c) - -#define DEFINE_SUBAST_OPS(T) void ml2c_ ## T (value v, T * a) { ml2c_Z3_ast(v, (Z3_ast*) a); } value c2ml_ ## T (T * a) { return c2ml_Z3_ast((Z3_ast*) a); } -DEFINE_SUBAST_OPS(Z3_sort) -#define camlidl_ml2c_z3_Z3_sort(v,c,ctx) ml2c_Z3_sort(v,c) - -#define camlidl_c2ml_z3_Z3_sort(c,ctx) c2ml_Z3_sort(c) - -DEFINE_SUBAST_OPS(Z3_func_decl) -#define camlidl_ml2c_z3_Z3_func_decl(v,c,ctx) ml2c_Z3_func_decl(v,c) - -#define camlidl_c2ml_z3_Z3_func_decl(c,ctx) c2ml_Z3_func_decl(c) - -DEFINE_SUBAST_OPS(Z3_app) -#define camlidl_ml2c_z3_Z3_app(v,c,ctx) ml2c_Z3_app(v,c) - -#define camlidl_c2ml_z3_Z3_app(c,ctx) c2ml_Z3_app(c) - -DEFINE_SUBAST_OPS(Z3_pattern) -#define camlidl_ml2c_z3_Z3_pattern(v,c,ctx) ml2c_Z3_pattern(v,c) - -#define camlidl_c2ml_z3_Z3_pattern(c,ctx) c2ml_Z3_pattern(c) - - #define DEFINE_RC_OPS(T) value c2ml_ ## T (T * c) { static value* finalize_ ## T ## _closure = NULL; value v; check_error_code(last_ctx); v = caml_alloc_small(2, Abstract_tag); Field(v, 0) = (value) *c; Field(v, 1) = (value) last_ctx; register_finalizer(&finalize_ ## T ## _closure, xstr(finalize_ ## T), (Z3_context) *c, v); T ## _inc_ref(last_ctx, *c); return v; } void ml2c_ ## T (value v, T * c) { *c = (T) Field(v, 0); } value finalize_ ## T (value v) { Z3_context c; c = (Z3_context) Field(v, 1); T ## _dec_ref(c, (T) Field(v, 0)); check_error_code(c); return Val_unit; } -DEFINE_RC_OPS(Z3_params) -#define camlidl_ml2c_z3_Z3_params(v,c,ctx) ml2c_Z3_params(v,c) - -#define camlidl_c2ml_z3_Z3_params(c,ctx) c2ml_Z3_params(c) - -DEFINE_RC_OPS(Z3_param_descrs) -#define camlidl_ml2c_z3_Z3_param_descrs(v,c,ctx) ml2c_Z3_param_descrs(v,c) - -#define camlidl_c2ml_z3_Z3_param_descrs(c,ctx) c2ml_Z3_param_descrs(c) - -DEFINE_RC_OPS(Z3_model) -#define camlidl_ml2c_z3_Z3_model(v,c,ctx) ml2c_Z3_model(v,c) - -#define camlidl_c2ml_z3_Z3_model(c,ctx) c2ml_Z3_model(c) - -DEFINE_RC_OPS(Z3_func_interp) -#define camlidl_ml2c_z3_Z3_func_interp(v,c,ctx) ml2c_Z3_func_interp(v,c) - -#define camlidl_c2ml_z3_Z3_func_interp(c,ctx) c2ml_Z3_func_interp(c) - -DEFINE_RC_OPS(Z3_func_entry) -#define camlidl_ml2c_z3_Z3_func_entry(v,c,ctx) ml2c_Z3_func_entry(v,c) - -#define camlidl_c2ml_z3_Z3_func_entry(c,ctx) c2ml_Z3_func_entry(c) - -DEFINE_RC_OPS(Z3_fixedpoint) -#define camlidl_ml2c_z3_Z3_fixedpoint(v,c,ctx) ml2c_Z3_fixedpoint(v,c) - -#define camlidl_c2ml_z3_Z3_fixedpoint(c,ctx) c2ml_Z3_fixedpoint(c) - -DEFINE_RC_OPS(Z3_ast_vector) -#define camlidl_ml2c_z3_Z3_ast_vector(v,c,ctx) ml2c_Z3_ast_vector(v,c) - -#define camlidl_c2ml_z3_Z3_ast_vector(c,ctx) c2ml_Z3_ast_vector(c) - -DEFINE_RC_OPS(Z3_ast_map) -#define camlidl_ml2c_z3_Z3_ast_map(v,c,ctx) ml2c_Z3_ast_map(v,c) - -#define camlidl_c2ml_z3_Z3_ast_map(c,ctx) c2ml_Z3_ast_map(c) - -DEFINE_RC_OPS(Z3_goal) -#define camlidl_ml2c_z3_Z3_goal(v,c,ctx) ml2c_Z3_goal(v,c) - -#define camlidl_c2ml_z3_Z3_goal(c,ctx) c2ml_Z3_goal(c) - -DEFINE_RC_OPS(Z3_tactic) -#define camlidl_ml2c_z3_Z3_tactic(v,c,ctx) ml2c_Z3_tactic(v,c) - -#define camlidl_c2ml_z3_Z3_tactic(c,ctx) c2ml_Z3_tactic(c) - -DEFINE_RC_OPS(Z3_probe) -#define camlidl_ml2c_z3_Z3_probe(v,c,ctx) ml2c_Z3_probe(v,c) - -#define camlidl_c2ml_z3_Z3_probe(c,ctx) c2ml_Z3_probe(c) - -DEFINE_RC_OPS(Z3_apply_result) -#define camlidl_ml2c_z3_Z3_apply_result(v,c,ctx) ml2c_Z3_apply_result(v,c) - -#define camlidl_c2ml_z3_Z3_apply_result(c,ctx) c2ml_Z3_apply_result(c) - -DEFINE_RC_OPS(Z3_solver) -#define camlidl_ml2c_z3_Z3_solver(v,c,ctx) ml2c_Z3_solver(v,c) - -#define camlidl_c2ml_z3_Z3_solver(c,ctx) c2ml_Z3_solver(c) - -DEFINE_RC_OPS(Z3_stats) -#define camlidl_ml2c_z3_Z3_stats(v,c,ctx) ml2c_Z3_stats(v,c) - -#define camlidl_c2ml_z3_Z3_stats(c,ctx) c2ml_Z3_stats(c) - -#define DEFINE_OPT_OPS(T) void ml2c_ ## T ## _opt (value v, T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; if (v != Val_int(0)) { camlidl_ml2c_z3_ ## T(Field(v, 0), c, _ctx); } else { *c = NULL; } } value c2ml_ ## T ## _opt (T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; value v; value a; if (*c) { a = camlidl_c2ml_z3_ ## T(c, _ctx); Begin_root(a) v = caml_alloc_small(1, 0); Field(v, 0) = a; End_roots(); } else { v = Val_int(0); } return v; } - -DEFINE_OPT_OPS(Z3_ast) -#define camlidl_ml2c_z3_Z3_ast_opt(v,c,ctx) ml2c_Z3_ast_opt(v,c) - -#define camlidl_c2ml_z3_Z3_ast_opt(c,ctx) c2ml_Z3_ast_opt(c) - -DEFINE_OPT_OPS(Z3_sort) -#define camlidl_ml2c_z3_Z3_sort_opt(v,c,ctx) ml2c_Z3_sort_opt(v,c) - -#define camlidl_c2ml_z3_Z3_sort_opt(c,ctx) c2ml_Z3_sort_opt(c) - -DEFINE_OPT_OPS(Z3_func_interp) -#define camlidl_ml2c_z3_Z3_func_interp_opt(v,c,ctx) ml2c_Z3_func_interp_opt(v,c) - -#define camlidl_c2ml_z3_Z3_func_interp_opt(c,ctx) c2ml_Z3_func_interp_opt(c) - -void camlidl_ml2c_z3_Z3_constructor(value _v1, Z3_constructor * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_constructor *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3_Z3_constructor(Z3_constructor * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_constructor) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_constructor *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3_Z3_constructor_list(value _v1, Z3_constructor_list * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_constructor_list *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3_Z3_constructor_list(Z3_constructor_list * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_constructor_list) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_constructor_list *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3_Z3_string(value _v1, Z3_string * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_malloc_string(_v1, _ctx); -} - -value camlidl_c2ml_z3_Z3_string(Z3_string * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = copy_string((*_c2)); - return _v1; -} - -int camlidl_transl_table_z3_enum_1[3] = { - Z3_L_FALSE, - Z3_L_UNDEF, - Z3_L_TRUE, -}; - -void camlidl_ml2c_z3_Z3_lbool(value _v1, Z3_lbool * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_1[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_lbool(Z3_lbool * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_L_FALSE: _v1 = Val_int(0); break; - case Z3_L_UNDEF: _v1 = Val_int(1); break; - case Z3_L_TRUE: _v1 = Val_int(2); break; - default: invalid_argument("typedef Z3_lbool: bad enum value"); - } - return _v1; -} - -int camlidl_transl_table_z3_enum_2[2] = { - Z3_INT_SYMBOL, - Z3_STRING_SYMBOL, -}; - -void camlidl_ml2c_z3_Z3_symbol_kind(value _v1, Z3_symbol_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_2[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_symbol_kind(Z3_symbol_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_INT_SYMBOL: _v1 = Val_int(0); break; - case Z3_STRING_SYMBOL: _v1 = Val_int(1); break; - default: invalid_argument("typedef Z3_symbol_kind: bad enum value"); - } - return _v1; -} - -int camlidl_transl_table_z3_enum_3[7] = { - Z3_PARAMETER_INT, - Z3_PARAMETER_DOUBLE, - Z3_PARAMETER_RATIONAL, - Z3_PARAMETER_SYMBOL, - Z3_PARAMETER_SORT, - Z3_PARAMETER_AST, - Z3_PARAMETER_FUNC_DECL, -}; - -void camlidl_ml2c_z3_Z3_parameter_kind(value _v1, Z3_parameter_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_3[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_parameter_kind(Z3_parameter_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_3, 7, "typedef Z3_parameter_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_4[10] = { - Z3_UNINTERPRETED_SORT, - Z3_BOOL_SORT, - Z3_INT_SORT, - Z3_REAL_SORT, - Z3_BV_SORT, - Z3_ARRAY_SORT, - Z3_DATATYPE_SORT, - Z3_RELATION_SORT, - Z3_FINITE_DOMAIN_SORT, - Z3_UNKNOWN_SORT, -}; - -void camlidl_ml2c_z3_Z3_sort_kind(value _v1, Z3_sort_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_4[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_sort_kind(Z3_sort_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_4, 10, "typedef Z3_sort_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_5[7] = { - Z3_NUMERAL_AST, - Z3_APP_AST, - Z3_VAR_AST, - Z3_QUANTIFIER_AST, - Z3_SORT_AST, - Z3_FUNC_DECL_AST, - Z3_UNKNOWN_AST, -}; - -void camlidl_ml2c_z3_Z3_ast_kind(value _v1, Z3_ast_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_5[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_ast_kind(Z3_ast_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_5, 7, "typedef Z3_ast_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_6[152] = { - Z3_OP_TRUE, - Z3_OP_FALSE, - Z3_OP_EQ, - Z3_OP_DISTINCT, - Z3_OP_ITE, - Z3_OP_AND, - Z3_OP_OR, - Z3_OP_IFF, - Z3_OP_XOR, - Z3_OP_NOT, - Z3_OP_IMPLIES, - Z3_OP_OEQ, - Z3_OP_ANUM, - Z3_OP_AGNUM, - Z3_OP_LE, - Z3_OP_GE, - Z3_OP_LT, - Z3_OP_GT, - Z3_OP_ADD, - Z3_OP_SUB, - Z3_OP_UMINUS, - Z3_OP_MUL, - Z3_OP_DIV, - Z3_OP_IDIV, - Z3_OP_REM, - Z3_OP_MOD, - Z3_OP_TO_REAL, - Z3_OP_TO_INT, - Z3_OP_IS_INT, - Z3_OP_POWER, - Z3_OP_STORE, - Z3_OP_SELECT, - Z3_OP_CONST_ARRAY, - Z3_OP_ARRAY_MAP, - Z3_OP_ARRAY_DEFAULT, - Z3_OP_SET_UNION, - Z3_OP_SET_INTERSECT, - Z3_OP_SET_DIFFERENCE, - Z3_OP_SET_COMPLEMENT, - Z3_OP_SET_SUBSET, - Z3_OP_AS_ARRAY, - Z3_OP_BNUM, - Z3_OP_BIT1, - Z3_OP_BIT0, - Z3_OP_BNEG, - Z3_OP_BADD, - Z3_OP_BSUB, - Z3_OP_BMUL, - Z3_OP_BSDIV, - Z3_OP_BUDIV, - Z3_OP_BSREM, - Z3_OP_BUREM, - Z3_OP_BSMOD, - Z3_OP_BSDIV0, - Z3_OP_BUDIV0, - Z3_OP_BSREM0, - Z3_OP_BUREM0, - Z3_OP_BSMOD0, - Z3_OP_ULEQ, - Z3_OP_SLEQ, - Z3_OP_UGEQ, - Z3_OP_SGEQ, - Z3_OP_ULT, - Z3_OP_SLT, - Z3_OP_UGT, - Z3_OP_SGT, - Z3_OP_BAND, - Z3_OP_BOR, - Z3_OP_BNOT, - Z3_OP_BXOR, - Z3_OP_BNAND, - Z3_OP_BNOR, - Z3_OP_BXNOR, - Z3_OP_CONCAT, - Z3_OP_SIGN_EXT, - Z3_OP_ZERO_EXT, - Z3_OP_EXTRACT, - Z3_OP_REPEAT, - Z3_OP_BREDOR, - Z3_OP_BREDAND, - Z3_OP_BCOMP, - Z3_OP_BSHL, - Z3_OP_BLSHR, - Z3_OP_BASHR, - Z3_OP_ROTATE_LEFT, - Z3_OP_ROTATE_RIGHT, - Z3_OP_EXT_ROTATE_LEFT, - Z3_OP_EXT_ROTATE_RIGHT, - Z3_OP_INT2BV, - Z3_OP_BV2INT, - Z3_OP_CARRY, - Z3_OP_XOR3, - Z3_OP_PR_UNDEF, - Z3_OP_PR_TRUE, - Z3_OP_PR_ASSERTED, - Z3_OP_PR_GOAL, - Z3_OP_PR_MODUS_PONENS, - Z3_OP_PR_REFLEXIVITY, - Z3_OP_PR_SYMMETRY, - Z3_OP_PR_TRANSITIVITY, - Z3_OP_PR_TRANSITIVITY_STAR, - Z3_OP_PR_MONOTONICITY, - Z3_OP_PR_QUANT_INTRO, - Z3_OP_PR_DISTRIBUTIVITY, - Z3_OP_PR_AND_ELIM, - Z3_OP_PR_NOT_OR_ELIM, - Z3_OP_PR_REWRITE, - Z3_OP_PR_REWRITE_STAR, - Z3_OP_PR_PULL_QUANT, - Z3_OP_PR_PULL_QUANT_STAR, - Z3_OP_PR_PUSH_QUANT, - Z3_OP_PR_ELIM_UNUSED_VARS, - Z3_OP_PR_DER, - Z3_OP_PR_QUANT_INST, - Z3_OP_PR_HYPOTHESIS, - Z3_OP_PR_LEMMA, - Z3_OP_PR_UNIT_RESOLUTION, - Z3_OP_PR_IFF_TRUE, - Z3_OP_PR_IFF_FALSE, - Z3_OP_PR_COMMUTATIVITY, - Z3_OP_PR_DEF_AXIOM, - Z3_OP_PR_DEF_INTRO, - Z3_OP_PR_APPLY_DEF, - Z3_OP_PR_IFF_OEQ, - Z3_OP_PR_NNF_POS, - Z3_OP_PR_NNF_NEG, - Z3_OP_PR_NNF_STAR, - Z3_OP_PR_CNF_STAR, - Z3_OP_PR_SKOLEMIZE, - Z3_OP_PR_MODUS_PONENS_OEQ, - Z3_OP_PR_TH_LEMMA, - Z3_OP_PR_HYPER_RESOLVE, - Z3_OP_RA_STORE, - Z3_OP_RA_EMPTY, - Z3_OP_RA_IS_EMPTY, - Z3_OP_RA_JOIN, - Z3_OP_RA_UNION, - Z3_OP_RA_WIDEN, - Z3_OP_RA_PROJECT, - Z3_OP_RA_FILTER, - Z3_OP_RA_NEGATION_FILTER, - Z3_OP_RA_RENAME, - Z3_OP_RA_COMPLEMENT, - Z3_OP_RA_SELECT, - Z3_OP_RA_CLONE, - Z3_OP_FD_LT, - Z3_OP_LABEL, - Z3_OP_LABEL_LIT, - Z3_OP_DT_CONSTRUCTOR, - Z3_OP_DT_RECOGNISER, - Z3_OP_DT_ACCESSOR, - Z3_OP_UNINTERPRETED, -}; - -void camlidl_ml2c_z3_Z3_decl_kind(value _v1, Z3_decl_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_6[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_decl_kind(Z3_decl_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_6, 152, "typedef Z3_decl_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_7[7] = { - Z3_PK_UINT, - Z3_PK_BOOL, - Z3_PK_DOUBLE, - Z3_PK_SYMBOL, - Z3_PK_STRING, - Z3_PK_OTHER, - Z3_PK_INVALID, -}; - -void camlidl_ml2c_z3_Z3_param_kind(value _v1, Z3_param_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_7[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_param_kind(Z3_param_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_7, 7, "typedef Z3_param_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_8[4] = { - Z3_PRINT_SMTLIB_FULL, - Z3_PRINT_LOW_LEVEL, - Z3_PRINT_SMTLIB_COMPLIANT, - Z3_PRINT_SMTLIB2_COMPLIANT, -}; - -void camlidl_ml2c_z3_Z3_ast_print_mode(value _v1, Z3_ast_print_mode * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_8[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_ast_print_mode(Z3_ast_print_mode * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_PRINT_SMTLIB_FULL: _v1 = Val_int(0); break; - case Z3_PRINT_LOW_LEVEL: _v1 = Val_int(1); break; - case Z3_PRINT_SMTLIB_COMPLIANT: _v1 = Val_int(2); break; - case Z3_PRINT_SMTLIB2_COMPLIANT: _v1 = Val_int(3); break; - default: invalid_argument("typedef Z3_ast_print_mode: bad enum value"); - } - return _v1; -} - -int camlidl_transl_table_z3_enum_9[13] = { - Z3_OK, - Z3_SORT_ERROR, - Z3_IOB, - Z3_INVALID_ARG, - Z3_PARSER_ERROR, - Z3_NO_PARSER, - Z3_INVALID_PATTERN, - Z3_MEMOUT_FAIL, - Z3_FILE_ACCESS_ERROR, - Z3_INTERNAL_FATAL, - Z3_INVALID_USAGE, - Z3_DEC_REF_ERROR, - Z3_EXCEPTION, -}; - -void camlidl_ml2c_z3_Z3_error_code(value _v1, Z3_error_code * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_9[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_error_code(Z3_error_code * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_9, 13, "typedef Z3_error_code: bad enum value"); - return _v1; -} - - -/* All contexts share the same handler */ -static value caml_z3_error_handler = 0; - - -value camlidl_c2ml_z3_Z3_error_code(Z3_error_code * _c2, camlidl_ctx _ctx); -/* Error checking routine that raises OCaml Error exceptions */ -void check_error_code (Z3_context c) -{ - static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - value* exn_tag = NULL; - value ctx_err[2]; - Z3_error_code e; - e = Z3_get_error_code(c); - if (e != Z3_OK) { - ctx_err[0] = c2ml_Z3_context(&c); - ctx_err[1] = camlidl_c2ml_z3_Z3_error_code(&e, &_ctxs); - exn_tag = caml_named_value("Z3.Error"); - if (*exn_tag == 0) { - fprintf(stderr, "Z3.Error not found"); - exit(1); - } - caml_raise_with_args(*exn_tag, 2, ctx_err); - } -} -/* Disable default error handler, all error checking is done by check_error_code */ -void* error_handler_static = NULL; - -int camlidl_transl_table_z3_enum_10[4] = { - Z3_GOAL_PRECISE, - Z3_GOAL_UNDER, - Z3_GOAL_OVER, - Z3_GOAL_UNDER_OVER, -}; - -void camlidl_ml2c_z3_Z3_goal_prec(value _v1, Z3_goal_prec * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_10[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_goal_prec(Z3_goal_prec * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_GOAL_PRECISE: _v1 = Val_int(0); break; - case Z3_GOAL_UNDER: _v1 = Val_int(1); break; - case Z3_GOAL_OVER: _v1 = Val_int(2); break; - case Z3_GOAL_UNDER_OVER: _v1 = Val_int(3); break; - default: invalid_argument("typedef Z3_goal_prec: bad enum value"); - } - return _v1; -} - - -value caml_z3_mk_context(value key_val_list) -{ - CAMLparam1( key_val_list ); - CAMLlocal4( item, vkey, vval, _vres ); - char * ckey; - char * cval; - Z3_config cfg; - Z3_context _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - cfg = Z3_mk_config(); - while (key_val_list != Val_emptylist) - { - item = Field(key_val_list, 0); - vkey = Field(item, 0); - vval = Field(item, 1); - ckey = camlidl_malloc_string(vkey, _ctx); - cval = camlidl_malloc_string(vval, _ctx); - Z3_set_param_value(cfg, ckey, cval); - key_val_list = Field(key_val_list, 1); - } - _res = Z3_mk_context_rc(cfg); - Z3_del_config(cfg); - _vres = camlidl_c2ml_z3_Z3_context(&_res, _ctx); - camlidl_free(_ctx); - Z3_set_error_handler(_res, error_handler_static); - CAMLreturn(_vres); -} - -value camlidl_z3_Z3_update_param_value( - value _v_c, - value _v_param_id, - value _v_param_value) -{ - Z3_context c; /*in*/ - Z3_string param_id; /*in*/ - Z3_string param_value; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_param_id, ¶m_id, _ctx); - camlidl_ml2c_z3_Z3_string(_v_param_value, ¶m_value, _ctx); - Z3_update_param_value(c, param_id, param_value); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_get_param_value( - value _v_c, - value _v_param_id) -{ - Z3_context c; /*in*/ - Z3_string param_id; /*in*/ - Z3_string *param_value; /*out*/ - Z3_string _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_param_id, ¶m_id, _ctx); - param_value = &_c1; - Z3_get_param_value(c, param_id, param_value); - if (param_value == NULL) { - _vres = Val_int(0); - } else { - _v2 = camlidl_c2ml_z3_Z3_string(&*param_value, _ctx); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_interrupt( - value _v_c) -{ - Z3_context c; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - Z3_interrupt(c); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_mk_params( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_params _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_params(c); - _vres = camlidl_c2ml_z3_Z3_params(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_params_set_bool( - value _v_c, - value _v_p, - value _v_k, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_symbol k; /*in*/ - int v; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_k, &k, _ctx); - v = Int_val(_v_v); - Z3_params_set_bool(c, p, k, v); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_params_set_uint( - value _v_c, - value _v_p, - value _v_k, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_symbol k; /*in*/ - unsigned int v; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_k, &k, _ctx); - v = Int_val(_v_v); - Z3_params_set_uint(c, p, k, v); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_params_set_double( - value _v_c, - value _v_p, - value _v_k, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_symbol k; /*in*/ - double v; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_k, &k, _ctx); - v = Double_val(_v_v); - Z3_params_set_double(c, p, k, v); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_params_set_symbol( - value _v_c, - value _v_p, - value _v_k, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_symbol k; /*in*/ - Z3_symbol v; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_k, &k, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_v, &v, _ctx); - Z3_params_set_symbol(c, p, k, v); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_params_to_string( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - _res = Z3_params_to_string(c, p); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_params_validate( - value _v_c, - value _v_p, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_params p; /*in*/ - Z3_param_descrs d; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_param_descrs(_v_d, &d, _ctx); - Z3_params_validate(c, p, d); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_param_descrs_get_kind( - value _v_c, - value _v_p, - value _v_n) -{ - Z3_context c; /*in*/ - Z3_param_descrs p; /*in*/ - Z3_symbol n; /*in*/ - Z3_param_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_param_descrs(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_n, &n, _ctx); - _res = Z3_param_descrs_get_kind(c, p, n); - _vres = camlidl_c2ml_z3_Z3_param_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_param_descrs_size( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_param_descrs p; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_param_descrs(_v_p, &p, _ctx); - _res = Z3_param_descrs_size(c, p); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_param_descrs_get_name( - value _v_c, - value _v_p, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_param_descrs p; /*in*/ - unsigned int i; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_param_descrs(_v_p, &p, _ctx); - i = Int_val(_v_i); - _res = Z3_param_descrs_get_name(c, p, i); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_param_descrs_to_string( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_param_descrs p; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_param_descrs(_v_p, &p, _ctx); - _res = Z3_param_descrs_to_string(c, p); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int_symbol( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - int i; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_mk_int_symbol(c, i); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_string_symbol( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_string s; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_s, &s, _ctx); - _res = Z3_mk_string_symbol(c, s); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_uninterpreted_sort( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_mk_uninterpreted_sort(c, s); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bool_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_bool_sort(c); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_int_sort(c); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_real_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_real_sort(c); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bv_sort( - value _v_c, - value _v_sz) -{ - Z3_context c; /*in*/ - unsigned int sz; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - sz = Int_val(_v_sz); - _res = Z3_mk_bv_sort(c, sz); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_finite_domain_sort( - value _v_c, - value _v_name, - value _v_size) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned long long size; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - size = Int64_val(_v_size); - _res = Z3_mk_finite_domain_sort(c, name, size); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_array_sort( - value _v_c, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_sort range; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_domain, &domain, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_array_sort(c, domain, range); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_tuple_sort( - value _v_c, - value _v_mk_tuple_name, - value _v_field_names, - value _v_field_sorts) -{ - Z3_context c; /*in*/ - Z3_symbol mk_tuple_name; /*in*/ - unsigned int num_fields; /*in*/ - Z3_symbol const *field_names; /*in*/ - Z3_sort const *field_sorts; /*in*/ - Z3_func_decl *mk_tuple_decl; /*out*/ - Z3_func_decl *proj_decl; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - Z3_func_decl _c7; - mlsize_t _c8; - value _v9; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_mk_tuple_name, &mk_tuple_name, _ctx); - _c1 = Wosize_val(_v_field_names); - field_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_field_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &field_names[_c2], _ctx); - } - num_fields = _c1; - _c4 = Wosize_val(_v_field_sorts); - field_sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_field_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &field_sorts[_c5], _ctx); - } - num_fields = _c4; - mk_tuple_decl = &_c7; - proj_decl = camlidl_malloc(num_fields * sizeof(Z3_func_decl ), _ctx); - _res = Z3_mk_tuple_sort(c, mk_tuple_name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decl); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3_Z3_func_decl(&*mk_tuple_decl, _ctx); - _vres[2] = camlidl_alloc(num_fields, 0); - Begin_root(_vres[2]) - for (_c8 = 0; _c8 < num_fields; _c8++) { - _v9 = camlidl_c2ml_z3_Z3_func_decl(&proj_decl[_c8], _ctx); - modify(&Field(_vres[2], _c8), _v9); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_mk_enumeration_sort( - value _v_c, - value _v_name, - value _v_enum_names) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned int n; /*in*/ - Z3_symbol const *enum_names; /*in*/ - Z3_func_decl *enum_consts; /*out*/ - Z3_func_decl *enum_testers; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - mlsize_t _c6; - value _v7; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - _c1 = Wosize_val(_v_enum_names); - enum_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_enum_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &enum_names[_c2], _ctx); - } - n = _c1; - enum_consts = camlidl_malloc(n * sizeof(Z3_func_decl ), _ctx); - enum_testers = camlidl_malloc(n * sizeof(Z3_func_decl ), _ctx); - _res = Z3_mk_enumeration_sort(c, name, n, enum_names, enum_consts, enum_testers); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_alloc(n, 0); - Begin_root(_vres[1]) - for (_c4 = 0; _c4 < n; _c4++) { - _v5 = camlidl_c2ml_z3_Z3_func_decl(&enum_consts[_c4], _ctx); - modify(&Field(_vres[1], _c4), _v5); - } - End_roots() - _vres[2] = camlidl_alloc(n, 0); - Begin_root(_vres[2]) - for (_c6 = 0; _c6 < n; _c6++) { - _v7 = camlidl_c2ml_z3_Z3_func_decl(&enum_testers[_c6], _ctx); - modify(&Field(_vres[2], _c6), _v7); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_mk_list_sort( - value _v_c, - value _v_name, - value _v_elem_sort) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - Z3_sort elem_sort; /*in*/ - Z3_func_decl *nil_decl; /*out*/ - Z3_func_decl *is_nil_decl; /*out*/ - Z3_func_decl *cons_decl; /*out*/ - Z3_func_decl *is_cons_decl; /*out*/ - Z3_func_decl *head_decl; /*out*/ - Z3_func_decl *tail_decl; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_func_decl _c1; - Z3_func_decl _c2; - Z3_func_decl _c3; - Z3_func_decl _c4; - Z3_func_decl _c5; - Z3_func_decl _c6; - value _vresult; - value _vres[7] = { 0, 0, 0, 0, 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_elem_sort, &elem_sort, _ctx); - nil_decl = &_c1; - is_nil_decl = &_c2; - cons_decl = &_c3; - is_cons_decl = &_c4; - head_decl = &_c5; - tail_decl = &_c6; - _res = Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl); - Begin_roots_block(_vres, 7) - _vres[0] = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3_Z3_func_decl(&*nil_decl, _ctx); - _vres[2] = camlidl_c2ml_z3_Z3_func_decl(&*is_nil_decl, _ctx); - _vres[3] = camlidl_c2ml_z3_Z3_func_decl(&*cons_decl, _ctx); - _vres[4] = camlidl_c2ml_z3_Z3_func_decl(&*is_cons_decl, _ctx); - _vres[5] = camlidl_c2ml_z3_Z3_func_decl(&*head_decl, _ctx); - _vres[6] = camlidl_c2ml_z3_Z3_func_decl(&*tail_decl, _ctx); - _vresult = camlidl_alloc_small(7, 0); - { mlsize_t _c7; - for (_c7 = 0; _c7 < 7; _c7++) Field(_vresult, _c7) = _vres[_c7]; - } - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_mk_constructor( - value _v_c, - value _v_name, - value _v_recognizer, - value _v_field_names, - value _v_sorts, - value _v_sort_refs) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - Z3_symbol recognizer; /*in*/ - unsigned int num_fields; /*in*/ - Z3_symbol const *field_names; /*in*/ - Z3_sort_opt const *sorts; /*in*/ - unsigned int *sort_refs; /*in*/ - Z3_constructor _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_recognizer, &recognizer, _ctx); - _c1 = Wosize_val(_v_field_names); - field_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_field_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &field_names[_c2], _ctx); - } - num_fields = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort_opt const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort_opt(_v6, &sorts[_c5], _ctx); - } - num_fields = _c4; - _c7 = Wosize_val(_v_sort_refs); - sort_refs = camlidl_malloc(_c7 * sizeof(unsigned int ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_sort_refs, _c8); - sort_refs[_c8] = Int_val(_v9); - } - num_fields = _c7; - _res = Z3_mk_constructor(c, name, recognizer, num_fields, field_names, sorts, sort_refs); - _vres = camlidl_c2ml_z3_Z3_constructor(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_constructor_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_constructor(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_del_constructor( - value _v_c, - value _v_constr) -{ - Z3_context c; /*in*/ - Z3_constructor constr; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_constructor(_v_constr, &constr, _ctx); - Z3_del_constructor(c, constr); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_mk_datatype( - value _v_c, - value _v_name, - value _v_constructors) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned int num_constructors; /*in*/ - Z3_constructor *constructors; /*in,out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - _c1 = Wosize_val(_v_constructors); - constructors = camlidl_malloc(_c1 * sizeof(Z3_constructor ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_constructors, _c2); - camlidl_ml2c_z3_Z3_constructor(_v3, &constructors[_c2], _ctx); - } - num_constructors = _c1; - _res = Z3_mk_datatype(c, name, num_constructors, constructors); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_alloc(num_constructors, 0); - Begin_root(_vres[1]) - for (_c4 = 0; _c4 < num_constructors; _c4++) { - _v5 = camlidl_c2ml_z3_Z3_constructor(&constructors[_c4], _ctx); - modify(&Field(_vres[1], _c4), _v5); - } - End_roots() - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_mk_constructor_list( - value _v_c, - value _v_constructors) -{ - Z3_context c; /*in*/ - unsigned int num_constructors; /*in*/ - Z3_constructor const *constructors; /*in*/ - Z3_constructor_list _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_constructors); - constructors = camlidl_malloc(_c1 * sizeof(Z3_constructor const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_constructors, _c2); - camlidl_ml2c_z3_Z3_constructor(_v3, &constructors[_c2], _ctx); - } - num_constructors = _c1; - _res = Z3_mk_constructor_list(c, num_constructors, constructors); - _vres = camlidl_c2ml_z3_Z3_constructor_list(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_del_constructor_list( - value _v_c, - value _v_clist) -{ - Z3_context c; /*in*/ - Z3_constructor_list clist; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_constructor_list(_v_clist, &clist, _ctx); - Z3_del_constructor_list(c, clist); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_mk_datatypes( - value _v_c, - value _v_sort_names, - value _v_constructor_lists) -{ - Z3_context c; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort *sorts; /*out*/ - Z3_constructor_list *constructor_lists; /*in,out*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - value _v8; - mlsize_t _c9; - value _v10; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_constructor_lists); - constructor_lists = camlidl_malloc(_c4 * sizeof(Z3_constructor_list ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_constructor_lists, _c5); - camlidl_ml2c_z3_Z3_constructor_list(_v6, &constructor_lists[_c5], _ctx); - } - num_sorts = _c4; - sorts = camlidl_malloc(num_sorts * sizeof(Z3_sort ), _ctx); - Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_alloc(num_sorts, 0); - Begin_root(_vres[0]) - for (_c7 = 0; _c7 < num_sorts; _c7++) { - _v8 = camlidl_c2ml_z3_Z3_sort(&sorts[_c7], _ctx); - modify(&Field(_vres[0], _c7), _v8); - } - End_roots() - _vres[1] = camlidl_alloc(num_sorts, 0); - Begin_root(_vres[1]) - for (_c9 = 0; _c9 < num_sorts; _c9++) { - _v10 = camlidl_c2ml_z3_Z3_constructor_list(&constructor_lists[_c9], _ctx); - modify(&Field(_vres[1], _c9), _v10); - } - End_roots() - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_query_constructor( - value _v_c, - value _v_constr, - value _v_num_fields) -{ - Z3_context c; /*in*/ - Z3_constructor constr; /*in*/ - unsigned int num_fields; /*in*/ - Z3_func_decl *constructor; /*out*/ - Z3_func_decl *tester; /*out*/ - Z3_func_decl *accessors; /*out*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_func_decl _c1; - Z3_func_decl _c2; - mlsize_t _c3; - value _v4; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_constructor(_v_constr, &constr, _ctx); - num_fields = Int_val(_v_num_fields); - constructor = &_c1; - tester = &_c2; - accessors = camlidl_malloc(num_fields * sizeof(Z3_func_decl ), _ctx); - Z3_query_constructor(c, constr, num_fields, constructor, tester, accessors); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3_Z3_func_decl(&*constructor, _ctx); - _vres[1] = camlidl_c2ml_z3_Z3_func_decl(&*tester, _ctx); - _vres[2] = camlidl_alloc(num_fields, 0); - Begin_root(_vres[2]) - for (_c3 = 0; _c3 < num_fields; _c3++) { - _v4 = camlidl_c2ml_z3_Z3_func_decl(&accessors[_c3], _ctx); - modify(&Field(_vres[2], _c3), _v4); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_mk_func_decl( - value _v_c, - value _v_s, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_func_decl(c, s, domain_size, domain, range); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_app( - value _v_c, - value _v_d, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_app(c, d, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_const( - value _v_c, - value _v_s, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_const(c, s, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_fresh_func_decl( - value _v_c, - value _v_prefix, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_string prefix; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_prefix, &prefix, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_fresh_func_decl(c, prefix, domain_size, domain, range); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_fresh_const( - value _v_c, - value _v_prefix, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_string prefix; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_prefix, &prefix, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_fresh_const(c, prefix, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_true( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_true(c); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_false( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_false(c); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_eq( - value _v_c, - value _v_l, - value _v_r) -{ - Z3_context c; /*in*/ - Z3_ast l; /*in*/ - Z3_ast r; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_l, &l, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_r, &r, _ctx); - _res = Z3_mk_eq(c, l, r); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_distinct( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_distinct(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_not( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_mk_not(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_ite( - value _v_c, - value _v_t1, - value _v_t2, - value _v_t3) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast t3; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t3, &t3, _ctx); - _res = Z3_mk_ite(c, t1, t2, t3); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_iff( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_iff(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_implies( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_implies(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_xor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_xor(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_and( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_and(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_or( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_or(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_add( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_add(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_mul( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_mul(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_sub( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_sub(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_unary_minus( - value _v_c, - value _v_arg) -{ - Z3_context c; /*in*/ - Z3_ast arg; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg, &arg, _ctx); - _res = Z3_mk_unary_minus(c, arg); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_div( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_div(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_mod( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_mod(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_rem( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_rem(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_power( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_power(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_lt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_lt(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_le( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_le(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_gt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_gt(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_ge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ge(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int2real( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_int2real(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_real2int( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_real2int(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_is_int( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_is_int(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvnot( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvnot(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvredand( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvredand(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvredor( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvredor(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvand( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvand(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvor(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvxor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvxor(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvnand( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvnand(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvnor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvnor(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvxnor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvxnor(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvneg( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvneg(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvadd( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvadd(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsub( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsub(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvmul( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvmul(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvudiv( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvudiv(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsdiv( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsdiv(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvurem( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvurem(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsrem( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsrem(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsmod( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsmod(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvult( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvult(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvslt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvslt(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvule( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvule(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsle( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsle(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvuge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvuge(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsge(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvugt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvugt(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsgt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsgt(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_concat( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_concat(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_extract( - value _v_c, - value _v_high, - value _v_low, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int high; /*in*/ - unsigned int low; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - high = Int_val(_v_high); - low = Int_val(_v_low); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_extract(c, high, low, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_sign_ext( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_sign_ext(c, i, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_zero_ext( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_zero_ext(c, i, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_repeat( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_repeat(c, i, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvshl( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvshl(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvlshr( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvlshr(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvashr( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvashr(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_rotate_left( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_rotate_left(c, i, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_rotate_right( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_rotate_right(c, i, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_ext_rotate_left( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ext_rotate_left(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_ext_rotate_right( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ext_rotate_right(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int2bv( - value _v_c, - value _v_n, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int n; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - n = Int_val(_v_n); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_int2bv(c, n, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bv2int( - value _v_c, - value _v_t1, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bv2int(c, t1, is_signed); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvadd_no_overflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvadd_no_overflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvadd_no_underflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvadd_no_underflow(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsub_no_overflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsub_no_overflow(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsub_no_underflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvsub_no_underflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvsdiv_no_overflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsdiv_no_overflow(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvneg_no_overflow( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvneg_no_overflow(c, t1); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvmul_no_overflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvmul_no_overflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bvmul_no_underflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvmul_no_underflow(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_select( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_i, &i, _ctx); - _res = Z3_mk_select(c, a, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_store( - value _v_c, - value _v_a, - value _v_i, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast i; /*in*/ - Z3_ast v; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_i, &i, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - _res = Z3_mk_store(c, a, i, v); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_const_array( - value _v_c, - value _v_domain, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast v; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_domain, &domain, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - _res = Z3_mk_const_array(c, domain, v); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_map( - value _v_c, - value _v_f, - value _v_n, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - unsigned int n; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - Z3_ast _c1; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - n = Int_val(_v_n); - args = &_c1; - camlidl_ml2c_z3_Z3_ast(_v_args, &_c1, _ctx); - _res = Z3_mk_map(c, f, n, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_array_default( - value _v_c, - value _v_array) -{ - Z3_context c; /*in*/ - Z3_ast array; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_array, &array, _ctx); - _res = Z3_mk_array_default(c, array); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_sort( - value _v_c, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_sort ty; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_set_sort(c, ty); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_empty_set( - value _v_c, - value _v_domain) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_domain, &domain, _ctx); - _res = Z3_mk_empty_set(c, domain); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_full_set( - value _v_c, - value _v_domain) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_domain, &domain, _ctx); - _res = Z3_mk_full_set(c, domain); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_add( - value _v_c, - value _v_set, - value _v_elem) -{ - Z3_context c; /*in*/ - Z3_ast set; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_set, &set, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_elem, &elem, _ctx); - _res = Z3_mk_set_add(c, set, elem); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_del( - value _v_c, - value _v_set, - value _v_elem) -{ - Z3_context c; /*in*/ - Z3_ast set; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_set, &set, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_elem, &elem, _ctx); - _res = Z3_mk_set_del(c, set, elem); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_union( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_set_union(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_intersect( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_set_intersect(c, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_difference( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_set_difference(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_complement( - value _v_c, - value _v_arg) -{ - Z3_context c; /*in*/ - Z3_ast arg; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg, &arg, _ctx); - _res = Z3_mk_set_complement(c, arg); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_member( - value _v_c, - value _v_elem, - value _v_set) -{ - Z3_context c; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast set; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_elem, &elem, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_set, &set, _ctx); - _res = Z3_mk_set_member(c, elem, set); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_set_subset( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_set_subset(c, arg1, arg2); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_numeral( - value _v_c, - value _v_numeral, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_string numeral; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_numeral, &numeral, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_numeral(c, numeral, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_real( - value _v_c, - value _v_num, - value _v_den) -{ - Z3_context c; /*in*/ - int num; /*in*/ - int den; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - num = Int_val(_v_num); - den = Int_val(_v_den); - _res = Z3_mk_real(c, num, den); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int( - value _v_c, - value _v_v, - value _v_ty) -{ - Z3_context c; /*in*/ - int v; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - v = Int_val(_v_v); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_int(c, v, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_int64( - value _v_c, - value _v_v, - value _v_ty) -{ - Z3_context c; /*in*/ - long long v; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - v = Int64_val(_v_v); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_int64(c, v, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_pattern( - value _v_c, - value _v_terms) -{ - Z3_context c; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_ast const *terms; /*in*/ - Z3_pattern _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_terms); - terms = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_terms, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &terms[_c2], _ctx); - } - num_patterns = _c1; - _res = Z3_mk_pattern(c, num_patterns, terms); - _vres = camlidl_c2ml_z3_Z3_pattern(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_bound( - value _v_c, - value _v_index, - value _v_ty) -{ - Z3_context c; /*in*/ - unsigned int index; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - index = Int_val(_v_index); - camlidl_ml2c_z3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_bound(c, index, ty); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_forall( - value _v_c, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_forall(c, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_forall_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_forall(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_mk_exists( - value _v_c, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_exists(c, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_exists_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_exists(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_mk_quantifier( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_quantifier(c, is_forall, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_quantifier_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_quantifier(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); -} - -value camlidl_z3_Z3_mk_quantifier_ex( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_quantifier_id, - value _v_skolem_id, - value _v_patterns, - value _v_no_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - Z3_symbol quantifier_id; /*in*/ - Z3_symbol skolem_id; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_no_patterns; /*in*/ - Z3_ast const *no_patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - camlidl_ml2c_z3_Z3_symbol(_v_quantifier_id, &quantifier_id, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_skolem_id, &skolem_id, _ctx); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_no_patterns); - no_patterns = camlidl_malloc(_c4 * sizeof(Z3_ast const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_no_patterns, _c5); - camlidl_ml2c_z3_Z3_ast(_v6, &no_patterns[_c5], _ctx); - } - num_no_patterns = _c4; - _c7 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c7 * sizeof(Z3_sort const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_sorts, _c8); - camlidl_ml2c_z3_Z3_sort(_v9, &sorts[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c10 * sizeof(Z3_symbol const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decl_names, _c11); - camlidl_ml2c_z3_Z3_symbol(_v12, &decl_names[_c11], _ctx); - } - num_decls = _c10; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = 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); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_quantifier_ex_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_quantifier_ex(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); -} - -value camlidl_z3_Z3_mk_forall_const( - value _v_c, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_forall_const(c, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_exists_const( - value _v_c, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_exists_const(c, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_quantifier_const( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_quantifier_const(c, is_forall, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_quantifier_const_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_quantifier_const(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_mk_quantifier_const_ex( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_quantifier_id, - value _v_skolem_id, - value _v_bound, - value _v_patterns, - value _v_no_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - Z3_symbol quantifier_id; /*in*/ - Z3_symbol skolem_id; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_no_patterns; /*in*/ - Z3_ast const *no_patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - camlidl_ml2c_z3_Z3_symbol(_v_quantifier_id, &quantifier_id, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_skolem_id, &skolem_id, _ctx); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - _c7 = Wosize_val(_v_no_patterns); - no_patterns = camlidl_malloc(_c7 * sizeof(Z3_ast const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_no_patterns, _c8); - camlidl_ml2c_z3_Z3_ast(_v9, &no_patterns[_c8], _ctx); - } - num_no_patterns = _c7; - camlidl_ml2c_z3_Z3_ast(_v_body, &body, _ctx); - _res = 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); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_quantifier_const_ex_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_mk_quantifier_const_ex(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); -} - -value camlidl_z3_Z3_get_symbol_kind( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_symbol_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_kind(c, s); - _vres = camlidl_c2ml_z3_Z3_symbol_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_symbol_int( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_int(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_symbol_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_string(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_sort_name( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_sort d; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_d, &d, _ctx); - _res = Z3_get_sort_name(c, d); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_sort_id( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_get_sort_id(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_sort_to_ast( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_sort_to_ast(c, s); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_eq_sort( - value _v_c, - value _v_s1, - value _v_s2) -{ - Z3_context c; /*in*/ - Z3_sort s1; /*in*/ - Z3_sort s2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s1, &s1, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s2, &s2, _ctx); - _res = Z3_is_eq_sort(c, s1, s2); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_sort_kind( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_sort_kind(c, t); - _vres = camlidl_c2ml_z3_Z3_sort_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_bv_sort_size( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_bv_sort_size(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_finite_domain_sort_size( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned long long *r; /*out*/ - unsigned long long _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - r = &_c1; - Z3_get_finite_domain_sort_size(c, s, r); - if (r == NULL) { - _vres = Val_int(0); - } else { - _v2 = copy_int64(*r); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_array_sort_domain( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_array_sort_domain(c, t); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_array_sort_range( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_array_sort_range(c, t); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_tuple_sort_mk_decl( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_tuple_sort_mk_decl(c, t); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_tuple_sort_num_fields( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_tuple_sort_num_fields(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_tuple_sort_field_decl( - value _v_c, - value _v_t, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - i = Int_val(_v_i); - _res = Z3_get_tuple_sort_field_decl(c, t, i); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_datatype_sort_num_constructors( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_datatype_sort_num_constructors(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_datatype_sort_constructor( - value _v_c, - value _v_t, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_datatype_sort_constructor(c, t, idx); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_datatype_sort_recognizer( - value _v_c, - value _v_t, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_datatype_sort_recognizer(c, t, idx); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_datatype_sort_constructor_accessor( - value _v_c, - value _v_t, - value _v_idx_c, - value _v_idx_a) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx_c; /*in*/ - unsigned int idx_a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_t, &t, _ctx); - idx_c = Int_val(_v_idx_c); - idx_a = Int_val(_v_idx_a); - _res = Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_relation_arity( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_get_relation_arity(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_relation_column( - value _v_c, - value _v_s, - value _v_col) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int col; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - col = Int_val(_v_col); - _res = Z3_get_relation_column(c, s, col); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_decl_to_ast( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - _res = Z3_func_decl_to_ast(c, f); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_eq_func_decl( - value _v_c, - value _v_f1, - value _v_f2) -{ - Z3_context c; /*in*/ - Z3_func_decl f1; /*in*/ - Z3_func_decl f2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f1, &f1, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f2, &f2, _ctx); - _res = Z3_is_eq_func_decl(c, f1, f2); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_func_decl_id( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - _res = Z3_get_func_decl_id(c, f); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_name( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_name(c, d); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_kind( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_decl_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_kind(c, d); - _vres = camlidl_c2ml_z3_Z3_decl_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_domain_size( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_domain_size(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_arity( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_arity(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_domain( - value _v_c, - value _v_d, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - i = Int_val(_v_i); - _res = Z3_get_domain(c, d, i); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_range( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_range(c, d); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_num_parameters( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_num_parameters(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_parameter_kind( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_parameter_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_parameter_kind(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_parameter_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_int_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_int_parameter(c, d, idx); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_double_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - double _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_double_parameter(c, d, idx); - _vres = copy_double(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_symbol_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_symbol_parameter(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_sort_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_sort_parameter(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_ast_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_ast_parameter(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_func_decl_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_func_decl_parameter(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_decl_rational_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_rational_parameter(c, d, idx); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_app_to_ast( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_app(_v_a, &a, _ctx); - _res = Z3_app_to_ast(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_app_decl( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_app(_v_a, &a, _ctx); - _res = Z3_get_app_decl(c, a); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_app_num_args( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_app(_v_a, &a, _ctx); - _res = Z3_get_app_num_args(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_app_arg( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_app(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_app_arg(c, a, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_eq_ast( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_is_eq_ast(c, t1, t2); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_ast_id( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_ast t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t, &t, _ctx); - _res = Z3_get_ast_id(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_ast_hash( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_ast_hash(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_sort( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_sort(c, a); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_well_sorted( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_ast t; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t, &t, _ctx); - _res = Z3_is_well_sorted(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_bool_value( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_lbool _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_bool_value(c, a); - _vres = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_ast_kind( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_ast_kind(c, a); - _vres = camlidl_c2ml_z3_Z3_ast_kind(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_app( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_app(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_numeral_ast( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_numeral_ast(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_algebraic_number( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_algebraic_number(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_to_app( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_app _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_to_app(c, a); - _vres = camlidl_c2ml_z3_Z3_app(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_to_func_decl( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_to_func_decl(c, a); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_numeral_string( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_numeral_string(c, a); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_numeral_decimal_string( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_numeral_decimal_string(c, a, precision); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_numerator( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_numerator(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_denominator( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_denominator(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_numeral_small( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - long long *num; /*out*/ - long long *den; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - long long _c2; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - num = &_c1; - den = &_c2; - _res = Z3_get_numeral_small(c, a, num, den); - Begin_roots_block(_vres, 3) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*num); - _vres[2] = copy_int64(*den); - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_get_numeral_int( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - int *i; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - int _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - i = &_c1; - _res = Z3_get_numeral_int(c, v, i); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = Val_int(*i); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_get_numeral_int64( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - long long *i; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - i = &_c1; - _res = Z3_get_numeral_int64(c, v, i); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*i); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_get_numeral_rational_int64( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - long long *num; /*out*/ - long long *den; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - long long _c2; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - num = &_c1; - den = &_c2; - _res = Z3_get_numeral_rational_int64(c, v, num, den); - Begin_roots_block(_vres, 3) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*num); - _vres[2] = copy_int64(*den); - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -value camlidl_z3_Z3_get_algebraic_number_lower( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_algebraic_number_lower(c, a, precision); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_algebraic_number_upper( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_algebraic_number_upper(c, a, precision); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_pattern_to_ast( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_pattern_to_ast(c, p); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_pattern_num_terms( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_get_pattern_num_terms(c, p); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_pattern( - value _v_c, - value _v_p, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_pattern(_v_p, &p, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_pattern(c, p, idx); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_index_value( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_index_value(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_quantifier_forall( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_quantifier_forall(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_weight( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_weight(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_num_patterns( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_patterns(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_pattern_ast( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_pattern _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_pattern_ast(c, a, i); - _vres = camlidl_c2ml_z3_Z3_pattern(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_num_no_patterns( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_no_patterns(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_no_pattern_ast( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_no_pattern_ast(c, a, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_num_bound( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_bound(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_bound_name( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_bound_name(c, a, i); - _vres = camlidl_c2ml_z3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_bound_sort( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_bound_sort(c, a, i); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_quantifier_body( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_body(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_simplify( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_simplify(c, a); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_simplify_ex( - value _v_c, - value _v_a, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_params p; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - _res = Z3_simplify_ex(c, a, p); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_simplify_get_help( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_simplify_get_help(c); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_simplify_get_param_descrs( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_param_descrs _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_simplify_get_param_descrs(c); - _vres = camlidl_c2ml_z3_Z3_param_descrs(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_update_term( - value _v_c, - value _v_a, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_update_term(c, a, num_args, args); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_substitute( - value _v_c, - value _v_a, - value _v_from, - value _v_to) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_exprs; /*in*/ - Z3_ast const *from; /*in*/ - Z3_ast const *to; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_from); - from = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_from, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &from[_c2], _ctx); - } - num_exprs = _c1; - _c4 = Wosize_val(_v_to); - to = camlidl_malloc(_c4 * sizeof(Z3_ast const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_to, _c5); - camlidl_ml2c_z3_Z3_ast(_v6, &to[_c5], _ctx); - } - num_exprs = _c4; - _res = Z3_substitute(c, a, num_exprs, from, to); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_substitute_vars( - value _v_c, - value _v_a, - value _v_to) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_exprs; /*in*/ - Z3_ast const *to; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_to); - to = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_to, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &to[_c2], _ctx); - } - num_exprs = _c1; - _res = Z3_substitute_vars(c, a, num_exprs, to); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_translate( - value _v_source, - value _v_a, - value _v_target) -{ - Z3_context source; /*in*/ - Z3_ast a; /*in*/ - Z3_context target; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_source, &source, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_context(_v_target, &target, _ctx); - _res = Z3_translate(source, a, target); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(source); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_eval( - value _v_c, - value _v_m, - value _v_t, - value _v_model_completion) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_ast t; /*in*/ - int model_completion; /*in*/ - Z3_ast *v; /*out*/ - Z3_ast _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_t, &t, _ctx); - model_completion = Int_val(_v_model_completion); - v = &_c1; - Z3_model_eval(c, m, t, model_completion, v); - if (v == NULL) { - _vres = Val_int(0); - } else { - _v2 = camlidl_c2ml_z3_Z3_ast(&*v, _ctx); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_const_interp( - value _v_c, - value _v_m, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_func_decl a; /*in*/ - Z3_ast_opt _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_a, &a, _ctx); - _res = Z3_model_get_const_interp(c, m, a); - _vres = camlidl_c2ml_z3_Z3_ast_opt(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_func_interp( - value _v_c, - value _v_m, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_func_decl f; /*in*/ - Z3_func_interp_opt _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - _res = Z3_model_get_func_interp(c, m, f); - _vres = camlidl_c2ml_z3_Z3_func_interp_opt(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_num_consts( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - _res = Z3_model_get_num_consts(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_const_decl( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_model_get_const_decl(c, m, i); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_num_funcs( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - _res = Z3_model_get_num_funcs(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_func_decl( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_model_get_func_decl(c, m, i); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_num_sorts( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - _res = Z3_model_get_num_sorts(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_sort( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_model_get_sort(c, m, i); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_get_sort_universe( - value _v_c, - value _v_m, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_sort s; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_model_get_sort_universe(c, m, s); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_is_as_array( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_as_array(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_as_array_func_decl( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_as_array_func_decl(c, a); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_interp_get_num_entries( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_interp f; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_interp(_v_f, &f, _ctx); - _res = Z3_func_interp_get_num_entries(c, f); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_interp_get_entry( - value _v_c, - value _v_f, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_func_interp f; /*in*/ - unsigned int i; /*in*/ - Z3_func_entry _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_interp(_v_f, &f, _ctx); - i = Int_val(_v_i); - _res = Z3_func_interp_get_entry(c, f, i); - _vres = camlidl_c2ml_z3_Z3_func_entry(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_interp_get_else( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_interp f; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_interp(_v_f, &f, _ctx); - _res = Z3_func_interp_get_else(c, f); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_interp_get_arity( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_interp f; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_interp(_v_f, &f, _ctx); - _res = Z3_func_interp_get_arity(c, f); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_entry_get_value( - value _v_c, - value _v_e) -{ - Z3_context c; /*in*/ - Z3_func_entry e; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_entry(_v_e, &e, _ctx); - _res = Z3_func_entry_get_value(c, e); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_entry_get_num_args( - value _v_c, - value _v_e) -{ - Z3_context c; /*in*/ - Z3_func_entry e; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_entry(_v_e, &e, _ctx); - _res = Z3_func_entry_get_num_args(c, e); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_entry_get_arg( - value _v_c, - value _v_e, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_func_entry e; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_entry(_v_e, &e, _ctx); - i = Int_val(_v_i); - _res = Z3_func_entry_get_arg(c, e, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_open_log( - value _v_filename) -{ - Z3_string filename; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_string(_v_filename, &filename, _ctx); - _res = Z3_open_log(filename); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3_Z3_append_log( - value _v_string) -{ - Z3_string string; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_string(_v_string, &string, _ctx); - Z3_append_log(string); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3_Z3_close_log(value _unit) -{ - Z3_close_log(); - return Val_unit; -} - -value camlidl_z3_Z3_toggle_warning_messages( - value _v_enabled) -{ - int enabled; /*in*/ - enabled = Int_val(_v_enabled); - Z3_toggle_warning_messages(enabled); - return Val_unit; -} - -value camlidl_z3_Z3_set_ast_print_mode( - value _v_c, - value _v_mode) -{ - Z3_context c; /*in*/ - Z3_ast_print_mode mode; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_print_mode(_v_mode, &mode, _ctx); - Z3_set_ast_print_mode(c, mode); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_to_string( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_ast_to_string(c, a); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_pattern_to_string( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_pattern_to_string(c, p); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_sort_to_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_sort_to_string(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_func_decl_to_string( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_func_decl_to_string(c, d); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_model_to_string( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - _res = Z3_model_to_string(c, m); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_benchmark_to_smtlib_string( - value _v_c, - value _v_name, - value _v_logic, - value _v_status, - value _v_attributes, - value _v_assumptions, - value _v_formula) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_string logic; /*in*/ - Z3_string status; /*in*/ - Z3_string attributes; /*in*/ - unsigned int num_assumptions; /*in*/ - Z3_ast const *assumptions; /*in*/ - Z3_ast formula; /*in*/ - Z3_string _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_name, &name, _ctx); - camlidl_ml2c_z3_Z3_string(_v_logic, &logic, _ctx); - camlidl_ml2c_z3_Z3_string(_v_status, &status, _ctx); - camlidl_ml2c_z3_Z3_string(_v_attributes, &attributes, _ctx); - _c1 = Wosize_val(_v_assumptions); - assumptions = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_assumptions, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &assumptions[_c2], _ctx); - } - num_assumptions = _c1; - camlidl_ml2c_z3_Z3_ast(_v_formula, &formula, _ctx); - _res = Z3_benchmark_to_smtlib_string(c, name, logic, status, attributes, num_assumptions, assumptions, formula); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_benchmark_to_smtlib_string_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_benchmark_to_smtlib_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); -} - -value camlidl_z3_Z3_parse_smtlib2_string( - value _v_c, - value _v_str, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_str, &str, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - _res = Z3_parse_smtlib2_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_parse_smtlib2_string_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_parse_smtlib2_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_parse_smtlib2_file( - value _v_c, - value _v_file_name, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_file_name, &file_name, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - _res = Z3_parse_smtlib2_file(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_parse_smtlib2_file_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_parse_smtlib2_file(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_parse_smtlib_string( - value _v_c, - value _v_str, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_str, &str, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_parse_smtlib_string_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_parse_smtlib_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_parse_smtlib_file( - value _v_c, - value _v_file_name, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_file_name, &file_name, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_parse_smtlib_file_bytecode(value * argv, int argn) -{ - return camlidl_z3_Z3_parse_smtlib_file(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3_Z3_get_smtlib_num_formulas( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_formulas(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_formula( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_formula(c, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_num_assumptions( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_assumptions(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_assumption( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_assumption(c, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_num_decls( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_decls(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_decl( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_decl(c, i); - _vres = camlidl_c2ml_z3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_num_sorts( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_sorts(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_sort( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_sort(c, i); - _vres = camlidl_c2ml_z3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_smtlib_error( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_error(c); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_set_error( - value _v_c, - value _v_e) -{ - Z3_context c; /*in*/ - Z3_error_code e; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_error_code(_v_e, &e, _ctx); - Z3_set_error(c, e); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_get_error_msg_ex( - value _v_c, - value _v_err) -{ - Z3_context c; /*in*/ - Z3_error_code err; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_error_code(_v_err, &err, _ctx); - _res = Z3_get_error_msg_ex(c, err); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_version(value _unit) -{ - unsigned int *major; /*out*/ - unsigned int *minor; /*out*/ - unsigned int *build_number; /*out*/ - unsigned int *revision_number; /*out*/ - unsigned int _c1; - unsigned int _c2; - unsigned int _c3; - unsigned int _c4; - value _vresult; - value _vres[4] = { 0, 0, 0, 0, }; - - major = &_c1; - minor = &_c2; - build_number = &_c3; - revision_number = &_c4; - Z3_get_version(major, minor, build_number, revision_number); - Begin_roots_block(_vres, 4) - _vres[0] = Val_int(*major); - _vres[1] = Val_int(*minor); - _vres[2] = Val_int(*build_number); - _vres[3] = Val_int(*revision_number); - _vresult = camlidl_alloc_small(4, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - Field(_vresult, 3) = _vres[3]; - End_roots() - return _vresult; -} - -value camlidl_z3_Z3_enable_trace( - value _v_tag) -{ - Z3_string tag; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_string(_v_tag, &tag, _ctx); - Z3_enable_trace(tag); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3_Z3_disable_trace( - value _v_tag) -{ - Z3_string tag; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_string(_v_tag, &tag, _ctx); - Z3_disable_trace(tag); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3_Z3_mk_fixedpoint( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_fixedpoint _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_fixedpoint(c); - _vres = camlidl_c2ml_z3_Z3_fixedpoint(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_add_rule( - value _v_c, - value _v_d, - value _v_rule, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_ast rule; /*in*/ - Z3_symbol name; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_rule, &rule, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - Z3_fixedpoint_add_rule(c, d, rule, name); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_add_fact( - value _v_c, - value _v_d, - value _v_r, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_func_decl r; /*in*/ - unsigned int num_args; /*in*/ - unsigned int *args; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_r, &r, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(unsigned int ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - args[_c2] = Int_val(_v3); - } - num_args = _c1; - Z3_fixedpoint_add_fact(c, d, r, num_args, args); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_assert( - value _v_c, - value _v_d, - value _v_axiom) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_ast axiom; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_axiom, &axiom, _ctx); - Z3_fixedpoint_assert(c, d, axiom); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_query( - value _v_c, - value _v_d, - value _v_query) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_ast query; /*in*/ - Z3_lbool _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_query, &query, _ctx); - _res = Z3_fixedpoint_query(c, d, query); - _vres = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_query_relations( - value _v_c, - value _v_d, - value _v_relations) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - unsigned int num_relations; /*in*/ - Z3_func_decl const *relations; /*in*/ - Z3_lbool _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - _c1 = Wosize_val(_v_relations); - relations = camlidl_malloc(_c1 * sizeof(Z3_func_decl const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_relations, _c2); - camlidl_ml2c_z3_Z3_func_decl(_v3, &relations[_c2], _ctx); - } - num_relations = _c1; - _res = Z3_fixedpoint_query_relations(c, d, num_relations, relations); - _vres = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_get_answer( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - _res = Z3_fixedpoint_get_answer(c, d); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_get_reason_unknown( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - _res = Z3_fixedpoint_get_reason_unknown(c, d); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_update_rule( - value _v_c, - value _v_d, - value _v_a, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_ast a; /*in*/ - Z3_symbol name; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_name, &name, _ctx); - Z3_fixedpoint_update_rule(c, d, a, name); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_get_num_levels( - value _v_c, - value _v_d, - value _v_pred) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_func_decl pred; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_pred, &pred, _ctx); - _res = Z3_fixedpoint_get_num_levels(c, d, pred); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_get_cover_delta( - value _v_c, - value _v_d, - value _v_level, - value _v_pred) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - int level; /*in*/ - Z3_func_decl pred; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - level = Int_val(_v_level); - camlidl_ml2c_z3_Z3_func_decl(_v_pred, &pred, _ctx); - _res = Z3_fixedpoint_get_cover_delta(c, d, level, pred); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_add_cover( - value _v_c, - value _v_d, - value _v_level, - value _v_pred, - value _v_property) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - int level; /*in*/ - Z3_func_decl pred; /*in*/ - Z3_ast property; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - level = Int_val(_v_level); - camlidl_ml2c_z3_Z3_func_decl(_v_pred, &pred, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_property, &property, _ctx); - Z3_fixedpoint_add_cover(c, d, level, pred, property); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_get_statistics( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_stats _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - _res = Z3_fixedpoint_get_statistics(c, d); - _vres = camlidl_c2ml_z3_Z3_stats(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_register_relation( - value _v_c, - value _v_d, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_func_decl f; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - Z3_fixedpoint_register_relation(c, d, f); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_set_predicate_representation( - value _v_c, - value _v_d, - value _v_f, - value _v_relation_kinds) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - Z3_func_decl f; /*in*/ - unsigned int num_relations; /*in*/ - Z3_symbol const *relation_kinds; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - camlidl_ml2c_z3_Z3_func_decl(_v_f, &f, _ctx); - _c1 = Wosize_val(_v_relation_kinds); - relation_kinds = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_relation_kinds, _c2); - camlidl_ml2c_z3_Z3_symbol(_v3, &relation_kinds[_c2], _ctx); - } - num_relations = _c1; - Z3_fixedpoint_set_predicate_representation(c, d, f, num_relations, relation_kinds); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_get_rules( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _res = Z3_fixedpoint_get_rules(c, f); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_get_assertions( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _res = Z3_fixedpoint_get_assertions(c, f); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_set_params( - value _v_c, - value _v_f, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_params p; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - Z3_fixedpoint_set_params(c, f, p); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_get_help( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _res = Z3_fixedpoint_get_help(c, f); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_get_param_descrs( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_param_descrs _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _res = Z3_fixedpoint_get_param_descrs(c, f); - _vres = camlidl_c2ml_z3_Z3_param_descrs(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_to_string( - value _v_c, - value _v_f, - value _v_queries) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - unsigned int num_queries; /*in*/ - Z3_ast *queries; /*in*/ - Z3_string _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _c1 = Wosize_val(_v_queries); - queries = camlidl_malloc(_c1 * sizeof(Z3_ast ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_queries, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &queries[_c2], _ctx); - } - num_queries = _c1; - _res = Z3_fixedpoint_to_string(c, f, num_queries, queries); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_from_string( - value _v_c, - value _v_f, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_string s; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - camlidl_ml2c_z3_Z3_string(_v_s, &s, _ctx); - _res = Z3_fixedpoint_from_string(c, f, s); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_from_file( - value _v_c, - value _v_f, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_fixedpoint f; /*in*/ - Z3_string s; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - camlidl_ml2c_z3_Z3_string(_v_s, &s, _ctx); - _res = Z3_fixedpoint_from_file(c, f, s); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_fixedpoint_push( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - Z3_fixedpoint_push(c, d); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_fixedpoint_pop( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_fixedpoint d; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_fixedpoint(_v_d, &d, _ctx); - Z3_fixedpoint_pop(c, d); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_mk_ast_vector( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_ast_vector(c); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_vector_size( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - _res = Z3_ast_vector_size(c, v); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_vector_get( - value _v_c, - value _v_v, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - i = Int_val(_v_i); - _res = Z3_ast_vector_get(c, v, i); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_vector_set( - value _v_c, - value _v_v, - value _v_i, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - unsigned int i; /*in*/ - Z3_ast a; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - Z3_ast_vector_set(c, v, i, a); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_vector_resize( - value _v_c, - value _v_v, - value _v_n) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - unsigned int n; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - n = Int_val(_v_n); - Z3_ast_vector_resize(c, v, n); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_vector_push( - value _v_c, - value _v_v, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - Z3_ast a; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - Z3_ast_vector_push(c, v, a); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_vector_translate( - value _v_s, - value _v_v, - value _v_t) -{ - Z3_context s; /*in*/ - Z3_ast_vector v; /*in*/ - Z3_context t; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_s, &s, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - camlidl_ml2c_z3_Z3_context(_v_t, &t, _ctx); - _res = Z3_ast_vector_translate(s, v, t); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(s); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_vector_to_string( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast_vector v; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_vector(_v_v, &v, _ctx); - _res = Z3_ast_vector_to_string(c, v); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_ast_map( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast_map _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_ast_map(c); - _vres = camlidl_c2ml_z3_Z3_ast_map(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_map_contains( - value _v_c, - value _v_m, - value _v_k) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_ast k; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_k, &k, _ctx); - _res = Z3_ast_map_contains(c, m, k); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_map_find( - value _v_c, - value _v_m, - value _v_k) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_ast k; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_k, &k, _ctx); - _res = Z3_ast_map_find(c, m, k); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_map_insert( - value _v_c, - value _v_m, - value _v_k, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_ast k; /*in*/ - Z3_ast v; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_k, &k, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_v, &v, _ctx); - Z3_ast_map_insert(c, m, k, v); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_map_erase( - value _v_c, - value _v_m, - value _v_k) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_ast k; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_k, &k, _ctx); - Z3_ast_map_erase(c, m, k); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_map_reset( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - Z3_ast_map_reset(c, m); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_ast_map_size( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - _res = Z3_ast_map_size(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_map_keys( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - _res = Z3_ast_map_keys(c, m); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_ast_map_to_string( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_ast_map m; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_ast_map(_v_m, &m, _ctx); - _res = Z3_ast_map_to_string(c, m); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_goal( - value _v_c, - value _v_models, - value _v_unsat_cores, - value _v_proofs) -{ - Z3_context c; /*in*/ - int models; /*in*/ - int unsat_cores; /*in*/ - int proofs; /*in*/ - Z3_goal _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - models = Int_val(_v_models); - unsat_cores = Int_val(_v_unsat_cores); - proofs = Int_val(_v_proofs); - _res = Z3_mk_goal(c, models, unsat_cores, proofs); - _vres = camlidl_c2ml_z3_Z3_goal(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_precision( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - Z3_goal_prec _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_precision(c, g); - _vres = camlidl_c2ml_z3_Z3_goal_prec(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_assert( - value _v_c, - value _v_g, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - Z3_ast a; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - Z3_goal_assert(c, g, a); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_goal_inconsistent( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_inconsistent(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_depth( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_depth(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_reset( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - Z3_goal_reset(c, g); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_goal_size( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_size(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_formula( - value _v_c, - value _v_g, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - idx = Int_val(_v_idx); - _res = Z3_goal_formula(c, g, idx); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_num_exprs( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_num_exprs(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_is_decided_sat( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_is_decided_sat(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_is_decided_unsat( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_is_decided_unsat(c, g); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_translate( - value _v_source, - value _v_g, - value _v_target) -{ - Z3_context source; /*in*/ - Z3_goal g; /*in*/ - Z3_context target; /*in*/ - Z3_goal _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_source, &source, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - camlidl_ml2c_z3_Z3_context(_v_target, &target, _ctx); - _res = Z3_goal_translate(source, g, target); - _vres = camlidl_c2ml_z3_Z3_goal(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(source); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_goal_to_string( - value _v_c, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_goal g; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_goal_to_string(c, g); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_tactic( - value _v_c, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_name, &name, _ctx); - _res = Z3_mk_tactic(c, name); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_probe( - value _v_c, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_name, &name, _ctx); - _res = Z3_mk_probe(c, name); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_and_then( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_tactic t1; /*in*/ - Z3_tactic t2; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t2, &t2, _ctx); - _res = Z3_tactic_and_then(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_or_else( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_tactic t1; /*in*/ - Z3_tactic t2; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t2, &t2, _ctx); - _res = Z3_tactic_or_else(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_par_or( - value _v_c, - value _v_ts) -{ - Z3_context c; /*in*/ - unsigned int num; /*in*/ - Z3_tactic const *ts; /*in*/ - Z3_tactic _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_ts); - ts = camlidl_malloc(_c1 * sizeof(Z3_tactic const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_ts, _c2); - camlidl_ml2c_z3_Z3_tactic(_v3, &ts[_c2], _ctx); - } - num = _c1; - _res = Z3_tactic_par_or(c, num, ts); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_par_and_then( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_tactic t1; /*in*/ - Z3_tactic t2; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t2, &t2, _ctx); - _res = Z3_tactic_par_and_then(c, t1, t2); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_try_for( - value _v_c, - value _v_t, - value _v_ms) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - unsigned int ms; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - ms = Int_val(_v_ms); - _res = Z3_tactic_try_for(c, t, ms); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_when( - value _v_c, - value _v_p, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_probe p; /*in*/ - Z3_tactic t; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - _res = Z3_tactic_when(c, p, t); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_cond( - value _v_c, - value _v_p, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_probe p; /*in*/ - Z3_tactic t1; /*in*/ - Z3_tactic t2; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t1, &t1, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t2, &t2, _ctx); - _res = Z3_tactic_cond(c, p, t1, t2); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_repeat( - value _v_c, - value _v_t, - value _v_max) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - unsigned int max; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - max = Int_val(_v_max); - _res = Z3_tactic_repeat(c, t, max); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_skip( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_tactic_skip(c); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_fail( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_tactic_fail(c); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_fail_if( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_probe p; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p, &p, _ctx); - _res = Z3_tactic_fail_if(c, p); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_fail_if_not_decided( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_tactic_fail_if_not_decided(c); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_using_params( - value _v_c, - value _v_t, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_params p; /*in*/ - Z3_tactic _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - _res = Z3_tactic_using_params(c, t, p); - _vres = camlidl_c2ml_z3_Z3_tactic(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_const( - value _v_x, - value _v_val) -{ - Z3_context x; /*in*/ - double val; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - val = Double_val(_v_val); - _res = Z3_probe_const(x, val); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_lt( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_lt(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_gt( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_gt(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_le( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_le(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_ge( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_ge(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_eq( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_eq(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_and( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_and(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_or( - value _v_x, - value _v_p1, - value _v_p2) -{ - Z3_context x; /*in*/ - Z3_probe p1; /*in*/ - Z3_probe p2; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p1, &p1, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p2, &p2, _ctx); - _res = Z3_probe_or(x, p1, p2); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_not( - value _v_x, - value _v_p) -{ - Z3_context x; /*in*/ - Z3_probe p; /*in*/ - Z3_probe _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_x, &x, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p, &p, _ctx); - _res = Z3_probe_not(x, p); - _vres = camlidl_c2ml_z3_Z3_probe(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(x); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_num_tactics( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_num_tactics(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_tactic_name( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_tactic_name(c, i); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_num_probes( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_num_probes(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_probe_name( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_probe_name(c, i); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_get_help( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - _res = Z3_tactic_get_help(c, t); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_get_param_descrs( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_param_descrs _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - _res = Z3_tactic_get_param_descrs(c, t); - _vres = camlidl_c2ml_z3_Z3_param_descrs(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_get_descr( - value _v_c, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_name, &name, _ctx); - _res = Z3_tactic_get_descr(c, name); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_get_descr( - value _v_c, - value _v_name) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_name, &name, _ctx); - _res = Z3_probe_get_descr(c, name); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_probe_apply( - value _v_c, - value _v_p, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_probe p; /*in*/ - Z3_goal g; /*in*/ - double _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_probe(_v_p, &p, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_probe_apply(c, p, g); - _vres = copy_double(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_apply( - value _v_c, - value _v_t, - value _v_g) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_goal g; /*in*/ - Z3_apply_result _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - _res = Z3_tactic_apply(c, t, g); - _vres = camlidl_c2ml_z3_Z3_apply_result(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_tactic_apply_ex( - value _v_c, - value _v_t, - value _v_g, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_goal g; /*in*/ - Z3_params p; /*in*/ - Z3_apply_result _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - camlidl_ml2c_z3_Z3_goal(_v_g, &g, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - _res = Z3_tactic_apply_ex(c, t, g, p); - _vres = camlidl_c2ml_z3_Z3_apply_result(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_apply_result_to_string( - value _v_c, - value _v_r) -{ - Z3_context c; /*in*/ - Z3_apply_result r; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_apply_result(_v_r, &r, _ctx); - _res = Z3_apply_result_to_string(c, r); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_apply_result_get_num_subgoals( - value _v_c, - value _v_r) -{ - Z3_context c; /*in*/ - Z3_apply_result r; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_apply_result(_v_r, &r, _ctx); - _res = Z3_apply_result_get_num_subgoals(c, r); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_apply_result_get_subgoal( - value _v_c, - value _v_r, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_apply_result r; /*in*/ - unsigned int i; /*in*/ - Z3_goal _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_apply_result(_v_r, &r, _ctx); - i = Int_val(_v_i); - _res = Z3_apply_result_get_subgoal(c, r, i); - _vres = camlidl_c2ml_z3_Z3_goal(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_apply_result_convert_model( - value _v_c, - value _v_r, - value _v_i, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_apply_result r; /*in*/ - unsigned int i; /*in*/ - Z3_model m; /*in*/ - Z3_model _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_apply_result(_v_r, &r, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3_Z3_model(_v_m, &m, _ctx); - _res = Z3_apply_result_convert_model(c, r, i, m); - _vres = camlidl_c2ml_z3_Z3_model(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_solver( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_solver _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_solver(c); - _vres = camlidl_c2ml_z3_Z3_solver(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_simple_solver( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_solver _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_simple_solver(c); - _vres = camlidl_c2ml_z3_Z3_solver(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_solver_for_logic( - value _v_c, - value _v_logic) -{ - Z3_context c; /*in*/ - Z3_symbol logic; /*in*/ - Z3_solver _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_symbol(_v_logic, &logic, _ctx); - _res = Z3_mk_solver_for_logic(c, logic); - _vres = camlidl_c2ml_z3_Z3_solver(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_mk_solver_from_tactic( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_tactic t; /*in*/ - Z3_solver _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_tactic(_v_t, &t, _ctx); - _res = Z3_mk_solver_from_tactic(c, t); - _vres = camlidl_c2ml_z3_Z3_solver(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_help( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_help(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_param_descrs( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_param_descrs _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_param_descrs(c, s); - _vres = camlidl_c2ml_z3_Z3_param_descrs(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_set_params( - value _v_c, - value _v_s, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_params p; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - camlidl_ml2c_z3_Z3_params(_v_p, &p, _ctx); - Z3_solver_set_params(c, s, p); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_push( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - Z3_solver_push(c, s); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_pop( - value _v_c, - value _v_s, - value _v_n) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - unsigned int n; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - n = Int_val(_v_n); - Z3_solver_pop(c, s, n); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_reset( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - Z3_solver_reset(c, s); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_get_num_scopes( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_num_scopes(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_assert( - value _v_c, - value _v_s, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_ast a; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - Z3_solver_assert(c, s, a); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_assert_and_track( - value _v_c, - value _v_s, - value _v_a, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_ast a; /*in*/ - Z3_ast p; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3_Z3_ast(_v_p, &p, _ctx); - Z3_solver_assert_and_track(c, s, a, p); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return Val_unit; -} - -value camlidl_z3_Z3_solver_get_assertions( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_assertions(c, s); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_check( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_lbool _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_check(c, s); - _vres = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_check_assumptions( - value _v_c, - value _v_s, - value _v_assumptions) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - unsigned int num_assumptions; /*in*/ - Z3_ast const *assumptions; /*in*/ - Z3_lbool _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _c1 = Wosize_val(_v_assumptions); - assumptions = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_assumptions, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &assumptions[_c2], _ctx); - } - num_assumptions = _c1; - _res = Z3_solver_check_assumptions(c, s, num_assumptions, assumptions); - _vres = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_model( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_model _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_model(c, s); - _vres = camlidl_c2ml_z3_Z3_model(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_proof( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_proof(c, s); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_unsat_core( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_ast_vector _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_unsat_core(c, s); - _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_reason_unknown( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_reason_unknown(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_get_statistics( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_stats _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_get_statistics(c, s); - _vres = camlidl_c2ml_z3_Z3_stats(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_solver_to_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _res = Z3_solver_to_string(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_to_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - _res = Z3_stats_to_string(c, s); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_size( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - _res = Z3_stats_size(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_get_key( - value _v_c, - value _v_s, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int idx; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - idx = Int_val(_v_idx); - _res = Z3_stats_get_key(c, s, idx); - _vres = camlidl_c2ml_z3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_is_uint( - value _v_c, - value _v_s, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int idx; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - idx = Int_val(_v_idx); - _res = Z3_stats_is_uint(c, s, idx); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_is_double( - value _v_c, - value _v_s, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int idx; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - idx = Int_val(_v_idx); - _res = Z3_stats_is_double(c, s, idx); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_get_uint_value( - value _v_c, - value _v_s, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int idx; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - idx = Int_val(_v_idx); - _res = Z3_stats_get_uint_value(c, s, idx); - _vres = Val_int(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_stats_get_double_value( - value _v_c, - value _v_s, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_stats s; /*in*/ - unsigned int idx; /*in*/ - double _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_stats(_v_s, &s, _ctx); - idx = Int_val(_v_idx); - _res = Z3_stats_get_double_value(c, s, idx); - _vres = copy_double(_res); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_get_implied_equalities( - value _v_c, - value _v_s, - value _v_terms) -{ - Z3_context c; /*in*/ - Z3_solver s; /*in*/ - unsigned int num_terms; /*in*/ - Z3_ast const *terms; /*in*/ - unsigned int *class_ids; /*out*/ - Z3_lbool _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); - _c1 = Wosize_val(_v_terms); - terms = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_terms, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &terms[_c2], _ctx); - } - num_terms = _c1; - class_ids = camlidl_malloc(num_terms * sizeof(unsigned int ), _ctx); - _res = Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); - _vres[1] = camlidl_alloc(num_terms, 0); - for (_c4 = 0; _c4 < num_terms; _c4++) { - _v5 = Val_int(class_ids[_c4]); - modify(&Field(_vres[1], _c4), _v5); - } - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vresult; -} - -void camlidl_ml2c_z3V3_Z3_symbol(value _v1, Z3_symbol * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_symbol *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_symbol(Z3_symbol * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_symbol) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_symbol *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_literals(value _v1, Z3_literals * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_literals *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_literals(Z3_literals * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_literals) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_literals *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_theory(value _v1, Z3_theory * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_theory *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_theory(Z3_theory * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_theory) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_theory *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_config(value _v1, Z3_config * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_config *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_config(Z3_config * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_config) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_config *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_context(value _v1, Z3_context * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_context *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_context(Z3_context * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_context) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_context *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_sort(value _v1, Z3_sort * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_sort *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_sort(Z3_sort * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_sort) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_sort *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_func_decl(value _v1, Z3_func_decl * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_func_decl *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_func_decl(Z3_func_decl * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_func_decl) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_func_decl *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_ast(value _v1, Z3_ast * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_ast *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_ast(Z3_ast * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_ast) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_ast *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_app(value _v1, Z3_app * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_app *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_app(Z3_app * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_app) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_app *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_pattern(value _v1, Z3_pattern * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_pattern *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_pattern(Z3_pattern * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_pattern) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_pattern *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_model(value _v1, Z3_model * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_model *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_model(Z3_model * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_model) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_model *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_constructor(value _v1, Z3_constructor * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_constructor *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_constructor(Z3_constructor * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_constructor) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_constructor *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_constructor_list(value _v1, Z3_constructor_list * _c2, camlidl_ctx _ctx) -{ - *_c2 = *((Z3_constructor_list *) Bp_val(_v1)); -} - -value camlidl_c2ml_z3V3_Z3_constructor_list(Z3_constructor_list * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_alloc((sizeof(Z3_constructor_list) + sizeof(value) - 1) / sizeof(value), Abstract_tag); - *((Z3_constructor_list *) Bp_val(_v1)) = *_c2; - return _v1; -} - -void camlidl_ml2c_z3V3_Z3_string(value _v1, Z3_string * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_malloc_string(_v1, _ctx); -} - -value camlidl_c2ml_z3V3_Z3_string(Z3_string * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = copy_string((*_c2)); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_1[3] = { - Z3_L_FALSE, - Z3_L_UNDEF, - Z3_L_TRUE, -}; - -void camlidl_ml2c_z3V3_Z3_lbool(value _v1, Z3_lbool * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_1[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_lbool(Z3_lbool * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_L_FALSE: _v1 = Val_int(0); break; - case Z3_L_UNDEF: _v1 = Val_int(1); break; - case Z3_L_TRUE: _v1 = Val_int(2); break; - default: invalid_argument("typedef Z3_lbool: bad enum value"); - } - return _v1; -} - -int camlidl_transl_table_z3V3_enum_2[2] = { - Z3_INT_SYMBOL, - Z3_STRING_SYMBOL, -}; - -void camlidl_ml2c_z3V3_Z3_symbol_kind(value _v1, Z3_symbol_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_2[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_symbol_kind(Z3_symbol_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_INT_SYMBOL: _v1 = Val_int(0); break; - case Z3_STRING_SYMBOL: _v1 = Val_int(1); break; - default: invalid_argument("typedef Z3_symbol_kind: bad enum value"); - } - return _v1; -} - -int camlidl_transl_table_z3V3_enum_3[7] = { - Z3_PARAMETER_INT, - Z3_PARAMETER_DOUBLE, - Z3_PARAMETER_RATIONAL, - Z3_PARAMETER_SYMBOL, - Z3_PARAMETER_SORT, - Z3_PARAMETER_AST, - Z3_PARAMETER_FUNC_DECL, -}; - -void camlidl_ml2c_z3V3_Z3_parameter_kind(value _v1, Z3_parameter_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_3[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_parameter_kind(Z3_parameter_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_3, 7, "typedef Z3_parameter_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_4[10] = { - Z3_UNINTERPRETED_SORT, - Z3_BOOL_SORT, - Z3_INT_SORT, - Z3_REAL_SORT, - Z3_BV_SORT, - Z3_ARRAY_SORT, - Z3_DATATYPE_SORT, - Z3_RELATION_SORT, - Z3_FINITE_DOMAIN_SORT, - Z3_UNKNOWN_SORT, -}; - -void camlidl_ml2c_z3V3_Z3_sort_kind(value _v1, Z3_sort_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_4[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_sort_kind(Z3_sort_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_4, 10, "typedef Z3_sort_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_5[7] = { - Z3_NUMERAL_AST, - Z3_APP_AST, - Z3_VAR_AST, - Z3_QUANTIFIER_AST, - Z3_SORT_AST, - Z3_FUNC_DECL_AST, - Z3_UNKNOWN_AST, -}; - -void camlidl_ml2c_z3V3_Z3_ast_kind(value _v1, Z3_ast_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_5[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_ast_kind(Z3_ast_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_5, 7, "typedef Z3_ast_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_6[152] = { - Z3_OP_TRUE, - Z3_OP_FALSE, - Z3_OP_EQ, - Z3_OP_DISTINCT, - Z3_OP_ITE, - Z3_OP_AND, - Z3_OP_OR, - Z3_OP_IFF, - Z3_OP_XOR, - Z3_OP_NOT, - Z3_OP_IMPLIES, - Z3_OP_OEQ, - Z3_OP_ANUM, - Z3_OP_AGNUM, - Z3_OP_LE, - Z3_OP_GE, - Z3_OP_LT, - Z3_OP_GT, - Z3_OP_ADD, - Z3_OP_SUB, - Z3_OP_UMINUS, - Z3_OP_MUL, - Z3_OP_DIV, - Z3_OP_IDIV, - Z3_OP_REM, - Z3_OP_MOD, - Z3_OP_TO_REAL, - Z3_OP_TO_INT, - Z3_OP_IS_INT, - Z3_OP_POWER, - Z3_OP_STORE, - Z3_OP_SELECT, - Z3_OP_CONST_ARRAY, - Z3_OP_ARRAY_MAP, - Z3_OP_ARRAY_DEFAULT, - Z3_OP_SET_UNION, - Z3_OP_SET_INTERSECT, - Z3_OP_SET_DIFFERENCE, - Z3_OP_SET_COMPLEMENT, - Z3_OP_SET_SUBSET, - Z3_OP_AS_ARRAY, - Z3_OP_BNUM, - Z3_OP_BIT1, - Z3_OP_BIT0, - Z3_OP_BNEG, - Z3_OP_BADD, - Z3_OP_BSUB, - Z3_OP_BMUL, - Z3_OP_BSDIV, - Z3_OP_BUDIV, - Z3_OP_BSREM, - Z3_OP_BUREM, - Z3_OP_BSMOD, - Z3_OP_BSDIV0, - Z3_OP_BUDIV0, - Z3_OP_BSREM0, - Z3_OP_BUREM0, - Z3_OP_BSMOD0, - Z3_OP_ULEQ, - Z3_OP_SLEQ, - Z3_OP_UGEQ, - Z3_OP_SGEQ, - Z3_OP_ULT, - Z3_OP_SLT, - Z3_OP_UGT, - Z3_OP_SGT, - Z3_OP_BAND, - Z3_OP_BOR, - Z3_OP_BNOT, - Z3_OP_BXOR, - Z3_OP_BNAND, - Z3_OP_BNOR, - Z3_OP_BXNOR, - Z3_OP_CONCAT, - Z3_OP_SIGN_EXT, - Z3_OP_ZERO_EXT, - Z3_OP_EXTRACT, - Z3_OP_REPEAT, - Z3_OP_BREDOR, - Z3_OP_BREDAND, - Z3_OP_BCOMP, - Z3_OP_BSHL, - Z3_OP_BLSHR, - Z3_OP_BASHR, - Z3_OP_ROTATE_LEFT, - Z3_OP_ROTATE_RIGHT, - Z3_OP_EXT_ROTATE_LEFT, - Z3_OP_EXT_ROTATE_RIGHT, - Z3_OP_INT2BV, - Z3_OP_BV2INT, - Z3_OP_CARRY, - Z3_OP_XOR3, - Z3_OP_PR_UNDEF, - Z3_OP_PR_TRUE, - Z3_OP_PR_ASSERTED, - Z3_OP_PR_GOAL, - Z3_OP_PR_MODUS_PONENS, - Z3_OP_PR_REFLEXIVITY, - Z3_OP_PR_SYMMETRY, - Z3_OP_PR_TRANSITIVITY, - Z3_OP_PR_TRANSITIVITY_STAR, - Z3_OP_PR_MONOTONICITY, - Z3_OP_PR_QUANT_INTRO, - Z3_OP_PR_DISTRIBUTIVITY, - Z3_OP_PR_AND_ELIM, - Z3_OP_PR_NOT_OR_ELIM, - Z3_OP_PR_REWRITE, - Z3_OP_PR_REWRITE_STAR, - Z3_OP_PR_PULL_QUANT, - Z3_OP_PR_PULL_QUANT_STAR, - Z3_OP_PR_PUSH_QUANT, - Z3_OP_PR_ELIM_UNUSED_VARS, - Z3_OP_PR_DER, - Z3_OP_PR_QUANT_INST, - Z3_OP_PR_HYPOTHESIS, - Z3_OP_PR_LEMMA, - Z3_OP_PR_UNIT_RESOLUTION, - Z3_OP_PR_IFF_TRUE, - Z3_OP_PR_IFF_FALSE, - Z3_OP_PR_COMMUTATIVITY, - Z3_OP_PR_DEF_AXIOM, - Z3_OP_PR_DEF_INTRO, - Z3_OP_PR_APPLY_DEF, - Z3_OP_PR_IFF_OEQ, - Z3_OP_PR_NNF_POS, - Z3_OP_PR_NNF_NEG, - Z3_OP_PR_NNF_STAR, - Z3_OP_PR_CNF_STAR, - Z3_OP_PR_SKOLEMIZE, - Z3_OP_PR_MODUS_PONENS_OEQ, - Z3_OP_PR_TH_LEMMA, - Z3_OP_PR_HYPER_RESOLVE, - Z3_OP_RA_STORE, - Z3_OP_RA_EMPTY, - Z3_OP_RA_IS_EMPTY, - Z3_OP_RA_JOIN, - Z3_OP_RA_UNION, - Z3_OP_RA_WIDEN, - Z3_OP_RA_PROJECT, - Z3_OP_RA_FILTER, - Z3_OP_RA_NEGATION_FILTER, - Z3_OP_RA_RENAME, - Z3_OP_RA_COMPLEMENT, - Z3_OP_RA_SELECT, - Z3_OP_RA_CLONE, - Z3_OP_FD_LT, - Z3_OP_LABEL, - Z3_OP_LABEL_LIT, - Z3_OP_DT_CONSTRUCTOR, - Z3_OP_DT_RECOGNISER, - Z3_OP_DT_ACCESSOR, - Z3_OP_UNINTERPRETED, -}; - -void camlidl_ml2c_z3V3_Z3_decl_kind(value _v1, Z3_decl_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_6[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_decl_kind(Z3_decl_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_6, 152, "typedef Z3_decl_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_7[7] = { - Z3_PK_UINT, - Z3_PK_BOOL, - Z3_PK_DOUBLE, - Z3_PK_SYMBOL, - Z3_PK_STRING, - Z3_PK_OTHER, - Z3_PK_INVALID, -}; - -void camlidl_ml2c_z3V3_Z3_param_kind(value _v1, Z3_param_kind * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_7[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_param_kind(Z3_param_kind * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_7, 7, "typedef Z3_param_kind: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_8[8] = { - Z3_NO_FAILURE, - Z3_UNKNOWN, - Z3_TIMEOUT, - Z3_MEMOUT_WATERMARK, - Z3_CANCELED, - Z3_NUM_CONFLICTS, - Z3_THEORY, - Z3_QUANTIFIERS, -}; - -void camlidl_ml2c_z3V3_Z3_search_failure(value _v1, Z3_search_failure * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_8[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_search_failure(Z3_search_failure * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3V3_enum_8, 8, "typedef Z3_search_failure: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3V3_enum_9[4] = { - Z3_PRINT_SMTLIB_FULL, - Z3_PRINT_LOW_LEVEL, - Z3_PRINT_SMTLIB_COMPLIANT, - Z3_PRINT_SMTLIB2_COMPLIANT, -}; - -void camlidl_ml2c_z3V3_Z3_ast_print_mode(value _v1, Z3_ast_print_mode * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3V3_enum_9[Int_val(_v1)]; -} - -value camlidl_c2ml_z3V3_Z3_ast_print_mode(Z3_ast_print_mode * _c2, camlidl_ctx _ctx) -{ -value _v1; - switch((*_c2)) { - case Z3_PRINT_SMTLIB_FULL: _v1 = Val_int(0); break; - case Z3_PRINT_LOW_LEVEL: _v1 = Val_int(1); break; - case Z3_PRINT_SMTLIB_COMPLIANT: _v1 = Val_int(2); break; - case Z3_PRINT_SMTLIB2_COMPLIANT: _v1 = Val_int(3); break; - default: invalid_argument("typedef Z3_ast_print_mode: bad enum value"); - } - return _v1; -} - -value camlidl_z3V3_Z3_global_param_set( - value _v_param_id, - value _v_param_value) -{ - Z3_string param_id; /*in*/ - Z3_string param_value; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_value, ¶m_value, _ctx); - Z3_global_param_set(param_id, param_value); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_global_param_reset_all(value _unit) -{ - Z3_global_param_reset_all(); - return Val_unit; -} - -value camlidl_z3V3_Z3_global_param_get( - value _v_param_id) -{ - Z3_string param_id; /*in*/ - Z3_string *param_value; /*out*/ - Z3_string _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); - param_value = &_c1; - Z3_global_param_get(param_id, param_value); - if (param_value == NULL) { - _vres = Val_int(0); - } else { - _v2 = camlidl_c2ml_z3V3_Z3_string(&*param_value, _ctx); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_config(value _unit) -{ - Z3_config _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - _res = Z3_mk_config(); - _vres = camlidl_c2ml_z3V3_Z3_config(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_del_config( - value _v_c) -{ - Z3_config c; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_config(_v_c, &c, _ctx); - Z3_del_config(c); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_set_param_value( - value _v_c, - value _v_param_id, - value _v_param_value) -{ - Z3_config c; /*in*/ - Z3_string param_id; /*in*/ - Z3_string param_value; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_config(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_value, ¶m_value, _ctx); - Z3_set_param_value(c, param_id, param_value); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_mk_context( - value _v_c) -{ - Z3_config c; /*in*/ - Z3_context _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_config(_v_c, &c, _ctx); - _res = Z3_mk_context(c); - _vres = camlidl_c2ml_z3V3_Z3_context(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -Z3_set_error_handler(_res, (void*)caml_z3_error_handler); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3V3_Z3_del_context( - value _v_c) -{ - Z3_context c; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - Z3_del_context(c); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_update_param_value( - value _v_c, - value _v_param_id, - value _v_param_value) -{ - Z3_context c; /*in*/ - Z3_string param_id; /*in*/ - Z3_string param_value; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_value, ¶m_value, _ctx); - Z3_update_param_value(c, param_id, param_value); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_get_param_value( - value _v_c, - value _v_param_id) -{ - Z3_context c; /*in*/ - Z3_string param_id; /*in*/ - Z3_string *param_value; /*out*/ - Z3_string _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); - param_value = &_c1; - Z3_get_param_value(c, param_id, param_value); - if (param_value == NULL) { - _vres = Val_int(0); - } else { - _v2 = camlidl_c2ml_z3V3_Z3_string(&*param_value, _ctx); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int_symbol( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - int i; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_mk_int_symbol(c, i); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_string_symbol( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_string s; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_s, &s, _ctx); - _res = Z3_mk_string_symbol(c, s); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_uninterpreted_sort( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_mk_uninterpreted_sort(c, s); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bool_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_bool_sort(c); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_int_sort(c); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_real_sort( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_real_sort(c); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bv_sort( - value _v_c, - value _v_sz) -{ - Z3_context c; /*in*/ - unsigned int sz; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - sz = Int_val(_v_sz); - _res = Z3_mk_bv_sort(c, sz); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_finite_domain_sort( - value _v_c, - value _v_name, - value _v_size) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned long long size; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_name, &name, _ctx); - size = Int64_val(_v_size); - _res = Z3_mk_finite_domain_sort(c, name, size); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_array_sort( - value _v_c, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_sort range; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_domain, &domain, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_array_sort(c, domain, range); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_tuple_sort( - value _v_c, - value _v_mk_tuple_name, - value _v_field_names, - value _v_field_sorts) -{ - Z3_context c; /*in*/ - Z3_symbol mk_tuple_name; /*in*/ - unsigned int num_fields; /*in*/ - Z3_symbol const *field_names; /*in*/ - Z3_sort const *field_sorts; /*in*/ - Z3_func_decl *mk_tuple_decl; /*out*/ - Z3_func_decl *proj_decl; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - Z3_func_decl _c7; - mlsize_t _c8; - value _v9; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_mk_tuple_name, &mk_tuple_name, _ctx); - _c1 = Wosize_val(_v_field_names); - field_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_field_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &field_names[_c2], _ctx); - } - num_fields = _c1; - _c4 = Wosize_val(_v_field_sorts); - field_sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_field_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &field_sorts[_c5], _ctx); - } - num_fields = _c4; - mk_tuple_decl = &_c7; - proj_decl = camlidl_malloc(num_fields * sizeof(Z3_func_decl ), _ctx); - _res = Z3_mk_tuple_sort(c, mk_tuple_name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decl); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3V3_Z3_func_decl(&*mk_tuple_decl, _ctx); - _vres[2] = camlidl_alloc(num_fields, 0); - Begin_root(_vres[2]) - for (_c8 = 0; _c8 < num_fields; _c8++) { - _v9 = camlidl_c2ml_z3V3_Z3_func_decl(&proj_decl[_c8], _ctx); - modify(&Field(_vres[2], _c8), _v9); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_mk_enumeration_sort( - value _v_c, - value _v_name, - value _v_enum_names) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned int n; /*in*/ - Z3_symbol const *enum_names; /*in*/ - Z3_func_decl *enum_consts; /*out*/ - Z3_func_decl *enum_testers; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - mlsize_t _c6; - value _v7; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_name, &name, _ctx); - _c1 = Wosize_val(_v_enum_names); - enum_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_enum_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &enum_names[_c2], _ctx); - } - n = _c1; - enum_consts = camlidl_malloc(n * sizeof(Z3_func_decl ), _ctx); - enum_testers = camlidl_malloc(n * sizeof(Z3_func_decl ), _ctx); - _res = Z3_mk_enumeration_sort(c, name, n, enum_names, enum_consts, enum_testers); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_alloc(n, 0); - Begin_root(_vres[1]) - for (_c4 = 0; _c4 < n; _c4++) { - _v5 = camlidl_c2ml_z3V3_Z3_func_decl(&enum_consts[_c4], _ctx); - modify(&Field(_vres[1], _c4), _v5); - } - End_roots() - _vres[2] = camlidl_alloc(n, 0); - Begin_root(_vres[2]) - for (_c6 = 0; _c6 < n; _c6++) { - _v7 = camlidl_c2ml_z3V3_Z3_func_decl(&enum_testers[_c6], _ctx); - modify(&Field(_vres[2], _c6), _v7); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_mk_list_sort( - value _v_c, - value _v_name, - value _v_elem_sort) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - Z3_sort elem_sort; /*in*/ - Z3_func_decl *nil_decl; /*out*/ - Z3_func_decl *is_nil_decl; /*out*/ - Z3_func_decl *cons_decl; /*out*/ - Z3_func_decl *is_cons_decl; /*out*/ - Z3_func_decl *head_decl; /*out*/ - Z3_func_decl *tail_decl; /*out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_func_decl _c1; - Z3_func_decl _c2; - Z3_func_decl _c3; - Z3_func_decl _c4; - Z3_func_decl _c5; - Z3_func_decl _c6; - value _vresult; - value _vres[7] = { 0, 0, 0, 0, 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_name, &name, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_elem_sort, &elem_sort, _ctx); - nil_decl = &_c1; - is_nil_decl = &_c2; - cons_decl = &_c3; - is_cons_decl = &_c4; - head_decl = &_c5; - tail_decl = &_c6; - _res = Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl); - Begin_roots_block(_vres, 7) - _vres[0] = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3V3_Z3_func_decl(&*nil_decl, _ctx); - _vres[2] = camlidl_c2ml_z3V3_Z3_func_decl(&*is_nil_decl, _ctx); - _vres[3] = camlidl_c2ml_z3V3_Z3_func_decl(&*cons_decl, _ctx); - _vres[4] = camlidl_c2ml_z3V3_Z3_func_decl(&*is_cons_decl, _ctx); - _vres[5] = camlidl_c2ml_z3V3_Z3_func_decl(&*head_decl, _ctx); - _vres[6] = camlidl_c2ml_z3V3_Z3_func_decl(&*tail_decl, _ctx); - _vresult = camlidl_alloc_small(7, 0); - { mlsize_t _c7; - for (_c7 = 0; _c7 < 7; _c7++) Field(_vresult, _c7) = _vres[_c7]; - } - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_mk_constructor( - value _v_c, - value _v_name, - value _v_recognizer, - value _v_field_names, - value _v_sorts, - value _v_sort_refs) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - Z3_symbol recognizer; /*in*/ - unsigned int num_fields; /*in*/ - Z3_symbol const *field_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int *sort_refs; /*in*/ - Z3_constructor _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_name, &name, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_recognizer, &recognizer, _ctx); - _c1 = Wosize_val(_v_field_names); - field_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_field_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &field_names[_c2], _ctx); - } - num_fields = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_fields = _c4; - _c7 = Wosize_val(_v_sort_refs); - sort_refs = camlidl_malloc(_c7 * sizeof(unsigned int ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_sort_refs, _c8); - sort_refs[_c8] = Int_val(_v9); - } - num_fields = _c7; - _res = Z3_mk_constructor(c, name, recognizer, num_fields, field_names, sorts, sort_refs); - _vres = camlidl_c2ml_z3V3_Z3_constructor(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_constructor_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_constructor(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_del_constructor( - value _v_c, - value _v_constr) -{ - Z3_context c; /*in*/ - Z3_constructor constr; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_constructor(_v_constr, &constr, _ctx); - Z3_del_constructor(c, constr); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_mk_datatype( - value _v_c, - value _v_name, - value _v_constructors) -{ - Z3_context c; /*in*/ - Z3_symbol name; /*in*/ - unsigned int num_constructors; /*in*/ - Z3_constructor *constructors; /*in,out*/ - Z3_sort _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_name, &name, _ctx); - _c1 = Wosize_val(_v_constructors); - constructors = camlidl_malloc(_c1 * sizeof(Z3_constructor ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_constructors, _c2); - camlidl_ml2c_z3V3_Z3_constructor(_v3, &constructors[_c2], _ctx); - } - num_constructors = _c1; - _res = Z3_mk_datatype(c, name, num_constructors, constructors); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - _vres[1] = camlidl_alloc(num_constructors, 0); - Begin_root(_vres[1]) - for (_c4 = 0; _c4 < num_constructors; _c4++) { - _v5 = camlidl_c2ml_z3V3_Z3_constructor(&constructors[_c4], _ctx); - modify(&Field(_vres[1], _c4), _v5); - } - End_roots() - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_mk_constructor_list( - value _v_c, - value _v_constructors) -{ - Z3_context c; /*in*/ - unsigned int num_constructors; /*in*/ - Z3_constructor const *constructors; /*in*/ - Z3_constructor_list _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_constructors); - constructors = camlidl_malloc(_c1 * sizeof(Z3_constructor const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_constructors, _c2); - camlidl_ml2c_z3V3_Z3_constructor(_v3, &constructors[_c2], _ctx); - } - num_constructors = _c1; - _res = Z3_mk_constructor_list(c, num_constructors, constructors); - _vres = camlidl_c2ml_z3V3_Z3_constructor_list(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_del_constructor_list( - value _v_c, - value _v_clist) -{ - Z3_context c; /*in*/ - Z3_constructor_list clist; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_constructor_list(_v_clist, &clist, _ctx); - Z3_del_constructor_list(c, clist); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_mk_datatypes( - value _v_c, - value _v_sort_names, - value _v_constructor_lists) -{ - Z3_context c; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort *sorts; /*out*/ - Z3_constructor_list *constructor_lists; /*in,out*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - value _v8; - mlsize_t _c9; - value _v10; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_constructor_lists); - constructor_lists = camlidl_malloc(_c4 * sizeof(Z3_constructor_list ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_constructor_lists, _c5); - camlidl_ml2c_z3V3_Z3_constructor_list(_v6, &constructor_lists[_c5], _ctx); - } - num_sorts = _c4; - sorts = camlidl_malloc(num_sorts * sizeof(Z3_sort ), _ctx); - Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_alloc(num_sorts, 0); - Begin_root(_vres[0]) - for (_c7 = 0; _c7 < num_sorts; _c7++) { - _v8 = camlidl_c2ml_z3V3_Z3_sort(&sorts[_c7], _ctx); - modify(&Field(_vres[0], _c7), _v8); - } - End_roots() - _vres[1] = camlidl_alloc(num_sorts, 0); - Begin_root(_vres[1]) - for (_c9 = 0; _c9 < num_sorts; _c9++) { - _v10 = camlidl_c2ml_z3V3_Z3_constructor_list(&constructor_lists[_c9], _ctx); - modify(&Field(_vres[1], _c9), _v10); - } - End_roots() - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_query_constructor( - value _v_c, - value _v_constr, - value _v_num_fields) -{ - Z3_context c; /*in*/ - Z3_constructor constr; /*in*/ - unsigned int num_fields; /*in*/ - Z3_func_decl *constructor; /*out*/ - Z3_func_decl *tester; /*out*/ - Z3_func_decl *accessors; /*out*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_func_decl _c1; - Z3_func_decl _c2; - mlsize_t _c3; - value _v4; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_constructor(_v_constr, &constr, _ctx); - num_fields = Int_val(_v_num_fields); - constructor = &_c1; - tester = &_c2; - accessors = camlidl_malloc(num_fields * sizeof(Z3_func_decl ), _ctx); - Z3_query_constructor(c, constr, num_fields, constructor, tester, accessors); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_c2ml_z3V3_Z3_func_decl(&*constructor, _ctx); - _vres[1] = camlidl_c2ml_z3V3_Z3_func_decl(&*tester, _ctx); - _vres[2] = camlidl_alloc(num_fields, 0); - Begin_root(_vres[2]) - for (_c3 = 0; _c3 < num_fields; _c3++) { - _v4 = camlidl_c2ml_z3V3_Z3_func_decl(&accessors[_c3], _ctx); - modify(&Field(_vres[2], _c3), _v4); - } - End_roots() - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_mk_func_decl( - value _v_c, - value _v_s, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3V3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3V3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_func_decl(c, s, domain_size, domain, range); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_app( - value _v_c, - value _v_d, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_app(c, d, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_const( - value _v_c, - value _v_s, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_const(c, s, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_fresh_func_decl( - value _v_c, - value _v_prefix, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_string prefix; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_prefix, &prefix, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3V3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3V3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_fresh_func_decl(c, prefix, domain_size, domain, range); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_fresh_const( - value _v_c, - value _v_prefix, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_string prefix; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_prefix, &prefix, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_fresh_const(c, prefix, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_true( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_true(c); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_false( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_mk_false(c); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_eq( - value _v_c, - value _v_l, - value _v_r) -{ - Z3_context c; /*in*/ - Z3_ast l; /*in*/ - Z3_ast r; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_l, &l, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_r, &r, _ctx); - _res = Z3_mk_eq(c, l, r); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_distinct( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_distinct(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_not( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_mk_not(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_ite( - value _v_c, - value _v_t1, - value _v_t2, - value _v_t3) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast t3; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t3, &t3, _ctx); - _res = Z3_mk_ite(c, t1, t2, t3); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_iff( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_iff(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_implies( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_implies(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_xor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_xor(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_and( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_and(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_or( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_or(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_add( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_add(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_mul( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_mul(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_sub( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_sub(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_unary_minus( - value _v_c, - value _v_arg) -{ - Z3_context c; /*in*/ - Z3_ast arg; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg, &arg, _ctx); - _res = Z3_mk_unary_minus(c, arg); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_div( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_div(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_mod( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_mod(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_rem( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_rem(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_power( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_power(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_lt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_lt(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_le( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_le(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_gt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_gt(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_ge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ge(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int2real( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_int2real(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_real2int( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_real2int(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_is_int( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_is_int(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvnot( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvnot(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvredand( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvredand(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvredor( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvredor(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvand( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvand(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvor(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvxor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvxor(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvnand( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvnand(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvnor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvnor(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvxnor( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvxnor(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvneg( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvneg(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvadd( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvadd(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsub( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsub(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvmul( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvmul(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvudiv( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvudiv(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsdiv( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsdiv(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvurem( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvurem(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsrem( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsrem(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsmod( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsmod(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvult( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvult(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvslt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvslt(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvule( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvule(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsle( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsle(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvuge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvuge(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsge( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsge(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvugt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvugt(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsgt( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsgt(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_concat( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_concat(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_extract( - value _v_c, - value _v_high, - value _v_low, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int high; /*in*/ - unsigned int low; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - high = Int_val(_v_high); - low = Int_val(_v_low); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_extract(c, high, low, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_sign_ext( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_sign_ext(c, i, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_zero_ext( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_zero_ext(c, i, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_repeat( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_repeat(c, i, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvshl( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvshl(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvlshr( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvlshr(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvashr( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvashr(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_rotate_left( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_rotate_left(c, i, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_rotate_right( - value _v_c, - value _v_i, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_rotate_right(c, i, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_ext_rotate_left( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ext_rotate_left(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_ext_rotate_right( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_ext_rotate_right(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int2bv( - value _v_c, - value _v_n, - value _v_t1) -{ - Z3_context c; /*in*/ - unsigned int n; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - n = Int_val(_v_n); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_int2bv(c, n, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bv2int( - value _v_c, - value _v_t1, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bv2int(c, t1, is_signed); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvadd_no_overflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvadd_no_overflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvadd_no_underflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvadd_no_underflow(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsub_no_overflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsub_no_overflow(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsub_no_underflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvsub_no_underflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvsdiv_no_overflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvsdiv_no_overflow(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvneg_no_overflow( - value _v_c, - value _v_t1) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - _res = Z3_mk_bvneg_no_overflow(c, t1); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvmul_no_overflow( - value _v_c, - value _v_t1, - value _v_t2, - value _v_is_signed) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int is_signed; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - is_signed = Int_val(_v_is_signed); - _res = Z3_mk_bvmul_no_overflow(c, t1, t2, is_signed); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bvmul_no_underflow( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_mk_bvmul_no_underflow(c, t1, t2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_select( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_i, &i, _ctx); - _res = Z3_mk_select(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_store( - value _v_c, - value _v_a, - value _v_i, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast i; /*in*/ - Z3_ast v; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_i, &i, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - _res = Z3_mk_store(c, a, i, v); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_const_array( - value _v_c, - value _v_domain, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast v; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_domain, &domain, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - _res = Z3_mk_const_array(c, domain, v); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_map( - value _v_c, - value _v_f, - value _v_n, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - unsigned int n; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - Z3_ast _c1; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_f, &f, _ctx); - n = Int_val(_v_n); - args = &_c1; - camlidl_ml2c_z3V3_Z3_ast(_v_args, &_c1, _ctx); - _res = Z3_mk_map(c, f, n, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_array_default( - value _v_c, - value _v_array) -{ - Z3_context c; /*in*/ - Z3_ast array; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_array, &array, _ctx); - _res = Z3_mk_array_default(c, array); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_sort( - value _v_c, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_sort ty; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_set_sort(c, ty); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_empty_set( - value _v_c, - value _v_domain) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_domain, &domain, _ctx); - _res = Z3_mk_empty_set(c, domain); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_full_set( - value _v_c, - value _v_domain) -{ - Z3_context c; /*in*/ - Z3_sort domain; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_domain, &domain, _ctx); - _res = Z3_mk_full_set(c, domain); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_add( - value _v_c, - value _v_set, - value _v_elem) -{ - Z3_context c; /*in*/ - Z3_ast set; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_set, &set, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_elem, &elem, _ctx); - _res = Z3_mk_set_add(c, set, elem); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_del( - value _v_c, - value _v_set, - value _v_elem) -{ - Z3_context c; /*in*/ - Z3_ast set; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_set, &set, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_elem, &elem, _ctx); - _res = Z3_mk_set_del(c, set, elem); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_union( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_set_union(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_intersect( - value _v_c, - value _v_args) -{ - Z3_context c; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_mk_set_intersect(c, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_difference( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_set_difference(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_complement( - value _v_c, - value _v_arg) -{ - Z3_context c; /*in*/ - Z3_ast arg; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg, &arg, _ctx); - _res = Z3_mk_set_complement(c, arg); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_member( - value _v_c, - value _v_elem, - value _v_set) -{ - Z3_context c; /*in*/ - Z3_ast elem; /*in*/ - Z3_ast set; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_elem, &elem, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_set, &set, _ctx); - _res = Z3_mk_set_member(c, elem, set); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_set_subset( - value _v_c, - value _v_arg1, - value _v_arg2) -{ - Z3_context c; /*in*/ - Z3_ast arg1; /*in*/ - Z3_ast arg2; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg1, &arg1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_arg2, &arg2, _ctx); - _res = Z3_mk_set_subset(c, arg1, arg2); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_numeral( - value _v_c, - value _v_numeral, - value _v_ty) -{ - Z3_context c; /*in*/ - Z3_string numeral; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_numeral, &numeral, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_numeral(c, numeral, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_real( - value _v_c, - value _v_num, - value _v_den) -{ - Z3_context c; /*in*/ - int num; /*in*/ - int den; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - num = Int_val(_v_num); - den = Int_val(_v_den); - _res = Z3_mk_real(c, num, den); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int( - value _v_c, - value _v_v, - value _v_ty) -{ - Z3_context c; /*in*/ - int v; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - v = Int_val(_v_v); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_int(c, v, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_int64( - value _v_c, - value _v_v, - value _v_ty) -{ - Z3_context c; /*in*/ - long long v; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - v = Int64_val(_v_v); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_int64(c, v, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_pattern( - value _v_c, - value _v_terms) -{ - Z3_context c; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_ast const *terms; /*in*/ - Z3_pattern _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_terms); - terms = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_terms, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &terms[_c2], _ctx); - } - num_patterns = _c1; - _res = Z3_mk_pattern(c, num_patterns, terms); - _vres = camlidl_c2ml_z3V3_Z3_pattern(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_bound( - value _v_c, - value _v_index, - value _v_ty) -{ - Z3_context c; /*in*/ - unsigned int index; /*in*/ - Z3_sort ty; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - index = Int_val(_v_index); - camlidl_ml2c_z3V3_Z3_sort(_v_ty, &ty, _ctx); - _res = Z3_mk_bound(c, index, ty); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_forall( - value _v_c, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3V3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_forall(c, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_forall_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_forall(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_mk_exists( - value _v_c, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3V3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_exists(c, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_exists_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_exists(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_mk_quantifier( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3V3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_decls = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_quantifier(c, is_forall, weight, num_patterns, patterns, num_decls, sorts, decl_names, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_quantifier_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_quantifier(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); -} - -value camlidl_z3V3_Z3_mk_quantifier_ex( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_quantifier_id, - value _v_skolem_id, - value _v_patterns, - value _v_no_patterns, - value _v_sorts, - value _v_decl_names, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - Z3_symbol quantifier_id; /*in*/ - Z3_symbol skolem_id; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_no_patterns; /*in*/ - Z3_ast const *no_patterns; /*in*/ - unsigned int num_decls; /*in*/ - Z3_sort const *sorts; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - camlidl_ml2c_z3V3_Z3_symbol(_v_quantifier_id, &quantifier_id, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_skolem_id, &skolem_id, _ctx); - _c1 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c1 * sizeof(Z3_pattern const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_patterns, _c2); - camlidl_ml2c_z3V3_Z3_pattern(_v3, &patterns[_c2], _ctx); - } - num_patterns = _c1; - _c4 = Wosize_val(_v_no_patterns); - no_patterns = camlidl_malloc(_c4 * sizeof(Z3_ast const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_no_patterns, _c5); - camlidl_ml2c_z3V3_Z3_ast(_v6, &no_patterns[_c5], _ctx); - } - num_no_patterns = _c4; - _c7 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c7 * sizeof(Z3_sort const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_sorts, _c8); - camlidl_ml2c_z3V3_Z3_sort(_v9, &sorts[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c10 * sizeof(Z3_symbol const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decl_names, _c11); - camlidl_ml2c_z3V3_Z3_symbol(_v12, &decl_names[_c11], _ctx); - } - num_decls = _c10; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = 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); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_quantifier_ex_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_quantifier_ex(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]); -} - -value camlidl_z3V3_Z3_mk_forall_const( - value _v_c, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3V3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3V3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_forall_const(c, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_exists_const( - value _v_c, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3V3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3V3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_exists_const(c, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_quantifier_const( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_bound, - value _v_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3V3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3V3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = Z3_mk_quantifier_const(c, is_forall, weight, num_bound, bound, num_patterns, patterns, body); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_quantifier_const_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_quantifier_const(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_mk_quantifier_const_ex( - value _v_c, - value _v_is_forall, - value _v_weight, - value _v_quantifier_id, - value _v_skolem_id, - value _v_bound, - value _v_patterns, - value _v_no_patterns, - value _v_body) -{ - Z3_context c; /*in*/ - int is_forall; /*in*/ - unsigned int weight; /*in*/ - Z3_symbol quantifier_id; /*in*/ - Z3_symbol skolem_id; /*in*/ - unsigned int num_bound; /*in*/ - Z3_app const *bound; /*in*/ - unsigned int num_patterns; /*in*/ - Z3_pattern const *patterns; /*in*/ - unsigned int num_no_patterns; /*in*/ - Z3_ast const *no_patterns; /*in*/ - Z3_ast body; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - is_forall = Int_val(_v_is_forall); - weight = Int_val(_v_weight); - camlidl_ml2c_z3V3_Z3_symbol(_v_quantifier_id, &quantifier_id, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_skolem_id, &skolem_id, _ctx); - _c1 = Wosize_val(_v_bound); - bound = camlidl_malloc(_c1 * sizeof(Z3_app const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_bound, _c2); - camlidl_ml2c_z3V3_Z3_app(_v3, &bound[_c2], _ctx); - } - num_bound = _c1; - _c4 = Wosize_val(_v_patterns); - patterns = camlidl_malloc(_c4 * sizeof(Z3_pattern const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_patterns, _c5); - camlidl_ml2c_z3V3_Z3_pattern(_v6, &patterns[_c5], _ctx); - } - num_patterns = _c4; - _c7 = Wosize_val(_v_no_patterns); - no_patterns = camlidl_malloc(_c7 * sizeof(Z3_ast const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_no_patterns, _c8); - camlidl_ml2c_z3V3_Z3_ast(_v9, &no_patterns[_c8], _ctx); - } - num_no_patterns = _c7; - camlidl_ml2c_z3V3_Z3_ast(_v_body, &body, _ctx); - _res = 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); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_mk_quantifier_const_ex(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]); -} - -value camlidl_z3V3_Z3_get_symbol_kind( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_symbol_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_kind(c, s); - _vres = camlidl_c2ml_z3V3_Z3_symbol_kind(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_symbol_int( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_int(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_symbol_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_get_symbol_string(c, s); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_sort_name( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_sort d; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_d, &d, _ctx); - _res = Z3_get_sort_name(c, d); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_sort_id( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_get_sort_id(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_sort_to_ast( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_sort_to_ast(c, s); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_eq_sort( - value _v_c, - value _v_s1, - value _v_s2) -{ - Z3_context c; /*in*/ - Z3_sort s1; /*in*/ - Z3_sort s2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s1, &s1, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s2, &s2, _ctx); - _res = Z3_is_eq_sort(c, s1, s2); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_sort_kind( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_sort_kind(c, t); - _vres = camlidl_c2ml_z3V3_Z3_sort_kind(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_bv_sort_size( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_bv_sort_size(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_finite_domain_sort_size( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned long long *r; /*out*/ - unsigned long long _c1; - value _v2; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - r = &_c1; - Z3_get_finite_domain_sort_size(c, s, r); - if (r == NULL) { - _vres = Val_int(0); - } else { - _v2 = copy_int64(*r); - Begin_root(_v2) - _vres = camlidl_alloc_small(1, 0); - Field(_vres, 0) = _v2; - End_roots(); - } - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_array_sort_domain( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_array_sort_domain(c, t); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_array_sort_range( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_array_sort_range(c, t); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_tuple_sort_mk_decl( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_tuple_sort_mk_decl(c, t); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_tuple_sort_num_fields( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_tuple_sort_num_fields(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_tuple_sort_field_decl( - value _v_c, - value _v_t, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - i = Int_val(_v_i); - _res = Z3_get_tuple_sort_field_decl(c, t, i); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_datatype_sort_num_constructors( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - _res = Z3_get_datatype_sort_num_constructors(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_datatype_sort_constructor( - value _v_c, - value _v_t, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_datatype_sort_constructor(c, t, idx); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_datatype_sort_recognizer( - value _v_c, - value _v_t, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_datatype_sort_recognizer(c, t, idx); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_datatype_sort_constructor_accessor( - value _v_c, - value _v_t, - value _v_idx_c, - value _v_idx_a) -{ - Z3_context c; /*in*/ - Z3_sort t; /*in*/ - unsigned int idx_c; /*in*/ - unsigned int idx_a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_t, &t, _ctx); - idx_c = Int_val(_v_idx_c); - idx_a = Int_val(_v_idx_a); - _res = Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_relation_arity( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_get_relation_arity(c, s); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_relation_column( - value _v_c, - value _v_s, - value _v_col) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - unsigned int col; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - col = Int_val(_v_col); - _res = Z3_get_relation_column(c, s, col); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_func_decl_to_ast( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_f, &f, _ctx); - _res = Z3_func_decl_to_ast(c, f); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_eq_func_decl( - value _v_c, - value _v_f1, - value _v_f2) -{ - Z3_context c; /*in*/ - Z3_func_decl f1; /*in*/ - Z3_func_decl f2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_f1, &f1, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_f2, &f2, _ctx); - _res = Z3_is_eq_func_decl(c, f1, f2); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_func_decl_id( - value _v_c, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_func_decl f; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_f, &f, _ctx); - _res = Z3_get_func_decl_id(c, f); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_name( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_name(c, d); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_kind( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_decl_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_kind(c, d); - _vres = camlidl_c2ml_z3V3_Z3_decl_kind(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_domain_size( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_domain_size(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_arity( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_arity(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_domain( - value _v_c, - value _v_d, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - i = Int_val(_v_i); - _res = Z3_get_domain(c, d, i); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_range( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_range(c, d); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_num_parameters( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_get_decl_num_parameters(c, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_parameter_kind( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_parameter_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_parameter_kind(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_parameter_kind(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_int_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_int_parameter(c, d, idx); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_double_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - double _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_double_parameter(c, d, idx); - _vres = copy_double(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_symbol_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_symbol_parameter(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_sort_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_sort_parameter(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_ast_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_ast_parameter(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_func_decl_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_func_decl_parameter(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_decl_rational_parameter( - value _v_c, - value _v_d, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int idx; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_decl_rational_parameter(c, d, idx); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_app_to_ast( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_app(_v_a, &a, _ctx); - _res = Z3_app_to_ast(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_app_decl( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_app(_v_a, &a, _ctx); - _res = Z3_get_app_decl(c, a); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_app_num_args( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_app(_v_a, &a, _ctx); - _res = Z3_get_app_num_args(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_app_arg( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_app a; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_app(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_app_arg(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_eq_ast( - value _v_c, - value _v_t1, - value _v_t2) -{ - Z3_context c; /*in*/ - Z3_ast t1; /*in*/ - Z3_ast t2; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t1, &t1, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t2, &t2, _ctx); - _res = Z3_is_eq_ast(c, t1, t2); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_ast_id( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_ast t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t, &t, _ctx); - _res = Z3_get_ast_id(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_ast_hash( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_ast_hash(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_sort( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_sort(c, a); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_well_sorted( - value _v_c, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_ast t; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t, &t, _ctx); - _res = Z3_is_well_sorted(c, t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_bool_value( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_lbool _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_bool_value(c, a); - _vres = camlidl_c2ml_z3V3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_ast_kind( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast_kind _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_ast_kind(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast_kind(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_app( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_app(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_numeral_ast( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_numeral_ast(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_algebraic_number( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_algebraic_number(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_to_app( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_app _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_to_app(c, a); - _vres = camlidl_c2ml_z3V3_Z3_app(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_to_func_decl( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_to_func_decl(c, a); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_numeral_string( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_numeral_string(c, a); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_numeral_decimal_string( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_numeral_decimal_string(c, a, precision); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_numerator( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_numerator(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_denominator( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_denominator(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_numeral_small( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - long long *num; /*out*/ - long long *den; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - long long _c2; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - num = &_c1; - den = &_c2; - _res = Z3_get_numeral_small(c, a, num, den); - Begin_roots_block(_vres, 3) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*num); - _vres[2] = copy_int64(*den); - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_numeral_int( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - int *i; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - int _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - i = &_c1; - _res = Z3_get_numeral_int(c, v, i); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = Val_int(*i); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_numeral_int64( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - long long *i; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - i = &_c1; - _res = Z3_get_numeral_int64(c, v, i); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*i); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_numeral_rational_int64( - value _v_c, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_ast v; /*in*/ - long long *num; /*out*/ - long long *den; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - long long _c1; - long long _c2; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - num = &_c1; - den = &_c2; - _res = Z3_get_numeral_rational_int64(c, v, num, den); - Begin_roots_block(_vres, 3) - _vres[0] = Val_int(_res); - _vres[1] = copy_int64(*num); - _vres[2] = copy_int64(*den); - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_algebraic_number_lower( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_algebraic_number_lower(c, a, precision); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_algebraic_number_upper( - value _v_c, - value _v_a, - value _v_precision) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int precision; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - precision = Int_val(_v_precision); - _res = Z3_get_algebraic_number_upper(c, a, precision); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_pattern_to_ast( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_pattern_to_ast(c, p); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_pattern_num_terms( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_get_pattern_num_terms(c, p); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_pattern( - value _v_c, - value _v_p, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_pattern(_v_p, &p, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_pattern(c, p, idx); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_index_value( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_index_value(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_is_quantifier_forall( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_is_quantifier_forall(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_weight( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_weight(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_num_patterns( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_patterns(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_pattern_ast( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_pattern _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_pattern_ast(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_pattern(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_num_no_patterns( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_no_patterns(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_no_pattern_ast( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_no_pattern_ast(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_num_bound( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_num_bound(c, a); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_bound_name( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_bound_name(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_bound_sort( - value _v_c, - value _v_a, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - i = Int_val(_v_i); - _res = Z3_get_quantifier_bound_sort(c, a, i); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_quantifier_body( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_get_quantifier_body(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_simplify( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_simplify(c, a); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_update_term( - value _v_c, - value _v_a, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - _res = Z3_update_term(c, a, num_args, args); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_substitute( - value _v_c, - value _v_a, - value _v_from, - value _v_to) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_exprs; /*in*/ - Z3_ast const *from; /*in*/ - Z3_ast const *to; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_from); - from = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_from, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &from[_c2], _ctx); - } - num_exprs = _c1; - _c4 = Wosize_val(_v_to); - to = camlidl_malloc(_c4 * sizeof(Z3_ast const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_to, _c5); - camlidl_ml2c_z3V3_Z3_ast(_v6, &to[_c5], _ctx); - } - num_exprs = _c4; - _res = Z3_substitute(c, a, num_exprs, from, to); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_substitute_vars( - value _v_c, - value _v_a, - value _v_to) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_exprs; /*in*/ - Z3_ast const *to; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _c1 = Wosize_val(_v_to); - to = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_to, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &to[_c2], _ctx); - } - num_exprs = _c1; - _res = Z3_substitute_vars(c, a, num_exprs, to); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_open_log( - value _v_filename) -{ - Z3_string filename; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_filename, &filename, _ctx); - _res = Z3_open_log(filename); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_append_log( - value _v_string) -{ - Z3_string string; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_string, &string, _ctx); - Z3_append_log(string); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_close_log(value _unit) -{ - Z3_close_log(); - return Val_unit; -} - -value camlidl_z3V3_Z3_toggle_warning_messages( - value _v_enabled) -{ - int enabled; /*in*/ - enabled = Int_val(_v_enabled); - Z3_toggle_warning_messages(enabled); - return Val_unit; -} - -value camlidl_z3V3_Z3_set_ast_print_mode( - value _v_c, - value _v_mode) -{ - Z3_context c; /*in*/ - Z3_ast_print_mode mode; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast_print_mode(_v_mode, &mode, _ctx); - Z3_set_ast_print_mode(c, mode); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_ast_to_string( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - _res = Z3_ast_to_string(c, a); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_pattern_to_string( - value _v_c, - value _v_p) -{ - Z3_context c; /*in*/ - Z3_pattern p; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_pattern(_v_p, &p, _ctx); - _res = Z3_pattern_to_string(c, p); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_sort_to_string( - value _v_c, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_sort s; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_sort_to_string(c, s); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_func_decl_to_string( - value _v_c, - value _v_d) -{ - Z3_context c; /*in*/ - Z3_func_decl d; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_func_decl_to_string(c, d); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_model_to_string( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - _res = Z3_model_to_string(c, m); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_benchmark_to_smtlib_string( - value _v_c, - value _v_name, - value _v_logic, - value _v_status, - value _v_attributes, - value _v_assumptions, - value _v_formula) -{ - Z3_context c; /*in*/ - Z3_string name; /*in*/ - Z3_string logic; /*in*/ - Z3_string status; /*in*/ - Z3_string attributes; /*in*/ - unsigned int num_assumptions; /*in*/ - Z3_ast const *assumptions; /*in*/ - Z3_ast formula; /*in*/ - Z3_string _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_name, &name, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_logic, &logic, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_status, &status, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_attributes, &attributes, _ctx); - _c1 = Wosize_val(_v_assumptions); - assumptions = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_assumptions, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &assumptions[_c2], _ctx); - } - num_assumptions = _c1; - camlidl_ml2c_z3V3_Z3_ast(_v_formula, &formula, _ctx); - _res = Z3_benchmark_to_smtlib_string(c, name, logic, status, attributes, num_assumptions, assumptions, formula); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_benchmark_to_smtlib_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]); -} - -value camlidl_z3V3_Z3_parse_smtlib2_string( - value _v_c, - value _v_str, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_str, &str, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3V3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - _res = Z3_parse_smtlib2_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_parse_smtlib2_string_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_parse_smtlib2_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_parse_smtlib2_file( - value _v_c, - value _v_file_name, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - Z3_ast _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_file_name, &file_name, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3V3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - _res = Z3_parse_smtlib2_file(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_parse_smtlib2_file_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_parse_smtlib2_file(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_parse_smtlib_string( - value _v_c, - value _v_str, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_str, &str, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3V3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_parse_smtlib_string_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_parse_smtlib_string(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_parse_smtlib_file( - value _v_c, - value _v_file_name, - value _v_sort_names, - value _v_sorts, - value _v_decl_names, - value _v_decls) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - unsigned int num_sorts; /*in*/ - Z3_symbol const *sort_names; /*in*/ - Z3_sort const *sorts; /*in*/ - unsigned int num_decls; /*in*/ - Z3_symbol const *decl_names; /*in*/ - Z3_func_decl const *decls; /*in*/ - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - mlsize_t _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - mlsize_t _c11; - value _v12; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_file_name, &file_name, _ctx); - _c1 = Wosize_val(_v_sort_names); - sort_names = camlidl_malloc(_c1 * sizeof(Z3_symbol const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_sort_names, _c2); - camlidl_ml2c_z3V3_Z3_symbol(_v3, &sort_names[_c2], _ctx); - } - num_sorts = _c1; - _c4 = Wosize_val(_v_sorts); - sorts = camlidl_malloc(_c4 * sizeof(Z3_sort const ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_sorts, _c5); - camlidl_ml2c_z3V3_Z3_sort(_v6, &sorts[_c5], _ctx); - } - num_sorts = _c4; - _c7 = Wosize_val(_v_decl_names); - decl_names = camlidl_malloc(_c7 * sizeof(Z3_symbol const ), _ctx); - for (_c8 = 0; _c8 < _c7; _c8++) { - _v9 = Field(_v_decl_names, _c8); - camlidl_ml2c_z3V3_Z3_symbol(_v9, &decl_names[_c8], _ctx); - } - num_decls = _c7; - _c10 = Wosize_val(_v_decls); - decls = camlidl_malloc(_c10 * sizeof(Z3_func_decl const ), _ctx); - for (_c11 = 0; _c11 < _c10; _c11++) { - _v12 = Field(_v_decls, _c11); - camlidl_ml2c_z3V3_Z3_func_decl(_v12, &decls[_c11], _ctx); - } - num_decls = _c10; - Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_parse_smtlib_file_bytecode(value * argv, int argn) -{ - return camlidl_z3V3_Z3_parse_smtlib_file(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); -} - -value camlidl_z3V3_Z3_get_smtlib_num_formulas( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_formulas(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_formula( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_formula(c, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_num_assumptions( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_assumptions(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_assumption( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_assumption(c, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_num_decls( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_decls(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_decl( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_decl(c, i); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_num_sorts( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_num_sorts(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_sort( - value _v_c, - value _v_i) -{ - Z3_context c; /*in*/ - unsigned int i; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - i = Int_val(_v_i); - _res = Z3_get_smtlib_sort(c, i); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_smtlib_error( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_smtlib_error(c); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_version(value _unit) -{ - unsigned int *major; /*out*/ - unsigned int *minor; /*out*/ - unsigned int *build_number; /*out*/ - unsigned int *revision_number; /*out*/ - unsigned int _c1; - unsigned int _c2; - unsigned int _c3; - unsigned int _c4; - value _vresult; - value _vres[4] = { 0, 0, 0, 0, }; - - major = &_c1; - minor = &_c2; - build_number = &_c3; - revision_number = &_c4; - Z3_get_version(major, minor, build_number, revision_number); - Begin_roots_block(_vres, 4) - _vres[0] = Val_int(*major); - _vres[1] = Val_int(*minor); - _vres[2] = Val_int(*build_number); - _vres[3] = Val_int(*revision_number); - _vresult = camlidl_alloc_small(4, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - Field(_vresult, 3) = _vres[3]; - End_roots() - return _vresult; -} - -value camlidl_z3V3_Z3_enable_trace( - value _v_tag) -{ - Z3_string tag; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_tag, &tag, _ctx); - Z3_enable_trace(tag); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_disable_trace( - value _v_tag) -{ - Z3_string tag; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_string(_v_tag, &tag, _ctx); - Z3_disable_trace(tag); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_reset_memory(value _unit) -{ - Z3_reset_memory(); - return Val_unit; -} - -value camlidl_z3V3_Z3_theory_mk_sort( - value _v_c, - value _v_t, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_theory t; /*in*/ - Z3_symbol s; /*in*/ - Z3_sort _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _res = Z3_theory_mk_sort(c, t, s); - _vres = camlidl_c2ml_z3V3_Z3_sort(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_mk_value( - value _v_c, - value _v_t, - value _v_n, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_theory t; /*in*/ - Z3_symbol n; /*in*/ - Z3_sort s; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_n, &n, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_theory_mk_value(c, t, n, s); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_mk_constant( - value _v_c, - value _v_t, - value _v_n, - value _v_s) -{ - Z3_context c; /*in*/ - Z3_theory t; /*in*/ - Z3_symbol n; /*in*/ - Z3_sort s; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_n, &n, _ctx); - camlidl_ml2c_z3V3_Z3_sort(_v_s, &s, _ctx); - _res = Z3_theory_mk_constant(c, t, n, s); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_mk_func_decl( - value _v_c, - value _v_t, - value _v_n, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_theory t; /*in*/ - Z3_symbol n; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_n, &n, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3V3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3V3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_theory_mk_func_decl(c, t, n, domain_size, domain, range); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_context( - value _v_t) -{ - Z3_theory t; /*in*/ - Z3_context _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - _res = Z3_theory_get_context(t); - _vres = camlidl_c2ml_z3V3_Z3_context(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_assert_axiom( - value _v_t, - value _v_ax) -{ - Z3_theory t; /*in*/ - Z3_ast ax; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_ax, &ax, _ctx); - Z3_theory_assert_axiom(t, ax); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_theory_assume_eq( - value _v_t, - value _v_lhs, - value _v_rhs) -{ - Z3_theory t; /*in*/ - Z3_ast lhs; /*in*/ - Z3_ast rhs; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_lhs, &lhs, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_rhs, &rhs, _ctx); - Z3_theory_assume_eq(t, lhs, rhs); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_theory_enable_axiom_simplification( - value _v_t, - value _v_flag) -{ - Z3_theory t; /*in*/ - int flag; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - flag = Int_val(_v_flag); - Z3_theory_enable_axiom_simplification(t, flag); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_theory_get_eqc_root( - value _v_t, - value _v_n) -{ - Z3_theory t; /*in*/ - Z3_ast n; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_n, &n, _ctx); - _res = Z3_theory_get_eqc_root(t, n); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_eqc_next( - value _v_t, - value _v_n) -{ - Z3_theory t; /*in*/ - Z3_ast n; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_n, &n, _ctx); - _res = Z3_theory_get_eqc_next(t, n); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_num_parents( - value _v_t, - value _v_n) -{ - Z3_theory t; /*in*/ - Z3_ast n; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_n, &n, _ctx); - _res = Z3_theory_get_num_parents(t, n); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_parent( - value _v_t, - value _v_n, - value _v_i) -{ - Z3_theory t; /*in*/ - Z3_ast n; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_n, &n, _ctx); - i = Int_val(_v_i); - _res = Z3_theory_get_parent(t, n, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_is_value( - value _v_t, - value _v_n) -{ - Z3_theory t; /*in*/ - Z3_ast n; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_n, &n, _ctx); - _res = Z3_theory_is_value(t, n); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_is_decl( - value _v_t, - value _v_d) -{ - Z3_theory t; /*in*/ - Z3_func_decl d; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _res = Z3_theory_is_decl(t, d); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_num_elems( - value _v_t) -{ - Z3_theory t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - _res = Z3_theory_get_num_elems(t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_elem( - value _v_t, - value _v_i) -{ - Z3_theory t; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - i = Int_val(_v_i); - _res = Z3_theory_get_elem(t, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_num_apps( - value _v_t) -{ - Z3_theory t; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - _res = Z3_theory_get_num_apps(t); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_theory_get_app( - value _v_t, - value _v_i) -{ - Z3_theory t; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_theory(_v_t, &t, _ctx); - i = Int_val(_v_i); - _res = Z3_theory_get_app(t, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_injective_function( - value _v_c, - value _v_s, - value _v_domain, - value _v_range) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - unsigned int domain_size; /*in*/ - Z3_sort const *domain; /*in*/ - Z3_sort range; /*in*/ - Z3_func_decl _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - _c1 = Wosize_val(_v_domain); - domain = camlidl_malloc(_c1 * sizeof(Z3_sort const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_domain, _c2); - camlidl_ml2c_z3V3_Z3_sort(_v3, &domain[_c2], _ctx); - } - domain_size = _c1; - camlidl_ml2c_z3V3_Z3_sort(_v_range, &range, _ctx); - _res = Z3_mk_injective_function(c, s, domain_size, domain, range); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_set_logic( - value _v_c, - value _v_logic) -{ - Z3_context c; /*in*/ - Z3_string logic; /*in*/ - int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_logic, &logic, _ctx); - _res = Z3_set_logic(c, logic); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_push( - value _v_c) -{ - Z3_context c; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - Z3_push(c); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_pop( - value _v_c, - value _v_num_scopes) -{ - Z3_context c; /*in*/ - unsigned int num_scopes; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - num_scopes = Int_val(_v_num_scopes); - Z3_pop(c, num_scopes); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_get_num_scopes( - value _v_c) -{ - Z3_context c; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_num_scopes(c); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_persist_ast( - value _v_c, - value _v_a, - value _v_num_scopes) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - unsigned int num_scopes; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - num_scopes = Int_val(_v_num_scopes); - Z3_persist_ast(c, a, num_scopes); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_assert_cnstr( - value _v_c, - value _v_a) -{ - Z3_context c; /*in*/ - Z3_ast a; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_a, &a, _ctx); - Z3_assert_cnstr(c, a); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_check_and_get_model( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_model *m; /*out*/ - Z3_lbool _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_model _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - m = &_c1; - _res = Z3_check_and_get_model(c, m); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3V3_Z3_lbool(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3V3_Z3_model(&*m, _ctx); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_check( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_lbool _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_check(c); - _vres = camlidl_c2ml_z3V3_Z3_lbool(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_check_assumptions( - value _v_c, - value _v_assumptions, - value _v_core_size, - value _v_core) -{ - Z3_context c; /*in*/ - unsigned int num_assumptions; /*in*/ - Z3_ast const *assumptions; /*in*/ - Z3_model *m; /*out*/ - Z3_ast *proof; /*out*/ - unsigned int *core_size; /*in,out*/ - Z3_ast *core; /*in,out*/ - Z3_lbool _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - unsigned int _c4; - mlsize_t _c5; - mlsize_t _c6; - value _v7; - Z3_model _c8; - Z3_ast _c9; - mlsize_t _c10; - value _v11; - value _vresult; - value _vres[5] = { 0, 0, 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_assumptions); - assumptions = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_assumptions, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &assumptions[_c2], _ctx); - } - num_assumptions = _c1; - core_size = &_c4; - _c4 = Int_val(_v_core_size); - _c5 = Wosize_val(_v_core); - core = camlidl_malloc(_c5 * sizeof(Z3_ast ), _ctx); - for (_c6 = 0; _c6 < _c5; _c6++) { - _v7 = Field(_v_core, _c6); - camlidl_ml2c_z3V3_Z3_ast(_v7, &core[_c6], _ctx); - } - num_assumptions = _c5; - m = &_c8; - proof = &_c9; - _res = Z3_check_assumptions(c, num_assumptions, assumptions, m, proof, core_size, core); - Begin_roots_block(_vres, 5) - _vres[0] = camlidl_c2ml_z3V3_Z3_lbool(&_res, _ctx); - _vres[1] = camlidl_c2ml_z3V3_Z3_model(&*m, _ctx); - _vres[2] = camlidl_c2ml_z3V3_Z3_ast(&*proof, _ctx); - _vres[3] = Val_int(*core_size); - _vres[4] = camlidl_alloc(num_assumptions, 0); - Begin_root(_vres[4]) - for (_c10 = 0; _c10 < num_assumptions; _c10++) { - _v11 = camlidl_c2ml_z3V3_Z3_ast(&core[_c10], _ctx); - modify(&Field(_vres[4], _c10), _v11); - } - End_roots() - _vresult = camlidl_alloc_small(5, 0); - { mlsize_t _c12; - for (_c12 = 0; _c12 < 5; _c12++) Field(_vresult, _c12) = _vres[_c12]; - } - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_del_model( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - Z3_del_model(c, m); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_soft_check_cancel( - value _v_c) -{ - Z3_context c; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - Z3_soft_check_cancel(c); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_get_search_failure( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_search_failure _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_search_failure(c); - _vres = camlidl_c2ml_z3V3_Z3_search_failure(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_mk_label( - value _v_c, - value _v_s, - value _v_is_pos, - value _v_f) -{ - Z3_context c; /*in*/ - Z3_symbol s; /*in*/ - int is_pos; /*in*/ - Z3_ast f; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_symbol(_v_s, &s, _ctx); - is_pos = Int_val(_v_is_pos); - camlidl_ml2c_z3V3_Z3_ast(_v_f, &f, _ctx); - _res = Z3_mk_label(c, s, is_pos, f); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_relevant_labels( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_literals _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_relevant_labels(c); - _vres = camlidl_c2ml_z3V3_Z3_literals(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_relevant_literals( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_literals _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_relevant_literals(c); - _vres = camlidl_c2ml_z3V3_Z3_literals(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_guessed_literals( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_literals _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_guessed_literals(c); - _vres = camlidl_c2ml_z3V3_Z3_literals(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_del_literals( - value _v_c, - value _v_lbls) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - Z3_del_literals(c, lbls); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_get_num_literals( - value _v_c, - value _v_lbls) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - _res = Z3_get_num_literals(c, lbls); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_label_symbol( - value _v_c, - value _v_lbls, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - unsigned int idx; /*in*/ - Z3_symbol _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_label_symbol(c, lbls, idx); - _vres = camlidl_c2ml_z3V3_Z3_symbol(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_literal( - value _v_c, - value _v_lbls, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - unsigned int idx; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - idx = Int_val(_v_idx); - _res = Z3_get_literal(c, lbls, idx); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_disable_literal( - value _v_c, - value _v_lbls, - value _v_idx) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - unsigned int idx; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - idx = Int_val(_v_idx); - Z3_disable_literal(c, lbls, idx); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_block_literals( - value _v_c, - value _v_lbls) -{ - Z3_context c; /*in*/ - Z3_literals lbls; /*in*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_literals(_v_lbls, &lbls, _ctx); - Z3_block_literals(c, lbls); - camlidl_free(_ctx); - return Val_unit; -} - -value camlidl_z3V3_Z3_get_model_num_constants( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - _res = Z3_get_model_num_constants(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_constant( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_get_model_constant(c, m, i); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_num_funcs( - value _v_c, - value _v_m) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - _res = Z3_get_model_num_funcs(c, m); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_func_decl( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_func_decl _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_get_model_func_decl(c, m, i); - _vres = camlidl_c2ml_z3V3_Z3_func_decl(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_eval_func_decl( - value _v_c, - value _v_m, - value _v_decl) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_func_decl decl; /*in*/ - Z3_ast *v; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_ast _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_decl, &decl, _ctx); - v = &_c1; - _res = Z3_eval_func_decl(c, m, decl, v); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = camlidl_c2ml_z3V3_Z3_ast(&*v, _ctx); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_is_array_value( - value _v_c, - value _v_m, - value _v_v) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_ast v; /*in*/ - unsigned int *num_entries; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - unsigned int _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - num_entries = &_c1; - _res = Z3_is_array_value(c, m, v, num_entries); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = Val_int(*num_entries); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_array_value( - value _v_c, - value _v_m, - value _v_v, - value _v_indices, - value _v_values) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_ast v; /*in*/ - unsigned int num_entries; /*in*/ - Z3_ast *indices; /*in,out*/ - Z3_ast *values; /*in,out*/ - Z3_ast *else_value; /*out*/ - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; - Z3_ast _c7; - mlsize_t _c8; - value _v9; - mlsize_t _c10; - value _v11; - value _vresult; - value _vres[3] = { 0, 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_v, &v, _ctx); - _c1 = Wosize_val(_v_indices); - indices = camlidl_malloc(_c1 * sizeof(Z3_ast ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_indices, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &indices[_c2], _ctx); - } - num_entries = _c1; - _c4 = Wosize_val(_v_values); - values = camlidl_malloc(_c4 * sizeof(Z3_ast ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_values, _c5); - camlidl_ml2c_z3V3_Z3_ast(_v6, &values[_c5], _ctx); - } - num_entries = _c4; - else_value = &_c7; - Z3_get_array_value(c, m, v, num_entries, indices, values, else_value); - Begin_roots_block(_vres, 3) - _vres[0] = camlidl_alloc(num_entries, 0); - Begin_root(_vres[0]) - for (_c8 = 0; _c8 < num_entries; _c8++) { - _v9 = camlidl_c2ml_z3V3_Z3_ast(&indices[_c8], _ctx); - modify(&Field(_vres[0], _c8), _v9); - } - End_roots() - _vres[1] = camlidl_alloc(num_entries, 0); - Begin_root(_vres[1]) - for (_c10 = 0; _c10 < num_entries; _c10++) { - _v11 = camlidl_c2ml_z3V3_Z3_ast(&values[_c10], _ctx); - modify(&Field(_vres[1], _c10), _v11); - } - End_roots() - _vres[2] = camlidl_c2ml_z3V3_Z3_ast(&*else_value, _ctx); - _vresult = camlidl_alloc_small(3, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - Field(_vresult, 2) = _vres[2]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_get_model_func_else( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_get_model_func_else(c, m, i); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_func_num_entries( - value _v_c, - value _v_m, - value _v_i) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - _res = Z3_get_model_func_num_entries(c, m, i); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_func_entry_num_args( - value _v_c, - value _v_m, - value _v_i, - value _v_j) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - unsigned int j; /*in*/ - unsigned int _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - j = Int_val(_v_j); - _res = Z3_get_model_func_entry_num_args(c, m, i, j); - _vres = Val_int(_res); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_func_entry_arg( - value _v_c, - value _v_m, - value _v_i, - value _v_j, - value _v_k) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - unsigned int j; /*in*/ - unsigned int k; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - j = Int_val(_v_j); - k = Int_val(_v_k); - _res = Z3_get_model_func_entry_arg(c, m, i, j, k); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_model_func_entry_value( - value _v_c, - value _v_m, - value _v_i, - value _v_j) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - unsigned int i; /*in*/ - unsigned int j; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - i = Int_val(_v_i); - j = Int_val(_v_j); - _res = Z3_get_model_func_entry_value(c, m, i, j); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_eval( - value _v_c, - value _v_m, - value _v_t) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_ast t; /*in*/ - Z3_ast *v; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - Z3_ast _c1; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3V3_Z3_ast(_v_t, &t, _ctx); - v = &_c1; - _res = Z3_eval(c, m, t, v); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = camlidl_c2ml_z3V3_Z3_ast(&*v, _ctx); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_eval_decl( - value _v_c, - value _v_m, - value _v_d, - value _v_args) -{ - Z3_context c; /*in*/ - Z3_model m; /*in*/ - Z3_func_decl d; /*in*/ - unsigned int num_args; /*in*/ - Z3_ast const *args; /*in*/ - Z3_ast *v; /*out*/ - int _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - Z3_ast _c4; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_model(_v_m, &m, _ctx); - camlidl_ml2c_z3V3_Z3_func_decl(_v_d, &d, _ctx); - _c1 = Wosize_val(_v_args); - args = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_args, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &args[_c2], _ctx); - } - num_args = _c1; - v = &_c4; - _res = Z3_eval_decl(c, m, d, num_args, args, v); - Begin_roots_block(_vres, 2) - _vres[0] = Val_int(_res); - _vres[1] = camlidl_c2ml_z3V3_Z3_ast(&*v, _ctx); - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - -value camlidl_z3V3_Z3_context_to_string( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_context_to_string(c); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_statistics_to_string( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_string _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_statistics_to_string(c); - _vres = camlidl_c2ml_z3V3_Z3_string(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3V3_Z3_get_context_assignment( - value _v_c) -{ - Z3_context c; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _res = Z3_get_context_assignment(c); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - diff --git a/src/api/ml/old/z3_theory_stubs.c b/src/api/ml/old/z3_theory_stubs.c deleted file mode 100644 index a48b94553..000000000 --- a/src/api/ml/old/z3_theory_stubs.c +++ /dev/null @@ -1,339 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation - -Module Name: - - z3_theory_stubs.c - -Abstract: - - OCaml C bindings for callbacks between OCaml and C for - theory plugins. - The API for theory plugins require associating a set of - callbacks as C function pointers. - We use the following strategy: - - - store in the user_ext_data blob that theory constructors allow - a record of callback functions. - - - define catch-all static callback functions that access the - ML record with the callbacks. It then invokes these through user-registered - application functions that apply the callback stored in the record to the - actual parameters. - It is tempting to avoid this user-registered callback and directly access - the record of callback functions and apply the proper field. - However, the layout of records appears to be opaque, or at least we assume it is - so, from the C runtime. - -Author: - - -Revision History: ---*/ - -#include -#include -#include -#include -#include -#include -#include -#ifdef Custom_tag -#include -#include -#endif - -#include "z3.h" - -#define ML_SIZE(_ty) ((sizeof(_ty) + sizeof(value) - 1)/ sizeof(value)) - -static value mk_func_decl(Z3_func_decl f) { - value _f = alloc(ML_SIZE(Z3_func_decl), Abstract_tag); - *((Z3_func_decl*) Bp_val(_f)) = f; - return _f; -} - -static value Val_ast(Z3_ast a) { - value _a = alloc(ML_SIZE(Z3_ast), Abstract_tag); - *((Z3_ast*) Bp_val(_a)) = a; - return _a; -} - - -static value Val_ast_array(unsigned int sz, Z3_ast const args[]) { - value res; - Z3_ast* args1; - unsigned int i; - args1 = malloc((sz+1)*sizeof(Z3_ast)); - for (i = 0; i < sz; ++i) { - args1[i] = args[i]; - } - args1[sz] = 0; - res = alloc_array((value (*)(char const*))Val_ast, (const char**)args1); - free(args1); - return res; -} - -// ------------------ -// get_theory_callbacks -// - -value get_theory_callbacks(value th) -{ - Z3_theory _th = *((Z3_theory*) Bp_val(th)); - return (value) Z3_theory_get_ext_data(_th); -} - -// ------------------ -// delete_theory -// -static void delete_callback_static(Z3_theory th) -{ - CAMLparam0(); - CAMLlocal1(f); - value user_data = (value) Z3_theory_get_ext_data(th); - f = *(caml_named_value("apply_delete")) ; - callback(f, user_data); - remove_global_root(&user_data); - CAMLreturn0; -} - -#define SET_CALLBACK(_cb_name) \ - value set_ ## _cb_name ## _callback_register(value th) \ - { \ - CAMLparam1(th); \ - Z3_theory _th = *((Z3_theory*) Bp_val(th)); \ - Z3_set_ ## _cb_name ## _callback(_th, _cb_name ## _callback_static); \ - CAMLreturn(Val_unit); \ - } \ - -SET_CALLBACK(delete); - - -// ------------------ -// mk_theory -// - -value mk_theory_register(value context, value name, value user_data) -{ - CAMLparam3(context, name, user_data); - Z3_context _context = *((Z3_context *) Bp_val(context)); - value _th; - Z3_theory th; - register_global_root(&user_data); - th = Z3_mk_theory(_context, String_val(name), (void*)user_data); - // jjb: test th == NULL ? - Z3_set_delete_callback(th, delete_callback_static); - _th = alloc(ML_SIZE(Z3_context), Abstract_tag); - *((Z3_theory*) Bp_val(_th)) = th; - CAMLreturn(_th); -} - - -// ------------------- -// reduce_app_callback - -static Z3_bool reduce_app_callback_static(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r) { - CAMLparam0(); - CAMLlocal4(cb, _r, _v, _args); - value user_data; - Z3_bool result; - - _args = Val_ast_array(num_args, args); - - user_data = (value) Z3_theory_get_ext_data(th); - - cb = *(caml_named_value("apply_reduce_app")); - _r = callback3(cb, user_data, mk_func_decl(f), _args); - - cb = *(caml_named_value("is_some")); - _v = callback(cb, _r); - result = 0 != Bool_val(_v); - - if (result && r) { - cb = *(caml_named_value("get_some")); - _v = callback(cb, _r); - *r = *((Z3_ast*) Bp_val(_v)); - } - - CAMLreturn (result); -} - -SET_CALLBACK(reduce_app); - -// ------------------- -// reduce_eq_callback - -static Z3_bool reduce_eq_callback_static(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast * r) -{ - CAMLparam0(); - CAMLlocal5(cb, _r, _a, _b, _v); - value user_data; - Z3_bool result; - - _a = Val_ast(a); - _b = Val_ast(b); - - user_data = (value) Z3_theory_get_ext_data(th); - - cb = *(caml_named_value("apply_reduce_eq")); - _r = callback3(cb, user_data, _a, _b); - - cb = *(caml_named_value("is_some")); - _v = callback(cb, _r); - result = 0 != Bool_val(_v); - - if (result && r) { - cb = *(caml_named_value("get_some")); - _v = callback(cb, _r); - *r = *((Z3_ast*) Bp_val(_v)); - } - - CAMLreturn (result); -} - -SET_CALLBACK(reduce_eq); - - -// ------------------- -// reduce_distinct - -static Z3_bool reduce_distinct_callback_static(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast * r) -{ - CAMLparam0(); - CAMLlocal4(cb, _r, _args, _v); - value user_data; - Z3_bool result; - - _args = Val_ast_array(n, args); - - user_data = (value) Z3_theory_get_ext_data(th); - - cb = *(caml_named_value("apply_reduce_distinct")); - _r = callback2(cb, user_data, _args); - - cb = *(caml_named_value("is_some")); - _v = callback(cb, _r); - result = 0 != Bool_val(_v); - - if (result && r) { - cb = *(caml_named_value("get_some")); - _v = callback(cb, _r); - *r = *((Z3_ast*) Bp_val(_v)); - } - - CAMLreturn (result); -} - -SET_CALLBACK(reduce_distinct); - -// ------------------- -// new_app - -#define AST_CALLBACK(_cb_name) \ -static void _cb_name##_callback_static(Z3_theory th, Z3_ast a) \ -{ \ - CAMLparam0(); \ - CAMLlocal3(cb, _a, user_data); \ - _a = Val_ast(a); \ - user_data = (value) Z3_theory_get_ext_data(th); \ - cb = *(caml_named_value("apply_" #_cb_name)); \ - callback2(cb, user_data, _a); \ - CAMLreturn0; \ -} \ - -AST_CALLBACK(new_app); -SET_CALLBACK(new_app); - -// ------------------- -// new_elem - -AST_CALLBACK(new_elem); -SET_CALLBACK(new_elem); - -// ------------------- -// init_search - -#define TH_CALLBACK(_cb_name) \ -static void _cb_name##_callback_static(Z3_theory th) \ -{ \ - CAMLparam0(); \ - CAMLlocal2(cb, user_data); \ - user_data = (value) Z3_theory_get_ext_data(th); \ - cb = *(caml_named_value("apply_" #_cb_name)); \ - callback(cb, user_data); \ - CAMLreturn0; \ -} \ - -TH_CALLBACK(init_search); -SET_CALLBACK(init_search); - -// ------------------- -// push - -TH_CALLBACK(push); -SET_CALLBACK(push); - -TH_CALLBACK(pop); -SET_CALLBACK(pop); - -TH_CALLBACK(restart); -SET_CALLBACK(restart); - -TH_CALLBACK(reset); -SET_CALLBACK(reset); - - -#define FC_CALLBACK(_cb_name) \ - static Z3_bool _cb_name##_callback_static(Z3_theory th) \ - { \ - CAMLparam0(); \ - CAMLlocal3(cb, r, user_data); \ - user_data = (value) Z3_theory_get_ext_data(th); \ - cb = *(caml_named_value("apply_" #_cb_name)); \ - r = callback(cb, user_data); \ - CAMLreturn (Bool_val(r) != 0); \ - } \ - -FC_CALLBACK(final_check); -SET_CALLBACK(final_check); - -#define AST_AST_CALLBACK(_cb_name) \ - static void _cb_name##_callback_static(Z3_theory th, Z3_ast a, Z3_ast b) \ - { \ - CAMLparam0(); \ - CAMLlocal4(cb, _a, _b, user_data); \ - _a = Val_ast(a); \ - _b = Val_ast(b); \ - user_data = (value) Z3_theory_get_ext_data(th); \ - cb = *(caml_named_value("apply_" #_cb_name)); \ - callback3(cb, user_data, _a, _b); \ - CAMLreturn0; \ - } \ - -AST_AST_CALLBACK(new_eq); -SET_CALLBACK(new_eq); - -AST_AST_CALLBACK(new_diseq); -SET_CALLBACK(new_diseq); - -#define AST_BOOL_CALLBACK(_cb_name) \ - static void _cb_name##_callback_static(Z3_theory th, Z3_ast a, Z3_bool b) \ - { \ - CAMLparam0(); \ - CAMLlocal4(cb, _a, _b, user_data); \ - _a = Val_ast(a); \ - _b = Val_bool(b); \ - user_data = (value) Z3_theory_get_ext_data(th); \ - cb = *(caml_named_value("apply_" #_cb_name)); \ - callback3(cb, user_data, _a, _b); \ - CAMLreturn0; \ - } \ - - -AST_BOOL_CALLBACK(new_assignment); -SET_CALLBACK(new_assignment); - -AST_CALLBACK(new_relevant); -SET_CALLBACK(new_relevant); - From b92bdaeebe9cedb3191d2c5e30abf95dcee72e82 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 18:51:47 +0000 Subject: [PATCH 531/646] ML API readme fixes Signed-off-by: Christoph M. Wintersteiger --- examples/ml/README | 2 -- src/api/ml/README | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/ml/README b/examples/ml/README index b7aa187fa..562e9fe46 100644 --- a/examples/ml/README +++ b/examples/ml/README @@ -1,5 +1,3 @@ -### This is work-in-progress. - Small example using the Z3 ML bindings. To build the example execute make examples diff --git a/src/api/ml/README b/src/api/ml/README index f697e5ff4..ffdd3e709 100644 --- a/src/api/ml/README +++ b/src/api/ml/README @@ -1,6 +1,5 @@ -This directory is work in progress. - -We are currently working on a brand new ML API. +This is the new ML API introduced with Z3 4.4. For the legacy bindings, please +refer to previous releases of Z3. On Windows, there are no less than four different ports of OCaml. The Z3 build system assumes that either the win32 or the win64 port is installed. This means From e1d469fcbf79609d6240e79b23a9b4e4f7f732c8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 24 Jan 2015 19:12:55 +0000 Subject: [PATCH 532/646] Update release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index f8cac4c8b..bfadb8f75 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -9,14 +9,17 @@ Version 4.4 See also: Froehlich, Biere, Wintersteiger, Hamadi: Stochastic Local Search for Satisfiability Modulo Theories, AAAI 2015. +- Upgrade: This release includes a brand new OCaml/ML API that is much better integrated with the build system, and hopefully also easier to use than the previous one. + - Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, and Codeplex users rsas, clockish, Heizmann. + Version 4.3.2 ============= - Added preliminary support for the theory of floating point numbers (tactics qffpa, qffpabv, and logics QF_FPA, QF_FPABV). -- Added the interpolation features of iZ3, which are now integrated into the Z3. +- Added the interpolation features of iZ3, which are now integrated into Z3. - Fixed a multitude of bugs and inconsistencies that were reported to us either in person, by email, or on Codeplex. Of those that we do have records of, we would like to express our gratitude to: Vladimir Klebanov, Konrad Jamrozik, Nuno Lopes, Carsten Ruetz, Esteban Pavese, Tomer Weiss, Ilya Mironov, Gabriele Paganelli, Levent Erkok, Fabian Emmes, David Cok, Etienne Kneuss, Arlen Cox, Matt Lewis, Carsten Otto, Paul Jackson, David Monniaux, Markus Rabe, Martin Pluecker, Jasmin Blanchette, Jules Villard, Andrew Gacek, George Karpenkov, Joerg Pfaehler, and Pablo Aledo From 2fa35233f7c3778b7e9f6c6883be547e1aa6b28b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 28 Jan 2015 13:17:22 -0600 Subject: [PATCH 533/646] Bugfix for the FPA theor. Thanks to codeplex user smccamant for reporting this one. Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 45cd60332..3bf9dadb8 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -463,7 +463,8 @@ namespace smt { switch (k) { case OP_FPA_TO_UBV: case OP_FPA_TO_SBV: - case OP_FPA_TO_REAL: { + case OP_FPA_TO_REAL: + case OP_FPA_TO_IEEE_BV: { expr_ref conv(m); conv = convert(term); assert_cnstr(m.mk_eq(term, conv)); From bcfefdd8ee6cd097df65d15813a8489b7408eeaa Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 28 Jan 2015 13:17:22 -0600 Subject: [PATCH 534/646] Bugfix for the FPA theory. Thanks to codeplex user smccamant for reporting this one. Signed-off-by: Christoph M. Wintersteiger --- src/smt/theory_fpa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/smt/theory_fpa.cpp b/src/smt/theory_fpa.cpp index 45cd60332..3bf9dadb8 100644 --- a/src/smt/theory_fpa.cpp +++ b/src/smt/theory_fpa.cpp @@ -463,7 +463,8 @@ namespace smt { switch (k) { case OP_FPA_TO_UBV: case OP_FPA_TO_SBV: - case OP_FPA_TO_REAL: { + case OP_FPA_TO_REAL: + case OP_FPA_TO_IEEE_BV: { expr_ref conv(m); conv = convert(term); assert_cnstr(m.mk_eq(term, conv)); From 3b78509d0afaa812426ff02ffca460e7f2aeaf28 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 30 Jan 2015 20:45:16 -0600 Subject: [PATCH 535/646] Improved memory use of the .NET API Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/AST.cs | 2 ++ src/api/dotnet/ASTMap.cs | 2 ++ src/api/dotnet/ASTVector.cs | 2 ++ src/api/dotnet/ApplyResult.cs | 2 ++ src/api/dotnet/Context.cs | 16 ++++++++-------- src/api/dotnet/Fixedpoint.cs | 2 ++ src/api/dotnet/FuncInterp.cs | 4 ++++ src/api/dotnet/Goal.cs | 2 ++ src/api/dotnet/IDecRefQueue.cs | 7 ++++++- src/api/dotnet/Model.cs | 2 ++ src/api/dotnet/ParamDescrs.cs | 2 ++ src/api/dotnet/Params.cs | 2 ++ src/api/dotnet/Probe.cs | 2 ++ src/api/dotnet/Solver.cs | 2 ++ src/api/dotnet/Statistics.cs | 2 ++ src/api/dotnet/Tactic.cs | 2 ++ 16 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/api/dotnet/AST.cs b/src/api/dotnet/AST.cs index d3b31a325..552fd6def 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -213,6 +213,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/ASTMap.cs b/src/api/dotnet/ASTMap.cs index 9de3b8358..fa8070908 100644 --- a/src/api/dotnet/ASTMap.cs +++ b/src/api/dotnet/ASTMap.cs @@ -128,6 +128,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_ast_map_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/ASTVector.cs b/src/api/dotnet/ASTVector.cs index bbba3de90..be5172f97 100644 --- a/src/api/dotnet/ASTVector.cs +++ b/src/api/dotnet/ASTVector.cs @@ -105,6 +105,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_ast_vector_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/ApplyResult.cs b/src/api/dotnet/ApplyResult.cs index d64dccb4b..4ff8851af 100644 --- a/src/api/dotnet/ApplyResult.cs +++ b/src/api/dotnet/ApplyResult.cs @@ -85,6 +85,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_apply_result_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 65ec87bc6..94baea35a 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4396,20 +4396,20 @@ namespace Microsoft.Z3 } readonly private AST.DecRefQueue m_AST_DRQ = new AST.DecRefQueue(); - readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(); - readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(); - readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(); + readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(10); + readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(10); + readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(10); readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(); readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(); - readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(); - readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(); + readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(10); + readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(10); readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(); readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(); readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(); - readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(); - readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(); + readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(10); + readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(10); readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(); - readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(); + readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10); internal AST.DecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } internal ASTMap.DecRefQueue ASTMap_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTMap_DRQ; } } diff --git a/src/api/dotnet/Fixedpoint.cs b/src/api/dotnet/Fixedpoint.cs index 3f40b220b..37ae1b110 100644 --- a/src/api/dotnet/Fixedpoint.cs +++ b/src/api/dotnet/Fixedpoint.cs @@ -335,6 +335,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_fixedpoint_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/FuncInterp.cs b/src/api/dotnet/FuncInterp.cs index a6628af28..488abb780 100644 --- a/src/api/dotnet/FuncInterp.cs +++ b/src/api/dotnet/FuncInterp.cs @@ -91,6 +91,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_func_entry_inc_ref(ctx.nCtx, obj); @@ -197,6 +199,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_func_interp_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Goal.cs b/src/api/dotnet/Goal.cs index b108683c9..13c98f932 100644 --- a/src/api/dotnet/Goal.cs +++ b/src/api/dotnet/Goal.cs @@ -219,6 +219,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_goal_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/IDecRefQueue.cs b/src/api/dotnet/IDecRefQueue.cs index d741a8f05..a69e28ff2 100644 --- a/src/api/dotnet/IDecRefQueue.cs +++ b/src/api/dotnet/IDecRefQueue.cs @@ -40,7 +40,12 @@ namespace Microsoft.Z3 readonly internal protected Object m_lock = new Object(); readonly internal protected List m_queue = new List(); - internal const uint m_move_limit = 1024; + internal uint m_move_limit; + + public IDecRefQueue(uint move_limit = 1024) + { + m_move_limit = move_limit; + } public abstract void IncRef(Context ctx, IntPtr obj); public abstract void DecRef(Context ctx, IntPtr obj); diff --git a/src/api/dotnet/Model.cs b/src/api/dotnet/Model.cs index 5c0bc24f8..9cff1e667 100644 --- a/src/api/dotnet/Model.cs +++ b/src/api/dotnet/Model.cs @@ -291,6 +291,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_model_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/ParamDescrs.cs b/src/api/dotnet/ParamDescrs.cs index acfae1b85..a08e11859 100644 --- a/src/api/dotnet/ParamDescrs.cs +++ b/src/api/dotnet/ParamDescrs.cs @@ -87,6 +87,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_param_descrs_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Params.cs b/src/api/dotnet/Params.cs index 9a814b2ec..de2287af5 100644 --- a/src/api/dotnet/Params.cs +++ b/src/api/dotnet/Params.cs @@ -140,6 +140,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_params_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Probe.cs b/src/api/dotnet/Probe.cs index 1ae7ee064..e8907b294 100644 --- a/src/api/dotnet/Probe.cs +++ b/src/api/dotnet/Probe.cs @@ -73,6 +73,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_probe_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Solver.cs b/src/api/dotnet/Solver.cs index 9de515e86..2e12a5842 100644 --- a/src/api/dotnet/Solver.cs +++ b/src/api/dotnet/Solver.cs @@ -328,6 +328,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_solver_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Statistics.cs b/src/api/dotnet/Statistics.cs index 408995140..81240e2c0 100644 --- a/src/api/dotnet/Statistics.cs +++ b/src/api/dotnet/Statistics.cs @@ -189,6 +189,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_stats_inc_ref(ctx.nCtx, obj); diff --git a/src/api/dotnet/Tactic.cs b/src/api/dotnet/Tactic.cs index eb4ef085c..be79c2a43 100644 --- a/src/api/dotnet/Tactic.cs +++ b/src/api/dotnet/Tactic.cs @@ -114,6 +114,8 @@ namespace Microsoft.Z3 internal class DecRefQueue : IDecRefQueue { + public DecRefQueue() : base() { } + public DecRefQueue(uint move_limit) : base(move_limit) { } public override void IncRef(Context ctx, IntPtr obj) { Native.Z3_tactic_inc_ref(ctx.nCtx, obj); From b8b57a8a26d010412cf7acd0d98f2eefd365e617 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 30 Jan 2015 21:04:18 -0600 Subject: [PATCH 536/646] Improved memory use of the Java API. + formatting --- examples/java/JavaExample.java | 4 +- src/api/dotnet/Context.cs | 12 +- src/api/java/AST.java | 18 +- src/api/java/ASTDecRefQueue.java | 10 + src/api/java/ASTMap.java | 10 +- src/api/java/ASTVector.java | 8 +- src/api/java/ApplyResultDecRefQueue.java | 10 + src/api/java/ArithExpr.java | 14 +- src/api/java/ArithSort.java | 8 +- src/api/java/ArrayExpr.java | 14 +- src/api/java/ArraySort.java | 62 +- src/api/java/AstMapDecRefQueue.java | 10 + src/api/java/AstVectorDecRefQueue.java | 10 + src/api/java/BitVecExpr.java | 34 +- src/api/java/BitVecSort.java | 26 +- src/api/java/BoolExpr.java | 32 +- src/api/java/Constructor.java | 132 +- src/api/java/ConstructorList.java | 38 +- src/api/java/Context.java | 340 +- src/api/java/DatatypeExpr.java | 14 +- src/api/java/DatatypeSort.java | 150 +- src/api/java/EnumSort.java | 70 +- src/api/java/Expr.java | 4326 +++++++++--------- src/api/java/FPNum.java | 8 +- src/api/java/FPRMNum.java | 8 +- src/api/java/FPSort.java | 10 +- src/api/java/FiniteDomainSort.java | 38 +- src/api/java/Fixedpoint.java | 8 +- src/api/java/FixedpointDecRefQueue.java | 10 + src/api/java/FuncDecl.java | 4 +- src/api/java/FuncInterp.java | 330 +- src/api/java/FuncInterpDecRefQueue.java | 10 + src/api/java/FuncInterpEntryDecRefQueue.java | 10 + src/api/java/Global.java | 6 +- src/api/java/Goal.java | 8 +- src/api/java/GoalDecRefQueue.java | 10 + src/api/java/IDecRefQueue.java | 68 +- src/api/java/IDisposable.java | 6 +- src/api/java/IntExpr.java | 16 +- src/api/java/IntSort.java | 16 +- src/api/java/IntSymbol.java | 2 +- src/api/java/InterpolationContext.java | 4 +- src/api/java/Log.java | 4 +- src/api/java/Model.java | 14 +- src/api/java/ModelDecRefQueue.java | 10 + src/api/java/ParamDescrsDecRefQueue.java | 10 + src/api/java/ParamsDecRefQueue.java | 10 + src/api/java/ProbeDecRefQueue.java | 10 + src/api/java/Quantifier.java | 14 +- src/api/java/RatNum.java | 2 +- src/api/java/Solver.java | 86 +- src/api/java/SolverDecRefQueue.java | 7 + src/api/java/Sort.java | 18 +- src/api/java/Statistics.java | 2 +- src/api/java/StatisticsDecRefQueue.java | 10 + src/api/java/StringSymbol.java | 2 +- src/api/java/Tactic.java | 4 +- src/api/java/TacticDecRefQueue.java | 10 + src/api/java/Version.java | 2 +- src/api/java/Z3Object.java | 2 +- 60 files changed, 3149 insertions(+), 2992 deletions(-) diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index af8662700..64e4015e0 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -2169,8 +2169,8 @@ class JavaExample FPNum y = (FPNum)ctx.mkNumeral("-10", s); /* -10 */ FPNum z = (FPNum)ctx.mkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */ System.out.println("x=" + x.toString() + - "; y=" + y.toString() + - "; z=" + z.toString()); + "; y=" + y.toString() + + "; z=" + z.toString()); BoolExpr a = ctx.mkAnd(ctx.mkFPEq(x, y), ctx.mkFPEq(y, z)); check(ctx, ctx.mkNot(a), Status.UNSATISFIABLE); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 94baea35a..3c3a960df 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4399,16 +4399,16 @@ namespace Microsoft.Z3 readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(10); readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(10); readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(10); - readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(); - readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(); + readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(10); + readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(10); readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(10); readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(10); - readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(); - readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(); - readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(); + readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(10); + readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(10); + readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(10); readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(10); readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(10); - readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(); + readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(10); readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10); internal AST.DecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 0cdfd025c..fdb1643a5 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -29,7 +29,7 @@ public class AST extends Z3Object /** * Object comparison. * - * @param o another AST + * @param o another AST **/ public boolean equals(Object o) { @@ -48,7 +48,7 @@ public class AST extends Z3Object /** * Object Comparison. - * @param other Another AST + * @param other Another AST * * @return Negative if the object should be sorted before {@code other}, * positive if after else zero. @@ -102,7 +102,7 @@ public class AST extends Z3Object /** * Translates (copies) the AST to the Context {@code ctx}. - * @param ctx A context + * @param ctx A context * * @return A copy of the AST which is associated with {@code ctx} * @throws Z3Exception on error @@ -130,7 +130,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is an Expr * @throws Z3Exception on error - * @throws Z3Exception on error + * @throws Z3Exception on error **/ public boolean isExpr() throws Z3Exception { @@ -148,7 +148,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is an application - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isApp() throws Z3Exception @@ -158,7 +158,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a BoundVariable. - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isVar() throws Z3Exception @@ -168,7 +168,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a Quantifier - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isQuantifier() throws Z3Exception @@ -228,7 +228,7 @@ public class AST extends Z3Object { // Console.WriteLine("AST IncRef()"); if (getContext() == null || o == 0) - return; + return; getContext().ast_DRQ().incAndClear(getContext(), o); super.incRef(o); } @@ -237,7 +237,7 @@ public class AST extends Z3Object { // Console.WriteLine("AST DecRef()"); if (getContext() == null || o == 0) - return; + return; getContext().ast_DRQ().add(o); super.decRef(o); } diff --git a/src/api/java/ASTDecRefQueue.java b/src/api/java/ASTDecRefQueue.java index 6ae84eb41..a8ee83e57 100644 --- a/src/api/java/ASTDecRefQueue.java +++ b/src/api/java/ASTDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTDecRefQueue extends IDecRefQueue { + public ASTDecRefQueue() + { + super(); + } + + public ASTDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index 3d63939ca..96ddfbf76 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -24,7 +24,7 @@ class ASTMap extends Z3Object { /** * Checks whether the map contains the key {@code k}. - * @param k An AST + * @param k An AST * * @return True if {@code k} is a key in the map, false * otherwise. @@ -40,7 +40,7 @@ class ASTMap extends Z3Object * Finds the value associated with the key {@code k}. * Remarks: This function signs an error when {@code k} is not a key in * the map. - * @param k An AST + * @param k An AST * * @throws Z3Exception **/ @@ -52,8 +52,8 @@ class ASTMap extends Z3Object /** * Stores or replaces a new key/value pair in the map. - * @param k The key AST - * @param v The value AST + * @param k The key AST + * @param v The value AST **/ public void insert(AST k, AST v) throws Z3Exception { @@ -64,7 +64,7 @@ class ASTMap extends Z3Object /** * Erases the key {@code k} from the map. - * @param k An AST + * @param k An AST **/ public void erase(AST k) throws Z3Exception { diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index d4df02244..30c96e2e7 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -34,7 +34,7 @@ class ASTVector extends Z3Object * Retrieves the i-th object in the vector. * Remarks: May throw an {@code IndexOutOfBoundsException} when * {@code i} is out of range. - * @param i Index + * @param i Index * * @return An AST * @throws Z3Exception @@ -54,7 +54,7 @@ class ASTVector extends Z3Object /** * Resize the vector to {@code newSize}. - * @param newSize The new size of the vector. + * @param newSize The new size of the vector. **/ public void resize(int newSize) throws Z3Exception { @@ -64,7 +64,7 @@ class ASTVector extends Z3Object /** * Add the AST {@code a} to the back of the vector. The size is * increased by 1. - * @param a An AST + * @param a An AST **/ public void push(AST a) throws Z3Exception { @@ -73,7 +73,7 @@ class ASTVector extends Z3Object /** * Translates all ASTs in the vector to {@code ctx}. - * @param ctx A context + * @param ctx A context * * @return A new ASTVector * @throws Z3Exception diff --git a/src/api/java/ApplyResultDecRefQueue.java b/src/api/java/ApplyResultDecRefQueue.java index 78f74d6cc..4cdf312fe 100644 --- a/src/api/java/ApplyResultDecRefQueue.java +++ b/src/api/java/ApplyResultDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ApplyResultDecRefQueue extends IDecRefQueue { + public ApplyResultDecRefQueue() + { + super(); + } + + public ApplyResultDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index 996b98afc..240518134 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -22,11 +22,11 @@ package com.microsoft.z3; **/ public class ArithExpr extends Expr { - /** - * Constructor for ArithExpr - **/ - ArithExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for ArithExpr + **/ + ArithExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/ArithSort.java b/src/api/java/ArithSort.java index 2346d9b74..848d23554 100644 --- a/src/api/java/ArithSort.java +++ b/src/api/java/ArithSort.java @@ -22,8 +22,8 @@ package com.microsoft.z3; **/ public class ArithSort extends Sort { - ArithSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ArithSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } }; diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index 154a56af4..4e6d9ed4d 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -23,11 +23,11 @@ package com.microsoft.z3; **/ public class ArrayExpr extends Expr { - /** - * Constructor for ArrayExpr - **/ - ArrayExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for ArrayExpr + **/ + ArrayExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/ArraySort.java b/src/api/java/ArraySort.java index ab545b7c1..a5b52a8f5 100644 --- a/src/api/java/ArraySort.java +++ b/src/api/java/ArraySort.java @@ -22,38 +22,38 @@ package com.microsoft.z3; **/ public class ArraySort extends Sort { - /** - * The domain of the array sort. - * @throws Z3Exception - * @throws Z3Exception on error - * @return a sort - **/ - public Sort getDomain() throws Z3Exception - { - return Sort.create(getContext(), - Native.getArraySortDomain(getContext().nCtx(), getNativeObject())); - } + /** + * The domain of the array sort. + * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort + **/ + public Sort getDomain() throws Z3Exception + { + return Sort.create(getContext(), + Native.getArraySortDomain(getContext().nCtx(), getNativeObject())); + } - /** - * The range of the array sort. - * @throws Z3Exception - * @throws Z3Exception on error - * @return a sort - **/ - public Sort getRange() throws Z3Exception - { - return Sort.create(getContext(), - Native.getArraySortRange(getContext().nCtx(), getNativeObject())); - } + /** + * The range of the array sort. + * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort + **/ + public Sort getRange() throws Z3Exception + { + return Sort.create(getContext(), + Native.getArraySortRange(getContext().nCtx(), getNativeObject())); + } - ArraySort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ArraySort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - ArraySort(Context ctx, Sort domain, Sort range) throws Z3Exception - { - super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(), - range.getNativeObject())); - } + ArraySort(Context ctx, Sort domain, Sort range) throws Z3Exception + { + super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(), + range.getNativeObject())); + } }; diff --git a/src/api/java/AstMapDecRefQueue.java b/src/api/java/AstMapDecRefQueue.java index a4e02d29f..2106ff0c2 100644 --- a/src/api/java/AstMapDecRefQueue.java +++ b/src/api/java/AstMapDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTMapDecRefQueue extends IDecRefQueue { + public ASTMapDecRefQueue() + { + super(); + } + + public ASTMapDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/AstVectorDecRefQueue.java b/src/api/java/AstVectorDecRefQueue.java index e0c7988a9..698e9e06b 100644 --- a/src/api/java/AstVectorDecRefQueue.java +++ b/src/api/java/AstVectorDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTVectorDecRefQueue extends IDecRefQueue { + public ASTVectorDecRefQueue() + { + super(); + } + + public ASTVectorDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 69a97de40..926a26b25 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -23,22 +23,22 @@ package com.microsoft.z3; public class BitVecExpr extends Expr { - /** - * The size of the sort of a bit-vector term. - * @throws Z3Exception - * @throws Z3Exception on error - * @return an int - **/ - public int getSortSize() throws Z3Exception - { - return ((BitVecSort) getSort()).getSize(); - } + /** + * The size of the sort of a bit-vector term. + * @throws Z3Exception + * @throws Z3Exception on error + * @return an int + **/ + public int getSortSize() throws Z3Exception + { + return ((BitVecSort) getSort()).getSize(); + } - /** - * Constructor for BitVecExpr - **/ - BitVecExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for BitVecExpr + **/ + BitVecExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/BitVecSort.java b/src/api/java/BitVecSort.java index 69d74151c..7fd644acb 100644 --- a/src/api/java/BitVecSort.java +++ b/src/api/java/BitVecSort.java @@ -22,18 +22,18 @@ package com.microsoft.z3; **/ public class BitVecSort extends Sort { - /** - * The size of the bit-vector sort. - * @throws Z3Exception on error - * @return an int - **/ - public int getSize() throws Z3Exception - { - return Native.getBvSortSize(getContext().nCtx(), getNativeObject()); - } + /** + * The size of the bit-vector sort. + * @throws Z3Exception on error + * @return an int + **/ + public int getSize() throws Z3Exception + { + return Native.getBvSortSize(getContext().nCtx(), getNativeObject()); + } - BitVecSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + BitVecSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } }; diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index ea3cdbfb4..6709e2ae9 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -22,21 +22,21 @@ package com.microsoft.z3; **/ public class BoolExpr extends Expr { - /** - * Constructor for BoolExpr - **/ - protected BoolExpr(Context ctx) - { - super(ctx); - } + /** + * Constructor for BoolExpr + **/ + protected BoolExpr(Context ctx) + { + super(ctx); + } - /** - * Constructor for BoolExpr - * @throws Z3Exception - * @throws Z3Exception on error - **/ - BoolExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for BoolExpr + * @throws Z3Exception + * @throws Z3Exception on error + **/ + BoolExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/Constructor.java b/src/api/java/Constructor.java index a5440092c..95e7799e1 100644 --- a/src/api/java/Constructor.java +++ b/src/api/java/Constructor.java @@ -22,53 +22,53 @@ package com.microsoft.z3; **/ public class Constructor extends Z3Object { - /** - * The number of fields of the constructor. - * @throws Z3Exception - * @throws Z3Exception on error - * @return an int - **/ - public int getNumFields() throws Z3Exception - { - return n; - } + /** + * The number of fields of the constructor. + * @throws Z3Exception + * @throws Z3Exception on error + * @return an int + **/ + public int getNumFields() throws Z3Exception + { + return n; + } - /** - * The function declaration of the constructor. - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl ConstructorDecl() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); - Native.LongPtr tester = new Native.LongPtr(); - long[] accessors = new long[n]; + /** + * The function declaration of the constructor. + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl ConstructorDecl() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); + Native.LongPtr tester = new Native.LongPtr(); + long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); return new FuncDecl(getContext(), constructor.value); - } + } - /** - * The function declaration of the tester. - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl getTesterDecl() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); + /** + * The function declaration of the tester. + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl getTesterDecl() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); return new FuncDecl(getContext(), tester.value); - } + } - /** - * The function declarations of the accessors - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl[] getAccessorDecls() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); + /** + * The function declarations of the accessors + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl[] getAccessorDecls() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); @@ -76,40 +76,40 @@ public class Constructor extends Z3Object for (int i = 0; i < n; i++) t[i] = new FuncDecl(getContext(), accessors[i]); return t; - } + } - /** - * Destructor. - * @throws Z3Exception on error - **/ - protected void finalize() throws Z3Exception - { - Native.delConstructor(getContext().nCtx(), getNativeObject()); - } + /** + * Destructor. + * @throws Z3Exception on error + **/ + protected void finalize() throws Z3Exception + { + Native.delConstructor(getContext().nCtx(), getNativeObject()); + } - private int n = 0; + private int n = 0; - Constructor(Context ctx, Symbol name, Symbol recognizer, - Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) - throws Z3Exception - { - super(ctx); + Constructor(Context ctx, Symbol name, Symbol recognizer, + Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) + throws Z3Exception + { + super(ctx); - n = AST.arrayLength(fieldNames); + n = AST.arrayLength(fieldNames); - if (n != AST.arrayLength(sorts)) - throw new Z3Exception( - "Number of field names does not match number of sorts"); - if (sortRefs != null && sortRefs.length != n) - throw new Z3Exception( - "Number of field names does not match number of sort refs"); + if (n != AST.arrayLength(sorts)) + throw new Z3Exception( + "Number of field names does not match number of sorts"); + if (sortRefs != null && sortRefs.length != n) + throw new Z3Exception( + "Number of field names does not match number of sort refs"); - if (sortRefs == null) - sortRefs = new int[n]; + if (sortRefs == null) + sortRefs = new int[n]; - setNativeObject(Native.mkConstructor(ctx.nCtx(), name.getNativeObject(), - recognizer.getNativeObject(), n, Symbol.arrayToNative(fieldNames), - Sort.arrayToNative(sorts), sortRefs)); + setNativeObject(Native.mkConstructor(ctx.nCtx(), name.getNativeObject(), + recognizer.getNativeObject(), n, Symbol.arrayToNative(fieldNames), + Sort.arrayToNative(sorts), sortRefs)); - } + } } diff --git a/src/api/java/ConstructorList.java b/src/api/java/ConstructorList.java index b38678b8a..0cff4cfa4 100644 --- a/src/api/java/ConstructorList.java +++ b/src/api/java/ConstructorList.java @@ -22,26 +22,26 @@ package com.microsoft.z3; **/ public class ConstructorList extends Z3Object { - /** - * Destructor. - * @throws Z3Exception on error - **/ - protected void finalize() throws Z3Exception - { - Native.delConstructorList(getContext().nCtx(), getNativeObject()); - } + /** + * Destructor. + * @throws Z3Exception on error + **/ + protected void finalize() throws Z3Exception + { + Native.delConstructorList(getContext().nCtx(), getNativeObject()); + } - ConstructorList(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ConstructorList(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - ConstructorList(Context ctx, Constructor[] constructors) throws Z3Exception - { - super(ctx); + ConstructorList(Context ctx, Constructor[] constructors) throws Z3Exception + { + super(ctx); - setNativeObject(Native.mkConstructorList(getContext().nCtx(), - (int) constructors.length, - Constructor.arrayToNative(constructors))); - } + setNativeObject(Native.mkConstructorList(getContext().nCtx(), + (int) constructors.length, + Constructor.arrayToNative(constructors))); + } } diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 294826f55..42fd0f7e1 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -261,12 +261,12 @@ public class Context extends IDisposable /** * Create a datatype constructor. - * @param name constructor name - * @param recognizer name of recognizer function. - * @param fieldNames names of the constructor fields. - * @param sorts field sorts, 0 if the field sort refers to a recursive sort. - * @param sortRefs reference to datatype sort that is an argument to the - * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be + * @param name constructor name + * @param recognizer name of recognizer function. + * @param fieldNames names of the constructor fields. + * @param sorts field sorts, 0 if the field sort refers to a recursive sort. + * @param sortRefs reference to datatype sort that is an argument to the + * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be * an index referring to one of the recursive datatypes that is * declared. **/ @@ -281,11 +281,11 @@ public class Context extends IDisposable /** * Create a datatype constructor. - * @param name - * @param recognizer - * @param fieldNames - * @param sorts - * @param sortRefs + * @param name + * @param recognizer + * @param fieldNames + * @param sorts + * @param sortRefs * * @return **/ @@ -321,8 +321,8 @@ public class Context extends IDisposable /** * Create mutually recursive datatypes. - * @param names names of datatype sorts - * @param c list of constructors, one list per sort. + * @param names names of datatype sorts + * @param c list of constructors, one list per sort. **/ public DatatypeSort[] mkDatatypeSorts(Symbol[] names, Constructor[][] c) throws Z3Exception @@ -350,8 +350,8 @@ public class Context extends IDisposable /** * Create mutually recursive data-types. - * @param names - * @param c + * @param names + * @param c * * @return **/ @@ -412,7 +412,7 @@ public class Context extends IDisposable /** * Creates a fresh function declaration with a name prefixed with * {@code prefix}. - * @see mkFuncDecl(String,Sort,Sort) + * @see mkFuncDecl(String,Sort,Sort) * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) @@ -457,8 +457,8 @@ public class Context extends IDisposable /** * Creates a new bound variable. - * @param index The de-Bruijn index of the variable - * @param ty The sort of the variable + * @param index The de-Bruijn index of the variable + * @param ty The sort of the variable **/ public Expr mkBound(int index, Sort ty) throws Z3Exception { @@ -516,7 +516,7 @@ public class Context extends IDisposable /** * Creates a fresh constant from the FuncDecl {@code f}. - * @param f A decl of a 0-arity function + * @param f A decl of a 0-arity function **/ public Expr mkConst(FuncDecl f) throws Z3Exception { @@ -654,9 +654,9 @@ public class Context extends IDisposable /** * Create an expression representing an if-then-else: * {@code ite(t1, t2, t3)}. - * @param t1 An expression with Boolean sort - * @param t2 An expression - * @param t3 An expression with the same sort as {@code t2} + * @param t1 An expression with Boolean sort + * @param t2 An expression + * @param t3 An expression with the same sort as {@code t2} **/ public Expr mkITE(BoolExpr t1, Expr t2, Expr t3) throws Z3Exception { @@ -773,7 +773,7 @@ public class Context extends IDisposable /** * Create an expression representing {@code t1 mod t2}. - * Remarks: The + * Remarks: The * arguments must have int type. **/ public IntExpr mkMod(IntExpr t1, IntExpr t2) throws Z3Exception @@ -786,7 +786,7 @@ public class Context extends IDisposable /** * Create an expression representing {@code t1 rem t2}. - * Remarks: The + * Remarks: The * arguments must have int type. **/ public IntExpr mkRem(IntExpr t1, IntExpr t2) throws Z3Exception @@ -856,7 +856,7 @@ public class Context extends IDisposable /** * Coerce an integer to a real. - * Remarks: There is also a converse operation + * Remarks: There is also a converse operation * exposed. It follows the semantics prescribed by the SMT-LIB standard. * * You can take the floor of a real by creating an auxiliary integer Term @@ -873,7 +873,7 @@ public class Context extends IDisposable /** * Coerce a real to an integer. - * Remarks: The semantics of this function + * Remarks: The semantics of this function * follows the SMT-LIB standard for the function to_int. The argument must * be of real sort. **/ @@ -894,7 +894,7 @@ public class Context extends IDisposable /** * Bitwise negation. - * Remarks: The argument must have a bit-vector + * Remarks: The argument must have a bit-vector * sort. **/ public BitVecExpr mkBVNot(BitVecExpr t) throws Z3Exception @@ -906,7 +906,7 @@ public class Context extends IDisposable /** * Take conjunction of bits in a vector, return vector of length 1. * - * Remarks: The argument must have a bit-vector sort. + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedAND(BitVecExpr t) throws Z3Exception { @@ -918,7 +918,7 @@ public class Context extends IDisposable /** * Take disjunction of bits in a vector, return vector of length 1. * - * Remarks: The argument must have a bit-vector sort. + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedOR(BitVecExpr t) throws Z3Exception { @@ -929,7 +929,7 @@ public class Context extends IDisposable /** * Bitwise conjunction. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -942,7 +942,7 @@ public class Context extends IDisposable /** * Bitwise disjunction. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -955,7 +955,7 @@ public class Context extends IDisposable /** * Bitwise XOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVXOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -968,7 +968,7 @@ public class Context extends IDisposable /** * Bitwise NAND. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVNAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -981,7 +981,7 @@ public class Context extends IDisposable /** * Bitwise NOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -994,7 +994,7 @@ public class Context extends IDisposable /** * Bitwise XNOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVXNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1007,7 +1007,7 @@ public class Context extends IDisposable /** * Standard two's complement unary minus. - * Remarks: The arguments must have a + * Remarks: The arguments must have a * bit-vector sort. **/ public BitVecExpr mkBVNeg(BitVecExpr t) throws Z3Exception @@ -1018,7 +1018,7 @@ public class Context extends IDisposable /** * Two's complement addition. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BitVecExpr mkBVAdd(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1031,7 +1031,7 @@ public class Context extends IDisposable /** * Two's complement subtraction. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BitVecExpr mkBVSub(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1044,7 +1044,7 @@ public class Context extends IDisposable /** * Two's complement multiplication. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BitVecExpr mkBVMul(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1057,7 +1057,7 @@ public class Context extends IDisposable /** * Unsigned division. - * Remarks: It is defined as the floor of + * Remarks: It is defined as the floor of * {@code t1/t2} if \c t2 is different from zero. If {@code t2} is * zero, then the result is undefined. The arguments must have the same * bit-vector sort. @@ -1072,7 +1072,7 @@ public class Context extends IDisposable /** * Signed division. - * Remarks: It is defined in the following way: + * Remarks: It is defined in the following way: * * - The \c floor of {@code t1/t2} if \c t2 is different from zero, and * {@code t1*t2 >= 0}. @@ -1093,7 +1093,7 @@ public class Context extends IDisposable /** * Unsigned remainder. - * Remarks: It is defined as + * Remarks: It is defined as * {@code t1 - (t1 /u t2) * t2}, where {@code /u} represents * unsigned division. If {@code t2} is zero, then the result is * undefined. The arguments must have the same bit-vector sort. @@ -1108,7 +1108,7 @@ public class Context extends IDisposable /** * Signed remainder. - * Remarks: It is defined as + * Remarks: It is defined as * {@code t1 - (t1 /s t2) * t2}, where {@code /s} represents * signed division. The most significant bit (sign) of the result is equal * to the most significant bit of \c t1. @@ -1126,7 +1126,7 @@ public class Context extends IDisposable /** * Two's complement signed remainder (sign follows divisor). - * Remarks: If + * Remarks: If * {@code t2} is zero, then the result is undefined. The arguments must * have the same bit-vector sort. **/ @@ -1140,7 +1140,7 @@ public class Context extends IDisposable /** * Unsigned less-than - * Remarks: The arguments must have the same bit-vector + * Remarks: The arguments must have the same bit-vector * sort. **/ public BoolExpr mkBVULT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1153,7 +1153,7 @@ public class Context extends IDisposable /** * Two's complement signed less-than - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVSLT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1166,7 +1166,7 @@ public class Context extends IDisposable /** * Unsigned less-than or equal to. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVULE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1179,7 +1179,7 @@ public class Context extends IDisposable /** * Two's complement signed less-than or equal to. - * Remarks: The arguments + * Remarks: The arguments * must have the same bit-vector sort. **/ public BoolExpr mkBVSLE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1192,7 +1192,7 @@ public class Context extends IDisposable /** * Unsigned greater than or equal to. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVUGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1205,7 +1205,7 @@ public class Context extends IDisposable /** * Two's complement signed greater than or equal to. - * Remarks: The arguments + * Remarks: The arguments * must have the same bit-vector sort. **/ public BoolExpr mkBVSGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1218,7 +1218,7 @@ public class Context extends IDisposable /** * Unsigned greater-than. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BoolExpr mkBVUGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1231,7 +1231,7 @@ public class Context extends IDisposable /** * Two's complement signed greater-than. - * Remarks: The arguments must have + * Remarks: The arguments must have * the same bit-vector sort. **/ public BoolExpr mkBVSGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1244,7 +1244,7 @@ public class Context extends IDisposable /** * Bit-vector concatenation. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. * * @return The result is a bit-vector of size {@code n1+n2}, where @@ -1262,7 +1262,7 @@ public class Context extends IDisposable /** * Bit-vector extraction. - * Remarks: Extract the bits {@code high} + * Remarks: Extract the bits {@code high} * down to {@code low} from a bitvector of size {@code m} to * yield a new bitvector of size {@code n}, where * {@code n = high - low + 1}. The argument {@code t} must @@ -1278,7 +1278,7 @@ public class Context extends IDisposable /** * Bit-vector sign extension. - * Remarks: Sign-extends the given bit-vector to + * Remarks: Sign-extends the given bit-vector to * the (signed) equivalent bitvector of size {@code m+i}, where \c m is * the size of the given bit-vector. The argument {@code t} must * have a bit-vector sort. @@ -1292,7 +1292,7 @@ public class Context extends IDisposable /** * Bit-vector zero extension. - * Remarks: Extend the given bit-vector with + * Remarks: Extend the given bit-vector with * zeros to the (unsigned) equivalent bitvector of size {@code m+i}, * where \c m is the size of the given bit-vector. The argument {@code t} * must have a bit-vector sort. @@ -1306,7 +1306,7 @@ public class Context extends IDisposable /** * Bit-vector repetition. - * Remarks: The argument {@code t} must + * Remarks: The argument {@code t} must * have a bit-vector sort. **/ public BitVecExpr mkRepeat(int i, BitVecExpr t) throws Z3Exception @@ -1318,7 +1318,7 @@ public class Context extends IDisposable /** * Shift left. - * Remarks: It is equivalent to multiplication by + * Remarks: It is equivalent to multiplication by * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This @@ -1337,7 +1337,7 @@ public class Context extends IDisposable /** * Logical shift right - * Remarks: It is equivalent to unsigned division by + * Remarks: It is equivalent to unsigned division by * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This @@ -1356,7 +1356,7 @@ public class Context extends IDisposable /** * Arithmetic shift right - * Remarks: It is like logical shift right except + * Remarks: It is like logical shift right except * that the most significant bits of the result always copy the most * significant bit of the second argument. * @@ -1376,7 +1376,7 @@ public class Context extends IDisposable /** * Rotate Left. - * Remarks: Rotate bits of \c t to the left \c i times. The + * Remarks: Rotate bits of \c t to the left \c i times. The * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateLeft(int i, BitVecExpr t) throws Z3Exception @@ -1388,7 +1388,7 @@ public class Context extends IDisposable /** * Rotate Right. - * Remarks: Rotate bits of \c t to the right \c i times. The + * Remarks: Rotate bits of \c t to the right \c i times. The * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateRight(int i, BitVecExpr t) throws Z3Exception @@ -1400,7 +1400,7 @@ public class Context extends IDisposable /** * Rotate Left. - * Remarks: Rotate bits of {@code t1} to the left + * Remarks: Rotate bits of {@code t1} to the left * {@code t2} times. The arguments must have the same bit-vector * sort. **/ @@ -1415,7 +1415,7 @@ public class Context extends IDisposable /** * Rotate Right. - * Remarks: Rotate bits of {@code t1} to the + * Remarks: Rotate bits of {@code t1} to the * right{@code t2} times. The arguments must have the same * bit-vector sort. **/ @@ -1431,7 +1431,7 @@ public class Context extends IDisposable /** * Create an {@code n} bit bit-vector from the integer argument * {@code t}. - * Remarks: NB. This function is essentially treated + * Remarks: NB. This function is essentially treated * as uninterpreted. So you cannot expect Z3 to precisely reflect the * semantics of this function when solving constraints with this function. * @@ -1468,7 +1468,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1483,7 +1483,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1497,7 +1497,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1511,7 +1511,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1526,7 +1526,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise signed division does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1540,7 +1540,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise negation does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVNegNoOverflow(BitVecExpr t) throws Z3Exception { @@ -1552,7 +1552,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1567,7 +1567,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1598,15 +1598,15 @@ public class Context extends IDisposable /** * Array read. - * Remarks: The argument {@code a} is the array and + * Remarks: The argument {@code a} is the array and * {@code i} is the index of the array that gets read. * * The node {@code a} must have an array sort * {@code [domain -> range]}, and {@code i} must have the sort * {@code domain}. The sort of the result is {@code range}. * - * @see mkArraySort - * @see mkStore + * @see mkArraySort + * @see mkStore **/ public Expr mkSelect(ArrayExpr a, Expr i) throws Z3Exception @@ -1621,7 +1621,7 @@ public class Context extends IDisposable /** * Array update. - * Remarks: The node {@code a} must have an array sort + * Remarks: The node {@code a} must have an array sort * {@code [domain -> range]}, {@code i} must have sort * {@code domain}, {@code v} must have sort range. The sort of the * result is {@code [domain -> range]}. The semantics of this function @@ -1631,8 +1631,8 @@ public class Context extends IDisposable * {@code select}) on all indices except for {@code i}, where it * maps to {@code v} (and the {@code select} of {@code a} * with respect to {@code i} may be a different value). - * @see mkArraySort - * @see mkSelect + * @see mkArraySort + * @see mkSelect **/ public ArrayExpr mkStore(ArrayExpr a, Expr i, Expr v) throws Z3Exception @@ -1646,11 +1646,11 @@ public class Context extends IDisposable /** * Create a constant array. - * Remarks: The resulting term is an array, such + * Remarks: The resulting term is an array, such * that a {@code select} on an arbitrary index produces the value * {@code v}. - * @see mkArraySort - * @see mkSelect + * @see mkArraySort + * @see mkSelect * **/ public ArrayExpr mkConstArray(Sort domain, Expr v) throws Z3Exception @@ -1663,15 +1663,15 @@ public class Context extends IDisposable /** * Maps f on the argument arrays. - * Remarks: Eeach element of + * Remarks: Eeach element of * {@code args} must be of an array sort * {@code [domain_i -> range_i]}. The function declaration * {@code f} must have type {@code range_1 .. range_n -> range}. * {@code v} must have sort range. The sort of the result is * {@code [domain_i -> range]}. - * @see mkArraySort - * @see mkSelect - * @see mkStore + * @see mkArraySort + * @see mkSelect + * @see mkStore **/ public ArrayExpr mkMap(FuncDecl f, ArrayExpr... args) throws Z3Exception @@ -1685,7 +1685,7 @@ public class Context extends IDisposable /** * Access the array default value. - * Remarks: Produces the default range + * Remarks: Produces the default range * value, for arrays that can be represented as finite maps with a default * range value. **/ @@ -1826,10 +1826,10 @@ public class Context extends IDisposable /** * Create a Term of a given sort. - * @param v A string representing the term value in decimal notation. If the given sort is a real, then the + * @param v A string representing the term value in decimal notation. If the given sort is a real, then the * Term can be a rational, that is, a string of the form * {@code [num]* / [num]*}. - * @param ty The sort of the + * @param ty The sort of the * numeral. In the current implementation, the given sort can be an int, * real, or bit-vectors of arbitrary size. * @@ -1847,8 +1847,8 @@ public class Context extends IDisposable * numerals that fit in a machine integer. It is slightly faster than * {@code MakeNumeral} since it is not necessary to parse a string. * - * @param v Value of the numeral - * @param ty Sort of the numeral + * @param v Value of the numeral + * @param ty Sort of the numeral * * @return A Term with value {@code v} and type {@code ty} **/ @@ -1863,8 +1863,8 @@ public class Context extends IDisposable * numerals that fit in a machine integer. It is slightly faster than * {@code MakeNumeral} since it is not necessary to parse a string. * - * @param v Value of the numeral - * @param ty Sort of the numeral + * @param v Value of the numeral + * @param ty Sort of the numeral * * @return A Term with value {@code v} and type {@code ty} **/ @@ -1877,12 +1877,12 @@ public class Context extends IDisposable /** * Create a real from a fraction. - * @param num numerator of rational. - * @param den denominator of rational. + * @param num numerator of rational. + * @param den denominator of rational. * * @return A Term with value {@code num}/{@code den} * and sort Real - * @see mkNumeral(String,Sort) + * @see mkNumeral(String,Sort) **/ public RatNum mkReal(int num, int den) throws Z3Exception { @@ -1894,7 +1894,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v A string representing the Term value in decimal notation. + * @param v A string representing the Term value in decimal notation. * * @return A Term with value {@code v} and sort Real **/ @@ -1907,7 +1907,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Real **/ @@ -1920,7 +1920,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Real **/ @@ -1933,7 +1933,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v A string representing the Term value in decimal notation. + * @param v A string representing the Term value in decimal notation. **/ public IntNum mkInt(String v) throws Z3Exception { @@ -1944,7 +1944,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Integer **/ @@ -1957,7 +1957,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Integer **/ @@ -1970,8 +1970,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v A string representing the value in decimal notation. - * @param size the size of the bit-vector + * @param v A string representing the value in decimal notation. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(String v, int size) throws Z3Exception { @@ -1980,8 +1980,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v value of the numeral. - * @param size the size of the bit-vector + * @param v value of the numeral. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(int v, int size) throws Z3Exception { @@ -1990,8 +1990,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v value of the numeral. * - * @param size the size of the bit-vector + * @param v value of the numeral. * + * @param size the size of the bit-vector **/ public BitVecNum mkBV(long v, int size) throws Z3Exception { @@ -2000,16 +2000,16 @@ public class Context extends IDisposable /** * Create a universal Quantifier. - * @param sorts the sorts of the bound variables. - * @param names names of the bound variables - * @param body the body of the quantifier. - * @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + * @param sorts the sorts of the bound variables. + * @param names names of the bound variables + * @param body the body of the quantifier. + * @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. * @param patterns array containing the patterns created using {@code MkPattern}. - * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. - * @param quantifierID optional symbol to track quantifier. - * @param skolemID optional symbol to track skolem constants. - * - * Remarks: Creates a forall formula, where + * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. + * @param quantifierID optional symbol to track quantifier. + * @param skolemID optional symbol to track skolem constants. + * + * Remarks: Creates a forall formula, where * {@code weight"/> is the weight, to every subgoal produced by 1) - res += "["; - Expr[] args = e.getArgs(); - for (int i = 0; i < n; i++) - { - if (i != 0) - res += ", "; - res += args[i]; - } - if (n > 1) - res += "]"; - res += " -> " + e.getValue() + ", "; - } - res += "else -> " + getElse(); - res += "]"; - return res; - } catch (Z3Exception e) - { - return new String("Z3Exception: " + e.getMessage()); - } - } + /** + * A string representation of the function interpretation. + **/ + public String toString() + { + try + { + String res = ""; + res += "["; + for (Entry e : getEntries()) + { + int n = e.getNumArgs(); + if (n > 1) + res += "["; + Expr[] args = e.getArgs(); + for (int i = 0; i < n; i++) + { + if (i != 0) + res += ", "; + res += args[i]; + } + if (n > 1) + res += "]"; + res += " -> " + e.getValue() + ", "; + } + res += "else -> " + getElse(); + res += "]"; + return res; + } catch (Z3Exception e) + { + return new String("Z3Exception: " + e.getMessage()); + } + } - FuncInterp(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + FuncInterp(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - void incRef(long o) throws Z3Exception - { - getContext().funcInterp_DRQ().incAndClear(getContext(), o); - super.incRef(o); - } + void incRef(long o) throws Z3Exception + { + getContext().funcInterp_DRQ().incAndClear(getContext(), o); + super.incRef(o); + } - void decRef(long o) throws Z3Exception - { - getContext().funcInterp_DRQ().add(o); - super.decRef(o); - } + void decRef(long o) throws Z3Exception + { + getContext().funcInterp_DRQ().add(o); + super.decRef(o); + } } diff --git a/src/api/java/FuncInterpDecRefQueue.java b/src/api/java/FuncInterpDecRefQueue.java index 8bdad4ad5..56660d2f9 100644 --- a/src/api/java/FuncInterpDecRefQueue.java +++ b/src/api/java/FuncInterpDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class FuncInterpDecRefQueue extends IDecRefQueue { + public FuncInterpDecRefQueue() + { + super(); + } + + public FuncInterpDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/FuncInterpEntryDecRefQueue.java b/src/api/java/FuncInterpEntryDecRefQueue.java index 494c2695c..406c0b33a 100644 --- a/src/api/java/FuncInterpEntryDecRefQueue.java +++ b/src/api/java/FuncInterpEntryDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class FuncInterpEntryDecRefQueue extends IDecRefQueue { + public FuncInterpEntryDecRefQueue() + { + super(); + } + + public FuncInterpEntryDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Global.java b/src/api/java/Global.java index b31c4a7ae..44fb4cac7 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -44,7 +44,7 @@ public final class Global **/ public static void setParameter(String id, String value) { - Native.globalParamSet(id, value); + Native.globalParamSet(id, value); } /** @@ -67,10 +67,10 @@ public final class Global * Restore the value of all global (and module) parameters. * Remarks: * This command will not affect already created objects (such as tactics and solvers) - * @see setParameter + * @see setParameter **/ public static void resetParameters() { - Native.globalParamResetAll(); + Native.globalParamResetAll(); } } diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index 5a9221b63..b6897c517 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -27,7 +27,7 @@ public class Goal extends Z3Object { /** * The precision of the goal. - * Remarks: Goals can be transformed using over + * Remarks: Goals can be transformed using over * and under approximations. An under approximation is applied when the * objective is to find a model for a given goal. An over approximation is * applied when the objective is to find a proof for a given goal. @@ -97,7 +97,7 @@ public class Goal extends Z3Object /** * The depth of the goal. - * Remarks: This tracks how many transformations + * Remarks: This tracks how many transformations * were applied to it. **/ public int getDepth() throws Z3Exception @@ -176,7 +176,7 @@ public class Goal extends Z3Object /** * Simplifies the goal. - * Remarks: Essentially invokes the `simplify' tactic + * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ public Goal simplify() throws Z3Exception @@ -192,7 +192,7 @@ public class Goal extends Z3Object /** * Simplifies the goal. - * Remarks: Essentially invokes the `simplify' tactic + * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ public Goal simplify(Params p) throws Z3Exception diff --git a/src/api/java/GoalDecRefQueue.java b/src/api/java/GoalDecRefQueue.java index 45992170f..dd9d69414 100644 --- a/src/api/java/GoalDecRefQueue.java +++ b/src/api/java/GoalDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class GoalDecRefQueue extends IDecRefQueue { + public GoalDecRefQueue() + { + super(); + } + + public GoalDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/IDecRefQueue.java b/src/api/java/IDecRefQueue.java index 2190f8e4d..e8cab3477 100644 --- a/src/api/java/IDecRefQueue.java +++ b/src/api/java/IDecRefQueue.java @@ -21,39 +21,49 @@ import java.util.LinkedList; abstract class IDecRefQueue { - protected Object m_lock = new Object(); - protected LinkedList m_queue = new LinkedList(); - protected final int m_move_limit = 1024; + protected Object m_lock = new Object(); + protected LinkedList m_queue = new LinkedList(); + protected int m_move_limit; - protected abstract void incRef(Context ctx, long obj); + public IDecRefQueue() + { + m_move_limit = 1024; + } - protected abstract void decRef(Context ctx, long obj); + public IDecRefQueue(int move_limit) + { + m_move_limit = move_limit; + } - protected void incAndClear(Context ctx, long o) - { - incRef(ctx, o); - if (m_queue.size() >= m_move_limit) - clear(ctx); - } + protected abstract void incRef(Context ctx, long obj); - protected void add(long o) - { - if (o == 0) - return; + protected abstract void decRef(Context ctx, long obj); - synchronized (m_lock) - { - m_queue.add(o); - } - } + protected void incAndClear(Context ctx, long o) + { + incRef(ctx, o); + if (m_queue.size() >= m_move_limit) + clear(ctx); + } - protected void clear(Context ctx) - { - synchronized (m_lock) - { - for (Long o : m_queue) - decRef(ctx, o); - m_queue.clear(); - } - } + protected void add(long o) + { + if (o == 0) + return; + + synchronized (m_lock) + { + m_queue.add(o); + } + } + + protected void clear(Context ctx) + { + synchronized (m_lock) + { + for (Long o : m_queue) + decRef(ctx, o); + m_queue.clear(); + } + } } diff --git a/src/api/java/IDisposable.java b/src/api/java/IDisposable.java index 9092213e3..dddfa5824 100644 --- a/src/api/java/IDisposable.java +++ b/src/api/java/IDisposable.java @@ -21,7 +21,7 @@ package com.microsoft.z3; public class IDisposable { - public void dispose() throws Z3Exception - { - } + public void dispose() throws Z3Exception + { + } } diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index 642a58a54..a424cd51e 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class IntExpr extends ArithExpr { - /** - * Constructor for IntExpr - * @throws Z3Exception on error - **/ - IntExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for IntExpr + * @throws Z3Exception on error + **/ + IntExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/IntSort.java b/src/api/java/IntSort.java index bcfc730c4..0b1047718 100644 --- a/src/api/java/IntSort.java +++ b/src/api/java/IntSort.java @@ -22,13 +22,13 @@ package com.microsoft.z3; **/ public class IntSort extends ArithSort { - IntSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + IntSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - IntSort(Context ctx) throws Z3Exception - { - super(ctx, Native.mkIntSort(ctx.nCtx())); - } + IntSort(Context ctx) throws Z3Exception + { + super(ctx, Native.mkIntSort(ctx.nCtx())); + } } diff --git a/src/api/java/IntSymbol.java b/src/api/java/IntSymbol.java index a677c9102..01f75e0a4 100644 --- a/src/api/java/IntSymbol.java +++ b/src/api/java/IntSymbol.java @@ -26,7 +26,7 @@ public class IntSymbol extends Symbol { /** * The int value of the symbol. - * Remarks: Throws an exception if the symbol + * Remarks: Throws an exception if the symbol * is not of int kind. **/ public int getInt() throws Z3Exception diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index c1590e07f..4c20ec6ae 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -43,8 +43,8 @@ public class InterpolationContext extends Context * Constructor. * * - * Remarks: - * @see Context#Context + * Remarks: + * @see Context#Context **/ public InterpolationContext(Map settings) throws Z3Exception { diff --git a/src/api/java/Log.java b/src/api/java/Log.java index 3e8f0050b..ac0ebfb7f 100644 --- a/src/api/java/Log.java +++ b/src/api/java/Log.java @@ -19,7 +19,7 @@ package com.microsoft.z3; /** * Interaction logging for Z3. - * Remarks: Note that this is a global, static log + * Remarks: Note that this is a global, static log * and if multiple Context objects are created, it logs the interaction with all * of them. **/ @@ -29,7 +29,7 @@ public final class Log /** * Open an interaction log file. - * @param filename the name of the file to open + * @param filename the name of the file to open * * @return True if opening the log file succeeds, false otherwise. **/ diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 70f0e91c5..9392aacb6 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -27,7 +27,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of {@code a} in * the model. - * @param a A Constant + * @param a A Constant * * @return An expression if the constant has an interpretation in the model, * null otherwise. @@ -42,7 +42,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of {@code f} in * the model. - * @param f A function declaration of zero arity + * @param f A function declaration of zero arity * * @return An expression if the function has an interpretation in the model, * null otherwise. @@ -68,7 +68,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of a non-constant {@code f} in the model. - * @param f A function declaration of non-zero arity + * @param f A function declaration of non-zero arity * * @return A FunctionInterpretation if the function has an interpretation in * the model, null otherwise. @@ -201,7 +201,7 @@ public class Model extends Z3Object * Remarks: This function may fail if {@code t} contains * quantifiers, is partial (MODEL_PARTIAL enabled), or if {@code t} is not well-sorted. In this case a * {@code ModelEvaluationFailedException} is thrown. - * @param t An expression {@code completion} When this flag + * @param t An expression {@code completion} When this flag * is enabled, a model value will be assigned to any constant or function * that does not have an interpretation in the model. * @@ -243,8 +243,8 @@ public class Model extends Z3Object * in a formula. The interpretation for a sort is a finite set of distinct * values. We say this finite set is the "universe" of the sort. * - * @see getNumSorts - * @see getSortUniverse + * @see getNumSorts + * @see getSortUniverse * * @throws Z3Exception **/ @@ -262,7 +262,7 @@ public class Model extends Z3Object /** * The finite set of distinct values that represent the interpretation for * sort {@code s}. - * @param s An uninterpreted sort + * @param s An uninterpreted sort * * @return An array of expressions, where each is an element of the universe * of {@code s} diff --git a/src/api/java/ModelDecRefQueue.java b/src/api/java/ModelDecRefQueue.java index 1200b29be..c954a1fa8 100644 --- a/src/api/java/ModelDecRefQueue.java +++ b/src/api/java/ModelDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ModelDecRefQueue extends IDecRefQueue { + public ModelDecRefQueue() + { + super(); + } + + public ModelDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ParamDescrsDecRefQueue.java b/src/api/java/ParamDescrsDecRefQueue.java index a29565e8e..95a92475e 100644 --- a/src/api/java/ParamDescrsDecRefQueue.java +++ b/src/api/java/ParamDescrsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ParamDescrsDecRefQueue extends IDecRefQueue { + public ParamDescrsDecRefQueue() + { + super(); + } + + public ParamDescrsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ParamsDecRefQueue.java b/src/api/java/ParamsDecRefQueue.java index 7d71feb8f..7b9f34c00 100644 --- a/src/api/java/ParamsDecRefQueue.java +++ b/src/api/java/ParamsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ParamsDecRefQueue extends IDecRefQueue { + public ParamsDecRefQueue() + { + super(); + } + + public ParamsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ProbeDecRefQueue.java b/src/api/java/ProbeDecRefQueue.java index fda5d37b4..e271bd949 100644 --- a/src/api/java/ProbeDecRefQueue.java +++ b/src/api/java/ProbeDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ProbeDecRefQueue extends IDecRefQueue { + public ProbeDecRefQueue() + { + super(); + } + + public ProbeDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index 58245d723..3ea2b2eaf 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -171,13 +171,13 @@ public class Quantifier extends BoolExpr } else { setNativeObject(Native.mkQuantifierEx(ctx.nCtx(), - (isForall) ? true : false, weight, AST.getNativeObject(quantifierID), - AST.getNativeObject(skolemID), - AST.arrayLength(patterns), AST.arrayToNative(patterns), - AST.arrayLength(noPatterns), AST.arrayToNative(noPatterns), - AST.arrayLength(sorts), AST.arrayToNative(sorts), - Symbol.arrayToNative(names), - body.getNativeObject())); + (isForall) ? true : false, weight, AST.getNativeObject(quantifierID), + AST.getNativeObject(skolemID), + AST.arrayLength(patterns), AST.arrayToNative(patterns), + AST.arrayLength(noPatterns), AST.arrayToNative(noPatterns), + AST.arrayLength(sorts), AST.arrayToNative(sorts), + Symbol.arrayToNative(names), + body.getNativeObject())); } } diff --git a/src/api/java/RatNum.java b/src/api/java/RatNum.java index 2e92a9429..278aba65e 100644 --- a/src/api/java/RatNum.java +++ b/src/api/java/RatNum.java @@ -62,7 +62,7 @@ public class RatNum extends RealExpr /** * Returns a string representation in decimal notation. - * Remarks: The result + * Remarks: The result * has at most {@code precision} decimal places. **/ public String toDecimalString(int precision) throws Z3Exception diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index b9c9ebca6..3e66a29ac 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -57,8 +57,8 @@ public class Solver extends Z3Object /** * The current number of backtracking points (scopes). - * @see pop - * @see push + * @see pop + * @see push **/ public int getNumScopes() throws Z3Exception { @@ -68,7 +68,7 @@ public class Solver extends Z3Object /** * Creates a backtracking point. - * @see pop + * @see pop **/ public void push() throws Z3Exception { @@ -77,7 +77,7 @@ public class Solver extends Z3Object /** * Backtracks one backtracking point. - * Remarks: . + * Remarks: . **/ public void pop() throws Z3Exception { @@ -86,10 +86,10 @@ public class Solver extends Z3Object /** * Backtracks {@code n} backtracking points. - * Remarks: Note that + * Remarks: Note that * an exception is thrown if {@code n} is not smaller than * {@code NumScopes} - * @see push + * @see push **/ public void pop(int n) throws Z3Exception { @@ -98,7 +98,7 @@ public class Solver extends Z3Object /** * Resets the Solver. - * Remarks: This removes all assertions from the + * Remarks: This removes all assertions from the * solver. **/ public void reset() throws Z3Exception @@ -121,20 +121,20 @@ public class Solver extends Z3Object } } - // / - // / Assert multiple constraints into the solver, and track them (in the - // unsat) core - // / using the Boolean constants in ps. - // / - // / Remarks: - // / This API is an alternative to with assumptions for - // extracting unsat cores. - // / Both APIs can be used in the same solver. The unsat core will contain a - // combination - // / of the Boolean variables provided using - // and the Boolean literals - // / provided using with assumptions. - // / + /** + * Assert multiple constraints into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * Remarks: + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + **/ public void assertAndTrack(BoolExpr[] constraints, BoolExpr[] ps) throws Z3Exception { getContext().checkContextMatch(constraints); @@ -147,19 +147,19 @@ public class Solver extends Z3Object constraints[i].getNativeObject(), ps[i].getNativeObject()); } - // / - // / Assert a constraint into the solver, and track it (in the unsat) core - // / using the Boolean constant p. - // / - // / Remarks: - // / This API is an alternative to with assumptions for - // extracting unsat cores. - // / Both APIs can be used in the same solver. The unsat core will contain a - // combination - // / of the Boolean variables provided using - // and the Boolean literals - // / provided using with assumptions. - // / + /** + * Assert a constraint into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * Remarks: + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + */ public void assertAndTrack(BoolExpr constraint, BoolExpr p) throws Z3Exception { getContext().checkContextMatch(constraint); @@ -200,9 +200,9 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. * Remarks: - * @see getModel - * @see getUnsatCore - * @see getProof + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check(Expr... assumptions) throws Z3Exception { @@ -228,9 +228,9 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. * Remarks: - * @see getModel - * @see getUnsatCore - * @see getProof + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check() throws Z3Exception { @@ -239,7 +239,7 @@ public class Solver extends Z3Object /** * The model of the last {@code Check}. - * Remarks: The result is + * Remarks: The result is * {@code null} if {@code Check} was not invoked before, if its * results was not {@code SATISFIABLE}, or if model production is not * enabled. @@ -257,7 +257,7 @@ public class Solver extends Z3Object /** * The proof of the last {@code Check}. - * Remarks: The result is + * Remarks: The result is * {@code null} if {@code Check} was not invoked before, if its * results was not {@code UNSATISFIABLE}, or if proof production is * disabled. @@ -275,7 +275,7 @@ public class Solver extends Z3Object /** * The unsat core of the last {@code Check}. - * Remarks: The unsat core + * Remarks: The unsat core * is a subset of {@code Assertions} The result is empty if * {@code Check} was not invoked before, if its results was not * {@code UNSATISFIABLE}, or if core production is disabled. diff --git a/src/api/java/SolverDecRefQueue.java b/src/api/java/SolverDecRefQueue.java index 993c99621..cbe5bbc3b 100644 --- a/src/api/java/SolverDecRefQueue.java +++ b/src/api/java/SolverDecRefQueue.java @@ -19,6 +19,13 @@ package com.microsoft.z3; class SolverDecRefQueue extends IDecRefQueue { + public SolverDecRefQueue() { super(); } + + public SolverDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 270abd43f..e1cbbea7c 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -29,20 +29,20 @@ public class Sort extends AST /** * Equality operator for objects of type Sort. - * @param o + * @param o * @return **/ public boolean equals(Object o) { Sort casted = null; - try { - casted = Sort.class.cast(o); - } catch (ClassCastException e) { - return false; - } + try { + casted = Sort.class.cast(o); + } catch (ClassCastException e) { + return false; + } - return this.getNativeObject() == casted.getNativeObject(); + return this.getNativeObject() == casted.getNativeObject(); } /** @@ -135,9 +135,9 @@ public class Sort extends AST case Z3_RELATION_SORT: return new RelationSort(ctx, obj); case Z3_FLOATING_POINT_SORT: - return new FPSort(ctx, obj); + return new FPSort(ctx, obj); case Z3_ROUNDING_MODE_SORT: - return new FPRMSort(ctx, obj); + return new FPRMSort(ctx, obj); default: throw new Z3Exception("Unknown sort kind"); } diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index 88a897d15..475352024 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -177,7 +177,7 @@ public class Statistics extends Z3Object /** * The value of a particular statistical counter. - * Remarks: Returns null if + * Remarks: Returns null if * the key is unknown. * * @throws Z3Exception diff --git a/src/api/java/StatisticsDecRefQueue.java b/src/api/java/StatisticsDecRefQueue.java index db3e32c86..89c66a746 100644 --- a/src/api/java/StatisticsDecRefQueue.java +++ b/src/api/java/StatisticsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class StatisticsDecRefQueue extends IDecRefQueue { + public StatisticsDecRefQueue() + { + super(); + } + + public StatisticsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/StringSymbol.java b/src/api/java/StringSymbol.java index 4692b0fb9..122c7765f 100644 --- a/src/api/java/StringSymbol.java +++ b/src/api/java/StringSymbol.java @@ -26,7 +26,7 @@ public class StringSymbol extends Symbol { /** * The string value of the symbol. - * Remarks: Throws an exception if the + * Remarks: Throws an exception if the * symbol is not of string kind. **/ public String getString() throws Z3Exception diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index 0286e786d..79f60e497 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -49,7 +49,7 @@ public class Tactic extends Z3Object * @throws Z3Exception **/ public ApplyResult apply(Goal g) throws Z3Exception - { + { return apply(g, null); } @@ -74,7 +74,7 @@ public class Tactic extends Z3Object /** * Creates a solver that is implemented using the given tactic. - * @see Context#mkSolver(Tactic) + * @see Context#mkSolver(Tactic) * @throws Z3Exception **/ public Solver getSolver() throws Z3Exception diff --git a/src/api/java/TacticDecRefQueue.java b/src/api/java/TacticDecRefQueue.java index 5557d03b8..026760e46 100644 --- a/src/api/java/TacticDecRefQueue.java +++ b/src/api/java/TacticDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class TacticDecRefQueue extends IDecRefQueue { + public TacticDecRefQueue() + { + super(); + } + + public TacticDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Version.java b/src/api/java/Version.java index 6e2fe5084..939a3ca5c 100644 --- a/src/api/java/Version.java +++ b/src/api/java/Version.java @@ -19,7 +19,7 @@ package com.microsoft.z3; /** * Version information. - * Remarks: Note that this class is static. + * Remarks: Note that this class is static. **/ public class Version { diff --git a/src/api/java/Z3Object.java b/src/api/java/Z3Object.java index 03cfcd625..9b39a3e2f 100644 --- a/src/api/java/Z3Object.java +++ b/src/api/java/Z3Object.java @@ -115,7 +115,7 @@ public class Z3Object extends IDisposable return null; long[] an = new long[a.length]; for (int i = 0; i < a.length; i++) - an[i] = (a[i] == null) ? 0 : a[i].getNativeObject(); + an[i] = (a[i] == null) ? 0 : a[i].getNativeObject(); return an; } From d7a62baef488fdb20c24c91fc71d6b36b0873255 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 30 Jan 2015 21:04:18 -0600 Subject: [PATCH 537/646] Improved memory use of the Java API. Thanks to Joerg Pfaehler for reporting this issue! + formatting Signed-off-by: Christoph M. Wintersteiger --- examples/java/JavaExample.java | 4 +- src/api/dotnet/Context.cs | 12 +- src/api/java/AST.java | 18 +- src/api/java/ASTDecRefQueue.java | 10 + src/api/java/ASTMap.java | 10 +- src/api/java/ASTVector.java | 8 +- src/api/java/ApplyResultDecRefQueue.java | 10 + src/api/java/ArithExpr.java | 14 +- src/api/java/ArithSort.java | 8 +- src/api/java/ArrayExpr.java | 14 +- src/api/java/ArraySort.java | 62 +- src/api/java/AstMapDecRefQueue.java | 10 + src/api/java/AstVectorDecRefQueue.java | 10 + src/api/java/BitVecExpr.java | 34 +- src/api/java/BitVecSort.java | 26 +- src/api/java/BoolExpr.java | 32 +- src/api/java/Constructor.java | 132 +- src/api/java/ConstructorList.java | 38 +- src/api/java/Context.java | 340 +- src/api/java/DatatypeExpr.java | 14 +- src/api/java/DatatypeSort.java | 150 +- src/api/java/EnumSort.java | 70 +- src/api/java/Expr.java | 4326 +++++++++--------- src/api/java/FPNum.java | 8 +- src/api/java/FPRMNum.java | 8 +- src/api/java/FPSort.java | 10 +- src/api/java/FiniteDomainSort.java | 38 +- src/api/java/Fixedpoint.java | 8 +- src/api/java/FixedpointDecRefQueue.java | 10 + src/api/java/FuncDecl.java | 4 +- src/api/java/FuncInterp.java | 330 +- src/api/java/FuncInterpDecRefQueue.java | 10 + src/api/java/FuncInterpEntryDecRefQueue.java | 10 + src/api/java/Global.java | 6 +- src/api/java/Goal.java | 8 +- src/api/java/GoalDecRefQueue.java | 10 + src/api/java/IDecRefQueue.java | 68 +- src/api/java/IDisposable.java | 6 +- src/api/java/IntExpr.java | 16 +- src/api/java/IntSort.java | 16 +- src/api/java/IntSymbol.java | 2 +- src/api/java/InterpolationContext.java | 4 +- src/api/java/Log.java | 4 +- src/api/java/Model.java | 14 +- src/api/java/ModelDecRefQueue.java | 10 + src/api/java/ParamDescrsDecRefQueue.java | 10 + src/api/java/ParamsDecRefQueue.java | 10 + src/api/java/ProbeDecRefQueue.java | 10 + src/api/java/Quantifier.java | 14 +- src/api/java/RatNum.java | 2 +- src/api/java/Solver.java | 86 +- src/api/java/SolverDecRefQueue.java | 7 + src/api/java/Sort.java | 18 +- src/api/java/Statistics.java | 2 +- src/api/java/StatisticsDecRefQueue.java | 10 + src/api/java/StringSymbol.java | 2 +- src/api/java/Tactic.java | 4 +- src/api/java/TacticDecRefQueue.java | 10 + src/api/java/Version.java | 2 +- src/api/java/Z3Object.java | 2 +- 60 files changed, 3149 insertions(+), 2992 deletions(-) diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index af8662700..64e4015e0 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -2169,8 +2169,8 @@ class JavaExample FPNum y = (FPNum)ctx.mkNumeral("-10", s); /* -10 */ FPNum z = (FPNum)ctx.mkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */ System.out.println("x=" + x.toString() + - "; y=" + y.toString() + - "; z=" + z.toString()); + "; y=" + y.toString() + + "; z=" + z.toString()); BoolExpr a = ctx.mkAnd(ctx.mkFPEq(x, y), ctx.mkFPEq(y, z)); check(ctx, ctx.mkNot(a), Status.UNSATISFIABLE); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 94baea35a..3c3a960df 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4399,16 +4399,16 @@ namespace Microsoft.Z3 readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(10); readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(10); readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(10); - readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(); - readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(); + readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(10); + readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(10); readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(10); readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(10); - readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(); - readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(); - readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(); + readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(10); + readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(10); + readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(10); readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(10); readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(10); - readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(); + readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(10); readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10); internal AST.DecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 0cdfd025c..fdb1643a5 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -29,7 +29,7 @@ public class AST extends Z3Object /** * Object comparison. * - * @param o another AST + * @param o another AST **/ public boolean equals(Object o) { @@ -48,7 +48,7 @@ public class AST extends Z3Object /** * Object Comparison. - * @param other Another AST + * @param other Another AST * * @return Negative if the object should be sorted before {@code other}, * positive if after else zero. @@ -102,7 +102,7 @@ public class AST extends Z3Object /** * Translates (copies) the AST to the Context {@code ctx}. - * @param ctx A context + * @param ctx A context * * @return A copy of the AST which is associated with {@code ctx} * @throws Z3Exception on error @@ -130,7 +130,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is an Expr * @throws Z3Exception on error - * @throws Z3Exception on error + * @throws Z3Exception on error **/ public boolean isExpr() throws Z3Exception { @@ -148,7 +148,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is an application - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isApp() throws Z3Exception @@ -158,7 +158,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a BoundVariable. - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isVar() throws Z3Exception @@ -168,7 +168,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a Quantifier - * @return a boolean + * @return a boolean * @throws Z3Exception on error **/ public boolean isQuantifier() throws Z3Exception @@ -228,7 +228,7 @@ public class AST extends Z3Object { // Console.WriteLine("AST IncRef()"); if (getContext() == null || o == 0) - return; + return; getContext().ast_DRQ().incAndClear(getContext(), o); super.incRef(o); } @@ -237,7 +237,7 @@ public class AST extends Z3Object { // Console.WriteLine("AST DecRef()"); if (getContext() == null || o == 0) - return; + return; getContext().ast_DRQ().add(o); super.decRef(o); } diff --git a/src/api/java/ASTDecRefQueue.java b/src/api/java/ASTDecRefQueue.java index 6ae84eb41..a8ee83e57 100644 --- a/src/api/java/ASTDecRefQueue.java +++ b/src/api/java/ASTDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTDecRefQueue extends IDecRefQueue { + public ASTDecRefQueue() + { + super(); + } + + public ASTDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index 3d63939ca..96ddfbf76 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -24,7 +24,7 @@ class ASTMap extends Z3Object { /** * Checks whether the map contains the key {@code k}. - * @param k An AST + * @param k An AST * * @return True if {@code k} is a key in the map, false * otherwise. @@ -40,7 +40,7 @@ class ASTMap extends Z3Object * Finds the value associated with the key {@code k}. * Remarks: This function signs an error when {@code k} is not a key in * the map. - * @param k An AST + * @param k An AST * * @throws Z3Exception **/ @@ -52,8 +52,8 @@ class ASTMap extends Z3Object /** * Stores or replaces a new key/value pair in the map. - * @param k The key AST - * @param v The value AST + * @param k The key AST + * @param v The value AST **/ public void insert(AST k, AST v) throws Z3Exception { @@ -64,7 +64,7 @@ class ASTMap extends Z3Object /** * Erases the key {@code k} from the map. - * @param k An AST + * @param k An AST **/ public void erase(AST k) throws Z3Exception { diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index d4df02244..30c96e2e7 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -34,7 +34,7 @@ class ASTVector extends Z3Object * Retrieves the i-th object in the vector. * Remarks: May throw an {@code IndexOutOfBoundsException} when * {@code i} is out of range. - * @param i Index + * @param i Index * * @return An AST * @throws Z3Exception @@ -54,7 +54,7 @@ class ASTVector extends Z3Object /** * Resize the vector to {@code newSize}. - * @param newSize The new size of the vector. + * @param newSize The new size of the vector. **/ public void resize(int newSize) throws Z3Exception { @@ -64,7 +64,7 @@ class ASTVector extends Z3Object /** * Add the AST {@code a} to the back of the vector. The size is * increased by 1. - * @param a An AST + * @param a An AST **/ public void push(AST a) throws Z3Exception { @@ -73,7 +73,7 @@ class ASTVector extends Z3Object /** * Translates all ASTs in the vector to {@code ctx}. - * @param ctx A context + * @param ctx A context * * @return A new ASTVector * @throws Z3Exception diff --git a/src/api/java/ApplyResultDecRefQueue.java b/src/api/java/ApplyResultDecRefQueue.java index 78f74d6cc..4cdf312fe 100644 --- a/src/api/java/ApplyResultDecRefQueue.java +++ b/src/api/java/ApplyResultDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ApplyResultDecRefQueue extends IDecRefQueue { + public ApplyResultDecRefQueue() + { + super(); + } + + public ApplyResultDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index 996b98afc..240518134 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -22,11 +22,11 @@ package com.microsoft.z3; **/ public class ArithExpr extends Expr { - /** - * Constructor for ArithExpr - **/ - ArithExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for ArithExpr + **/ + ArithExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/ArithSort.java b/src/api/java/ArithSort.java index 2346d9b74..848d23554 100644 --- a/src/api/java/ArithSort.java +++ b/src/api/java/ArithSort.java @@ -22,8 +22,8 @@ package com.microsoft.z3; **/ public class ArithSort extends Sort { - ArithSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ArithSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } }; diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index 154a56af4..4e6d9ed4d 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -23,11 +23,11 @@ package com.microsoft.z3; **/ public class ArrayExpr extends Expr { - /** - * Constructor for ArrayExpr - **/ - ArrayExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for ArrayExpr + **/ + ArrayExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/ArraySort.java b/src/api/java/ArraySort.java index ab545b7c1..a5b52a8f5 100644 --- a/src/api/java/ArraySort.java +++ b/src/api/java/ArraySort.java @@ -22,38 +22,38 @@ package com.microsoft.z3; **/ public class ArraySort extends Sort { - /** - * The domain of the array sort. - * @throws Z3Exception - * @throws Z3Exception on error - * @return a sort - **/ - public Sort getDomain() throws Z3Exception - { - return Sort.create(getContext(), - Native.getArraySortDomain(getContext().nCtx(), getNativeObject())); - } + /** + * The domain of the array sort. + * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort + **/ + public Sort getDomain() throws Z3Exception + { + return Sort.create(getContext(), + Native.getArraySortDomain(getContext().nCtx(), getNativeObject())); + } - /** - * The range of the array sort. - * @throws Z3Exception - * @throws Z3Exception on error - * @return a sort - **/ - public Sort getRange() throws Z3Exception - { - return Sort.create(getContext(), - Native.getArraySortRange(getContext().nCtx(), getNativeObject())); - } + /** + * The range of the array sort. + * @throws Z3Exception + * @throws Z3Exception on error + * @return a sort + **/ + public Sort getRange() throws Z3Exception + { + return Sort.create(getContext(), + Native.getArraySortRange(getContext().nCtx(), getNativeObject())); + } - ArraySort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ArraySort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - ArraySort(Context ctx, Sort domain, Sort range) throws Z3Exception - { - super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(), - range.getNativeObject())); - } + ArraySort(Context ctx, Sort domain, Sort range) throws Z3Exception + { + super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(), + range.getNativeObject())); + } }; diff --git a/src/api/java/AstMapDecRefQueue.java b/src/api/java/AstMapDecRefQueue.java index a4e02d29f..2106ff0c2 100644 --- a/src/api/java/AstMapDecRefQueue.java +++ b/src/api/java/AstMapDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTMapDecRefQueue extends IDecRefQueue { + public ASTMapDecRefQueue() + { + super(); + } + + public ASTMapDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/AstVectorDecRefQueue.java b/src/api/java/AstVectorDecRefQueue.java index e0c7988a9..698e9e06b 100644 --- a/src/api/java/AstVectorDecRefQueue.java +++ b/src/api/java/AstVectorDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ASTVectorDecRefQueue extends IDecRefQueue { + public ASTVectorDecRefQueue() + { + super(); + } + + public ASTVectorDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 69a97de40..926a26b25 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -23,22 +23,22 @@ package com.microsoft.z3; public class BitVecExpr extends Expr { - /** - * The size of the sort of a bit-vector term. - * @throws Z3Exception - * @throws Z3Exception on error - * @return an int - **/ - public int getSortSize() throws Z3Exception - { - return ((BitVecSort) getSort()).getSize(); - } + /** + * The size of the sort of a bit-vector term. + * @throws Z3Exception + * @throws Z3Exception on error + * @return an int + **/ + public int getSortSize() throws Z3Exception + { + return ((BitVecSort) getSort()).getSize(); + } - /** - * Constructor for BitVecExpr - **/ - BitVecExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for BitVecExpr + **/ + BitVecExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/BitVecSort.java b/src/api/java/BitVecSort.java index 69d74151c..7fd644acb 100644 --- a/src/api/java/BitVecSort.java +++ b/src/api/java/BitVecSort.java @@ -22,18 +22,18 @@ package com.microsoft.z3; **/ public class BitVecSort extends Sort { - /** - * The size of the bit-vector sort. - * @throws Z3Exception on error - * @return an int - **/ - public int getSize() throws Z3Exception - { - return Native.getBvSortSize(getContext().nCtx(), getNativeObject()); - } + /** + * The size of the bit-vector sort. + * @throws Z3Exception on error + * @return an int + **/ + public int getSize() throws Z3Exception + { + return Native.getBvSortSize(getContext().nCtx(), getNativeObject()); + } - BitVecSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + BitVecSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } }; diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index ea3cdbfb4..6709e2ae9 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -22,21 +22,21 @@ package com.microsoft.z3; **/ public class BoolExpr extends Expr { - /** - * Constructor for BoolExpr - **/ - protected BoolExpr(Context ctx) - { - super(ctx); - } + /** + * Constructor for BoolExpr + **/ + protected BoolExpr(Context ctx) + { + super(ctx); + } - /** - * Constructor for BoolExpr - * @throws Z3Exception - * @throws Z3Exception on error - **/ - BoolExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for BoolExpr + * @throws Z3Exception + * @throws Z3Exception on error + **/ + BoolExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/Constructor.java b/src/api/java/Constructor.java index a5440092c..95e7799e1 100644 --- a/src/api/java/Constructor.java +++ b/src/api/java/Constructor.java @@ -22,53 +22,53 @@ package com.microsoft.z3; **/ public class Constructor extends Z3Object { - /** - * The number of fields of the constructor. - * @throws Z3Exception - * @throws Z3Exception on error - * @return an int - **/ - public int getNumFields() throws Z3Exception - { - return n; - } + /** + * The number of fields of the constructor. + * @throws Z3Exception + * @throws Z3Exception on error + * @return an int + **/ + public int getNumFields() throws Z3Exception + { + return n; + } - /** - * The function declaration of the constructor. - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl ConstructorDecl() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); - Native.LongPtr tester = new Native.LongPtr(); - long[] accessors = new long[n]; + /** + * The function declaration of the constructor. + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl ConstructorDecl() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); + Native.LongPtr tester = new Native.LongPtr(); + long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); return new FuncDecl(getContext(), constructor.value); - } + } - /** - * The function declaration of the tester. - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl getTesterDecl() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); + /** + * The function declaration of the tester. + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl getTesterDecl() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); return new FuncDecl(getContext(), tester.value); - } + } - /** - * The function declarations of the accessors - * @throws Z3Exception - * @throws Z3Exception on error - **/ - public FuncDecl[] getAccessorDecls() throws Z3Exception - { - Native.LongPtr constructor = new Native.LongPtr(); + /** + * The function declarations of the accessors + * @throws Z3Exception + * @throws Z3Exception on error + **/ + public FuncDecl[] getAccessorDecls() throws Z3Exception + { + Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); long[] accessors = new long[n]; Native.queryConstructor(getContext().nCtx(), getNativeObject(), n, constructor, tester, accessors); @@ -76,40 +76,40 @@ public class Constructor extends Z3Object for (int i = 0; i < n; i++) t[i] = new FuncDecl(getContext(), accessors[i]); return t; - } + } - /** - * Destructor. - * @throws Z3Exception on error - **/ - protected void finalize() throws Z3Exception - { - Native.delConstructor(getContext().nCtx(), getNativeObject()); - } + /** + * Destructor. + * @throws Z3Exception on error + **/ + protected void finalize() throws Z3Exception + { + Native.delConstructor(getContext().nCtx(), getNativeObject()); + } - private int n = 0; + private int n = 0; - Constructor(Context ctx, Symbol name, Symbol recognizer, - Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) - throws Z3Exception - { - super(ctx); + Constructor(Context ctx, Symbol name, Symbol recognizer, + Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) + throws Z3Exception + { + super(ctx); - n = AST.arrayLength(fieldNames); + n = AST.arrayLength(fieldNames); - if (n != AST.arrayLength(sorts)) - throw new Z3Exception( - "Number of field names does not match number of sorts"); - if (sortRefs != null && sortRefs.length != n) - throw new Z3Exception( - "Number of field names does not match number of sort refs"); + if (n != AST.arrayLength(sorts)) + throw new Z3Exception( + "Number of field names does not match number of sorts"); + if (sortRefs != null && sortRefs.length != n) + throw new Z3Exception( + "Number of field names does not match number of sort refs"); - if (sortRefs == null) - sortRefs = new int[n]; + if (sortRefs == null) + sortRefs = new int[n]; - setNativeObject(Native.mkConstructor(ctx.nCtx(), name.getNativeObject(), - recognizer.getNativeObject(), n, Symbol.arrayToNative(fieldNames), - Sort.arrayToNative(sorts), sortRefs)); + setNativeObject(Native.mkConstructor(ctx.nCtx(), name.getNativeObject(), + recognizer.getNativeObject(), n, Symbol.arrayToNative(fieldNames), + Sort.arrayToNative(sorts), sortRefs)); - } + } } diff --git a/src/api/java/ConstructorList.java b/src/api/java/ConstructorList.java index b38678b8a..0cff4cfa4 100644 --- a/src/api/java/ConstructorList.java +++ b/src/api/java/ConstructorList.java @@ -22,26 +22,26 @@ package com.microsoft.z3; **/ public class ConstructorList extends Z3Object { - /** - * Destructor. - * @throws Z3Exception on error - **/ - protected void finalize() throws Z3Exception - { - Native.delConstructorList(getContext().nCtx(), getNativeObject()); - } + /** + * Destructor. + * @throws Z3Exception on error + **/ + protected void finalize() throws Z3Exception + { + Native.delConstructorList(getContext().nCtx(), getNativeObject()); + } - ConstructorList(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + ConstructorList(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - ConstructorList(Context ctx, Constructor[] constructors) throws Z3Exception - { - super(ctx); + ConstructorList(Context ctx, Constructor[] constructors) throws Z3Exception + { + super(ctx); - setNativeObject(Native.mkConstructorList(getContext().nCtx(), - (int) constructors.length, - Constructor.arrayToNative(constructors))); - } + setNativeObject(Native.mkConstructorList(getContext().nCtx(), + (int) constructors.length, + Constructor.arrayToNative(constructors))); + } } diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 294826f55..42fd0f7e1 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -261,12 +261,12 @@ public class Context extends IDisposable /** * Create a datatype constructor. - * @param name constructor name - * @param recognizer name of recognizer function. - * @param fieldNames names of the constructor fields. - * @param sorts field sorts, 0 if the field sort refers to a recursive sort. - * @param sortRefs reference to datatype sort that is an argument to the - * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be + * @param name constructor name + * @param recognizer name of recognizer function. + * @param fieldNames names of the constructor fields. + * @param sorts field sorts, 0 if the field sort refers to a recursive sort. + * @param sortRefs reference to datatype sort that is an argument to the + * constructor; if the corresponding sort reference is 0, then the value in sort_refs should be * an index referring to one of the recursive datatypes that is * declared. **/ @@ -281,11 +281,11 @@ public class Context extends IDisposable /** * Create a datatype constructor. - * @param name - * @param recognizer - * @param fieldNames - * @param sorts - * @param sortRefs + * @param name + * @param recognizer + * @param fieldNames + * @param sorts + * @param sortRefs * * @return **/ @@ -321,8 +321,8 @@ public class Context extends IDisposable /** * Create mutually recursive datatypes. - * @param names names of datatype sorts - * @param c list of constructors, one list per sort. + * @param names names of datatype sorts + * @param c list of constructors, one list per sort. **/ public DatatypeSort[] mkDatatypeSorts(Symbol[] names, Constructor[][] c) throws Z3Exception @@ -350,8 +350,8 @@ public class Context extends IDisposable /** * Create mutually recursive data-types. - * @param names - * @param c + * @param names + * @param c * * @return **/ @@ -412,7 +412,7 @@ public class Context extends IDisposable /** * Creates a fresh function declaration with a name prefixed with * {@code prefix}. - * @see mkFuncDecl(String,Sort,Sort) + * @see mkFuncDecl(String,Sort,Sort) * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) @@ -457,8 +457,8 @@ public class Context extends IDisposable /** * Creates a new bound variable. - * @param index The de-Bruijn index of the variable - * @param ty The sort of the variable + * @param index The de-Bruijn index of the variable + * @param ty The sort of the variable **/ public Expr mkBound(int index, Sort ty) throws Z3Exception { @@ -516,7 +516,7 @@ public class Context extends IDisposable /** * Creates a fresh constant from the FuncDecl {@code f}. - * @param f A decl of a 0-arity function + * @param f A decl of a 0-arity function **/ public Expr mkConst(FuncDecl f) throws Z3Exception { @@ -654,9 +654,9 @@ public class Context extends IDisposable /** * Create an expression representing an if-then-else: * {@code ite(t1, t2, t3)}. - * @param t1 An expression with Boolean sort - * @param t2 An expression - * @param t3 An expression with the same sort as {@code t2} + * @param t1 An expression with Boolean sort + * @param t2 An expression + * @param t3 An expression with the same sort as {@code t2} **/ public Expr mkITE(BoolExpr t1, Expr t2, Expr t3) throws Z3Exception { @@ -773,7 +773,7 @@ public class Context extends IDisposable /** * Create an expression representing {@code t1 mod t2}. - * Remarks: The + * Remarks: The * arguments must have int type. **/ public IntExpr mkMod(IntExpr t1, IntExpr t2) throws Z3Exception @@ -786,7 +786,7 @@ public class Context extends IDisposable /** * Create an expression representing {@code t1 rem t2}. - * Remarks: The + * Remarks: The * arguments must have int type. **/ public IntExpr mkRem(IntExpr t1, IntExpr t2) throws Z3Exception @@ -856,7 +856,7 @@ public class Context extends IDisposable /** * Coerce an integer to a real. - * Remarks: There is also a converse operation + * Remarks: There is also a converse operation * exposed. It follows the semantics prescribed by the SMT-LIB standard. * * You can take the floor of a real by creating an auxiliary integer Term @@ -873,7 +873,7 @@ public class Context extends IDisposable /** * Coerce a real to an integer. - * Remarks: The semantics of this function + * Remarks: The semantics of this function * follows the SMT-LIB standard for the function to_int. The argument must * be of real sort. **/ @@ -894,7 +894,7 @@ public class Context extends IDisposable /** * Bitwise negation. - * Remarks: The argument must have a bit-vector + * Remarks: The argument must have a bit-vector * sort. **/ public BitVecExpr mkBVNot(BitVecExpr t) throws Z3Exception @@ -906,7 +906,7 @@ public class Context extends IDisposable /** * Take conjunction of bits in a vector, return vector of length 1. * - * Remarks: The argument must have a bit-vector sort. + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedAND(BitVecExpr t) throws Z3Exception { @@ -918,7 +918,7 @@ public class Context extends IDisposable /** * Take disjunction of bits in a vector, return vector of length 1. * - * Remarks: The argument must have a bit-vector sort. + * Remarks: The argument must have a bit-vector sort. **/ public BitVecExpr mkBVRedOR(BitVecExpr t) throws Z3Exception { @@ -929,7 +929,7 @@ public class Context extends IDisposable /** * Bitwise conjunction. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -942,7 +942,7 @@ public class Context extends IDisposable /** * Bitwise disjunction. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -955,7 +955,7 @@ public class Context extends IDisposable /** * Bitwise XOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVXOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -968,7 +968,7 @@ public class Context extends IDisposable /** * Bitwise NAND. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVNAND(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -981,7 +981,7 @@ public class Context extends IDisposable /** * Bitwise NOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -994,7 +994,7 @@ public class Context extends IDisposable /** * Bitwise XNOR. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. **/ public BitVecExpr mkBVXNOR(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1007,7 +1007,7 @@ public class Context extends IDisposable /** * Standard two's complement unary minus. - * Remarks: The arguments must have a + * Remarks: The arguments must have a * bit-vector sort. **/ public BitVecExpr mkBVNeg(BitVecExpr t) throws Z3Exception @@ -1018,7 +1018,7 @@ public class Context extends IDisposable /** * Two's complement addition. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BitVecExpr mkBVAdd(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1031,7 +1031,7 @@ public class Context extends IDisposable /** * Two's complement subtraction. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BitVecExpr mkBVSub(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1044,7 +1044,7 @@ public class Context extends IDisposable /** * Two's complement multiplication. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BitVecExpr mkBVMul(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1057,7 +1057,7 @@ public class Context extends IDisposable /** * Unsigned division. - * Remarks: It is defined as the floor of + * Remarks: It is defined as the floor of * {@code t1/t2} if \c t2 is different from zero. If {@code t2} is * zero, then the result is undefined. The arguments must have the same * bit-vector sort. @@ -1072,7 +1072,7 @@ public class Context extends IDisposable /** * Signed division. - * Remarks: It is defined in the following way: + * Remarks: It is defined in the following way: * * - The \c floor of {@code t1/t2} if \c t2 is different from zero, and * {@code t1*t2 >= 0}. @@ -1093,7 +1093,7 @@ public class Context extends IDisposable /** * Unsigned remainder. - * Remarks: It is defined as + * Remarks: It is defined as * {@code t1 - (t1 /u t2) * t2}, where {@code /u} represents * unsigned division. If {@code t2} is zero, then the result is * undefined. The arguments must have the same bit-vector sort. @@ -1108,7 +1108,7 @@ public class Context extends IDisposable /** * Signed remainder. - * Remarks: It is defined as + * Remarks: It is defined as * {@code t1 - (t1 /s t2) * t2}, where {@code /s} represents * signed division. The most significant bit (sign) of the result is equal * to the most significant bit of \c t1. @@ -1126,7 +1126,7 @@ public class Context extends IDisposable /** * Two's complement signed remainder (sign follows divisor). - * Remarks: If + * Remarks: If * {@code t2} is zero, then the result is undefined. The arguments must * have the same bit-vector sort. **/ @@ -1140,7 +1140,7 @@ public class Context extends IDisposable /** * Unsigned less-than - * Remarks: The arguments must have the same bit-vector + * Remarks: The arguments must have the same bit-vector * sort. **/ public BoolExpr mkBVULT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1153,7 +1153,7 @@ public class Context extends IDisposable /** * Two's complement signed less-than - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVSLT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1166,7 +1166,7 @@ public class Context extends IDisposable /** * Unsigned less-than or equal to. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVULE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1179,7 +1179,7 @@ public class Context extends IDisposable /** * Two's complement signed less-than or equal to. - * Remarks: The arguments + * Remarks: The arguments * must have the same bit-vector sort. **/ public BoolExpr mkBVSLE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1192,7 +1192,7 @@ public class Context extends IDisposable /** * Unsigned greater than or equal to. - * Remarks: The arguments must have the + * Remarks: The arguments must have the * same bit-vector sort. **/ public BoolExpr mkBVUGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1205,7 +1205,7 @@ public class Context extends IDisposable /** * Two's complement signed greater than or equal to. - * Remarks: The arguments + * Remarks: The arguments * must have the same bit-vector sort. **/ public BoolExpr mkBVSGE(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1218,7 +1218,7 @@ public class Context extends IDisposable /** * Unsigned greater-than. - * Remarks: The arguments must have the same + * Remarks: The arguments must have the same * bit-vector sort. **/ public BoolExpr mkBVUGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1231,7 +1231,7 @@ public class Context extends IDisposable /** * Two's complement signed greater-than. - * Remarks: The arguments must have + * Remarks: The arguments must have * the same bit-vector sort. **/ public BoolExpr mkBVSGT(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1244,7 +1244,7 @@ public class Context extends IDisposable /** * Bit-vector concatenation. - * Remarks: The arguments must have a bit-vector + * Remarks: The arguments must have a bit-vector * sort. * * @return The result is a bit-vector of size {@code n1+n2}, where @@ -1262,7 +1262,7 @@ public class Context extends IDisposable /** * Bit-vector extraction. - * Remarks: Extract the bits {@code high} + * Remarks: Extract the bits {@code high} * down to {@code low} from a bitvector of size {@code m} to * yield a new bitvector of size {@code n}, where * {@code n = high - low + 1}. The argument {@code t} must @@ -1278,7 +1278,7 @@ public class Context extends IDisposable /** * Bit-vector sign extension. - * Remarks: Sign-extends the given bit-vector to + * Remarks: Sign-extends the given bit-vector to * the (signed) equivalent bitvector of size {@code m+i}, where \c m is * the size of the given bit-vector. The argument {@code t} must * have a bit-vector sort. @@ -1292,7 +1292,7 @@ public class Context extends IDisposable /** * Bit-vector zero extension. - * Remarks: Extend the given bit-vector with + * Remarks: Extend the given bit-vector with * zeros to the (unsigned) equivalent bitvector of size {@code m+i}, * where \c m is the size of the given bit-vector. The argument {@code t} * must have a bit-vector sort. @@ -1306,7 +1306,7 @@ public class Context extends IDisposable /** * Bit-vector repetition. - * Remarks: The argument {@code t} must + * Remarks: The argument {@code t} must * have a bit-vector sort. **/ public BitVecExpr mkRepeat(int i, BitVecExpr t) throws Z3Exception @@ -1318,7 +1318,7 @@ public class Context extends IDisposable /** * Shift left. - * Remarks: It is equivalent to multiplication by + * Remarks: It is equivalent to multiplication by * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This @@ -1337,7 +1337,7 @@ public class Context extends IDisposable /** * Logical shift right - * Remarks: It is equivalent to unsigned division by + * Remarks: It is equivalent to unsigned division by * {@code 2^x} where \c x is the value of {@code t2}. * * NB. The semantics of shift operations varies between environments. This @@ -1356,7 +1356,7 @@ public class Context extends IDisposable /** * Arithmetic shift right - * Remarks: It is like logical shift right except + * Remarks: It is like logical shift right except * that the most significant bits of the result always copy the most * significant bit of the second argument. * @@ -1376,7 +1376,7 @@ public class Context extends IDisposable /** * Rotate Left. - * Remarks: Rotate bits of \c t to the left \c i times. The + * Remarks: Rotate bits of \c t to the left \c i times. The * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateLeft(int i, BitVecExpr t) throws Z3Exception @@ -1388,7 +1388,7 @@ public class Context extends IDisposable /** * Rotate Right. - * Remarks: Rotate bits of \c t to the right \c i times. The + * Remarks: Rotate bits of \c t to the right \c i times. The * argument {@code t} must have a bit-vector sort. **/ public BitVecExpr mkBVRotateRight(int i, BitVecExpr t) throws Z3Exception @@ -1400,7 +1400,7 @@ public class Context extends IDisposable /** * Rotate Left. - * Remarks: Rotate bits of {@code t1} to the left + * Remarks: Rotate bits of {@code t1} to the left * {@code t2} times. The arguments must have the same bit-vector * sort. **/ @@ -1415,7 +1415,7 @@ public class Context extends IDisposable /** * Rotate Right. - * Remarks: Rotate bits of {@code t1} to the + * Remarks: Rotate bits of {@code t1} to the * right{@code t2} times. The arguments must have the same * bit-vector sort. **/ @@ -1431,7 +1431,7 @@ public class Context extends IDisposable /** * Create an {@code n} bit bit-vector from the integer argument * {@code t}. - * Remarks: NB. This function is essentially treated + * Remarks: NB. This function is essentially treated * as uninterpreted. So you cannot expect Z3 to precisely reflect the * semantics of this function when solving constraints with this function. * @@ -1468,7 +1468,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1483,7 +1483,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise addition does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1497,7 +1497,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1511,7 +1511,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise subtraction does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1526,7 +1526,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise signed division does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1540,7 +1540,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise negation does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVNegNoOverflow(BitVecExpr t) throws Z3Exception { @@ -1552,7 +1552,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not * overflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoOverflow(BitVecExpr t1, BitVecExpr t2, boolean isSigned) throws Z3Exception @@ -1567,7 +1567,7 @@ public class Context extends IDisposable /** * Create a predicate that checks that the bit-wise multiplication does not * underflow. - * Remarks: The arguments must be of bit-vector sort. + * Remarks: The arguments must be of bit-vector sort. **/ public BoolExpr mkBVMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) throws Z3Exception @@ -1598,15 +1598,15 @@ public class Context extends IDisposable /** * Array read. - * Remarks: The argument {@code a} is the array and + * Remarks: The argument {@code a} is the array and * {@code i} is the index of the array that gets read. * * The node {@code a} must have an array sort * {@code [domain -> range]}, and {@code i} must have the sort * {@code domain}. The sort of the result is {@code range}. * - * @see mkArraySort - * @see mkStore + * @see mkArraySort + * @see mkStore **/ public Expr mkSelect(ArrayExpr a, Expr i) throws Z3Exception @@ -1621,7 +1621,7 @@ public class Context extends IDisposable /** * Array update. - * Remarks: The node {@code a} must have an array sort + * Remarks: The node {@code a} must have an array sort * {@code [domain -> range]}, {@code i} must have sort * {@code domain}, {@code v} must have sort range. The sort of the * result is {@code [domain -> range]}. The semantics of this function @@ -1631,8 +1631,8 @@ public class Context extends IDisposable * {@code select}) on all indices except for {@code i}, where it * maps to {@code v} (and the {@code select} of {@code a} * with respect to {@code i} may be a different value). - * @see mkArraySort - * @see mkSelect + * @see mkArraySort + * @see mkSelect **/ public ArrayExpr mkStore(ArrayExpr a, Expr i, Expr v) throws Z3Exception @@ -1646,11 +1646,11 @@ public class Context extends IDisposable /** * Create a constant array. - * Remarks: The resulting term is an array, such + * Remarks: The resulting term is an array, such * that a {@code select} on an arbitrary index produces the value * {@code v}. - * @see mkArraySort - * @see mkSelect + * @see mkArraySort + * @see mkSelect * **/ public ArrayExpr mkConstArray(Sort domain, Expr v) throws Z3Exception @@ -1663,15 +1663,15 @@ public class Context extends IDisposable /** * Maps f on the argument arrays. - * Remarks: Eeach element of + * Remarks: Eeach element of * {@code args} must be of an array sort * {@code [domain_i -> range_i]}. The function declaration * {@code f} must have type {@code range_1 .. range_n -> range}. * {@code v} must have sort range. The sort of the result is * {@code [domain_i -> range]}. - * @see mkArraySort - * @see mkSelect - * @see mkStore + * @see mkArraySort + * @see mkSelect + * @see mkStore **/ public ArrayExpr mkMap(FuncDecl f, ArrayExpr... args) throws Z3Exception @@ -1685,7 +1685,7 @@ public class Context extends IDisposable /** * Access the array default value. - * Remarks: Produces the default range + * Remarks: Produces the default range * value, for arrays that can be represented as finite maps with a default * range value. **/ @@ -1826,10 +1826,10 @@ public class Context extends IDisposable /** * Create a Term of a given sort. - * @param v A string representing the term value in decimal notation. If the given sort is a real, then the + * @param v A string representing the term value in decimal notation. If the given sort is a real, then the * Term can be a rational, that is, a string of the form * {@code [num]* / [num]*}. - * @param ty The sort of the + * @param ty The sort of the * numeral. In the current implementation, the given sort can be an int, * real, or bit-vectors of arbitrary size. * @@ -1847,8 +1847,8 @@ public class Context extends IDisposable * numerals that fit in a machine integer. It is slightly faster than * {@code MakeNumeral} since it is not necessary to parse a string. * - * @param v Value of the numeral - * @param ty Sort of the numeral + * @param v Value of the numeral + * @param ty Sort of the numeral * * @return A Term with value {@code v} and type {@code ty} **/ @@ -1863,8 +1863,8 @@ public class Context extends IDisposable * numerals that fit in a machine integer. It is slightly faster than * {@code MakeNumeral} since it is not necessary to parse a string. * - * @param v Value of the numeral - * @param ty Sort of the numeral + * @param v Value of the numeral + * @param ty Sort of the numeral * * @return A Term with value {@code v} and type {@code ty} **/ @@ -1877,12 +1877,12 @@ public class Context extends IDisposable /** * Create a real from a fraction. - * @param num numerator of rational. - * @param den denominator of rational. + * @param num numerator of rational. + * @param den denominator of rational. * * @return A Term with value {@code num}/{@code den} * and sort Real - * @see mkNumeral(String,Sort) + * @see mkNumeral(String,Sort) **/ public RatNum mkReal(int num, int den) throws Z3Exception { @@ -1894,7 +1894,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v A string representing the Term value in decimal notation. + * @param v A string representing the Term value in decimal notation. * * @return A Term with value {@code v} and sort Real **/ @@ -1907,7 +1907,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Real **/ @@ -1920,7 +1920,7 @@ public class Context extends IDisposable /** * Create a real numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Real **/ @@ -1933,7 +1933,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v A string representing the Term value in decimal notation. + * @param v A string representing the Term value in decimal notation. **/ public IntNum mkInt(String v) throws Z3Exception { @@ -1944,7 +1944,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Integer **/ @@ -1957,7 +1957,7 @@ public class Context extends IDisposable /** * Create an integer numeral. - * @param v value of the numeral. + * @param v value of the numeral. * * @return A Term with value {@code v} and sort Integer **/ @@ -1970,8 +1970,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v A string representing the value in decimal notation. - * @param size the size of the bit-vector + * @param v A string representing the value in decimal notation. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(String v, int size) throws Z3Exception { @@ -1980,8 +1980,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v value of the numeral. - * @param size the size of the bit-vector + * @param v value of the numeral. + * @param size the size of the bit-vector **/ public BitVecNum mkBV(int v, int size) throws Z3Exception { @@ -1990,8 +1990,8 @@ public class Context extends IDisposable /** * Create a bit-vector numeral. - * @param v value of the numeral. * - * @param size the size of the bit-vector + * @param v value of the numeral. * + * @param size the size of the bit-vector **/ public BitVecNum mkBV(long v, int size) throws Z3Exception { @@ -2000,16 +2000,16 @@ public class Context extends IDisposable /** * Create a universal Quantifier. - * @param sorts the sorts of the bound variables. - * @param names names of the bound variables - * @param body the body of the quantifier. - * @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. + * @param sorts the sorts of the bound variables. + * @param names names of the bound variables + * @param body the body of the quantifier. + * @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. * @param patterns array containing the patterns created using {@code MkPattern}. - * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. - * @param quantifierID optional symbol to track quantifier. - * @param skolemID optional symbol to track skolem constants. - * - * Remarks: Creates a forall formula, where + * @param noPatterns array containing the anti-patterns created using {@code MkPattern}. + * @param quantifierID optional symbol to track quantifier. + * @param skolemID optional symbol to track skolem constants. + * + * Remarks: Creates a forall formula, where * {@code weight"/> is the weight, to every subgoal produced by 1) - res += "["; - Expr[] args = e.getArgs(); - for (int i = 0; i < n; i++) - { - if (i != 0) - res += ", "; - res += args[i]; - } - if (n > 1) - res += "]"; - res += " -> " + e.getValue() + ", "; - } - res += "else -> " + getElse(); - res += "]"; - return res; - } catch (Z3Exception e) - { - return new String("Z3Exception: " + e.getMessage()); - } - } + /** + * A string representation of the function interpretation. + **/ + public String toString() + { + try + { + String res = ""; + res += "["; + for (Entry e : getEntries()) + { + int n = e.getNumArgs(); + if (n > 1) + res += "["; + Expr[] args = e.getArgs(); + for (int i = 0; i < n; i++) + { + if (i != 0) + res += ", "; + res += args[i]; + } + if (n > 1) + res += "]"; + res += " -> " + e.getValue() + ", "; + } + res += "else -> " + getElse(); + res += "]"; + return res; + } catch (Z3Exception e) + { + return new String("Z3Exception: " + e.getMessage()); + } + } - FuncInterp(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + FuncInterp(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - void incRef(long o) throws Z3Exception - { - getContext().funcInterp_DRQ().incAndClear(getContext(), o); - super.incRef(o); - } + void incRef(long o) throws Z3Exception + { + getContext().funcInterp_DRQ().incAndClear(getContext(), o); + super.incRef(o); + } - void decRef(long o) throws Z3Exception - { - getContext().funcInterp_DRQ().add(o); - super.decRef(o); - } + void decRef(long o) throws Z3Exception + { + getContext().funcInterp_DRQ().add(o); + super.decRef(o); + } } diff --git a/src/api/java/FuncInterpDecRefQueue.java b/src/api/java/FuncInterpDecRefQueue.java index 8bdad4ad5..56660d2f9 100644 --- a/src/api/java/FuncInterpDecRefQueue.java +++ b/src/api/java/FuncInterpDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class FuncInterpDecRefQueue extends IDecRefQueue { + public FuncInterpDecRefQueue() + { + super(); + } + + public FuncInterpDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/FuncInterpEntryDecRefQueue.java b/src/api/java/FuncInterpEntryDecRefQueue.java index 494c2695c..406c0b33a 100644 --- a/src/api/java/FuncInterpEntryDecRefQueue.java +++ b/src/api/java/FuncInterpEntryDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class FuncInterpEntryDecRefQueue extends IDecRefQueue { + public FuncInterpEntryDecRefQueue() + { + super(); + } + + public FuncInterpEntryDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Global.java b/src/api/java/Global.java index b31c4a7ae..44fb4cac7 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -44,7 +44,7 @@ public final class Global **/ public static void setParameter(String id, String value) { - Native.globalParamSet(id, value); + Native.globalParamSet(id, value); } /** @@ -67,10 +67,10 @@ public final class Global * Restore the value of all global (and module) parameters. * Remarks: * This command will not affect already created objects (such as tactics and solvers) - * @see setParameter + * @see setParameter **/ public static void resetParameters() { - Native.globalParamResetAll(); + Native.globalParamResetAll(); } } diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index 5a9221b63..b6897c517 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -27,7 +27,7 @@ public class Goal extends Z3Object { /** * The precision of the goal. - * Remarks: Goals can be transformed using over + * Remarks: Goals can be transformed using over * and under approximations. An under approximation is applied when the * objective is to find a model for a given goal. An over approximation is * applied when the objective is to find a proof for a given goal. @@ -97,7 +97,7 @@ public class Goal extends Z3Object /** * The depth of the goal. - * Remarks: This tracks how many transformations + * Remarks: This tracks how many transformations * were applied to it. **/ public int getDepth() throws Z3Exception @@ -176,7 +176,7 @@ public class Goal extends Z3Object /** * Simplifies the goal. - * Remarks: Essentially invokes the `simplify' tactic + * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ public Goal simplify() throws Z3Exception @@ -192,7 +192,7 @@ public class Goal extends Z3Object /** * Simplifies the goal. - * Remarks: Essentially invokes the `simplify' tactic + * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ public Goal simplify(Params p) throws Z3Exception diff --git a/src/api/java/GoalDecRefQueue.java b/src/api/java/GoalDecRefQueue.java index 45992170f..dd9d69414 100644 --- a/src/api/java/GoalDecRefQueue.java +++ b/src/api/java/GoalDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class GoalDecRefQueue extends IDecRefQueue { + public GoalDecRefQueue() + { + super(); + } + + public GoalDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/IDecRefQueue.java b/src/api/java/IDecRefQueue.java index 2190f8e4d..e8cab3477 100644 --- a/src/api/java/IDecRefQueue.java +++ b/src/api/java/IDecRefQueue.java @@ -21,39 +21,49 @@ import java.util.LinkedList; abstract class IDecRefQueue { - protected Object m_lock = new Object(); - protected LinkedList m_queue = new LinkedList(); - protected final int m_move_limit = 1024; + protected Object m_lock = new Object(); + protected LinkedList m_queue = new LinkedList(); + protected int m_move_limit; - protected abstract void incRef(Context ctx, long obj); + public IDecRefQueue() + { + m_move_limit = 1024; + } - protected abstract void decRef(Context ctx, long obj); + public IDecRefQueue(int move_limit) + { + m_move_limit = move_limit; + } - protected void incAndClear(Context ctx, long o) - { - incRef(ctx, o); - if (m_queue.size() >= m_move_limit) - clear(ctx); - } + protected abstract void incRef(Context ctx, long obj); - protected void add(long o) - { - if (o == 0) - return; + protected abstract void decRef(Context ctx, long obj); - synchronized (m_lock) - { - m_queue.add(o); - } - } + protected void incAndClear(Context ctx, long o) + { + incRef(ctx, o); + if (m_queue.size() >= m_move_limit) + clear(ctx); + } - protected void clear(Context ctx) - { - synchronized (m_lock) - { - for (Long o : m_queue) - decRef(ctx, o); - m_queue.clear(); - } - } + protected void add(long o) + { + if (o == 0) + return; + + synchronized (m_lock) + { + m_queue.add(o); + } + } + + protected void clear(Context ctx) + { + synchronized (m_lock) + { + for (Long o : m_queue) + decRef(ctx, o); + m_queue.clear(); + } + } } diff --git a/src/api/java/IDisposable.java b/src/api/java/IDisposable.java index 9092213e3..dddfa5824 100644 --- a/src/api/java/IDisposable.java +++ b/src/api/java/IDisposable.java @@ -21,7 +21,7 @@ package com.microsoft.z3; public class IDisposable { - public void dispose() throws Z3Exception - { - } + public void dispose() throws Z3Exception + { + } } diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index 642a58a54..a424cd51e 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class IntExpr extends ArithExpr { - /** - * Constructor for IntExpr - * @throws Z3Exception on error - **/ - IntExpr(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + /** + * Constructor for IntExpr + * @throws Z3Exception on error + **/ + IntExpr(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } } diff --git a/src/api/java/IntSort.java b/src/api/java/IntSort.java index bcfc730c4..0b1047718 100644 --- a/src/api/java/IntSort.java +++ b/src/api/java/IntSort.java @@ -22,13 +22,13 @@ package com.microsoft.z3; **/ public class IntSort extends ArithSort { - IntSort(Context ctx, long obj) throws Z3Exception - { - super(ctx, obj); - } + IntSort(Context ctx, long obj) throws Z3Exception + { + super(ctx, obj); + } - IntSort(Context ctx) throws Z3Exception - { - super(ctx, Native.mkIntSort(ctx.nCtx())); - } + IntSort(Context ctx) throws Z3Exception + { + super(ctx, Native.mkIntSort(ctx.nCtx())); + } } diff --git a/src/api/java/IntSymbol.java b/src/api/java/IntSymbol.java index a677c9102..01f75e0a4 100644 --- a/src/api/java/IntSymbol.java +++ b/src/api/java/IntSymbol.java @@ -26,7 +26,7 @@ public class IntSymbol extends Symbol { /** * The int value of the symbol. - * Remarks: Throws an exception if the symbol + * Remarks: Throws an exception if the symbol * is not of int kind. **/ public int getInt() throws Z3Exception diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index c1590e07f..4c20ec6ae 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -43,8 +43,8 @@ public class InterpolationContext extends Context * Constructor. * * - * Remarks: - * @see Context#Context + * Remarks: + * @see Context#Context **/ public InterpolationContext(Map settings) throws Z3Exception { diff --git a/src/api/java/Log.java b/src/api/java/Log.java index 3e8f0050b..ac0ebfb7f 100644 --- a/src/api/java/Log.java +++ b/src/api/java/Log.java @@ -19,7 +19,7 @@ package com.microsoft.z3; /** * Interaction logging for Z3. - * Remarks: Note that this is a global, static log + * Remarks: Note that this is a global, static log * and if multiple Context objects are created, it logs the interaction with all * of them. **/ @@ -29,7 +29,7 @@ public final class Log /** * Open an interaction log file. - * @param filename the name of the file to open + * @param filename the name of the file to open * * @return True if opening the log file succeeds, false otherwise. **/ diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 70f0e91c5..9392aacb6 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -27,7 +27,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of {@code a} in * the model. - * @param a A Constant + * @param a A Constant * * @return An expression if the constant has an interpretation in the model, * null otherwise. @@ -42,7 +42,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of {@code f} in * the model. - * @param f A function declaration of zero arity + * @param f A function declaration of zero arity * * @return An expression if the function has an interpretation in the model, * null otherwise. @@ -68,7 +68,7 @@ public class Model extends Z3Object /** * Retrieves the interpretation (the assignment) of a non-constant {@code f} in the model. - * @param f A function declaration of non-zero arity + * @param f A function declaration of non-zero arity * * @return A FunctionInterpretation if the function has an interpretation in * the model, null otherwise. @@ -201,7 +201,7 @@ public class Model extends Z3Object * Remarks: This function may fail if {@code t} contains * quantifiers, is partial (MODEL_PARTIAL enabled), or if {@code t} is not well-sorted. In this case a * {@code ModelEvaluationFailedException} is thrown. - * @param t An expression {@code completion} When this flag + * @param t An expression {@code completion} When this flag * is enabled, a model value will be assigned to any constant or function * that does not have an interpretation in the model. * @@ -243,8 +243,8 @@ public class Model extends Z3Object * in a formula. The interpretation for a sort is a finite set of distinct * values. We say this finite set is the "universe" of the sort. * - * @see getNumSorts - * @see getSortUniverse + * @see getNumSorts + * @see getSortUniverse * * @throws Z3Exception **/ @@ -262,7 +262,7 @@ public class Model extends Z3Object /** * The finite set of distinct values that represent the interpretation for * sort {@code s}. - * @param s An uninterpreted sort + * @param s An uninterpreted sort * * @return An array of expressions, where each is an element of the universe * of {@code s} diff --git a/src/api/java/ModelDecRefQueue.java b/src/api/java/ModelDecRefQueue.java index 1200b29be..c954a1fa8 100644 --- a/src/api/java/ModelDecRefQueue.java +++ b/src/api/java/ModelDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ModelDecRefQueue extends IDecRefQueue { + public ModelDecRefQueue() + { + super(); + } + + public ModelDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ParamDescrsDecRefQueue.java b/src/api/java/ParamDescrsDecRefQueue.java index a29565e8e..95a92475e 100644 --- a/src/api/java/ParamDescrsDecRefQueue.java +++ b/src/api/java/ParamDescrsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ParamDescrsDecRefQueue extends IDecRefQueue { + public ParamDescrsDecRefQueue() + { + super(); + } + + public ParamDescrsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ParamsDecRefQueue.java b/src/api/java/ParamsDecRefQueue.java index 7d71feb8f..7b9f34c00 100644 --- a/src/api/java/ParamsDecRefQueue.java +++ b/src/api/java/ParamsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ParamsDecRefQueue extends IDecRefQueue { + public ParamsDecRefQueue() + { + super(); + } + + public ParamsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/ProbeDecRefQueue.java b/src/api/java/ProbeDecRefQueue.java index fda5d37b4..e271bd949 100644 --- a/src/api/java/ProbeDecRefQueue.java +++ b/src/api/java/ProbeDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class ProbeDecRefQueue extends IDecRefQueue { + public ProbeDecRefQueue() + { + super(); + } + + public ProbeDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index 58245d723..3ea2b2eaf 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -171,13 +171,13 @@ public class Quantifier extends BoolExpr } else { setNativeObject(Native.mkQuantifierEx(ctx.nCtx(), - (isForall) ? true : false, weight, AST.getNativeObject(quantifierID), - AST.getNativeObject(skolemID), - AST.arrayLength(patterns), AST.arrayToNative(patterns), - AST.arrayLength(noPatterns), AST.arrayToNative(noPatterns), - AST.arrayLength(sorts), AST.arrayToNative(sorts), - Symbol.arrayToNative(names), - body.getNativeObject())); + (isForall) ? true : false, weight, AST.getNativeObject(quantifierID), + AST.getNativeObject(skolemID), + AST.arrayLength(patterns), AST.arrayToNative(patterns), + AST.arrayLength(noPatterns), AST.arrayToNative(noPatterns), + AST.arrayLength(sorts), AST.arrayToNative(sorts), + Symbol.arrayToNative(names), + body.getNativeObject())); } } diff --git a/src/api/java/RatNum.java b/src/api/java/RatNum.java index 2e92a9429..278aba65e 100644 --- a/src/api/java/RatNum.java +++ b/src/api/java/RatNum.java @@ -62,7 +62,7 @@ public class RatNum extends RealExpr /** * Returns a string representation in decimal notation. - * Remarks: The result + * Remarks: The result * has at most {@code precision} decimal places. **/ public String toDecimalString(int precision) throws Z3Exception diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index b9c9ebca6..3e66a29ac 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -57,8 +57,8 @@ public class Solver extends Z3Object /** * The current number of backtracking points (scopes). - * @see pop - * @see push + * @see pop + * @see push **/ public int getNumScopes() throws Z3Exception { @@ -68,7 +68,7 @@ public class Solver extends Z3Object /** * Creates a backtracking point. - * @see pop + * @see pop **/ public void push() throws Z3Exception { @@ -77,7 +77,7 @@ public class Solver extends Z3Object /** * Backtracks one backtracking point. - * Remarks: . + * Remarks: . **/ public void pop() throws Z3Exception { @@ -86,10 +86,10 @@ public class Solver extends Z3Object /** * Backtracks {@code n} backtracking points. - * Remarks: Note that + * Remarks: Note that * an exception is thrown if {@code n} is not smaller than * {@code NumScopes} - * @see push + * @see push **/ public void pop(int n) throws Z3Exception { @@ -98,7 +98,7 @@ public class Solver extends Z3Object /** * Resets the Solver. - * Remarks: This removes all assertions from the + * Remarks: This removes all assertions from the * solver. **/ public void reset() throws Z3Exception @@ -121,20 +121,20 @@ public class Solver extends Z3Object } } - // / - // / Assert multiple constraints into the solver, and track them (in the - // unsat) core - // / using the Boolean constants in ps. - // / - // / Remarks: - // / This API is an alternative to with assumptions for - // extracting unsat cores. - // / Both APIs can be used in the same solver. The unsat core will contain a - // combination - // / of the Boolean variables provided using - // and the Boolean literals - // / provided using with assumptions. - // / + /** + * Assert multiple constraints into the solver, and track them (in the + * unsat) core + * using the Boolean constants in ps. + * + * Remarks: + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + **/ public void assertAndTrack(BoolExpr[] constraints, BoolExpr[] ps) throws Z3Exception { getContext().checkContextMatch(constraints); @@ -147,19 +147,19 @@ public class Solver extends Z3Object constraints[i].getNativeObject(), ps[i].getNativeObject()); } - // / - // / Assert a constraint into the solver, and track it (in the unsat) core - // / using the Boolean constant p. - // / - // / Remarks: - // / This API is an alternative to with assumptions for - // extracting unsat cores. - // / Both APIs can be used in the same solver. The unsat core will contain a - // combination - // / of the Boolean variables provided using - // and the Boolean literals - // / provided using with assumptions. - // / + /** + * Assert a constraint into the solver, and track it (in the unsat) core + * using the Boolean constant p. + * + * Remarks: + * This API is an alternative to with assumptions for + * extracting unsat cores. + * Both APIs can be used in the same solver. The unsat core will contain a + * combination + * of the Boolean variables provided using + * and the Boolean literals + * provided using with assumptions. + */ public void assertAndTrack(BoolExpr constraint, BoolExpr p) throws Z3Exception { getContext().checkContextMatch(constraint); @@ -200,9 +200,9 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. * Remarks: - * @see getModel - * @see getUnsatCore - * @see getProof + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check(Expr... assumptions) throws Z3Exception { @@ -228,9 +228,9 @@ public class Solver extends Z3Object /** * Checks whether the assertions in the solver are consistent or not. * Remarks: - * @see getModel - * @see getUnsatCore - * @see getProof + * @see getModel + * @see getUnsatCore + * @see getProof **/ public Status check() throws Z3Exception { @@ -239,7 +239,7 @@ public class Solver extends Z3Object /** * The model of the last {@code Check}. - * Remarks: The result is + * Remarks: The result is * {@code null} if {@code Check} was not invoked before, if its * results was not {@code SATISFIABLE}, or if model production is not * enabled. @@ -257,7 +257,7 @@ public class Solver extends Z3Object /** * The proof of the last {@code Check}. - * Remarks: The result is + * Remarks: The result is * {@code null} if {@code Check} was not invoked before, if its * results was not {@code UNSATISFIABLE}, or if proof production is * disabled. @@ -275,7 +275,7 @@ public class Solver extends Z3Object /** * The unsat core of the last {@code Check}. - * Remarks: The unsat core + * Remarks: The unsat core * is a subset of {@code Assertions} The result is empty if * {@code Check} was not invoked before, if its results was not * {@code UNSATISFIABLE}, or if core production is disabled. diff --git a/src/api/java/SolverDecRefQueue.java b/src/api/java/SolverDecRefQueue.java index 993c99621..cbe5bbc3b 100644 --- a/src/api/java/SolverDecRefQueue.java +++ b/src/api/java/SolverDecRefQueue.java @@ -19,6 +19,13 @@ package com.microsoft.z3; class SolverDecRefQueue extends IDecRefQueue { + public SolverDecRefQueue() { super(); } + + public SolverDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 270abd43f..e1cbbea7c 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -29,20 +29,20 @@ public class Sort extends AST /** * Equality operator for objects of type Sort. - * @param o + * @param o * @return **/ public boolean equals(Object o) { Sort casted = null; - try { - casted = Sort.class.cast(o); - } catch (ClassCastException e) { - return false; - } + try { + casted = Sort.class.cast(o); + } catch (ClassCastException e) { + return false; + } - return this.getNativeObject() == casted.getNativeObject(); + return this.getNativeObject() == casted.getNativeObject(); } /** @@ -135,9 +135,9 @@ public class Sort extends AST case Z3_RELATION_SORT: return new RelationSort(ctx, obj); case Z3_FLOATING_POINT_SORT: - return new FPSort(ctx, obj); + return new FPSort(ctx, obj); case Z3_ROUNDING_MODE_SORT: - return new FPRMSort(ctx, obj); + return new FPRMSort(ctx, obj); default: throw new Z3Exception("Unknown sort kind"); } diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index 88a897d15..475352024 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -177,7 +177,7 @@ public class Statistics extends Z3Object /** * The value of a particular statistical counter. - * Remarks: Returns null if + * Remarks: Returns null if * the key is unknown. * * @throws Z3Exception diff --git a/src/api/java/StatisticsDecRefQueue.java b/src/api/java/StatisticsDecRefQueue.java index db3e32c86..89c66a746 100644 --- a/src/api/java/StatisticsDecRefQueue.java +++ b/src/api/java/StatisticsDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class StatisticsDecRefQueue extends IDecRefQueue { + public StatisticsDecRefQueue() + { + super(); + } + + public StatisticsDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/StringSymbol.java b/src/api/java/StringSymbol.java index 4692b0fb9..122c7765f 100644 --- a/src/api/java/StringSymbol.java +++ b/src/api/java/StringSymbol.java @@ -26,7 +26,7 @@ public class StringSymbol extends Symbol { /** * The string value of the symbol. - * Remarks: Throws an exception if the + * Remarks: Throws an exception if the * symbol is not of string kind. **/ public String getString() throws Z3Exception diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index 0286e786d..79f60e497 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -49,7 +49,7 @@ public class Tactic extends Z3Object * @throws Z3Exception **/ public ApplyResult apply(Goal g) throws Z3Exception - { + { return apply(g, null); } @@ -74,7 +74,7 @@ public class Tactic extends Z3Object /** * Creates a solver that is implemented using the given tactic. - * @see Context#mkSolver(Tactic) + * @see Context#mkSolver(Tactic) * @throws Z3Exception **/ public Solver getSolver() throws Z3Exception diff --git a/src/api/java/TacticDecRefQueue.java b/src/api/java/TacticDecRefQueue.java index 5557d03b8..026760e46 100644 --- a/src/api/java/TacticDecRefQueue.java +++ b/src/api/java/TacticDecRefQueue.java @@ -19,6 +19,16 @@ package com.microsoft.z3; class TacticDecRefQueue extends IDecRefQueue { + public TacticDecRefQueue() + { + super(); + } + + public TacticDecRefQueue(int move_limit) + { + super(move_limit); + } + protected void incRef(Context ctx, long obj) { try diff --git a/src/api/java/Version.java b/src/api/java/Version.java index 6e2fe5084..939a3ca5c 100644 --- a/src/api/java/Version.java +++ b/src/api/java/Version.java @@ -19,7 +19,7 @@ package com.microsoft.z3; /** * Version information. - * Remarks: Note that this class is static. + * Remarks: Note that this class is static. **/ public class Version { diff --git a/src/api/java/Z3Object.java b/src/api/java/Z3Object.java index 03cfcd625..9b39a3e2f 100644 --- a/src/api/java/Z3Object.java +++ b/src/api/java/Z3Object.java @@ -115,7 +115,7 @@ public class Z3Object extends IDisposable return null; long[] an = new long[a.length]; for (int i = 0; i < a.length; i++) - an[i] = (a[i] == null) ? 0 : a[i].getNativeObject(); + an[i] = (a[i] == null) ? 0 : a[i].getNativeObject(); return an; } From 4bed5183f890b8b8fbecb7abe69beb0f18c47d72 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 30 Jan 2015 21:58:43 -0600 Subject: [PATCH 538/646] Made DRQ objects public in Java and .NET APIs. Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/AST.cs | 4 +- src/api/dotnet/ASTMap.cs | 4 +- src/api/dotnet/ASTVector.cs | 4 +- src/api/dotnet/ApplyResult.cs | 4 +- src/api/dotnet/Context.cs | 89 ++++++++++++++++++++++++++++------ src/api/dotnet/Fixedpoint.cs | 4 +- src/api/dotnet/FuncInterp.cs | 8 +-- src/api/dotnet/Goal.cs | 4 +- src/api/dotnet/IDecRefQueue.cs | 33 ++++++++----- src/api/dotnet/Model.cs | 4 +- src/api/dotnet/ParamDescrs.cs | 4 +- src/api/dotnet/Params.cs | 4 +- src/api/dotnet/Probe.cs | 4 +- src/api/dotnet/Solver.cs | 4 +- src/api/dotnet/Statistics.cs | 4 +- src/api/dotnet/Tactic.cs | 7 ++- src/api/java/AST.java | 4 +- src/api/java/ASTMap.java | 4 +- src/api/java/ASTVector.java | 4 +- src/api/java/ApplyResult.java | 4 +- src/api/java/Context.java | 30 ++++++------ src/api/java/Fixedpoint.java | 4 +- src/api/java/FuncInterp.java | 8 +-- src/api/java/Goal.java | 4 +- src/api/java/IDecRefQueue.java | 16 +++--- src/api/java/Model.java | 4 +- src/api/java/ParamDescrs.java | 4 +- src/api/java/Params.java | 4 +- src/api/java/Probe.java | 4 +- src/api/java/Solver.java | 4 +- src/api/java/Statistics.java | 4 +- src/api/java/Tactic.java | 4 +- 32 files changed, 182 insertions(+), 109 deletions(-) diff --git a/src/api/dotnet/AST.cs b/src/api/dotnet/AST.cs index 552fd6def..2ffaaa661 100644 --- a/src/api/dotnet/AST.cs +++ b/src/api/dotnet/AST.cs @@ -215,12 +215,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/ASTMap.cs b/src/api/dotnet/ASTMap.cs index fa8070908..6f296147e 100644 --- a/src/api/dotnet/ASTMap.cs +++ b/src/api/dotnet/ASTMap.cs @@ -130,12 +130,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_ast_map_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_ast_map_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/ASTVector.cs b/src/api/dotnet/ASTVector.cs index be5172f97..597b1decc 100644 --- a/src/api/dotnet/ASTVector.cs +++ b/src/api/dotnet/ASTVector.cs @@ -107,12 +107,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_ast_vector_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_ast_vector_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/ApplyResult.cs b/src/api/dotnet/ApplyResult.cs index 4ff8851af..608be7080 100644 --- a/src/api/dotnet/ApplyResult.cs +++ b/src/api/dotnet/ApplyResult.cs @@ -87,12 +87,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_apply_result_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_apply_result_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 3c3a960df..d14c591aa 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4411,21 +4411,80 @@ namespace Microsoft.Z3 readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(10); readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10); - internal AST.DecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } - internal ASTMap.DecRefQueue ASTMap_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTMap_DRQ; } } - internal ASTVector.DecRefQueue ASTVector_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTVector_DRQ; } } - internal ApplyResult.DecRefQueue ApplyResult_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ApplyResult_DRQ; } } - internal FuncInterp.Entry.DecRefQueue FuncEntry_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_FuncEntry_DRQ; } } - internal FuncInterp.DecRefQueue FuncInterp_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_FuncInterp_DRQ; } } - internal Goal.DecRefQueue Goal_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Goal_DRQ; } } - internal Model.DecRefQueue Model_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Model_DRQ; } } - internal Params.DecRefQueue Params_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Params_DRQ; } } - internal ParamDescrs.DecRefQueue ParamDescrs_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ParamDescrs_DRQ; } } - internal Probe.DecRefQueue Probe_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Probe_DRQ; } } - internal Solver.DecRefQueue Solver_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Solver_DRQ; } } - internal Statistics.DecRefQueue Statistics_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Statistics_DRQ; } } - internal Tactic.DecRefQueue Tactic_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Tactic_DRQ; } } - internal Fixedpoint.DecRefQueue Fixedpoint_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Fixedpoint_DRQ; } } + /// + /// AST DRQ + /// + public IDecRefQueue AST_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_AST_DRQ; } } + + /// + /// ASTMap DRQ + /// + public IDecRefQueue ASTMap_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTMap_DRQ; } } + + /// + /// ASTVector DRQ + /// + public IDecRefQueue ASTVector_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ASTVector_DRQ; } } + + /// + /// ApplyResult DRQ + /// + public IDecRefQueue ApplyResult_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ApplyResult_DRQ; } } + + /// + /// FuncEntry DRQ + /// + public IDecRefQueue FuncEntry_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_FuncEntry_DRQ; } } + + /// + /// FuncInterp DRQ + /// + public IDecRefQueue FuncInterp_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_FuncInterp_DRQ; } } + + /// + /// Goal DRQ + /// + public IDecRefQueue Goal_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Goal_DRQ; } } + + /// + /// Model DRQ + /// + public IDecRefQueue Model_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Model_DRQ; } } + + /// + /// Params DRQ + /// + public IDecRefQueue Params_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Params_DRQ; } } + + /// + /// ParamDescrs DRQ + /// + public IDecRefQueue ParamDescrs_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_ParamDescrs_DRQ; } } + + /// + /// Probe DRQ + /// + public IDecRefQueue Probe_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Probe_DRQ; } } + + /// + /// Solver DRQ + /// + public IDecRefQueue Solver_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Solver_DRQ; } } + + /// + /// Statistics DRQ + /// + public IDecRefQueue Statistics_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Statistics_DRQ; } } + + /// + /// Tactic DRQ + /// + public IDecRefQueue Tactic_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Tactic_DRQ; } } + + /// + /// FixedPoint DRQ + /// + public IDecRefQueue Fixedpoint_DRQ { get { Contract.Ensures(Contract.Result() != null); return m_Fixedpoint_DRQ; } } internal long refCount = 0; diff --git a/src/api/dotnet/Fixedpoint.cs b/src/api/dotnet/Fixedpoint.cs index 37ae1b110..281ed9ad2 100644 --- a/src/api/dotnet/Fixedpoint.cs +++ b/src/api/dotnet/Fixedpoint.cs @@ -337,12 +337,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_fixedpoint_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_fixedpoint_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/FuncInterp.cs b/src/api/dotnet/FuncInterp.cs index 488abb780..449d460f9 100644 --- a/src/api/dotnet/FuncInterp.cs +++ b/src/api/dotnet/FuncInterp.cs @@ -93,12 +93,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_func_entry_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_func_entry_dec_ref(ctx.nCtx, obj); } @@ -201,12 +201,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_func_interp_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_func_interp_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Goal.cs b/src/api/dotnet/Goal.cs index 13c98f932..46d519d35 100644 --- a/src/api/dotnet/Goal.cs +++ b/src/api/dotnet/Goal.cs @@ -221,12 +221,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_goal_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_goal_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/IDecRefQueue.cs b/src/api/dotnet/IDecRefQueue.cs index a69e28ff2..43506fabf 100644 --- a/src/api/dotnet/IDecRefQueue.cs +++ b/src/api/dotnet/IDecRefQueue.cs @@ -25,8 +25,11 @@ using System.Diagnostics.Contracts; namespace Microsoft.Z3 { + /// + /// DecRefQueue interface + /// [ContractClass(typeof(DecRefQueueContracts))] - internal abstract class IDecRefQueue + public abstract class IDecRefQueue { #region Object invariant @@ -38,19 +41,25 @@ namespace Microsoft.Z3 #endregion - readonly internal protected Object m_lock = new Object(); - readonly internal protected List m_queue = new List(); - internal uint m_move_limit; + readonly private Object m_lock = new Object(); + readonly private List m_queue = new List(); + private uint m_move_limit; - public IDecRefQueue(uint move_limit = 1024) + internal IDecRefQueue(uint move_limit = 1024) { m_move_limit = move_limit; } - public abstract void IncRef(Context ctx, IntPtr obj); - public abstract void DecRef(Context ctx, IntPtr obj); + /// + /// Sets the limit on numbers of objects that are kept back at GC collection. + /// + /// + public void SetLimit(uint l) { m_move_limit = l; } - public void IncAndClear(Context ctx, IntPtr o) + internal abstract void IncRef(Context ctx, IntPtr obj); + internal abstract void DecRef(Context ctx, IntPtr obj); + + internal void IncAndClear(Context ctx, IntPtr o) { Contract.Requires(ctx != null); @@ -58,7 +67,7 @@ namespace Microsoft.Z3 if (m_queue.Count >= m_move_limit) Clear(ctx); } - public void Add(IntPtr o) + internal void Add(IntPtr o) { if (o == IntPtr.Zero) return; @@ -68,7 +77,7 @@ namespace Microsoft.Z3 } } - public void Clear(Context ctx) + internal void Clear(Context ctx) { Contract.Requires(ctx != null); @@ -84,12 +93,12 @@ namespace Microsoft.Z3 [ContractClassFor(typeof(IDecRefQueue))] abstract class DecRefQueueContracts : IDecRefQueue { - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Contract.Requires(ctx != null); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Contract.Requires(ctx != null); } diff --git a/src/api/dotnet/Model.cs b/src/api/dotnet/Model.cs index 9cff1e667..adf233a98 100644 --- a/src/api/dotnet/Model.cs +++ b/src/api/dotnet/Model.cs @@ -293,12 +293,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_model_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_model_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/ParamDescrs.cs b/src/api/dotnet/ParamDescrs.cs index a08e11859..af2916faa 100644 --- a/src/api/dotnet/ParamDescrs.cs +++ b/src/api/dotnet/ParamDescrs.cs @@ -89,12 +89,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_param_descrs_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_param_descrs_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Params.cs b/src/api/dotnet/Params.cs index de2287af5..81ca6727b 100644 --- a/src/api/dotnet/Params.cs +++ b/src/api/dotnet/Params.cs @@ -142,12 +142,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_params_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_params_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Probe.cs b/src/api/dotnet/Probe.cs index e8907b294..c10755263 100644 --- a/src/api/dotnet/Probe.cs +++ b/src/api/dotnet/Probe.cs @@ -75,12 +75,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_probe_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_probe_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Solver.cs b/src/api/dotnet/Solver.cs index 2e12a5842..012a283f5 100644 --- a/src/api/dotnet/Solver.cs +++ b/src/api/dotnet/Solver.cs @@ -330,12 +330,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_solver_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_solver_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Statistics.cs b/src/api/dotnet/Statistics.cs index 81240e2c0..cf4b703fe 100644 --- a/src/api/dotnet/Statistics.cs +++ b/src/api/dotnet/Statistics.cs @@ -191,12 +191,12 @@ namespace Microsoft.Z3 { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_stats_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_stats_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/dotnet/Tactic.cs b/src/api/dotnet/Tactic.cs index be79c2a43..8399490d5 100644 --- a/src/api/dotnet/Tactic.cs +++ b/src/api/dotnet/Tactic.cs @@ -112,16 +112,19 @@ namespace Microsoft.Z3 Contract.Requires(ctx != null); } + /// + /// DecRefQueue + /// internal class DecRefQueue : IDecRefQueue { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } - public override void IncRef(Context ctx, IntPtr obj) + internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_tactic_inc_ref(ctx.nCtx, obj); } - public override void DecRef(Context ctx, IntPtr obj) + internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_tactic_dec_ref(ctx.nCtx, obj); } diff --git a/src/api/java/AST.java b/src/api/java/AST.java index fdb1643a5..870f1d5d3 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -229,7 +229,7 @@ public class AST extends Z3Object // Console.WriteLine("AST IncRef()"); if (getContext() == null || o == 0) return; - getContext().ast_DRQ().incAndClear(getContext(), o); + getContext().getASTDRQ().incAndClear(getContext(), o); super.incRef(o); } @@ -238,7 +238,7 @@ public class AST extends Z3Object // Console.WriteLine("AST DecRef()"); if (getContext() == null || o == 0) return; - getContext().ast_DRQ().add(o); + getContext().getASTDRQ().add(o); super.decRef(o); } diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index 96ddfbf76..a37e9d0ff 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -124,13 +124,13 @@ class ASTMap extends Z3Object void incRef(long o) throws Z3Exception { - getContext().astmap_DRQ().incAndClear(getContext(), o); + getContext().getASTMapDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().astmap_DRQ().add(o); + getContext().getASTMapDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 30c96e2e7..48c079ecc 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -110,13 +110,13 @@ class ASTVector extends Z3Object void incRef(long o) throws Z3Exception { - getContext().astvector_DRQ().incAndClear(getContext(), o); + getContext().getASTVectorDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().astvector_DRQ().add(o); + getContext().getASTVectorDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/ApplyResult.java b/src/api/java/ApplyResult.java index d21a78a9c..8e998111f 100644 --- a/src/api/java/ApplyResult.java +++ b/src/api/java/ApplyResult.java @@ -81,13 +81,13 @@ public class ApplyResult extends Z3Object void incRef(long o) throws Z3Exception { - getContext().applyResult_DRQ().incAndClear(getContext(), o); + getContext().getApplyResultDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().applyResult_DRQ().add(o); + getContext().getApplyResultDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 42fd0f7e1..e9dd42dc0 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3674,77 +3674,77 @@ public class Context extends IDisposable private TacticDecRefQueue m_Tactic_DRQ = new TacticDecRefQueue(10); private FixedpointDecRefQueue m_Fixedpoint_DRQ = new FixedpointDecRefQueue(10); - ASTDecRefQueue ast_DRQ() + public IDecRefQueue getASTDRQ() { return m_AST_DRQ; } - ASTMapDecRefQueue astmap_DRQ() + public IDecRefQueue getASTMapDRQ() { return m_ASTMap_DRQ; } - ASTVectorDecRefQueue astvector_DRQ() + public IDecRefQueue getASTVectorDRQ() { return m_ASTVector_DRQ; } - ApplyResultDecRefQueue applyResult_DRQ() + public IDecRefQueue getApplyResultDRQ() { return m_ApplyResult_DRQ; } - FuncInterpEntryDecRefQueue funcEntry_DRQ() + public IDecRefQueue getFuncEntryDRQ() { return m_FuncEntry_DRQ; } - FuncInterpDecRefQueue funcInterp_DRQ() + public IDecRefQueue getFuncInterpDRQ() { return m_FuncInterp_DRQ; } - GoalDecRefQueue goal_DRQ() + public IDecRefQueue getGoalDRQ() { return m_Goal_DRQ; } - ModelDecRefQueue model_DRQ() + public IDecRefQueue getModelDRQ() { return m_Model_DRQ; } - ParamsDecRefQueue params_DRQ() + public IDecRefQueue getParamsDRQ() { return m_Params_DRQ; } - ParamDescrsDecRefQueue paramDescrs_DRQ() + public IDecRefQueue getParamDescrsDRQ() { return m_ParamDescrs_DRQ; } - ProbeDecRefQueue probe_DRQ() + public IDecRefQueue getProbeDRQ() { return m_Probe_DRQ; } - SolverDecRefQueue solver_DRQ() + public IDecRefQueue getSolverDRQ() { return m_Solver_DRQ; } - StatisticsDecRefQueue statistics_DRQ() + public IDecRefQueue getStatisticsDRQ() { return m_Statistics_DRQ; } - TacticDecRefQueue tactic_DRQ() + public IDecRefQueue getTacticDRQ() { return m_Tactic_DRQ; } - FixedpointDecRefQueue fixedpoint_DRQ() + public IDecRefQueue getFixedpointDRQ() { return m_Fixedpoint_DRQ; } diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index 808785ddc..624a527fd 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -334,13 +334,13 @@ public class Fixedpoint extends Z3Object void incRef(long o) throws Z3Exception { - getContext().fixedpoint_DRQ().incAndClear(getContext(), o); + getContext().getFixedpointDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().fixedpoint_DRQ().add(o); + getContext().getFixedpointDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/FuncInterp.java b/src/api/java/FuncInterp.java index 7fb5ac13e..31f37a4ba 100644 --- a/src/api/java/FuncInterp.java +++ b/src/api/java/FuncInterp.java @@ -93,13 +93,13 @@ public class FuncInterp extends Z3Object void incRef(long o) throws Z3Exception { - getContext().funcEntry_DRQ().incAndClear(getContext(), o); + getContext().getFuncEntryDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().funcEntry_DRQ().add(o); + getContext().getFuncEntryDRQ().add(o); super.decRef(o); } }; @@ -194,13 +194,13 @@ public class FuncInterp extends Z3Object void incRef(long o) throws Z3Exception { - getContext().funcInterp_DRQ().incAndClear(getContext(), o); + getContext().getFuncInterpDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().funcInterp_DRQ().add(o); + getContext().getFuncInterpDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index b6897c517..64f2e0acb 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -236,13 +236,13 @@ public class Goal extends Z3Object void incRef(long o) throws Z3Exception { - getContext().goal_DRQ().incAndClear(getContext(), o); + getContext().getGoalDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().goal_DRQ().add(o); + getContext().getGoalDRQ().add(o); super.decRef(o); } diff --git a/src/api/java/IDecRefQueue.java b/src/api/java/IDecRefQueue.java index e8cab3477..823288a20 100644 --- a/src/api/java/IDecRefQueue.java +++ b/src/api/java/IDecRefQueue.java @@ -19,22 +19,24 @@ package com.microsoft.z3; import java.util.LinkedList; -abstract class IDecRefQueue +public abstract class IDecRefQueue { protected Object m_lock = new Object(); protected LinkedList m_queue = new LinkedList(); protected int m_move_limit; - public IDecRefQueue() - { - m_move_limit = 1024; + protected IDecRefQueue() + { + m_move_limit = 1024; } - public IDecRefQueue(int move_limit) + protected IDecRefQueue(int move_limit) { - m_move_limit = move_limit; + m_move_limit = move_limit; } - + + public void setLimit(int l) { m_move_limit = l; } + protected abstract void incRef(Context ctx, long obj); protected abstract void decRef(Context ctx, long obj); diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 9392aacb6..3d68d5485 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -303,13 +303,13 @@ public class Model extends Z3Object void incRef(long o) throws Z3Exception { - getContext().model_DRQ().incAndClear(getContext(), o); + getContext().getModelDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().model_DRQ().add(o); + getContext().getModelDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/ParamDescrs.java b/src/api/java/ParamDescrs.java index 4afae9f76..e1f0d16e5 100644 --- a/src/api/java/ParamDescrs.java +++ b/src/api/java/ParamDescrs.java @@ -90,13 +90,13 @@ public class ParamDescrs extends Z3Object void incRef(long o) throws Z3Exception { - getContext().paramDescrs_DRQ().incAndClear(getContext(), o); + getContext().getParamDescrsDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().paramDescrs_DRQ().add(o); + getContext().getParamDescrsDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Params.java b/src/api/java/Params.java index bbe6d66cf..693491f41 100644 --- a/src/api/java/Params.java +++ b/src/api/java/Params.java @@ -130,13 +130,13 @@ public class Params extends Z3Object void incRef(long o) throws Z3Exception { - getContext().params_DRQ().incAndClear(getContext(), o); + getContext().getParamsDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().params_DRQ().add(o); + getContext().getParamsDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Probe.java b/src/api/java/Probe.java index 335bd038c..62b0612b9 100644 --- a/src/api/java/Probe.java +++ b/src/api/java/Probe.java @@ -53,13 +53,13 @@ public class Probe extends Z3Object void incRef(long o) throws Z3Exception { - getContext().probe_DRQ().incAndClear(getContext(), o); + getContext().getProbeDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().probe_DRQ().add(o); + getContext().getProbeDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index 3e66a29ac..4b330ff86 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -337,13 +337,13 @@ public class Solver extends Z3Object void incRef(long o) throws Z3Exception { - getContext().solver_DRQ().incAndClear(getContext(), o); + getContext().getSolverDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().solver_DRQ().add(o); + getContext().getSolverDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index 475352024..aa909b9bd 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -199,13 +199,13 @@ public class Statistics extends Z3Object void incRef(long o) throws Z3Exception { - getContext().statistics_DRQ().incAndClear(getContext(), o); + getContext().getStatisticsDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().statistics_DRQ().add(o); + getContext().getStatisticsDRQ().add(o); super.decRef(o); } } diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index 79f60e497..65404a927 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -94,13 +94,13 @@ public class Tactic extends Z3Object void incRef(long o) throws Z3Exception { - getContext().tactic_DRQ().incAndClear(getContext(), o); + getContext().getTacticDRQ().incAndClear(getContext(), o); super.incRef(o); } void decRef(long o) throws Z3Exception { - getContext().tactic_DRQ().add(o); + getContext().getTacticDRQ().add(o); super.decRef(o); } } From 3478cdb75693801b97bc0aa92a819e9cc5e9dac9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 3 Feb 2015 12:30:42 +0000 Subject: [PATCH 539/646] Added smt kernel setup for QF_FP(BV). Thanks to codeplex user smccamant for reporting this performance problem. Signed-off-by: Christoph M. Wintersteiger --- src/ast/static_features.cpp | 6 ++++++ src/ast/static_features.h | 8 +++++++- src/smt/smt_setup.cpp | 25 +++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index cba31665c..e725df691 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -22,6 +22,8 @@ Revision History: static_features::static_features(ast_manager & m): m_manager(m), m_autil(m), + m_bvutil(m), + m_fpautil(m), m_bfid(m.get_basic_family_id()), m_afid(m.mk_family_id("arith")), m_lfid(m.mk_family_id("label")), @@ -266,6 +268,10 @@ void static_features::update_core(expr * e) { m_has_int = true; if (!m_has_real && m_autil.is_real(e)) m_has_real = true; + if (!m_has_bv && m_bvutil.is_bv(e)) + m_has_bv = true; + if (!m_has_fpa && (m_fpautil.is_float(e) || m_fpautil.is_rm(e))) + m_has_fpa = true; if (is_app(e)) { family_id fid = to_app(e)->get_family_id(); mark_theory(fid); diff --git a/src/ast/static_features.h b/src/ast/static_features.h index bbbea65bf..2d6213ded 100644 --- a/src/ast/static_features.h +++ b/src/ast/static_features.h @@ -21,14 +21,18 @@ Revision History: #include"ast.h" #include"arith_decl_plugin.h" +#include"bv_decl_plugin.h" +#include"fpa_decl_plugin.h" #include"map.h" struct static_features { ast_manager & m_manager; arith_util m_autil; + bv_util m_bvutil; + fpa_util m_fpautil; family_id m_bfid; family_id m_afid; - family_id m_lfid; + family_id m_lfid; ast_mark m_already_visited; bool m_cnf; unsigned m_num_exprs; // @@ -68,6 +72,8 @@ struct static_features { bool m_has_rational; // bool m_has_int; // bool m_has_real; // + bool m_has_bv; // + bool m_has_fpa; // rational m_arith_k_sum; // sum of the numerals in arith atoms. unsigned m_num_arith_terms; unsigned m_num_arith_eqs; // equalities of the form t = k where k is a numeral diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index d17e4b803..7abd40399 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -113,6 +113,10 @@ namespace smt { setup_UFLRA(); else if (m_logic == "LRA") setup_LRA(); + else if (m_logic == "QF_FP") + setup_QF_FP(); + else if (m_logic == "QF_FPBV") + setup_QF_FPBV(); else setup_unknown(); } @@ -680,7 +684,8 @@ namespace smt { setup_mi_arith(); } - void setup::setup_QF_FP() { + void setup::setup_QF_FP() { + setup_QF_BV(); m_context.register_plugin(alloc(smt::theory_fpa, m_manager)); } @@ -791,6 +796,7 @@ namespace smt { } void setup::setup_fpa() { + setup_bv(); m_context.register_plugin(alloc(theory_fpa, m_manager)); } @@ -867,7 +873,22 @@ namespace smt { return; } - // TODO QF_BV, QF_AUFBV, QF_AUFLIA + if (st.num_theories() == 1 && st.m_has_bv) { + setup_QF_BV(); + return; + } + + if (st.num_theories() == 1 && st.m_has_fpa) { + setup_QF_FP(); + return; + } + + if (st.num_theories() == 2 && st.m_has_fpa && st.m_has_bv) { + setup_QF_FPBV(); + return; + } + + // TODO QF_AUFBV, QF_AUFLIA setup_unknown(); } From a4c599a43511c899bf322c03b4789cd6c99da873 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Feb 2015 18:25:32 +0000 Subject: [PATCH 540/646] typo Signed-off-by: Christoph M. Wintersteiger --- src/ast/rewriter/rewriter.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ast/rewriter/rewriter.txt b/src/ast/rewriter/rewriter.txt index 84dd85e15..cdfba9f0f 100644 --- a/src/ast/rewriter/rewriter.txt +++ b/src/ast/rewriter/rewriter.txt @@ -6,8 +6,9 @@ The following classes implement theory specific rewriting rules: - bv_rewriter - array_rewriter - datatype_rewriter + - fpa_rewriter -Each of the provide the method +Each of them provide the method br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) where - f is expected to be a func_decl of the given theory From 9d5bc024e4b1500e328fe69c83b58f78e8df69b6 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Thu, 5 Feb 2015 09:51:05 +0000 Subject: [PATCH 541/646] add implementation of UNREACHABLE for MSVC in release mode. This reduces code size of Z3 by 0.1% \o/ Signed-off-by: Nuno Lopes --- src/util/debug.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/util/debug.h b/src/util/debug.h index a36743f73..f7383511b 100644 --- a/src/util/debug.h +++ b/src/util/debug.h @@ -58,12 +58,18 @@ bool is_debug_enabled(const char * tag); #define CASSERT(TAG, COND) DEBUG_CODE(if (assertions_enabled() && is_debug_enabled(TAG) && !(COND)) { notify_assertion_violation(__FILE__, __LINE__, #COND); INVOKE_DEBUGGER(); }) #define XASSERT(COND, EXTRA_CODE) DEBUG_CODE(if (assertions_enabled() && !(COND)) { notify_assertion_violation(__FILE__, __LINE__, #COND); { EXTRA_CODE } INVOKE_DEBUGGER(); }) +#ifdef Z3DEBUG +# define UNREACHABLE() DEBUG_CODE(notify_assertion_violation(__FILE__, __LINE__, "UNREACHABLE CODE WAS REACHED."); INVOKE_DEBUGGER();) +#else #if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 405)) || __has_builtin(__builtin_unreachable) // only available in gcc >= 4.5 and in newer versions of clang # define UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) +# define UNREACHABLE() __assume(0) #else #define UNREACHABLE() DEBUG_CODE(notify_assertion_violation(__FILE__, __LINE__, "UNREACHABLE CODE WAS REACHED."); INVOKE_DEBUGGER();) #endif +#endif #define NOT_IMPLEMENTED_YET() { std::cerr << "NOT IMPLEMENTED YET!\n"; UNREACHABLE(); exit(ERR_NOT_IMPLEMENTED_YET); } ((void) 0) From 088dc411bab7e65d99180245f94f0afd71fb9737 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 5 Feb 2015 18:32:36 +0000 Subject: [PATCH 542/646] fixed potential handle leak Signed-off-by: Christoph M. Wintersteiger --- src/shell/smtlib_frontend.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 3197f8cff..13c928ddd 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -124,6 +124,7 @@ unsigned read_smtlib2_commands(char const * file_name) { exit(ERR_OPEN_FILE); } result = parse_smt2_commands(ctx, in); + in.close(); } else { result = parse_smt2_commands(ctx, std::cin, true); From 0db973ab4bb95fe285559d28657c72a024240b10 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 5 Feb 2015 19:02:35 +0000 Subject: [PATCH 543/646] undid previous fix Signed-off-by: Christoph M. Wintersteiger --- src/shell/smtlib_frontend.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 13c928ddd..3197f8cff 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -124,7 +124,6 @@ unsigned read_smtlib2_commands(char const * file_name) { exit(ERR_OPEN_FILE); } result = parse_smt2_commands(ctx, in); - in.close(); } else { result = parse_smt2_commands(ctx, std::cin, true); From 5e60bcd920a0a65f7fa285aa0eada852cb8604c8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 6 Feb 2015 16:53:31 +0000 Subject: [PATCH 544/646] FPA: fixes for the fpa_rewriter to enable model extraction and validation. Signed-off-by: Christoph M. Wintersteiger --- src/ast/fpa/fpa2bv_converter.cpp | 10 +- src/ast/fpa/fpa2bv_rewriter_params.pyg | 4 +- src/ast/fpa_decl_plugin.h | 9 +- src/ast/rewriter/fpa_rewriter.cpp | 424 ++++++++++++++------- src/ast/rewriter/fpa_rewriter.h | 17 +- src/ast/rewriter/fpa_rewriter_params.pyg | 5 + src/ast/simplifier/fpa_simplifier_plugin.h | 4 +- src/tactic/fpa/qffp_tactic.cpp | 2 + src/util/mpf.cpp | 43 ++- src/util/mpf.h | 6 +- 10 files changed, 376 insertions(+), 148 deletions(-) create mode 100644 src/ast/rewriter/fpa_rewriter_params.pyg diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index bdaf2017e..8e2dd326a 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1872,7 +1872,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args m_bv_util.is_bv(args[0]) && m_bv_util.get_bv_size(args[0]) == 3 && m_util.is_float(m.get_sort(args[1]))) { - // float -> float conversion + // rm + float -> float mk_to_fp_float(f, f->get_range(), args[0], args[1], result); } else if (num == 2 && @@ -1886,12 +1886,14 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args m_bv_util.is_bv(args[0]) && m_bv_util.get_bv_size(args[0]) == 3 && m_bv_util.is_bv(args[1])) { + // rm + signed bv -> float mk_to_fp_signed(f, num, args, result); } else if (num == 3 && m_bv_util.is_bv(args[0]) && m_bv_util.is_bv(args[1]) && - m_bv_util.is_bv(args[2])) { + m_bv_util.is_bv(args[2])) { + // 3 BV -> float SASSERT(m_bv_util.get_bv_size(args[0]) == 1); SASSERT(m_util.get_ebits(f->get_range()) == m_bv_util.get_bv_size(args[1])); SASSERT(m_util.get_sbits(f->get_range()) == m_bv_util.get_bv_size(args[2])+1); @@ -1899,9 +1901,11 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args } else if (num == 3 && m_bv_util.is_bv(args[0]) && + m_bv_util.get_bv_size(args[0]) == 3 && m_arith_util.is_numeral(args[1]) && m_arith_util.is_numeral(args[2])) { + // rm + real + int -> float mk_to_fp_real_int(f, num, args, result); } else @@ -3206,7 +3210,7 @@ expr_ref fpa2bv_converter::mk_rounding_decision(expr * rm, expr * sgn, expr * la expr_ref inc_teven(m), inc_taway(m), inc_pos(m), inc_neg(m); inc_teven = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, nround_lors)); expr *taway_args[2] = { m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, nl_r)), - m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(3, nl_nr_sn)) }; + m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(3, nl_nr_sn)) }; inc_taway = m_bv_util.mk_bv_or(2, taway_args); inc_pos = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, pos_args)); inc_neg = m_bv_util.mk_bv_not(m_bv_util.mk_bv_or(2, neg_args)); diff --git a/src/ast/fpa/fpa2bv_rewriter_params.pyg b/src/ast/fpa/fpa2bv_rewriter_params.pyg index 42df0fa0e..91304f143 100644 --- a/src/ast/fpa/fpa2bv_rewriter_params.pyg +++ b/src/ast/fpa/fpa2bv_rewriter_params.pyg @@ -1,5 +1,5 @@ def_module_params(module_name='rewriter', class_name='fpa2bv_rewriter_params', export=True, - params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real)"), - )) + params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real"), +)) diff --git a/src/ast/fpa_decl_plugin.h b/src/ast/fpa_decl_plugin.h index fc1521456..0e7901aca 100644 --- a/src/ast/fpa_decl_plugin.h +++ b/src/ast/fpa_decl_plugin.h @@ -206,11 +206,12 @@ public: }; class fpa_util { - ast_manager & m_manager; + ast_manager & m_manager; fpa_decl_plugin * m_plugin; - family_id m_fid; - arith_util m_a_util; - bv_util m_bv_util; + family_id m_fid; + arith_util m_a_util; + bv_util m_bv_util; + public: fpa_util(ast_manager & m); ~fpa_util(); diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index 9a8ab7da0..394c2f117 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -17,16 +17,21 @@ Notes: --*/ #include"fpa_rewriter.h" +#include"fpa_rewriter_params.hpp" -fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p): - m_util(m) { +fpa_rewriter::fpa_rewriter(ast_manager & m, params_ref const & p) : + m_util(m), + m_fm(m_util.fm()), + m_hi_fp_unspecified(true) { updt_params(p); } fpa_rewriter::~fpa_rewriter() { } -void fpa_rewriter::updt_params(params_ref const & p) { +void fpa_rewriter::updt_params(params_ref const & _p) { + fpa_rewriter_params p(_p); + m_hi_fp_unspecified = p.hi_fp_unspecified(); } void fpa_rewriter::get_param_descrs(param_descrs & r) { @@ -35,9 +40,25 @@ void fpa_rewriter::get_param_descrs(param_descrs & r) { br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); - switch (f->get_decl_kind()) { - case OP_FPA_TO_FP: st = mk_to_fp(f, num_args, args, result); break; - case OP_FPA_TO_FP_UNSIGNED: st = mk_to_fp_unsigned(f, num_args, args, result); break; + fpa_op_kind k = (fpa_op_kind)f->get_decl_kind(); + switch (k) { + case OP_FPA_RM_NEAREST_TIES_TO_EVEN: + case OP_FPA_RM_NEAREST_TIES_TO_AWAY: + case OP_FPA_RM_TOWARD_POSITIVE: + case OP_FPA_RM_TOWARD_NEGATIVE: + case OP_FPA_RM_TOWARD_ZERO: + SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; + + case OP_FPA_PLUS_INF: + case OP_FPA_MINUS_INF: + case OP_FPA_NAN: + case OP_FPA_PLUS_ZERO: + case OP_FPA_MINUS_ZERO: + SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; + + case OP_FPA_NUM: + SASSERT(num_args == 0); result = m().mk_app(f, (expr * const *)0); st = BR_DONE; break; + case OP_FPA_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FPA_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; case OP_FPA_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; @@ -63,115 +84,208 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con case OP_FPA_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; case OP_FPA_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; case OP_FPA_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; + case OP_FPA_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; - case OP_FPA_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; - case OP_FPA_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; + case OP_FPA_TO_FP: st = mk_to_fp(f, num_args, args, result); break; + case OP_FPA_TO_FP_UNSIGNED: SASSERT(num_args == 2); st = mk_to_fp_unsigned(f, args[0], args[1], result); break; + case OP_FPA_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(f, args[0], args[1], result); break; + case OP_FPA_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(f, args[0], args[1], result); break; case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; - case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + + case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED: + SASSERT(num_args == 0); st = mk_to_ubv_unspecified(f, result); break; + case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: + SASSERT(num_args == 0); st = mk_to_sbv_unspecified(f, result); break; + case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: + SASSERT(num_args == 0); st = mk_to_real_unspecified(result); break; + + default: + NOT_IMPLEMENTED_YET(); } return st; } +br_status fpa_rewriter::mk_to_ubv_unspecified(func_decl * f, expr_ref & result) { + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + unsigned bv_sz = f->get_parameter(0).get_int(); + + bv_util bu(m()); + if (m_hi_fp_unspecified) + // The "hardware interpretation" is 0. + result = bu.mk_numeral(0, bv_sz); + else + result = m_util.mk_internal_to_real_unspecified(); + + return BR_DONE; +} + +br_status fpa_rewriter::mk_to_sbv_unspecified(func_decl * f, expr_ref & result) { + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + unsigned bv_sz = f->get_parameter(0).get_int(); + + bv_util bu(m()); + if (m_hi_fp_unspecified) + // The "hardware interpretation" is 0. + result = bu.mk_numeral(0, bv_sz); + else + result = m_util.mk_internal_to_real_unspecified(); + + return BR_DONE; +} + +br_status fpa_rewriter::mk_to_real_unspecified(expr_ref & result) { + if (m_hi_fp_unspecified) + result = m_util.au().mk_numeral(0, false); + else + // The "hardware interpretation" is 0. + result = m_util.mk_internal_to_real_unspecified(); + + return BR_DONE; +} + br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); SASSERT(f->get_parameter(1).is_int()); + bv_util bu(m()); + scoped_mpf v(m_fm); + mpf_rounding_mode rmv; + rational r1, r2, r3; + unsigned bvs1, bvs2, bvs3; unsigned ebits = f->get_parameter(0).get_int(); unsigned sbits = f->get_parameter(1).get_int(); - if (num_args == 2) { - mpf_rounding_mode rm; - if (!m_util.is_rm_numeral(args[0], rm)) + if (num_args == 1) { + if (bu.is_numeral(args[0], r1, bvs1)) { + // BV -> float + SASSERT(bvs1 == sbits + ebits); + unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); + unsynch_mpq_manager & mpqm = m_fm.mpq_manager(); + scoped_mpz sig(mpzm), exp(mpzm); + + const mpz & sm1 = m_fm.m_powers2(sbits - 1); + const mpz & em1 = m_fm.m_powers2(ebits); + + scoped_mpq q(mpqm); + mpqm.set(q, r1.to_mpq()); + SASSERT(mpzm.is_one(q.get().denominator())); + scoped_mpz z(mpzm); + z = q.get().numerator(); + + mpzm.rem(z, sm1, sig); + mpzm.div(z, sm1, z); + + mpzm.rem(z, em1, exp); + mpzm.div(z, em1, z); + + SASSERT(mpzm.is_int64(exp)); + mpf_exp_t mpf_exp = mpzm.get_int64(exp); + + m_fm.set(v, ebits, sbits, !mpzm.is_zero(z), sig, mpf_exp); + result = m_util.mk_value(v); + return BR_DONE; + } + } + else if (num_args == 2) { + if (!m_util.is_rm_numeral(args[0], rmv)) return BR_FAILED; - rational q; - scoped_mpf q_mpf(m_util.fm()); - if (m_util.au().is_numeral(args[1], q)) { - TRACE("fp_rewriter", tout << "q: " << q << std::endl; ); - scoped_mpf v(m_util.fm()); - m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); - result = m_util.mk_value(v); - m_util.fm().del(v); + if (m_util.au().is_numeral(args[1], r1)) { + // rm + real -> float + TRACE("fp_rewriter", tout << "r: " << r1 << std::endl;); + scoped_mpf v(m_fm); + m_fm.set(v, ebits, sbits, rmv, r1.to_mpq()); + result = m_util.mk_value(v); // TRACE("fp_rewriter", tout << "result: " << result << std::endl; ); return BR_DONE; } - else if (m_util.is_numeral(args[1], q_mpf)) { - TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; ); - scoped_mpf v(m_util.fm()); - m_util.fm().set(v, ebits, sbits, rm, q_mpf); + else if (m_util.is_numeral(args[1], v)) { + // rm + float -> float + TRACE("fp_rewriter", tout << "v: " << m_fm.to_string(v) << std::endl; ); + scoped_mpf v(m_fm); + m_fm.set(v, ebits, sbits, rmv, v); result = m_util.mk_value(v); - m_util.fm().del(v); // TRACE("fp_rewriter", tout << "result: " << result << std::endl; ); return BR_DONE; } - else - return BR_FAILED; + else if (bu.is_numeral(args[1], r1, bvs1)) { + // rm + signed bv -> float + scoped_mpf v(m_fm); + m_fm.set(v, ebits, sbits, rmv, r1.to_mpq()); + result = m_util.mk_value(v); + return BR_DONE; + } } - else if (num_args == 3) { - bv_util bu(m()); - rational r1, r2, r3; - unsigned bvs1, bvs2, bvs3; - - if (m_util.is_rm(args[0]) && + else if (num_args == 3) { + if (m_util.is_rm_numeral(args[0], rmv) && m_util.au().is_real(args[1]) && m_util.au().is_int(args[2])) { - mpf_rounding_mode rm; - if (!m_util.is_rm_numeral(args[0], rm)) + // rm + real + int -> float + if (!m_util.is_rm_numeral(args[0], rmv) || + !m_util.au().is_numeral(args[1], r1) || + !m_util.au().is_numeral(args[2], r2)) return BR_FAILED; - rational q; - if (!m_util.au().is_numeral(args[1], q)) - return BR_FAILED; - - rational e; - if (!m_util.au().is_numeral(args[2], e)) - return BR_FAILED; - - TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";); - scoped_mpf v(m_util.fm()); - m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator()); + TRACE("fp_rewriter", tout << "r1: " << r1 << ", r2: " << r2 << "\n";); + scoped_mpf v(m_fm); + m_fm.set(v, ebits, sbits, rmv, r1.to_mpq(), r2.to_mpq().numerator()); result = m_util.mk_value(v); - m_util.fm().del(v); return BR_DONE; } else if (bu.is_numeral(args[0], r1, bvs1) && bu.is_numeral(args[1], r2, bvs2) && bu.is_numeral(args[2], r3, bvs3)) { - SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator())); - SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator())); - SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator())); - scoped_mpf v(m_util.fm()); - mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator()); - m_util.fm().set(v, bvs2, bvs3 + 1, + // 3 BV -> float + SASSERT(m_fm.mpz_manager().is_one(r2.to_mpq().denominator())); + SASSERT(m_fm.mpz_manager().is_one(r3.to_mpq().denominator())); + SASSERT(m_fm.mpz_manager().is_int64(r3.to_mpq().numerator())); + scoped_mpf v(m_fm); + mpf_exp_t biased_exp = m_fm.mpz_manager().get_int64(r2.to_mpq().numerator()); + m_fm.set(v, bvs2, bvs3 + 1, r1.is_one(), r3.to_mpq().numerator(), - m_util.fm().unbias_exp(bvs2, biased_exp)); - TRACE("fp_rewriter", tout << "v = " << m_util.fm().to_string(v) << std::endl;); + m_fm.unbias_exp(bvs2, biased_exp)); + TRACE("fp_rewriter", tout << "v = " << m_fm.to_string(v) << std::endl;); result = m_util.mk_value(v); return BR_DONE; - } - else - return BR_FAILED; + } } - else - return BR_FAILED; + + return BR_FAILED; } -br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status fpa_rewriter::mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); - SASSERT(f->get_parameter(1).is_int()); + SASSERT(f->get_parameter(1).is_int()); + bv_util bu(m()); + unsigned ebits = f->get_parameter(0).get_int(); + unsigned sbits = f->get_parameter(1).get_int(); + mpf_rounding_mode rmv; + rational r; + unsigned bvs; + if (m_util.is_rm_numeral(arg1, rmv) && + bu.is_numeral(arg2, r, bvs)) { + scoped_mpf v(m_fm); + m_fm.set(v, ebits, sbits, rmv, r.to_mpq()); + result = m_util.mk_value(v); + return BR_DONE; + } + return BR_FAILED; } br_status fpa_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()), v3(m_util.fm()); + scoped_mpf v2(m_fm), v3(m_fm); if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { - scoped_mpf t(m_util.fm()); - m_util.fm().add(rm, v2, v3, t); + scoped_mpf t(m_fm); + m_fm.add(rm, v2, v3, t); result = m_util.mk_value(t); return BR_DONE; } @@ -189,10 +303,10 @@ br_status fpa_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()), v3(m_util.fm()); + scoped_mpf v2(m_fm), v3(m_fm); if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { - scoped_mpf t(m_util.fm()); - m_util.fm().mul(rm, v2, v3, t); + scoped_mpf t(m_fm); + m_fm.mul(rm, v2, v3, t); result = m_util.mk_value(t); return BR_DONE; } @@ -204,10 +318,10 @@ br_status fpa_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & br_status fpa_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()), v3(m_util.fm()); + scoped_mpf v2(m_fm), v3(m_fm); if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3)) { - scoped_mpf t(m_util.fm()); - m_util.fm().div(rm, v2, v3, t); + scoped_mpf t(m_fm); + m_fm.div(rm, v2, v3, t); result = m_util.mk_value(t); return BR_DONE; } @@ -238,22 +352,21 @@ br_status fpa_rewriter::mk_neg(expr * arg1, expr_ref & result) { return BR_DONE; } - scoped_mpf v1(m_util.fm()); + scoped_mpf v1(m_fm); if (m_util.is_numeral(arg1, v1)) { - m_util.fm().neg(v1); + m_fm.neg(v1); result = m_util.mk_value(v1); return BR_DONE; } - // TODO: more simplifications return BR_FAILED; } br_status fpa_rewriter::mk_rem(expr * arg1, expr * arg2, expr_ref & result) { - scoped_mpf v1(m_util.fm()), v2(m_util.fm()); + scoped_mpf v1(m_fm), v2(m_fm); if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { - scoped_mpf t(m_util.fm()); - m_util.fm().rem(v1, v2, t); + scoped_mpf t(m_fm); + m_fm.rem(v1, v2, t); result = m_util.mk_value(t); return BR_DONE; } @@ -267,6 +380,13 @@ br_status fpa_rewriter::mk_abs(expr * arg1, expr_ref & result) { return BR_DONE; } + scoped_mpf v(m_fm); + if (m_util.is_numeral(arg1, v)) { + if (m_fm.is_neg(v)) m_fm.neg(v); + result = m_util.mk_value(v); + return BR_DONE; + } + return BR_FAILED; } @@ -313,10 +433,10 @@ br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm()); + scoped_mpf v2(m_fm), v3(m_fm), v4(m_fm); if (m_util.is_numeral(arg2, v2) && m_util.is_numeral(arg3, v3) && m_util.is_numeral(arg4, v4)) { - scoped_mpf t(m_util.fm()); - m_util.fm().fused_mul_add(rm, v2, v3, v4, t); + scoped_mpf t(m_fm); + m_fm.fused_mul_add(rm, v2, v3, v4, t); result = m_util.mk_value(t); return BR_DONE; } @@ -328,10 +448,10 @@ br_status fpa_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()); + scoped_mpf v2(m_fm); if (m_util.is_numeral(arg2, v2)) { - scoped_mpf t(m_util.fm()); - m_util.fm().sqrt(rm, v2, t); + scoped_mpf t(m_fm); + m_fm.sqrt(rm, v2, t); result = m_util.mk_value(t); return BR_DONE; } @@ -343,10 +463,10 @@ br_status fpa_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) { br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_numeral(arg1, rm)) { - scoped_mpf v2(m_util.fm()); + scoped_mpf v2(m_fm); if (m_util.is_numeral(arg2, v2)) { - scoped_mpf t(m_util.fm()); - m_util.fm().round_to_integral(rm, v2, t); + scoped_mpf t(m_fm); + m_fm.round_to_integral(rm, v2, t); result = m_util.mk_value(t); return BR_DONE; } @@ -357,9 +477,9 @@ br_status fpa_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) { // This the floating point theory == br_status fpa_rewriter::mk_float_eq(expr * arg1, expr * arg2, expr_ref & result) { - scoped_mpf v1(m_util.fm()), v2(m_util.fm()); + scoped_mpf v1(m_fm), v2(m_fm); if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { - result = (m_util.fm().eq(v1, v2)) ? m().mk_true() : m().mk_false(); + result = (m_fm.eq(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -402,9 +522,9 @@ br_status fpa_rewriter::mk_lt(expr * arg1, expr * arg2, expr_ref & result) { return BR_REWRITE3; } - scoped_mpf v1(m_util.fm()), v2(m_util.fm()); + scoped_mpf v1(m_fm), v2(m_fm); if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { - result = (m_util.fm().lt(v1, v2)) ? m().mk_true() : m().mk_false(); + result = (m_fm.lt(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -422,9 +542,10 @@ br_status fpa_rewriter::mk_le(expr * arg1, expr * arg2, expr_ref & result) { result = m().mk_false(); return BR_DONE; } - scoped_mpf v1(m_util.fm()), v2(m_util.fm()); + + scoped_mpf v1(m_fm), v2(m_fm); if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { - result = (m_util.fm().le(v1, v2)) ? m().mk_true() : m().mk_false(); + result = (m_fm.le(v1, v2)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -437,9 +558,9 @@ br_status fpa_rewriter::mk_ge(expr * arg1, expr * arg2, expr_ref & result) { } br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_zero(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_zero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -447,9 +568,9 @@ br_status fpa_rewriter::mk_is_zero(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_nzero(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_nzero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -457,9 +578,9 @@ br_status fpa_rewriter::mk_is_nzero(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_pzero(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_pzero(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -467,9 +588,9 @@ br_status fpa_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_nan(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -477,9 +598,9 @@ br_status fpa_rewriter::mk_is_nan(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_inf(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -487,9 +608,9 @@ br_status fpa_rewriter::mk_is_inf(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_normal(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -497,9 +618,9 @@ br_status fpa_rewriter::mk_is_normal(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_denormal(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -507,9 +628,9 @@ br_status fpa_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false(); + result = (m_fm.is_neg(v)) ? m().mk_true() : m().mk_false(); return BR_DONE; } @@ -517,9 +638,9 @@ br_status fpa_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { - scoped_mpf v(m_util.fm()); + scoped_mpf v(m_fm); if (m_util.is_numeral(arg1, v)) { - result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true(); + result = (m_fm.is_neg(v) || m_fm.is_nan(v)) ? m().mk_false() : m().mk_true(); return BR_DONE; } @@ -529,7 +650,7 @@ br_status fpa_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { // This the SMT = br_status fpa_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { - scoped_mpf v1(m_util.fm()), v2(m_util.fm()); + scoped_mpf v1(m_fm), v2(m_fm); if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) { // Note: == is the floats-equality, here we need normal equality. result = (m_fm.is_nan(v1) && m_fm.is_nan(v2)) ? m().mk_true() : @@ -547,21 +668,24 @@ br_status fpa_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) { } br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { + unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); bv_util bu(m()); rational r1, r2, r3; - unsigned bvs1, bvs2, bvs3; + unsigned bvs1, bvs2, bvs3; - if (bu.is_numeral(arg1, r1, bvs1) && bu.is_numeral(arg2, r2, bvs2) && bu.is_numeral(arg3, r3, bvs3)) { - SASSERT(m_util.fm().mpz_manager().is_one(r2.to_mpq().denominator())); - SASSERT(m_util.fm().mpz_manager().is_one(r3.to_mpq().denominator())); - SASSERT(m_util.fm().mpz_manager().is_int64(r3.to_mpq().numerator())); - scoped_mpf v(m_util.fm()); - mpf_exp_t biased_exp = m_util.fm().mpz_manager().get_int64(r2.to_mpq().numerator()); - m_util.fm().set(v, bvs2, bvs3 + 1, + if (bu.is_numeral(arg1, r1, bvs1) && + bu.is_numeral(arg2, r2, bvs2) && + bu.is_numeral(arg3, r3, bvs3)) { + SASSERT(mpzm.is_one(r2.to_mpq().denominator())); + SASSERT(mpzm.is_one(r3.to_mpq().denominator())); + SASSERT(mpzm.is_int64(r3.to_mpq().numerator())); + scoped_mpf v(m_fm); + mpf_exp_t biased_exp = mpzm.get_int64(r2.to_mpq().numerator()); + m_fm.set(v, bvs2, bvs3 + 1, r1.is_one(), r3.to_mpq().numerator(), - m_util.fm().unbias_exp(bvs2, biased_exp)); - TRACE("fp_rewriter", tout << "simplified (fp ...) to " << m_util.fm().to_string(v) << std::endl;); + m_fm.unbias_exp(bvs2, biased_exp)); + TRACE("fp_rewriter", tout << "simplified (fp ...) to " << m_fm.to_string(v) << std::endl;); result = m_util.mk_value(v); return BR_DONE; } @@ -569,24 +693,68 @@ br_status fpa_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & return BR_FAILED; } -br_status fpa_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) { + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + int bv_sz = f->get_parameter(0).get_int(); + mpf_rounding_mode rmv; + scoped_mpf v(m_fm); + + if (m_util.is_rm_numeral(arg1, rmv) && + m_util.is_numeral(arg2, v)) { + + if (m_fm.is_nan(v) || m_fm.is_inf(v) || m_fm.is_neg(v)) { + result = m_util.mk_internal_to_ubv_unspecified(bv_sz); + return BR_REWRITE_FULL; + } + + bv_util bu(m()); + scoped_mpq q(m_fm.mpq_manager()); + m_fm.to_sbv_mpq(rmv, v, q); + rational r(q); + result = bu.mk_numeral(r, bv_sz); + return BR_DONE; + } + return BR_FAILED; } -br_status fpa_rewriter::mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result) { +br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) { + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + int bv_sz = f->get_parameter(0).get_int(); + mpf_rounding_mode rmv; + scoped_mpf v(m_fm); + + if (m_util.is_rm_numeral(arg1, rmv) && + m_util.is_numeral(arg2, v)) { + + if (m_fm.is_nan(v) || m_fm.is_inf(v)) { + result = m_util.mk_internal_to_sbv_unspecified(bv_sz); + return BR_REWRITE_FULL; + } + + bv_util bu(m()); + scoped_mpq q(m_fm.mpq_manager()); + m_fm.to_sbv_mpq(rmv, v, q); + rational r(q); + result = bu.mk_numeral(r, bv_sz); + return BR_DONE; + } + return BR_FAILED; } -br_status fpa_rewriter::mk_to_real(expr * arg1, expr_ref & result) { - scoped_mpf fv(m_util.fm()); +br_status fpa_rewriter::mk_to_real(expr * arg, expr_ref & result) { + scoped_mpf v(m_fm); - if (m_util.is_numeral(arg1, fv)) { - if (m_fm.is_nan(fv) || m_fm.is_inf(fv)) { + if (m_util.is_numeral(arg, v)) { + if (m_fm.is_nan(v) || m_fm.is_inf(v)) { result = m_util.mk_internal_to_real_unspecified(); } else { scoped_mpq r(m_fm.mpq_manager()); - m_fm.to_rational(fv, r); + m_fm.to_rational(v, r); result = m_util.au().mk_numeral(r.get(), false); } return BR_DONE; diff --git a/src/ast/rewriter/fpa_rewriter.h b/src/ast/rewriter/fpa_rewriter.h index a10df95ca..2c76fad6a 100644 --- a/src/ast/rewriter/fpa_rewriter.h +++ b/src/ast/rewriter/fpa_rewriter.h @@ -27,7 +27,8 @@ Notes: class fpa_rewriter { fpa_util m_util; - mpf_manager m_fm; + mpf_manager & m_fm; + bool m_hi_fp_unspecified; app * mk_eq_nan(expr * arg); app * mk_neq_nan(expr * arg); @@ -44,7 +45,7 @@ public: br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_eq_core(expr * arg1, expr * arg2, expr_ref & result); - + br_status mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); @@ -75,12 +76,16 @@ public: br_status mk_to_ieee_bv(expr * arg1, expr_ref & result); br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); - br_status mk_to_fp_unsigned(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); + br_status mk_to_fp_unsigned(func_decl * f, expr * arg1, expr * arg2, expr_ref & result); br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_to_sbv(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_to_real(expr * arg1, expr_ref & result); + br_status mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result); + br_status mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ref & result); + br_status mk_to_real(expr * arg, expr_ref & result); + + br_status mk_to_ubv_unspecified(func_decl * f, expr_ref & result); + br_status mk_to_sbv_unspecified(func_decl * f, expr_ref & result); + br_status mk_to_real_unspecified(expr_ref & result); }; #endif diff --git a/src/ast/rewriter/fpa_rewriter_params.pyg b/src/ast/rewriter/fpa_rewriter_params.pyg new file mode 100644 index 000000000..85973e744 --- /dev/null +++ b/src/ast/rewriter/fpa_rewriter_params.pyg @@ -0,0 +1,5 @@ +def_module_params(module_name='rewriter', + class_name='fpa_rewriter_params', + export=True, + params=(("hi_fp_unspecified", BOOL, True, "use the 'hardware interpretation' for unspecified values in fp.to_ubv, fp.to_sbv, and fp.to_real"), +)) diff --git a/src/ast/simplifier/fpa_simplifier_plugin.h b/src/ast/simplifier/fpa_simplifier_plugin.h index 13a235091..08fa6c49b 100644 --- a/src/ast/simplifier/fpa_simplifier_plugin.h +++ b/src/ast/simplifier/fpa_simplifier_plugin.h @@ -22,8 +22,8 @@ Author: #include"fpa_rewriter.h" class fpa_simplifier_plugin : public simplifier_plugin { - fpa_util m_util; - fpa_rewriter m_rw; + fpa_util m_util; + fpa_rewriter m_rw; public: fpa_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b); diff --git a/src/tactic/fpa/qffp_tactic.cpp b/src/tactic/fpa/qffp_tactic.cpp index 6b081f0a5..c45898cc7 100644 --- a/src/tactic/fpa/qffp_tactic.cpp +++ b/src/tactic/fpa/qffp_tactic.cpp @@ -89,6 +89,8 @@ public: virtual result operator()(goal const & g) { return !test(g); } + + virtual ~is_qffp_probe() {} }; probe * mk_is_qffp_probe() { diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index de4107746..323ffa3af 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1098,6 +1098,46 @@ void mpf_manager::to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o) { zm.mul2k(o, e); } +void mpf_manager::to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o) { + SASSERT(!is_nan(x) && !is_inf(x)); + + scoped_mpf t(*this); + scoped_mpz z(m_mpz_manager); + + set(t, x); + unpack(t, true); + + SASSERT(t.exponent() < INT_MAX); + + m_mpz_manager.set(z, t.significand()); + if (t.sign()) m_mpz_manager.neg(z); + mpf_exp_t e = (mpf_exp_t)t.exponent() - t.sbits() + 1; + if (e < 0) { + bool last = false, round = false, guard = false, sticky = m_mpz_manager.is_odd(z); + for (; e != 0; e++) { + m_mpz_manager.machine_div2k(z, 1); + sticky |= guard; + guard = round; + round = last; + last = m_mpz_manager.is_odd(z); + } + bool inc = false; + switch (rm) { + case MPF_ROUND_NEAREST_TEVEN: inc = round && (last || sticky); break; + case MPF_ROUND_NEAREST_TAWAY: inc = round && (!last || sticky); break; // CMW: Check! + case MPF_ROUND_TOWARD_POSITIVE: inc = (!m_mpz_manager.is_neg(z) && (round || sticky)); break; + case MPF_ROUND_TOWARD_NEGATIVE: inc = (m_mpz_manager.is_neg(z) && (round || sticky)); break; + case MPF_ROUND_TOWARD_ZERO: inc = false; break; + default: UNREACHABLE(); + } + if (inc) m_mpz_manager.inc(z); + } + else + m_mpz_manager.mul2k(z, (unsigned) e); + + m_mpq_manager.set(o, z); +} + void mpf_manager::rem(mpf const & x, mpf const & y, mpf & o) { SASSERT(x.sbits == y.sbits && x.ebits == y.ebits); @@ -1662,7 +1702,8 @@ void mpf_manager::round(mpf_rounding_mode rm, mpf & o) { bool inc = false; switch (rm) { case MPF_ROUND_NEAREST_TEVEN: inc = round && (last || sticky); break; - case MPF_ROUND_NEAREST_TAWAY: inc = round; break; // CMW: Check this. + // case MPF_ROUND_NEAREST_TAWAY: inc = round; break; // CMW: Check + case MPF_ROUND_NEAREST_TAWAY: inc = round && (!last || sticky); break; // CMW: Fix ok? case MPF_ROUND_TOWARD_POSITIVE: inc = (!o.sign && (round || sticky)); break; case MPF_ROUND_TOWARD_NEGATIVE: inc = (o.sign && (round || sticky)); break; case MPF_ROUND_TOWARD_ZERO: inc = false; break; diff --git a/src/util/mpf.h b/src/util/mpf.h index 39eb7330e..bac502c58 100644 --- a/src/util/mpf.h +++ b/src/util/mpf.h @@ -206,6 +206,8 @@ public: */ unsigned prev_power_of_two(mpf const & a); + void to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o); + protected: bool has_bot_exp(mpf const & x); bool has_top_exp(mpf const & x); @@ -218,8 +220,8 @@ protected: void mk_round_inf(mpf_rounding_mode rm, mpf & o); // Convert x into a mpz numeral. zm is the manager that owns o. - void to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o); - void to_mpz(mpf const & x, scoped_mpz & o) { to_mpz(x, o.m(), o); } + void to_mpz(mpf const & x, unsynch_mpz_manager & zm, mpz & o); + void to_mpz(mpf const & x, scoped_mpz & o) { to_mpz(x, o.m(), o); } class powers2 { unsynch_mpz_manager & m; From 941d1063dd13d9a0c44d62e23dc5eaa584211ef8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 6 Feb 2015 18:48:14 +0000 Subject: [PATCH 545/646] FPA rewriter and MPF bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/ast/rewriter/fpa_rewriter.cpp | 50 +++++++++++++++++----- src/util/mpf.cpp | 69 ++++--------------------------- 2 files changed, 48 insertions(+), 71 deletions(-) diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index 394c2f117..291712805 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -100,6 +100,11 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED: SASSERT(num_args == 0); st = mk_to_real_unspecified(result); break; + case OP_FPA_INTERNAL_BVWRAP: + case OP_FPA_INTERNAL_BVUNWRAP: + st = BR_FAILED; + break; + default: NOT_IMPLEMENTED_YET(); } @@ -183,8 +188,15 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const SASSERT(mpzm.is_int64(exp)); mpf_exp_t mpf_exp = mpzm.get_int64(exp); + mpf_exp = m_fm.unbias_exp(ebits, mpf_exp); m_fm.set(v, ebits, sbits, !mpzm.is_zero(z), sig, mpf_exp); + TRACE("fp_rewriter", + tout << "sgn: " << !mpzm.is_zero(z) << std::endl; + tout << "sig: " << mpzm.to_string(sig) << std::endl; + tout << "exp: " << mpf_exp << std::endl; + tout << "v: " << m_fm.to_string(v) << std::endl;); + result = m_util.mk_value(v); return BR_DONE; } @@ -198,22 +210,24 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const TRACE("fp_rewriter", tout << "r: " << r1 << std::endl;); scoped_mpf v(m_fm); m_fm.set(v, ebits, sbits, rmv, r1.to_mpq()); - result = m_util.mk_value(v); + result = m_util.mk_value(v); // TRACE("fp_rewriter", tout << "result: " << result << std::endl; ); return BR_DONE; } else if (m_util.is_numeral(args[1], v)) { // rm + float -> float TRACE("fp_rewriter", tout << "v: " << m_fm.to_string(v) << std::endl; ); - scoped_mpf v(m_fm); - m_fm.set(v, ebits, sbits, rmv, v); - result = m_util.mk_value(v); + scoped_mpf vf(m_fm); + m_fm.set(vf, ebits, sbits, rmv, v); + result = m_util.mk_value(vf); // TRACE("fp_rewriter", tout << "result: " << result << std::endl; ); return BR_DONE; } - else if (bu.is_numeral(args[1], r1, bvs1)) { + else if (bu.is_numeral(args[1], r1, bvs1)) { // rm + signed bv -> float - scoped_mpf v(m_fm); + TRACE("fp_rewriter", tout << "r1: " << r1 << std::endl;); + r1 = bu.norm(r1, bvs1, true); + TRACE("fp_rewriter", tout << "r1 norm: " << r1 << std::endl;); m_fm.set(v, ebits, sbits, rmv, r1.to_mpq()); result = m_util.mk_value(v); return BR_DONE; @@ -229,8 +243,7 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const !m_util.au().is_numeral(args[2], r2)) return BR_FAILED; - TRACE("fp_rewriter", tout << "r1: " << r1 << ", r2: " << r2 << "\n";); - scoped_mpf v(m_fm); + TRACE("fp_rewriter", tout << "r1: " << r1 << ", r2: " << r2 << "\n";); m_fm.set(v, ebits, sbits, rmv, r1.to_mpq(), r2.to_mpq().numerator()); result = m_util.mk_value(v); return BR_DONE; @@ -242,7 +255,6 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const SASSERT(m_fm.mpz_manager().is_one(r2.to_mpq().denominator())); SASSERT(m_fm.mpz_manager().is_one(r3.to_mpq().denominator())); SASSERT(m_fm.mpz_manager().is_int64(r3.to_mpq().numerator())); - scoped_mpf v(m_fm); mpf_exp_t biased_exp = m_fm.mpz_manager().get_int64(r2.to_mpq().numerator()); m_fm.set(v, bvs2, bvs3 + 1, r1.is_one(), @@ -711,8 +723,16 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ bv_util bu(m()); scoped_mpq q(m_fm.mpq_manager()); m_fm.to_sbv_mpq(rmv, v, q); + rational r(q); - result = bu.mk_numeral(r, bv_sz); + unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); + rational ul, ll; + ul = m_fm.m_powers2.m1(bv_sz); + ll = rational(0); + if (r >= ll && r <= ul) + result = bu.mk_numeral(r, bv_sz); + else + result = m_util.mk_internal_to_ubv_unspecified(bv_sz); return BR_DONE; } @@ -737,8 +757,16 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ bv_util bu(m()); scoped_mpq q(m_fm.mpq_manager()); m_fm.to_sbv_mpq(rmv, v, q); + rational r(q); - result = bu.mk_numeral(r, bv_sz); + unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); + rational ul, ll; + ul = m_fm.m_powers2.m1(bv_sz - 1); + ll = - m_fm.m_powers2(bv_sz - 1); + if (r >= ll && r <= ul) + result = bu.mk_numeral(r, bv_sz); + else + result = m_util.mk_internal_to_sbv_unspecified(bv_sz); return BR_DONE; } diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 323ffa3af..4e452b1e8 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -190,59 +190,9 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, float value) { void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, mpf_rounding_mode rm, mpq const & value) { TRACE("mpf_dbg", tout << "set: " << m_mpq_manager.to_string(value) << " [" << ebits << "/" << sbits << "]"<< std::endl;); - - if (m_mpq_manager.is_zero(value)) - mk_pzero(ebits, sbits, o); - else { - o.ebits = ebits; - o.sbits = sbits; - o.sign = m_mpq_manager.is_neg(value); - - scoped_mpq x(m_mpq_manager); - m_mpq_manager.set(x, value); - m_mpq_manager.abs(x); - - m_mpz_manager.set(o.significand, 0); - - scoped_mpq v(m_mpq_manager); - m_mpq_manager.set(v, x); - o.exponent = 0; - - // Normalize - while (m_mpq_manager.ge(v, mpq(2))) - { - m_mpq_manager.div(v, mpq(2), v); - o.exponent++; - } - - while (m_mpq_manager.lt(v, mpq(1))) - { - m_mpq_manager.mul(v, mpq(2), v); - o.exponent--; - } - - m_mpz_manager.set(o.significand, 0); - SASSERT(m_mpq_manager.lt(v, mpq(2))); - SASSERT(m_mpq_manager.ge(v, mpq(1))); - - // 1.0 <= v < 2.0 (* 2^o.exponent) - // (and v != 0.0) - for (unsigned i = 0; i < sbits + 3 ; i++) - { - m_mpz_manager.mul2k(o.significand, 1); - if (m_mpq_manager.ge(v, mpq(1))) { - m_mpz_manager.inc(o.significand); - m_mpq_manager.dec(v); // v := v - 1.0 - } - m_mpq_manager.mul(mpq(2), v, v); // v := 2.0 * v - } - - TRACE("mpf_dbg", tout << "rnd sig=" << m_mpz_manager.to_string(o.significand) << - " exp=" << o.exponent << std::endl;); - - round(rm, o); - } - + scoped_mpz exp(m_mpz_manager); + m_mpz_manager.set(exp, 0); + set(o, ebits, sbits, rm, value, exp); TRACE("mpf_dbg", tout << "set: res = " << to_string(o) << std::endl;); } @@ -1109,15 +1059,13 @@ void mpf_manager::to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o SASSERT(t.exponent() < INT_MAX); - m_mpz_manager.set(z, t.significand()); - if (t.sign()) m_mpz_manager.neg(z); + m_mpz_manager.set(z, t.significand()); mpf_exp_t e = (mpf_exp_t)t.exponent() - t.sbits() + 1; if (e < 0) { - bool last = false, round = false, guard = false, sticky = m_mpz_manager.is_odd(z); + bool last = false, round = false, sticky = m_mpz_manager.is_odd(z); for (; e != 0; e++) { m_mpz_manager.machine_div2k(z, 1); - sticky |= guard; - guard = round; + sticky |= round; round = last; last = m_mpz_manager.is_odd(z); } @@ -1125,8 +1073,8 @@ void mpf_manager::to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o switch (rm) { case MPF_ROUND_NEAREST_TEVEN: inc = round && (last || sticky); break; case MPF_ROUND_NEAREST_TAWAY: inc = round && (!last || sticky); break; // CMW: Check! - case MPF_ROUND_TOWARD_POSITIVE: inc = (!m_mpz_manager.is_neg(z) && (round || sticky)); break; - case MPF_ROUND_TOWARD_NEGATIVE: inc = (m_mpz_manager.is_neg(z) && (round || sticky)); break; + case MPF_ROUND_TOWARD_POSITIVE: inc = (!x.sign && (round || sticky)); break; + case MPF_ROUND_TOWARD_NEGATIVE: inc = (x.sign && (round || sticky)); break; case MPF_ROUND_TOWARD_ZERO: inc = false; break; default: UNREACHABLE(); } @@ -1136,6 +1084,7 @@ void mpf_manager::to_sbv_mpq(mpf_rounding_mode rm, const mpf & x, scoped_mpq & o m_mpz_manager.mul2k(z, (unsigned) e); m_mpq_manager.set(o, z); + if (x.sign) m_mpq_manager.neg(o); } void mpf_manager::rem(mpf const & x, mpf const & y, mpf & o) { From b96551a1a25e6ec810ff9dfa261dd335852c143d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 7 Feb 2015 14:17:39 +0000 Subject: [PATCH 546/646] .NET/Java/ML: Moved toggle_warning_messages to Global, added en/disable_trace. Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 4 ++-- examples/java/JavaExample.java | 4 ++-- src/api/dotnet/Context.cs | 12 +---------- src/api/dotnet/Global.cs | 36 +++++++++++++++++++++++++++++++- src/api/java/Context.java | 12 ----------- src/api/java/Global.java | 38 +++++++++++++++++++++++++++++++--- src/api/ml/z3.ml | 9 +++++++- src/api/ml/z3.mli | 16 +++++++++++++- 8 files changed, 98 insertions(+), 33 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 0c33d6793..0847bc868 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -1041,7 +1041,7 @@ namespace test_mapi { Console.WriteLine("LogicTest"); - Context.ToggleWarningMessages(true); + Microsoft.Z3.Global.ToggleWarningMessages(true); BitVecSort bvs = ctx.MkBitVecSort(32); Expr x = ctx.MkConst("x", bvs); @@ -2110,7 +2110,7 @@ namespace test_mapi { try { - Context.ToggleWarningMessages(true); + Microsoft.Z3.Global.ToggleWarningMessages(true); Log.Open("test.log"); Console.Write("Z3 Major Version: "); diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 64e4015e0..d23f249de 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -1101,7 +1101,7 @@ class JavaExample System.out.println("LogicTest"); Log.append("LogicTest"); - Context.ToggleWarningMessages(true); + com.microsoft.z3.Global.ToggleWarningMessages(true); BitVecSort bvs = ctx.mkBitVecSort(32); Expr x = ctx.mkConst("x", bvs); @@ -2242,7 +2242,7 @@ class JavaExample JavaExample p = new JavaExample(); try { - Context.ToggleWarningMessages(true); + com.microsoft.z3.Global.ToggleWarningMessages(true); Log.open("test.log"); System.out.print("Z3 Major Version: "); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index d14c591aa..917b0a954 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -4287,17 +4287,7 @@ namespace Microsoft.Z3 public ParamDescrs SimplifyParameterDescriptions { get { return new ParamDescrs(this, Native.Z3_simplify_get_param_descrs(nCtx)); } - } - - /// - /// Enable/disable printing of warning messages to the console. - /// - /// Note that this function is static and effects the behaviour of - /// all contexts globally. - public static void ToggleWarningMessages(bool enabled) - { - Native.Z3_toggle_warning_messages((enabled) ? 1 : 0); - } + } #endregion #region Error Handling diff --git a/src/api/dotnet/Global.cs b/src/api/dotnet/Global.cs index 787c9b788..acf3fab32 100644 --- a/src/api/dotnet/Global.cs +++ b/src/api/dotnet/Global.cs @@ -82,6 +82,40 @@ namespace Microsoft.Z3 public static void ResetParameters() { Native.Z3_global_param_reset_all(); - } + } + + /// + /// Enable/disable printing of warning messages to the console. + /// + /// Note that this function is static and effects the behaviour of + /// all contexts globally. + public static void ToggleWarningMessages(bool enabled) + { + Native.Z3_toggle_warning_messages((enabled) ? 1 : 0); + } + + /// + /// Enable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + /// + /// + /// It is a NOOP otherwise. + /// + /// trace tag + public static void EnableTrace(string tag) + { + Native.Z3_enable_trace(tag); + } + + /// + /// Disable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + /// + /// + /// It is a NOOP otherwise. + /// + /// trace tag + public static void DisableTrace(string tag) + { + Native.Z3_disable_trace(tag); + } } } diff --git a/src/api/java/Context.java b/src/api/java/Context.java index e9dd42dc0..ce7cef5c2 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3607,18 +3607,6 @@ public class Context extends IDisposable return new ParamDescrs(this, Native.simplifyGetParamDescrs(nCtx())); } - /** - * Enable/disable printing of warning messages to the console. - * Remarks: Note - * that this function is static and effects the behaviour of all contexts - * globally. - **/ - public static void ToggleWarningMessages(boolean enabled) - throws Z3Exception - { - Native.toggleWarningMessages((enabled) ? true : false); - } - /** * Update a mutable configuration parameter. * Remarks: The list of all diff --git a/src/api/java/Global.java b/src/api/java/Global.java index 44fb4cac7..65bae9a01 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -44,7 +44,7 @@ public final class Global **/ public static void setParameter(String id, String value) { - Native.globalParamSet(id, value); + Native.globalParamSet(id, value); } /** @@ -71,6 +71,38 @@ public final class Global **/ public static void resetParameters() { - Native.globalParamResetAll(); - } + Native.globalParamResetAll(); + } + + /** + * Enable/disable printing of warning messages to the console. + * Remarks: Note + * that this function is static and effects the behaviour of all contexts + * globally. + **/ + public static void ToggleWarningMessages(boolean enabled) + throws Z3Exception + { + Native.toggleWarningMessages((enabled) ? true : false); + } + + /** + * Enable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + * + * Remarks: It is a NOOP otherwise. + **/ + public static void enableTrace(String tag) + { + Native.enableTrace(tag); + } + + /** + * Disable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + * + * Remarks: It is a NOOP otherwise. + **/ + public static void disableTrace(String tag) + { + Native.disableTrace(tag); + } } diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index fe78b65a6..d8cf21cda 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -2943,5 +2943,12 @@ let get_global_param ( id : string ) = let global_param_reset_all = Z3native.global_param_reset_all -let toggle_warning_messages ( enabled: bool ) = +let toggle_warning_messages ( enabled : bool ) = Z3native.toggle_warning_messages enabled + +let enable_trace ( tag : string ) = + (Z3native.enable_trace tag) + +let disable_trace ( tag : string ) = + (Z3native.enable_trace tag) + diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index aa526417e..e223008bb 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -3328,4 +3328,18 @@ val global_param_reset_all : unit -> unit Note that this function is static and effects the behaviour of all contexts globally. *) val toggle_warning_messages : bool -> unit - + +(** + Enable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + + Remarks: It is a NOOP otherwise. +*) +val enable_trace : string -> unit + +(** + Disable tracing messages tagged as `tag' when Z3 is compiled in debug mode. + + Remarks: It is a NOOP otherwise. +*) +val disable_trace : string -> unit + From 359c7e4da980cc7349a395c50da99d9a89e09eb2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 7 Feb 2015 14:47:26 +0000 Subject: [PATCH 547/646] Removed unnecessary variables and added initialization to others to silence warnings. Signed-off-by: Christoph M. Wintersteiger --- src/ast/ast.cpp | 2 +- src/ast/fpa_decl_plugin.cpp | 2 +- src/ast/rewriter/fpa_rewriter.cpp | 6 ++---- src/nlsat/nlsat_explain.cpp | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index b134d38cb..6780145d9 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1662,7 +1662,7 @@ ast * ast_manager::register_node_core(ast * n) { for (unsigned i = 0; i < num_args; i++) { expr * arg = t->get_arg(i); inc_ref(arg); - unsigned arg_depth; + unsigned arg_depth = 0; switch (arg->get_kind()) { case AST_APP: { app_flags * arg_flags = to_app(arg)->flags(); diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 8cf158604..bd2676ee4 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -252,7 +252,7 @@ func_decl * fpa_decl_plugin::mk_rm_const_decl(decl_kind k, unsigned num_paramete func_decl * fpa_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { - sort * s; + sort * s = 0; if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast()) && is_float_sort(to_sort(parameters[0].get_ast()))) { s = to_sort(parameters[0].get_ast()); } diff --git a/src/ast/rewriter/fpa_rewriter.cpp b/src/ast/rewriter/fpa_rewriter.cpp index 291712805..6aee683ff 100644 --- a/src/ast/rewriter/fpa_rewriter.cpp +++ b/src/ast/rewriter/fpa_rewriter.cpp @@ -724,8 +724,7 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_ scoped_mpq q(m_fm.mpq_manager()); m_fm.to_sbv_mpq(rmv, v, q); - rational r(q); - unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); + rational r(q); rational ul, ll; ul = m_fm.m_powers2.m1(bv_sz); ll = rational(0); @@ -758,8 +757,7 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_ scoped_mpq q(m_fm.mpq_manager()); m_fm.to_sbv_mpq(rmv, v, q); - rational r(q); - unsynch_mpz_manager & mpzm = m_fm.mpz_manager(); + rational r(q); rational ul, ll; ul = m_fm.m_powers2.m1(bv_sz - 1); ll = - m_fm.m_powers2(bv_sz - 1); diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index 50466c276..4b87f9e65 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -700,7 +700,7 @@ namespace nlsat { void add_root_literal(atom::kind k, var y, unsigned i, poly * p) { scoped_mpz c(m_pm.m()); bool_var b; - bool lsign; + bool lsign = false; if (m_pm.degree(p, y) == 1 && m_pm.const_coeff(p, y, 1, c)) { SASSERT(!m_pm.m().is_zero(c)); // literal can be expressed using a linear ineq_atom From 778dd997d37b1547b7a11f45596fe9accde3409e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 7 Feb 2015 18:05:52 +0000 Subject: [PATCH 548/646] formatting (tabs) Signed-off-by: Christoph M. Wintersteiger --- src/util/buffer.h | 88 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/util/buffer.h b/src/util/buffer.h index 55ab43ec3..ee2fbbc65 100644 --- a/src/util/buffer.h +++ b/src/util/buffer.h @@ -31,18 +31,18 @@ protected: char m_initial_buffer[INITIAL_SIZE * sizeof(T)]; void free_memory() { - if (m_buffer != reinterpret_cast(m_initial_buffer)) { - memory::deallocate(m_buffer); - } + if (m_buffer != reinterpret_cast(m_initial_buffer)) { + memory::deallocate(m_buffer); + } } void expand() { - unsigned new_capacity = m_capacity << 1; - T * new_buffer = reinterpret_cast(memory::allocate(sizeof(T) * new_capacity)); - memcpy(new_buffer, m_buffer, m_pos * sizeof(T)); - free_memory(); - m_buffer = new_buffer; - m_capacity = new_capacity; + unsigned new_capacity = m_capacity << 1; + T * new_buffer = reinterpret_cast(memory::allocate(sizeof(T) * new_capacity)); + memcpy(new_buffer, m_buffer, m_pos * sizeof(T)); + free_memory(); + m_buffer = new_buffer; + m_capacity = new_capacity; } void destroy_elements() { @@ -50,14 +50,14 @@ protected: iterator e = end(); for (; it != e; ++it) { it->~T(); - } + } } void destroy() { - if (CallDestructors) { - destroy_elements(); - } - free_memory(); + if (CallDestructors) { + destroy_elements(); + } + free_memory(); } public: @@ -66,15 +66,15 @@ public: typedef const T * const_iterator; buffer(): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { } buffer(const buffer & source): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { unsigned sz = source.size(); for(unsigned i = 0; i < sz; i++) { push_back(source.m_buffer[i]); @@ -82,9 +82,9 @@ public: } buffer(unsigned sz, const T & elem): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { for (unsigned i = 0; i < sz; i++) { push_back(elem); } @@ -96,10 +96,10 @@ public: } void reset() { - if (CallDestructors) { - destroy_elements(); - } - m_pos = 0; + if (CallDestructors) { + destroy_elements(); + } + m_pos = 0; } void finalize() { @@ -110,11 +110,11 @@ public: } unsigned size() const { - return m_pos; + return m_pos; } bool empty() const { - return m_pos == 0; + return m_pos == 0; } iterator begin() { @@ -126,13 +126,13 @@ public: } void set_end(iterator it) { - m_pos = static_cast(it - m_buffer); - if (CallDestructors) { - iterator e = end(); - for (; it != e; ++it) { - it->~T(); - } - } + m_pos = static_cast(it - m_buffer); + if (CallDestructors) { + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } } const_iterator begin() const { @@ -144,33 +144,33 @@ public: } void push_back(const T & elem) { - if (m_pos >= m_capacity) - expand(); - new (m_buffer + m_pos) T(elem); - m_pos++; + if (m_pos >= m_capacity) + expand(); + new (m_buffer + m_pos) T(elem); + m_pos++; } void pop_back() { if (CallDestructors) { back().~T(); - } + } m_pos--; } const T & back() const { SASSERT(!empty()); - SASSERT(m_pos > 0); + SASSERT(m_pos > 0); return m_buffer[m_pos - 1]; } T & back() { SASSERT(!empty()); - SASSERT(m_pos > 0); + SASSERT(m_pos > 0); return m_buffer[m_pos - 1]; } T * c_ptr() const { - return m_buffer; + return m_buffer; } void append(unsigned n, T const * elems) { From da01f237fd298deac36b13813bce2308f1995bf5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 7 Feb 2015 18:06:13 +0000 Subject: [PATCH 549/646] fixed memory leaks Signed-off-by: Christoph M. Wintersteiger --- src/tactic/arith/propagate_ineqs_tactic.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tactic/arith/propagate_ineqs_tactic.cpp b/src/tactic/arith/propagate_ineqs_tactic.cpp index d7e4f30d2..977f15167 100644 --- a/src/tactic/arith/propagate_ineqs_tactic.cpp +++ b/src/tactic/arith/propagate_ineqs_tactic.cpp @@ -115,6 +115,7 @@ struct propagate_ineqs_tactic::imp { out << "< oo"; out << "\n"; } + nm.del(k); } a_var mk_var(expr * t) { @@ -234,6 +235,7 @@ struct propagate_ineqs_tactic::imp { SASSERT(k == GE); bp.assert_lower(x, c_prime, strict); } + nm.del(c_prime); return true; } @@ -309,6 +311,8 @@ struct propagate_ineqs_tactic::imp { m_new_goal->assert_expr(m_util.mk_le(p, m_util.mk_numeral(rational(u), m_util.is_int(p)))); } } + nm.del(l); + nm.del(u); } bool is_x_minus_y_eq_0(expr * t, expr * & x, expr * & y) { From 7e579604e19be1a86bcb0e52f50dc38002d00049 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 7 Feb 2015 19:39:15 +0000 Subject: [PATCH 550/646] Eliminated the old MS-Bignum interface because it stood in the way of progress. Signed-off-by: Christoph M. Wintersteiger --- src/util/mpff.cpp | 50 ++++++++++++--------------- src/util/mpff.h | 4 ++- src/util/mpfx.cpp | 26 +++++++------- src/util/mpfx.h | 2 ++ src/util/mpn.cpp | 16 +++++++-- src/util/mpn.h | 88 +++-------------------------------------------- src/util/mpz.cpp | 88 +++++++++++++++++++---------------------------- src/util/mpz.h | 4 ++- 8 files changed, 95 insertions(+), 183 deletions(-) diff --git a/src/util/mpff.cpp b/src/util/mpff.cpp index 7678a051e..b979b32ff 100644 --- a/src/util/mpff.cpp +++ b/src/util/mpff.cpp @@ -700,7 +700,7 @@ void mpff_manager::add_sub(bool is_sub, mpff const & a, mpff const & b, mpff & c c.m_sign = sgn_a; unsigned * sig_r = m_buffers[1].c_ptr(); size_t r_sz; - add_full(sig_a, m_precision, n_sig_b, m_precision, sig_r, m_precision + 1, &r_sz, 0); + m_mpn_manager.add(sig_a, m_precision, n_sig_b, m_precision, sig_r, m_precision + 1, &r_sz); SASSERT(r_sz <= m_precision + 1); unsigned num_leading_zeros = nlz(m_precision + 1, sig_r); SASSERT(num_leading_zeros >= sizeof(unsigned) * 8 - 1); // num_leading_zeros >= 31 @@ -740,11 +740,11 @@ void mpff_manager::add_sub(bool is_sub, mpff const & a, mpff const & b, mpff & c unsigned * sig_c = sig(c); if (::lt(m_precision, sig_a, n_sig_b)) { c.m_sign = sgn_b; - sub_diff(n_sig_b, m_precision, sig_a, m_precision, sig_c, &borrow, 0); + m_mpn_manager.sub(n_sig_b, m_precision, sig_a, m_precision, sig_c, &borrow); } else { c.m_sign = sgn_a; - sub_diff(sig_a, m_precision, n_sig_b, m_precision, sig_c, &borrow, 0); + m_mpn_manager.sub(sig_a, m_precision, n_sig_b, m_precision, sig_c, &borrow); } SASSERT(borrow == 0); unsigned num_leading_zeros = nlz(m_precision, sig_c); @@ -793,7 +793,7 @@ void mpff_manager::mul(mpff const & a, mpff const & b, mpff & c) { int64 exp_c = exp_a + exp_b; // store result in m_buffers[0] unsigned * r = m_buffers[0].c_ptr(); - multiply(sig(a), m_precision, sig(b), m_precision, r, 0); + m_mpn_manager.mul(sig(a), m_precision, sig(b), m_precision, r); // r has 2*m_precision_bits bits unsigned num_leading_zeros = nlz(m_precision*2, r); SASSERT(num_leading_zeros <= m_precision_bits); @@ -864,12 +864,10 @@ void mpff_manager::div(mpff const & a, mpff const & b, mpff & c) { // a is at least 2^(2*m_precision_bits - 1) // Thus the quotient of a/b cannot be zero // Actually, quotient of a/b must be >= 2^(2*m_precision_bits - 1)/(2^m_precision_bits - 1) - divide(_a, 2*m_precision, - sig(b), m_precision, - reciprocal_1_NULL, - q, - r, - 0); + m_mpn_manager.div(_a, 2 * m_precision, + sig(b), m_precision, + q, + r); TRACE("mpff_div", unsigned j = q_sz; while (j > 0) { --j; tout << std::hex << std::setfill('0') << std::setw(2*sizeof(unsigned)) << q[j]; tout << " "; } @@ -1193,7 +1191,7 @@ void mpff_manager::display(std::ostream & out, mpff const & n) const { if (shift > 0) shr(m_precision, u_buffer.c_ptr(), shift, u_buffer.c_ptr()); sbuffer str_buffer(11*m_precision, 0); - out << mp_decimal(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size()); if (exp > 0) { if (exp <= 63) { uint64 _exp = 1; @@ -1225,7 +1223,7 @@ void mpff_manager::display(std::ostream & out, mpff const & n) const { } } -void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned prec, unsigned min_exponent) const { +void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned prec, unsigned min_exponent) { // The result in scientific notation when n.m_exponent >= min_exponent or n.m_exponent <= - min_exponent - m_precision_bits int64 exp = n.m_exponent; if (exp >= min_exponent || exp <= -static_cast(min_exponent) - m_precision_bits || is_int(n)) { @@ -1246,7 +1244,7 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned buffer.push_back(s[i]); shr(buffer.size(), buffer.c_ptr(), shift, buffer.size(), buffer.c_ptr()); sbuffer str_buffer(11*buffer.size(), 0); - out << mp_decimal(buffer.c_ptr(), buffer.size(), str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(buffer.c_ptr(), buffer.size(), str_buffer.begin(), str_buffer.size()); } else { sbuffer buffer1, buffer2; @@ -1274,14 +1272,12 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned out << "0"; } else { - divide(buffer1.c_ptr(), m_precision, - pw_buffer.c_ptr(), num_words, - reciprocal_1_NULL, - buffer3.c_ptr(), - buffer2.c_ptr(), - 0); + m_mpn_manager.div(buffer1.c_ptr(), m_precision, + pw_buffer.c_ptr(), num_words, + buffer3.c_ptr(), + buffer2.c_ptr()); sbuffer str_buffer(11*buffer3.size(), 0); - out << mp_decimal(buffer3.c_ptr(), buffer3.size(), str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(buffer3.c_ptr(), buffer3.size(), str_buffer.begin(), str_buffer.size()); SASSERT(!::is_zero(buffer2.size(), buffer2.c_ptr())); // otherwise n is an integer ::copy(buffer2.size(), buffer2.c_ptr(), buffer1.size(), buffer1.c_ptr()); } @@ -1298,7 +1294,7 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned return; } i = i + 1; - multiply(buffer1.c_ptr(), sz1, &ten, 1, buffer2.c_ptr(), 0); + m_mpn_manager.mul(buffer1.c_ptr(), sz1, &ten, 1, buffer2.c_ptr()); unsigned sz2 = sz1 + 1; while (sz2 > 0 && buffer2[sz2-1] == 0) --sz2; @@ -1310,12 +1306,10 @@ void mpff_manager::display_decimal(std::ostream & out, mpff const & n, unsigned SASSERT(sz1 == 0 || !::is_zero(sz1, buffer1.c_ptr())); } else { - divide(buffer2.c_ptr(), sz2, - pw_buffer.c_ptr(), num_words, - reciprocal_1_NULL, - buffer3.c_ptr(), - buffer1.c_ptr(), - 0); + m_mpn_manager.div(buffer2.c_ptr(), sz2, + pw_buffer.c_ptr(), num_words, + buffer3.c_ptr(), + buffer1.c_ptr()); out << buffer3[0]; sz1 = num_words; while (sz1 > 0 && buffer1[sz1-1] == 0) @@ -1353,7 +1347,7 @@ void mpff_manager::display_smt2(std::ostream & out, mpff const & n, bool decimal out << "(/ "; sbuffer str_buffer(11*m_precision, 0); - out << mp_decimal(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(u_buffer.c_ptr(), m_precision, str_buffer.begin(), str_buffer.size()); if (decimal) out << ".0"; if (exp != 0) { diff --git a/src/util/mpff.h b/src/util/mpff.h index 8d4c853af..ef488c934 100644 --- a/src/util/mpff.h +++ b/src/util/mpff.h @@ -29,6 +29,7 @@ Revision History: #include"z3_exception.h" #include"scoped_numeral.h" #include"scoped_numeral_vector.h" +#include"mpn.h" class mpff_manager; @@ -115,6 +116,7 @@ class mpff_manager { svector m_buffers[MPFF_NUM_BUFFERS]; svector m_set_buffer; mpff m_one; + mpn_manager m_mpn_manager; unsigned * sig(mpff const & n) const { return m_significands.c_ptr() + (n.m_sig_idx * m_precision); } @@ -465,7 +467,7 @@ public: void display_raw(std::ostream & out, mpff const & n) const; void display(std::ostream & out, mpff const & n) const; void display_pp(std::ostream & out, mpff const & n) const { display(out, n); } - void display_decimal(std::ostream & out, mpff const & n, unsigned prec=32, unsigned max_power=128) const; + void display_decimal(std::ostream & out, mpff const & n, unsigned prec=32, unsigned max_power=128); void display_smt2(std::ostream & out, mpff const & n, bool decimal=true) const; std::string to_string(mpff const & a) const; diff --git a/src/util/mpfx.cpp b/src/util/mpfx.cpp index c0b3a1936..c75a43046 100644 --- a/src/util/mpfx.cpp +++ b/src/util/mpfx.cpp @@ -387,12 +387,12 @@ void mpfx_manager::add_sub(bool is_sub, mpfx const & a, mpfx const & b, mpfx & c SASSERT(sgn_a != sgn_b); if (::lt(m_total_sz, w_a, w_b)) { c.m_sign = sgn_b; - sub_diff(w_b, m_total_sz, w_a, m_total_sz, w_c, &borrow, 0); + m_mpn_manager.sub(w_b, m_total_sz, w_a, m_total_sz, w_c, &borrow); SASSERT(!::is_zero(m_total_sz, w_c)); } else { c.m_sign = sgn_a; - sub_diff(w_a, m_total_sz, w_b, m_total_sz, w_c, &borrow, 0); + m_mpn_manager.sub(w_a, m_total_sz, w_b, m_total_sz, w_c, &borrow); if (::is_zero(m_total_sz, w_c)) reset(c); } @@ -423,7 +423,7 @@ void mpfx_manager::mul(mpfx const & a, mpfx const & b, mpfx & c) { allocate_if_needed(c); c.m_sign = a.m_sign ^ b.m_sign; unsigned * r = m_buffer0.c_ptr(); - multiply(words(a), m_total_sz, words(b), m_total_sz, r, 0); + m_mpn_manager.mul(words(a), m_total_sz, words(b), m_total_sz, r); // round result unsigned * _r = r + m_frac_part_sz; if ((c.m_sign == 1) != m_to_plus_inf && !::is_zero(m_frac_part_sz, r)) { @@ -473,12 +473,10 @@ void mpfx_manager::div(mpfx const & a, mpfx const & b, mpfx & c) { unsigned q_sz = a_shft_sz - b_sz + 1; unsigned * w_r = m_buffer2.c_ptr(); unsigned r_sz = b_sz; - divide(w_a_shft, a_shft_sz, - w_b, b_sz, - reciprocal_1_NULL, - w_q, - w_r, - 0); + m_mpn_manager.div(w_a_shft, a_shft_sz, + w_b, b_sz, + w_q, + w_r); for (unsigned i = m_total_sz; i < q_sz; i++) if (w_q[i] != 0) throw overflow_exception(); @@ -769,7 +767,7 @@ void mpfx_manager::display(std::ostream & out, mpfx const & n) const { } sbuffer str_buffer(11*sz, 0); - out << mp_decimal(w, sz, str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(w, sz, str_buffer.begin(), str_buffer.size()); if (!is_int(n)) { SASSERT(shift != UINT_MAX); // reverse effect of shr @@ -796,7 +794,7 @@ void mpfx_manager::display_smt2(std::ostream & out, mpfx const & n) const { out << "(/ "; } sbuffer str_buffer(11*sz, 0); - out << mp_decimal(w, sz, str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(w, sz, str_buffer.begin(), str_buffer.size()); if (!is_int(n)) { out << " "; unsigned * w = m_buffer0.c_ptr(); @@ -804,7 +802,7 @@ void mpfx_manager::display_smt2(std::ostream & out, mpfx const & n) const { w[i] = 0; w[m_frac_part_sz] = 1; sbuffer str_buffer2(11*(m_frac_part_sz+1), 0); - out << mp_decimal(w, m_frac_part_sz+1, str_buffer2.begin(), str_buffer2.size(), 0); + out << m_mpn_manager.to_string(w, m_frac_part_sz + 1, str_buffer2.begin(), str_buffer2.size()); out << ")"; } if (is_neg(n)) @@ -816,7 +814,7 @@ void mpfx_manager::display_decimal(std::ostream & out, mpfx const & n, unsigned out << "-"; unsigned * w = words(n); sbuffer str_buffer(11*m_int_part_sz, 0); - out << mp_decimal(w + m_frac_part_sz, m_int_part_sz, str_buffer.begin(), str_buffer.size(), 0); + out << m_mpn_manager.to_string(w + m_frac_part_sz, m_int_part_sz, str_buffer.begin(), str_buffer.size()); if (!is_int(n)) { out << "."; unsigned * frac = m_buffer0.c_ptr(); @@ -830,7 +828,7 @@ void mpfx_manager::display_decimal(std::ostream & out, mpfx const & n, unsigned out << "?"; return; } - multiply(frac, m_frac_part_sz, &ten, 1, n_frac, 0); + m_mpn_manager.mul(frac, m_frac_part_sz, &ten, 1, n_frac); frac_is_zero = ::is_zero(m_frac_part_sz, n_frac); SASSERT(n_frac[m_frac_part_sz] <= 9); if (!frac_is_zero || n_frac[m_frac_part_sz] != 0) diff --git a/src/util/mpfx.h b/src/util/mpfx.h index b4eeaebe6..f152128d8 100644 --- a/src/util/mpfx.h +++ b/src/util/mpfx.h @@ -25,6 +25,7 @@ Revision History: #include"z3_exception.h" #include"scoped_numeral.h" #include"scoped_numeral_vector.h" +#include"mpn.h" class mpfx_manager; @@ -83,6 +84,7 @@ class mpfx_manager { unsigned_vector m_buffer0, m_buffer1, m_buffer2; unsigned_vector m_tmp_digits; mpfx m_one; + mpn_manager m_mpn_manager; unsigned * words(mpfx const & n) const { return m_words.c_ptr() + (n.m_sig_idx * m_total_sz); } unsigned sz(unsigned * ws) const; diff --git a/src/util/mpn.cpp b/src/util/mpn.cpp index 6a544f583..ba0a8563a 100644 --- a/src/util/mpn.cpp +++ b/src/util/mpn.cpp @@ -26,17 +26,17 @@ Revision History: typedef uint64 mpn_double_digit; COMPILE_TIME_ASSERT(sizeof(mpn_double_digit) == 2 * sizeof(mpn_digit)); -mpn_manager static_mpn_manager; - const mpn_digit mpn_manager::zero = 0; mpn_manager::mpn_manager() { #ifdef Z3DEBUG trace_enabled=true; #endif + omp_init_nest_lock(&m_lock); } mpn_manager::~mpn_manager() { + omp_destroy_nest_lock(&m_lock); } int mpn_manager::compare(mpn_digit const * a, size_t const lnga, @@ -164,6 +164,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum, mpn_digit const * denom, size_t const lden, mpn_digit * quot, mpn_digit * rem) { + MPN_BEGIN_CRITICAL(); trace(numer, lnum, denom, lden, "/"); bool res = false; @@ -225,6 +226,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum, SASSERT(ok); #endif + MPN_END_CRITICAL(); return res; } @@ -233,6 +235,7 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum, mpn_sbuffer & n_numer, mpn_sbuffer & n_denom) const { + MPN_BEGIN_CRITICAL(); size_t d = 0; while (((denom[lden-1] << d) & MASK_FIRST) == 0) d++; SASSERT(d < DIGIT_BITS); @@ -261,11 +264,13 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum, STRACE("mpn_norm", tout << "Normalized: n_numer="; display_raw(tout, n_numer.c_ptr(), n_numer.size()); tout << " n_denom="; display_raw(tout, n_denom.c_ptr(), n_denom.size()); tout << std::endl; ); + MPN_END_CRITICAL(); return d; } void mpn_manager::div_unnormalize(mpn_sbuffer & numer, mpn_sbuffer & denom, size_t const d, mpn_digit * rem) const { + MPN_BEGIN_CRITICAL(); if (d == 0) { for (size_t i = 0; i < denom.size(); i++) rem[i] = numer[i]; @@ -275,11 +280,13 @@ void mpn_manager::div_unnormalize(mpn_sbuffer & numer, mpn_sbuffer & denom, rem[i] = numer[i] >> d | (LAST_BITS(d, numer[i+1]) << (DIGIT_BITS-d)); rem[denom.size()-1] = numer[denom.size()-1] >> d; } + MPN_END_CRITICAL(); } bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom, mpn_digit * quot) const { + MPN_BEGIN_CRITICAL(); mpn_double_digit q_hat, temp, r_hat, ms; mpn_digit borrow; @@ -307,11 +314,13 @@ bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom, tout << std::endl; ); } + MPN_END_CRITICAL(); return true; // return rem != 0 or something like that? } bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, mpn_digit * quot, mpn_digit * rem) { + MPN_BEGIN_CRITICAL(); SASSERT(denom.size() > 1); // This is essentially Knuth's Algorithm D. @@ -363,7 +372,8 @@ bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, tout << " borrow=" << borrow; tout << std::endl; ); } - + + MPN_END_CRITICAL(); return true; // return rem != 0 or something like that? } diff --git a/src/util/mpn.h b/src/util/mpn.h index 219368de3..ab96446b2 100644 --- a/src/util/mpn.h +++ b/src/util/mpn.h @@ -22,13 +22,15 @@ Revision History: #include #include"util.h" #include"buffer.h" - -// we supply a definition of a basic max because mpz relies on it. -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#include"z3_omp.h" typedef unsigned int mpn_digit; class mpn_manager { + omp_nest_lock_t m_lock; +#define MPN_BEGIN_CRITICAL() omp_set_nest_lock(&const_cast(m_lock)); +#define MPN_END_CRITICAL() omp_unset_nest_lock(&const_cast(m_lock)); + public: mpn_manager(); ~mpn_manager(); @@ -56,7 +58,6 @@ public: char * to_string(mpn_digit const * a, size_t const lng, char * buf, size_t const lbuf) const; - private: #ifdef _AMD64_ class mpn_sbuffer : public sbuffer { @@ -112,85 +113,6 @@ private: void trace(mpn_digit const * a, size_t const lnga) const; void trace_nl(mpn_digit const * a, size_t const lnga) const; - -public: - // This function is needed because of the static_mpn_manager global variable. - // It must be invoked by the memory_manager during finalization. - // After we remove MSBignum from the code base, the global variable will - // not be needed anymore, and we will be able to eliminate this function. - void finalize() { - u.finalize(); - v.finalize(); - t_ms.finalize(); - t_ab.finalize(); - } }; - -// MSBignum compatible interface -// Note: The `owner' parameter is ignored. We use separate mpn_manager objects for the -// same purpose. Multiple owners are not supported in these compatibility functions, -// instead a static mpn_manager is used. - -extern mpn_manager static_mpn_manager; - -typedef unsigned int digit_t; - -typedef struct { - mpn_digit multiplier; - size_t shiftamt; -} reciprocal_1_t; - -#define reciprocal_1_NULL ((reciprocal_1_t*)0) - -inline int compare_diff(digit_t const * a, size_t const lnga, - digit_t const * b, size_t const lngb) -{ - return static_mpn_manager.compare(a, lnga, b, lngb); -} - -inline char * mp_decimal(digit_t const * a, size_t const lng, // Number to be converted and its length - char * buf, size_t const lbuf, // output buffer and its length - int owner) -{ - return static_mpn_manager.to_string(a, lng, buf, lbuf); -} - -inline bool add_full(digit_t const * a, size_t const lnga, - digit_t const * b, size_t const lngb, - digit_t *c, size_t const lngc_alloc, - size_t * plngc, - int owner) -{ - return static_mpn_manager.add(a, lnga, b, lngb, c, lngc_alloc, plngc); -} - -inline bool sub_diff(digit_t const * a, size_t const lnga, - digit_t const * b, size_t const lngb, - digit_t * c, digit_t * pborrow, - int owner) -{ - return static_mpn_manager.sub(a, lnga, b, lngb, c, pborrow); -} - -inline bool multiply(digit_t const * a, size_t const lnga, - digit_t const * b, size_t const lngb, - digit_t * c, - int owner) -{ - return static_mpn_manager.mul(a, lnga, b, lngb, c); -} - -inline bool divide(digit_t const * numer, size_t const lnum, - digit_t const * denom, size_t const lden, - reciprocal_1_t const * supplied_reciprocal, /* reciprocal_t struct for this denominator, - or reciprocal_1_NULL - if not previously precomputed */ - digit_t * quot, /* Quotient -- length MAX(lnum - lden + 1, 0) */ - digit_t * rem, /* Remainder -- length lden */ - int owner) -{ - return static_mpn_manager.div(numer, lnum, denom, lden, quot, rem); -} - #endif diff --git a/src/util/mpz.cpp b/src/util/mpz.cpp index 94df9f78d..163f7fb86 100644 --- a/src/util/mpz.cpp +++ b/src/util/mpz.cpp @@ -37,7 +37,7 @@ Revision History: // #define LS_BINARY_GCD // #define LEHMER_GCD -#if defined(_MP_GMP) || (defined(_MP_MSBIGNUM) && defined(_AMD64_)) +#if defined(_MP_GMP) // Use LEHMER only if not using GMP // LEHMER assumes 32-bit digits, so it cannot be used with MSBIGNUM library + 64-bit binary #define EUCLID_GCD @@ -365,25 +365,18 @@ void mpz_manager::big_add_sub(mpz const & a, mpz const & b, mpz & c) { sign_b = -sign_b; size_t real_sz; if (sign_a == sign_b) { - unsigned sz = max(cell_a->m_size, cell_b->m_size)+1; + unsigned sz = std::max(cell_a->m_size, cell_b->m_size)+1; ensure_tmp_capacity<0>(sz); - add_full(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size, - m_tmp[0]->m_digits, - sz, - &real_sz, - 0); + m_mpn_manager.add(cell_a->m_digits, cell_a->m_size, + cell_b->m_digits, cell_b->m_size, + m_tmp[0]->m_digits, sz, &real_sz); SASSERT(real_sz <= sz); set<0>(c, sign_a, static_cast(real_sz)); } else { digit_t borrow; - int r = compare_diff(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size); + int r = m_mpn_manager.compare(cell_a->m_digits, cell_a->m_size, + cell_b->m_digits, cell_b->m_size); if (r == 0) { reset(c); } @@ -391,13 +384,12 @@ void mpz_manager::big_add_sub(mpz const & a, mpz const & b, mpz & c) { // a < b unsigned sz = cell_b->m_size; ensure_tmp_capacity<0>(sz); - sub_diff(cell_b->m_digits, - cell_b->m_size, - cell_a->m_digits, - cell_a->m_size, - m_tmp[0]->m_digits, - &borrow, - 0); + m_mpn_manager.sub(cell_b->m_digits, + cell_b->m_size, + cell_a->m_digits, + cell_a->m_size, + m_tmp[0]->m_digits, + &borrow); SASSERT(borrow == 0); set<0>(c, sign_b, sz); } @@ -405,13 +397,12 @@ void mpz_manager::big_add_sub(mpz const & a, mpz const & b, mpz & c) { // a > b unsigned sz = cell_a->m_size; ensure_tmp_capacity<0>(sz); - sub_diff(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size, - m_tmp[0]->m_digits, - &borrow, - 0); + m_mpn_manager.sub(cell_a->m_digits, + cell_a->m_size, + cell_b->m_digits, + cell_b->m_size, + m_tmp[0]->m_digits, + &borrow); SASSERT(borrow == 0); set<0>(c, sign_a, sz); } @@ -460,12 +451,11 @@ void mpz_manager::big_mul(mpz const & a, mpz const & b, mpz & c) { get_sign_cell<1>(b, sign_b, cell_b); unsigned sz = cell_a->m_size + cell_b->m_size; ensure_tmp_capacity<0>(sz); - multiply(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size, - m_tmp[0]->m_digits, - 0); + m_mpn_manager.mul(cell_a->m_digits, + cell_a->m_size, + cell_b->m_digits, + cell_b->m_size, + m_tmp[0]->m_digits); set<0>(c, sign_a == sign_b ? 1 : -1, sz); #else // GMP version @@ -505,14 +495,10 @@ void mpz_manager::quot_rem_core(mpz const & a, mpz const & b, mpz & q, mp unsigned r_sz = cell_b->m_size; ensure_tmp_capacity<0>(q_sz); ensure_tmp_capacity<1>(r_sz); - divide(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size, - reciprocal_1_NULL, - m_tmp[0]->m_digits, - m_tmp[1]->m_digits, - 0); + m_mpn_manager.div(cell_a->m_digits, cell_a->m_size, + cell_b->m_digits, cell_b->m_size, + m_tmp[0]->m_digits, + m_tmp[1]->m_digits); if (MODE == QUOT_ONLY || MODE == QUOT_AND_REM) set<0>(q, sign_a == sign_b ? 1 : -1, q_sz); if (MODE == REM_ONLY || MODE == QUOT_AND_REM) @@ -606,7 +592,7 @@ void mpz_manager::gcd(mpz const & a, mpz const & b, mpz & c) { // Binary GCD for big numbers // - It doesn't use division // - The initial experiments, don't show any performance improvement - // - It only works with _MP_INTERNAL and _MP_MSBIGNUM + // - It only works with _MP_INTERNAL mpz u, v, diff; set(u, a); set(v, b); @@ -1243,10 +1229,8 @@ int mpz_manager::big_compare(mpz const & a, mpz const & b) { // a is positive if (sign_b > 0) { // a & b are positive - return compare_diff(cell_a->m_digits, - cell_a->m_size, - cell_b->m_digits, - cell_b->m_size); + return m_mpn_manager.compare(cell_a->m_digits, cell_a->m_size, + cell_b->m_digits, cell_b->m_size); } else { // b is negative @@ -1261,10 +1245,8 @@ int mpz_manager::big_compare(mpz const & a, mpz const & b) { } else { // a & b are negative - return compare_diff(cell_b->m_digits, - cell_b->m_size, - cell_a->m_digits, - cell_a->m_size); + return m_mpn_manager.compare(cell_b->m_digits, cell_b->m_size, + cell_a->m_digits, cell_a->m_size); } } #else @@ -1411,11 +1393,11 @@ void mpz_manager::display(std::ostream & out, mpz const & a) const { out << "-"; if (sizeof(digit_t) == 4) { sbuffer buffer(11*size(a), 0); - out << mp_decimal(digits(a), size(a), buffer.begin(), buffer.size(), 0); + out << m_mpn_manager.to_string(digits(a), size(a), buffer.begin(), buffer.size()); } else { sbuffer buffer(21*size(a), 0); - out << mp_decimal(digits(a), size(a), buffer.begin(), buffer.size(), 0); + out << m_mpn_manager.to_string(digits(a), size(a), buffer.begin(), buffer.size()); } #else // GMP version diff --git a/src/util/mpz.h b/src/util/mpz.h index 923d5b3a7..05e87886d 100644 --- a/src/util/mpz.h +++ b/src/util/mpz.h @@ -27,6 +27,7 @@ Revision History: #include"scoped_numeral.h" #include"scoped_numeral_vector.h" #include"z3_omp.h" +#include"mpn.h" unsigned u_gcd(unsigned u, unsigned v); uint64 u64_gcd(uint64 u, uint64 v); @@ -37,7 +38,7 @@ typedef unsigned digit_t; #ifdef _MSC_VER #pragma warning(disable : 4200) -#endif +#endif template class mpz_manager; template class mpq_manager; @@ -107,6 +108,7 @@ class mpz_manager { omp_nest_lock_t m_lock; #define MPZ_BEGIN_CRITICAL() if (SYNCH) omp_set_nest_lock(&m_lock); #define MPZ_END_CRITICAL() if (SYNCH) omp_unset_nest_lock(&m_lock); + mpn_manager m_mpn_manager; #ifndef _MP_GMP unsigned m_init_cell_capacity; From a78dd680fb256b35036f95fc22d7a6c90029a560 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 13:25:18 +0000 Subject: [PATCH 551/646] MPN synchronization fix --- src/util/mpn.cpp | 107 ++++++++++++++++++----------------------------- src/util/mpn.h | 12 ++---- 2 files changed, 45 insertions(+), 74 deletions(-) diff --git a/src/util/mpn.cpp b/src/util/mpn.cpp index ba0a8563a..610eee564 100644 --- a/src/util/mpn.cpp +++ b/src/util/mpn.cpp @@ -29,9 +29,6 @@ COMPILE_TIME_ASSERT(sizeof(mpn_double_digit) == 2 * sizeof(mpn_digit)); const mpn_digit mpn_manager::zero = 0; mpn_manager::mpn_manager() { -#ifdef Z3DEBUG - trace_enabled=true; -#endif omp_init_nest_lock(&m_lock); } @@ -43,11 +40,6 @@ int mpn_manager::compare(mpn_digit const * a, size_t const lnga, mpn_digit const * b, size_t const lngb) const { int res = 0; - #ifdef Z3DEBUG - if (trace_enabled) - STRACE("mpn", tout << "[mpn] "; ); - #endif - trace(a, lnga); size_t j = max(lnga, lngb) - 1; @@ -60,10 +52,7 @@ int mpn_manager::compare(mpn_digit const * a, size_t const lnga, res = -1; } - #ifdef Z3DEBUG - if (trace_enabled) - STRACE("mpn", tout << ((res == 1) ? " > " : (res == -1) ? " < " : " == "); ); - #endif + TRACE("mpn", tout << ((res == 1) ? " > " : (res == -1) ? " < " : " == "); ); trace_nl(b, lngb); return res; @@ -92,7 +81,7 @@ bool mpn_manager::add(mpn_digit const * a, size_t const lnga, for (os = len+1; os > 1 && c[os-1] == 0; ) os--; SASSERT(os > 0 && os <= len+1); trace_nl(c, os); - return true; // return k != 0? What would MSBignum return? + return true; // return k != 0? } bool mpn_manager::sub(mpn_digit const * a, size_t const lnga, @@ -173,6 +162,7 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum, quot[i] = 0; for (size_t i = 0; i < lden; i++) rem[i] = (i < lnum) ? numer[i] : 0; + MPN_END_CRITICAL(); return false; } @@ -181,8 +171,8 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum, if (denom[i] != zero) all_zero = false; if (all_zero) { - // Division by 0. What would the MSBignum divide function do? UNREACHABLE(); + MPN_END_CRITICAL(); return res; } @@ -202,12 +192,12 @@ bool mpn_manager::div(mpn_digit const * numer, size_t const lnum, if (lden == 1) res = div_1(u, v[0], quot); else - res = div_n(u, v, quot, rem); + res = div_n(u, v, quot, rem, t_ms, t_ab); div_unnormalize(u, v, d, rem); } - // STRACE("mpn_dbg", display_raw(tout, quot, lnum - lden + 1); tout << ", "; - // display_raw(tout, rem, lden); tout << std::endl; ); + // TRACE("mpn_dbg", display_raw(tout, quot, lnum - lden + 1); tout << ", "; + // display_raw(tout, rem, lden); tout << std::endl; ); trace_nl(quot, lnum-lden+1); trace(numer, lnum, denom, lden, "%"); @@ -234,8 +224,7 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum, mpn_digit const * denom, size_t const lden, mpn_sbuffer & n_numer, mpn_sbuffer & n_denom) const -{ - MPN_BEGIN_CRITICAL(); +{ size_t d = 0; while (((denom[lden-1] << d) & MASK_FIRST) == 0) d++; SASSERT(d < DIGIT_BITS); @@ -261,16 +250,13 @@ size_t mpn_manager::div_normalize(mpn_digit const * numer, size_t const lnum, n_denom[0] = denom[0] << d; } - STRACE("mpn_norm", tout << "Normalized: n_numer="; display_raw(tout, n_numer.c_ptr(), n_numer.size()); - tout << " n_denom="; display_raw(tout, n_denom.c_ptr(), n_denom.size()); tout << std::endl; ); - - MPN_END_CRITICAL(); + TRACE("mpn_norm", tout << "Normalized: n_numer="; display_raw(tout, n_numer.c_ptr(), n_numer.size()); + tout << " n_denom="; display_raw(tout, n_denom.c_ptr(), n_denom.size()); tout << std::endl; ); return d; } void mpn_manager::div_unnormalize(mpn_sbuffer & numer, mpn_sbuffer & denom, size_t const d, mpn_digit * rem) const { - MPN_BEGIN_CRITICAL(); if (d == 0) { for (size_t i = 0; i < denom.size(); i++) rem[i] = numer[i]; @@ -280,13 +266,10 @@ void mpn_manager::div_unnormalize(mpn_sbuffer & numer, mpn_sbuffer & denom, rem[i] = numer[i] >> d | (LAST_BITS(d, numer[i+1]) << (DIGIT_BITS-d)); rem[denom.size()-1] = numer[denom.size()-1] >> d; } - MPN_END_CRITICAL(); } bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom, - mpn_digit * quot) const -{ - MPN_BEGIN_CRITICAL(); + mpn_digit * quot) const { mpn_double_digit q_hat, temp, r_hat, ms; mpn_digit borrow; @@ -307,20 +290,19 @@ bool mpn_manager::div_1(mpn_sbuffer & numer, mpn_digit const denom, quot[j-1]--; numer[j] = numer[j-1] + denom; } - STRACE("mpn_div1", tout << "j=" << j << " q_hat=" << q_hat << " r_hat=" << r_hat; - tout << " ms=" << ms; - tout << " new numer="; display_raw(tout, numer.c_ptr(), numer.size()); - tout << " borrow=" << borrow; - tout << std::endl; ); + TRACE("mpn_div1", tout << "j=" << j << " q_hat=" << q_hat << " r_hat=" << r_hat; + tout << " ms=" << ms; + tout << " new numer="; display_raw(tout, numer.c_ptr(), numer.size()); + tout << " borrow=" << borrow; + tout << std::endl; ); } - MPN_END_CRITICAL(); - return true; // return rem != 0 or something like that? + return true; // return rem != 0? } bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, - mpn_digit * quot, mpn_digit * rem) { - MPN_BEGIN_CRITICAL(); + mpn_digit * quot, mpn_digit * rem, + mpn_sbuffer & ms, mpn_sbuffer & ab) const { SASSERT(denom.size() > 1); // This is essentially Knuth's Algorithm D. @@ -329,7 +311,7 @@ bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, SASSERT(numer.size() == m+n); - t_ms.resize(n+1); + ms.resize(n+1); mpn_double_digit q_hat, temp, r_hat; mpn_digit borrow; @@ -349,37 +331,30 @@ bool mpn_manager::div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, // Replace numer[j+n]...numer[j] with // numer[j+n]...numer[j] - q * (denom[n-1]...denom[0]) mpn_digit q_hat_small = (mpn_digit)q_hat; - #ifdef Z3DEBUG - trace_enabled = false; - #endif - mul(&q_hat_small, 1, denom.c_ptr(), n, t_ms.c_ptr()); - sub(&numer[j], n+1, t_ms.c_ptr(), n+1, &numer[j], &borrow); + mul(&q_hat_small, 1, denom.c_ptr(), n, ms.c_ptr()); + sub(&numer[j], n+1, ms.c_ptr(), n+1, &numer[j], &borrow); quot[j] = q_hat_small; if (borrow) { quot[j]--; - t_ab.resize(n+2); + ab.resize(n+2); size_t real_size; - add(denom.c_ptr(), n, &numer[j], n+1, t_ab.c_ptr(), n+2, &real_size); + add(denom.c_ptr(), n, &numer[j], n+1, ab.c_ptr(), n+2, &real_size); for (size_t i = 0; i < n+1; i++) - numer[j+i] = t_ab[i]; + numer[j+i] = ab[i]; } - #ifdef Z3DEBUG - trace_enabled = true; - #endif - STRACE("mpn_div", tout << "q_hat=" << q_hat << " r_hat=" << r_hat; - tout << " t_ms="; display_raw(tout, t_ms.c_ptr(), n); - tout << " new numer="; display_raw(tout, numer.c_ptr(), m+n+1); - tout << " borrow=" << borrow; - tout << std::endl; ); + TRACE("mpn_div", tout << "q_hat=" << q_hat << " r_hat=" << r_hat; + tout << " ms="; display_raw(tout, ms.c_ptr(), n); + tout << " new numer="; display_raw(tout, numer.c_ptr(), m+n+1); + tout << " borrow=" << borrow; + tout << std::endl; ); } - MPN_END_CRITICAL(); - return true; // return rem != 0 or something like that? + return true; // return rem != 0? } char * mpn_manager::to_string(mpn_digit const * a, size_t const lng, char * buf, size_t const lbuf) const { SASSERT(buf && lbuf > 0); - STRACE("mpn_to_string", tout << "[mpn] to_string "; display_raw(tout, a, lng); tout << " == "; ); + TRACE("mpn_to_string", tout << "[mpn] to_string "; display_raw(tout, a, lng); tout << " == "; ); if (lng == 1) { #ifdef _WINDOWS @@ -412,7 +387,7 @@ char * mpn_manager::to_string(mpn_digit const * a, size_t const lng, char * buf, std::swap(buf[i], buf[j-i]); } - STRACE("mpn_to_string", tout << buf << std::endl; ); + TRACE("mpn_to_string", tout << buf << std::endl; ); return buf; } @@ -427,23 +402,23 @@ void mpn_manager::trace(mpn_digit const * a, size_t const lnga, mpn_digit const * b, size_t const lngb, const char * op) const { #ifdef Z3DEBUG - if (trace_enabled) - STRACE("mpn", tout << "[mpn] " << to_string(a, lnga, char_buf, sizeof(char_buf)); - tout << " " << op << " " << to_string(b, lngb, char_buf, sizeof(char_buf)); - tout << " == "; ); + char char_buf[4096]; + TRACE("mpn", tout << "[mpn] " << to_string(a, lnga, char_buf, sizeof(char_buf)); + tout << " " << op << " " << to_string(b, lngb, char_buf, sizeof(char_buf)); + tout << " == "; ); #endif } void mpn_manager::trace(mpn_digit const * a, size_t const lnga) const { #ifdef Z3DEBUG - if (trace_enabled) - STRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)); ); + char char_buf[4096]; + TRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)); ); #endif } void mpn_manager::trace_nl(mpn_digit const * a, size_t const lnga) const { #ifdef Z3DEBUG - if (trace_enabled) - STRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)) << std::endl; ); + char char_buf[4096]; + TRACE("mpn", tout << to_string(a, lnga, char_buf, sizeof(char_buf)) << std::endl; ); #endif } diff --git a/src/util/mpn.h b/src/util/mpn.h index ab96446b2..495ae135c 100644 --- a/src/util/mpn.h +++ b/src/util/mpn.h @@ -28,8 +28,8 @@ typedef unsigned int mpn_digit; class mpn_manager { omp_nest_lock_t m_lock; -#define MPN_BEGIN_CRITICAL() omp_set_nest_lock(&const_cast(m_lock)); -#define MPN_END_CRITICAL() omp_unset_nest_lock(&const_cast(m_lock)); +#define MPN_BEGIN_CRITICAL() omp_set_nest_lock(&m_lock); +#define MPN_END_CRITICAL() omp_unset_nest_lock(&m_lock); public: mpn_manager(); @@ -100,12 +100,8 @@ private: mpn_digit * quot) const; bool div_n(mpn_sbuffer & numer, mpn_sbuffer const & denom, - mpn_digit * quot, mpn_digit * rem); - - #ifdef Z3DEBUG - mutable char char_buf[4096]; - bool trace_enabled; - #endif + mpn_digit * quot, mpn_digit * rem, + mpn_sbuffer & ms, mpn_sbuffer & ab) const; void trace(mpn_digit const * a, size_t const lnga, mpn_digit const * b, size_t const lngb, From 73cebc24c8de4511adac40549c074b68840205dd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 13:25:40 +0000 Subject: [PATCH 552/646] propagate_ineqs synchronization fix --- src/tactic/arith/bound_propagator.h | 2 +- src/tactic/arith/linear_equation.h | 2 +- src/tactic/arith/propagate_ineqs_tactic.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tactic/arith/bound_propagator.h b/src/tactic/arith/bound_propagator.h index 04f2e0e17..6ac405ebc 100644 --- a/src/tactic/arith/bound_propagator.h +++ b/src/tactic/arith/bound_propagator.h @@ -31,7 +31,7 @@ class bound_propagator { public: typedef unsigned var; typedef unsigned assumption; - typedef unsynch_mpq_manager numeral_manager; + typedef synch_mpq_manager numeral_manager; typedef unsigned_vector assumption_vector; typedef unsigned constraint_id; typedef numeral_buffer mpz_buffer; diff --git a/src/tactic/arith/linear_equation.h b/src/tactic/arith/linear_equation.h index 8b38a30e4..56349e2a4 100644 --- a/src/tactic/arith/linear_equation.h +++ b/src/tactic/arith/linear_equation.h @@ -52,7 +52,7 @@ public: class linear_equation_manager { public: - typedef unsynch_mpq_manager numeral_manager; + typedef synch_mpq_manager numeral_manager; typedef linear_equation::var var; typedef numeral_buffer mpz_buffer; private: diff --git a/src/tactic/arith/propagate_ineqs_tactic.cpp b/src/tactic/arith/propagate_ineqs_tactic.cpp index 977f15167..6c284a0d4 100644 --- a/src/tactic/arith/propagate_ineqs_tactic.cpp +++ b/src/tactic/arith/propagate_ineqs_tactic.cpp @@ -65,7 +65,7 @@ tactic * mk_propagate_ineqs_tactic(ast_manager & m, params_ref const & p) { struct propagate_ineqs_tactic::imp { ast_manager & m; - unsynch_mpq_manager nm; + synch_mpq_manager nm; small_object_allocator m_allocator; bound_propagator bp; arith_util m_util; @@ -73,7 +73,7 @@ struct propagate_ineqs_tactic::imp { obj_map m_expr2var; expr_ref_vector m_var2expr; - typedef numeral_buffer mpq_buffer; + typedef numeral_buffer mpq_buffer; typedef svector var_buffer; mpq_buffer m_num_buffer; From 72345026be090f3c1203262662f5b1fabc9af225 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 15:16:24 +0000 Subject: [PATCH 553/646] Revert "propagate_ineqs synchronization fix" This reverts commit 73cebc24c8de4511adac40549c074b68840205dd. --- src/tactic/arith/bound_propagator.h | 2 +- src/tactic/arith/linear_equation.h | 2 +- src/tactic/arith/propagate_ineqs_tactic.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tactic/arith/bound_propagator.h b/src/tactic/arith/bound_propagator.h index 6ac405ebc..04f2e0e17 100644 --- a/src/tactic/arith/bound_propagator.h +++ b/src/tactic/arith/bound_propagator.h @@ -31,7 +31,7 @@ class bound_propagator { public: typedef unsigned var; typedef unsigned assumption; - typedef synch_mpq_manager numeral_manager; + typedef unsynch_mpq_manager numeral_manager; typedef unsigned_vector assumption_vector; typedef unsigned constraint_id; typedef numeral_buffer mpz_buffer; diff --git a/src/tactic/arith/linear_equation.h b/src/tactic/arith/linear_equation.h index 56349e2a4..8b38a30e4 100644 --- a/src/tactic/arith/linear_equation.h +++ b/src/tactic/arith/linear_equation.h @@ -52,7 +52,7 @@ public: class linear_equation_manager { public: - typedef synch_mpq_manager numeral_manager; + typedef unsynch_mpq_manager numeral_manager; typedef linear_equation::var var; typedef numeral_buffer mpz_buffer; private: diff --git a/src/tactic/arith/propagate_ineqs_tactic.cpp b/src/tactic/arith/propagate_ineqs_tactic.cpp index 6c284a0d4..977f15167 100644 --- a/src/tactic/arith/propagate_ineqs_tactic.cpp +++ b/src/tactic/arith/propagate_ineqs_tactic.cpp @@ -65,7 +65,7 @@ tactic * mk_propagate_ineqs_tactic(ast_manager & m, params_ref const & p) { struct propagate_ineqs_tactic::imp { ast_manager & m; - synch_mpq_manager nm; + unsynch_mpq_manager nm; small_object_allocator m_allocator; bound_propagator bp; arith_util m_util; @@ -73,7 +73,7 @@ struct propagate_ineqs_tactic::imp { obj_map m_expr2var; expr_ref_vector m_var2expr; - typedef numeral_buffer mpq_buffer; + typedef numeral_buffer mpq_buffer; typedef svector var_buffer; mpq_buffer m_num_buffer; From 4792c5fb7c91b24b3eb21fcdcf04adfbf21919d4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 16:53:08 +0000 Subject: [PATCH 554/646] Fixed bugs in static features and smt setup Signed-off-by: Christoph M. Wintersteiger --- src/ast/static_features.cpp | 8 +++++++- src/ast/static_features.h | 7 +++++-- src/smt/smt_setup.cpp | 10 +++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index e725df691..1634f8df4 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -23,6 +23,7 @@ static_features::static_features(ast_manager & m): m_manager(m), m_autil(m), m_bvutil(m), + m_arrayutil(m), m_fpautil(m), m_bfid(m.get_basic_family_id()), m_afid(m.mk_family_id("arith")), @@ -72,7 +73,10 @@ void static_features::reset() { m_num_eqs = 0; m_has_rational = false; m_has_int = false; - m_has_real = false; + m_has_real = false; + m_has_bv = false; + m_has_fpa = false; + m_has_arrays = false; m_arith_k_sum .reset(); m_num_arith_terms = 0; m_num_arith_eqs = 0; @@ -272,6 +276,8 @@ void static_features::update_core(expr * e) { m_has_bv = true; if (!m_has_fpa && (m_fpautil.is_float(e) || m_fpautil.is_rm(e))) m_has_fpa = true; + if (!m_has_arrays && m_arrayutil.is_array(e)) + m_has_arrays = true; if (is_app(e)) { family_id fid = to_app(e)->get_family_id(); mark_theory(fid); diff --git a/src/ast/static_features.h b/src/ast/static_features.h index 2d6213ded..d27d026cf 100644 --- a/src/ast/static_features.h +++ b/src/ast/static_features.h @@ -22,6 +22,7 @@ Revision History: #include"ast.h" #include"arith_decl_plugin.h" #include"bv_decl_plugin.h" +#include"array_decl_plugin.h" #include"fpa_decl_plugin.h" #include"map.h" @@ -29,6 +30,7 @@ struct static_features { ast_manager & m_manager; arith_util m_autil; bv_util m_bvutil; + array_util m_arrayutil; fpa_util m_fpautil; family_id m_bfid; family_id m_afid; @@ -72,8 +74,9 @@ struct static_features { bool m_has_rational; // bool m_has_int; // bool m_has_real; // - bool m_has_bv; // - bool m_has_fpa; // + bool m_has_bv; // + bool m_has_fpa; // + bool m_has_arrays; // rational m_arith_k_sum; // sum of the numerals in arith atoms. unsigned m_num_arith_terms; unsigned m_num_arith_eqs; // equalities of the form t = k where k is a numeral diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 7abd40399..a89422ee0 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -888,7 +888,15 @@ namespace smt { return; } - // TODO QF_AUFBV, QF_AUFLIA + if (st.num_theories() == 1 && st.m_has_arrays) + setup_QF_AX(); + + if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_bv) + setup_QF_AUFBV(); + + if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_int) + setup_QF_AUFLIA(); + setup_unknown(); } From d7a37f246c88cf785edca81f3b0737c2c6eb2691 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 16:59:46 +0000 Subject: [PATCH 555/646] More bugfixes for smt setup Signed-off-by: Christoph M. Wintersteiger --- src/smt/smt_setup.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index a89422ee0..96f6122cb 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -888,14 +888,20 @@ namespace smt { return; } - if (st.num_theories() == 1 && st.m_has_arrays) + if (st.num_theories() == 1 && st.m_has_arrays) { setup_QF_AX(); + return; + } - if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_bv) + if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_bv) { setup_QF_AUFBV(); + return; + } - if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_int) + if (st.num_theories() == 2 && st.has_uf() && st.m_has_arrays && st.m_has_int) { setup_QF_AUFLIA(); + return; + } setup_unknown(); } From f9d38a97df6465709b1215a633c2ab3ff0c97e1a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 17:49:30 +0000 Subject: [PATCH 556/646] Bugfix for array simplifier Signed-off-by: Christoph M. Wintersteiger --- src/ast/simplifier/array_simplifier_plugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index 065f8bd96..b169babac 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -421,9 +421,6 @@ bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & resul tout << mk_pp(lhs, m_manager) << " = " << mk_pp(rhs, m_manager) << " := " << eq << "\n";); switch(eq) { - case l_false: - result = m_manager.mk_false(); - return true; case l_true: result = m_manager.mk_true(); return true; From 0298519b4fe518da49c61c2a63be850a9fde7702 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 17:53:06 +0000 Subject: [PATCH 557/646] Revert "Bugfix for array simplifier" This reverts commit f9d38a97df6465709b1215a633c2ab3ff0c97e1a. --- src/ast/simplifier/array_simplifier_plugin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index b169babac..065f8bd96 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -421,6 +421,9 @@ bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & resul tout << mk_pp(lhs, m_manager) << " = " << mk_pp(rhs, m_manager) << " := " << eq << "\n";); switch(eq) { + case l_false: + result = m_manager.mk_false(); + return true; case l_true: result = m_manager.mk_true(); return true; From 321c181fd8841615c6b2b6b96acef71ab5ff8811 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 18:04:23 +0000 Subject: [PATCH 558/646] Bugfix for array_simplifier_plugin. Thanks to codeplex user mtappler for reporting this. Signed-off-by: Christoph M. Wintersteiger --- src/ast/simplifier/array_simplifier_plugin.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index 065f8bd96..3f056df8e 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -409,14 +409,15 @@ bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & resul set_reduce_invoked(); expr* c1, *c2; ptr_vector st1, st2; - unsigned arity = 0; - get_stores(lhs, arity, c1, st1); - get_stores(rhs, arity, c2, st2); - if (is_const_array(c1) && is_const_array(c2)) { + unsigned arity1 = 0; + unsigned arity2 = 0; + get_stores(lhs, arity1, c1, st1); + get_stores(rhs, arity2, c2, st2); + if (arity1 == arity1 && is_const_array(c1) && is_const_array(c2)) { c1 = to_app(c1)->get_arg(0); c2 = to_app(c2)->get_arg(0); if (c1 == c2) { - lbool eq = eq_stores(c1, arity, st1.size(), st1.c_ptr(), st2.size(), st2.c_ptr()); + lbool eq = eq_stores(c1, arity2, st1.size(), st1.c_ptr(), st2.size(), st2.c_ptr()); TRACE("array_simplifier", tout << mk_pp(lhs, m_manager) << " = " << mk_pp(rhs, m_manager) << " := " << eq << "\n";); From 0a22f1e0f555324ab83b9a8f42946bceb87bcb6f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 8 Feb 2015 18:07:10 +0000 Subject: [PATCH 559/646] array simplifier fix for a fix... Signed-off-by: Christoph M. Wintersteiger --- src/ast/simplifier/array_simplifier_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index 3f056df8e..c75766b25 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -413,7 +413,7 @@ bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & resul unsigned arity2 = 0; get_stores(lhs, arity1, c1, st1); get_stores(rhs, arity2, c2, st2); - if (arity1 == arity1 && is_const_array(c1) && is_const_array(c2)) { + if (arity1 == arity2 && is_const_array(c1) && is_const_array(c2)) { c1 = to_app(c1)->get_arg(0); c2 = to_app(c2)->get_arg(0); if (c1 == c2) { From 3a8a62fc4c70ccaeb5e48778dd4c9ac151faf274 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 9 Feb 2015 13:41:45 +0000 Subject: [PATCH 560/646] Added array index/element sort detection to static_features --- src/ast/static_features.cpp | 25 +++++++++++++++++++++++++ src/ast/static_features.h | 2 ++ src/smt/smt_setup.cpp | 5 ++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index 1634f8df4..8534ffd4a 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -28,6 +28,7 @@ static_features::static_features(ast_manager & m): m_bfid(m.get_basic_family_id()), m_afid(m.mk_family_id("arith")), m_lfid(m.mk_family_id("label")), + m_arrfid(m.mk_family_id("array")), m_label_sym("label"), m_pattern_sym("pattern"), m_expr_list_sym("expr-list") { @@ -317,6 +318,16 @@ void static_features::update_core(expr * e) { } } } + if (m_arrayutil.is_array(e)) { + TRACE("sf_array", tout << mk_ismt2_pp(e, m_manager) << "\n";); + sort * ty = to_app(e)->get_decl()->get_range(); + SASSERT(ty->get_num_parameters() == 2); + sort * inx_srt = to_sort(ty->get_parameter(0).get_ast()); + sort * elm_srt = to_sort(ty->get_parameter(1).get_ast()); + mark_theory(ty->get_family_id()); + update_core(inx_srt); + update_core(elm_srt); + } func_decl * d = to_app(e)->get_decl(); inc_num_apps(d); if (d->get_arity() > 0 && !is_marked(d)) { @@ -351,6 +362,20 @@ void static_features::update_core(expr * e) { } } +void static_features::update_core(sort * s) { + mark_theory(s->get_family_id()); + if (!m_has_int && m_autil.is_int(s)) + m_has_int = true; + if (!m_has_real && m_autil.is_real(s)) + m_has_real = true; + if (!m_has_bv && m_bvutil.is_bv_sort(s)) + m_has_bv = true; + if (!m_has_fpa && (m_fpautil.is_float(s) || m_fpautil.is_rm(s))) + m_has_fpa = true; + if (!m_has_arrays && m_arrayutil.is_array(s)) + m_has_arrays = true; +} + void static_features::process(expr * e, bool form_ctx, bool or_and_ctx, bool ite_ctx, unsigned stack_depth) { TRACE("static_features", tout << "processing\n" << mk_pp(e, m_manager) << "\n";); if (is_var(e)) diff --git a/src/ast/static_features.h b/src/ast/static_features.h index d27d026cf..4bdcd6f05 100644 --- a/src/ast/static_features.h +++ b/src/ast/static_features.h @@ -35,6 +35,7 @@ struct static_features { family_id m_bfid; family_id m_afid; family_id m_lfid; + family_id m_arrfid; ast_mark m_already_visited; bool m_cnf; unsigned m_num_exprs; // @@ -148,6 +149,7 @@ struct static_features { void inc_theory_eqs(family_id fid) { m_num_theory_eqs.reserve(fid+1, 0); m_num_theory_eqs[fid]++; } void inc_num_aliens(family_id fid) { m_num_aliens_per_family.reserve(fid+1, 0); m_num_aliens_per_family[fid]++; } void update_core(expr * e); + void update_core(sort * s); void process(expr * e, bool form_ctx, bool or_and_ctx, bool ite_ctx, unsigned stack_depth); void process_root(expr * e); unsigned get_depth(expr const * e) const { return m_expr2depth.get(e->get_id(), 1); } diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index 96f6122cb..e6d21a1e2 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -830,7 +830,10 @@ namespace smt { tout << "is_arith: " << is_arith(st) << "\n"; tout << "has UF: " << st.has_uf() << "\n"; tout << "has real: " << st.m_has_real << "\n"; - tout << "has int: " << st.m_has_int << "\n";); + tout << "has int: " << st.m_has_int << "\n"; + tout << "has bv: " << st.m_has_bv << "\n"; + tout << "has fpa: " << st.m_has_fpa << "\n"; + tout << "has arrays: " << st.m_has_arrays << "\n";); if (st.num_non_uf_theories() == 0) { setup_QF_UF(st); From 83a90a9133d6cd36c2607775328fc0de4ee202c3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 9 Feb 2015 15:26:25 +0000 Subject: [PATCH 561/646] Fixed infinite loop when nightly tests crash while std::cin is attached to /dev/null Signed-off-by: Christoph M. Wintersteiger --- src/util/debug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/debug.cpp b/src/util/debug.cpp index c336ddb73..54c67feca 100644 --- a/src/util/debug.cpp +++ b/src/util/debug.cpp @@ -76,7 +76,8 @@ void invoke_gdb() { for (;;) { std::cerr << "(C)ontinue, (A)bort, (S)top, (T)hrow exception, Invoke (G)DB\n"; char result; - std::cin >> result; + bool ok = (std::cin >> result); + if (!ok) exit(ERR_INTERNAL_FATAL); // happens if std::cin is eof or unattached. switch(result) { case 'C': case 'c': From 614caaca62c003d70c0341b894264628e5de3ccf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 9 Feb 2015 16:20:17 +0000 Subject: [PATCH 562/646] Fix for arrays with arity > 1 in static_features --- src/ast/static_features.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index 8534ffd4a..328128794 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -321,12 +321,12 @@ void static_features::update_core(expr * e) { if (m_arrayutil.is_array(e)) { TRACE("sf_array", tout << mk_ismt2_pp(e, m_manager) << "\n";); sort * ty = to_app(e)->get_decl()->get_range(); - SASSERT(ty->get_num_parameters() == 2); - sort * inx_srt = to_sort(ty->get_parameter(0).get_ast()); - sort * elm_srt = to_sort(ty->get_parameter(1).get_ast()); mark_theory(ty->get_family_id()); - update_core(inx_srt); - update_core(elm_srt); + unsigned n = ty->get_num_parameters(); + for (unsigned i = 0; i < n; i++) { + sort * ds = to_sort(ty->get_parameter(i).get_ast()); + update_core(ds); + } } func_decl * d = to_app(e)->get_decl(); inc_num_apps(d); From d3fb5f2a4cda9309651bcf71ea8313c43cad93e3 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 15 Feb 2015 11:53:24 +0000 Subject: [PATCH 563/646] fix misc compiler warnings Signed-off-by: Nuno Lopes --- src/muz/rel/dl_base.cpp | 3 +-- src/smt/smt_implied_equalities.cpp | 3 +-- src/smt/theory_arith_core.h | 9 +++------ src/smt/theory_array_base.cpp | 3 +-- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/muz/rel/dl_base.cpp b/src/muz/rel/dl_base.cpp index dc10b5f8e..0d4cd02d3 100644 --- a/src/muz/rel/dl_base.cpp +++ b/src/muz/rel/dl_base.cpp @@ -189,8 +189,7 @@ namespace datalog { union_find_default_ctx uf_ctx; union_find<> uf(uf_ctx); //the numbers in uf correspond to column indexes after the join for(unsigned i=0; i theory_var theory_arith::internalize_numeral(app * n) { rational _val; - context & ctx = get_context(); - bool flag = m_util.is_numeral(n, _val); + VERIFY(m_util.is_numeral(n, _val)); numeral val(_val); - SASSERT(flag); - SASSERT(!ctx.e_internalized(n)); + SASSERT(!get_context().e_internalized(n)); enode * e = mk_enode(n); // internalizer is marking enodes as interpreted whenever the associated ast is a value and a constant. // e->mark_as_interpreted(); @@ -3117,8 +3115,7 @@ namespace smt { del_vars(get_old_num_vars(num_scopes)); m_scopes.shrink(new_lvl); theory::pop_scope_eh(num_scopes); - bool r = make_feasible(); - SASSERT(r); + VERIFY(make_feasible()); SASSERT(m_to_patch.empty()); m_to_check.reset(); m_in_to_check.reset(); diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index b33e6b4e6..663816a7d 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -645,11 +645,10 @@ namespace smt { if (is_store(n)) { theory_var w = n->get_arg(0)->get_th_var(get_id()); SASSERT(w != null_theory_var); - ast_manager& m = get_manager(); mg_merge(v, get_representative(w)); - TRACE("array", tout << "merge: " << mk_pp(n->get_owner(), m) << " " << v << " " << w << "\n";); + TRACE("array", tout << "merge: " << mk_pp(n->get_owner(), get_manager()) << " " << v << " " << w << "\n";); } else if (is_const(n)) { set_default(v, n->get_arg(0)); From 9b137d54d34e0a014b4c5c5c9c21cbf43b78f604 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 18 Feb 2015 16:25:27 +0000 Subject: [PATCH 564/646] Bugfix and new examples for implicit assumptions in Z3_solver_assert_and_track. Thanks to Amir Ebrahimi for reporting this issue! (See http://stackoverflow.com/questions/28558683/modeling-constraints-in-z3-and-unsat-core-cases) Signed-off-by: Christoph M. Wintersteiger --- examples/dotnet/Program.cs | 42 ++++++++++++++++++++++++++++++++++ examples/java/JavaExample.java | 42 ++++++++++++++++++++++++++++++++++ src/solver/combined_solver.cpp | 15 ++++++++++-- src/solver/solver.h | 12 +++++++++- src/solver/solver_na2as.h | 3 +++ 5 files changed, 111 insertions(+), 3 deletions(-) diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 0847bc868..e1b5fb6d8 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -2010,6 +2010,47 @@ namespace test_mapi } } + /// + /// Extract unsatisfiable core example with AssertAndTrack + /// + public static void UnsatCoreAndProofExample2(Context ctx) + { + Console.WriteLine("UnsatCoreAndProofExample2"); + + Solver solver = ctx.MkSolver(); + + BoolExpr pa = ctx.MkBoolConst("PredA"); + BoolExpr pb = ctx.MkBoolConst("PredB"); + BoolExpr pc = ctx.MkBoolConst("PredC"); + BoolExpr pd = ctx.MkBoolConst("PredD"); + + BoolExpr f1 = ctx.MkAnd(new BoolExpr[] { pa, pb, pc }); + BoolExpr f2 = ctx.MkAnd(new BoolExpr[] { pa, ctx.MkNot(pb), pc }); + BoolExpr f3 = ctx.MkOr(ctx.MkNot(pa), ctx.MkNot(pc)); + BoolExpr f4 = pd; + + BoolExpr p1 = ctx.MkBoolConst("P1"); + BoolExpr p2 = ctx.MkBoolConst("P2"); + BoolExpr p3 = ctx.MkBoolConst("P3"); + BoolExpr p4 = ctx.MkBoolConst("P4"); + + solver.AssertAndTrack(f1, p1); + solver.AssertAndTrack(f2, p2); + solver.AssertAndTrack(f3, p3); + solver.AssertAndTrack(f4, p4); + Status result = solver.Check(); + + if (result == Status.UNSATISFIABLE) + { + Console.WriteLine("unsat"); + Console.WriteLine("core: "); + foreach (Expr c in solver.UnsatCore) + { + Console.WriteLine("{0}", c); + } + } + } + public static void FiniteDomainExample(Context ctx) { Console.WriteLine("FiniteDomainExample"); @@ -2164,6 +2205,7 @@ namespace test_mapi TreeExample(ctx); ForestExample(ctx); UnsatCoreAndProofExample(ctx); + UnsatCoreAndProofExample2(ctx); } // These examples need proof generation turned on and auto-config set to false. diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index d23f249de..5c49b56ae 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -2137,6 +2137,47 @@ class JavaExample } } } + + /// Extract unsatisfiable core example with AssertAndTrack + + public void unsatCoreAndProofExample2(Context ctx) throws Z3Exception + { + System.out.println("UnsatCoreAndProofExample2"); + Log.append("UnsatCoreAndProofExample2"); + + Solver solver = ctx.mkSolver(); + + BoolExpr pa = ctx.mkBoolConst("PredA"); + BoolExpr pb = ctx.mkBoolConst("PredB"); + BoolExpr pc = ctx.mkBoolConst("PredC"); + BoolExpr pd = ctx.mkBoolConst("PredD"); + + BoolExpr f1 = ctx.mkAnd(new BoolExpr[] { pa, pb, pc }); + BoolExpr f2 = ctx.mkAnd(new BoolExpr[] { pa, ctx.mkNot(pb), pc }); + BoolExpr f3 = ctx.mkOr(ctx.mkNot(pa), ctx.mkNot(pc)); + BoolExpr f4 = pd; + + BoolExpr p1 = ctx.mkBoolConst("P1"); + BoolExpr p2 = ctx.mkBoolConst("P2"); + BoolExpr p3 = ctx.mkBoolConst("P3"); + BoolExpr p4 = ctx.mkBoolConst("P4"); + + solver.assertAndTrack(f1, p1); + solver.assertAndTrack(f2, p2); + solver.assertAndTrack(f3, p3); + solver.assertAndTrack(f4, p4); + Status result = solver.check(); + + if (result == Status.UNSATISFIABLE) + { + System.out.println("unsat"); + System.out.println("core: "); + for (Expr c : solver.getUnsatCore()) + { + System.out.println(c); + } + } + } public void finiteDomainExample(Context ctx) throws Z3Exception { @@ -2298,6 +2339,7 @@ class JavaExample p.treeExample(ctx); p.forestExample(ctx); p.unsatCoreAndProofExample(ctx); + p.unsatCoreAndProofExample2(ctx); } { // These examples need proof generation turned on and auto-config diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp index dfbb62f65..649a79be2 100644 --- a/src/solver/combined_solver.cpp +++ b/src/solver/combined_solver.cpp @@ -178,8 +178,9 @@ public: virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { m_check_sat_executed = true; - - if (num_assumptions > 0 || // assumptions were provided + + if (get_num_assumptions() != 0 || + num_assumptions > 0 || // assumptions were provided m_ignore_solver1) { // must use incremental solver switch_inc_mode(); @@ -241,6 +242,16 @@ public: return m_solver1->get_assertion(idx); } + virtual unsigned get_num_assumptions() const { + return m_solver1->get_num_assumptions() + m_solver2->get_num_assumptions(); + } + + virtual expr * get_assumption(unsigned idx) const { + unsigned c1 = m_solver1->get_num_assumptions(); + if (idx < c1) return m_solver1->get_assumption(idx); + return m_solver2->get_assumption(idx - c1); + } + virtual void display(std::ostream & out) const { m_solver1->display(out); } diff --git a/src/solver/solver.h b/src/solver/solver.h index a95c649c0..b5a407e2a 100644 --- a/src/solver/solver.h +++ b/src/solver/solver.h @@ -72,7 +72,7 @@ public: /** \brief Add a new formula \c t to the assertion stack, and "tag" it with \c a. - The propositional varialbe \c a is used to track the use of \c t in a proof + The propositional variable \c a is used to track the use of \c t in a proof of unsatisfiability. */ virtual void assert_expr(expr * t, expr * a) = 0; @@ -125,6 +125,16 @@ public: */ virtual expr * get_assertion(unsigned idx) const; + /** + \brief The number of tracked assumptions (see assert_expr(t, a)). + */ + virtual unsigned get_num_assumptions() const = 0; + + /** + \brief Retrieves the idx'th tracked assumption (see assert_expr(t, a)). + */ + virtual expr * get_assumption(unsigned idx) const = 0; + /** \brief Display the content of this solver. */ diff --git a/src/solver/solver_na2as.h b/src/solver/solver_na2as.h index 15750344a..4c6af0dca 100644 --- a/src/solver/solver_na2as.h +++ b/src/solver/solver_na2as.h @@ -41,6 +41,9 @@ public: virtual void push(); virtual void pop(unsigned n); virtual unsigned get_scope_level() const; + + virtual unsigned get_num_assumptions() const { return m_assumptions.size(); } + virtual expr * get_assumption(unsigned idx) const { return m_assumptions[idx]; } protected: virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) = 0; virtual void push_core() = 0; From 65373901713982718358752fbd3d719cf348d585 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 18 Feb 2015 16:34:35 +0000 Subject: [PATCH 565/646] + bug reporter Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index bfadb8f75..d93a13129 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,7 +11,7 @@ Version 4.4 - Upgrade: This release includes a brand new OCaml/ML API that is much better integrated with the build system, and hopefully also easier to use than the previous one. -- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, and Codeplex users rsas, clockish, Heizmann. +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, and Codeplex users rsas, clockish, Heizmann. Version 4.3.2 From 7735a40752859d84f743c4a776fe831740dd7b6b Mon Sep 17 00:00:00 2001 From: nikolajbjorner Date: Thu, 19 Feb 2015 07:01:55 -0800 Subject: [PATCH 566/646] fix bug in array simplification. Codeplex issue 173 Signed-off-by: nikolajbjorner --- .../simplifier/array_simplifier_plugin.cpp | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index c75766b25..221d2a209 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -327,18 +327,22 @@ void array_simplifier_plugin::get_stores(expr* n, unsigned& arity, expr*& m, ptr } lbool array_simplifier_plugin::eq_default(expr* def, unsigned arity, unsigned num_st, expr*const* const* st) { + bool all_diseq = m_manager.is_unique_value(def) && num_st > 0; + bool all_eq = true; for (unsigned i = 0; i < num_st; ++i) { - if (st[i][arity] == def) { - continue; - } - if (m_manager.is_unique_value(st[i][arity]) && m_manager.is_unique_value(def)) { - return l_false; - } - return l_undef; + all_eq &= (st[i][arity] == def); + all_diseq &= m_manager.is_unique_value(st[i][arity]) && (st[i][arity] != def); } - return l_true; + if (all_eq) { + return l_true; + } + if (all_diseq) { + return l_false; + } + return l_undef; } + bool array_simplifier_plugin::insert_table(expr* def, unsigned arity, unsigned num_st, expr*const* const* st, arg_table& table) { for (unsigned i = 0; i < num_st; ++i ) { for (unsigned j = 0; j < arity; ++j) { From 185f9325a610c6d3939bce76adeae25ce4371ff5 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Thu, 19 Feb 2015 12:25:06 -0800 Subject: [PATCH 567/646] fixed interpolation bug --- src/interp/iz3interp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interp/iz3interp.cpp b/src/interp/iz3interp.cpp index 7a0090981..e1846d3b5 100755 --- a/src/interp/iz3interp.cpp +++ b/src/interp/iz3interp.cpp @@ -127,7 +127,7 @@ struct frame_reducer : public iz3mgr { for(int i = 0; i < frames-2; i++){ int p = orig_parents_copy.size() == 0 ? i+1 : orig_parents_copy[i]; if(p < frames - 1 && !used_frames[p]) - interpolants[p] = interpolants[i]; + interpolants[p] = mk_and(interpolants[i],interpolants[p]); } } }; From aa40316268eaecfd7b68c0031324e348369c521e Mon Sep 17 00:00:00 2001 From: nikolajbjorner Date: Thu, 19 Feb 2015 19:09:12 -0800 Subject: [PATCH 568/646] rewrite terminology for policheck Signed-off-by: nikolajbjorner --- src/api/api_interp.cpp | 12 ++++++------ src/api/java/Solver.java | 10 +++++----- src/duality/duality_rpfp.cpp | 14 +++++++------- src/interp/iz3scopes.cpp | 2 +- src/sat/sat_clause.cpp | 2 ++ 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index dd689dcb0..38d726761 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -293,10 +293,10 @@ extern "C" { else { model_ref _m; m_solver.get()->get_model(_m); - Z3_model_ref *crap = alloc(Z3_model_ref); - crap->m_model = _m.get(); - mk_c(c)->save_object(crap); - *model = of_model(crap); + Z3_model_ref *tmp_val = alloc(Z3_model_ref); + tmp_val->m_model = _m.get(); + mk_c(c)->save_object(tmp_val); + *model = of_model(tmp_val); } *out_interp = of_ast_vector(v); @@ -490,8 +490,8 @@ extern "C" { try { std::string foo(filename); if (foo.size() >= 5 && foo.substr(foo.size() - 5) == ".smt2"){ - Z3_ast ass = Z3_parse_smtlib2_file(ctx, filename, 0, 0, 0, 0, 0, 0); - Z3_app app = Z3_to_app(ctx, ass); + Z3_ast assrts = Z3_parse_smtlib2_file(ctx, filename, 0, 0, 0, 0, 0, 0); + Z3_app app = Z3_to_app(ctx, assrts); int nconjs = Z3_get_app_num_args(ctx, app); assertions.resize(nconjs); for (int k = 0; k < nconjs; k++) diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index 4b330ff86..db3f46bfd 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -176,9 +176,9 @@ public class Solver extends Z3Object **/ public int getNumAssertions() throws Z3Exception { - ASTVector ass = new ASTVector(getContext(), Native.solverGetAssertions( + ASTVector assrts = new ASTVector(getContext(), Native.solverGetAssertions( getContext().nCtx(), getNativeObject())); - return ass.size(); + return assrts.size(); } /** @@ -188,12 +188,12 @@ public class Solver extends Z3Object **/ public BoolExpr[] getAssertions() throws Z3Exception { - ASTVector ass = new ASTVector(getContext(), Native.solverGetAssertions( + ASTVector assrts = new ASTVector(getContext(), Native.solverGetAssertions( getContext().nCtx(), getNativeObject())); - int n = ass.size(); + int n = assrts.size(); BoolExpr[] res = new BoolExpr[n]; for (int i = 0; i < n; i++) - res[i] = new BoolExpr(getContext(), ass.get(i).getNativeObject()); + res[i] = new BoolExpr(getContext(), assrts.get(i).getNativeObject()); return res; } diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index e2a5d05dc..eefb3b85f 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -1131,10 +1131,10 @@ namespace Duality { } std::vector *cnsts[2] = { &child->getTerms(), &assumptions->getTerms() }; for (unsigned i = 0; i < assumps.size(); i++) { - expr &ass = assumps[i]; - expr alit = (ass.is_app() && ass.decl().get_decl_kind() == Implies) ? ass.arg(0) : ass; + expr &as = assumps[i]; + expr alit = (as.is_app() && as.decl().get_decl_kind() == Implies) ? as.arg(0) : as; bool isA = map.find(alit) != map.end(); - cnsts[isA ? 0 : 1]->push_back(ass); + cnsts[isA ? 0 : 1]->push_back(as); } } else @@ -3221,12 +3221,12 @@ done: std::vector assumps, core, conjuncts; AssertEdgeCache(edge,assumps); for(unsigned i = 0; i < edge->Children.size(); i++){ - expr ass = GetAnnotation(edge->Children[i]); + expr as = GetAnnotation(edge->Children[i]); std::vector clauses; - if(!ass.is_true()){ - CollectConjuncts(ass.arg(1),clauses); + if(!as.is_true()){ + CollectConjuncts(as.arg(1),clauses); for(unsigned j = 0; j < clauses.size(); j++) - GetAssumptionLits(ass.arg(0) || clauses[j],assumps); + GetAssumptionLits(as.arg(0) || clauses[j],assumps); } } expr fmla = GetAnnotation(node); diff --git a/src/interp/iz3scopes.cpp b/src/interp/iz3scopes.cpp index 389a64b6c..9c08a0e31 100755 --- a/src/interp/iz3scopes.cpp +++ b/src/interp/iz3scopes.cpp @@ -165,7 +165,7 @@ scopes::range scopes::range_glb(const range &rng1, const range &rng2){ return bar.first->second; //std::pair::iterator,bool> bar = rt->unique.insert(foo); // const range_lo *baz = &*(bar.first); - // return (range_lo *)baz; // exit const hell + // return (range_lo *)baz; // coerce const } scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){ diff --git a/src/sat/sat_clause.cpp b/src/sat/sat_clause.cpp index b5f6521b8..facd2897d 100644 --- a/src/sat/sat_clause.cpp +++ b/src/sat/sat_clause.cpp @@ -19,6 +19,7 @@ Revision History: #include #include"sat_clause.h" #include"z3_exception.h" +#include"trace.h" namespace sat { @@ -173,6 +174,7 @@ namespace sat { } void clause_allocator::del_clause(clause * cls) { + TRACE("sat", tout << "delete: " << cls->id() << " " << cls << "\n";); m_id_gen.recycle(cls->id()); size_t size = clause::get_obj_size(cls->m_capacity); #ifdef _AMD64_ From 5676fbbc9e96c13b91bad56eadb4a2c03b1c3215 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 22 Feb 2015 11:13:51 +0000 Subject: [PATCH 569/646] compiler love: make a few symbols static and avoid unneeded relocations Signed-off-by: Nuno Lopes --- scripts/mk_util.py | 2 +- src/ast/ast_smt_pp.cpp | 8 ++++---- src/ast/rewriter/poly_rewriter.h | 2 -- src/ast/rewriter/poly_rewriter_def.h | 5 +---- src/smt/database.h | 2 +- src/util/memory_manager.cpp | 2 +- src/util/util.cpp | 4 ++-- 7 files changed, 10 insertions(+), 15 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 2ed420c20..ae91cd8bd 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2104,7 +2104,7 @@ def mk_pat_db(): c = get_component(PATTERN_COMPONENT) fin = open(os.path.join(c.src_dir, 'database.smt2'), 'r') fout = open(os.path.join(c.src_dir, 'database.h'), 'w') - fout.write('char const * g_pattern_database =\n') + fout.write('static char const g_pattern_database[] =\n') for line in fin: fout.write('"%s\\n"\n' % line.strip('\n')) fout.write(';\n') diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index b28b640bb..805f3070f 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -34,9 +34,9 @@ Revision History: // --------------------------------------- // smt_renaming -const static char* m_predef_names[] = { +static const char m_predef_names[][8] = { "=", ">=", "<=", "+", "-", "*", ">", "<", "!=", "or", "and", "implies", "not", "iff", "xor", - "true", "false", "forall", "exists", "let", "flet", NULL + "true", "false", "forall", "exists", "let", "flet" }; symbol smt_renaming::fix_symbol(symbol s, int k) { @@ -120,8 +120,8 @@ bool smt_renaming::all_is_legal(char const* s) { } smt_renaming::smt_renaming() { - for (const char **p = m_predef_names; *p; ++p) { - symbol s(*p); + for (unsigned i = 0; i < ARRAYSIZE(m_predef_names); ++i) { + symbol s(m_predef_names[i]); m_translate.insert(s, s); m_rev_translate.insert(s, s); } diff --git a/src/ast/rewriter/poly_rewriter.h b/src/ast/rewriter/poly_rewriter.h index 9bdaf4959..6268c761d 100644 --- a/src/ast/rewriter/poly_rewriter.h +++ b/src/ast/rewriter/poly_rewriter.h @@ -26,8 +26,6 @@ Notes: template class poly_rewriter : public Config { -public: - static char const * g_ste_blowup_msg; protected: typedef typename Config::numeral numeral; sort * m_curr_sort; diff --git a/src/ast/rewriter/poly_rewriter_def.h b/src/ast/rewriter/poly_rewriter_def.h index 036221f96..0a00a7199 100644 --- a/src/ast/rewriter/poly_rewriter_def.h +++ b/src/ast/rewriter/poly_rewriter_def.h @@ -22,9 +22,6 @@ Notes: #include"ast_ll_pp.h" #include"ast_smt2_pp.h" -template -char const * poly_rewriter::g_ste_blowup_msg = "sum of monomials blowup"; - template void poly_rewriter::updt_params(params_ref const & _p) { @@ -356,7 +353,7 @@ br_status poly_rewriter::mk_nflat_mul_core(unsigned num_args, expr * con TRACE("som", for (unsigned i = 0; i < it.size(); i++) tout << it[i] << " "; tout << "\n";); if (sum.size() > m_som_blowup) - throw rewriter_exception(g_ste_blowup_msg); + throw rewriter_exception("sum of monomials blowup"); m_args.reset(); for (unsigned i = 0; i < num_args; i++) { expr * const * v = sums[i]; diff --git a/src/smt/database.h b/src/smt/database.h index 1975fe3c3..69843f434 100644 --- a/src/smt/database.h +++ b/src/smt/database.h @@ -1,4 +1,4 @@ -static char const * g_pattern_database = +static char const g_pattern_database[] = "(benchmark patterns \n" " :status unknown \n" " :logic ALL \n" diff --git a/src/util/memory_manager.cpp b/src/util/memory_manager.cpp index 45088d5d4..5f56ded98 100644 --- a/src/util/memory_manager.cpp +++ b/src/util/memory_manager.cpp @@ -60,7 +60,7 @@ static void throw_out_of_memory() { } #ifdef PROFILE_MEMORY -unsigned g_synch_counter = 0; +static unsigned g_synch_counter = 0; class mem_usage_report { public: ~mem_usage_report() { diff --git a/src/util/util.cpp b/src/util/util.cpp index eb9acb385..c4b729adb 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -19,7 +19,7 @@ Revision History: #include"util.h" -unsigned g_verbosity_level = 0; +static unsigned g_verbosity_level = 0; void set_verbosity_level(unsigned lvl) { g_verbosity_level = lvl; @@ -40,7 +40,7 @@ std::ostream& verbose_stream() { } -void (*g_fatal_error_handler)(int) = 0; +static void (*g_fatal_error_handler)(int) = 0; void fatal_error(int error_code) { if (g_fatal_error_handler) { From 1e30fd2c65da1d3293a19ef2bef55eab80eefc5d Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 22 Feb 2015 11:38:46 +0000 Subject: [PATCH 570/646] Hide non-exported symbols when compiling with gcc/clang. I get a 17% reduction in the size of libz3.so on linux 32 bits, plus a 0.5-1% speedup when using the API. Signed-off-by: Nuno Lopes --- scripts/mk_util.py | 2 +- src/api/api_ast.cpp | 8 ++++---- src/api/api_context.cpp | 6 +++--- src/api/api_model.cpp | 2 +- src/api/api_quant.cpp | 2 +- src/api/api_solver_old.cpp | 2 +- src/api/z3.h | 4 ++++ 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ae91cd8bd..a3eed360c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1782,7 +1782,7 @@ def mk_config(): FOCI2 = False if GIT_HASH: CPPFLAGS = '%s -DZ3GITHASH=%s' % (CPPFLAGS, GIT_HASH) - CXXFLAGS = '%s -c' % CXXFLAGS + CXXFLAGS = '%s -fvisibility=hidden -c' % CXXFLAGS HAS_OMP = test_openmp(CXX) if HAS_OMP: CXXFLAGS = '%s -fopenmp -mfpmath=sse' % CXXFLAGS diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index b9c6230b7..20ef9ba7f 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -300,7 +300,7 @@ extern "C" { Z3_CATCH_RETURN(-1); } - char const * Z3_API Z3_get_symbol_string(Z3_context c, Z3_symbol s) { + Z3_API char const * Z3_get_symbol_string(Z3_context c, Z3_symbol s) { Z3_TRY; LOG_Z3_get_symbol_string(c, s); RESET_ERROR_CODE(); @@ -823,7 +823,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - char const * Z3_API Z3_ast_to_string(Z3_context c, Z3_ast a) { + Z3_API char const * Z3_ast_to_string(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_ast_to_string(c, a); RESET_ERROR_CODE(); @@ -866,11 +866,11 @@ extern "C" { Z3_CATCH_RETURN(0); } - char const * Z3_API Z3_sort_to_string(Z3_context c, Z3_sort s) { + Z3_API char const * Z3_sort_to_string(Z3_context c, Z3_sort s) { return Z3_ast_to_string(c, reinterpret_cast(s)); } - char const * Z3_API Z3_func_decl_to_string(Z3_context c, Z3_func_decl f) { + Z3_API char const * Z3_func_decl_to_string(Z3_context c, Z3_func_decl f) { return Z3_ast_to_string(c, reinterpret_cast(f)); } diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 3408cdf3c..49fa10d94 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -548,12 +548,12 @@ extern "C" { } } - char const * Z3_API Z3_get_error_msg(Z3_error_code err) { + Z3_API char const * 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) { + Z3_API char const * 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); } @@ -577,7 +577,7 @@ extern "C" { }; -ast_manager & Z3_API Z3_get_manager(__in Z3_context c) { +Z3_API ast_manager& Z3_get_manager(__in Z3_context c) { return mk_c(c)->m(); } diff --git a/src/api/api_model.cpp b/src/api/api_model.cpp index f0c31d800..0ae1a9948 100644 --- a/src/api/api_model.cpp +++ b/src/api/api_model.cpp @@ -651,7 +651,7 @@ extern "C" { Z3_CATCH_RETURN(Z3_FALSE); } - char const * Z3_API Z3_model_to_string(Z3_context c, Z3_model m) { + Z3_API char const * Z3_model_to_string(Z3_context c, Z3_model m) { Z3_TRY; LOG_Z3_model_to_string(c, m); RESET_ERROR_CODE(); diff --git a/src/api/api_quant.cpp b/src/api/api_quant.cpp index 4170852a9..727005186 100644 --- a/src/api/api_quant.cpp +++ b/src/api/api_quant.cpp @@ -507,7 +507,7 @@ extern "C" { return (Z3_ast)(p); } - char const * Z3_API Z3_pattern_to_string(Z3_context c, Z3_pattern p) { + Z3_API char const * Z3_pattern_to_string(Z3_context c, Z3_pattern p) { return Z3_ast_to_string(c, reinterpret_cast(p)); } diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index b81fb2f2c..7e994a0e2 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -297,7 +297,7 @@ extern "C" { Z3_CATCH; } - char const * Z3_API Z3_context_to_string(Z3_context c) { + Z3_API char const * Z3_context_to_string(Z3_context c) { Z3_TRY; LOG_Z3_context_to_string(c); RESET_ERROR_CODE(); diff --git a/src/api/z3.h b/src/api/z3.h index bb7611030..47e3a1fe1 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -21,6 +21,10 @@ Notes: #ifndef _Z3__H_ #define _Z3__H_ +#ifdef __GNUC__ +# define Z3_API __attribute__ ((visibility ("default"))) +#endif + #include #include"z3_macros.h" #include"z3_api.h" From a106b4125ae9ab1f92c8d583bf73b6f178b1c2b7 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 22 Feb 2015 11:57:40 +0000 Subject: [PATCH 571/646] move definition of Z3_API to the right file Signed-off-by: Nuno Lopes --- src/api/z3.h | 4 ---- src/api/z3_macros.h | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/z3.h b/src/api/z3.h index 47e3a1fe1..bb7611030 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -21,10 +21,6 @@ Notes: #ifndef _Z3__H_ #define _Z3__H_ -#ifdef __GNUC__ -# define Z3_API __attribute__ ((visibility ("default"))) -#endif - #include #include"z3_macros.h" #include"z3_api.h" diff --git a/src/api/z3_macros.h b/src/api/z3_macros.h index a4a0cb4be..7a0b6857c 100644 --- a/src/api/z3_macros.h +++ b/src/api/z3_macros.h @@ -35,7 +35,11 @@ #endif #ifndef Z3_API -#define Z3_API +# ifdef __GNUC__ +# define Z3_API __attribute__ ((visibility ("default"))) +# else +# define Z3_API +# endif #endif #ifndef DEFINE_TYPE From 8ea7a1905f493bdd9875eb386dfd5098126e39c5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 22 Feb 2015 10:16:38 -0800 Subject: [PATCH 572/646] reset scope on reset, codeplex issue 183 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index f5937955d..0c60d876b 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1185,6 +1185,7 @@ void cmd_context::reset(bool finalize) { restore_assertions(0); if (m_solver) m_solver = 0; + m_scopes.reset(); m_pp_env = 0; m_dt_eh = 0; if (m_manager) { From 0d9f949ab254f0e004bc70c698f760500eb19e08 Mon Sep 17 00:00:00 2001 From: nikolajbjorner Date: Mon, 23 Feb 2015 10:28:32 -0800 Subject: [PATCH 573/646] Fix memory smash on double free of clauses Signed-off-by: nikolajbjorner --- src/sat/sat_clause.cpp | 2 +- src/sat/sat_elim_eqs.cpp | 5 +++++ src/sat/sat_integrity_checker.cpp | 19 +++++++++++++++++++ src/sat/sat_integrity_checker.h | 1 + src/sat/sat_simplifier.cpp | 1 + src/sat/sat_solver.cpp | 5 +++++ 6 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/sat/sat_clause.cpp b/src/sat/sat_clause.cpp index facd2897d..6314d6fad 100644 --- a/src/sat/sat_clause.cpp +++ b/src/sat/sat_clause.cpp @@ -174,7 +174,7 @@ namespace sat { } void clause_allocator::del_clause(clause * cls) { - TRACE("sat", tout << "delete: " << cls->id() << " " << cls << "\n";); + TRACE("sat", tout << "delete: " << cls->id() << " " << cls << " " << *cls << "\n";); m_id_gen.recycle(cls->id()); size_t size = clause::get_obj_size(cls->m_capacity); #ifdef _AMD64_ diff --git a/src/sat/sat_elim_eqs.cpp b/src/sat/sat_elim_eqs.cpp index a2c1c7871..6a7ca6280 100644 --- a/src/sat/sat_elim_eqs.cpp +++ b/src/sat/sat_elim_eqs.cpp @@ -128,6 +128,11 @@ namespace sat { if (j == 0) { // empty clause m_solver.set_conflict(justification()); + for (; it != end; ++it) { + *it2 = *it; + it2++; + } + cs.set_end(it2); return; } TRACE("elim_eqs", tout << "after removing duplicates: " << c << " j: " << j << "\n";); diff --git a/src/sat/sat_integrity_checker.cpp b/src/sat/sat_integrity_checker.cpp index b5d9f1550..d0052b8c2 100644 --- a/src/sat/sat_integrity_checker.cpp +++ b/src/sat/sat_integrity_checker.cpp @@ -207,6 +207,24 @@ namespace sat { } return true; } + + bool integrity_checker::check_disjoint_clauses() const { + uint_set ids; + clause_vector::const_iterator it = s.m_clauses.begin(); + clause_vector::const_iterator end = s.m_clauses.end(); + for (; it != end; ++it) { + ids.insert((*it)->id()); + } + it = s.m_learned.begin(); + end = s.m_learned.end(); + for (; it != end; ++it) { + if (ids.contains((*it)->id())) { + TRACE("sat", tout << "Repeated clause: " << (*it)->id() << "\n";); + return false; + } + } + return true; + } bool integrity_checker::operator()() const { if (s.inconsistent()) @@ -216,6 +234,7 @@ namespace sat { SASSERT(check_watches()); SASSERT(check_bool_vars()); SASSERT(check_reinit_stack()); + SASSERT(check_disjoint_clauses()); return true; } }; diff --git a/src/sat/sat_integrity_checker.h b/src/sat/sat_integrity_checker.h index fc3da8c5d..8aa9340c0 100644 --- a/src/sat/sat_integrity_checker.h +++ b/src/sat/sat_integrity_checker.h @@ -36,6 +36,7 @@ namespace sat { bool check_bool_vars() const; bool check_watches() const; bool check_reinit_stack() const; + bool check_disjoint_clauses() const; bool operator()() const; }; }; diff --git a/src/sat/sat_simplifier.cpp b/src/sat/sat_simplifier.cpp index 219b9f278..e67043c04 100644 --- a/src/sat/sat_simplifier.cpp +++ b/src/sat/sat_simplifier.cpp @@ -227,6 +227,7 @@ namespace sat { } void simplifier::cleanup_clauses(clause_vector & cs, bool learned, bool vars_eliminated, bool in_use_lists) { + TRACE("sat", tout << "cleanup_clauses\n";); clause_vector::iterator it = cs.begin(); clause_vector::iterator it2 = it; clause_vector::iterator end = cs.end(); diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index f898130af..5c0d60260 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -50,7 +50,10 @@ namespace sat { } solver::~solver() { + SASSERT(check_invariant()); + TRACE("sat", tout << "Delete clauses\n";); del_clauses(m_clauses.begin(), m_clauses.end()); + TRACE("sat", tout << "Delete learned\n";); del_clauses(m_learned.begin(), m_learned.end()); } @@ -1121,6 +1124,7 @@ namespace sat { \brief GC (the second) half of the clauses in the database. */ void solver::gc_half(char const * st_name) { + TRACE("sat", tout << "gc\n";); unsigned sz = m_learned.size(); unsigned new_sz = sz/2; unsigned j = new_sz; @@ -1145,6 +1149,7 @@ namespace sat { \brief Use gc based on dynamic psm. Clauses are initially frozen. */ void solver::gc_dyn_psm() { + TRACE("sat", tout << "gc\n";); // To do gc at scope_lvl() > 0, I will need to use the reinitialization stack, or live with the fact // that I may miss some propagations for reactivated clauses. SASSERT(scope_lvl() == 0); From a51aed01331839250c9a8aa6466ab204b7a59a80 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 24 Feb 2015 21:26:25 +0000 Subject: [PATCH 574/646] Fixed bug in constant propagation Signed-off-by: Christoph M. Wintersteiger --- src/smt/asserted_formulas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 1acfcdf57..faf5ce0ef 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -603,7 +603,7 @@ void asserted_formulas::propagate_values() { proof_ref_vector new_prs1(m_manager); expr_ref_vector new_exprs2(m_manager); proof_ref_vector new_prs2(m_manager); - unsigned i = m_asserted_qhead; + unsigned i = 0; unsigned sz = m_asserted_formulas.size(); for (; i < sz; i++) { expr * n = m_asserted_formulas.get(i); From 64e2011d425cc3493468eba862f309815263538b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 24 Feb 2015 17:34:38 -0800 Subject: [PATCH 575/646] fix crash in explanation generation. Codeplex issue 181 Signed-off-by: Nikolaj Bjorner --- src/muz/base/dl_rule.cpp | 5 +++-- src/muz/rel/dl_mk_explanations.cpp | 2 +- src/muz/rel/dl_relation_manager.cpp | 1 + src/muz/rel/karr_relation.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/muz/base/dl_rule.cpp b/src/muz/base/dl_rule.cpp index 017bac724..1849903c5 100644 --- a/src/muz/base/dl_rule.cpp +++ b/src/muz/base/dl_rule.cpp @@ -884,14 +884,15 @@ namespace datalog { struct uninterpreted_function_finder_proc { ast_manager& m; datatype_util m_dt; + dl_decl_util m_dl; bool m_found; func_decl* m_func; uninterpreted_function_finder_proc(ast_manager& m): - m(m), m_dt(m), m_found(false), m_func(0) {} + m(m), m_dt(m), m_dl(m), m_found(false), m_func(0) {} void operator()(var * n) { } void operator()(quantifier * n) { } void operator()(app * n) { - if (is_uninterp(n)) { + if (is_uninterp(n) && !m_dl.is_rule_sort(n->get_decl()->get_range())) { m_found = true; m_func = n->get_decl(); } diff --git a/src/muz/rel/dl_mk_explanations.cpp b/src/muz/rel/dl_mk_explanations.cpp index 60a10190a..7344f187c 100644 --- a/src/muz/rel/dl_mk_explanations.cpp +++ b/src/muz/rel/dl_mk_explanations.cpp @@ -828,7 +828,7 @@ namespace datalog { SASSERT(&expl_singleton->get_plugin()==m_er_plugin); m_e_fact_relation = static_cast(expl_singleton); } - func_decl_set const& predicates = m_context.get_predicates(); + func_decl_set predicates(m_context.get_predicates()); decl_set::iterator it = predicates.begin(); decl_set::iterator end = predicates.end(); for (; it!=end; ++it) { diff --git a/src/muz/rel/dl_relation_manager.cpp b/src/muz/rel/dl_relation_manager.cpp index 9421b26df..7fcca9ce2 100644 --- a/src/muz/rel/dl_relation_manager.cpp +++ b/src/muz/rel/dl_relation_manager.cpp @@ -734,6 +734,7 @@ namespace datalog { relation_union_fn * relation_manager::mk_union_fn(const relation_base & tgt, const relation_base & src, const relation_base * delta) { + TRACE("dl", tout << src.get_plugin().get_name() << " " << tgt.get_plugin().get_name() << "\n";); relation_union_fn * res = tgt.get_plugin().mk_union_fn(tgt, src, delta); if(!res && &tgt.get_plugin()!=&src.get_plugin()) { res = src.get_plugin().mk_union_fn(tgt, src, delta); diff --git a/src/muz/rel/karr_relation.h b/src/muz/rel/karr_relation.h index 00a92748a..72448f026 100644 --- a/src/muz/rel/karr_relation.h +++ b/src/muz/rel/karr_relation.h @@ -45,7 +45,7 @@ namespace datalog { {} virtual bool can_handle_signature(const relation_signature & sig) { - return true; + return get_manager().get_context().karr(); } static symbol get_name() { return symbol("karr_relation"); } From 8d303a09b5dc156fa67508c67559225b45510ed6 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 25 Feb 2015 13:10:29 +0000 Subject: [PATCH 576/646] Compile Z3 with link-time optimizations on Windows, yielding a 2-3% speedup Signed-off-by: Nuno Lopes --- scripts/mk_util.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a3eed360c..fbec2cf06 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1695,7 +1695,7 @@ def mk_config(): 'OBJ_EXT=.obj\n' 'LIB_EXT=.lib\n' 'AR=lib\n' - 'AR_FLAGS=/nologo\n' + 'AR_FLAGS=/nologo /LTCG\n' 'AR_OUTFLAG=/OUT:\n' 'EXE_EXT=.exe\n' 'LINK=cl\n' @@ -1709,36 +1709,36 @@ def mk_config(): extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) if DEBUG_MODE: config.write( - 'LINK_FLAGS=/nologo /MDd\n' - 'SLINK_FLAGS=/nologo /LDd\n') + 'LINK_FLAGS=/nologo /MDd /LTCG\n' + 'SLINK_FLAGS=/nologo /LDd /LTCG\n') if not VS_X64: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: # Windows Release mode config.write( - 'LINK_FLAGS=/nologo /MD\n' - 'SLINK_FLAGS=/nologo /LD\n') + 'LINK_FLAGS=/nologo /MD /LTCG\n' + 'SLINK_FLAGS=/nologo /LD /LTCG\n') if TRACE: extra_opt = '%s /D _TRACE' % extra_opt if not VS_X64: config.write( - 'CXXFLAGS=/nologo /c /Zi /openmp /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) + 'CXXFLAGS=/nologo /c /GL /Zi /openmp /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' 'SLINK_EXTRA_FLAGS=/link /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n') From 71d31c126730e13b00cc87806564f9ed40b10ab3 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Fri, 27 Feb 2015 11:48:14 +0000 Subject: [PATCH 577/646] minor optimization to reset() methods in smt::ketnel and smt::quantifier_manager Signed-off-by: Nuno Lopes --- src/smt/smt_kernel.cpp | 4 ++-- src/smt/smt_quantifier.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/smt/smt_kernel.cpp b/src/smt/smt_kernel.cpp index d78b82cc6..a4e97380b 100644 --- a/src/smt/smt_kernel.cpp +++ b/src/smt/smt_kernel.cpp @@ -236,8 +236,8 @@ namespace smt { params_ref ps = m_imp->params(); #pragma omp critical (smt_kernel) { - dealloc(m_imp); - m_imp = alloc(imp, _m, fps, ps); + m_imp->~imp(); + m_imp = new (m_imp) imp(_m, fps, ps); } } diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index b76fb6c74..f824cb3f1 100644 --- a/src/smt/smt_quantifier.cpp +++ b/src/smt/smt_quantifier.cpp @@ -361,8 +361,8 @@ namespace smt { context & ctx = m_imp->m_context; smt_params & p = m_imp->m_params; quantifier_manager_plugin * plugin = m_imp->m_plugin->mk_fresh(); - dealloc(m_imp); - m_imp = alloc(imp, *this, ctx, p, plugin); + m_imp->~imp(); + m_imp = new (m_imp) imp(*this, ctx, p, plugin); plugin->set_manager(*this); } } From 3ca3c948cf3e16a3e4dd8ce50811615eb2a8f18a Mon Sep 17 00:00:00 2001 From: nikolajbjorner Date: Fri, 27 Feb 2015 11:08:49 -0800 Subject: [PATCH 578/646] add bit-vector extract shortcuts to C++ API Signed-off-by: nikolajbjorner --- examples/c++/example.cpp | 10 ++++++++++ src/api/c++/z3++.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 0d8a3ceb3..e48c23905 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -975,6 +975,15 @@ void substitute_example() { std::cout << new_f << std::endl; } +void extract_example() { + std::cout << "extract example\n"; + context c; + expr x(c); + x = c.constant("x", c.bv_sort(32)); + expr y = x.extract(21, 10); + std::cout << y << " " << y.hi() << " " << y.lo() << "\n"; +} + int main() { try { demorgan(); std::cout << "\n"; @@ -1013,6 +1022,7 @@ int main() { expr_vector_example(); std::cout << "\n"; exists_expr_vector_example(); std::cout << "\n"; substitute_example(); std::cout << "\n"; + extract_example(); std::cout << "\n"; std::cout << "done\n"; } catch (exception & ex) { diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 7380e52f1..f43ba83e5 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -866,6 +866,9 @@ namespace z3 { friend expr operator|(int a, expr const & b) { return b.ctx().num_val(a, b.get_sort()) | b; } friend expr operator~(expr const & a) { Z3_ast r = Z3_mk_bvnot(a.ctx(), a); return expr(a.ctx(), r); } + expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); return expr(ctx(), r); } + unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast(Z3_get_decl_int_parameter(ctx(), decl(), 1)); } + unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast(Z3_get_decl_int_parameter(ctx(), decl(), 0)); } /** \brief Return a simplified version of this expression. From 8029e31ddd5240f4fa78679e8a4de4cab254f0a1 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sat, 28 Feb 2015 17:31:50 +0000 Subject: [PATCH 579/646] add compiler attributes to allocation functions Signed-off-by: Nuno Lopes --- src/util/memory_manager.cpp | 2 ++ src/util/memory_manager.h | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/util/memory_manager.cpp b/src/util/memory_manager.cpp index 5f56ded98..354a11aeb 100644 --- a/src/util/memory_manager.cpp +++ b/src/util/memory_manager.cpp @@ -173,6 +173,7 @@ void memory::display_i_max_usage(std::ostream & os) { << "\n"; } +#if _DEBUG void memory::deallocate(char const * file, int line, void * p) { deallocate(p); TRACE_CODE(if (!g_finalizing) TRACE("memory", tout << "dealloc " << std::hex << p << std::dec << " " << file << ":" << line << "\n";);); @@ -183,6 +184,7 @@ void * memory::allocate(char const* file, int line, char const* obj, size_t s) { TRACE("memory", tout << "alloc " << std::hex << r << std::dec << " " << file << ":" << line << " " << obj << " " << s << "\n";); return r; } +#endif #if defined(_WINDOWS) || defined(_USE_THREAD_LOCAL) // ================================== diff --git a/src/util/memory_manager.h b/src/util/memory_manager.h index 2cabc70b7..f1ce37ca6 100644 --- a/src/util/memory_manager.h +++ b/src/util/memory_manager.h @@ -23,6 +23,24 @@ Revision History: #include #include"z3_exception.h" +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#ifdef __GNUC__ +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 || __has_builtin(returns_nonnull) +# define GCC_RET_NON_NULL __attribute__((returns_nonnull)) +# else +# define GCC_RET_NON_NULL +# endif +# define ALLOC_ATTR __attribute__((malloc)) GCC_RET_NON_NULL +#elif defined(_WINDOWS) +# define ALLOC_ATTR __declspec(restrict) +#else +# define ALLOC_ATTR +#endif + + class out_of_memory_error : public z3_error { public: out_of_memory_error(); @@ -39,9 +57,11 @@ public: static void display_max_usage(std::ostream& os); static void display_i_max_usage(std::ostream& os); static void deallocate(void* p); - static void* allocate(size_t s); + static void* allocate(size_t s) ALLOC_ATTR; +#if _DEBUG static void deallocate(char const* file, int line, void* p); - static void* allocate(char const* file, int line, char const* obj, size_t s); + static void* allocate(char const* file, int line, char const* obj, size_t s) ALLOC_ATTR; +#endif static unsigned long long get_allocation_size(); static unsigned long long get_max_used_memory(); // temporary hack to avoid out-of-memory crash in z3.exe @@ -74,6 +94,9 @@ void dealloc(T * ptr) { #endif +template +T * alloc_vect(unsigned sz) ALLOC_ATTR; + template T * alloc_vect(unsigned sz) { T * r = static_cast(memory::allocate(sizeof(T) * sz)); From 8bcd6edd08af29aca856f455fddbd08486c0b530 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 1 Mar 2015 15:19:57 -0800 Subject: [PATCH 580/646] temporary build fix Signed-off-by: Nikolaj Bjorner --- src/util/memory_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/memory_manager.h b/src/util/memory_manager.h index f1ce37ca6..aaf8b2825 100644 --- a/src/util/memory_manager.h +++ b/src/util/memory_manager.h @@ -34,7 +34,7 @@ Revision History: # define GCC_RET_NON_NULL # endif # define ALLOC_ATTR __attribute__((malloc)) GCC_RET_NON_NULL -#elif defined(_WINDOWS) +#elif defined(_WINDOWS) && (VisualStudioVersion >= 13) # define ALLOC_ATTR __declspec(restrict) #else # define ALLOC_ATTR From e64760abbdfc5545fad13fb198dc58aae55bbd6d Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 2 Mar 2015 09:18:15 +0000 Subject: [PATCH 581/646] fix the build with VS Signed-off-by: Nuno Lopes --- src/util/memory_manager.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/memory_manager.h b/src/util/memory_manager.h index aaf8b2825..49472ef28 100644 --- a/src/util/memory_manager.h +++ b/src/util/memory_manager.h @@ -34,7 +34,7 @@ Revision History: # define GCC_RET_NON_NULL # endif # define ALLOC_ATTR __attribute__((malloc)) GCC_RET_NON_NULL -#elif defined(_WINDOWS) && (VisualStudioVersion >= 13) +#elif defined(_WINDOWS) # define ALLOC_ATTR __declspec(restrict) #else # define ALLOC_ATTR @@ -57,10 +57,10 @@ public: static void display_max_usage(std::ostream& os); static void display_i_max_usage(std::ostream& os); static void deallocate(void* p); - static void* allocate(size_t s) ALLOC_ATTR; + static ALLOC_ATTR void* allocate(size_t s); #if _DEBUG static void deallocate(char const* file, int line, void* p); - static void* allocate(char const* file, int line, char const* obj, size_t s) ALLOC_ATTR; + static ALLOC_ATTR void* allocate(char const* file, int line, char const* obj, size_t s); #endif static unsigned long long get_allocation_size(); static unsigned long long get_max_used_memory(); @@ -95,7 +95,7 @@ void dealloc(T * ptr) { #endif template -T * alloc_vect(unsigned sz) ALLOC_ATTR; +ALLOC_ATTR T * alloc_vect(unsigned sz); template T * alloc_vect(unsigned sz) { From 89c43676d5719b70ffa4fbfe334dc826f43239f0 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 2 Mar 2015 09:50:35 +0000 Subject: [PATCH 582/646] save memory in the sat solver to tentatively speed things up. I get a slight speedup on my benchmarks. There's still one extra sign extend, which will be removed in a follow-up patch Signed-off-by: Nuno Lopes --- src/sat/sat_solver.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index 2a64c9cd5..72f1d5770 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -89,7 +89,7 @@ namespace sat { clause_vector m_learned; unsigned m_num_frozen; vector m_watches; - svector m_assignment; + char_vector m_assignment; svector m_justification; svector m_decision; svector m_mark; @@ -200,8 +200,8 @@ namespace sat { bool is_external(bool_var v) const { return m_external[v] != 0; } bool was_eliminated(bool_var v) const { return m_eliminated[v] != 0; } unsigned scope_lvl() const { return m_scope_lvl; } - lbool value(literal l) const { return m_assignment[l.index()]; } - lbool value(bool_var v) const { return m_assignment[literal(v, false).index()]; } + lbool value(literal l) const { return static_cast(m_assignment[l.index()]); } + lbool value(bool_var v) const { return static_cast(m_assignment[literal(v, false).index()]); } unsigned lvl(bool_var v) const { return m_level[v]; } unsigned lvl(literal l) const { return m_level[l.var()]; } void assign(literal l, justification j) { From dd2c1796631b0bae208ebb7b59782360eb63e692 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 2 Mar 2015 15:05:38 +0000 Subject: [PATCH 583/646] Fix warnings during compilation with MSVC due to /LTCG Signed-off-by: Nuno Lopes --- scripts/mk_util.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index fbec2cf06..8c1f129d5 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1709,39 +1709,39 @@ def mk_config(): extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) if DEBUG_MODE: config.write( - 'LINK_FLAGS=/nologo /MDd /LTCG\n' - 'SLINK_FLAGS=/nologo /LDd /LTCG\n') + 'LINK_FLAGS=/nologo /MDd\n' + 'SLINK_FLAGS=/nologo /LDd\n') if not VS_X64: config.write( 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' + 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' % extra_opt) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' + 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: # Windows Release mode config.write( - 'LINK_FLAGS=/nologo /MD /LTCG\n' - 'SLINK_FLAGS=/nologo /LD /LTCG\n') + 'LINK_FLAGS=/nologo /MD\n' + 'SLINK_FLAGS=/nologo /LD\n') if TRACE: extra_opt = '%s /D _TRACE' % extra_opt if not VS_X64: config.write( 'CXXFLAGS=/nologo /c /GL /Zi /openmp /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( - 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' - 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') + 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' + 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP\n' % extra_opt) config.write( - 'LINK_EXTRA_FLAGS=/link /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' - 'SLINK_EXTRA_FLAGS=/link /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n') + 'LINK_EXTRA_FLAGS=/link /LTCG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' + 'SLINK_EXTRA_FLAGS=/link /LTCG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n') # End of Windows VS config.mk if is_verbose(): From 71f2d358efc5cd3c22b898daf5906e63b320d71e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 2 Mar 2015 17:30:41 +0000 Subject: [PATCH 584/646] Bugfix in windows dist scripts Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_win_dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 3a95fb730..33d7a3eab 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -39,7 +39,7 @@ def mk_dir(d): os.makedirs(d) def set_build_dir(path): - global BUILD_DIR + global BUILD_DIR, BUILD_X86_DIR, BUILD_X64_DIR BUILD_DIR = path BUILD_X86_DIR = os.path.join(path, 'x86') BUILD_X64_DIR = os.path.join(path, 'x64') From 1f8119f6017d4eb911e3ae29bca645104f338ff8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 15:14:07 +0000 Subject: [PATCH 585/646] Bugfix for the Java API. Thanks to codeplex user susmitj for reporting this problem! Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 2 +- scripts/update_api.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index d93a13129..8e4df94ba 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,7 +11,7 @@ Version 4.4 - Upgrade: This release includes a brand new OCaml/ML API that is much better integrated with the build system, and hopefully also easier to use than the previous one. -- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, and Codeplex users rsas, clockish, Heizmann. +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, and Codeplex users rsas, clockish, Heizmann, susmitj. Version 4.3.2 diff --git a/scripts/update_api.py b/scripts/update_api.py index 889044d1f..2e3963319 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -642,6 +642,7 @@ def mk_java(): java_wrapper.write('#ifdef __cplusplus\n') java_wrapper.write('extern "C" {\n') java_wrapper.write('#endif\n\n') + java_wrapper.write('#ifdef __GNUC__\n#if __GNUC__ >= 4\n#define DLL_VIS __attribute__ ((visibility ("default")))\n#else\n#define DLL_VIS\n#endif\n#endif\n\n') java_wrapper.write('#if defined(_M_X64) || defined(_AMD64_)\n\n') java_wrapper.write('#define GETLONGAELEMS(T,OLD,NEW) \\\n') java_wrapper.write(' T * NEW = (OLD == 0) ? 0 : (T*) jenv->GetLongArrayElements(OLD, NULL);\n') @@ -688,13 +689,13 @@ def mk_java(): java_wrapper.write(' // upon errors, but the actual error handling is done by throwing exceptions in the\n') java_wrapper.write(' // wrappers below.\n') java_wrapper.write('}\n\n') - java_wrapper.write('JNIEXPORT void JNICALL Java_%s_Native_setInternalErrorHandler(JNIEnv * jenv, jclass cls, jlong a0)\n' % pkg_str) + java_wrapper.write('DLL_VIS JNIEXPORT void JNICALL Java_%s_Native_setInternalErrorHandler(JNIEnv * jenv, jclass cls, jlong a0)\n' % pkg_str) java_wrapper.write('{\n') java_wrapper.write(' Z3_set_error_handler((Z3_context)a0, Z3JavaErrorHandler);\n') java_wrapper.write('}\n\n') java_wrapper.write('') for name, result, params in _dotnet_decls: - java_wrapper.write('JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) + java_wrapper.write('DLL_VIS JNIEXPORT %s JNICALL Java_%s_Native_INTERNAL%s(JNIEnv * jenv, jclass cls' % (type2javaw(result), pkg_str, java_method_name(name))) i = 0; for param in params: java_wrapper.write(', ') From ec4a07318e700b2ee434e4aa118919830879ec8a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 15:19:15 +0000 Subject: [PATCH 586/646] Bugfix for the Java API on Windows Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 2e3963319..93800237e 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -642,7 +642,7 @@ def mk_java(): java_wrapper.write('#ifdef __cplusplus\n') java_wrapper.write('extern "C" {\n') java_wrapper.write('#endif\n\n') - java_wrapper.write('#ifdef __GNUC__\n#if __GNUC__ >= 4\n#define DLL_VIS __attribute__ ((visibility ("default")))\n#else\n#define DLL_VIS\n#endif\n#endif\n\n') + java_wrapper.write('#ifdef __GNUC__\n#if __GNUC__ >= 4\n#define DLL_VIS __attribute__ ((visibility ("default")))\n#else\n#define DLL_VIS\n#endif\n#else\n#define DLL_VIS\n#endif\n\n') java_wrapper.write('#if defined(_M_X64) || defined(_AMD64_)\n\n') java_wrapper.write('#define GETLONGAELEMS(T,OLD,NEW) \\\n') java_wrapper.write(' T * NEW = (OLD == 0) ? 0 : (T*) jenv->GetLongArrayElements(OLD, NULL);\n') From 8d11c431b76adf8d880554ef27aed24f1f9be1a0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 17:44:53 +0000 Subject: [PATCH 587/646] Bugfix for the OCaml bindings on Windows Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8c1f129d5..0f4fdb216 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1376,6 +1376,7 @@ class MLComponent(Component): sub_dir = os.path.join('api', 'ml') mk_dir(os.path.join(BUILD_DIR, sub_dir)) api_src = get_component(API_COMPONENT).to_src_dir + out.write('CXXFLAGS_OCAML=$(CXXFLAGS:/GL=)\n') # remove /GL; the ocaml tools don't like it. for f in filter(lambda f: f.endswith('.ml'), os.listdir(self.src_dir)): out.write('%s: %s\n' % (os.path.join(sub_dir,f),os.path.join(src_dir,f))) str = '\t%s %s %s\n' % (CP_CMD,os.path.join(src_dir,f),os.path.join(sub_dir,f)) @@ -1412,7 +1413,7 @@ class MLComponent(Component): (os.path.join(sub_dir, 'z3native_stubs$(OBJ_EXT)'), os.path.join(sub_dir, 'z3native_stubs.c'), get_component(Z3_DLL_COMPONENT).dll_name+'$(SO_EXT)')); - out.write('\t$(CC) $(CXXFLAGS) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % + out.write('\t$(CC) $(CXXFLAGS_OCAML) -I %s -I %s %s $(CXX_OUT_FLAG)%s$(OBJ_EXT)\n' % (OCAML_LIB, api_src, os.path.join(sub_dir, 'z3native_stubs.c'), os.path.join(sub_dir, 'z3native_stubs'))) out.write('%s: %s %s %s$(SO_EXT)' % ( From 858ce1158d6b8708408a954bb08dba70cf1702d2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 18:30:06 +0000 Subject: [PATCH 588/646] Bugfix in model translation (ast_manager mismatch after par-or). Thanks to stackoverflow user user297886 for reporting this issue. http://stackoverflow.com/questions/28852722/segmentation-fault-while-using-par-or-tactic Signed-off-by: Christoph M. Wintersteiger --- src/model/func_interp.cpp | 4 ++-- src/model/model.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/model/func_interp.cpp b/src/model/func_interp.cpp index ae4c657bd..9110014bf 100644 --- a/src/model/func_interp.cpp +++ b/src/model/func_interp.cpp @@ -276,8 +276,8 @@ expr * func_interp::get_interp() const { return r; } -func_interp * func_interp::translate(ast_translation & translator) const { - func_interp * new_fi = alloc(func_interp, m_manager, m_arity); +func_interp * func_interp::translate(ast_translation & translator) const { + func_interp * new_fi = alloc(func_interp, translator.to(), m_arity); ptr_vector::const_iterator it = m_entries.begin(); ptr_vector::const_iterator end = m_entries.end(); diff --git a/src/model/model.cpp b/src/model/model.cpp index a6b9695b4..73a39a8eb 100644 --- a/src/model/model.cpp +++ b/src/model/model.cpp @@ -74,6 +74,7 @@ void model::register_decl(func_decl * d, expr * v) { void model::register_decl(func_decl * d, func_interp * fi) { SASSERT(d->get_arity() > 0); + SASSERT(&fi->m() == &m_manager); decl2finterp::obj_map_entry * entry = m_finterp.insert_if_not_there2(d, 0); if (entry->get_data().m_value == 0) { // new entry From 6630994a3d3a5d72c42d63c69da31f7868a82d23 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 18:31:08 +0000 Subject: [PATCH 589/646] + bug reporter Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 8e4df94ba..01f9e687e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,7 +11,7 @@ Version 4.4 - Upgrade: This release includes a brand new OCaml/ML API that is much better integrated with the build system, and hopefully also easier to use than the previous one. -- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, and Codeplex users rsas, clockish, Heizmann, susmitj. +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, Codeplex users rsas, clockish, Heizmann, susmitj, and Stackoverflow users user297886. Version 4.3.2 From 55ca6ce44b2f6963831209528a8b49728c7c58bf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 4 Mar 2015 19:14:57 +0000 Subject: [PATCH 590/646] Resurrected the dack* options. Signed-off-by: Christoph M. Wintersteiger --- src/smt/params/dyn_ack_params.cpp | 22 ++++++++++------------ src/smt/params/dyn_ack_params.h | 6 +++++- src/smt/params/smt_params.cpp | 1 + src/smt/params/smt_params_helper.pyg | 8 +++++++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/smt/params/dyn_ack_params.cpp b/src/smt/params/dyn_ack_params.cpp index 2e94c376d..c559e2b9b 100644 --- a/src/smt/params/dyn_ack_params.cpp +++ b/src/smt/params/dyn_ack_params.cpp @@ -17,16 +17,14 @@ Revision History: --*/ #include"dyn_ack_params.h" +#include"smt_params_helper.hpp" -#if 0 -void dyn_ack_params::register_params(ini_params & p) { - p.register_int_param("dack", 0, 2, reinterpret_cast(m_dack), - "0 - disable dynamic ackermannization, 1 - expand Leibniz's axiom if a congruence is the root of a conflict, 2 - expand Leibniz's axiom if a congruence is used during conflict resolution."); - p.register_bool_param("dack_eq", m_dack_eq, "enable dynamic ackermannization for transtivity of equalities"); - p.register_unsigned_param("dack_threshold", m_dack_threshold, "number of times the congruence rule must be used before Leibniz's axiom is expanded"); - p.register_double_param("dack_factor", m_dack_factor, "number of instance per conflict"); - p.register_unsigned_param("dack_gc", m_dack_gc, "Dynamic ackermannization garbage collection frequency (per conflict)."); - p.register_double_param("dack_gc_inv_decay", m_dack_gc_inv_decay); -} -#endif - +void dyn_ack_params::updt_params(params_ref const & _p) { + smt_params_helper p(_p); + m_dack = static_cast(p.dack()); + m_dack_eq = p.dack_eq(); + m_dack_factor = p.dack_factor(); + m_dack_threshold = p.dack_threshold(); + m_dack_gc = p.dack_gc(); + m_dack_gc_inv_decay = p.dack_gc_inv_decay(); +} \ No newline at end of file diff --git a/src/smt/params/dyn_ack_params.h b/src/smt/params/dyn_ack_params.h index 9f7ce578c..95b5aff8a 100644 --- a/src/smt/params/dyn_ack_params.h +++ b/src/smt/params/dyn_ack_params.h @@ -19,6 +19,8 @@ Revision History: #ifndef _DYN_ACK_PARAMS_H_ #define _DYN_ACK_PARAMS_H_ +#include"params.h" + enum dyn_ack_strategy { DACK_DISABLED, DACK_ROOT, // congruence is the root of the conflict @@ -34,15 +36,17 @@ struct dyn_ack_params { double m_dack_gc_inv_decay; public: - dyn_ack_params(): + dyn_ack_params(params_ref const & p = params_ref()) : m_dack(DACK_ROOT), m_dack_eq(false), m_dack_factor(0.1), m_dack_threshold(10), m_dack_gc(2000), m_dack_gc_inv_decay(0.8) { + updt_params(p); } + void updt_params(params_ref const & _p); }; diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 18619c8ec..2f8d9c1ee 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -46,6 +46,7 @@ void smt_params::updt_local_params(params_ref const & _p) { void smt_params::updt_params(params_ref const & p) { preprocessor_params::updt_params(p); + dyn_ack_params::updt_params(p); qi_params::updt_params(p); theory_arith_params::updt_params(p); theory_bv_params::updt_params(p); diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 869b8cdc4..39818e621 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -45,5 +45,11 @@ def_module_params(module_name='smt', ('arith.int_eq_branch', BOOL, False, 'branching using derived integer equations'), ('arith.ignore_int', BOOL, False, 'treat integer variables as real'), ('array.weak', BOOL, False, 'weak array theory'), - ('array.extensional', BOOL, True, 'extensional array theory') + ('array.extensional', BOOL, True, 'extensional array theory'), + ('dack', UINT, 1, '0 - disable dynamic ackermannization, 1 - expand Leibniz\'s axiom if a congruence is the root of a conflict, 2 - expand Leibniz\'s axiom if a congruence is used during conflict resolution'), + ('dack.eq', BOOL, False, 'enable dynamic ackermannization for transtivity of equalities'), + ('dack.factor', DOUBLE, 0.1, 'number of instance per conflict'), + ('dack.gc', UINT, 2000, 'Dynamic ackermannization garbage collection frequency (per conflict)'), + ('dack.gc_inv_decay', DOUBLE, 0.8, 'Dynamic ackermannization garbage collection decay'), + ('dack.threshold', UINT, 10, ' number of times the congruence rule must be used before Leibniz\'s axiom is expanded') )) From 44e647e72b5e019e245fbaa66e40c68bdde6c939 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 10 Mar 2015 16:53:47 +0000 Subject: [PATCH 591/646] add reallocate() function and use it in bit_vector and vector containers give a speedup of 1-4% Signed-off-by: Nuno Lopes --- src/util/bit_vector.cpp | 10 ++++----- src/util/bit_vector.h | 4 +--- src/util/memory_manager.cpp | 42 +++++++++++++++++++++++++++++++++++++ src/util/memory_manager.h | 1 + src/util/vector.h | 12 +++-------- 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/util/bit_vector.cpp b/src/util/bit_vector.cpp index 1490b9628..c41e4574c 100644 --- a/src/util/bit_vector.cpp +++ b/src/util/bit_vector.cpp @@ -25,13 +25,11 @@ Revision History: #define MK_MASK(_num_bits_) ((1U << _num_bits_) - 1) void bit_vector::expand_to(unsigned new_capacity) { - unsigned * new_data = alloc_svect(unsigned, new_capacity); - memset(new_data, 0, new_capacity * sizeof(unsigned)); - if (m_capacity > 0) { - memcpy(new_data, m_data, m_capacity * sizeof(unsigned)); - dealloc_svect(m_data); + if (m_data) { + m_data = (unsigned*)memory::reallocate(m_data, new_capacity * sizeof(unsigned)); + } else { + m_data = alloc_svect(unsigned, new_capacity); } - m_data = new_data; m_capacity = new_capacity; } diff --git a/src/util/bit_vector.h b/src/util/bit_vector.h index 0ccdeae9e..6738ba0aa 100644 --- a/src/util/bit_vector.h +++ b/src/util/bit_vector.h @@ -87,9 +87,7 @@ public: } ~bit_vector() { - if (m_data) { - dealloc_svect(m_data); - } + dealloc_svect(m_data); } void reset() { diff --git a/src/util/memory_manager.cpp b/src/util/memory_manager.cpp index 354a11aeb..e911ff505 100644 --- a/src/util/memory_manager.cpp +++ b/src/util/memory_manager.cpp @@ -252,6 +252,24 @@ void * memory::allocate(size_t s) { return static_cast(r) + 1; // we return a pointer to the location after the extra field } +void* memory::reallocate(void *p, size_t s) { + size_t *sz_p = reinterpret_cast(p)-1; + size_t sz = *sz_p; + void *real_p = reinterpret_cast(sz_p); + s = s + sizeof(size_t); // we allocate an extra field! + + g_memory_thread_alloc_size += s - sz; + if (g_memory_thread_alloc_size > SYNCH_THRESHOLD) { + synchronize_counters(true); + } + + void *r = realloc(real_p, s); + if (r == 0) + throw_out_of_memory(); + *(static_cast(r)) = s; + return static_cast(r) + 1; // we return a pointer to the location after the extra field +} + #else // ================================== // ================================== @@ -292,5 +310,29 @@ void * memory::allocate(size_t s) { *(static_cast(r)) = s; return static_cast(r) + 1; // we return a pointer to the location after the extra field } + +void* memory::reallocate(void *p, size_t s) { + size_t * sz_p = reinterpret_cast(p) - 1; + size_t sz = *sz_p; + void * real_p = reinterpret_cast(sz_p); + s = s + sizeof(size_t); // we allocate an extra field! + bool out_of_mem = false; + #pragma omp critical (z3_memory_manager) + { + g_memory_alloc_size += s - sz; + if (g_memory_alloc_size > g_memory_max_used_size) + g_memory_max_used_size = g_memory_alloc_size; + if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size) + out_of_mem = true; + } + if (out_of_mem) + throw_out_of_memory(); + + void *r = realloc(real_p, s); + if (r == 0) + throw_out_of_memory(); + *(static_cast(r)) = s; + return static_cast(r) + 1; // we return a pointer to the location after the extra field +} #endif diff --git a/src/util/memory_manager.h b/src/util/memory_manager.h index 49472ef28..bd912828e 100644 --- a/src/util/memory_manager.h +++ b/src/util/memory_manager.h @@ -58,6 +58,7 @@ public: static void display_i_max_usage(std::ostream& os); static void deallocate(void* p); static ALLOC_ATTR void* allocate(size_t s); + static ALLOC_ATTR void* reallocate(void *p, size_t s); #if _DEBUG static void deallocate(char const* file, int line, void* p); static ALLOC_ATTR void* allocate(char const* file, int line, char const* obj, size_t s); diff --git a/src/util/vector.h b/src/util/vector.h index 9370a4eed..dc08a63b3 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -71,18 +71,12 @@ class vector { SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2; SZ new_capacity = (3 * old_capacity + 1) >> 1; SZ new_capacity_T = sizeof(T) * new_capacity + sizeof(SZ) * 2; - SZ size = reinterpret_cast(m_data)[SIZE_IDX]; if (new_capacity <= old_capacity || new_capacity_T <= old_capacity_T) { throw default_exception("Overflow encountered when expanding vector"); } - SZ * mem = reinterpret_cast(memory::allocate(new_capacity_T)); - *mem = new_capacity; - mem ++; - *mem = size; - mem++; - memcpy(mem, m_data, size * sizeof(T)); - free_memory(); - m_data = reinterpret_cast(mem); + SZ *mem = (SZ*)memory::reallocate(reinterpret_cast(m_data)-2, new_capacity_T); + *mem = new_capacity; + m_data = reinterpret_cast(mem + 2); } } From 755a259ea0fac2d8568b3f277add7f169fb9bd44 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 11 Mar 2015 00:44:56 -0700 Subject: [PATCH 592/646] fix codeplex issue 188 Signed-off-by: Nikolaj Bjorner --- src/cmd_context/context_params.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index f87c8d264..13f6f5be3 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -24,6 +24,16 @@ Notes: #include"solver.h" context_params::context_params() { + m_unsat_core = false; + m_model = true; + m_model_validate = false; + m_auto_config = true; + m_proof = false; + m_trace = false; + m_debug_ref_count = false; + m_smtlib2_compliant = false; + m_well_sorted_check = false; + m_timeout = UINT_MAX; updt_params(); } @@ -98,17 +108,17 @@ void context_params::updt_params() { } void context_params::updt_params(params_ref const & p) { - m_timeout = p.get_uint("timeout", UINT_MAX); - m_well_sorted_check = p.get_bool("type_check", p.get_bool("well_sorted_check", true)); - m_auto_config = p.get_bool("auto_config", true); - m_proof = p.get_bool("proof", false); - m_model = p.get_bool("model", true); - m_model_validate = p.get_bool("model_validate", false); - m_trace = p.get_bool("trace", false); + m_timeout = p.get_uint("timeout", m_timeout); + m_well_sorted_check = p.get_bool("type_check", p.get_bool("well_sorted_check", m_well_sorted_check)); + m_auto_config = p.get_bool("auto_config", m_auto_config); + m_proof = p.get_bool("proof", m_proof); + m_model = p.get_bool("model", m_model); + m_model_validate = p.get_bool("model_validate", m_model_validate); + m_trace = p.get_bool("trace", m_trace); m_trace_file_name = p.get_str("trace_file_name", "z3.log"); - m_unsat_core = p.get_bool("unsat_core", false); - m_debug_ref_count = p.get_bool("debug_ref_count", false); - m_smtlib2_compliant = p.get_bool("smtlib2_compliant", false); + m_unsat_core = p.get_bool("unsat_core", m_unsat_core); + m_debug_ref_count = p.get_bool("debug_ref_count", m_debug_ref_count); + m_smtlib2_compliant = p.get_bool("smtlib2_compliant", m_smtlib2_compliant); } void context_params::collect_param_descrs(param_descrs & d) { From 4ed062d54a648c35e425c51260f24820499693c7 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 11 Mar 2015 11:04:33 +0000 Subject: [PATCH 593/646] fix missing memset in my previous commit Signed-off-by: Nuno Lopes --- src/util/bit_vector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/bit_vector.cpp b/src/util/bit_vector.cpp index c41e4574c..cf96cb295 100644 --- a/src/util/bit_vector.cpp +++ b/src/util/bit_vector.cpp @@ -30,6 +30,7 @@ void bit_vector::expand_to(unsigned new_capacity) { } else { m_data = alloc_svect(unsigned, new_capacity); } + memset(m_data + m_capacity, 0, (new_capacity - m_capacity) * sizeof(unsigned)); m_capacity = new_capacity; } From ed81e3b9d80890e83a70b7bf5b8add6e2a5f85fb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 20 Mar 2015 17:07:32 +0000 Subject: [PATCH 594/646] Bugfix for BV-SLS initialization Signed-off-by: Christoph M. Wintersteiger --- src/tactic/sls/sls_engine.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp index 98f659fe0..fc7358f3d 100644 --- a/src/tactic/sls/sls_engine.cpp +++ b/src/tactic/sls/sls_engine.cpp @@ -555,8 +555,12 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) { mc = 0; } -lbool sls_engine::operator()() { +lbool sls_engine::operator()() { m_tracker.initialize(m_assertions); + m_tracker.reset(m_assertions); + if (m_restart_init) + m_tracker.randomize(m_assertions); + lbool res = l_undef; do { From 47d33452c66064aae6148b342dc1e17a7315a34b Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Fri, 20 Mar 2015 17:39:45 -0700 Subject: [PATCH 595/646] interpolation fix (issue 182) --- src/interp/iz3interp.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/interp/iz3interp.cpp b/src/interp/iz3interp.cpp index e1846d3b5..750c0c85e 100755 --- a/src/interp/iz3interp.cpp +++ b/src/interp/iz3interp.cpp @@ -97,6 +97,18 @@ struct frame_reducer : public iz3mgr { get_proof_assumptions_rec(proof,memo,used_frames); std::vector assertions_back_map(frames); + // if multiple children of a tree node are used, we can't delete it + std::vector used_children; + for(int i = 0; i < frames; i++) + used_children.push_back(0); + for(int i = 0; i < frames; i++) + if(orig_parents[i] != SHRT_MAX) + if(used_frames[i] || used_children[i]){ + if(used_children[i] > 1) + used_frames[i] = true; + used_children[orig_parents[i]]++; + } + for(unsigned i = 0; i < z3_preds.size(); i++) if(used_frames[i] || i == z3_preds.size() - 1){ assertions.push_back(z3_preds[i]); From b76d588c281c4ca1d08bec4477f903490cd7d412 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 21 Mar 2015 16:10:30 +0000 Subject: [PATCH 596/646] Renamed the soft_timeout option to just timeout. Signed-off-by: Christoph M. Wintersteiger --- src/muz/base/dl_context.cpp | 2 +- src/muz/base/dl_context.h | 2 +- src/muz/clp/clp_context.cpp | 2 +- src/muz/rel/rel_context.cpp | 4 ++-- src/muz/tab/tab_context.cpp | 2 +- src/smt/params/smt_params.cpp | 2 +- src/smt/params/smt_params.h | 4 ++-- src/smt/params/smt_params_helper.pyg | 2 +- src/smt/smt_context.cpp | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 7c9c5813b..30dd08ff4 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -288,7 +288,7 @@ namespace datalog { bool context::unbound_compressor() const { return m_params->unbound_compressor(); } bool context::similarity_compressor() const { return m_params->similarity_compressor(); } unsigned context::similarity_compressor_threshold() const { return m_params->similarity_compressor_threshold(); } - unsigned context::soft_timeout() const { return m_fparams.m_soft_timeout; } + unsigned context::timeout() const { return m_fparams.m_timeout; } unsigned context::initial_restart_timeout() const { return m_params->initial_restart_timeout(); } bool context::generate_explanations() const { return m_params->generate_explanations(); } bool context::explanations_on_relation_level() const { return m_params->explanations_on_relation_level(); } diff --git a/src/muz/base/dl_context.h b/src/muz/base/dl_context.h index cf2c53913..8a881d71b 100644 --- a/src/muz/base/dl_context.h +++ b/src/muz/base/dl_context.h @@ -258,7 +258,7 @@ namespace datalog { bool unbound_compressor() const; bool similarity_compressor() const; unsigned similarity_compressor_threshold() const; - unsigned soft_timeout() const; + unsigned timeout() const; unsigned initial_restart_timeout() const; bool generate_explanations() const; bool explanations_on_relation_level() const; diff --git a/src/muz/clp/clp_context.cpp b/src/muz/clp/clp_context.cpp index 0cd08e5b3..11f6ae1db 100644 --- a/src/muz/clp/clp_context.cpp +++ b/src/muz/clp/clp_context.cpp @@ -59,7 +59,7 @@ namespace datalog { { // m_fparams.m_relevancy_lvl = 0; m_fparams.m_mbqi = false; - m_fparams.m_soft_timeout = 1000; + m_fparams.m_timeout = 1000; } ~imp() {} diff --git a/src/muz/rel/rel_context.cpp b/src/muz/rel/rel_context.cpp index 02b00be39..4e219b2f7 100644 --- a/src/muz/rel/rel_context.cpp +++ b/src/muz/rel/rel_context.cpp @@ -128,8 +128,8 @@ namespace datalog { lbool rel_context::saturate(scoped_query& sq) { m_context.ensure_closed(); - bool time_limit = m_context.soft_timeout()!=0; - unsigned remaining_time_limit = m_context.soft_timeout(); + bool time_limit = m_context.timeout()!=0; + unsigned remaining_time_limit = m_context.timeout(); unsigned restart_time = m_context.initial_restart_timeout(); instruction_block termination_code; diff --git a/src/muz/tab/tab_context.cpp b/src/muz/tab/tab_context.cpp index 83842a68b..f13590e35 100644 --- a/src/muz/tab/tab_context.cpp +++ b/src/muz/tab/tab_context.cpp @@ -1367,7 +1367,7 @@ namespace datalog { { // m_fparams.m_relevancy_lvl = 0; m_fparams.m_mbqi = false; - m_fparams.m_soft_timeout = 1000; + m_fparams.m_timeout = 1000; } ~imp() {} diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 2f8d9c1ee..a0f56663c 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -34,7 +34,7 @@ void smt_params::updt_local_params(params_ref const & _p) { m_delay_units = p.delay_units(); m_delay_units_threshold = p.delay_units_threshold(); m_preprocess = _p.get_bool("preprocess", true); // hidden parameter - m_soft_timeout = p.soft_timeout(); + m_timeout = p.timeout(); model_params mp(_p); m_model_compact = mp.compact(); if (_p.get_bool("arith.greatest_error_pivot", false)) diff --git a/src/smt/params/smt_params.h b/src/smt/params/smt_params.h index 256c5a646..2fbc9b6d4 100644 --- a/src/smt/params/smt_params.h +++ b/src/smt/params/smt_params.h @@ -202,7 +202,7 @@ struct smt_params : public preprocessor_params, bool m_preprocess; // temporary hack for disabling all preprocessing.. bool m_user_theory_preprocess_axioms; bool m_user_theory_persist_axioms; - unsigned m_soft_timeout; + unsigned m_timeout; bool m_at_labels_cex; // only use labels which contains the @ symbol when building multiple counterexamples. bool m_check_at_labels; // check that @ labels are inserted to generate unique counter-examples. bool m_dump_goal_as_smt; @@ -270,7 +270,7 @@ struct smt_params : public preprocessor_params, m_preprocess(true), // temporary hack for disabling all preprocessing.. m_user_theory_preprocess_axioms(false), m_user_theory_persist_axioms(false), - m_soft_timeout(0), + m_timeout(0), m_at_labels_cex(false), m_check_at_labels(false), m_dump_goal_as_smt(false), diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 39818e621..97a326e4d 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -15,7 +15,7 @@ def_module_params(module_name='smt', ('delay_units_threshold', UINT, 32, 'maximum number of learned unit clauses before restarting, ingored if delay_units is false'), ('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'), ('refine_inj_axioms', BOOL, True, 'refine injectivity axioms'), - ('soft_timeout', UINT, 0, 'soft timeout (0 means no timeout)'), + ('timeout', UINT, 0, 'timeout (0 means no timeout)'), ('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'), ('mbqi.max_cexs', UINT, 1, 'initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation'), ('mbqi.max_cexs_incr', UINT, 0, 'increment for MBQI_MAX_CEXS, the increment is performed after each round of MBQI'), diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 957d5ebe7..d7e18461b 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -3355,7 +3355,7 @@ namespace smt { if (m_last_search_failure != OK) return true; - if (m_timer.ms_timeout(m_fparams.m_soft_timeout)) { + if (m_timer.ms_timeout(m_fparams.m_timeout)) { m_last_search_failure = TIMEOUT; return true; } From 1c77ad00c30cb308864bbb2a099932a4110ed96b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 24 Mar 2015 21:42:05 +0000 Subject: [PATCH 597/646] Added accessors to enumeration sorts. Thanks to codeplex user steimann for suggesting this. (http://z3.codeplex.com/workitem/195) Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 2 +- src/api/dotnet/EnumSort.cs | 32 +++++++++++++++++++++++++++++++- src/api/java/EnumSort.java | 30 +++++++++++++++++++++++++++++- src/api/ml/z3.ml | 15 ++++++++++++++- src/api/ml/z3.mli | 12 ++++++++++++ 5 files changed, 87 insertions(+), 4 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 01f9e687e..afa613f57 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -11,7 +11,7 @@ Version 4.4 - Upgrade: This release includes a brand new OCaml/ML API that is much better integrated with the build system, and hopefully also easier to use than the previous one. -- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, Codeplex users rsas, clockish, Heizmann, susmitj, and Stackoverflow users user297886. +- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, Malte Schwerhoff, Amir Ebrahimi, Codeplex users rsas, clockish, Heizmann, susmitj, steimann, and Stackoverflow users user297886. Version 4.3.2 diff --git a/src/api/dotnet/EnumSort.cs b/src/api/dotnet/EnumSort.cs index f7ba98222..62be48a2c 100644 --- a/src/api/dotnet/EnumSort.cs +++ b/src/api/dotnet/EnumSort.cs @@ -44,6 +44,16 @@ namespace Microsoft.Z3 } } + /// + /// Retrieves the inx'th constant declaration in the enumeration. + /// + /// + /// + public FuncDecl ConstDecl(uint inx) + { + return new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, inx)); + } + /// /// The constants in the enumeration. /// @@ -61,7 +71,17 @@ namespace Microsoft.Z3 } /// - /// The test predicates for the constants in the enumeration. + /// Retrieves the inx'th constant in the enumeration. + /// + /// + /// + public Expr Const(uint inx) + { + return Context.MkApp(ConstDecl(inx)); + } + + /// + /// The test predicates (recognizers) for the constants in the enumeration. /// public FuncDecl[] TesterDecls { @@ -76,6 +96,16 @@ namespace Microsoft.Z3 } } + /// + /// Retrieves the inx'th tester/recognizer declaration in the enumeration. + /// + /// + /// + public FuncDecl TesterDecl(uint inx) + { + return new FuncDecl(Context, Native.Z3_get_datatype_sort_recognizer(Context.nCtx, NativeObject, inx)); + } + #region Internal internal EnumSort(Context ctx, Symbol name, Symbol[] enumNames) : base(ctx, IntPtr.Zero) diff --git a/src/api/java/EnumSort.java b/src/api/java/EnumSort.java index e33b9b348..bfe0c50b8 100644 --- a/src/api/java/EnumSort.java +++ b/src/api/java/EnumSort.java @@ -34,11 +34,20 @@ public class EnumSort extends Sort t[i] = new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), i)); return t; } + + /** + * Retrieves the inx'th constant declaration in the enumeration. + * @throws Z3Exception on error + **/ + public FuncDecl getConstDecl(int inx) throws Z3Exception + { + return new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), inx)); + } /** * The constants in the enumeration. * @throws Z3Exception on error - * @return an Expr + * @return an Expr[] **/ public Expr[] getConsts() throws Z3Exception { @@ -48,6 +57,16 @@ public class EnumSort extends Sort t[i] = getContext().mkApp(cds[i]); return t; } + + /** + * Retrieves the inx'th constant in the enumeration. + * @throws Z3Exception on error + * @return an Expr + **/ + public Expr getConst(int inx) throws Z3Exception + { + return getContext().mkApp(getConstDecl(inx)); + } /** * The test predicates for the constants in the enumeration. @@ -61,6 +80,15 @@ public class EnumSort extends Sort t[i] = new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), i)); return t; } + + /** + * Retrieves the inx'th tester/recognizer declaration in the enumeration. + * @throws Z3Exception on error + **/ + public FuncDecl getTesterDecl(int inx) throws Z3Exception + { + return new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), inx)); + } EnumSort(Context ctx, Symbol name, Symbol[] enumNames) throws Z3Exception { diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index d8cf21cda..a7cafbc29 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -1390,11 +1390,24 @@ struct let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) i)) in mk_list f n + let get_const_decl ( x : sort ) ( inx : int ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_constructor (Sort.gnc x) (Sort.gno x) inx) + + let get_consts ( x : sort ) = + let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in + let f i = (Expr.mk_const_f (Sort.gc x) (get_const_decl x i)) in + mk_list f n + + let get_const ( x : sort ) ( inx : int ) = + Expr.mk_const_f (Sort.gc x) (get_const_decl x inx) + let get_tester_decls ( x : sort ) = let n = Z3native.get_datatype_sort_num_constructors (Sort.gnc x) (Sort.gno x) in - let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i)) in + let f i = (func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) i)) in mk_list f n + let get_tester_decl ( x : sort ) ( inx : int ) = + func_decl_of_ptr (Sort.gc x) (Z3native.get_datatype_sort_recognizer (Sort.gnc x) (Sort.gno x) inx) end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index e223008bb..db0c3f130 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -1091,8 +1091,20 @@ sig (** The function declarations of the constants in the enumeration. *) val get_const_decls : Sort.sort -> FuncDecl.func_decl list + (** Retrieves the inx'th constant declaration in the enumeration. *) + val get_const_decl : Sort.sort -> int -> FuncDecl.func_decl + + (** The constants in the enumeration. *) + val get_consts : Sort.sort -> Expr.expr list + + (** Retrieves the inx'th constant in the enumeration. *) + val get_const : Sort.sort -> int -> Expr.expr + (** The test predicates for the constants in the enumeration. *) val get_tester_decls : Sort.sort -> FuncDecl.func_decl list + + (** Retrieves the inx'th tester/recognizer declaration in the enumeration. *) + val get_tester_decl : Sort.sort -> int -> FuncDecl.func_decl end (** Functions to manipulate List expressions *) From a7927908827e60216c89fddbc2cecb45cfdec859 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 25 Mar 2015 18:08:56 +0000 Subject: [PATCH 598/646] Fixed performance problems with enumeration sorts (Codeplex #190). --- src/api/api_datatype.cpp | 22 +++++++++++----------- src/ast/datatype_decl_plugin.h | 12 +++++++++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index f3a275508..9cd357ed5 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -475,12 +475,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - ptr_vector const * decls = dt_util.get_datatype_constructors(_t); - if (!decls || idx >= decls->size()) { + unsigned n = dt_util.get_datatype_num_constructors(_t); + if (idx >= n) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - func_decl* decl = (*decls)[idx]; + func_decl* decl = dt_util.get_constructor(_t, idx); mk_c(c)->save_ast_trail(decl); return of_func_decl(decl); } @@ -505,12 +505,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } - ptr_vector const * decls = dt_util.get_datatype_constructors(_t); - if (!decls || idx >= decls->size()) { + unsigned n = dt_util.get_datatype_num_constructors(_t); + if (idx >= n) { SET_ERROR_CODE(Z3_INVALID_ARG); - RETURN_Z3(0); + return 0; } - func_decl* decl = (*decls)[idx]; + func_decl* decl = dt_util.get_constructor(_t, idx); decl = dt_util.get_constructor_recognizer(decl); mk_c(c)->save_ast_trail(decl); RETURN_Z3(of_func_decl(decl)); @@ -528,12 +528,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } - ptr_vector const * decls = dt_util.get_datatype_constructors(_t); - if (!decls || idx_c >= decls->size()) { + unsigned n = dt_util.get_datatype_num_constructors(_t); + if (idx_c >= n) { SET_ERROR_CODE(Z3_INVALID_ARG); - RETURN_Z3(0); + return 0; } - func_decl* decl = (*decls)[idx_c]; + func_decl* decl = dt_util.get_constructor(_t, idx_c); if (decl->get_arity() <= idx_a) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index 96b678fb2..af9c125f7 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -168,8 +168,7 @@ class datatype_util { obj_map m_is_recursive; ast_ref_vector m_asts; ptr_vector > m_vectors; - - func_decl * get_constructor(sort * ty, unsigned c_id); + func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector & forbidden_set); public: @@ -185,7 +184,12 @@ public: bool is_recognizer(app * f) const { return is_app_of(f, m_family_id, OP_DT_RECOGNISER); } bool is_accessor(app * f) const { return is_app_of(f, m_family_id, OP_DT_ACCESSOR); } ptr_vector const * get_datatype_constructors(sort * ty); - unsigned get_datatype_num_constructors(sort * ty) { return get_datatype_constructors(ty)->size(); } + unsigned get_datatype_num_constructors(sort * ty) { + SASSERT(is_datatype(ty)); + unsigned tid = ty->get_parameter(1).get_int(); + unsigned o = ty->get_parameter(3 + 2 * tid).get_int(); + return ty->get_parameter(o).get_int(); + } unsigned get_constructor_idx(func_decl * f) const { SASSERT(is_constructor(f)); return f->get_parameter(1).get_int(); } unsigned get_recognizer_constructor_idx(func_decl * f) const { SASSERT(is_recognizer(f)); return f->get_parameter(1).get_int(); } func_decl * get_non_rec_constructor(sort * ty); @@ -197,6 +201,8 @@ public: bool are_siblings(sort * s1, sort * s2); void reset(); void display_datatype(sort *s, std::ostream& strm); + + func_decl * get_constructor(sort * ty, unsigned c_id); }; #endif /* _DATATYPE_DECL_PLUGIN_H_ */ From 2aa91eee70569d10f978aa46497d0215b13e0e56 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Mar 2015 11:24:47 -0700 Subject: [PATCH 599/646] cache datatype util in context to avoid performance bug, codeplex issue 195 Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 1 + src/api/api_context.cpp | 1 + src/api/api_context.h | 2 ++ src/api/api_datatype.cpp | 18 +++++++++--------- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index e48c23905..0f0dd5ebf 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -4,6 +4,7 @@ using namespace z3; + /** Demonstration of how Z3 can be used to prove validity of De Morgan's Duality Law: {e not(x and y) <-> (not x) or ( not y) } diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 49fa10d94..cff59cd80 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -89,6 +89,7 @@ namespace api { m_bv_util(m()), m_datalog_util(m()), m_fpa_util(m()), + m_dtutil(m()), m_last_result(m()), m_ast_trail(m()), m_replay_stack() { diff --git a/src/api/api_context.h b/src/api/api_context.h index 58394c028..f02dc6f16 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -58,6 +58,7 @@ namespace api { bv_util m_bv_util; datalog::dl_decl_util m_datalog_util; fpa_util m_fpa_util; + datatype_util m_dtutil; // Support for old solver API smt_params m_fparams; @@ -119,6 +120,7 @@ namespace api { bv_util & bvutil() { return m_bv_util; } datalog::dl_decl_util & datalog_util() { return m_datalog_util; } fpa_util & fpautil() { return m_fpa_util; } + datatype_util& dtutil() { return m_dtutil; } 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; } diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index f3a275508..7e9dc6689 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -36,7 +36,7 @@ extern "C" { RESET_ERROR_CODE(); mk_c(c)->reset_last_result(); ast_manager& m = mk_c(c)->m(); - datatype_util dt_util(m); + datatype_util& dt_util = mk_c(c)->dtutil(); sort_ref_vector tuples(m); sort* tuple; @@ -102,7 +102,7 @@ extern "C" { RESET_ERROR_CODE(); mk_c(c)->reset_last_result(); ast_manager& m = mk_c(c)->m(); - datatype_util dt_util(m); + datatype_util& dt_util = mk_c(c)->dtutil(); sort_ref_vector sorts(m); sort* e; @@ -451,7 +451,7 @@ extern "C" { RESET_ERROR_CODE(); CHECK_VALID_AST(t, 0); sort * _t = to_sort(t); - datatype_util dt_util(mk_c(c)->m()); + datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); @@ -470,7 +470,7 @@ extern "C" { RESET_ERROR_CODE(); CHECK_VALID_AST(t, 0); sort * _t = to_sort(t); - datatype_util dt_util(mk_c(c)->m()); + datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; @@ -499,7 +499,7 @@ extern "C" { 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()); + datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); @@ -522,7 +522,7 @@ extern "C" { 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()); + datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); @@ -555,7 +555,7 @@ extern "C" { 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()); + datatype_util& dt_util = mk_c(c)->dtutil(); 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); @@ -570,7 +570,7 @@ extern "C" { 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()); + datatype_util& dt_util = mk_c(c)->dtutil(); 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; @@ -593,7 +593,7 @@ extern "C" { 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()); + datatype_util& dt_util = mk_c(c)->dtutil(); 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); From 86ac20faf65ea3aaaed43aa17c3682e4e6a8dadf Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Mar 2015 11:35:44 -0700 Subject: [PATCH 600/646] cache datatype util in context to avoid performance bug, codeplex issue 195 Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 0f0dd5ebf..1278a50e4 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -1,10 +1,28 @@ #include #include"z3++.h" - +#include using namespace z3; +void slow() { + context ctx; + unsigned sortSize = 200000; + char** names = new char*[sortSize]; + func_decl_vector enum_consts(ctx); + func_decl_vector enum_testers(ctx); + for (unsigned i = 0; i < sortSize; ++i) { + std::stringstream strm; + strm << "c" << i; + names[i] = strdup(strm.str().c_str()); + } + sort s = ctx.enumeration_sort("enumT", sortSize, names, enum_consts, enum_testers); + std::vector decls; + for (unsigned i = 0; i < sortSize; ++i) { + decls.push_back(Z3_get_datatype_sort_constructor(ctx, s, i)); + } +} + /** Demonstration of how Z3 can be used to prove validity of De Morgan's Duality Law: {e not(x and y) <-> (not x) or ( not y) } @@ -986,6 +1004,8 @@ void extract_example() { } int main() { + slow(); + return 0; try { demorgan(); std::cout << "\n"; find_model_example1(); std::cout << "\n"; From 8059a5a0b75e1ff4bbf25e946efece8de7f25278 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Mar 2015 11:36:01 -0700 Subject: [PATCH 601/646] cache datatype util in context to avoid performance bug, codeplex issue 195 Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 1278a50e4..81af289d3 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -1,27 +1,9 @@ #include #include"z3++.h" -#include using namespace z3; -void slow() { - context ctx; - unsigned sortSize = 200000; - char** names = new char*[sortSize]; - func_decl_vector enum_consts(ctx); - func_decl_vector enum_testers(ctx); - for (unsigned i = 0; i < sortSize; ++i) { - std::stringstream strm; - strm << "c" << i; - names[i] = strdup(strm.str().c_str()); - } - sort s = ctx.enumeration_sort("enumT", sortSize, names, enum_consts, enum_testers); - std::vector decls; - for (unsigned i = 0; i < sortSize; ++i) { - decls.push_back(Z3_get_datatype_sort_constructor(ctx, s, i)); - } -} /** Demonstration of how Z3 can be used to prove validity of @@ -1004,8 +986,6 @@ void extract_example() { } int main() { - slow(); - return 0; try { demorgan(); std::cout << "\n"; find_model_example1(); std::cout << "\n"; From 39892aae10c28810b8db5e4b9a6addda36a09520 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Mar 2015 11:46:17 -0700 Subject: [PATCH 602/646] cache datatype util in context to avoid performance bug, codeplex issue 195 Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 4 ++++ src/api/api_datatype.cpp | 18 +++++++++--------- src/ast/datatype_decl_plugin.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 81af289d3..67af5eb34 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -5,6 +5,7 @@ using namespace z3; + /** Demonstration of how Z3 can be used to prove validity of De Morgan's Duality Law: {e not(x and y) <-> (not x) or ( not y) } @@ -986,6 +987,9 @@ void extract_example() { } int main() { + slow(); + return 0; + try { demorgan(); std::cout << "\n"; find_model_example1(); std::cout << "\n"; diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index 7acd93bf0..a9794c980 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -475,12 +475,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - unsigned n = dt_util.get_datatype_num_constructors(_t); - if (idx >= n) { + ptr_vector const * decls = dt_util.get_datatype_constructors(_t); + if (idx >= decls->size()) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - func_decl* decl = dt_util.get_constructor(_t, idx); + func_decl* decl = (*decls)[idx]; mk_c(c)->save_ast_trail(decl); return of_func_decl(decl); } @@ -505,12 +505,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } - unsigned n = dt_util.get_datatype_num_constructors(_t); - if (idx >= n) { + ptr_vector const * decls = dt_util.get_datatype_constructors(_t); + if (idx >= decls->size()) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - func_decl* decl = dt_util.get_constructor(_t, idx); + 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)); @@ -528,12 +528,12 @@ extern "C" { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); } - unsigned n = dt_util.get_datatype_num_constructors(_t); - if (idx_c >= n) { + ptr_vector const * decls = dt_util.get_datatype_constructors(_t); + if (idx_c >= decls->size()) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } - func_decl* decl = dt_util.get_constructor(_t, idx_c); + func_decl* decl = (*decls)[idx_c]; if (decl->get_arity() <= idx_a) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index af9c125f7..3f7f01364 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -170,6 +170,7 @@ class datatype_util { ptr_vector > m_vectors; func_decl * get_non_rec_constructor_core(sort * ty, ptr_vector & forbidden_set); + func_decl * get_constructor(sort * ty, unsigned c_id); public: datatype_util(ast_manager & m); @@ -202,7 +203,6 @@ public: void reset(); void display_datatype(sort *s, std::ostream& strm); - func_decl * get_constructor(sort * ty, unsigned c_id); }; #endif /* _DATATYPE_DECL_PLUGIN_H_ */ From 0482e7fe727c75e259ac55a932b28cf1842c530e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 25 Mar 2015 11:46:28 -0700 Subject: [PATCH 603/646] cache datatype util in context to avoid performance bug, codeplex issue 195 Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 67af5eb34..9f4f9431c 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -987,8 +987,6 @@ void extract_example() { } int main() { - slow(); - return 0; try { demorgan(); std::cout << "\n"; From 9cbf45f689cc7d2722c869d830881136a48a6bc4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 26 Mar 2015 14:48:55 +0000 Subject: [PATCH 604/646] Added int to float conversion. --- src/ast/fpa/fpa2bv_converter.cpp | 6 ++++-- src/ast/fpa_decl_plugin.cpp | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 8e2dd326a..89072a795 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1878,6 +1878,7 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args else if (num == 2 && m_bv_util.is_bv(args[0]) && m_bv_util.get_bv_size(args[0]) == 3 && + m_arith_util.is_int(args[1]) || m_arith_util.is_real(args[1])) { // rm + real -> float mk_to_fp_real(f, f->get_range(), args[0], args[1], result); @@ -2066,7 +2067,7 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * TRACE("fpa2bv_to_fp_real", tout << "rm: " << mk_ismt2_pp(rm, m) << std::endl << "x: " << mk_ismt2_pp(x, m) << std::endl;); SASSERT(m_util.is_float(s)); - SASSERT(au().is_real(x)); + SASSERT(au().is_real(x) || au().is_int(x)); unsigned ebits = m_util.get_ebits(s); unsigned sbits = m_util.get_sbits(s); @@ -2089,7 +2090,8 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * } rational q; - m_util.au().is_numeral(x, q); + bool is_int; + m_util.au().is_numeral(x, q, is_int); scoped_mpf v(m_mpf_manager); m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index bd2676ee4..48b7adb8b 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -521,14 +521,26 @@ func_decl * fpa_decl_plugin::mk_to_fp(decl_kind k, unsigned num_parameters, para symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } + else if (arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_arith_fid, INT_SORT)) { + // Rounding + 1 Int -> 1 FP + if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) + m_manager->raise_exception("expecting two integer parameters to to_fp"); + + sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } else { m_manager->raise_exception("Unexpected argument combination for (_ to_fp eb sb). Supported argument combinations are: " - "((_ BitVec 1) (_ BitVec eb) (_ BitVec sb-1))," - "(_ BitVec (eb+sb))," - "(Real)," - "(RoundingMode (_ BitVec (eb+sb)))," - "(RoundingMode (_ FloatingPoint eb' sb'))," - "(RoundingMode Real Int), and" + "((_ BitVec 1) (_ BitVec eb) (_ BitVec sb-1)), " + "(_ BitVec (eb+sb)), " + "(Real), " + "(RoundingMode (_ BitVec (eb+sb))), " + "(RoundingMode (_ FloatingPoint eb' sb')), " + "(RoundingMode Real Int), " + "(RoundingMode Int), and " "(RoundingMode Real)." ); } From 274f2b7a5d40051c4af4791e157544bfc9a74926 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 26 Mar 2015 11:22:09 -0700 Subject: [PATCH 605/646] Move to MIT License --- LICENSE.txt | 46 ++++++---------------------------------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 72d85818f..91c8070d0 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,41 +1,7 @@ -Microsoft Research License Agreement -Non-Commercial Use Only Z3 -_____________________________________________________________________ -This Microsoft Research License Agreement, including all exhibits ("MSR-LA") is a legal agreement between you and Microsoft Corporation ("Microsoft" or "we") for the data identified above, which may include associated materials, text or speech files, associated media and "online" or electronic documentation and any updates we provide in our discretion (together, the "Software"). - -By installing, copying, or otherwise using this Software, you agree to be bound by the terms of this MSR-LA. If you do not agree, do not install copy or use the Software. The Software is protected by copyright and other intellectual property laws and is licensed, not sold. - -SCOPE OF RIGHTS: -You may use, copy, reproduce, and distribute this Software for any non-commercial purpose, subject to the restrictions in this MSR-LA. Some purposes which can be non-commercial are teaching, academic research, public demonstrations and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software for academic or other non-commercial purposes. - -You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, distributing the Software for use with commercial products, using the Software in the creation or use of commercial products or any other activity which purpose is to procure a commercial gain to you or others. - -You may create derivative works of the Software source code and distribute the modified Software solely for non-commercial academic purposes, as provided herein. If you distribute the Software or any derivative works of the Software, you will distribute them under the same terms and conditions as in this license, and you will not grant other rights to the Software or derivative works that are different from those provided by this MSR-LA. - -If you have created derivative works of the Software, and distribute such derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes. -In return, we simply require that you agree: - -1. That you will not remove any copyright or other notices from the Software. - -2. That if any of the Software is in binary format, you will not attempt to modify such portions of the Software, or to reverse engineer or decompile them, except and only to the extent authorized by applicable law. - -3. That Microsoft is granted back, without any restrictions or limitations, a non-exclusive, perpetual, irrevocable, royalty-free, assignable and sub-licensable license, to reproduce, publicly perform or display, install, use, modify, post, distribute, make and have made, sell and transfer your modifications to and/or derivative works of the Software source code or data, for any purpose. - -4. That any feedback about the Software provided by you to us is voluntarily given, and Microsoft shall be free to use the feedback as it sees fit without obligation or restriction of any kind, even if the feedback is designated by you as confidential. - -5. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ANY WARRANTY AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE SOFTWARE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. THERE IS NO WARRANTY THAT THIS SOFTWARE WILL FULFILL ANY OF YOUR PARTICULAR PURPOSES OR NEEDS. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS. - -6. THAT NEITHER MICROSOFT NOR ANY CONTRIBUTOR TO THE SOFTWARE WILL BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS MSR-LA, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS. - -7. That we have no duty of reasonable care or lack of negligence, and we are not obligated to (and will not) provide technical support for the Software. - -8. That if you breach this MSR-LA or if you sue anyone over patents that you think may apply to or read on the Software or anyone's use of the Software, this MSR-LA (and your license and rights obtained herein) terminate automatically. Upon any such termination, you shall destroy all of your copies of the Software immediately. Sections 3, 4, 5, 6, 7, 8, 11 and 12 of this MSR-LA shall survive any termination of this MSR-LA. - -9. That the patent rights, if any, granted to you in this MSR-LA only apply to the Software, not to any derivative works you make. - -10. That the Software may be subject to U.S. export jurisdiction at the time it is licensed to you, and it may be subject to additional export or import laws in other places. You agree to comply with all such laws and regulations that may apply to the Software after delivery of the Software to you. - -11. That all rights not expressly granted to you in this MSR-LA are reserved. - -12. That this MSR-LA shall be construed and controlled by the laws of the State of Washington, USA, without regard to conflicts of law. If any provision of this MSR-LA shall be deemed unenforceable or contrary to law, the rest of this MSR-LA shall remain in full effect and interpreted in an enforceable manner that most nearly captures the intent of the original language. +Copyright (c) Microsoft Corporation +All rights reserved. +MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 3b16cfbd4449bb5fd3becb527d4545ef98757e09 Mon Sep 17 00:00:00 2001 From: NikolajBjorner Date: Thu, 26 Mar 2015 11:31:34 -0700 Subject: [PATCH 606/646] Update README change reference to license --- README | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README b/README index 074abd2a3..d7f441d64 100644 --- a/README +++ b/README @@ -1,6 +1,5 @@ Z3 is a theorem prover from Microsoft Research. -Z3 is licensed under MSR-LA (Microsoft Research License Agreement). -See http://z3.codeplex.com/license for more information about this license. +Z3 is licensed under the MIT license. Z3 can be built using Visual Studio Command Prompt and make/g++. 1) Building Z3 on Windows using Visual Studio Command Prompt @@ -42,4 +41,4 @@ Remark: clang does not support OpenMP yet. make -To clean Z3 you can delete the build directory and run the mk_make.py script again. \ No newline at end of file +To clean Z3 you can delete the build directory and run the mk_make.py script again. From e456af142e5e51ab80e5cf8f49a1f09a32368a5d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Mar 2015 02:42:08 -0700 Subject: [PATCH 607/646] fix complex.py example with power prompted by suggestion of smilliken Signed-off-by: Nikolaj Bjorner --- examples/python/complex/complex.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/python/complex/complex.py b/examples/python/complex/complex.py index a2de4a6cc..5d6283745 100644 --- a/examples/python/complex/complex.py +++ b/examples/python/complex/complex.py @@ -46,6 +46,15 @@ class ComplexExpr: other = _to_complex(other) return ComplexExpr(other.r*self.r - other.i*self.i, other.i*self.r + other.r*self.i) + def __pow__(self, k): + if k == 0: + return ComplexExpr(1, 0) + if k == 1: + return self + if k < 0: + return (self ** (-k)).inv() + return reduce(lambda x, y: x * y, [self for _ in xrange(k)], ComplexExpr(1, 0)) + def inv(self): den = self.r*self.r + self.i*self.i return ComplexExpr(self.r/den, -self.i/den) @@ -104,4 +113,5 @@ print(s.model()) s.add(x.i != 1) print(s.check()) # print(s.model()) -print (3 + I)^2/(5 - I) +print ((3 + I) ** 2)/(5 - I) +print ((3 + I) ** -3)/(5 - I) From 4bfe20647bd17092179dbed8f9390017456652ec Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 27 Mar 2015 02:43:21 -0700 Subject: [PATCH 608/646] remove tab in mk_util.py Signed-off-by: Nikolaj Bjorner --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 0f4fdb216..e13bbada3 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -565,7 +565,7 @@ def parse_options(): if not IS_WINDOWS: raise MKException('x64 compilation mode can only be specified when using Visual Studio') VS_X64 = True - elif opt in ('--x86'): + elif opt in ('--x86'): LINUX_X64=False elif opt in ('-h', '--help'): display_help(0) From 690eb8eaca3e7d79d5379cf6ab5ab4682e480c00 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 29 Mar 2015 13:31:44 +0100 Subject: [PATCH 609/646] Bugfix for fp.isSubnormal. Fixes #10 --- src/ast/fpa/fpa2bv_converter.cpp | 9 +++++++-- src/util/mpf.cpp | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 89072a795..738422b89 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2952,11 +2952,16 @@ void fpa2bv_converter::mk_is_pzero(expr * e, expr_ref & result) { } void fpa2bv_converter::mk_is_denormal(expr * e, expr_ref & result) { - expr * sgn, * sig, * exp; + expr * sgn, *sig, *exp; split_fp(e, sgn, exp, sig); - expr_ref zero(m); + + expr_ref zero(m), zexp(m), is_zero(m), n_is_zero(m); zero = m_bv_util.mk_numeral(0, m_bv_util.get_bv_size(exp)); m_simp.mk_eq(exp, zero, result); + m_simp.mk_eq(exp, zero, zexp); + mk_is_zero(e, is_zero); + m_simp.mk_not(is_zero, n_is_zero); + m_simp.mk_and(n_is_zero, zexp, result); } void fpa2bv_converter::mk_is_normal(expr * e, expr_ref & result) { diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 4e452b1e8..d28395195 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1350,7 +1350,7 @@ bool mpf_manager::is_ninf(mpf const & x) { } bool mpf_manager::is_normal(mpf const & x) { - return !has_bot_exp(x) && !has_top_exp(x); + return !is_zero(x) && has_bot_exp(x); } bool mpf_manager::is_denormal(mpf const & x) { From 0ed16c09f9dbfed1c80ae08f7303a9d67ffa12bd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 29 Mar 2015 13:57:11 +0100 Subject: [PATCH 610/646] Bugfix for fp.isNegative. Fixes #13 --- src/ast/fpa/fpa2bv_converter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 738422b89..f049750c3 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1837,7 +1837,10 @@ void fpa2bv_converter::mk_is_subnormal(func_decl * f, unsigned num, expr * const void fpa2bv_converter::mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); - mk_is_neg(args[0], result); + expr_ref t1(m), t2(m); + mk_is_nan(args[0], t1); + mk_is_neg(args[0], t2); + result = m.mk_and(m.mk_not(t1), t2); TRACE("fpa2bv_is_negative", tout << "result = " << mk_ismt2_pp(result, m) << std::endl;); } From 5911f788c3eba23e3d1f1aba28c64af218cdd028 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 29 Mar 2015 14:39:47 +0100 Subject: [PATCH 611/646] Improved translation from reals to floats (fp.to_real). Fixes #14 --- src/ast/fpa/fpa2bv_converter.cpp | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index f049750c3..06662e205 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2107,6 +2107,64 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * mk_fp(sgn, e, s, result); } + else if (m_util.au().is_numeral(x)) { + rational q; + bool is_int; + m_util.au().is_numeral(x, q, is_int); + + expr_ref rm_nta(m), rm_nte(m), rm_tp(m), rm_tn(m), rm_tz(m); + mk_is_rm(rm, BV_RM_TIES_TO_AWAY, rm_nta); + mk_is_rm(rm, BV_RM_TIES_TO_EVEN, rm_nte); + mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_tp); + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_tn); + mk_is_rm(rm, BV_RM_TO_ZERO, rm_tz); + + scoped_mpf v_nta(m_mpf_manager), v_nte(m_mpf_manager), v_tp(m_mpf_manager); + scoped_mpf v_tn(m_mpf_manager), v_tz(m_mpf_manager); + m_util.fm().set(v_nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq()); + m_util.fm().set(v_nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq()); + m_util.fm().set(v_tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq()); + m_util.fm().set(v_tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq()); + m_util.fm().set(v_tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq()); + + expr_ref v1(m), v2(m), v3(m), v4(m); + + expr_ref sgn(m), s(m), e(m), unbiased_exp(m); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nta)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_nta), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nta), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v1); + + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nte)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_nte), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nte), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v2); + + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v3); + + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tn)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tn), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tn), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v4); + + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); + mk_bias(unbiased_exp, e); + + mk_fp(sgn, e, s, result); + mk_ite(rm_tn, v4, result, result); + mk_ite(rm_tp, v3, result, result); + mk_ite(rm_nte, v2, result, result); + mk_ite(rm_nta, v1, result, result); + } else { bv_util & bu = m_bv_util; arith_util & au = m_arith_util; From 0f03cd2ae0ccc1ec96f4b51a398cfd69d163cd2d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sun, 29 Mar 2015 15:49:03 +0100 Subject: [PATCH 612/646] Enabled test for OpenMP in Windows (for old and express versions of visual studio). Fixes #8 --- scripts/mk_util.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index e13bbada3..99df6aa4d 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -226,7 +226,10 @@ def test_openmp(cc): t = TempFile('tstomp.cpp') t.add('#include\nint main() { return omp_in_parallel() ? 1 : 0; }\n') t.commit() - return exec_compiler_cmd([cc, CPPFLAGS, 'tstomp.cpp', LDFLAGS, '-fopenmp']) == 0 + if IS_WINDOWS: + return exec_compiler_cmd([cc, CPPFLAGS, 'tstomp.cpp', LDFLAGS, '/openmp']) == 0 + else: + return exec_compiler_cmd([cc, CPPFLAGS, 'tstomp.cpp', LDFLAGS, '-fopenmp']) == 0 def find_jni_h(path): for root, dirs, files in os.walk(path): @@ -1706,21 +1709,26 @@ def mk_config(): 'SLINK_OUT_FLAG=/Fe\n' 'OS_DEFINES=/D _WINDOWS\n') extra_opt = '' + HAS_OMP = test_openmp('cl') + if HAS_OMP: + extra_opt = ' /openmp' + else: + extra_opt = ' -D_NO_OMP_' if GIT_HASH: - extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) + extra_opt = ' %s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH) if DEBUG_MODE: config.write( 'LINK_FLAGS=/nologo /MDd\n' 'SLINK_FLAGS=/nologo /LDd\n') if not VS_X64: config.write( - 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( - 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG %s /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') @@ -1730,16 +1738,16 @@ def mk_config(): 'LINK_FLAGS=/nologo /MD\n' 'SLINK_FLAGS=/nologo /LD\n') if TRACE: - extra_opt = '%s /D _TRACE' % extra_opt + extra_opt = '%s /D _TRACE ' % extra_opt if not VS_X64: config.write( - 'CXXFLAGS=/nologo /c /GL /Zi /openmp /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) + 'CXXFLAGS=/nologo /c /GL /Zi /W3 /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _CONSOLE /D _WINDOWS /D ASYNC_COMMANDS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /LTCG /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( - 'CXXFLAGS=/c /GL /Zi /nologo /openmp /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP\n' % extra_opt) + 'CXXFLAGS=/c /GL /Zi /nologo /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D WIN32 /D NDEBUG %s /D _LIB /D _WINDOWS /D _AMD64_ /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP\n' % extra_opt) config.write( 'LINK_EXTRA_FLAGS=/link /LTCG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608\n' 'SLINK_EXTRA_FLAGS=/link /LTCG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608\n') @@ -1747,7 +1755,8 @@ def mk_config(): # End of Windows VS config.mk if is_verbose(): print('64-bit: %s' % is64()) - if is_java_enabled(): + print('OpenMP: %s' % HAS_OMP) + if is_java_enabled(): print('JNI Bindings: %s' % JNI_HOME) print('Java Compiler: %s' % JAVAC) if is_ml_enabled(): From 99ea0a8c19e04c7daf0f2649cd1e4826f64dd722 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 30 Mar 2015 08:02:57 +0100 Subject: [PATCH 613/646] Bugfix for mpf is_normal. Fixes #17 --- src/util/mpf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index d28395195..c96ba594e 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1350,11 +1350,11 @@ bool mpf_manager::is_ninf(mpf const & x) { } bool mpf_manager::is_normal(mpf const & x) { - return !is_zero(x) && has_bot_exp(x); + return !(has_top_exp(x) || is_denormal(x)); } bool mpf_manager::is_denormal(mpf const & x) { - return has_bot_exp(x); + return !is_zero(x) && has_bot_exp(x); } bool mpf_manager::is_int(mpf const & x) { From 1d9c9bcf7ac074b965bb862cc8d23c6f6ed7b92a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 31 Mar 2015 19:51:42 +0200 Subject: [PATCH 614/646] Made the InterpolationContext public. Fixes #20 --- src/api/dotnet/InterpolationContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index b5ada1bbd..0f516c0b0 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -13,7 +13,7 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the C/C++ API, which is well documented. [ContractVerification(true)] - class InterpolationContext : Context + public class InterpolationContext : Context { /// From b47851d7da0965e24e33c5c1d532776618e0698d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 2 Apr 2015 16:51:30 +0100 Subject: [PATCH 615/646] Made GetInterpolant and ComputeInterpolant public in Java and .NET. Fixes Codeplex discussion #616450 --- src/api/dotnet/ASTVector.cs | 2 +- src/api/dotnet/InterpolationContext.cs | 4 ++-- src/api/java/ASTVector.java | 2 +- src/api/java/InterpolationContext.java | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/dotnet/ASTVector.cs b/src/api/dotnet/ASTVector.cs index 597b1decc..b70ff13b6 100644 --- a/src/api/dotnet/ASTVector.cs +++ b/src/api/dotnet/ASTVector.cs @@ -25,7 +25,7 @@ namespace Microsoft.Z3 /// /// Vectors of ASTs. /// - internal class ASTVector : Z3Object + public class ASTVector : Z3Object { /// /// The size of the vector diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index 0f516c0b0..d54c8f634 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -47,7 +47,7 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_get_interpolant in the C/C++ API, which is /// well documented. - Expr[] GetInterpolant(Expr pf, Expr pat, Params p) + public Expr[] GetInterpolant(Expr pf, Expr pat, Params p) { Contract.Requires(pf != null); Contract.Requires(pat != null); @@ -72,7 +72,7 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_compute_interpolant in the C/C++ API, which is /// well documented. - Z3_lbool ComputeInterpolant(Expr pat, Params p, out ASTVector interp, out Model model) + public Z3_lbool ComputeInterpolant(Expr pat, Params p, out ASTVector interp, out Model model) { Contract.Requires(pat != null); Contract.Requires(p != null); diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 48c079ecc..03e1b0a98 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -20,7 +20,7 @@ package com.microsoft.z3; /** * Vectors of ASTs. **/ -class ASTVector extends Z3Object +public class ASTVector extends Z3Object { /** * The size of the vector diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 4c20ec6ae..91aac7f93 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -73,7 +73,7 @@ public class InterpolationContext extends Context * well documented. * @throws Z3Exception **/ - Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception + public Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception { checkContextMatch(pf); checkContextMatch(pat); @@ -94,7 +94,7 @@ public class InterpolationContext extends Context * well documented. * @throws Z3Exception **/ - Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception + public Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception { checkContextMatch(pat); checkContextMatch(p); From d01c3491a67d4a06ea1f6e57d385f04914529317 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 2 Apr 2015 10:28:30 -0700 Subject: [PATCH 616/646] simplify with caching, but without expanding number of asserted formulas. Bug reported by Heizmann, codeplex issue 197 Signed-off-by: Nikolaj Bjorner --- src/smt/asserted_formulas.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index faf5ce0ef..c02c6760a 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -603,11 +603,11 @@ void asserted_formulas::propagate_values() { proof_ref_vector new_prs1(m_manager); expr_ref_vector new_exprs2(m_manager); proof_ref_vector new_prs2(m_manager); - unsigned i = 0; unsigned sz = m_asserted_formulas.size(); - for (; i < sz; i++) { + for (unsigned i = 0; i < sz; i++) { expr * n = m_asserted_formulas.get(i); proof * pr = m_asserted_formula_prs.get(i, 0); + TRACE("simplifier", tout << mk_pp(n, m_manager) << "\n";); if (m_manager.is_eq(n)) { expr * lhs = to_app(n)->get_arg(0); expr * rhs = to_app(n)->get_arg(1); @@ -615,9 +615,11 @@ void asserted_formulas::propagate_values() { if (m_manager.is_value(lhs)) std::swap(lhs, rhs); if (!m_manager.is_value(lhs) && !m_simplifier.is_cached(lhs)) { - new_exprs1.push_back(n); - if (m_manager.proofs_enabled()) - new_prs1.push_back(pr); + if (i >= m_asserted_qhead) { + new_exprs1.push_back(n); + if (m_manager.proofs_enabled()) + new_prs1.push_back(pr); + } TRACE("propagate_values", tout << "found:\n" << mk_pp(lhs, m_manager) << "\n->\n" << mk_pp(rhs, m_manager) << "\n";); m_simplifier.cache_result(lhs, rhs, pr); found = true; @@ -625,9 +627,11 @@ void asserted_formulas::propagate_values() { } } } - new_exprs2.push_back(n); - if (m_manager.proofs_enabled()) - new_prs2.push_back(pr); + if (i >= m_asserted_qhead) { + new_exprs2.push_back(n); + if (m_manager.proofs_enabled()) + new_prs2.push_back(pr); + } } TRACE("propagate_values", tout << "found: " << found << "\n";); // If C is not empty, then reduce R using the updated simplifier cache with entries From d42e3ce6519a5d3d83173399692e665c7e5ac9c7 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Thu, 2 Apr 2015 13:10:23 -0700 Subject: [PATCH 617/646] possible header problem for std::less --- src/interp/iz3mgr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/interp/iz3mgr.h b/src/interp/iz3mgr.h index 7f66bb2d8..4ae39ef46 100755 --- a/src/interp/iz3mgr.h +++ b/src/interp/iz3mgr.h @@ -23,6 +23,8 @@ Revision History: #include #include +#include + #include "iz3hash.h" #include"well_sorted.h" From 0e8a0822f1678b1804c757f8ef1e7ef8479feba3 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 3 Apr 2015 11:59:27 -0700 Subject: [PATCH 618/646] fix used_vars reported by Daniel J. H, issue #24 Signed-off-by: Nikolaj Bjorner --- src/ast/used_vars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/used_vars.cpp b/src/ast/used_vars.cpp index 6353ad5fd..f33c5cb50 100644 --- a/src/ast/used_vars.cpp +++ b/src/ast/used_vars.cpp @@ -107,7 +107,7 @@ unsigned used_vars::get_num_vars() const { unsigned num = m_found_vars.size(); for (unsigned i = 0; i < num; i++) { if (m_found_vars[i]) - return r++; + r++; } return r; } From 841c1c22908295711721a930eb659ac2bd9f13a6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 3 Apr 2015 12:06:31 -0700 Subject: [PATCH 619/646] scope precedence of ||, github issue 24 Signed-off-by: Nikolaj Bjorner --- src/ast/fpa/fpa2bv_converter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 06662e205..69b661589 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -1881,8 +1881,8 @@ void fpa2bv_converter::mk_to_fp(func_decl * f, unsigned num, expr * const * args else if (num == 2 && m_bv_util.is_bv(args[0]) && m_bv_util.get_bv_size(args[0]) == 3 && - m_arith_util.is_int(args[1]) || - m_arith_util.is_real(args[1])) { + (m_arith_util.is_int(args[1]) || + m_arith_util.is_real(args[1]))) { // rm + real -> float mk_to_fp_real(f, f->get_range(), args[0], args[1], result); } From 4a3abbfe0f473976c4af5c764dd5341114021950 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 7 Apr 2015 13:47:34 +0100 Subject: [PATCH 620/646] Added (un)install targets for the Java API --- scripts/mk_util.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 99df6aa4d..da2fbb8b5 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1344,6 +1344,15 @@ class JavaDLLComponent(Component): so = get_so_ext() shutil.copy(os.path.join(build_path, 'libz3java.%s' % so), os.path.join(dist_path, 'bin', 'libz3java.%s' % so)) + def mk_install(self, out): + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@cp %s %s\n' % (dllfile, os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@cp %s.jar %s.jar\n' % (self.package_name, os.path.join('$(PREFIX)', 'lib', self.package_name))) + + def mk_uninstall(self, out): + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@rm %s\n' % (os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@rm %s.jar\n' % (os.path.join('$(PREFIX)', 'lib', self.package_name))) class MLComponent(Component): def __init__(self, name, lib_name, path, deps): From 0ad97022a1d4181ccdd02cabaf168d83b8d58f5b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 7 Apr 2015 13:47:34 +0100 Subject: [PATCH 621/646] Added (un)install targets for the Java API --- scripts/mk_util.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 99df6aa4d..da2fbb8b5 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1344,6 +1344,15 @@ class JavaDLLComponent(Component): so = get_so_ext() shutil.copy(os.path.join(build_path, 'libz3java.%s' % so), os.path.join(dist_path, 'bin', 'libz3java.%s' % so)) + def mk_install(self, out): + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@cp %s %s\n' % (dllfile, os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@cp %s.jar %s.jar\n' % (self.package_name, os.path.join('$(PREFIX)', 'lib', self.package_name))) + + def mk_uninstall(self, out): + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@rm %s\n' % (os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@rm %s.jar\n' % (os.path.join('$(PREFIX)', 'lib', self.package_name))) class MLComponent(Component): def __init__(self, name, lib_name, path, deps): From 0e8d314a2af6224208b990e4986696b09e920afa Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Apr 2015 11:02:56 +0100 Subject: [PATCH 622/646] Fixed Java API installation targets. Fixes #28 --- scripts/mk_util.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index da2fbb8b5..cece133dd 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1275,6 +1275,7 @@ class JavaDLLComponent(Component): self.dll_name = dll_name self.package_name = package_name self.manifest_file = manifest_file + self.install = not is_windows() def mk_makefile(self, out): global JAVAC @@ -1344,15 +1345,18 @@ class JavaDLLComponent(Component): so = get_so_ext() shutil.copy(os.path.join(build_path, 'libz3java.%s' % so), os.path.join(dist_path, 'bin', 'libz3java.%s' % so)) + def mk_install(self, out): - dllfile = '%s$(SO_EXT)' % self.dll_name - out.write('\t@cp %s %s\n' % (dllfile, os.path.join('$(PREFIX)', 'lib', dllfile))) - out.write('\t@cp %s.jar %s.jar\n' % (self.package_name, os.path.join('$(PREFIX)', 'lib', self.package_name))) + if is_java_enabled() and self.install: + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@cp %s %s\n' % (dllfile, os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@cp %s.jar %s.jar\n' % (self.package_name, os.path.join('$(PREFIX)', 'lib', self.package_name))) def mk_uninstall(self, out): - dllfile = '%s$(SO_EXT)' % self.dll_name - out.write('\t@rm %s\n' % (os.path.join('$(PREFIX)', 'lib', dllfile))) - out.write('\t@rm %s.jar\n' % (os.path.join('$(PREFIX)', 'lib', self.package_name))) + if is_java_enabled() and self.install: + dllfile = '%s$(SO_EXT)' % self.dll_name + out.write('\t@rm %s\n' % (os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@rm %s.jar\n' % (os.path.join('$(PREFIX)', 'lib', self.package_name))) class MLComponent(Component): def __init__(self, name, lib_name, path, deps): From ba066ff8997efa5c4c8fe63a567e4a6fd20a7f6b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Apr 2015 11:54:25 +0100 Subject: [PATCH 623/646] Bugfix for build scripts. Partially fixes #27 --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index cece133dd..6c8230f3b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -572,7 +572,7 @@ def parse_options(): LINUX_X64=False elif opt in ('-h', '--help'): display_help(0) - elif opt in ('-m', '--onlymakefiles'): + elif opt in ('-m', '--makefiles'): ONLY_MAKEFILES = True elif opt in ('-c', '--showcpp'): SHOW_CPPS = True From 03020b9f9687b552cba1caeeee17ca1300515072 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Apr 2015 12:09:14 +0100 Subject: [PATCH 624/646] Build system bugfixes. Partially fixes #27 --- scripts/mk_util.py | 8 ++++---- scripts/update_api.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 6c8230f3b..547379aec 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2810,19 +2810,19 @@ def mk_z3consts_ml(api_files): if name not in DeprecatedEnums: efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in decls.iteritems(): + for k, i in decls.items(): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') - for k, i in decls.iteritems(): + for k, i in decls.items(): efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') - for k, i in decls.iteritems(): + for k, i in decls.items(): efile.write(' | %d -> %s\n' % (i, k[3:])) # use Z3.Exception? efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') @@ -2888,7 +2888,7 @@ def mk_z3consts_ml(api_files): if name not in DeprecatedEnums: efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in decls.iteritems(): + for k, i in decls.items(): efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) diff --git a/scripts/update_api.py b/scripts/update_api.py index 93800237e..e179043e2 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1169,7 +1169,7 @@ def mk_ml(): ml_i.write('type ptr\n') ml_native.write('and z3_symbol = ptr\n') ml_i.write('and z3_symbol = ptr\n') - for k, v in Type2Str.iteritems(): + for k, v in Type2Str.items(): if is_obj(k): ml_native.write('and %s = ptr\n' % v.lower()) ml_i.write('and %s = ptr\n' % v.lower()) From 2f4c923216f7f1e10da26306f85c5bd225c2a6c5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Apr 2015 13:09:27 +0100 Subject: [PATCH 625/646] Bugfix; InterpolationContext deleted Z3_config objects (inconsistent with non-Interpolation mk_context). Fixes #25 --- src/api/api_interp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 38d726761..5ec585c7d 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -66,7 +66,6 @@ extern "C" { // Z3_set_param_value(cfg, "SIMPLIFY_CLAUSES","false"); Z3_context ctx = Z3_mk_context(cfg); - Z3_del_config(cfg); return ctx; } From b7bb53406f7807daddf025d7849b2cf7b49c1fb4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Apr 2015 13:16:32 +0100 Subject: [PATCH 626/646] Turned Z3Exception into a RuntimeException such that throws declarations are not needed anymore. Thanks to codeplex user steimann for this suggestion. --- src/api/java/AST.java | 30 +- src/api/java/ASTMap.java | 22 +- src/api/java/ASTVector.java | 20 +- src/api/java/AlgebraicNum.java | 8 +- src/api/java/ApplyResult.java | 12 +- src/api/java/ArithExpr.java | 2 +- src/api/java/ArithSort.java | 2 +- src/api/java/ArrayExpr.java | 2 +- src/api/java/ArraySort.java | 8 +- src/api/java/BitVecExpr.java | 4 +- src/api/java/BitVecNum.java | 6 +- src/api/java/BitVecSort.java | 4 +- src/api/java/BoolExpr.java | 2 +- src/api/java/BoolSort.java | 4 +- src/api/java/Constructor.java | 12 +- src/api/java/ConstructorList.java | 6 +- src/api/java/Context.java | 584 ++++++++++++------------- src/api/java/DatatypeExpr.java | 2 +- src/api/java/DatatypeSort.java | 12 +- src/api/java/EnumSort.java | 14 +- src/api/java/Expr.java | 348 +++++++-------- src/api/java/FPExpr.java | 6 +- src/api/java/FPNum.java | 10 +- src/api/java/FPRMExpr.java | 2 +- src/api/java/FPRMNum.java | 22 +- src/api/java/FPRMSort.java | 4 +- src/api/java/FPSort.java | 8 +- src/api/java/FiniteDomainSort.java | 6 +- src/api/java/Fixedpoint.java | 50 +-- src/api/java/FuncDecl.java | 44 +- src/api/java/FuncInterp.java | 26 +- src/api/java/Global.java | 2 +- src/api/java/Goal.java | 42 +- src/api/java/IDisposable.java | 2 +- src/api/java/IntExpr.java | 2 +- src/api/java/IntNum.java | 8 +- src/api/java/IntSort.java | 4 +- src/api/java/IntSymbol.java | 8 +- src/api/java/InterpolationContext.java | 18 +- src/api/java/ListSort.java | 16 +- src/api/java/Log.java | 2 +- src/api/java/Model.java | 32 +- src/api/java/ParamDescrs.java | 14 +- src/api/java/Params.java | 24 +- src/api/java/Pattern.java | 6 +- src/api/java/Probe.java | 10 +- src/api/java/Quantifier.java | 30 +- src/api/java/RatNum.java | 12 +- src/api/java/RealExpr.java | 2 +- src/api/java/RealSort.java | 4 +- src/api/java/RelationSort.java | 6 +- src/api/java/SetSort.java | 4 +- src/api/java/Solver.java | 46 +- src/api/java/Sort.java | 12 +- src/api/java/Statistics.java | 16 +- src/api/java/StringSymbol.java | 8 +- src/api/java/Symbol.java | 10 +- src/api/java/Tactic.java | 18 +- src/api/java/TupleSort.java | 8 +- src/api/java/UninterpretedSort.java | 4 +- src/api/java/Z3Exception.java | 2 +- src/api/java/Z3Object.java | 14 +- 62 files changed, 834 insertions(+), 834 deletions(-) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 870f1d5d3..436a9fdcb 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -54,7 +54,7 @@ public class AST extends Z3Object * positive if after else zero. * @throws Z3Exception on error **/ - public int compareTo(Object other) throws Z3Exception + public int compareTo(Object other) { if (other == null) return 1; @@ -95,7 +95,7 @@ public class AST extends Z3Object * A unique identifier for the AST (unique among all ASTs). * @throws Z3Exception on error **/ - public int getId() throws Z3Exception + public int getId() { return Native.getAstId(getContext().nCtx(), getNativeObject()); } @@ -107,7 +107,7 @@ public class AST extends Z3Object * @return A copy of the AST which is associated with {@code ctx} * @throws Z3Exception on error **/ - public AST translate(Context ctx) throws Z3Exception + public AST translate(Context ctx) { if (getContext() == ctx) @@ -121,7 +121,7 @@ public class AST extends Z3Object * The kind of the AST. * @throws Z3Exception on error **/ - public Z3_ast_kind getASTKind() throws Z3Exception + public Z3_ast_kind getASTKind() { return Z3_ast_kind.fromInt(Native.getAstKind(getContext().nCtx(), getNativeObject())); @@ -132,7 +132,7 @@ public class AST extends Z3Object * @throws Z3Exception on error * @throws Z3Exception on error **/ - public boolean isExpr() throws Z3Exception + public boolean isExpr() { switch (getASTKind()) { @@ -151,7 +151,7 @@ public class AST extends Z3Object * @return a boolean * @throws Z3Exception on error **/ - public boolean isApp() throws Z3Exception + public boolean isApp() { return this.getASTKind() == Z3_ast_kind.Z3_APP_AST; } @@ -161,7 +161,7 @@ public class AST extends Z3Object * @return a boolean * @throws Z3Exception on error **/ - public boolean isVar() throws Z3Exception + public boolean isVar() { return this.getASTKind() == Z3_ast_kind.Z3_VAR_AST; } @@ -171,7 +171,7 @@ public class AST extends Z3Object * @return a boolean * @throws Z3Exception on error **/ - public boolean isQuantifier() throws Z3Exception + public boolean isQuantifier() { return this.getASTKind() == Z3_ast_kind.Z3_QUANTIFIER_AST; } @@ -179,7 +179,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a Sort **/ - public boolean isSort() throws Z3Exception + public boolean isSort() { return this.getASTKind() == Z3_ast_kind.Z3_SORT_AST; } @@ -187,7 +187,7 @@ public class AST extends Z3Object /** * Indicates whether the AST is a FunctionDeclaration **/ - public boolean isFuncDecl() throws Z3Exception + public boolean isFuncDecl() { return this.getASTKind() == Z3_ast_kind.Z3_FUNC_DECL_AST; } @@ -209,7 +209,7 @@ public class AST extends Z3Object /** * A string representation of the AST in s-expression notation. **/ - public String getSExpr() throws Z3Exception + public String getSExpr() { return Native.astToString(getContext().nCtx(), getNativeObject()); } @@ -219,12 +219,12 @@ public class AST extends Z3Object super(ctx); } - AST(Context ctx, long obj) throws Z3Exception + AST(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { // Console.WriteLine("AST IncRef()"); if (getContext() == null || o == 0) @@ -233,7 +233,7 @@ public class AST extends Z3Object super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { // Console.WriteLine("AST DecRef()"); if (getContext() == null || o == 0) @@ -242,7 +242,7 @@ public class AST extends Z3Object super.decRef(o); } - static AST create(Context ctx, long obj) throws Z3Exception + static AST create(Context ctx, long obj) { switch (Z3_ast_kind.fromInt(Native.getAstKind(ctx.nCtx(), obj))) { diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index a37e9d0ff..398aac77f 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -29,7 +29,7 @@ class ASTMap extends Z3Object * @return True if {@code k} is a key in the map, false * otherwise. **/ - public boolean contains(AST k) throws Z3Exception + public boolean contains(AST k) { return Native.astMapContains(getContext().nCtx(), getNativeObject(), @@ -44,7 +44,7 @@ class ASTMap extends Z3Object * * @throws Z3Exception **/ - public AST find(AST k) throws Z3Exception + public AST find(AST k) { return new AST(getContext(), Native.astMapFind(getContext().nCtx(), getNativeObject(), k.getNativeObject())); @@ -55,7 +55,7 @@ class ASTMap extends Z3Object * @param k The key AST * @param v The value AST **/ - public void insert(AST k, AST v) throws Z3Exception + public void insert(AST k, AST v) { Native.astMapInsert(getContext().nCtx(), getNativeObject(), k.getNativeObject(), @@ -66,7 +66,7 @@ class ASTMap extends Z3Object * Erases the key {@code k} from the map. * @param k An AST **/ - public void erase(AST k) throws Z3Exception + public void erase(AST k) { Native.astMapErase(getContext().nCtx(), getNativeObject(), k.getNativeObject()); } @@ -74,7 +74,7 @@ class ASTMap extends Z3Object /** * Removes all keys from the map. **/ - public void reset() throws Z3Exception + public void reset() { Native.astMapReset(getContext().nCtx(), getNativeObject()); } @@ -82,7 +82,7 @@ class ASTMap extends Z3Object /** * The size of the map **/ - public int size() throws Z3Exception + public int size() { return Native.astMapSize(getContext().nCtx(), getNativeObject()); } @@ -92,7 +92,7 @@ class ASTMap extends Z3Object * * @throws Z3Exception **/ - public ASTVector getKeys() throws Z3Exception + public ASTVector getKeys() { return new ASTVector(getContext(), Native.astMapKeys(getContext().nCtx(), getNativeObject())); @@ -112,23 +112,23 @@ class ASTMap extends Z3Object } } - ASTMap(Context ctx, long obj) throws Z3Exception + ASTMap(Context ctx, long obj) { super(ctx, obj); } - ASTMap(Context ctx) throws Z3Exception + ASTMap(Context ctx) { super(ctx, Native.mkAstMap(ctx.nCtx())); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getASTMapDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getASTMapDRQ().add(o); super.decRef(o); diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 03e1b0a98..9c6504493 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -25,7 +25,7 @@ public class ASTVector extends Z3Object /** * The size of the vector **/ - public int size() throws Z3Exception + public int size() { return Native.astVectorSize(getContext().nCtx(), getNativeObject()); } @@ -39,13 +39,13 @@ public class ASTVector extends Z3Object * @return An AST * @throws Z3Exception **/ - public AST get(int i) throws Z3Exception + public AST get(int i) { return new AST(getContext(), Native.astVectorGet(getContext().nCtx(), getNativeObject(), i)); } - public void set(int i, AST value) throws Z3Exception + public void set(int i, AST value) { Native.astVectorSet(getContext().nCtx(), getNativeObject(), i, @@ -56,7 +56,7 @@ public class ASTVector extends Z3Object * Resize the vector to {@code newSize}. * @param newSize The new size of the vector. **/ - public void resize(int newSize) throws Z3Exception + public void resize(int newSize) { Native.astVectorResize(getContext().nCtx(), getNativeObject(), newSize); } @@ -66,7 +66,7 @@ public class ASTVector extends Z3Object * increased by 1. * @param a An AST **/ - public void push(AST a) throws Z3Exception + public void push(AST a) { Native.astVectorPush(getContext().nCtx(), getNativeObject(), a.getNativeObject()); } @@ -78,7 +78,7 @@ public class ASTVector extends Z3Object * @return A new ASTVector * @throws Z3Exception **/ - public ASTVector translate(Context ctx) throws Z3Exception + public ASTVector translate(Context ctx) { return new ASTVector(getContext(), Native.astVectorTranslate(getContext() .nCtx(), getNativeObject(), ctx.nCtx())); @@ -98,23 +98,23 @@ public class ASTVector extends Z3Object } } - ASTVector(Context ctx, long obj) throws Z3Exception + ASTVector(Context ctx, long obj) { super(ctx, obj); } - ASTVector(Context ctx) throws Z3Exception + ASTVector(Context ctx) { super(ctx, Native.mkAstVector(ctx.nCtx())); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getASTVectorDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getASTVectorDRQ().add(o); super.decRef(o); diff --git a/src/api/java/AlgebraicNum.java b/src/api/java/AlgebraicNum.java index 322b24d39..6725d3937 100644 --- a/src/api/java/AlgebraicNum.java +++ b/src/api/java/AlgebraicNum.java @@ -32,7 +32,7 @@ public class AlgebraicNum extends ArithExpr * @return A numeral Expr of sort Real * @throws Z3Exception on error **/ - public RatNum toUpper(int precision) throws Z3Exception + public RatNum toUpper(int precision) { return new RatNum(getContext(), Native.getAlgebraicNumberUpper(getContext() @@ -49,7 +49,7 @@ public class AlgebraicNum extends ArithExpr * @return A numeral Expr of sort Real * @throws Z3Exception on error **/ - public RatNum toLower(int precision) throws Z3Exception + public RatNum toLower(int precision) { return new RatNum(getContext(), Native.getAlgebraicNumberLower(getContext() @@ -63,14 +63,14 @@ public class AlgebraicNum extends ArithExpr * @return String * @throws Z3Exception on error **/ - public String toDecimal(int precision) throws Z3Exception + public String toDecimal(int precision) { return Native.getNumeralDecimalString(getContext().nCtx(), getNativeObject(), precision); } - AlgebraicNum(Context ctx, long obj) throws Z3Exception + AlgebraicNum(Context ctx, long obj) { super(ctx, obj); diff --git a/src/api/java/ApplyResult.java b/src/api/java/ApplyResult.java index 8e998111f..2812efd70 100644 --- a/src/api/java/ApplyResult.java +++ b/src/api/java/ApplyResult.java @@ -26,7 +26,7 @@ public class ApplyResult extends Z3Object /** * The number of Subgoals. **/ - public int getNumSubgoals() throws Z3Exception + public int getNumSubgoals() { return Native.applyResultGetNumSubgoals(getContext().nCtx(), getNativeObject()); @@ -37,7 +37,7 @@ public class ApplyResult extends Z3Object * * @throws Z3Exception **/ - public Goal[] getSubgoals() throws Z3Exception + public Goal[] getSubgoals() { int n = getNumSubgoals(); Goal[] res = new Goal[n]; @@ -54,7 +54,7 @@ public class ApplyResult extends Z3Object * @return A model for {@code g} * @throws Z3Exception **/ - public Model convertModel(int i, Model m) throws Z3Exception + public Model convertModel(int i, Model m) { return new Model(getContext(), Native.applyResultConvertModel(getContext().nCtx(), getNativeObject(), i, m.getNativeObject())); @@ -74,18 +74,18 @@ public class ApplyResult extends Z3Object } } - ApplyResult(Context ctx, long obj) throws Z3Exception + ApplyResult(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getApplyResultDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getApplyResultDRQ().add(o); super.decRef(o); diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index 240518134..d92d8523b 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -25,7 +25,7 @@ public class ArithExpr extends Expr /** * Constructor for ArithExpr **/ - ArithExpr(Context ctx, long obj) throws Z3Exception + ArithExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/ArithSort.java b/src/api/java/ArithSort.java index 848d23554..5f4d4c1eb 100644 --- a/src/api/java/ArithSort.java +++ b/src/api/java/ArithSort.java @@ -22,7 +22,7 @@ package com.microsoft.z3; **/ public class ArithSort extends Sort { - ArithSort(Context ctx, long obj) throws Z3Exception + ArithSort(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index 4e6d9ed4d..b8318b648 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -26,7 +26,7 @@ public class ArrayExpr extends Expr /** * Constructor for ArrayExpr **/ - ArrayExpr(Context ctx, long obj) throws Z3Exception + ArrayExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/ArraySort.java b/src/api/java/ArraySort.java index a5b52a8f5..1574823d1 100644 --- a/src/api/java/ArraySort.java +++ b/src/api/java/ArraySort.java @@ -28,7 +28,7 @@ public class ArraySort extends Sort * @throws Z3Exception on error * @return a sort **/ - public Sort getDomain() throws Z3Exception + public Sort getDomain() { return Sort.create(getContext(), Native.getArraySortDomain(getContext().nCtx(), getNativeObject())); @@ -40,18 +40,18 @@ public class ArraySort extends Sort * @throws Z3Exception on error * @return a sort **/ - public Sort getRange() throws Z3Exception + public Sort getRange() { return Sort.create(getContext(), Native.getArraySortRange(getContext().nCtx(), getNativeObject())); } - ArraySort(Context ctx, long obj) throws Z3Exception + ArraySort(Context ctx, long obj) { super(ctx, obj); } - ArraySort(Context ctx, Sort domain, Sort range) throws Z3Exception + ArraySort(Context ctx, Sort domain, Sort range) { super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(), range.getNativeObject())); diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 926a26b25..175da9d66 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -29,7 +29,7 @@ public class BitVecExpr extends Expr * @throws Z3Exception on error * @return an int **/ - public int getSortSize() throws Z3Exception + public int getSortSize() { return ((BitVecSort) getSort()).getSize(); } @@ -37,7 +37,7 @@ public class BitVecExpr extends Expr /** * Constructor for BitVecExpr **/ - BitVecExpr(Context ctx, long obj) throws Z3Exception + BitVecExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/BitVecNum.java b/src/api/java/BitVecNum.java index 69ac5dadc..08da40256 100644 --- a/src/api/java/BitVecNum.java +++ b/src/api/java/BitVecNum.java @@ -29,7 +29,7 @@ public class BitVecNum extends BitVecExpr * * @throws Z3Exception **/ - public int getInt() throws Z3Exception + public int getInt() { Native.IntPtr res = new Native.IntPtr(); if (Native.getNumeralInt(getContext().nCtx(), getNativeObject(), res) ^ true) @@ -42,7 +42,7 @@ public class BitVecNum extends BitVecExpr * * @throws Z3Exception **/ - public long getLong() throws Z3Exception + public long getLong() { Native.LongPtr res = new Native.LongPtr(); if (Native.getNumeralInt64(getContext().nCtx(), getNativeObject(), res) ^ true) @@ -72,7 +72,7 @@ public class BitVecNum extends BitVecExpr } } - BitVecNum(Context ctx, long obj) throws Z3Exception + BitVecNum(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/BitVecSort.java b/src/api/java/BitVecSort.java index 7fd644acb..5c8e9a1e5 100644 --- a/src/api/java/BitVecSort.java +++ b/src/api/java/BitVecSort.java @@ -27,12 +27,12 @@ public class BitVecSort extends Sort * @throws Z3Exception on error * @return an int **/ - public int getSize() throws Z3Exception + public int getSize() { return Native.getBvSortSize(getContext().nCtx(), getNativeObject()); } - BitVecSort(Context ctx, long obj) throws Z3Exception + BitVecSort(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index 6709e2ae9..02eabd2b5 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -35,7 +35,7 @@ public class BoolExpr extends Expr * @throws Z3Exception * @throws Z3Exception on error **/ - BoolExpr(Context ctx, long obj) throws Z3Exception + BoolExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/BoolSort.java b/src/api/java/BoolSort.java index 85ca0a7f7..66a4ddaa9 100644 --- a/src/api/java/BoolSort.java +++ b/src/api/java/BoolSort.java @@ -22,6 +22,6 @@ package com.microsoft.z3; **/ public class BoolSort extends Sort { - BoolSort(Context ctx, long obj) throws Z3Exception { super(ctx, obj); { }} - BoolSort(Context ctx) throws Z3Exception { super(ctx, Native.mkBoolSort(ctx.nCtx())); { }} + BoolSort(Context ctx, long obj) { super(ctx, obj); { }} + BoolSort(Context ctx) { super(ctx, Native.mkBoolSort(ctx.nCtx())); { }} }; diff --git a/src/api/java/Constructor.java b/src/api/java/Constructor.java index 95e7799e1..2ceaddcff 100644 --- a/src/api/java/Constructor.java +++ b/src/api/java/Constructor.java @@ -28,7 +28,7 @@ public class Constructor extends Z3Object * @throws Z3Exception on error * @return an int **/ - public int getNumFields() throws Z3Exception + public int getNumFields() { return n; } @@ -38,7 +38,7 @@ public class Constructor extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public FuncDecl ConstructorDecl() throws Z3Exception + public FuncDecl ConstructorDecl() { Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); @@ -52,7 +52,7 @@ public class Constructor extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public FuncDecl getTesterDecl() throws Z3Exception + public FuncDecl getTesterDecl() { Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); @@ -66,7 +66,7 @@ public class Constructor extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public FuncDecl[] getAccessorDecls() throws Z3Exception + public FuncDecl[] getAccessorDecls() { Native.LongPtr constructor = new Native.LongPtr(); Native.LongPtr tester = new Native.LongPtr(); @@ -82,7 +82,7 @@ public class Constructor extends Z3Object * Destructor. * @throws Z3Exception on error **/ - protected void finalize() throws Z3Exception + protected void finalize() { Native.delConstructor(getContext().nCtx(), getNativeObject()); } @@ -91,7 +91,7 @@ public class Constructor extends Z3Object Constructor(Context ctx, Symbol name, Symbol recognizer, Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) - throws Z3Exception + { super(ctx); diff --git a/src/api/java/ConstructorList.java b/src/api/java/ConstructorList.java index 0cff4cfa4..2b3aa94e2 100644 --- a/src/api/java/ConstructorList.java +++ b/src/api/java/ConstructorList.java @@ -26,17 +26,17 @@ public class ConstructorList extends Z3Object * Destructor. * @throws Z3Exception on error **/ - protected void finalize() throws Z3Exception + protected void finalize() { Native.delConstructorList(getContext().nCtx(), getNativeObject()); } - ConstructorList(Context ctx, long obj) throws Z3Exception + ConstructorList(Context ctx, long obj) { super(ctx, obj); } - ConstructorList(Context ctx, Constructor[] constructors) throws Z3Exception + ConstructorList(Context ctx, Constructor[] constructors) { super(ctx); diff --git a/src/api/java/Context.java b/src/api/java/Context.java index ce7cef5c2..744cfc03f 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -29,7 +29,7 @@ public class Context extends IDisposable /** * Constructor. **/ - public Context() throws Z3Exception + public Context() { super(); m_ctx = Native.mkContextRc(0); @@ -53,7 +53,7 @@ public class Context extends IDisposable * Note that in previous versions of Z3, this constructor was also used to set global and * module parameters. For this purpose we should now use {@code Global.setParameter} **/ - public Context(Map settings) throws Z3Exception + public Context(Map settings) { super(); long cfg = Native.mkConfig(); @@ -69,7 +69,7 @@ public class Context extends IDisposable * Remarks: Not all integers can be passed to this function. * The legal range of unsigned integers is 0 to 2^30-1. **/ - public IntSymbol mkSymbol(int i) throws Z3Exception + public IntSymbol mkSymbol(int i) { return new IntSymbol(this, i); } @@ -77,7 +77,7 @@ public class Context extends IDisposable /** * Create a symbol using a string. **/ - public StringSymbol mkSymbol(String name) throws Z3Exception + public StringSymbol mkSymbol(String name) { return new StringSymbol(this, name); } @@ -85,7 +85,7 @@ public class Context extends IDisposable /** * Create an array of symbols. **/ - Symbol[] mkSymbols(String[] names) throws Z3Exception + Symbol[] mkSymbols(String[] names) { if (names == null) return null; @@ -102,7 +102,7 @@ public class Context extends IDisposable /** * Retrieves the Boolean sort of the context. **/ - public BoolSort getBoolSort() throws Z3Exception + public BoolSort getBoolSort() { if (m_boolSort == null) m_boolSort = new BoolSort(this); @@ -112,7 +112,7 @@ public class Context extends IDisposable /** * Retrieves the Integer sort of the context. **/ - public IntSort getIntSort() throws Z3Exception + public IntSort getIntSort() { if (m_intSort == null) m_intSort = new IntSort(this); @@ -122,7 +122,7 @@ public class Context extends IDisposable /** * Retrieves the Real sort of the context. **/ - public RealSort getRealSort() throws Z3Exception + public RealSort getRealSort() { if (m_realSort == null) m_realSort = new RealSort(this); @@ -132,7 +132,7 @@ public class Context extends IDisposable /** * Create a new Boolean sort. **/ - public BoolSort mkBoolSort() throws Z3Exception + public BoolSort mkBoolSort() { return new BoolSort(this); } @@ -140,7 +140,7 @@ public class Context extends IDisposable /** * Create a new uninterpreted sort. **/ - public UninterpretedSort mkUninterpretedSort(Symbol s) throws Z3Exception + public UninterpretedSort mkUninterpretedSort(Symbol s) { checkContextMatch(s); return new UninterpretedSort(this, s); @@ -149,7 +149,7 @@ public class Context extends IDisposable /** * Create a new uninterpreted sort. **/ - public UninterpretedSort mkUninterpretedSort(String str) throws Z3Exception + public UninterpretedSort mkUninterpretedSort(String str) { return mkUninterpretedSort(mkSymbol(str)); } @@ -157,7 +157,7 @@ public class Context extends IDisposable /** * Create a new integer sort. **/ - public IntSort mkIntSort() throws Z3Exception + public IntSort mkIntSort() { return new IntSort(this); } @@ -165,7 +165,7 @@ public class Context extends IDisposable /** * Create a real sort. **/ - public RealSort mkRealSort() throws Z3Exception + public RealSort mkRealSort() { return new RealSort(this); } @@ -173,7 +173,7 @@ public class Context extends IDisposable /** * Create a new bit-vector sort. **/ - public BitVecSort mkBitVecSort(int size) throws Z3Exception + public BitVecSort mkBitVecSort(int size) { return new BitVecSort(this, Native.mkBvSort(nCtx(), size)); } @@ -181,7 +181,7 @@ public class Context extends IDisposable /** * Create a new array sort. **/ - public ArraySort mkArraySort(Sort domain, Sort range) throws Z3Exception + public ArraySort mkArraySort(Sort domain, Sort range) { checkContextMatch(domain); checkContextMatch(range); @@ -192,7 +192,7 @@ public class Context extends IDisposable * Create a new tuple sort. **/ public TupleSort mkTupleSort(Symbol name, Symbol[] fieldNames, - Sort[] fieldSorts) throws Z3Exception + Sort[] fieldSorts) { checkContextMatch(name); checkContextMatch(fieldNames); @@ -205,7 +205,7 @@ public class Context extends IDisposable * Create a new enumeration sort. **/ public EnumSort mkEnumSort(Symbol name, Symbol... enumNames) - throws Z3Exception + { checkContextMatch(name); checkContextMatch(enumNames); @@ -216,7 +216,7 @@ public class Context extends IDisposable * Create a new enumeration sort. **/ public EnumSort mkEnumSort(String name, String... enumNames) - throws Z3Exception + { return new EnumSort(this, mkSymbol(name), mkSymbols(enumNames)); } @@ -224,7 +224,7 @@ public class Context extends IDisposable /** * Create a new list sort. **/ - public ListSort mkListSort(Symbol name, Sort elemSort) throws Z3Exception + public ListSort mkListSort(Symbol name, Sort elemSort) { checkContextMatch(name); checkContextMatch(elemSort); @@ -234,7 +234,7 @@ public class Context extends IDisposable /** * Create a new list sort. **/ - public ListSort mkListSort(String name, Sort elemSort) throws Z3Exception + public ListSort mkListSort(String name, Sort elemSort) { checkContextMatch(elemSort); return new ListSort(this, mkSymbol(name), elemSort); @@ -244,7 +244,7 @@ public class Context extends IDisposable * Create a new finite domain sort. **/ public FiniteDomainSort mkFiniteDomainSort(Symbol name, long size) - throws Z3Exception + { checkContextMatch(name); return new FiniteDomainSort(this, name, size); @@ -254,7 +254,7 @@ public class Context extends IDisposable * Create a new finite domain sort. **/ public FiniteDomainSort mkFiniteDomainSort(String name, long size) - throws Z3Exception + { return new FiniteDomainSort(this, mkSymbol(name), size); } @@ -272,7 +272,7 @@ public class Context extends IDisposable **/ public Constructor mkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames, Sort[] sorts, int[] sortRefs) - throws Z3Exception + { return new Constructor(this, name, recognizer, fieldNames, sorts, @@ -291,7 +291,7 @@ public class Context extends IDisposable **/ public Constructor mkConstructor(String name, String recognizer, String[] fieldNames, Sort[] sorts, int[] sortRefs) - throws Z3Exception + { return new Constructor(this, mkSymbol(name), mkSymbol(recognizer), @@ -302,7 +302,7 @@ public class Context extends IDisposable * Create a new datatype sort. **/ public DatatypeSort mkDatatypeSort(Symbol name, Constructor[] constructors) - throws Z3Exception + { checkContextMatch(name); checkContextMatch(constructors); @@ -313,7 +313,7 @@ public class Context extends IDisposable * Create a new datatype sort. **/ public DatatypeSort mkDatatypeSort(String name, Constructor[] constructors) - throws Z3Exception + { checkContextMatch(constructors); return new DatatypeSort(this, mkSymbol(name), constructors); @@ -325,7 +325,7 @@ public class Context extends IDisposable * @param c list of constructors, one list per sort. **/ public DatatypeSort[] mkDatatypeSorts(Symbol[] names, Constructor[][] c) - throws Z3Exception + { checkContextMatch(names); int n = (int) names.length; @@ -356,7 +356,7 @@ public class Context extends IDisposable * @return **/ public DatatypeSort[] mkDatatypeSorts(String[] names, Constructor[][] c) - throws Z3Exception + { return mkDatatypeSorts(mkSymbols(names), c); } @@ -365,7 +365,7 @@ public class Context extends IDisposable * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(Symbol name, Sort[] domain, Sort range) - throws Z3Exception + { checkContextMatch(name); checkContextMatch(domain); @@ -377,7 +377,7 @@ public class Context extends IDisposable * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(Symbol name, Sort domain, Sort range) - throws Z3Exception + { checkContextMatch(name); checkContextMatch(domain); @@ -390,7 +390,7 @@ public class Context extends IDisposable * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(String name, Sort[] domain, Sort range) - throws Z3Exception + { checkContextMatch(domain); checkContextMatch(range); @@ -401,7 +401,7 @@ public class Context extends IDisposable * Creates a new function declaration. **/ public FuncDecl mkFuncDecl(String name, Sort domain, Sort range) - throws Z3Exception + { checkContextMatch(domain); checkContextMatch(range); @@ -416,7 +416,7 @@ public class Context extends IDisposable * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range) - throws Z3Exception + { checkContextMatch(domain); checkContextMatch(range); @@ -426,7 +426,7 @@ public class Context extends IDisposable /** * Creates a new constant function declaration. **/ - public FuncDecl mkConstDecl(Symbol name, Sort range) throws Z3Exception + public FuncDecl mkConstDecl(Symbol name, Sort range) { checkContextMatch(name); checkContextMatch(range); @@ -436,7 +436,7 @@ public class Context extends IDisposable /** * Creates a new constant function declaration. **/ - public FuncDecl mkConstDecl(String name, Sort range) throws Z3Exception + public FuncDecl mkConstDecl(String name, Sort range) { checkContextMatch(range); return new FuncDecl(this, mkSymbol(name), null, range); @@ -449,7 +449,7 @@ public class Context extends IDisposable * @see mkFuncDecl(String,Sort[],Sort) **/ public FuncDecl mkFreshConstDecl(String prefix, Sort range) - throws Z3Exception + { checkContextMatch(range); return new FuncDecl(this, prefix, null, range); @@ -460,7 +460,7 @@ public class Context extends IDisposable * @param index The de-Bruijn index of the variable * @param ty The sort of the variable **/ - public Expr mkBound(int index, Sort ty) throws Z3Exception + public Expr mkBound(int index, Sort ty) { return Expr.create(this, Native.mkBound(nCtx(), index, ty.getNativeObject())); @@ -469,7 +469,7 @@ public class Context extends IDisposable /** * Create a quantifier pattern. **/ - public Pattern mkPattern(Expr... terms) throws Z3Exception + public Pattern mkPattern(Expr... terms) { if (terms.length == 0) throw new Z3Exception("Cannot create a pattern from zero terms"); @@ -483,7 +483,7 @@ public class Context extends IDisposable * Creates a new Constant of sort {@code range} and named * {@code name}. **/ - public Expr mkConst(Symbol name, Sort range) throws Z3Exception + public Expr mkConst(Symbol name, Sort range) { checkContextMatch(name); checkContextMatch(range); @@ -498,7 +498,7 @@ public class Context extends IDisposable * Creates a new Constant of sort {@code range} and named * {@code name}. **/ - public Expr mkConst(String name, Sort range) throws Z3Exception + public Expr mkConst(String name, Sort range) { return mkConst(mkSymbol(name), range); } @@ -507,7 +507,7 @@ public class Context extends IDisposable * Creates a fresh Constant of sort {@code range} and a name * prefixed with {@code prefix}. **/ - public Expr mkFreshConst(String prefix, Sort range) throws Z3Exception + public Expr mkFreshConst(String prefix, Sort range) { checkContextMatch(range); return Expr.create(this, @@ -518,7 +518,7 @@ public class Context extends IDisposable * Creates a fresh constant from the FuncDecl {@code f}. * @param f A decl of a 0-arity function **/ - public Expr mkConst(FuncDecl f) throws Z3Exception + public Expr mkConst(FuncDecl f) { return mkApp(f, (Expr[]) null); } @@ -526,7 +526,7 @@ public class Context extends IDisposable /** * Create a Boolean constant. **/ - public BoolExpr mkBoolConst(Symbol name) throws Z3Exception + public BoolExpr mkBoolConst(Symbol name) { return (BoolExpr) mkConst(name, getBoolSort()); } @@ -534,7 +534,7 @@ public class Context extends IDisposable /** * Create a Boolean constant. **/ - public BoolExpr mkBoolConst(String name) throws Z3Exception + public BoolExpr mkBoolConst(String name) { return (BoolExpr) mkConst(mkSymbol(name), getBoolSort()); } @@ -542,7 +542,7 @@ public class Context extends IDisposable /** * Creates an integer constant. **/ - public IntExpr mkIntConst(Symbol name) throws Z3Exception + public IntExpr mkIntConst(Symbol name) { return (IntExpr) mkConst(name, getIntSort()); } @@ -550,7 +550,7 @@ public class Context extends IDisposable /** * Creates an integer constant. **/ - public IntExpr mkIntConst(String name) throws Z3Exception + public IntExpr mkIntConst(String name) { return (IntExpr) mkConst(name, getIntSort()); } @@ -558,7 +558,7 @@ public class Context extends IDisposable /** * Creates a real constant. **/ - public RealExpr mkRealConst(Symbol name) throws Z3Exception + public RealExpr mkRealConst(Symbol name) { return (RealExpr) mkConst(name, getRealSort()); } @@ -566,7 +566,7 @@ public class Context extends IDisposable /** * Creates a real constant. **/ - public RealExpr mkRealConst(String name) throws Z3Exception + public RealExpr mkRealConst(String name) { return (RealExpr) mkConst(name, getRealSort()); } @@ -574,7 +574,7 @@ public class Context extends IDisposable /** * Creates a bit-vector constant. **/ - public BitVecExpr mkBVConst(Symbol name, int size) throws Z3Exception + public BitVecExpr mkBVConst(Symbol name, int size) { return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } @@ -582,7 +582,7 @@ public class Context extends IDisposable /** * Creates a bit-vector constant. **/ - public BitVecExpr mkBVConst(String name, int size) throws Z3Exception + public BitVecExpr mkBVConst(String name, int size) { return (BitVecExpr) mkConst(name, mkBitVecSort(size)); } @@ -590,7 +590,7 @@ public class Context extends IDisposable /** * Create a new function application. **/ - public Expr mkApp(FuncDecl f, Expr... args) throws Z3Exception + public Expr mkApp(FuncDecl f, Expr... args) { checkContextMatch(f); checkContextMatch(args); @@ -600,7 +600,7 @@ public class Context extends IDisposable /** * The true Term. **/ - public BoolExpr mkTrue() throws Z3Exception + public BoolExpr mkTrue() { return new BoolExpr(this, Native.mkTrue(nCtx())); } @@ -608,7 +608,7 @@ public class Context extends IDisposable /** * The false Term. **/ - public BoolExpr mkFalse() throws Z3Exception + public BoolExpr mkFalse() { return new BoolExpr(this, Native.mkFalse(nCtx())); } @@ -616,7 +616,7 @@ public class Context extends IDisposable /** * Creates a Boolean value. **/ - public BoolExpr mkBool(boolean value) throws Z3Exception + public BoolExpr mkBool(boolean value) { return value ? mkTrue() : mkFalse(); } @@ -624,7 +624,7 @@ public class Context extends IDisposable /** * Creates the equality {@code x"/> = to every subgoal produced by evaluates to true and level. **/ public void addCover(int level, FuncDecl predicate, Expr property) - throws Z3Exception + { Native.fixedpointAddCover(getContext().nCtx(), getNativeObject(), level, predicate.getNativeObject(), property.getNativeObject()); @@ -269,7 +269,7 @@ public class Fixedpoint extends Z3Object * Instrument the Datalog engine on which table representation to use for * recursive predicate. **/ - public void setPredicateRepresentation(FuncDecl f, Symbol[] kinds) throws Z3Exception + public void setPredicateRepresentation(FuncDecl f, Symbol[] kinds) { Native.fixedpointSetPredicateRepresentation(getContext().nCtx(), @@ -281,7 +281,7 @@ public class Fixedpoint extends Z3Object /** * Convert benchmark given as set of axioms, rules and queries to a string. **/ - public String toString(BoolExpr[] queries) throws Z3Exception + public String toString(BoolExpr[] queries) { return Native.fixedpointToString(getContext().nCtx(), getNativeObject(), @@ -293,7 +293,7 @@ public class Fixedpoint extends Z3Object * * @throws Z3Exception **/ - public BoolExpr[] getRules() throws Z3Exception + public BoolExpr[] getRules() { ASTVector v = new ASTVector(getContext(), Native.fixedpointGetRules( @@ -310,7 +310,7 @@ public class Fixedpoint extends Z3Object * * @throws Z3Exception **/ - public BoolExpr[] getAssertions() throws Z3Exception + public BoolExpr[] getAssertions() { ASTVector v = new ASTVector(getContext(), Native.fixedpointGetAssertions( @@ -322,23 +322,23 @@ public class Fixedpoint extends Z3Object return res; } - Fixedpoint(Context ctx, long obj) throws Z3Exception + Fixedpoint(Context ctx, long obj) { super(ctx, obj); } - Fixedpoint(Context ctx) throws Z3Exception + Fixedpoint(Context ctx) { super(ctx, Native.mkFixedpoint(ctx.nCtx())); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getFixedpointDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getFixedpointDRQ().add(o); super.decRef(o); diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index e9b05f08c..f7e9de2b2 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -78,7 +78,7 @@ public class FuncDecl extends AST /** * Returns a unique identifier for the function declaration. **/ - public int getId() throws Z3Exception + public int getId() { return Native.getFuncDeclId(getContext().nCtx(), getNativeObject()); } @@ -86,7 +86,7 @@ public class FuncDecl extends AST /** * The arity of the function declaration **/ - public int getArity() throws Z3Exception + public int getArity() { return Native.getArity(getContext().nCtx(), getNativeObject()); } @@ -95,7 +95,7 @@ public class FuncDecl extends AST * The size of the domain of the function declaration * @see getArity **/ - public int getDomainSize() throws Z3Exception + public int getDomainSize() { return Native.getDomainSize(getContext().nCtx(), getNativeObject()); } @@ -103,7 +103,7 @@ public class FuncDecl extends AST /** * The domain of the function declaration **/ - public Sort[] getDomain() throws Z3Exception + public Sort[] getDomain() { int n = getDomainSize(); @@ -118,7 +118,7 @@ public class FuncDecl extends AST /** * The range of the function declaration **/ - public Sort getRange() throws Z3Exception + public Sort getRange() { return Sort.create(getContext(), @@ -128,7 +128,7 @@ public class FuncDecl extends AST /** * The kind of the function declaration. **/ - public Z3_decl_kind getDeclKind() throws Z3Exception + public Z3_decl_kind getDeclKind() { return Z3_decl_kind.fromInt(Native.getDeclKind(getContext().nCtx(), getNativeObject())); @@ -137,7 +137,7 @@ public class FuncDecl extends AST /** * The name of the function declaration **/ - public Symbol getName() throws Z3Exception + public Symbol getName() { return Symbol.create(getContext(), @@ -147,7 +147,7 @@ public class FuncDecl extends AST /** * The number of parameters of the function declaration **/ - public int getNumParameters() throws Z3Exception + public int getNumParameters() { return Native.getDeclNumParameters(getContext().nCtx(), getNativeObject()); } @@ -155,7 +155,7 @@ public class FuncDecl extends AST /** * The parameters of the function declaration **/ - public Parameter[] getParameters() throws Z3Exception + public Parameter[] getParameters() { int num = getNumParameters(); @@ -223,7 +223,7 @@ public class FuncDecl extends AST /** * The int value of the parameter. **/ - public int getInt() throws Z3Exception + public int getInt() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_INT) throw new Z3Exception("parameter is not an int"); @@ -233,7 +233,7 @@ public class FuncDecl extends AST /** * The double value of the parameter. **/ - public double getDouble() throws Z3Exception + public double getDouble() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_DOUBLE) throw new Z3Exception("parameter is not a double "); @@ -243,7 +243,7 @@ public class FuncDecl extends AST /** * The Symbol value of the parameter. **/ - public Symbol getSymbol() throws Z3Exception + public Symbol getSymbol() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_SYMBOL) throw new Z3Exception("parameter is not a Symbol"); @@ -253,7 +253,7 @@ public class FuncDecl extends AST /** * The Sort value of the parameter. **/ - public Sort getSort() throws Z3Exception + public Sort getSort() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_SORT) throw new Z3Exception("parameter is not a Sort"); @@ -263,7 +263,7 @@ public class FuncDecl extends AST /** * The AST value of the parameter. **/ - public AST getAST() throws Z3Exception + public AST getAST() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_AST) throw new Z3Exception("parameter is not an AST"); @@ -273,7 +273,7 @@ public class FuncDecl extends AST /** * The FunctionDeclaration value of the parameter. **/ - public FuncDecl getFuncDecl() throws Z3Exception + public FuncDecl getFuncDecl() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_FUNC_DECL) throw new Z3Exception("parameter is not a function declaration"); @@ -283,7 +283,7 @@ public class FuncDecl extends AST /** * The rational string value of the parameter. **/ - public String getRational() throws Z3Exception + public String getRational() { if (getParameterKind() != Z3_parameter_kind.Z3_PARAMETER_RATIONAL) throw new Z3Exception("parameter is not a rational String"); @@ -293,7 +293,7 @@ public class FuncDecl extends AST /** * The kind of the parameter. **/ - public Z3_parameter_kind getParameterKind() throws Z3Exception + public Z3_parameter_kind getParameterKind() { return kind; } @@ -341,14 +341,14 @@ public class FuncDecl extends AST } } - FuncDecl(Context ctx, long obj) throws Z3Exception + FuncDecl(Context ctx, long obj) { super(ctx, obj); } FuncDecl(Context ctx, Symbol name, Sort[] domain, Sort range) - throws Z3Exception + { super(ctx, Native.mkFuncDecl(ctx.nCtx(), name.getNativeObject(), AST.arrayLength(domain), AST.arrayToNative(domain), @@ -357,7 +357,7 @@ public class FuncDecl extends AST } FuncDecl(Context ctx, String prefix, Sort[] domain, Sort range) - throws Z3Exception + { super(ctx, Native.mkFreshFuncDecl(ctx.nCtx(), prefix, AST.arrayLength(domain), AST.arrayToNative(domain), @@ -365,7 +365,7 @@ public class FuncDecl extends AST } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { if (Native.getAstKind(getContext().nCtx(), obj) != Z3_ast_kind.Z3_FUNC_DECL_AST .toInt()) @@ -380,7 +380,7 @@ public class FuncDecl extends AST * * @return **/ - public Expr apply(Expr ... args) throws Z3Exception + public Expr apply(Expr ... args) { getContext().checkContextMatch(args); return Expr.create(getContext(), this, args); diff --git a/src/api/java/FuncInterp.java b/src/api/java/FuncInterp.java index 31f37a4ba..59a8a0398 100644 --- a/src/api/java/FuncInterp.java +++ b/src/api/java/FuncInterp.java @@ -36,7 +36,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public Expr getValue() throws Z3Exception + public Expr getValue() { return Expr.create(getContext(), Native.funcEntryGetValue(getContext().nCtx(), getNativeObject())); @@ -46,7 +46,7 @@ public class FuncInterp extends Z3Object * The number of arguments of the entry. * @throws Z3Exception on error **/ - public int getNumArgs() throws Z3Exception + public int getNumArgs() { return Native.funcEntryGetNumArgs(getContext().nCtx(), getNativeObject()); } @@ -57,7 +57,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public Expr[] getArgs() throws Z3Exception + public Expr[] getArgs() { int n = getNumArgs(); Expr[] res = new Expr[n]; @@ -86,18 +86,18 @@ public class FuncInterp extends Z3Object } } - Entry(Context ctx, long obj) throws Z3Exception + Entry(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getFuncEntryDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getFuncEntryDRQ().add(o); super.decRef(o); @@ -109,7 +109,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception on error * @return an int **/ - public int getNumEntries() throws Z3Exception + public int getNumEntries() { return Native.funcInterpGetNumEntries(getContext().nCtx(), getNativeObject()); } @@ -120,7 +120,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception * @throws Z3Exception on error **/ - public Entry[] getEntries() throws Z3Exception + public Entry[] getEntries() { int n = getNumEntries(); Entry[] res = new Entry[n]; @@ -137,7 +137,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception on error * @return an Expr **/ - public Expr getElse() throws Z3Exception + public Expr getElse() { return Expr.create(getContext(), Native.funcInterpGetElse(getContext().nCtx(), getNativeObject())); @@ -148,7 +148,7 @@ public class FuncInterp extends Z3Object * @throws Z3Exception on error * @return an int **/ - public int getArity() throws Z3Exception + public int getArity() { return Native.funcInterpGetArity(getContext().nCtx(), getNativeObject()); } @@ -187,18 +187,18 @@ public class FuncInterp extends Z3Object } } - FuncInterp(Context ctx, long obj) throws Z3Exception + FuncInterp(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getFuncInterpDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getFuncInterpDRQ().add(o); super.decRef(o); diff --git a/src/api/java/Global.java b/src/api/java/Global.java index 65bae9a01..67a051792 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -81,7 +81,7 @@ public final class Global * globally. **/ public static void ToggleWarningMessages(boolean enabled) - throws Z3Exception + { Native.toggleWarningMessages((enabled) ? true : false); } diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index 64f2e0acb..18aecb557 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -33,7 +33,7 @@ public class Goal extends Z3Object * applied when the objective is to find a proof for a given goal. * **/ - public Z3_goal_prec getPrecision() throws Z3Exception + public Z3_goal_prec getPrecision() { return Z3_goal_prec.fromInt(Native.goalPrecision(getContext().nCtx(), getNativeObject())); @@ -42,7 +42,7 @@ public class Goal extends Z3Object /** * Indicates whether the goal is precise. **/ - public boolean isPrecise() throws Z3Exception + public boolean isPrecise() { return getPrecision() == Z3_goal_prec.Z3_GOAL_PRECISE; } @@ -50,7 +50,7 @@ public class Goal extends Z3Object /** * Indicates whether the goal is an under-approximation. **/ - public boolean isUnderApproximation() throws Z3Exception + public boolean isUnderApproximation() { return getPrecision() == Z3_goal_prec.Z3_GOAL_UNDER; } @@ -58,7 +58,7 @@ public class Goal extends Z3Object /** * Indicates whether the goal is an over-approximation. **/ - public boolean isOverApproximation() throws Z3Exception + public boolean isOverApproximation() { return getPrecision() == Z3_goal_prec.Z3_GOAL_OVER; } @@ -67,7 +67,7 @@ public class Goal extends Z3Object * Indicates whether the goal is garbage (i.e., the product of over- and * under-approximations). **/ - public boolean isGarbage() throws Z3Exception + public boolean isGarbage() { return getPrecision() == Z3_goal_prec.Z3_GOAL_UNDER_OVER; } @@ -77,7 +77,7 @@ public class Goal extends Z3Object * * @throws Z3Exception **/ - public void add(BoolExpr ... constraints) throws Z3Exception + public void add(BoolExpr ... constraints) { getContext().checkContextMatch(constraints); for (BoolExpr c : constraints) @@ -90,7 +90,7 @@ public class Goal extends Z3Object /** * Indicates whether the goal contains `false'. **/ - public boolean inconsistent() throws Z3Exception + public boolean inconsistent() { return Native.goalInconsistent(getContext().nCtx(), getNativeObject()); } @@ -100,7 +100,7 @@ public class Goal extends Z3Object * Remarks: This tracks how many transformations * were applied to it. **/ - public int getDepth() throws Z3Exception + public int getDepth() { return Native.goalDepth(getContext().nCtx(), getNativeObject()); } @@ -108,7 +108,7 @@ public class Goal extends Z3Object /** * Erases all formulas from the given goal. **/ - public void reset() throws Z3Exception + public void reset() { Native.goalReset(getContext().nCtx(), getNativeObject()); } @@ -116,7 +116,7 @@ public class Goal extends Z3Object /** * The number of formulas in the goal. **/ - public int size() throws Z3Exception + public int size() { return Native.goalSize(getContext().nCtx(), getNativeObject()); } @@ -126,7 +126,7 @@ public class Goal extends Z3Object * * @throws Z3Exception **/ - public BoolExpr[] getFormulas() throws Z3Exception + public BoolExpr[] getFormulas() { int n = size(); BoolExpr[] res = new BoolExpr[n]; @@ -139,7 +139,7 @@ public class Goal extends Z3Object /** * The number of formulas, subformulas and terms in the goal. **/ - public int getNumExprs() throws Z3Exception + public int getNumExprs() { return Native.goalNumExprs(getContext().nCtx(), getNativeObject()); } @@ -148,7 +148,7 @@ public class Goal extends Z3Object * Indicates whether the goal is empty, and it is precise or the product of * an under approximation. **/ - public boolean isDecidedSat() throws Z3Exception + public boolean isDecidedSat() { return Native.goalIsDecidedSat(getContext().nCtx(), getNativeObject()); } @@ -157,7 +157,7 @@ public class Goal extends Z3Object * Indicates whether the goal contains `false', and it is precise or the * product of an over approximation. **/ - public boolean isDecidedUnsat() throws Z3Exception + public boolean isDecidedUnsat() { return Native .goalIsDecidedUnsat(getContext().nCtx(), getNativeObject()); @@ -168,7 +168,7 @@ public class Goal extends Z3Object * * @throws Z3Exception **/ - public Goal translate(Context ctx) throws Z3Exception + public Goal translate(Context ctx) { return new Goal(ctx, Native.goalTranslate(getContext().nCtx(), getNativeObject(), ctx.nCtx())); @@ -179,7 +179,7 @@ public class Goal extends Z3Object * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ - public Goal simplify() throws Z3Exception + public Goal simplify() { Tactic t = getContext().mkTactic("simplify"); ApplyResult res = t.apply(this); @@ -195,7 +195,7 @@ public class Goal extends Z3Object * Remarks: Essentially invokes the `simplify' tactic * on the goal. **/ - public Goal simplify(Params p) throws Z3Exception + public Goal simplify(Params p) { Tactic t = getContext().mkTactic("simplify"); ApplyResult res = t.apply(this, p); @@ -222,25 +222,25 @@ public class Goal extends Z3Object } } - Goal(Context ctx, long obj) throws Z3Exception + Goal(Context ctx, long obj) { super(ctx, obj); } Goal(Context ctx, boolean models, boolean unsatCores, boolean proofs) - throws Z3Exception + { super(ctx, Native.mkGoal(ctx.nCtx(), (models) ? true : false, (unsatCores) ? true : false, (proofs) ? true : false)); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getGoalDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getGoalDRQ().add(o); super.decRef(o); diff --git a/src/api/java/IDisposable.java b/src/api/java/IDisposable.java index dddfa5824..c3855c428 100644 --- a/src/api/java/IDisposable.java +++ b/src/api/java/IDisposable.java @@ -21,7 +21,7 @@ package com.microsoft.z3; public class IDisposable { - public void dispose() throws Z3Exception + public void dispose() { } } diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index a424cd51e..56ba9ccdf 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -26,7 +26,7 @@ public class IntExpr extends ArithExpr * Constructor for IntExpr * @throws Z3Exception on error **/ - IntExpr(Context ctx, long obj) throws Z3Exception + IntExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/IntNum.java b/src/api/java/IntNum.java index 0fdcf1aa6..4078b3db3 100644 --- a/src/api/java/IntNum.java +++ b/src/api/java/IntNum.java @@ -25,7 +25,7 @@ import java.math.BigInteger; public class IntNum extends IntExpr { - IntNum(Context ctx, long obj) throws Z3Exception + IntNum(Context ctx, long obj) { super(ctx, obj); } @@ -33,7 +33,7 @@ public class IntNum extends IntExpr /** * Retrieve the int value. **/ - public int getInt() throws Z3Exception + public int getInt() { Native.IntPtr res = new Native.IntPtr(); if (Native.getNumeralInt(getContext().nCtx(), getNativeObject(), res) ^ true) @@ -44,7 +44,7 @@ public class IntNum extends IntExpr /** * Retrieve the 64-bit int value. **/ - public long getInt64() throws Z3Exception + public long getInt64() { Native.LongPtr res = new Native.LongPtr(); if (Native.getNumeralInt64(getContext().nCtx(), getNativeObject(), res) ^ true) @@ -55,7 +55,7 @@ public class IntNum extends IntExpr /** * Retrieve the BigInteger value. **/ - public BigInteger getBigInteger() throws Z3Exception + public BigInteger getBigInteger() { return new BigInteger(this.toString()); } diff --git a/src/api/java/IntSort.java b/src/api/java/IntSort.java index 0b1047718..59526ed0b 100644 --- a/src/api/java/IntSort.java +++ b/src/api/java/IntSort.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class IntSort extends ArithSort { - IntSort(Context ctx, long obj) throws Z3Exception + IntSort(Context ctx, long obj) { super(ctx, obj); } - IntSort(Context ctx) throws Z3Exception + IntSort(Context ctx) { super(ctx, Native.mkIntSort(ctx.nCtx())); } diff --git a/src/api/java/IntSymbol.java b/src/api/java/IntSymbol.java index 01f75e0a4..db99e6840 100644 --- a/src/api/java/IntSymbol.java +++ b/src/api/java/IntSymbol.java @@ -29,24 +29,24 @@ public class IntSymbol extends Symbol * Remarks: Throws an exception if the symbol * is not of int kind. **/ - public int getInt() throws Z3Exception + public int getInt() { if (!isIntSymbol()) throw new Z3Exception("Int requested from non-Int symbol"); return Native.getSymbolInt(getContext().nCtx(), getNativeObject()); } - IntSymbol(Context ctx, long obj) throws Z3Exception + IntSymbol(Context ctx, long obj) { super(ctx, obj); } - IntSymbol(Context ctx, int i) throws Z3Exception + IntSymbol(Context ctx, int i) { super(ctx, Native.mkIntSymbol(ctx.nCtx(), i)); } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { if (Native.getSymbolKind(getContext().nCtx(), obj) != Z3_symbol_kind.Z3_INT_SYMBOL .toInt()) diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 91aac7f93..897c0e9e9 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -33,7 +33,7 @@ public class InterpolationContext extends Context /** * Constructor. **/ - public InterpolationContext() throws Z3Exception + public InterpolationContext() { m_ctx = Native.mkInterpolationContext(0); initContext(); @@ -46,7 +46,7 @@ public class InterpolationContext extends Context * Remarks: * @see Context#Context **/ - public InterpolationContext(Map settings) throws Z3Exception + public InterpolationContext(Map settings) { long cfg = Native.mkConfig(); for (Map.Entry kv : settings.entrySet()) @@ -60,7 +60,7 @@ public class InterpolationContext extends Context * Create an expression that marks a formula position for interpolation. * @throws Z3Exception **/ - public BoolExpr MkInterpolant(BoolExpr a) throws Z3Exception + public BoolExpr MkInterpolant(BoolExpr a) { checkContextMatch(a); return new BoolExpr(this, Native.mkInterpolant(nCtx(), a.getNativeObject())); @@ -73,7 +73,7 @@ public class InterpolationContext extends Context * well documented. * @throws Z3Exception **/ - public Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception + public Expr[] GetInterpolant(Expr pf, Expr pat, Params p) { checkContextMatch(pf); checkContextMatch(pat); @@ -94,7 +94,7 @@ public class InterpolationContext extends Context * well documented. * @throws Z3Exception **/ - public Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception + public Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) { checkContextMatch(pat); checkContextMatch(p); @@ -113,7 +113,7 @@ public class InterpolationContext extends Context /// Remarks: For more information on interpolation please refer /// too the function Z3_interpolation_profile in the C/C++ API, which is /// well documented. - public String InterpolationProfile() throws Z3Exception + public String InterpolationProfile() { return Native.interpolationProfile(nCtx()); } @@ -124,7 +124,7 @@ public class InterpolationContext extends Context /// Remarks: For more information on interpolation please refer /// too the function Z3_check_interpolant in the C/C++ API, which is /// well documented. - public int CheckInterpolant(Expr[] cnsts, int[] parents, Expr[] interps, String error, Expr[] theory) throws Z3Exception + public int CheckInterpolant(Expr[] cnsts, int[] parents, Expr[] interps, String error, Expr[] theory) { Native.StringPtr n_err_str = new Native.StringPtr(); int r = Native.checkInterpolant(nCtx(), @@ -145,7 +145,7 @@ public class InterpolationContext extends Context /// Remarks: For more information on interpolation please refer /// too the function Z3_read_interpolation_problem in the C/C++ API, which is /// well documented. - public int ReadInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception + public int ReadInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) { Native.IntPtr n_num = new Native.IntPtr(); Native.IntPtr n_num_theory = new Native.IntPtr(); @@ -176,7 +176,7 @@ public class InterpolationContext extends Context /// Remarks: For more information on interpolation please refer /// too the function Z3_write_interpolation_problem in the C/C++ API, which is /// well documented. - public void WriteInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception + public void WriteInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) { Native.writeInterpolationProblem(nCtx(), cnsts.length, Expr.arrayToNative(cnsts), parents, filename, theory.length, Expr.arrayToNative(theory)); } diff --git a/src/api/java/ListSort.java b/src/api/java/ListSort.java index a7ad0403b..705e93579 100644 --- a/src/api/java/ListSort.java +++ b/src/api/java/ListSort.java @@ -26,7 +26,7 @@ public class ListSort extends Sort * The declaration of the nil function of this list sort. * @throws Z3Exception **/ - public FuncDecl getNilDecl() throws Z3Exception + public FuncDecl getNilDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), 0)); } @@ -35,7 +35,7 @@ public class ListSort extends Sort * The empty list. * @throws Z3Exception **/ - public Expr getNil() throws Z3Exception + public Expr getNil() { return getContext().mkApp(getNilDecl()); } @@ -44,7 +44,7 @@ public class ListSort extends Sort * The declaration of the isNil function of this list sort. * @throws Z3Exception **/ - public FuncDecl getIsNilDecl() throws Z3Exception + public FuncDecl getIsNilDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), 0)); } @@ -53,7 +53,7 @@ public class ListSort extends Sort * The declaration of the cons function of this list sort. * @throws Z3Exception **/ - public FuncDecl getConsDecl() throws Z3Exception + public FuncDecl getConsDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortConstructor(getContext().nCtx(), getNativeObject(), 1)); } @@ -63,7 +63,7 @@ public class ListSort extends Sort * @throws Z3Exception * **/ - public FuncDecl getIsConsDecl() throws Z3Exception + public FuncDecl getIsConsDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortRecognizer(getContext().nCtx(), getNativeObject(), 1)); } @@ -72,7 +72,7 @@ public class ListSort extends Sort * The declaration of the head function of this list sort. * @throws Z3Exception **/ - public FuncDecl getHeadDecl() throws Z3Exception + public FuncDecl getHeadDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortConstructorAccessor(getContext().nCtx(), getNativeObject(), 1, 0)); } @@ -81,12 +81,12 @@ public class ListSort extends Sort * The declaration of the tail function of this list sort. * @throws Z3Exception **/ - public FuncDecl getTailDecl() throws Z3Exception + public FuncDecl getTailDecl() { return new FuncDecl(getContext(), Native.getDatatypeSortConstructorAccessor(getContext().nCtx(), getNativeObject(), 1, 1)); } - ListSort(Context ctx, Symbol name, Sort elemSort) throws Z3Exception + ListSort(Context ctx, Symbol name, Sort elemSort) { super(ctx, 0); diff --git a/src/api/java/Log.java b/src/api/java/Log.java index ac0ebfb7f..7dc9a1ef1 100644 --- a/src/api/java/Log.java +++ b/src/api/java/Log.java @@ -53,7 +53,7 @@ public final class Log * log. * @throws Z3Exception **/ - public static void append(String s) throws Z3Exception + public static void append(String s) { if (!m_is_open) throw new Z3Exception("Log cannot be closed."); diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 3d68d5485..22d232006 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -33,7 +33,7 @@ public class Model extends Z3Object * null otherwise. * @throws Z3Exception **/ - public Expr getConstInterp(Expr a) throws Z3Exception + public Expr getConstInterp(Expr a) { getContext().checkContextMatch(a); return getConstInterp(a.getFuncDecl()); @@ -48,7 +48,7 @@ public class Model extends Z3Object * null otherwise. * @throws Z3Exception **/ - public Expr getConstInterp(FuncDecl f) throws Z3Exception + public Expr getConstInterp(FuncDecl f) { getContext().checkContextMatch(f); if (f.getArity() != 0 @@ -74,7 +74,7 @@ public class Model extends Z3Object * the model, null otherwise. * @throws Z3Exception **/ - public FuncInterp getFuncInterp(FuncDecl f) throws Z3Exception + public FuncInterp getFuncInterp(FuncDecl f) { getContext().checkContextMatch(f); @@ -117,7 +117,7 @@ public class Model extends Z3Object /** * The number of constants that have an interpretation in the model. **/ - public int getNumConsts() throws Z3Exception + public int getNumConsts() { return Native.modelGetNumConsts(getContext().nCtx(), getNativeObject()); } @@ -127,7 +127,7 @@ public class Model extends Z3Object * * @throws Z3Exception **/ - public FuncDecl[] getConstDecls() throws Z3Exception + public FuncDecl[] getConstDecls() { int n = getNumConsts(); FuncDecl[] res = new FuncDecl[n]; @@ -140,7 +140,7 @@ public class Model extends Z3Object /** * The number of function interpretations in the model. **/ - public int getNumFuncs() throws Z3Exception + public int getNumFuncs() { return Native.modelGetNumFuncs(getContext().nCtx(), getNativeObject()); } @@ -150,7 +150,7 @@ public class Model extends Z3Object * * @throws Z3Exception **/ - public FuncDecl[] getFuncDecls() throws Z3Exception + public FuncDecl[] getFuncDecls() { int n = getNumFuncs(); FuncDecl[] res = new FuncDecl[n]; @@ -165,7 +165,7 @@ public class Model extends Z3Object * * @throws Z3Exception **/ - public FuncDecl[] getDecls() throws Z3Exception + public FuncDecl[] getDecls() { int nFuncs = getNumFuncs(); int nConsts = getNumConsts(); @@ -208,7 +208,7 @@ public class Model extends Z3Object * @return The evaluation of {@code t} in the model. * @throws Z3Exception **/ - public Expr eval(Expr t, boolean completion) throws Z3Exception + public Expr eval(Expr t, boolean completion) { Native.LongPtr v = new Native.LongPtr(); if (Native.modelEval(getContext().nCtx(), getNativeObject(), @@ -223,7 +223,7 @@ public class Model extends Z3Object * * @throws Z3Exception **/ - public Expr evaluate(Expr t, boolean completion) throws Z3Exception + public Expr evaluate(Expr t, boolean completion) { return eval(t, completion); } @@ -232,7 +232,7 @@ public class Model extends Z3Object * The number of uninterpreted sorts that the model has an interpretation * for. **/ - public int getNumSorts() throws Z3Exception + public int getNumSorts() { return Native.modelGetNumSorts(getContext().nCtx(), getNativeObject()); } @@ -248,7 +248,7 @@ public class Model extends Z3Object * * @throws Z3Exception **/ - public Sort[] getSorts() throws Z3Exception + public Sort[] getSorts() { int n = getNumSorts(); @@ -268,7 +268,7 @@ public class Model extends Z3Object * of {@code s} * @throws Z3Exception **/ - public Expr[] getSortUniverse(Sort s) throws Z3Exception + public Expr[] getSortUniverse(Sort s) { ASTVector nUniv = new ASTVector(getContext(), Native.modelGetSortUniverse( @@ -296,18 +296,18 @@ public class Model extends Z3Object } } - Model(Context ctx, long obj) throws Z3Exception + Model(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getModelDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getModelDRQ().add(o); super.decRef(o); diff --git a/src/api/java/ParamDescrs.java b/src/api/java/ParamDescrs.java index e1f0d16e5..514c65b46 100644 --- a/src/api/java/ParamDescrs.java +++ b/src/api/java/ParamDescrs.java @@ -27,7 +27,7 @@ public class ParamDescrs extends Z3Object /** * validate a set of parameters. **/ - public void validate(Params p) throws Z3Exception + public void validate(Params p) { Native.paramsValidate(getContext().nCtx(), p.getNativeObject(), @@ -37,7 +37,7 @@ public class ParamDescrs extends Z3Object /** * Retrieve kind of parameter. **/ - public Z3_param_kind getKind(Symbol name) throws Z3Exception + public Z3_param_kind getKind(Symbol name) { return Z3_param_kind.fromInt(Native.paramDescrsGetKind( @@ -49,7 +49,7 @@ public class ParamDescrs extends Z3Object * * @throws Z3Exception **/ - public Symbol[] getNames() throws Z3Exception + public Symbol[] getNames() { int sz = Native.paramDescrsSize(getContext().nCtx(), getNativeObject()); Symbol[] names = new Symbol[sz]; @@ -64,7 +64,7 @@ public class ParamDescrs extends Z3Object /** * The size of the ParamDescrs. **/ - public int size() throws Z3Exception + public int size() { return Native.paramDescrsSize(getContext().nCtx(), getNativeObject()); } @@ -83,18 +83,18 @@ public class ParamDescrs extends Z3Object } } - ParamDescrs(Context ctx, long obj) throws Z3Exception + ParamDescrs(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getParamDescrsDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getParamDescrsDRQ().add(o); super.decRef(o); diff --git a/src/api/java/Params.java b/src/api/java/Params.java index 693491f41..c241ac8aa 100644 --- a/src/api/java/Params.java +++ b/src/api/java/Params.java @@ -26,7 +26,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(Symbol name, boolean value) throws Z3Exception + public void add(Symbol name, boolean value) { Native.paramsSetBool(getContext().nCtx(), getNativeObject(), name.getNativeObject(), (value) ? true : false); @@ -35,7 +35,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(Symbol name, double value) throws Z3Exception + public void add(Symbol name, double value) { Native.paramsSetDouble(getContext().nCtx(), getNativeObject(), name.getNativeObject(), value); @@ -44,7 +44,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(Symbol name, String value) throws Z3Exception + public void add(Symbol name, String value) { Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), @@ -55,7 +55,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(Symbol name, Symbol value) throws Z3Exception + public void add(Symbol name, Symbol value) { Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), @@ -65,7 +65,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(String name, boolean value) throws Z3Exception + public void add(String name, boolean value) { Native.paramsSetBool(getContext().nCtx(), getNativeObject(), getContext().mkSymbol(name).getNativeObject(), value); @@ -74,7 +74,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(String name, int value) throws Z3Exception + public void add(String name, int value) { Native.paramsSetUint(getContext().nCtx(), getNativeObject(), getContext() .mkSymbol(name).getNativeObject(), value); @@ -83,7 +83,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(String name, double value) throws Z3Exception + public void add(String name, double value) { Native.paramsSetDouble(getContext().nCtx(), getNativeObject(), getContext() .mkSymbol(name).getNativeObject(), value); @@ -92,7 +92,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(String name, Symbol value) throws Z3Exception + public void add(String name, Symbol value) { Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), getContext() .mkSymbol(name).getNativeObject(), value.getNativeObject()); @@ -101,7 +101,7 @@ public class Params extends Z3Object /** * Adds a parameter setting. **/ - public void add(String name, String value) throws Z3Exception + public void add(String name, String value) { Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), @@ -123,18 +123,18 @@ public class Params extends Z3Object } } - Params(Context ctx) throws Z3Exception + Params(Context ctx) { super(ctx, Native.mkParams(ctx.nCtx())); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getParamsDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getParamsDRQ().add(o); super.decRef(o); diff --git a/src/api/java/Pattern.java b/src/api/java/Pattern.java index 797b387d0..d51315abf 100644 --- a/src/api/java/Pattern.java +++ b/src/api/java/Pattern.java @@ -26,7 +26,7 @@ public class Pattern extends AST /** * The number of terms in the pattern. **/ - public int getNumTerms() throws Z3Exception + public int getNumTerms() { return Native.getPatternNumTerms(getContext().nCtx(), getNativeObject()); } @@ -36,7 +36,7 @@ public class Pattern extends AST * * @throws Z3Exception **/ - public Expr[] getTerms() throws Z3Exception + public Expr[] getTerms() { int n = getNumTerms(); @@ -61,7 +61,7 @@ public class Pattern extends AST } } - Pattern(Context ctx, long obj) throws Z3Exception + Pattern(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/Probe.java b/src/api/java/Probe.java index 62b0612b9..e190229df 100644 --- a/src/api/java/Probe.java +++ b/src/api/java/Probe.java @@ -34,30 +34,30 @@ public class Probe extends Z3Object * 0.0 for false, and a value different from 0.0 for true. * @throws Z3Exception **/ - public double apply(Goal g) throws Z3Exception + public double apply(Goal g) { getContext().checkContextMatch(g); return Native.probeApply(getContext().nCtx(), getNativeObject(), g.getNativeObject()); } - Probe(Context ctx, long obj) throws Z3Exception + Probe(Context ctx, long obj) { super(ctx, obj); } - Probe(Context ctx, String name) throws Z3Exception + Probe(Context ctx, String name) { super(ctx, Native.mkProbe(ctx.nCtx(), name)); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getProbeDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getProbeDRQ().add(o); super.decRef(o); diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index 3ea2b2eaf..08df1c1f5 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -27,7 +27,7 @@ public class Quantifier extends BoolExpr /** * Indicates whether the quantifier is universal. **/ - public boolean isUniversal() throws Z3Exception + public boolean isUniversal() { return Native.isQuantifierForall(getContext().nCtx(), getNativeObject()); } @@ -35,7 +35,7 @@ public class Quantifier extends BoolExpr /** * Indicates whether the quantifier is existential. **/ - public boolean isExistential() throws Z3Exception + public boolean isExistential() { return !isUniversal(); } @@ -43,7 +43,7 @@ public class Quantifier extends BoolExpr /** * The weight of the quantifier. **/ - public int getWeight() throws Z3Exception + public int getWeight() { return Native.getQuantifierWeight(getContext().nCtx(), getNativeObject()); } @@ -51,7 +51,7 @@ public class Quantifier extends BoolExpr /** * The number of patterns. **/ - public int getNumPatterns() throws Z3Exception + public int getNumPatterns() { return Native .getQuantifierNumPatterns(getContext().nCtx(), getNativeObject()); @@ -62,7 +62,7 @@ public class Quantifier extends BoolExpr * * @throws Z3Exception **/ - public Pattern[] getPatterns() throws Z3Exception + public Pattern[] getPatterns() { int n = getNumPatterns(); Pattern[] res = new Pattern[n]; @@ -75,7 +75,7 @@ public class Quantifier extends BoolExpr /** * The number of no-patterns. **/ - public int getNumNoPatterns() throws Z3Exception + public int getNumNoPatterns() { return Native.getQuantifierNumNoPatterns(getContext().nCtx(), getNativeObject()); @@ -86,7 +86,7 @@ public class Quantifier extends BoolExpr * * @throws Z3Exception **/ - public Pattern[] getNoPatterns() throws Z3Exception + public Pattern[] getNoPatterns() { int n = getNumNoPatterns(); Pattern[] res = new Pattern[n]; @@ -99,7 +99,7 @@ public class Quantifier extends BoolExpr /** * The number of bound variables. **/ - public int getNumBound() throws Z3Exception + public int getNumBound() { return Native.getQuantifierNumBound(getContext().nCtx(), getNativeObject()); } @@ -109,7 +109,7 @@ public class Quantifier extends BoolExpr * * @throws Z3Exception **/ - public Symbol[] getBoundVariableNames() throws Z3Exception + public Symbol[] getBoundVariableNames() { int n = getNumBound(); Symbol[] res = new Symbol[n]; @@ -124,7 +124,7 @@ public class Quantifier extends BoolExpr * * @throws Z3Exception **/ - public Sort[] getBoundVariableSorts() throws Z3Exception + public Sort[] getBoundVariableSorts() { int n = getNumBound(); Sort[] res = new Sort[n]; @@ -139,7 +139,7 @@ public class Quantifier extends BoolExpr * * @throws Z3Exception **/ - public BoolExpr getBody() throws Z3Exception + public BoolExpr getBody() { return new BoolExpr(getContext(), Native.getQuantifierBody(getContext() .nCtx(), getNativeObject())); @@ -147,7 +147,7 @@ public class Quantifier extends BoolExpr Quantifier(Context ctx, boolean isForall, Sort[] sorts, Symbol[] names, Expr body, int weight, Pattern[] patterns, Expr[] noPatterns, - Symbol quantifierID, Symbol skolemID) throws Z3Exception + Symbol quantifierID, Symbol skolemID) { super(ctx, 0); @@ -183,7 +183,7 @@ public class Quantifier extends BoolExpr Quantifier(Context ctx, boolean isForall, Expr[] bound, Expr body, int weight, Pattern[] patterns, Expr[] noPatterns, - Symbol quantifierID, Symbol skolemID) throws Z3Exception + Symbol quantifierID, Symbol skolemID) { super(ctx, 0); @@ -210,12 +210,12 @@ public class Quantifier extends BoolExpr } } - Quantifier(Context ctx, long obj) throws Z3Exception + Quantifier(Context ctx, long obj) { super(ctx, obj); } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { if (Native.getAstKind(getContext().nCtx(), obj) != Z3_ast_kind.Z3_QUANTIFIER_AST .toInt()) diff --git a/src/api/java/RatNum.java b/src/api/java/RatNum.java index 278aba65e..8fd815742 100644 --- a/src/api/java/RatNum.java +++ b/src/api/java/RatNum.java @@ -27,7 +27,7 @@ public class RatNum extends RealExpr /** * The numerator of a rational numeral. **/ - public IntNum getNumerator() throws Z3Exception + public IntNum getNumerator() { return new IntNum(getContext(), Native.getNumerator(getContext().nCtx(), getNativeObject())); @@ -36,7 +36,7 @@ public class RatNum extends RealExpr /** * The denominator of a rational numeral. **/ - public IntNum getDenominator() throws Z3Exception + public IntNum getDenominator() { return new IntNum(getContext(), Native.getDenominator(getContext().nCtx(), getNativeObject())); @@ -45,7 +45,7 @@ public class RatNum extends RealExpr /** * Converts the numerator of the rational to a BigInteger **/ - public BigInteger getBigIntNumerator() throws Z3Exception + public BigInteger getBigIntNumerator() { IntNum n = getNumerator(); return new BigInteger(n.toString()); @@ -54,7 +54,7 @@ public class RatNum extends RealExpr /** * Converts the denominator of the rational to a BigInteger **/ - public BigInteger getBigIntDenominator() throws Z3Exception + public BigInteger getBigIntDenominator() { IntNum n = getDenominator(); return new BigInteger(n.toString()); @@ -65,7 +65,7 @@ public class RatNum extends RealExpr * Remarks: The result * has at most {@code precision} decimal places. **/ - public String toDecimalString(int precision) throws Z3Exception + public String toDecimalString(int precision) { return Native.getNumeralDecimalString(getContext().nCtx(), getNativeObject(), precision); @@ -85,7 +85,7 @@ public class RatNum extends RealExpr } } - RatNum(Context ctx, long obj) throws Z3Exception + RatNum(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/RealExpr.java b/src/api/java/RealExpr.java index 579d344e1..c977e2ac0 100644 --- a/src/api/java/RealExpr.java +++ b/src/api/java/RealExpr.java @@ -25,7 +25,7 @@ public class RealExpr extends ArithExpr /** * Constructor for RealExpr **/ - RealExpr(Context ctx, long obj) throws Z3Exception + RealExpr(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/RealSort.java b/src/api/java/RealSort.java index d76823a0d..0f6333314 100644 --- a/src/api/java/RealSort.java +++ b/src/api/java/RealSort.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class RealSort extends ArithSort { - RealSort(Context ctx, long obj) throws Z3Exception + RealSort(Context ctx, long obj) { super(ctx, obj); } - RealSort(Context ctx) throws Z3Exception + RealSort(Context ctx) { super(ctx, Native.mkRealSort(ctx.nCtx())); } diff --git a/src/api/java/RelationSort.java b/src/api/java/RelationSort.java index 77f6c595b..e996479ab 100644 --- a/src/api/java/RelationSort.java +++ b/src/api/java/RelationSort.java @@ -25,7 +25,7 @@ public class RelationSort extends Sort /** * The arity of the relation sort. **/ - public int getArity() throws Z3Exception + public int getArity() { return Native.getRelationArity(getContext().nCtx(), getNativeObject()); } @@ -34,7 +34,7 @@ public class RelationSort extends Sort * The sorts of the columns of the relation sort. * @throws Z3Exception **/ - public Sort[] getColumnSorts() throws Z3Exception + public Sort[] getColumnSorts() { if (m_columnSorts != null) @@ -50,7 +50,7 @@ public class RelationSort extends Sort private Sort[] m_columnSorts = null; - RelationSort(Context ctx, long obj) throws Z3Exception + RelationSort(Context ctx, long obj) { super(ctx, obj); } diff --git a/src/api/java/SetSort.java b/src/api/java/SetSort.java index 69126933a..2aa821250 100644 --- a/src/api/java/SetSort.java +++ b/src/api/java/SetSort.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class SetSort extends Sort { - SetSort(Context ctx, long obj) throws Z3Exception + SetSort(Context ctx, long obj) { super(ctx, obj); } - SetSort(Context ctx, Sort ty) throws Z3Exception + SetSort(Context ctx, Sort ty) { super(ctx, Native.mkSetSort(ctx.nCtx(), ty.getNativeObject())); } diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index db3f46bfd..e4ba9de42 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -27,7 +27,7 @@ public class Solver extends Z3Object /** * A string that describes all available solver parameters. **/ - public String getHelp() throws Z3Exception + public String getHelp() { return Native.solverGetHelp(getContext().nCtx(), getNativeObject()); } @@ -37,7 +37,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public void setParameters(Params value) throws Z3Exception + public void setParameters(Params value) { getContext().checkContextMatch(value); Native.solverSetParams(getContext().nCtx(), getNativeObject(), @@ -49,7 +49,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public ParamDescrs getParameterDescriptions() throws Z3Exception + public ParamDescrs getParameterDescriptions() { return new ParamDescrs(getContext(), Native.solverGetParamDescrs( getContext().nCtx(), getNativeObject())); @@ -60,7 +60,7 @@ public class Solver extends Z3Object * @see pop * @see push **/ - public int getNumScopes() throws Z3Exception + public int getNumScopes() { return Native .solverGetNumScopes(getContext().nCtx(), getNativeObject()); @@ -70,7 +70,7 @@ public class Solver extends Z3Object * Creates a backtracking point. * @see pop **/ - public void push() throws Z3Exception + public void push() { Native.solverPush(getContext().nCtx(), getNativeObject()); } @@ -79,7 +79,7 @@ public class Solver extends Z3Object * Backtracks one backtracking point. * Remarks: . **/ - public void pop() throws Z3Exception + public void pop() { pop(1); } @@ -91,7 +91,7 @@ public class Solver extends Z3Object * {@code NumScopes} * @see push **/ - public void pop(int n) throws Z3Exception + public void pop(int n) { Native.solverPop(getContext().nCtx(), getNativeObject(), n); } @@ -101,7 +101,7 @@ public class Solver extends Z3Object * Remarks: This removes all assertions from the * solver. **/ - public void reset() throws Z3Exception + public void reset() { Native.solverReset(getContext().nCtx(), getNativeObject()); } @@ -111,7 +111,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public void add(BoolExpr... constraints) throws Z3Exception + public void add(BoolExpr... constraints) { getContext().checkContextMatch(constraints); for (BoolExpr a : constraints) @@ -135,7 +135,7 @@ public class Solver extends Z3Object * and the Boolean literals * provided using with assumptions. **/ - public void assertAndTrack(BoolExpr[] constraints, BoolExpr[] ps) throws Z3Exception + public void assertAndTrack(BoolExpr[] constraints, BoolExpr[] ps) { getContext().checkContextMatch(constraints); getContext().checkContextMatch(ps); @@ -160,7 +160,7 @@ public class Solver extends Z3Object * and the Boolean literals * provided using with assumptions. */ - public void assertAndTrack(BoolExpr constraint, BoolExpr p) throws Z3Exception + public void assertAndTrack(BoolExpr constraint, BoolExpr p) { getContext().checkContextMatch(constraint); getContext().checkContextMatch(p); @@ -174,7 +174,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public int getNumAssertions() throws Z3Exception + public int getNumAssertions() { ASTVector assrts = new ASTVector(getContext(), Native.solverGetAssertions( getContext().nCtx(), getNativeObject())); @@ -186,7 +186,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public BoolExpr[] getAssertions() throws Z3Exception + public BoolExpr[] getAssertions() { ASTVector assrts = new ASTVector(getContext(), Native.solverGetAssertions( getContext().nCtx(), getNativeObject())); @@ -204,7 +204,7 @@ public class Solver extends Z3Object * @see getUnsatCore * @see getProof **/ - public Status check(Expr... assumptions) throws Z3Exception + public Status check(Expr... assumptions) { Z3_lbool r; if (assumptions == null) @@ -232,7 +232,7 @@ public class Solver extends Z3Object * @see getUnsatCore * @see getProof **/ - public Status check() throws Z3Exception + public Status check() { return check((Expr[]) null); } @@ -246,7 +246,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public Model getModel() throws Z3Exception + public Model getModel() { long x = Native.solverGetModel(getContext().nCtx(), getNativeObject()); if (x == 0) @@ -264,7 +264,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public Expr getProof() throws Z3Exception + public Expr getProof() { long x = Native.solverGetProof(getContext().nCtx(), getNativeObject()); if (x == 0) @@ -282,7 +282,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public Expr[] getUnsatCore() throws Z3Exception + public Expr[] getUnsatCore() { ASTVector core = new ASTVector(getContext(), Native.solverGetUnsatCore( @@ -298,7 +298,7 @@ public class Solver extends Z3Object * A brief justification of why the last call to {@code Check} returned * {@code UNKNOWN}. **/ - public String getReasonUnknown() throws Z3Exception + public String getReasonUnknown() { return Native.solverGetReasonUnknown(getContext().nCtx(), getNativeObject()); @@ -309,7 +309,7 @@ public class Solver extends Z3Object * * @throws Z3Exception **/ - public Statistics getStatistics() throws Z3Exception + public Statistics getStatistics() { return new Statistics(getContext(), Native.solverGetStatistics( getContext().nCtx(), getNativeObject())); @@ -330,18 +330,18 @@ public class Solver extends Z3Object } } - Solver(Context ctx, long obj) throws Z3Exception + Solver(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getSolverDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getSolverDRQ().add(o); super.decRef(o); diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index e1cbbea7c..46e349cc7 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -58,7 +58,7 @@ public class Sort extends AST /** * Returns a unique identifier for the sort. **/ - public int getId() throws Z3Exception + public int getId() { return Native.getSortId(getContext().nCtx(), getNativeObject()); } @@ -66,7 +66,7 @@ public class Sort extends AST /** * The kind of the sort. **/ - public Z3_sort_kind getSortKind() throws Z3Exception + public Z3_sort_kind getSortKind() { return Z3_sort_kind.fromInt(Native.getSortKind(getContext().nCtx(), getNativeObject())); @@ -75,7 +75,7 @@ public class Sort extends AST /** * The name of the sort **/ - public Symbol getName() throws Z3Exception + public Symbol getName() { return Symbol.create(getContext(), Native.getSortName(getContext().nCtx(), getNativeObject())); @@ -98,12 +98,12 @@ public class Sort extends AST /** * Sort constructor **/ - Sort(Context ctx, long obj) throws Z3Exception + Sort(Context ctx, long obj) { super(ctx, obj); } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { if (Native.getAstKind(getContext().nCtx(), obj) != Z3_ast_kind.Z3_SORT_AST .toInt()) @@ -111,7 +111,7 @@ public class Sort extends AST super.checkNativeObject(obj); } - static Sort create(Context ctx, long obj) throws Z3Exception + static Sort create(Context ctx, long obj) { Z3_sort_kind sk = Z3_sort_kind.fromInt(Native.getSortKind(ctx.nCtx(), obj)); switch (sk) diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index aa909b9bd..de5a52ebb 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -70,7 +70,7 @@ public class Statistics extends Z3Object * * @throws Z3Exception **/ - public String getValueString() throws Z3Exception + public String getValueString() { if (isUInt()) return Integer.toString(m_int); @@ -131,7 +131,7 @@ public class Statistics extends Z3Object /** * The number of statistical data. **/ - public int size() throws Z3Exception + public int size() { return Native.statsSize(getContext().nCtx(), getNativeObject()); } @@ -141,7 +141,7 @@ public class Statistics extends Z3Object * * @throws Z3Exception **/ - public Entry[] getEntries() throws Z3Exception + public Entry[] getEntries() { int n = size(); @@ -166,7 +166,7 @@ public class Statistics extends Z3Object /** * The statistical counters. **/ - public String[] getKeys() throws Z3Exception + public String[] getKeys() { int n = size(); String[] res = new String[n]; @@ -182,7 +182,7 @@ public class Statistics extends Z3Object * * @throws Z3Exception **/ - public Entry get(String key) throws Z3Exception + public Entry get(String key) { int n = size(); Entry[] es = getEntries(); @@ -192,18 +192,18 @@ public class Statistics extends Z3Object return null; } - Statistics(Context ctx, long obj) throws Z3Exception + Statistics(Context ctx, long obj) { super(ctx, obj); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getStatisticsDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getStatisticsDRQ().add(o); super.decRef(o); diff --git a/src/api/java/StringSymbol.java b/src/api/java/StringSymbol.java index 122c7765f..efbd3a9d2 100644 --- a/src/api/java/StringSymbol.java +++ b/src/api/java/StringSymbol.java @@ -29,22 +29,22 @@ public class StringSymbol extends Symbol * Remarks: Throws an exception if the * symbol is not of string kind. **/ - public String getString() throws Z3Exception + public String getString() { return Native.getSymbolString(getContext().nCtx(), getNativeObject()); } - StringSymbol(Context ctx, long obj) throws Z3Exception + StringSymbol(Context ctx, long obj) { super(ctx, obj); } - StringSymbol(Context ctx, String s) throws Z3Exception + StringSymbol(Context ctx, String s) { super(ctx, Native.mkStringSymbol(ctx.nCtx(), s)); } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { if (Native.getSymbolKind(getContext().nCtx(), obj) != Z3_symbol_kind.Z3_STRING_SYMBOL .toInt()) diff --git a/src/api/java/Symbol.java b/src/api/java/Symbol.java index 856c9b57e..6f12dda38 100644 --- a/src/api/java/Symbol.java +++ b/src/api/java/Symbol.java @@ -27,7 +27,7 @@ public class Symbol extends Z3Object /** * The kind of the symbol (int or string) **/ - protected Z3_symbol_kind getKind() throws Z3Exception + protected Z3_symbol_kind getKind() { return Z3_symbol_kind.fromInt(Native.getSymbolKind(getContext().nCtx(), getNativeObject())); @@ -36,7 +36,7 @@ public class Symbol extends Z3Object /** * Indicates whether the symbol is of Int kind **/ - public boolean isIntSymbol() throws Z3Exception + public boolean isIntSymbol() { return getKind() == Z3_symbol_kind.Z3_INT_SYMBOL; } @@ -44,7 +44,7 @@ public class Symbol extends Z3Object /** * Indicates whether the symbol is of string kind. **/ - public boolean isStringSymbol() throws Z3Exception + public boolean isStringSymbol() { return getKind() == Z3_symbol_kind.Z3_STRING_SYMBOL; } @@ -72,12 +72,12 @@ public class Symbol extends Z3Object /** * Symbol constructor **/ - protected Symbol(Context ctx, long obj) throws Z3Exception + protected Symbol(Context ctx, long obj) { super(ctx, obj); } - static Symbol create(Context ctx, long obj) throws Z3Exception + static Symbol create(Context ctx, long obj) { switch (Z3_symbol_kind.fromInt(Native.getSymbolKind(ctx.nCtx(), obj))) { diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index 65404a927..81d886537 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -29,7 +29,7 @@ public class Tactic extends Z3Object /** * A string containing a description of parameters accepted by the tactic. **/ - public String getHelp() throws Z3Exception + public String getHelp() { return Native.tacticGetHelp(getContext().nCtx(), getNativeObject()); } @@ -38,7 +38,7 @@ public class Tactic extends Z3Object * Retrieves parameter descriptions for Tactics. * @throws Z3Exception **/ - public ParamDescrs getParameterDescriptions() throws Z3Exception + public ParamDescrs getParameterDescriptions() { return new ParamDescrs(getContext(), Native.tacticGetParamDescrs(getContext() .nCtx(), getNativeObject())); @@ -48,7 +48,7 @@ public class Tactic extends Z3Object * Execute the tactic over the goal. * @throws Z3Exception **/ - public ApplyResult apply(Goal g) throws Z3Exception + public ApplyResult apply(Goal g) { return apply(g, null); } @@ -57,7 +57,7 @@ public class Tactic extends Z3Object * Execute the tactic over the goal. * @throws Z3Exception **/ - public ApplyResult apply(Goal g, Params p) throws Z3Exception + public ApplyResult apply(Goal g, Params p) { getContext().checkContextMatch(g); if (p == null) @@ -77,28 +77,28 @@ public class Tactic extends Z3Object * @see Context#mkSolver(Tactic) * @throws Z3Exception **/ - public Solver getSolver() throws Z3Exception + public Solver getSolver() { return getContext().mkSolver(this); } - Tactic(Context ctx, long obj) throws Z3Exception + Tactic(Context ctx, long obj) { super(ctx, obj); } - Tactic(Context ctx, String name) throws Z3Exception + Tactic(Context ctx, String name) { super(ctx, Native.mkTactic(ctx.nCtx(), name)); } - void incRef(long o) throws Z3Exception + void incRef(long o) { getContext().getTacticDRQ().incAndClear(getContext(), o); super.incRef(o); } - void decRef(long o) throws Z3Exception + void decRef(long o) { getContext().getTacticDRQ().add(o); super.decRef(o); diff --git a/src/api/java/TupleSort.java b/src/api/java/TupleSort.java index 87572b9ee..1594b874d 100644 --- a/src/api/java/TupleSort.java +++ b/src/api/java/TupleSort.java @@ -26,7 +26,7 @@ public class TupleSort extends Sort * The constructor function of the tuple. * @throws Z3Exception **/ - public FuncDecl mkDecl() throws Z3Exception + public FuncDecl mkDecl() { return new FuncDecl(getContext(), Native.getTupleSortMkDecl(getContext() @@ -36,7 +36,7 @@ public class TupleSort extends Sort /** * The number of fields in the tuple. **/ - public int getNumFields() throws Z3Exception + public int getNumFields() { return Native.getTupleSortNumFields(getContext().nCtx(), getNativeObject()); } @@ -45,7 +45,7 @@ public class TupleSort extends Sort * The field declarations. * @throws Z3Exception **/ - public FuncDecl[] getFieldDecls() throws Z3Exception + public FuncDecl[] getFieldDecls() { int n = getNumFields(); @@ -57,7 +57,7 @@ public class TupleSort extends Sort } TupleSort(Context ctx, Symbol name, int numFields, Symbol[] fieldNames, - Sort[] fieldSorts) throws Z3Exception + Sort[] fieldSorts) { super(ctx, 0); diff --git a/src/api/java/UninterpretedSort.java b/src/api/java/UninterpretedSort.java index 07e4707f5..7f7427493 100644 --- a/src/api/java/UninterpretedSort.java +++ b/src/api/java/UninterpretedSort.java @@ -22,12 +22,12 @@ package com.microsoft.z3; **/ public class UninterpretedSort extends Sort { - UninterpretedSort(Context ctx, long obj) throws Z3Exception + UninterpretedSort(Context ctx, long obj) { super(ctx, obj); } - UninterpretedSort(Context ctx, Symbol s) throws Z3Exception + UninterpretedSort(Context ctx, Symbol s) { super(ctx, Native.mkUninterpretedSort(ctx.nCtx(), s.getNativeObject())); } diff --git a/src/api/java/Z3Exception.java b/src/api/java/Z3Exception.java index 2522db627..a27e40048 100644 --- a/src/api/java/Z3Exception.java +++ b/src/api/java/Z3Exception.java @@ -22,7 +22,7 @@ package com.microsoft.z3; * The exception base class for error reporting from Z3 **/ @SuppressWarnings("serial") -public class Z3Exception extends Exception +public class Z3Exception extends RuntimeException { /** * Constructor. diff --git a/src/api/java/Z3Object.java b/src/api/java/Z3Object.java index 9b39a3e2f..877e22cac 100644 --- a/src/api/java/Z3Object.java +++ b/src/api/java/Z3Object.java @@ -26,7 +26,7 @@ public class Z3Object extends IDisposable /** * Finalizer. **/ - protected void finalize() throws Z3Exception + protected void finalize() { dispose(); } @@ -34,7 +34,7 @@ public class Z3Object extends IDisposable /** * Disposes of the underlying native Z3 object. **/ - public void dispose() throws Z3Exception + public void dispose() { if (m_n_obj != 0) { @@ -58,7 +58,7 @@ public class Z3Object extends IDisposable m_ctx = ctx; } - Z3Object(Context ctx, long obj) throws Z3Exception + Z3Object(Context ctx, long obj) { ctx.m_refCount++; m_ctx = ctx; @@ -66,15 +66,15 @@ public class Z3Object extends IDisposable m_n_obj = obj; } - void incRef(long o) throws Z3Exception + void incRef(long o) { } - void decRef(long o) throws Z3Exception + void decRef(long o) { } - void checkNativeObject(long obj) throws Z3Exception + void checkNativeObject(long obj) { } @@ -83,7 +83,7 @@ public class Z3Object extends IDisposable return m_n_obj; } - void setNativeObject(long value) throws Z3Exception + void setNativeObject(long value) { if (value != 0) { From 3cd018bd6c829172fb6f1017f432d2c49a5e1efc Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 9 Apr 2015 14:46:59 +0100 Subject: [PATCH 627/646] Java API: Removed throws declarations for Z3Exception. --- examples/java/JavaExample.java | 127 ++++++++++++++------------------- 1 file changed, 52 insertions(+), 75 deletions(-) diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 5c49b56ae..4a579f9da 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -41,7 +41,7 @@ class JavaExample // / // / Where, finvis a fresh function declaration. - public BoolExpr injAxiom(Context ctx, FuncDecl f, int i) throws Z3Exception + public BoolExpr injAxiom(Context ctx, FuncDecl f, int i) { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); @@ -102,7 +102,6 @@ class JavaExample // / Where, finvis a fresh function declaration. public BoolExpr injAxiomAbs(Context ctx, FuncDecl f, int i) - throws Z3Exception { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); @@ -179,7 +178,7 @@ class JavaExample // / "Hello world" example: create a Z3 logical context, and delete it. - public void simpleExample() throws Z3Exception + public void simpleExample() { System.out.println("SimpleExample"); Log.append("SimpleExample"); @@ -193,8 +192,7 @@ class JavaExample } } - Model check(Context ctx, BoolExpr f, Status sat) throws Z3Exception, - TestFailedException + Model check(Context ctx, BoolExpr f, Status sat) throws TestFailedException { Solver s = ctx.mkSolver(); s.add(f); @@ -207,7 +205,7 @@ class JavaExample } void solveTactical(Context ctx, Tactic t, Goal g, Status sat) - throws Z3Exception, TestFailedException + throws TestFailedException { Solver s = ctx.mkSolver(t); System.out.println("\nTactical solver: " + s); @@ -220,7 +218,7 @@ class JavaExample throw new TestFailedException(); } - ApplyResult applyTactic(Context ctx, Tactic t, Goal g) throws Z3Exception + ApplyResult applyTactic(Context ctx, Tactic t, Goal g) { System.out.println("\nGoal: " + g); @@ -250,15 +248,14 @@ class JavaExample return res; } - void prove(Context ctx, BoolExpr f, boolean useMBQI) throws Z3Exception, - TestFailedException + void prove(Context ctx, BoolExpr f, boolean useMBQI) throws TestFailedException { BoolExpr[] assumptions = new BoolExpr[0]; prove(ctx, f, useMBQI, assumptions); } void prove(Context ctx, BoolExpr f, boolean useMBQI, - BoolExpr... assumptions) throws Z3Exception, TestFailedException + BoolExpr... assumptions) throws TestFailedException { System.out.println("Proving: " + f); Solver s = ctx.mkSolver(); @@ -283,15 +280,15 @@ class JavaExample } } - void disprove(Context ctx, BoolExpr f, boolean useMBQI) throws Z3Exception, - TestFailedException + void disprove(Context ctx, BoolExpr f, boolean useMBQI) + throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); } void disprove(Context ctx, BoolExpr f, boolean useMBQI, - BoolExpr... assumptions) throws Z3Exception, TestFailedException + BoolExpr... assumptions) throws TestFailedException { System.out.println("Disproving: " + f); Solver s = ctx.mkSolver(); @@ -316,8 +313,7 @@ class JavaExample } } - void modelConverterTest(Context ctx) throws Z3Exception, - TestFailedException + void modelConverterTest(Context ctx) throws TestFailedException { System.out.println("ModelConverterTest"); @@ -357,7 +353,7 @@ class JavaExample // / A simple array example. - void arrayExample1(Context ctx) throws Z3Exception, TestFailedException + void arrayExample1(Context ctx) throws TestFailedException { System.out.println("ArrayExample1"); Log.append("ArrayExample1"); @@ -407,8 +403,7 @@ class JavaExample // / This example demonstrates how to use the array // theory. - public void arrayExample2(Context ctx) throws Z3Exception, - TestFailedException + public void arrayExample2(Context ctx) throws TestFailedException { System.out.println("ArrayExample2"); Log.append("ArrayExample2"); @@ -457,8 +452,7 @@ class JavaExample // / This example also shows how to use the distinct // construct. - public void arrayExample3(Context ctx) throws Z3Exception, - TestFailedException + public void arrayExample3(Context ctx) throws TestFailedException { System.out.println("ArrayExample3"); Log.append("ArrayExample2"); @@ -497,7 +491,7 @@ class JavaExample // / Sudoku solving example. - void sudokuExample(Context ctx) throws Z3Exception, TestFailedException + void sudokuExample(Context ctx) throws TestFailedException { System.out.println("SudokuExample"); Log.append("SudokuExample"); @@ -600,7 +594,7 @@ class JavaExample // / A basic example of how to use quantifiers. - void quantifierExample1(Context ctx) throws Z3Exception + void quantifierExample1(Context ctx) { System.out.println("QuantifierExample"); Log.append("QuantifierExample"); @@ -638,7 +632,7 @@ class JavaExample System.out.println("Quantifier Y: " + y.toString()); } - void quantifierExample2(Context ctx) throws Z3Exception + void quantifierExample2(Context ctx) { System.out.println("QuantifierExample2"); @@ -694,8 +688,7 @@ class JavaExample // / f is injective in the second argument. - public void quantifierExample3(Context ctx) throws Z3Exception, - TestFailedException + public void quantifierExample3(Context ctx) throws TestFailedException { System.out.println("QuantifierExample3"); Log.append("QuantifierExample3"); @@ -736,8 +729,7 @@ class JavaExample // / f is injective in the second argument. - public void quantifierExample4(Context ctx) throws Z3Exception, - TestFailedException + public void quantifierExample4(Context ctx) throws TestFailedException { System.out.println("QuantifierExample4"); Log.append("QuantifierExample4"); @@ -776,7 +768,7 @@ class JavaExample // / Some basic tests. - void basicTests(Context ctx) throws Z3Exception, TestFailedException + void basicTests(Context ctx) throws TestFailedException { System.out.println("BasicTests"); @@ -890,7 +882,7 @@ class JavaExample // / Some basic expression casting tests. - void castingTest(Context ctx) throws Z3Exception, TestFailedException + void castingTest(Context ctx) throws TestFailedException { System.out.println("CastingTest"); @@ -1038,7 +1030,7 @@ class JavaExample // / Shows how to read an SMT1 file. - void smt1FileTest(String filename) throws Z3Exception + void smt1FileTest(String filename) { System.out.print("SMT File test "); @@ -1054,7 +1046,7 @@ class JavaExample // / Shows how to read an SMT2 file. - void smt2FileTest(String filename) throws Z3Exception + void smt2FileTest(String filename) { Date before = new Date(); @@ -1096,7 +1088,7 @@ class JavaExample // / Shows how to use Solver(logic) // / @param ctx - void logicExample(Context ctx) throws Z3Exception, TestFailedException + void logicExample(Context ctx) throws TestFailedException { System.out.println("LogicTest"); Log.append("LogicTest"); @@ -1128,7 +1120,7 @@ class JavaExample // / Demonstrates how to use the ParOr tactic. - void parOrExample(Context ctx) throws Z3Exception, TestFailedException + void parOrExample(Context ctx) throws TestFailedException { System.out.println("ParOrExample"); Log.append("ParOrExample"); @@ -1151,7 +1143,7 @@ class JavaExample throw new TestFailedException(); } - void bigIntCheck(Context ctx, RatNum r) throws Z3Exception + void bigIntCheck(Context ctx, RatNum r) { System.out.println("Num: " + r.getBigIntNumerator()); System.out.println("Den: " + r.getBigIntDenominator()); @@ -1159,8 +1151,7 @@ class JavaExample // / Find a model for x xor y. - public void findModelExample1(Context ctx) throws Z3Exception, - TestFailedException + public void findModelExample1(Context ctx) throws TestFailedException { System.out.println("FindModelExample1"); Log.append("FindModelExample1"); @@ -1177,8 +1168,7 @@ class JavaExample // / Find a model for x < y + 1, x > 2. // / Then, assert not(x = y), and find another model. - public void findModelExample2(Context ctx) throws Z3Exception, - TestFailedException + public void findModelExample2(Context ctx) throws TestFailedException { System.out.println("FindModelExample2"); Log.append("FindModelExample2"); @@ -1217,8 +1207,7 @@ class JavaExample // / This function demonstrates how to create uninterpreted // / types and functions. - public void proveExample1(Context ctx) throws Z3Exception, - TestFailedException + public void proveExample1(Context ctx) throws TestFailedException { System.out.println("ProveExample1"); Log.append("ProveExample1"); @@ -1264,8 +1253,7 @@ class JavaExample // / This example demonstrates how to combine uninterpreted // functions // / and arithmetic. - public void proveExample2(Context ctx) throws Z3Exception, - TestFailedException + public void proveExample2(Context ctx) throws TestFailedException { System.out.println("ProveExample2"); Log.append("ProveExample2"); @@ -1319,8 +1307,7 @@ class JavaExample // / This example also demonstrates how big numbers can be // / created in ctx. - public void pushPopExample1(Context ctx) throws Z3Exception, - TestFailedException + public void pushPopExample1(Context ctx) throws TestFailedException { System.out.println("PushPopExample1"); Log.append("PushPopExample1"); @@ -1386,8 +1373,7 @@ class JavaExample // / Check that the projection of a tuple // / returns the corresponding element. - public void tupleExample(Context ctx) throws Z3Exception, - TestFailedException + public void tupleExample(Context ctx) throws TestFailedException { System.out.println("TupleExample"); Log.append("TupleExample"); @@ -1422,8 +1408,7 @@ class JavaExample // / This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) // machine integers // / - public void bitvectorExample1(Context ctx) throws Z3Exception, - TestFailedException + public void bitvectorExample1(Context ctx) throws TestFailedException { System.out.println("BitvectorExample1"); Log.append("BitvectorExample1"); @@ -1444,8 +1429,7 @@ class JavaExample // / Find x and y such that: x ^ y - 103 == x * y - public void bitvectorExample2(Context ctx) throws Z3Exception, - TestFailedException + public void bitvectorExample2(Context ctx) throws TestFailedException { System.out.println("BitvectorExample2"); Log.append("BitvectorExample2"); @@ -1470,8 +1454,7 @@ class JavaExample // / Demonstrates how to use the SMTLIB parser. - public void parserExample1(Context ctx) throws Z3Exception, - TestFailedException + public void parserExample1(Context ctx) throws TestFailedException { System.out.println("ParserExample1"); Log.append("ParserExample1"); @@ -1489,8 +1472,7 @@ class JavaExample // / Demonstrates how to initialize the parser symbol table. - public void parserExample2(Context ctx) throws Z3Exception, - TestFailedException + public void parserExample2(Context ctx) throws TestFailedException { System.out.println("ParserExample2"); Log.append("ParserExample2"); @@ -1532,7 +1514,7 @@ class JavaExample // / Display the declarations, assumptions and formulas in a SMT-LIB string. - public void parserExample4(Context ctx) throws Z3Exception + public void parserExample4(Context ctx) { System.out.println("ParserExample4"); Log.append("ParserExample4"); @@ -1579,7 +1561,7 @@ class JavaExample // / Create an ite-Expr (if-then-else Exprs). - public void iteExample(Context ctx) throws Z3Exception + public void iteExample(Context ctx) { System.out.println("ITEExample"); Log.append("ITEExample"); @@ -1594,8 +1576,7 @@ class JavaExample // / Create an enumeration data type. - public void enumExample(Context ctx) throws Z3Exception, - TestFailedException + public void enumExample(Context ctx) throws TestFailedException { System.out.println("EnumExample"); Log.append("EnumExample"); @@ -1642,8 +1623,7 @@ class JavaExample // / Create a list datatype. - public void listExample(Context ctx) throws Z3Exception, - TestFailedException + public void listExample(Context ctx) throws TestFailedException { System.out.println("ListExample"); Log.append("ListExample"); @@ -1706,8 +1686,7 @@ class JavaExample // / Create a binary tree datatype. - public void treeExample(Context ctx) throws Z3Exception, - TestFailedException + public void treeExample(Context ctx) throws TestFailedException { System.out.println("TreeExample"); Log.append("TreeExample"); @@ -1779,8 +1758,7 @@ class JavaExample // / forest ::= nil | cons(tree, forest) // / tree ::= nil | cons(forest, forest) // / - public void forestExample(Context ctx) throws Z3Exception, - TestFailedException + public void forestExample(Context ctx) throws TestFailedException { System.out.println("ForestExample"); Log.append("ForestExample"); @@ -1899,7 +1877,7 @@ class JavaExample // / Demonstrate how to use #Eval. - public void evalExample1(Context ctx) throws Z3Exception + public void evalExample1(Context ctx) { System.out.println("EvalExample1"); Log.append("EvalExample1"); @@ -1939,7 +1917,7 @@ class JavaExample // / Demonstrate how to use #Eval on tuples. - public void evalExample2(Context ctx) throws Z3Exception + public void evalExample2(Context ctx) { System.out.println("EvalExample2"); Log.append("EvalExample2"); @@ -1990,8 +1968,7 @@ class JavaExample // / control the size of models. // / Note: this test is specialized to 32-bit bitvectors. - public void checkSmall(Context ctx, Solver solver, - BitVecExpr... to_minimize) throws Z3Exception + public void checkSmall(Context ctx, Solver solver, BitVecExpr... to_minimize) { int num_Exprs = to_minimize.length; int[] upper = new int[num_Exprs]; @@ -2063,7 +2040,7 @@ class JavaExample // / Reduced-size model generation example. - public void findSmallModelExample(Context ctx) throws Z3Exception + public void findSmallModelExample(Context ctx) { System.out.println("FindSmallModelExample"); Log.append("FindSmallModelExample"); @@ -2080,7 +2057,7 @@ class JavaExample // / Simplifier example. - public void simplifierExample(Context ctx) throws Z3Exception + public void simplifierExample(Context ctx) { System.out.println("SimplifierExample"); Log.append("SimplifierExample"); @@ -2098,7 +2075,7 @@ class JavaExample // / Extract unsatisfiable core example - public void unsatCoreAndProofExample(Context ctx) throws Z3Exception + public void unsatCoreAndProofExample(Context ctx) { System.out.println("UnsatCoreAndProofExample"); Log.append("UnsatCoreAndProofExample"); @@ -2140,7 +2117,7 @@ class JavaExample /// Extract unsatisfiable core example with AssertAndTrack - public void unsatCoreAndProofExample2(Context ctx) throws Z3Exception + public void unsatCoreAndProofExample2(Context ctx) { System.out.println("UnsatCoreAndProofExample2"); Log.append("UnsatCoreAndProofExample2"); @@ -2179,7 +2156,7 @@ class JavaExample } } - public void finiteDomainExample(Context ctx) throws Z3Exception + public void finiteDomainExample(Context ctx) { System.out.println("FiniteDomainExample"); Log.append("FiniteDomainExample"); @@ -2198,7 +2175,7 @@ class JavaExample // System.out.println(ctx.mkEq(s1, t1)); } - public void floatingPointExample1(Context ctx) throws Z3Exception, TestFailedException + public void floatingPointExample1(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample1"); Log.append("FloatingPointExample1"); @@ -2249,7 +2226,7 @@ class JavaExample System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); } - public void floatingPointExample2(Context ctx) throws Z3Exception, TestFailedException + public void floatingPointExample2(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample2"); Log.append("FloatingPointExample2"); From 8862cb4833a684124baf75897e26598f26883fa1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 9 Apr 2015 14:46:59 +0100 Subject: [PATCH 628/646] Java example: Removed throws declarations for Z3Exception. --- examples/java/JavaExample.java | 127 ++++++++++++++------------------- 1 file changed, 52 insertions(+), 75 deletions(-) diff --git a/examples/java/JavaExample.java b/examples/java/JavaExample.java index 5c49b56ae..4a579f9da 100644 --- a/examples/java/JavaExample.java +++ b/examples/java/JavaExample.java @@ -41,7 +41,7 @@ class JavaExample // / // / Where, finvis a fresh function declaration. - public BoolExpr injAxiom(Context ctx, FuncDecl f, int i) throws Z3Exception + public BoolExpr injAxiom(Context ctx, FuncDecl f, int i) { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); @@ -102,7 +102,6 @@ class JavaExample // / Where, finvis a fresh function declaration. public BoolExpr injAxiomAbs(Context ctx, FuncDecl f, int i) - throws Z3Exception { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); @@ -179,7 +178,7 @@ class JavaExample // / "Hello world" example: create a Z3 logical context, and delete it. - public void simpleExample() throws Z3Exception + public void simpleExample() { System.out.println("SimpleExample"); Log.append("SimpleExample"); @@ -193,8 +192,7 @@ class JavaExample } } - Model check(Context ctx, BoolExpr f, Status sat) throws Z3Exception, - TestFailedException + Model check(Context ctx, BoolExpr f, Status sat) throws TestFailedException { Solver s = ctx.mkSolver(); s.add(f); @@ -207,7 +205,7 @@ class JavaExample } void solveTactical(Context ctx, Tactic t, Goal g, Status sat) - throws Z3Exception, TestFailedException + throws TestFailedException { Solver s = ctx.mkSolver(t); System.out.println("\nTactical solver: " + s); @@ -220,7 +218,7 @@ class JavaExample throw new TestFailedException(); } - ApplyResult applyTactic(Context ctx, Tactic t, Goal g) throws Z3Exception + ApplyResult applyTactic(Context ctx, Tactic t, Goal g) { System.out.println("\nGoal: " + g); @@ -250,15 +248,14 @@ class JavaExample return res; } - void prove(Context ctx, BoolExpr f, boolean useMBQI) throws Z3Exception, - TestFailedException + void prove(Context ctx, BoolExpr f, boolean useMBQI) throws TestFailedException { BoolExpr[] assumptions = new BoolExpr[0]; prove(ctx, f, useMBQI, assumptions); } void prove(Context ctx, BoolExpr f, boolean useMBQI, - BoolExpr... assumptions) throws Z3Exception, TestFailedException + BoolExpr... assumptions) throws TestFailedException { System.out.println("Proving: " + f); Solver s = ctx.mkSolver(); @@ -283,15 +280,15 @@ class JavaExample } } - void disprove(Context ctx, BoolExpr f, boolean useMBQI) throws Z3Exception, - TestFailedException + void disprove(Context ctx, BoolExpr f, boolean useMBQI) + throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); } void disprove(Context ctx, BoolExpr f, boolean useMBQI, - BoolExpr... assumptions) throws Z3Exception, TestFailedException + BoolExpr... assumptions) throws TestFailedException { System.out.println("Disproving: " + f); Solver s = ctx.mkSolver(); @@ -316,8 +313,7 @@ class JavaExample } } - void modelConverterTest(Context ctx) throws Z3Exception, - TestFailedException + void modelConverterTest(Context ctx) throws TestFailedException { System.out.println("ModelConverterTest"); @@ -357,7 +353,7 @@ class JavaExample // / A simple array example. - void arrayExample1(Context ctx) throws Z3Exception, TestFailedException + void arrayExample1(Context ctx) throws TestFailedException { System.out.println("ArrayExample1"); Log.append("ArrayExample1"); @@ -407,8 +403,7 @@ class JavaExample // / This example demonstrates how to use the array // theory. - public void arrayExample2(Context ctx) throws Z3Exception, - TestFailedException + public void arrayExample2(Context ctx) throws TestFailedException { System.out.println("ArrayExample2"); Log.append("ArrayExample2"); @@ -457,8 +452,7 @@ class JavaExample // / This example also shows how to use the distinct // construct. - public void arrayExample3(Context ctx) throws Z3Exception, - TestFailedException + public void arrayExample3(Context ctx) throws TestFailedException { System.out.println("ArrayExample3"); Log.append("ArrayExample2"); @@ -497,7 +491,7 @@ class JavaExample // / Sudoku solving example. - void sudokuExample(Context ctx) throws Z3Exception, TestFailedException + void sudokuExample(Context ctx) throws TestFailedException { System.out.println("SudokuExample"); Log.append("SudokuExample"); @@ -600,7 +594,7 @@ class JavaExample // / A basic example of how to use quantifiers. - void quantifierExample1(Context ctx) throws Z3Exception + void quantifierExample1(Context ctx) { System.out.println("QuantifierExample"); Log.append("QuantifierExample"); @@ -638,7 +632,7 @@ class JavaExample System.out.println("Quantifier Y: " + y.toString()); } - void quantifierExample2(Context ctx) throws Z3Exception + void quantifierExample2(Context ctx) { System.out.println("QuantifierExample2"); @@ -694,8 +688,7 @@ class JavaExample // / f is injective in the second argument. - public void quantifierExample3(Context ctx) throws Z3Exception, - TestFailedException + public void quantifierExample3(Context ctx) throws TestFailedException { System.out.println("QuantifierExample3"); Log.append("QuantifierExample3"); @@ -736,8 +729,7 @@ class JavaExample // / f is injective in the second argument. - public void quantifierExample4(Context ctx) throws Z3Exception, - TestFailedException + public void quantifierExample4(Context ctx) throws TestFailedException { System.out.println("QuantifierExample4"); Log.append("QuantifierExample4"); @@ -776,7 +768,7 @@ class JavaExample // / Some basic tests. - void basicTests(Context ctx) throws Z3Exception, TestFailedException + void basicTests(Context ctx) throws TestFailedException { System.out.println("BasicTests"); @@ -890,7 +882,7 @@ class JavaExample // / Some basic expression casting tests. - void castingTest(Context ctx) throws Z3Exception, TestFailedException + void castingTest(Context ctx) throws TestFailedException { System.out.println("CastingTest"); @@ -1038,7 +1030,7 @@ class JavaExample // / Shows how to read an SMT1 file. - void smt1FileTest(String filename) throws Z3Exception + void smt1FileTest(String filename) { System.out.print("SMT File test "); @@ -1054,7 +1046,7 @@ class JavaExample // / Shows how to read an SMT2 file. - void smt2FileTest(String filename) throws Z3Exception + void smt2FileTest(String filename) { Date before = new Date(); @@ -1096,7 +1088,7 @@ class JavaExample // / Shows how to use Solver(logic) // / @param ctx - void logicExample(Context ctx) throws Z3Exception, TestFailedException + void logicExample(Context ctx) throws TestFailedException { System.out.println("LogicTest"); Log.append("LogicTest"); @@ -1128,7 +1120,7 @@ class JavaExample // / Demonstrates how to use the ParOr tactic. - void parOrExample(Context ctx) throws Z3Exception, TestFailedException + void parOrExample(Context ctx) throws TestFailedException { System.out.println("ParOrExample"); Log.append("ParOrExample"); @@ -1151,7 +1143,7 @@ class JavaExample throw new TestFailedException(); } - void bigIntCheck(Context ctx, RatNum r) throws Z3Exception + void bigIntCheck(Context ctx, RatNum r) { System.out.println("Num: " + r.getBigIntNumerator()); System.out.println("Den: " + r.getBigIntDenominator()); @@ -1159,8 +1151,7 @@ class JavaExample // / Find a model for x xor y. - public void findModelExample1(Context ctx) throws Z3Exception, - TestFailedException + public void findModelExample1(Context ctx) throws TestFailedException { System.out.println("FindModelExample1"); Log.append("FindModelExample1"); @@ -1177,8 +1168,7 @@ class JavaExample // / Find a model for x < y + 1, x > 2. // / Then, assert not(x = y), and find another model. - public void findModelExample2(Context ctx) throws Z3Exception, - TestFailedException + public void findModelExample2(Context ctx) throws TestFailedException { System.out.println("FindModelExample2"); Log.append("FindModelExample2"); @@ -1217,8 +1207,7 @@ class JavaExample // / This function demonstrates how to create uninterpreted // / types and functions. - public void proveExample1(Context ctx) throws Z3Exception, - TestFailedException + public void proveExample1(Context ctx) throws TestFailedException { System.out.println("ProveExample1"); Log.append("ProveExample1"); @@ -1264,8 +1253,7 @@ class JavaExample // / This example demonstrates how to combine uninterpreted // functions // / and arithmetic. - public void proveExample2(Context ctx) throws Z3Exception, - TestFailedException + public void proveExample2(Context ctx) throws TestFailedException { System.out.println("ProveExample2"); Log.append("ProveExample2"); @@ -1319,8 +1307,7 @@ class JavaExample // / This example also demonstrates how big numbers can be // / created in ctx. - public void pushPopExample1(Context ctx) throws Z3Exception, - TestFailedException + public void pushPopExample1(Context ctx) throws TestFailedException { System.out.println("PushPopExample1"); Log.append("PushPopExample1"); @@ -1386,8 +1373,7 @@ class JavaExample // / Check that the projection of a tuple // / returns the corresponding element. - public void tupleExample(Context ctx) throws Z3Exception, - TestFailedException + public void tupleExample(Context ctx) throws TestFailedException { System.out.println("TupleExample"); Log.append("TupleExample"); @@ -1422,8 +1408,7 @@ class JavaExample // / This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) // machine integers // / - public void bitvectorExample1(Context ctx) throws Z3Exception, - TestFailedException + public void bitvectorExample1(Context ctx) throws TestFailedException { System.out.println("BitvectorExample1"); Log.append("BitvectorExample1"); @@ -1444,8 +1429,7 @@ class JavaExample // / Find x and y such that: x ^ y - 103 == x * y - public void bitvectorExample2(Context ctx) throws Z3Exception, - TestFailedException + public void bitvectorExample2(Context ctx) throws TestFailedException { System.out.println("BitvectorExample2"); Log.append("BitvectorExample2"); @@ -1470,8 +1454,7 @@ class JavaExample // / Demonstrates how to use the SMTLIB parser. - public void parserExample1(Context ctx) throws Z3Exception, - TestFailedException + public void parserExample1(Context ctx) throws TestFailedException { System.out.println("ParserExample1"); Log.append("ParserExample1"); @@ -1489,8 +1472,7 @@ class JavaExample // / Demonstrates how to initialize the parser symbol table. - public void parserExample2(Context ctx) throws Z3Exception, - TestFailedException + public void parserExample2(Context ctx) throws TestFailedException { System.out.println("ParserExample2"); Log.append("ParserExample2"); @@ -1532,7 +1514,7 @@ class JavaExample // / Display the declarations, assumptions and formulas in a SMT-LIB string. - public void parserExample4(Context ctx) throws Z3Exception + public void parserExample4(Context ctx) { System.out.println("ParserExample4"); Log.append("ParserExample4"); @@ -1579,7 +1561,7 @@ class JavaExample // / Create an ite-Expr (if-then-else Exprs). - public void iteExample(Context ctx) throws Z3Exception + public void iteExample(Context ctx) { System.out.println("ITEExample"); Log.append("ITEExample"); @@ -1594,8 +1576,7 @@ class JavaExample // / Create an enumeration data type. - public void enumExample(Context ctx) throws Z3Exception, - TestFailedException + public void enumExample(Context ctx) throws TestFailedException { System.out.println("EnumExample"); Log.append("EnumExample"); @@ -1642,8 +1623,7 @@ class JavaExample // / Create a list datatype. - public void listExample(Context ctx) throws Z3Exception, - TestFailedException + public void listExample(Context ctx) throws TestFailedException { System.out.println("ListExample"); Log.append("ListExample"); @@ -1706,8 +1686,7 @@ class JavaExample // / Create a binary tree datatype. - public void treeExample(Context ctx) throws Z3Exception, - TestFailedException + public void treeExample(Context ctx) throws TestFailedException { System.out.println("TreeExample"); Log.append("TreeExample"); @@ -1779,8 +1758,7 @@ class JavaExample // / forest ::= nil | cons(tree, forest) // / tree ::= nil | cons(forest, forest) // / - public void forestExample(Context ctx) throws Z3Exception, - TestFailedException + public void forestExample(Context ctx) throws TestFailedException { System.out.println("ForestExample"); Log.append("ForestExample"); @@ -1899,7 +1877,7 @@ class JavaExample // / Demonstrate how to use #Eval. - public void evalExample1(Context ctx) throws Z3Exception + public void evalExample1(Context ctx) { System.out.println("EvalExample1"); Log.append("EvalExample1"); @@ -1939,7 +1917,7 @@ class JavaExample // / Demonstrate how to use #Eval on tuples. - public void evalExample2(Context ctx) throws Z3Exception + public void evalExample2(Context ctx) { System.out.println("EvalExample2"); Log.append("EvalExample2"); @@ -1990,8 +1968,7 @@ class JavaExample // / control the size of models. // / Note: this test is specialized to 32-bit bitvectors. - public void checkSmall(Context ctx, Solver solver, - BitVecExpr... to_minimize) throws Z3Exception + public void checkSmall(Context ctx, Solver solver, BitVecExpr... to_minimize) { int num_Exprs = to_minimize.length; int[] upper = new int[num_Exprs]; @@ -2063,7 +2040,7 @@ class JavaExample // / Reduced-size model generation example. - public void findSmallModelExample(Context ctx) throws Z3Exception + public void findSmallModelExample(Context ctx) { System.out.println("FindSmallModelExample"); Log.append("FindSmallModelExample"); @@ -2080,7 +2057,7 @@ class JavaExample // / Simplifier example. - public void simplifierExample(Context ctx) throws Z3Exception + public void simplifierExample(Context ctx) { System.out.println("SimplifierExample"); Log.append("SimplifierExample"); @@ -2098,7 +2075,7 @@ class JavaExample // / Extract unsatisfiable core example - public void unsatCoreAndProofExample(Context ctx) throws Z3Exception + public void unsatCoreAndProofExample(Context ctx) { System.out.println("UnsatCoreAndProofExample"); Log.append("UnsatCoreAndProofExample"); @@ -2140,7 +2117,7 @@ class JavaExample /// Extract unsatisfiable core example with AssertAndTrack - public void unsatCoreAndProofExample2(Context ctx) throws Z3Exception + public void unsatCoreAndProofExample2(Context ctx) { System.out.println("UnsatCoreAndProofExample2"); Log.append("UnsatCoreAndProofExample2"); @@ -2179,7 +2156,7 @@ class JavaExample } } - public void finiteDomainExample(Context ctx) throws Z3Exception + public void finiteDomainExample(Context ctx) { System.out.println("FiniteDomainExample"); Log.append("FiniteDomainExample"); @@ -2198,7 +2175,7 @@ class JavaExample // System.out.println(ctx.mkEq(s1, t1)); } - public void floatingPointExample1(Context ctx) throws Z3Exception, TestFailedException + public void floatingPointExample1(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample1"); Log.append("FloatingPointExample1"); @@ -2249,7 +2226,7 @@ class JavaExample System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); } - public void floatingPointExample2(Context ctx) throws Z3Exception, TestFailedException + public void floatingPointExample2(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample2"); Log.append("FloatingPointExample2"); From f993d3df15c37c52a8c0db25b4dc0f15e80ac84f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 13 Apr 2015 17:33:26 +0100 Subject: [PATCH 629/646] Documentation generator bugfixes and updates. --- doc/mk_api_doc.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++- doc/website.dox | 3 ++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/doc/mk_api_doc.py b/doc/mk_api_doc.py index 476f2c8c7..b93654288 100644 --- a/doc/mk_api_doc.py +++ b/doc/mk_api_doc.py @@ -1,11 +1,52 @@ import os import shutil import re +import getopt import pydoc import sys import subprocess import shutil +ML_ENABLED=False +BUILD_DIR='../build' + +def norm_path(p): + # We use '/' on mk_project for convenience + return os.path.join(*(p.split('/'))) + +def display_help(exit_code): + print("mk_api_doc.py: Z3 documentation generator\n") + print("\nOptions:") + print(" -h, --help display this message.") + print(" -b , --build= subdirectory where Z3 is built (default: ../build).") + print(" --ml include ML/OCaml API documentation.") + +def parse_options(): + global ML_ENABLED, BUILD_DIR + + try: + options, remainder = getopt.gnu_getopt(sys.argv[1:], + 'b:h', + ['build=', 'help', 'ml']) + except: + print("ERROR: Invalid command line option") + display_help(1) + + for opt, arg in options: + if opt in ('-b', '--build'): + BUILD_DIR = norm_path(arg) + elif opt in ('h', '--help'): + display_help() + exit(1) + elif opt in ('--ml'): + ML_ENABLED=True + else: + print("ERROR: Invalid command line option: %s" % opt) + display_help(1) + + + + def mk_dir(d): if not os.path.exists(d): os.makedirs(d) @@ -22,9 +63,23 @@ def cleanup_API(inf, outf): _outf.write(line) try: + parse_options() + + fi = open('website.dox', 'r') + fo = open('website-adj.dox', 'w') + + for line in fi: + if (line != '[ML]\n'): + fo.write(line) + elif (ML_ENABLED): + fo.write(' - ML/OCaml API\n') + fi.close() + fo.close() + mk_dir('api/html') mk_dir('tmp') - shutil.copyfile('website.dox', 'tmp/website.dox') + shutil.copyfile('website-adj.dox', 'tmp/website.dox') + os.remove('website-adj.dox') shutil.copyfile('../src/api/python/z3.py', 'tmp/z3py.py') cleanup_API('../src/api/z3_api.h', 'tmp/z3_api.h') cleanup_API('../src/api/z3_algebraic.h', 'tmp/z3_algebraic.h') @@ -59,6 +114,14 @@ try: pydoc.writedoc('z3') shutil.move('z3.html', 'api/html/z3.html') print "Generated Python documentation." + + if ML_ENABLED: + mk_dir('api/html/ml') + if subprocess.call(['ocamldoc', '-html', '-d', 'api\html\ml', '-sort', '-hide', 'Z3', '-I', '%s/api/ml' % BUILD_DIR, '../src/api/ml/z3enums.mli', '../src/api/ml/z3.mli']) != 0: + print "ERROR: ocamldoc failed." + exit(1) + print "Generated ML/OCaml documentation." + print "Documentation was successfully generated at subdirectory './api/html'." except: print "ERROR: failed to generate documentation" diff --git a/doc/website.dox b/doc/website.dox index d048dab0c..5b77c46c6 100644 --- a/doc/website.dox +++ b/doc/website.dox @@ -14,6 +14,7 @@ - \ref cppapi - .NET API - Java API - - Python API (also available in pydoc format). + - Python API (also available in pydoc format) +[ML] - Try Z3 online at RiSE4Fun. */ From bf00723d379b506010c47ef4b1a94b71215cce54 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 13 Apr 2015 17:37:58 +0100 Subject: [PATCH 630/646] Updated links in the documentation --- doc/website.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/website.dox b/doc/website.dox index 5b77c46c6..799949752 100644 --- a/doc/website.dox +++ b/doc/website.dox @@ -4,9 +4,9 @@ Z3 is a high-performance theorem prover being developed at Microsoft Research. - The Z3 website moved to z3.codeplex.com. + The Z3 website moved to http://github.com/z3prover.. - The old Z3 website can be found here. + The old Z3 websites can be found here and here. This website hosts the automatically generated documentation for the Z3 APIs. From 2948e47240b22445b3627aa3fb38a35d8ab796bb Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 13 Apr 2015 17:43:29 +0100 Subject: [PATCH 631/646] Java API doc fix --- src/api/java/Context.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 744cfc03f..fac4f5180 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -3195,7 +3195,7 @@ public class Context extends IDisposable * @param rm rounding mode term * @param t1 floating-point term * @param t2 floating-point term - * @param t3">floating-point term + * @param t3 floating-point term * Remarks: * The result is round((t1 * t2) + t3) * @throws Z3Exception @@ -3230,7 +3230,7 @@ public class Context extends IDisposable /** * Floating-point roundToIntegral. Rounds a floating-point number to * the closest integer, again represented as a floating-point number. - * @param rm">term of RoundingMode sort + * @param rm term of RoundingMode sort * @param t floating-point term * @throws Z3Exception **/ @@ -3408,7 +3408,7 @@ public class Context extends IDisposable /** * Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. - * @param bv">bit-vector value (of size m). + * @param bv bit-vector value (of size m). * @param s FloatingPoint sort (ebits+sbits == m) * Remarks: * Produces a term that represents the conversion of a bit-vector term bv to a From a5036769b30e5c7ef9b46ebeca8ee6459a300125 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 13 Apr 2015 17:46:18 +0100 Subject: [PATCH 632/646] ML API doc fix --- doc/mk_api_doc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/mk_api_doc.py b/doc/mk_api_doc.py index b93654288..1b498fb19 100644 --- a/doc/mk_api_doc.py +++ b/doc/mk_api_doc.py @@ -72,7 +72,7 @@ try: if (line != '[ML]\n'): fo.write(line) elif (ML_ENABLED): - fo.write(' - ML/OCaml API\n') + fo.write(' - ML/OCaml API\n') fi.close() fo.close() From 80a13977fcd94b5ebe4cc458f0633c5b213c867d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 15 Apr 2015 05:44:10 +0100 Subject: [PATCH 633/646] fix race condition from cancellation exposed by build regression tests Signed-off-by: Nikolaj Bjorner --- src/math/polynomial/polynomial.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 3f1883749..8f4c55392 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -4761,6 +4761,25 @@ namespace polynomial { } } + // muladd may throw if the cancel flag is set. + // So we wrap the degree2pos set and reset + // in a scoped class to ensure the state is clean + // on exit. + struct scoped_degree2pos { + imp& pm; + polynomial const* p; + scoped_degree2pos(imp& pm, polynomial const* p): + pm(pm), + p(p) + { + pm.save_degree2pos(p); + } + + ~scoped_degree2pos() { + pm.reset_degree2pos(p); + } + }; + /** \brief Given an univariate polynomial p(x) and a polynomial q(y_1, ..., y_n), return a polynomial r(y_1, ..., y_n) = p(q(y_1, ..., y_n)). @@ -4773,7 +4792,7 @@ namespace polynomial { } var x = max_var(p); unsigned d = degree(p, x); - save_degree2pos(p); + scoped_degree2pos _sd2pos(*this, p); scoped_numeral a(m()); m_manager.set(a, p->a(m_degree2pos[d])); r = mk_const(a); @@ -4783,9 +4802,8 @@ namespace polynomial { m_manager.set(a, p->a(pos)); else m_manager.reset(a); - r = muladd(q, r, a); + r = muladd(q, r, a); } - reset_degree2pos(p); } polynomial * mk_x_minus_y(var x, var y) { From e1303e1eabbb003232ad3f7db35c332f5a0deca6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 15 Apr 2015 12:07:53 +0100 Subject: [PATCH 634/646] Python API: Fixed expression types for floating point conversion functions. Partially fixes #39 --- src/api/python/z3.py | 64 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 414aeb2af..cf4bcd87c 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -8422,29 +8422,77 @@ def fpToFPUnsigned(rm, x, s): return FPRef(Z3_mk_fpa_to_fp_unsigned(rm.ctx_ref(), rm.ast, x.ast, s.ast), rm.ctx) def fpToSBV(rm, x, s): - """Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector.""" + """Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector. + + >>> x = FP('x', FPSort(8, 24)) + >>> y = fpToSBV(RTZ(), x, BitVecSort(32)) + >>> print is_fp(x) + True + >>> print is_bv(y) + True + >>> print is_fp(y) + False + >>> print is_bv(x) + False + """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") - return FPRef(Z3_mk_fpa_to_sbv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) + return BitVecRef(Z3_mk_fpa_to_sbv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) def fpToUBV(rm, x, s): - """Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector.""" + """Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector. + + >>> x = FP('x', FPSort(8, 24)) + >>> y = fpToUBV(RTZ(), x, BitVecSort(32)) + >>> print is_fp(x) + True + >>> print is_bv(y) + True + >>> print is_fp(y) + False + >>> print is_bv(x) + False + """ if __debug__: _z3_assert(is_fprm(rm), "First argument must be a Z3 floating-point rounding mode expression") _z3_assert(is_fp(x), "Second argument must be a Z3 floating-point expression") _z3_assert(is_bv_sort(s), "Third argument must be Z3 bit-vector sort") - return FPRef(Z3_mk_fpa_to_ubv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) + return BitVecRef(Z3_mk_fpa_to_ubv(rm.ctx_ref(), rm.ast, x.ast, s.size()), rm.ctx) def fpToReal(x): - """Create a Z3 floating-point conversion expression, from floating-point expression to real.""" + """Create a Z3 floating-point conversion expression, from floating-point expression to real. + + >>> x = FP('x', FPSort(8, 24)) + >>> y = fpToReal(x) + >>> print is_fp(x) + True + >>> print is_real(y) + True + >>> print is_fp(y) + False + >>> print is_real(x) + False + """ if __debug__: _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") - return FPRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx) + return ArithRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx) def fpToIEEEBV(x): - """Create a Z3 floating-point conversion expression, from floating-point expression to IEEE bit-vector.""" + """Create a Z3 floating-point conversion expression, from floating-point expression to IEEE bit-vector. + + >>> x = FP('x', FPSort(8, 24)) + >>> y = fpToIEEEBV(x) + >>> print is_fp(x) + True + >>> print is_bv(y) + True + >>> print is_fp(y) + False + >>> print is_bv(x) + False + """ if __debug__: _z3_assert(is_fp(x), "First argument must be a Z3 floating-point expression") - return FPRef(Z3_mk_fpa_to_ieee_bv(x.ctx_ref(), x.ast), x.ctx) + return BitVecRef(Z3_mk_fpa_to_ieee_bv(x.ctx_ref(), x.ast), x.ctx) From af444beb2edb2b8ad650ffdc4a62fafee3ecd10d Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 15 Apr 2015 12:22:50 -0700 Subject: [PATCH 635/646] re-indenting interp and duality --- src/api/api_interp.cpp | 146 +- src/cmd_context/interpolant_cmds.cpp | 258 +- src/cmd_context/interpolant_cmds.h | 18 +- src/duality/duality.h | 1782 ++--- src/duality/duality_profiling.cpp | 194 +- src/duality/duality_profiling.h | 34 +- src/duality/duality_rpfp.cpp | 8014 +++++++++++----------- src/duality/duality_solver.cpp | 6106 ++++++++--------- src/duality/duality_wrapper.cpp | 1252 ++-- src/duality/duality_wrapper.h | 1166 ++-- src/interp/foci2.h | 80 +- src/interp/iz3base.cpp | 494 +- src/interp/iz3base.h | 242 +- src/interp/iz3checker.cpp | 276 +- src/interp/iz3checker.h | 18 +- src/interp/iz3foci.cpp | 638 +- src/interp/iz3foci.h | 20 +- src/interp/iz3hash.h | 732 +- src/interp/iz3interp.cpp | 732 +- src/interp/iz3interp.h | 28 +- src/interp/iz3mgr.cpp | 1258 ++-- src/interp/iz3mgr.h | 1246 ++-- src/interp/iz3pp.cpp | 218 +- src/interp/iz3pp.h | 18 +- src/interp/iz3profiling.cpp | 188 +- src/interp/iz3profiling.h | 34 +- src/interp/iz3proof.cpp | 864 +-- src/interp/iz3proof.h | 352 +- src/interp/iz3proof_itp.cpp | 5446 +++++++-------- src/interp/iz3proof_itp.h | 148 +- src/interp/iz3scopes.cpp | 406 +- src/interp/iz3scopes.h | 292 +- src/interp/iz3secondary.h | 24 +- src/interp/iz3translate.cpp | 3684 +++++----- src/interp/iz3translate.h | 46 +- src/interp/iz3translate_direct.cpp | 2986 ++++---- src/muz/duality/duality_dl_interface.cpp | 990 +-- src/muz/duality/duality_dl_interface.h | 20 +- 38 files changed, 20225 insertions(+), 20225 deletions(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 5ec585c7d..615b798bb 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -1,20 +1,20 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: -api_interp.cpp + api_interp.cpp -Abstract: -API for interpolation + Abstract: + API for interpolation -Author: + Author: -Ken McMillan + Ken McMillan -Revision History: + Revision History: ---*/ + --*/ #include #include #include @@ -191,19 +191,19 @@ extern "C" { Z3_interpolation_options - Z3_mk_interpolation_options(){ + Z3_mk_interpolation_options(){ return (Z3_interpolation_options) new interpolation_options_struct; } void - Z3_del_interpolation_options(Z3_interpolation_options opts){ + Z3_del_interpolation_options(Z3_interpolation_options opts){ delete opts; } void - Z3_set_interpolation_option(Z3_interpolation_options opts, - Z3_string name, - Z3_string value){ + Z3_set_interpolation_option(Z3_interpolation_options opts, + Z3_string name, + Z3_string value){ opts->map[name] = value; } @@ -412,11 +412,11 @@ extern "C" { Z3_ast foo = Z3_mk_interpolant(ctx, and_vec(ctx, c)); chs[parents[i]].push_back(foo); } - { - svector &c = chs[num - 1]; - c.push_back(cnsts[num - 1]); - res = and_vec(ctx, c); - } + { + svector &c = chs[num - 1]; + c.push_back(cnsts[num - 1]); + res = and_vec(ctx, c); + } } Z3_inc_ref(ctx, res); return res; @@ -620,8 +620,8 @@ extern "C" { for (unsigned j = 0; j < num - 1; j++) if (read_parents[j] == SHRT_MAX){ - read_error << "formula " << j + 1 << ": unreferenced"; - goto fail; + read_error << "formula " << j + 1 << ": unreferenced"; + goto fail; } *_num = num; @@ -643,69 +643,69 @@ extern "C" { #define IZ3_ROOT SHRT_MAX /** This function uses Z3 to determine satisfiability of a set of -constraints. If UNSAT, an interpolant is returned, based on the -refutation generated by Z3. If SAT, a model is returned. + constraints. If UNSAT, an interpolant is returned, based on the + refutation generated by Z3. If SAT, a model is returned. -If "parents" is non-null, computes a tree interpolant. The tree is -defined by the array "parents". This array maps each formula in -the tree to its parent, where formulas are indicated by their -integer index in "cnsts". The parent of formula n must have index -greater than n. The last formula is the root of the tree. Its -parent entry should be the constant IZ3_ROOT. + If "parents" is non-null, computes a tree interpolant. The tree is + defined by the array "parents". This array maps each formula in + the tree to its parent, where formulas are indicated by their + integer index in "cnsts". The parent of formula n must have index + greater than n. The last formula is the root of the tree. Its + parent entry should be the constant IZ3_ROOT. -If "parents" is null, computes a sequence interpolant. + If "parents" is null, computes a sequence interpolant. -\param ctx The Z3 context. Must be generated by iz3_mk_context -\param num The number of constraints in the sequence -\param cnsts Array of constraints (AST's in context ctx) -\param parents The parents vector defining the tree structure -\param options Interpolation options (may be NULL) -\param interps Array to return interpolants (size at least num-1, may be NULL) -\param model Returns a Z3 model if constraints SAT (may be NULL) -\param labels Returns relevant labels if SAT (may be NULL) -\param incremental + \param ctx The Z3 context. Must be generated by iz3_mk_context + \param num The number of constraints in the sequence + \param cnsts Array of constraints (AST's in context ctx) + \param parents The parents vector defining the tree structure + \param options Interpolation options (may be NULL) + \param interps Array to return interpolants (size at least num-1, may be NULL) + \param model Returns a Z3 model if constraints SAT (may be NULL) + \param labels Returns relevant labels if SAT (may be NULL) + \param incremental -VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 -context ctx. The model and interpolants returned are also -in this context. + VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 + context ctx. The model and interpolants returned are also + in this context. -The return code is as in Z3_check_assumptions, that is, + The return code is as in Z3_check_assumptions, that is, -Z3_L_FALSE = constraints UNSAT (interpolants returned) -Z3_L_TRUE = constraints SAT (model returned) -Z3_L_UNDEF = Z3 produced no result, or interpolation not possible + Z3_L_FALSE = constraints UNSAT (interpolants returned) + Z3_L_TRUE = constraints SAT (model returned) + Z3_L_UNDEF = Z3 produced no result, or interpolation not possible -Currently, this function supports integer and boolean variables, -as well as arrays over these types, with linear arithmetic, -uninterpreted functions and quantifiers over integers (that is -AUFLIA). Interpolants are produced in AULIA. However, some -uses of array operations may cause quantifiers to appear in the -interpolants even when there are no quantifiers in the input formulas. -Although quantifiers may appear in the input formulas, Z3 may give up in -this case, returning Z3_L_UNDEF. + Currently, this function supports integer and boolean variables, + as well as arrays over these types, with linear arithmetic, + uninterpreted functions and quantifiers over integers (that is + AUFLIA). Interpolants are produced in AULIA. However, some + uses of array operations may cause quantifiers to appear in the + interpolants even when there are no quantifiers in the input formulas. + Although quantifiers may appear in the input formulas, Z3 may give up in + this case, returning Z3_L_UNDEF. -If "incremental" is true, cnsts must contain exactly the set of -formulas that are currently asserted in the context. If false, -there must be no formulas currently asserted in the context. -Setting "incremental" to true makes it posisble to incrementally -add and remove constraints from the context until the context -becomes UNSAT, at which point an interpolant is computed. Caution -must be used, however. Before popping the context, if you wish to -keep the interolant formulas, you *must* preserve them by using -Z3_persist_ast. Also, if you want to simplify the interpolant -formulas using Z3_simplify, you must first pop all of the -assertions in the context (or use a different context). Otherwise, -the formulas will be simplified *relative* to these constraints, -which is almost certainly not what you want. + If "incremental" is true, cnsts must contain exactly the set of + formulas that are currently asserted in the context. If false, + there must be no formulas currently asserted in the context. + Setting "incremental" to true makes it posisble to incrementally + add and remove constraints from the context until the context + becomes UNSAT, at which point an interpolant is computed. Caution + must be used, however. Before popping the context, if you wish to + keep the interolant formulas, you *must* preserve them by using + Z3_persist_ast. Also, if you want to simplify the interpolant + formulas using Z3_simplify, you must first pop all of the + assertions in the context (or use a different context). Otherwise, + the formulas will be simplified *relative* to these constraints, + which is almost certainly not what you want. -Current limitations on tree interpolants. In a tree interpolation -problem, each constant (0-ary function symbol) must occur only -along one path from root to leaf. Function symbols (of arity > 0) -are considered to have global scope (i.e., may appear in any -interpolant formula). + Current limitations on tree interpolants. In a tree interpolation + problem, each constant (0-ary function symbol) must occur only + along one path from root to leaf. Function symbols (of arity > 0) + are considered to have global scope (i.e., may appear in any + interpolant formula). -def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST))) + def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST))) */ Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, diff --git a/src/cmd_context/interpolant_cmds.cpp b/src/cmd_context/interpolant_cmds.cpp index 42646a99d..f41f175ea 100644 --- a/src/cmd_context/interpolant_cmds.cpp +++ b/src/cmd_context/interpolant_cmds.cpp @@ -1,20 +1,20 @@ /*++ -Copyright (c) 2013 Microsoft Corporation + Copyright (c) 2013 Microsoft Corporation -Module Name: + Module Name: - interpolant_cmds.cpp + interpolant_cmds.cpp -Abstract: - Commands for interpolation. + Abstract: + Commands for interpolation. -Author: + Author: - Leonardo (leonardo) 2011-12-23 + Leonardo (leonardo) 2011-12-23 -Notes: + Notes: ---*/ + --*/ #include #include"cmd_context.h" #include"cmd_util.h" @@ -43,180 +43,180 @@ static void show_interpolant_and_maybe_check(cmd_context & ctx, bool check) { - if (m_params.get_bool("som", false)) - m_params.set_bool("flat", true); - th_rewriter s(ctx.m(), m_params); + if (m_params.get_bool("som", false)) + m_params.set_bool("flat", true); + th_rewriter s(ctx.m(), m_params); - for(unsigned i = 0; i < interps.size(); i++){ + for(unsigned i = 0; i < interps.size(); i++){ - expr_ref r(ctx.m()); - proof_ref pr(ctx.m()); - s(to_expr(interps[i]),r,pr); + expr_ref r(ctx.m()); + proof_ref pr(ctx.m()); + s(to_expr(interps[i]),r,pr); - ctx.regular_stream() << mk_pp(r.get(), ctx.m()) << std::endl; + ctx.regular_stream() << mk_pp(r.get(), ctx.m()) << std::endl; #if 0 - ast_smt_pp pp(ctx.m()); - pp.set_logic(ctx.get_logic().str().c_str()); - pp.display_smt2(ctx.regular_stream(), to_expr(interps[i])); - ctx.regular_stream() << std::endl; + ast_smt_pp pp(ctx.m()); + pp.set_logic(ctx.get_logic().str().c_str()); + pp.display_smt2(ctx.regular_stream(), to_expr(interps[i])); + ctx.regular_stream() << std::endl; #endif - } + } - s.cleanup(); + s.cleanup(); - // verify, for the paranoid... - if(check || interp_params(m_params).check()){ - std::ostringstream err; - ast_manager &_m = ctx.m(); + // verify, for the paranoid... + if(check || interp_params(m_params).check()){ + std::ostringstream err; + ast_manager &_m = ctx.m(); - // need a solver -- make one here FIXME is this right? - bool proofs_enabled, models_enabled, unsat_core_enabled; - params_ref p; - ctx.params().get_solver_params(_m, p, proofs_enabled, models_enabled, unsat_core_enabled); - scoped_ptr sp = (ctx.get_solver_factory())(_m, p, false, true, false, ctx.get_logic()); + // need a solver -- make one here FIXME is this right? + bool proofs_enabled, models_enabled, unsat_core_enabled; + params_ref p; + ctx.params().get_solver_params(_m, p, proofs_enabled, models_enabled, unsat_core_enabled); + scoped_ptr sp = (ctx.get_solver_factory())(_m, p, false, true, false, ctx.get_logic()); - if(iz3check(_m,sp.get(),err,cnsts,t,interps)) - ctx.regular_stream() << "correct\n"; - else - ctx.regular_stream() << "incorrect: " << err.str().c_str() << "\n"; - } + if(iz3check(_m,sp.get(),err,cnsts,t,interps)) + ctx.regular_stream() << "correct\n"; + else + ctx.regular_stream() << "incorrect: " << err.str().c_str() << "\n"; + } - for(unsigned i = 0; i < interps.size(); i++){ - ctx.m().dec_ref(interps[i]); - } + for(unsigned i = 0; i < interps.size(); i++){ + ctx.m().dec_ref(interps[i]); + } - interp_params itp_params(m_params); - if(itp_params.profile()) - profiling::print(ctx.regular_stream()); + interp_params itp_params(m_params); + if(itp_params.profile()) + profiling::print(ctx.regular_stream()); } static void check_can_interpolate(cmd_context & ctx){ - if (!ctx.produce_interpolants()) - throw cmd_exception("interpolation is not enabled, use command (set-option :produce-interpolants true)"); + if (!ctx.produce_interpolants()) + throw cmd_exception("interpolation is not enabled, use command (set-option :produce-interpolants true)"); } static void get_interpolant_and_maybe_check(cmd_context & ctx, expr * t, params_ref &m_params, bool check) { - check_can_interpolate(ctx); + check_can_interpolate(ctx); - // get the proof, if there is one + // get the proof, if there is one - if (!ctx.has_manager() || - ctx.cs_state() != cmd_context::css_unsat) - throw cmd_exception("proof is not available"); - expr_ref pr(ctx.m()); - pr = ctx.get_check_sat_result()->get_proof(); - if (pr == 0) - throw cmd_exception("proof is not available"); + if (!ctx.has_manager() || + ctx.cs_state() != cmd_context::css_unsat) + throw cmd_exception("proof is not available"); + expr_ref pr(ctx.m()); + pr = ctx.get_check_sat_result()->get_proof(); + if (pr == 0) + throw cmd_exception("proof is not available"); - // get the assertions from the context + // get the assertions from the context - ptr_vector::const_iterator it = ctx.begin_assertions(); - ptr_vector::const_iterator end = ctx.end_assertions(); - ptr_vector cnsts((unsigned)(end - it)); - for (int i = 0; it != end; ++it, ++i) - cnsts[i] = *it; + ptr_vector::const_iterator it = ctx.begin_assertions(); + ptr_vector::const_iterator end = ctx.end_assertions(); + ptr_vector cnsts((unsigned)(end - it)); + for (int i = 0; it != end; ++it, ++i) + cnsts[i] = *it; - // compute an interpolant + // compute an interpolant - ptr_vector interps; + ptr_vector interps; - try { - iz3interpolate(ctx.m(),pr.get(),cnsts,t,interps,0); - } - catch (iz3_bad_tree &) { - throw cmd_exception("interpolation pattern contains non-asserted formula"); - } - catch (iz3_incompleteness &) { - throw cmd_exception("incompleteness in interpolator"); - } + try { + iz3interpolate(ctx.m(),pr.get(),cnsts,t,interps,0); + } + catch (iz3_bad_tree &) { + throw cmd_exception("interpolation pattern contains non-asserted formula"); + } + catch (iz3_incompleteness &) { + throw cmd_exception("incompleteness in interpolator"); + } - show_interpolant_and_maybe_check(ctx, cnsts, t, interps, m_params, check); + show_interpolant_and_maybe_check(ctx, cnsts, t, interps, m_params, check); } static void get_interpolant(cmd_context & ctx, expr * t, params_ref &m_params) { - get_interpolant_and_maybe_check(ctx,t,m_params,false); + get_interpolant_and_maybe_check(ctx,t,m_params,false); } #if 0 static void get_and_check_interpolant(cmd_context & ctx, params_ref &m_params, expr * t) { - get_interpolant_and_maybe_check(ctx,t,m_params,true); + get_interpolant_and_maybe_check(ctx,t,m_params,true); } #endif static void compute_interpolant_and_maybe_check(cmd_context & ctx, expr * t, params_ref &m_params, bool check){ - // create a fresh solver suitable for interpolation - bool proofs_enabled, models_enabled, unsat_core_enabled; - params_ref p; - ast_manager &_m = ctx.m(); - // TODO: the following is a HACK to enable proofs in the old smt solver - // When we stop using that solver, this hack can be removed - scoped_proof_mode spm(_m,PGM_FINE); - ctx.params().get_solver_params(_m, p, proofs_enabled, models_enabled, unsat_core_enabled); - p.set_bool("proof", true); - scoped_ptr sp = (ctx.get_interpolating_solver_factory())(_m, p, true, models_enabled, false, ctx.get_logic()); + // create a fresh solver suitable for interpolation + bool proofs_enabled, models_enabled, unsat_core_enabled; + params_ref p; + ast_manager &_m = ctx.m(); + // TODO: the following is a HACK to enable proofs in the old smt solver + // When we stop using that solver, this hack can be removed + scoped_proof_mode spm(_m,PGM_FINE); + ctx.params().get_solver_params(_m, p, proofs_enabled, models_enabled, unsat_core_enabled); + p.set_bool("proof", true); + scoped_ptr sp = (ctx.get_interpolating_solver_factory())(_m, p, true, models_enabled, false, ctx.get_logic()); - ptr_vector cnsts; - ptr_vector interps; - model_ref m; + ptr_vector cnsts; + ptr_vector interps; + model_ref m; - // compute an interpolant + // compute an interpolant - lbool res; - try { - res = iz3interpolate(_m, *sp.get(), t, cnsts, interps, m, 0); - } - catch (iz3_incompleteness &) { - throw cmd_exception("incompleteness in interpolator"); - } + lbool res; + try { + res = iz3interpolate(_m, *sp.get(), t, cnsts, interps, m, 0); + } + catch (iz3_incompleteness &) { + throw cmd_exception("incompleteness in interpolator"); + } - switch(res){ - case l_false: - ctx.regular_stream() << "unsat\n"; - show_interpolant_and_maybe_check(ctx, cnsts, t, interps, m_params, check); - break; + switch(res){ + case l_false: + ctx.regular_stream() << "unsat\n"; + show_interpolant_and_maybe_check(ctx, cnsts, t, interps, m_params, check); + break; - case l_true: - ctx.regular_stream() << "sat\n"; - // TODO: how to return the model to the context, if it exists? - break; + case l_true: + ctx.regular_stream() << "sat\n"; + // TODO: how to return the model to the context, if it exists? + break; - case l_undef: - ctx.regular_stream() << "unknown\n"; - // TODO: how to return the model to the context, if it exists? - break; - } + case l_undef: + ctx.regular_stream() << "unknown\n"; + // TODO: how to return the model to the context, if it exists? + break; + } - for(unsigned i = 0; i < cnsts.size(); i++) - ctx.m().dec_ref(cnsts[i]); + for(unsigned i = 0; i < cnsts.size(); i++) + ctx.m().dec_ref(cnsts[i]); } static expr *make_tree(cmd_context & ctx, const ptr_vector &exprs){ - if(exprs.size() == 0) - throw cmd_exception("not enough arguments"); - expr *foo = exprs[0]; - for(unsigned i = 1; i < exprs.size(); i++){ - foo = ctx.m().mk_and(ctx.m().mk_interp(foo),exprs[i]); - } - return foo; + if(exprs.size() == 0) + throw cmd_exception("not enough arguments"); + expr *foo = exprs[0]; + for(unsigned i = 1; i < exprs.size(); i++){ + foo = ctx.m().mk_and(ctx.m().mk_interp(foo),exprs[i]); + } + return foo; } static void get_interpolant(cmd_context & ctx, const ptr_vector &exprs, params_ref &m_params) { - expr *foo = make_tree(ctx,exprs); - ctx.m().inc_ref(foo); - get_interpolant(ctx,foo,m_params); - ctx.m().dec_ref(foo); + expr *foo = make_tree(ctx,exprs); + ctx.m().inc_ref(foo); + get_interpolant(ctx,foo,m_params); + ctx.m().dec_ref(foo); } static void compute_interpolant(cmd_context & ctx, const ptr_vector &exprs, params_ref &m_params) { - expr *foo = make_tree(ctx, exprs); - ctx.m().inc_ref(foo); - compute_interpolant_and_maybe_check(ctx,foo,m_params,false); - ctx.m().dec_ref(foo); + expr *foo = make_tree(ctx, exprs); + ctx.m().inc_ref(foo); + compute_interpolant_and_maybe_check(ctx,foo,m_params,false); + ctx.m().dec_ref(foo); } @@ -249,11 +249,11 @@ public: } virtual void set_next_arg(cmd_context & ctx, expr * arg) { - m_targets.push_back(arg); + m_targets.push_back(arg); } virtual void execute(cmd_context & ctx) { - get_interpolant(ctx,m_targets,m_params); + get_interpolant(ctx,m_targets,m_params); } }; @@ -262,7 +262,7 @@ public: compute_interpolant_cmd(char const * name = "compute-interpolant"):get_interpolant_cmd(name) {} virtual void execute(cmd_context & ctx) { - compute_interpolant(ctx,m_targets,m_params); + compute_interpolant(ctx,m_targets,m_params); } }; diff --git a/src/cmd_context/interpolant_cmds.h b/src/cmd_context/interpolant_cmds.h index d7ceb5dc2..a7c127a75 100644 --- a/src/cmd_context/interpolant_cmds.h +++ b/src/cmd_context/interpolant_cmds.h @@ -1,20 +1,20 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - interpolant_cmds.h + interpolant_cmds.h -Abstract: - Commands for interpolation. + Abstract: + Commands for interpolation. -Author: + Author: - Leonardo (leonardo) 2011-12-23 + Leonardo (leonardo) 2011-12-23 -Notes: + Notes: ---*/ + --*/ #ifndef _INTERPOLANT_CMDS_H_ #define _INTERPOLANT_CMDS_H_ diff --git a/src/duality/duality.h b/src/duality/duality.h index 04527450c..cde703617 100755 --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2012 Microsoft Corporation + Copyright (c) 2012 Microsoft Corporation -Module Name: + Module Name: - duality.h + duality.h -Abstract: + Abstract: - main header for duality + main header for duality -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #pragma once @@ -29,106 +29,106 @@ using namespace stl_ext; namespace Duality { - struct implicant_solver; + struct implicant_solver; - /* Generic operations on Z3 formulas */ + /* Generic operations on Z3 formulas */ - struct Z3User { + struct Z3User { - context &ctx; + context &ctx; - typedef func_decl FuncDecl; - typedef expr Term; + typedef func_decl FuncDecl; + typedef expr Term; - Z3User(context &_ctx) : ctx(_ctx){} + Z3User(context &_ctx) : ctx(_ctx){} - const char *string_of_int(int n); + const char *string_of_int(int n); - Term conjoin(const std::vector &args); + Term conjoin(const std::vector &args); - Term sum(const std::vector &args); + Term sum(const std::vector &args); - Term CloneQuantifier(const Term &t, const Term &new_body); + Term CloneQuantifier(const Term &t, const Term &new_body); - Term SubstRec(hash_map &memo, const Term &t); + Term SubstRec(hash_map &memo, const Term &t); - Term SubstRec(hash_map &memo, hash_map &map, const Term &t); + Term SubstRec(hash_map &memo, hash_map &map, const Term &t); - void Strengthen(Term &x, const Term &y); + void Strengthen(Term &x, const Term &y); // return the func_del of an app if it is uninterpreted - bool get_relation(const Term &t, func_decl &R); + bool get_relation(const Term &t, func_decl &R); // return true if term is an individual variable // TODO: have to check that it is not a background symbol - bool is_variable(const Term &t); + bool is_variable(const Term &t); - FuncDecl SuffixFuncDecl(Term t, int n); + FuncDecl SuffixFuncDecl(Term t, int n); - Term SubstRecHide(hash_map &memo, const Term &t, int number); + Term SubstRecHide(hash_map &memo, const Term &t, int number); - void CollectConjuncts(const Term &f, std::vector &lits, bool pos = true); + void CollectConjuncts(const Term &f, std::vector &lits, bool pos = true); - void SortTerms(std::vector &terms); + void SortTerms(std::vector &terms); - Term SortSum(const Term &t); + Term SortSum(const Term &t); - void Summarize(const Term &t); + void Summarize(const Term &t); - int CountOperators(const Term &t); + int CountOperators(const Term &t); - Term SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val); + Term SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val); - Term CloneQuantAndSimp(const expr &t, const expr &body); + Term CloneQuantAndSimp(const expr &t, const expr &body); - Term RemoveRedundancy(const Term &t); + Term RemoveRedundancy(const Term &t); - Term IneqToEq(const Term &t); + Term IneqToEq(const Term &t); - bool IsLiteral(const expr &lit, expr &atom, expr &val); + bool IsLiteral(const expr &lit, expr &atom, expr &val); - expr Negate(const expr &f); + expr Negate(const expr &f); - expr SimplifyAndOr(const std::vector &args, bool is_and); + expr SimplifyAndOr(const std::vector &args, bool is_and); - expr ReallySimplifyAndOr(const std::vector &args, bool is_and); + expr ReallySimplifyAndOr(const std::vector &args, bool is_and); - int MaxIndex(hash_map &memo, const Term &t); + int MaxIndex(hash_map &memo, const Term &t); - bool IsClosedFormula(const Term &t); + bool IsClosedFormula(const Term &t); - Term AdjustQuantifiers(const Term &t); + Term AdjustQuantifiers(const Term &t); - FuncDecl RenumberPred(const FuncDecl &f, int n); + FuncDecl RenumberPred(const FuncDecl &f, int n); - FuncDecl NumberPred(const FuncDecl &f, int n); + FuncDecl NumberPred(const FuncDecl &f, int n); - Term ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming); + Term ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming); -protected: + protected: - void SummarizeRec(hash_set &memo, std::vector &lits, int &ops, const Term &t); - int CountOperatorsRec(hash_set &memo, const Term &t); - void RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo); - Term RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t); - Term SubstAtomTriv(const expr &foo, const expr &atom, const expr &val); - expr ReduceAndOr(const std::vector &args, bool is_and, std::vector &res); - expr FinishAndOr(const std::vector &args, bool is_and); - expr PullCommonFactors(std::vector &args, bool is_and); - Term IneqToEqRec(hash_map &memo, const Term &t); - Term CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall); - Term PushQuantifier(const expr &t, const expr &body, bool is_forall); - void CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate); - Term DeleteBoundRec(hash_map > &memo, int level, int num, const Term &t); - Term DeleteBound(int level, int num, const Term &t); + void SummarizeRec(hash_set &memo, std::vector &lits, int &ops, const Term &t); + int CountOperatorsRec(hash_set &memo, const Term &t); + void RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo); + Term RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t); + Term SubstAtomTriv(const expr &foo, const expr &atom, const expr &val); + expr ReduceAndOr(const std::vector &args, bool is_and, std::vector &res); + expr FinishAndOr(const std::vector &args, bool is_and); + expr PullCommonFactors(std::vector &args, bool is_and); + Term IneqToEqRec(hash_map &memo, const Term &t); + Term CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall); + Term PushQuantifier(const expr &t, const expr &body, bool is_forall); + void CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate); + Term DeleteBoundRec(hash_map > &memo, int level, int num, const Term &t); + Term DeleteBound(int level, int num, const Term &t); -}; + }; - /** This class represents a relation post-fixed point (RPFP) problem as + /** This class represents a relation post-fixed point (RPFP) problem as * a "problem graph". The graph consists of Nodes and hyper-edges. * * A node consists of @@ -172,1018 +172,1018 @@ protected: { public: - class Edge; - class Node; - bool HornClauses; + class Edge; + class Node; + bool HornClauses; - /** Interface class for interpolating solver. */ + /** Interface class for interpolating solver. */ - class LogicSolver { - public: + class LogicSolver { + public: - context *ctx; /** Z3 context for formulas */ - solver *slvr; /** Z3 solver */ - bool need_goals; /** Can the solver use the goal tree to optimize interpolants? */ - solver aux_solver; /** For temporary use -- don't leave assertions here. */ + context *ctx; /** Z3 context for formulas */ + solver *slvr; /** Z3 solver */ + bool need_goals; /** Can the solver use the goal tree to optimize interpolants? */ + solver aux_solver; /** For temporary use -- don't leave assertions here. */ - /** Tree interpolation. This method assumes the formulas in TermTree - "assumptions" are currently asserted in the solver. The return - value indicates whether the assertions are satisfiable. In the - UNSAT case, a tree interpolant is returned in "interpolants". - In the SAT case, a model is returned. - */ + /** Tree interpolation. This method assumes the formulas in TermTree + "assumptions" are currently asserted in the solver. The return + value indicates whether the assertions are satisfiable. In the + UNSAT case, a tree interpolant is returned in "interpolants". + In the SAT case, a model is returned. + */ - virtual - lbool interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals = 0, - bool weak = false - ) = 0; + virtual + lbool interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals = 0, + bool weak = false + ) = 0; - /** Declare a constant in the background theory. */ - virtual void declare_constant(const func_decl &f) = 0; + /** Declare a constant in the background theory. */ + virtual void declare_constant(const func_decl &f) = 0; - /** Is this a background constant? */ - virtual bool is_constant(const func_decl &f) = 0; + /** Is this a background constant? */ + virtual bool is_constant(const func_decl &f) = 0; - /** Get the constants in the background vocabulary */ - virtual hash_set &get_constants() = 0; + /** Get the constants in the background vocabulary */ + virtual hash_set &get_constants() = 0; - /** Assert a background axiom. */ - virtual void assert_axiom(const expr &axiom) = 0; + /** Assert a background axiom. */ + virtual void assert_axiom(const expr &axiom) = 0; - /** Get the background axioms. */ - virtual const std::vector &get_axioms() = 0; + /** Get the background axioms. */ + virtual const std::vector &get_axioms() = 0; - /** Return a string describing performance. */ - virtual std::string profile() = 0; + /** Return a string describing performance. */ + virtual std::string profile() = 0; - virtual void write_interpolation_problem(const std::string &file_name, - const std::vector &assumptions, - const std::vector &theory - ){} + virtual void write_interpolation_problem(const std::string &file_name, + const std::vector &assumptions, + const std::vector &theory + ){} - /** Cancel, throw Canceled object if possible. */ - virtual void cancel(){ } + /** Cancel, throw Canceled object if possible. */ + virtual void cancel(){ } - /* Note: aux solver uses extensional array theory, since it - needs to be able to produce counter-models for - interpolants the have array equalities in them. - */ - LogicSolver(context &c) : aux_solver(c,true){} + /* Note: aux solver uses extensional array theory, since it + needs to be able to produce counter-models for + interpolants the have array equalities in them. + */ + LogicSolver(context &c) : aux_solver(c,true){} - virtual ~LogicSolver(){} - }; + virtual ~LogicSolver(){} + }; - /** This solver uses iZ3. */ - class iZ3LogicSolver : public LogicSolver { - public: - interpolating_context *ictx; /** iZ3 context for formulas */ - interpolating_solver *islvr; /** iZ3 solver */ + /** This solver uses iZ3. */ + class iZ3LogicSolver : public LogicSolver { + public: + interpolating_context *ictx; /** iZ3 context for formulas */ + interpolating_solver *islvr; /** iZ3 solver */ - lbool interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals = 0, - bool weak = false) - { - literals _labels; - islvr->SetWeakInterpolants(weak); - return islvr->interpolate_tree(assumptions,interpolants,_model,_labels,true); - } + lbool interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals = 0, + bool weak = false) + { + literals _labels; + islvr->SetWeakInterpolants(weak); + return islvr->interpolate_tree(assumptions,interpolants,_model,_labels,true); + } - void assert_axiom(const expr &axiom){ + void assert_axiom(const expr &axiom){ #if 1 - // HACK: large "distict" predicates can kill the legacy SMT solver. - // encode them with a UIF - if(axiom.is_app() && axiom.decl().get_decl_kind() == Distinct) - if(axiom.num_args() > 10){ - sort s = axiom.arg(0).get_sort(); - std::vector sv; - sv.push_back(s); - int nargs = axiom.num_args(); - std::vector args(nargs); - func_decl f = ctx->fresh_func_decl("@distinct",sv,ctx->int_sort()); - for(int i = 0; i < nargs; i++){ - expr a = axiom.arg(i); - expr new_cnstr = f(a) == ctx->int_val(i); - args[i] = new_cnstr; - } - expr cnstr = ctx->make(And,args); - islvr->AssertInterpolationAxiom(cnstr); - return; - } + // HACK: large "distict" predicates can kill the legacy SMT solver. + // encode them with a UIF + if(axiom.is_app() && axiom.decl().get_decl_kind() == Distinct) + if(axiom.num_args() > 10){ + sort s = axiom.arg(0).get_sort(); + std::vector sv; + sv.push_back(s); + int nargs = axiom.num_args(); + std::vector args(nargs); + func_decl f = ctx->fresh_func_decl("@distinct",sv,ctx->int_sort()); + for(int i = 0; i < nargs; i++){ + expr a = axiom.arg(i); + expr new_cnstr = f(a) == ctx->int_val(i); + args[i] = new_cnstr; + } + expr cnstr = ctx->make(And,args); + islvr->AssertInterpolationAxiom(cnstr); + return; + } #endif - islvr->AssertInterpolationAxiom(axiom); - } + islvr->AssertInterpolationAxiom(axiom); + } - const std::vector &get_axioms() { - return islvr->GetInterpolationAxioms(); - } + const std::vector &get_axioms() { + return islvr->GetInterpolationAxioms(); + } - std::string profile(){ - return islvr->profile(); - } + std::string profile(){ + return islvr->profile(); + } #if 0 - iZ3LogicSolver(config &_config){ - ctx = ictx = new interpolating_context(_config); - slvr = islvr = new interpolating_solver(*ictx); - need_goals = false; - islvr->SetWeakInterpolants(true); - } + iZ3LogicSolver(config &_config){ + ctx = ictx = new interpolating_context(_config); + slvr = islvr = new interpolating_solver(*ictx); + need_goals = false; + islvr->SetWeakInterpolants(true); + } #endif - iZ3LogicSolver(context &c, bool models = true) : LogicSolver(c) { - ctx = ictx = &c; - slvr = islvr = new interpolating_solver(*ictx, models); - need_goals = false; - islvr->SetWeakInterpolants(true); - } + iZ3LogicSolver(context &c, bool models = true) : LogicSolver(c) { + ctx = ictx = &c; + slvr = islvr = new interpolating_solver(*ictx, models); + need_goals = false; + islvr->SetWeakInterpolants(true); + } - void write_interpolation_problem(const std::string &file_name, - const std::vector &assumptions, - const std::vector &theory - ){ + void write_interpolation_problem(const std::string &file_name, + const std::vector &assumptions, + const std::vector &theory + ){ #if 0 - islvr->write_interpolation_problem(file_name,assumptions,theory); + islvr->write_interpolation_problem(file_name,assumptions,theory); #endif - } + } - void cancel(){islvr->cancel();} + void cancel(){islvr->cancel();} - /** Declare a constant in the background theory. */ - virtual void declare_constant(const func_decl &f){ - bckg.insert(f); - } + /** Declare a constant in the background theory. */ + virtual void declare_constant(const func_decl &f){ + bckg.insert(f); + } - /** Is this a background constant? */ - virtual bool is_constant(const func_decl &f){ - return bckg.find(f) != bckg.end(); - } + /** Is this a background constant? */ + virtual bool is_constant(const func_decl &f){ + return bckg.find(f) != bckg.end(); + } - /** Get the constants in the background vocabulary */ - virtual hash_set &get_constants(){ - return bckg; - } + /** Get the constants in the background vocabulary */ + virtual hash_set &get_constants(){ + return bckg; + } - ~iZ3LogicSolver(){ - // delete ictx; - delete islvr; - } - private: - hash_set bckg; + ~iZ3LogicSolver(){ + // delete ictx; + delete islvr; + } + private: + hash_set bckg; - }; + }; #if 0 - /** Create a logic solver from a Z3 configuration. */ - static iZ3LogicSolver *CreateLogicSolver(config &_config){ - return new iZ3LogicSolver(_config); - } + /** Create a logic solver from a Z3 configuration. */ + static iZ3LogicSolver *CreateLogicSolver(config &_config){ + return new iZ3LogicSolver(_config); + } #endif - /** Create a logic solver from a low-level Z3 context. - Only use this if you know what you're doing. */ - static iZ3LogicSolver *CreateLogicSolver(context c){ - return new iZ3LogicSolver(c); - } + /** Create a logic solver from a low-level Z3 context. + Only use this if you know what you're doing. */ + static iZ3LogicSolver *CreateLogicSolver(context c){ + return new iZ3LogicSolver(c); + } - LogicSolver *ls; + LogicSolver *ls; protected: - int nodeCount; - int edgeCount; + int nodeCount; + int edgeCount; - class stack_entry - { - public: - std::list edges; - std::list nodes; - std::list > constraints; - }; + class stack_entry + { + public: + std::list edges; + std::list nodes; + std::list > constraints; + }; public: - model dualModel; + model dualModel; protected: - literals dualLabels; - std::list stack; - std::vector axioms; // only saved here for printing purposes - solver &aux_solver; - hash_set *proof_core; + literals dualLabels; + std::list stack; + std::vector axioms; // only saved here for printing purposes + solver &aux_solver; + hash_set *proof_core; public: - /** Construct an RPFP graph with a given interpolating prover context. It is allowed to - have multiple RPFP's use the same context, but you should never have teo RPFP's - with the same conext asserting nodes or edges at the same time. Note, if you create - axioms in one RPFP, them create a second RPFP with the same context, the second will - inherit the axioms. - */ + /** Construct an RPFP graph with a given interpolating prover context. It is allowed to + have multiple RPFP's use the same context, but you should never have teo RPFP's + with the same conext asserting nodes or edges at the same time. Note, if you create + axioms in one RPFP, them create a second RPFP with the same context, the second will + inherit the axioms. + */ RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx)), dualModel(*(_ls->ctx)), aux_solver(_ls->aux_solver) - { - ls = _ls; - nodeCount = 0; - edgeCount = 0; - stack.push_back(stack_entry()); - HornClauses = false; - proof_core = 0; - } + { + ls = _ls; + nodeCount = 0; + edgeCount = 0; + stack.push_back(stack_entry()); + HornClauses = false; + proof_core = 0; + } - virtual ~RPFP(); + virtual ~RPFP(); - /** Symbolic representation of a relational transformer */ - class Transformer - { - public: - std::vector RelParams; - std::vector IndParams; - Term Formula; - RPFP *owner; - hash_map labels; + /** Symbolic representation of a relational transformer */ + class Transformer + { + public: + std::vector RelParams; + std::vector IndParams; + Term Formula; + RPFP *owner; + hash_map labels; - Transformer *Clone() - { - return new Transformer(*this); - } + Transformer *Clone() + { + return new Transformer(*this); + } - void SetEmpty(){ - Formula = owner->ctx.bool_val(false); - } + void SetEmpty(){ + Formula = owner->ctx.bool_val(false); + } - void SetFull(){ - Formula = owner->ctx.bool_val(true); - } + void SetFull(){ + Formula = owner->ctx.bool_val(true); + } - bool IsEmpty(){ - return eq(Formula,owner->ctx.bool_val(false)); - } + bool IsEmpty(){ + return eq(Formula,owner->ctx.bool_val(false)); + } - bool IsFull(){ - return eq(Formula,owner->ctx.bool_val(true)); - } + bool IsFull(){ + return eq(Formula,owner->ctx.bool_val(true)); + } - void UnionWith(const Transformer &other){ - Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); - Formula = Formula || t; - } + void UnionWith(const Transformer &other){ + Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); + Formula = Formula || t; + } - void IntersectWith(const Transformer &other){ - Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); - Formula = Formula && t; - } + void IntersectWith(const Transformer &other){ + Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); + Formula = Formula && t; + } - bool SubsetEq(const Transformer &other){ - Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); - expr test = Formula && !t; - owner->aux_solver.push(); - owner->aux_solver.add(test); - check_result res = owner->aux_solver.check(); - owner->aux_solver.pop(1); - return res == unsat; - } + bool SubsetEq(const Transformer &other){ + Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula); + expr test = Formula && !t; + owner->aux_solver.push(); + owner->aux_solver.add(test); + check_result res = owner->aux_solver.check(); + owner->aux_solver.pop(1); + return res == unsat; + } - void Complement(){ - Formula = !Formula; - } + void Complement(){ + Formula = !Formula; + } - void Simplify(){ - Formula = Formula.simplify(); - } + void Simplify(){ + Formula = Formula.simplify(); + } Transformer(const std::vector &_RelParams, const std::vector &_IndParams, const Term &_Formula, RPFP *_owner) - : RelParams(_RelParams), IndParams(_IndParams), Formula(_Formula) {owner = _owner;} - }; + : RelParams(_RelParams), IndParams(_IndParams), Formula(_Formula) {owner = _owner;} + }; - /** Create a symbolic transformer. */ - Transformer CreateTransformer(const std::vector &_RelParams, const std::vector &_IndParams, const Term &_Formula) - { - // var ops = new Util.ContextOps(ctx); - // var foo = ops.simplify_lhs(_Formula); - // t.Formula = foo.Item1; - // t.labels = foo.Item2; - return Transformer(_RelParams,_IndParams,_Formula,this); - } + /** Create a symbolic transformer. */ + Transformer CreateTransformer(const std::vector &_RelParams, const std::vector &_IndParams, const Term &_Formula) + { + // var ops = new Util.ContextOps(ctx); + // var foo = ops.simplify_lhs(_Formula); + // t.Formula = foo.Item1; + // t.labels = foo.Item2; + return Transformer(_RelParams,_IndParams,_Formula,this); + } - /** Create a relation (nullary relational transformer) */ - Transformer CreateRelation(const std::vector &_IndParams, const Term &_Formula) - { - return CreateTransformer(std::vector(), _IndParams, _Formula); - } + /** Create a relation (nullary relational transformer) */ + Transformer CreateRelation(const std::vector &_IndParams, const Term &_Formula) + { + return CreateTransformer(std::vector(), _IndParams, _Formula); + } - /** A node in the RPFP graph */ - class Node - { - public: - FuncDecl Name; - Transformer Annotation; - Transformer Bound; - Transformer Underapprox; - RPFP *owner; - int number; - Edge *Outgoing; - std::vector Incoming; - Term dual; - Node *map; - unsigned recursion_bound; + /** A node in the RPFP graph */ + class Node + { + public: + FuncDecl Name; + Transformer Annotation; + Transformer Bound; + Transformer Underapprox; + RPFP *owner; + int number; + Edge *Outgoing; + std::vector Incoming; + Term dual; + Node *map; + unsigned recursion_bound; - Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number) - : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;} - }; + Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number) + : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;} + }; - /** Create a node in the graph. The input is a term R(v_1...v_n) - * where R is an arbitrary relational symbol and v_1...v_n are - * arbitary distinct variables. The names are only of mnemonic value, - * however, the number and type of arguments determine the type - * of the relation at this node. */ + /** Create a node in the graph. The input is a term R(v_1...v_n) + * where R is an arbitrary relational symbol and v_1...v_n are + * arbitary distinct variables. The names are only of mnemonic value, + * however, the number and type of arguments determine the type + * of the relation at this node. */ - Node *CreateNode(const Term &t) - { - std::vector _IndParams; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - _IndParams.push_back(t.arg(i)); - Node *n = new Node(t.decl(), - CreateRelation(_IndParams,ctx.bool_val(true)), - CreateRelation(_IndParams,ctx.bool_val(true)), - CreateRelation(_IndParams,ctx.bool_val(false)), - expr(ctx), this, ++nodeCount - ); - nodes.push_back(n); - return n; - } + Node *CreateNode(const Term &t) + { + std::vector _IndParams; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + _IndParams.push_back(t.arg(i)); + Node *n = new Node(t.decl(), + CreateRelation(_IndParams,ctx.bool_val(true)), + CreateRelation(_IndParams,ctx.bool_val(true)), + CreateRelation(_IndParams,ctx.bool_val(false)), + expr(ctx), this, ++nodeCount + ); + nodes.push_back(n); + return n; + } - /** Clone a node (can be from another graph). */ + /** Clone a node (can be from another graph). */ - Node *CloneNode(Node *old) - { - Node *n = new Node(old->Name, - old->Annotation, - old->Bound, - old->Underapprox, - expr(ctx), - this, - ++nodeCount - ); - nodes.push_back(n); - n->map = old; - return n; - } + Node *CloneNode(Node *old) + { + Node *n = new Node(old->Name, + old->Annotation, + old->Bound, + old->Underapprox, + expr(ctx), + this, + ++nodeCount + ); + nodes.push_back(n); + n->map = old; + return n; + } - /** Delete a node. You can only do this if not connected to any edges.*/ - void DeleteNode(Node *node){ - if(node->Outgoing || !node->Incoming.empty()) - throw "cannot delete RPFP node"; - for(std::vector::iterator it = nodes.end(), en = nodes.begin(); it != en;){ - if(*(--it) == node){ - nodes.erase(it); - break; - } - } - delete node; - } + /** Delete a node. You can only do this if not connected to any edges.*/ + void DeleteNode(Node *node){ + if(node->Outgoing || !node->Incoming.empty()) + throw "cannot delete RPFP node"; + for(std::vector::iterator it = nodes.end(), en = nodes.begin(); it != en;){ + if(*(--it) == node){ + nodes.erase(it); + break; + } + } + delete node; + } - /** This class represents a hyper-edge in the RPFP graph */ + /** This class represents a hyper-edge in the RPFP graph */ - class Edge - { - public: - Transformer F; - Node *Parent; - std::vector Children; - RPFP *owner; - int number; - // these should be internal... - Term dual; - hash_map relMap; - hash_map varMap; - Edge *map; - Term labeled; - std::vector constraints; + class Edge + { + public: + Transformer F; + Node *Parent; + std::vector Children; + RPFP *owner; + int number; + // these should be internal... + Term dual; + hash_map relMap; + hash_map varMap; + Edge *map; + Term labeled; + std::vector constraints; - Edge(Node *_Parent, const Transformer &_F, const std::vector &_Children, RPFP *_owner, int _number) - : F(_F), Parent(_Parent), Children(_Children), dual(expr(_owner->ctx)) { - owner = _owner; - number = _number; - } - }; + Edge(Node *_Parent, const Transformer &_F, const std::vector &_Children, RPFP *_owner, int _number) + : F(_F), Parent(_Parent), Children(_Children), dual(expr(_owner->ctx)) { + owner = _owner; + number = _number; + } + }; - /** Create a hyper-edge. */ - Edge *CreateEdge(Node *_Parent, const Transformer &_F, const std::vector &_Children) - { - Edge *e = new Edge(_Parent,_F,_Children,this,++edgeCount); - _Parent->Outgoing = e; - for(unsigned i = 0; i < _Children.size(); i++) - _Children[i]->Incoming.push_back(e); - edges.push_back(e); - return e; - } + /** Create a hyper-edge. */ + Edge *CreateEdge(Node *_Parent, const Transformer &_F, const std::vector &_Children) + { + Edge *e = new Edge(_Parent,_F,_Children,this,++edgeCount); + _Parent->Outgoing = e; + for(unsigned i = 0; i < _Children.size(); i++) + _Children[i]->Incoming.push_back(e); + edges.push_back(e); + return e; + } - /** Delete a hyper-edge and unlink it from any nodes. */ - void DeleteEdge(Edge *edge){ - if(edge->Parent) - edge->Parent->Outgoing = 0; - for(unsigned int i = 0; i < edge->Children.size(); i++){ - std::vector &ic = edge->Children[i]->Incoming; - for(std::vector::iterator it = ic.begin(), en = ic.end(); it != en; ++it){ - if(*it == edge){ - ic.erase(it); - break; - } - } - } - for(std::vector::iterator it = edges.end(), en = edges.begin(); it != en;){ - if(*(--it) == edge){ - edges.erase(it); - break; - } - } - delete edge; - } + /** Delete a hyper-edge and unlink it from any nodes. */ + void DeleteEdge(Edge *edge){ + if(edge->Parent) + edge->Parent->Outgoing = 0; + for(unsigned int i = 0; i < edge->Children.size(); i++){ + std::vector &ic = edge->Children[i]->Incoming; + for(std::vector::iterator it = ic.begin(), en = ic.end(); it != en; ++it){ + if(*it == edge){ + ic.erase(it); + break; + } + } + } + for(std::vector::iterator it = edges.end(), en = edges.begin(); it != en;){ + if(*(--it) == edge){ + edges.erase(it); + break; + } + } + delete edge; + } - /** Create an edge that lower-bounds its parent. */ - Edge *CreateLowerBoundEdge(Node *_Parent) - { - return CreateEdge(_Parent, _Parent->Annotation, std::vector()); - } + /** Create an edge that lower-bounds its parent. */ + Edge *CreateLowerBoundEdge(Node *_Parent) + { + return CreateEdge(_Parent, _Parent->Annotation, std::vector()); + } - /** For incremental solving, asserts the constraint associated - * with this edge in the SMT context. If this edge is removed, - * you must pop the context accordingly. The second argument is - * the number of pushes we are inside. */ + /** For incremental solving, asserts the constraint associated + * with this edge in the SMT context. If this edge is removed, + * you must pop the context accordingly. The second argument is + * the number of pushes we are inside. */ - virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false); + virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false); - /* Constrain an edge by the annotation of one of its children. */ + /* Constrain an edge by the annotation of one of its children. */ - void ConstrainParent(Edge *parent, Node *child); + void ConstrainParent(Edge *parent, Node *child); - /** For incremental solving, asserts the negation of the upper bound associated - * with a node. - * */ + /** For incremental solving, asserts the negation of the upper bound associated + * with a node. + * */ - void AssertNode(Node *n); + void AssertNode(Node *n); - /** Assert a constraint on an edge in the SMT context. - */ - void ConstrainEdge(Edge *e, const Term &t); + /** Assert a constraint on an edge in the SMT context. + */ + void ConstrainEdge(Edge *e, const Term &t); - /** Fix the truth values of atomic propositions in the given - edge to their values in the current assignment. */ - void FixCurrentState(Edge *root); + /** Fix the truth values of atomic propositions in the given + edge to their values in the current assignment. */ + void FixCurrentState(Edge *root); - void FixCurrentStateFull(Edge *edge, const expr &extra); + void FixCurrentStateFull(Edge *edge, const expr &extra); - void FixCurrentStateFull(Edge *edge, const std::vector &assumps, const hash_map &renaming); + void FixCurrentStateFull(Edge *edge, const std::vector &assumps, const hash_map &renaming); - /** Declare a constant in the background theory. */ + /** Declare a constant in the background theory. */ - void DeclareConstant(const FuncDecl &f); + void DeclareConstant(const FuncDecl &f); - /** Assert a background axiom. Background axioms can be used to provide the - * theory of auxilliary functions or relations. All symbols appearing in - * background axioms are considered global, and may appear in both transformer - * and relational solutions. Semantically, a solution to the RPFP gives - * an interpretation of the unknown relations for each interpretation of the - * auxilliary symbols that is consistent with the axioms. Axioms should be - * asserted before any calls to Push. They cannot be de-asserted by Pop. */ + /** Assert a background axiom. Background axioms can be used to provide the + * theory of auxilliary functions or relations. All symbols appearing in + * background axioms are considered global, and may appear in both transformer + * and relational solutions. Semantically, a solution to the RPFP gives + * an interpretation of the unknown relations for each interpretation of the + * auxilliary symbols that is consistent with the axioms. Axioms should be + * asserted before any calls to Push. They cannot be de-asserted by Pop. */ - void AssertAxiom(const Term &t); + void AssertAxiom(const Term &t); #if 0 - /** Do not call this. */ + /** Do not call this. */ - void RemoveAxiom(const Term &t); + void RemoveAxiom(const Term &t); #endif - /** Solve an RPFP graph. This means either strengthen the annotation - * so that the bound at the given root node is satisfied, or - * show that this cannot be done by giving a dual solution - * (i.e., a counterexample). - * - * In the current implementation, this only works for graphs that - * are: - * - tree-like - * - * - closed. - * - * In a tree-like graph, every nod has out most one incoming and one out-going edge, - * and there are no cycles. In a closed graph, every node has exactly one out-going - * edge. This means that the leaves of the tree are all hyper-edges with no - * children. Such an edge represents a relation (nullary transformer) and thus - * a lower bound on its parent. The parameter root must be the root of this tree. - * - * If Solve returns LBool.False, this indicates success. The annotation of the tree - * has been updated to satisfy the upper bound at the root. - * - * If Solve returns LBool.True, this indicates a counterexample. For each edge, - * you can then call Eval to determine the values of symbols in the transformer formula. - * You can also call Empty on a node to determine if its value in the counterexample - * is the empty relation. - * - * \param root The root of the tree - * \param persist Number of context pops through which result should persist - * - * - */ + /** Solve an RPFP graph. This means either strengthen the annotation + * so that the bound at the given root node is satisfied, or + * show that this cannot be done by giving a dual solution + * (i.e., a counterexample). + * + * In the current implementation, this only works for graphs that + * are: + * - tree-like + * + * - closed. + * + * In a tree-like graph, every nod has out most one incoming and one out-going edge, + * and there are no cycles. In a closed graph, every node has exactly one out-going + * edge. This means that the leaves of the tree are all hyper-edges with no + * children. Such an edge represents a relation (nullary transformer) and thus + * a lower bound on its parent. The parameter root must be the root of this tree. + * + * If Solve returns LBool.False, this indicates success. The annotation of the tree + * has been updated to satisfy the upper bound at the root. + * + * If Solve returns LBool.True, this indicates a counterexample. For each edge, + * you can then call Eval to determine the values of symbols in the transformer formula. + * You can also call Empty on a node to determine if its value in the counterexample + * is the empty relation. + * + * \param root The root of the tree + * \param persist Number of context pops through which result should persist + * + * + */ - lbool Solve(Node *root, int persist); + lbool Solve(Node *root, int persist); - /** Same as Solve, but annotates only a single node. */ + /** Same as Solve, but annotates only a single node. */ - lbool SolveSingleNode(Node *root, Node *node); + lbool SolveSingleNode(Node *root, Node *node); - /** Get the constraint tree (but don't solve it) */ + /** Get the constraint tree (but don't solve it) */ - TermTree *GetConstraintTree(Node *root, Node *skip_descendant = 0); + TermTree *GetConstraintTree(Node *root, Node *skip_descendant = 0); - /** Dispose of the dual model (counterexample) if there is one. */ + /** Dispose of the dual model (counterexample) if there is one. */ - void DisposeDualModel(); + void DisposeDualModel(); - /** Check satisfiability of asserted edges and nodes. Same functionality as - * Solve, except no primal solution (interpolant) is generated in the unsat case. */ + /** Check satisfiability of asserted edges and nodes. Same functionality as + * Solve, except no primal solution (interpolant) is generated in the unsat case. */ - check_result Check(Node *root, std::vector underapproxes = std::vector(), - std::vector *underapprox_core = 0); + check_result Check(Node *root, std::vector underapproxes = std::vector(), + std::vector *underapprox_core = 0); - /** Update the model, attempting to make the propositional literals in assumps true. If possible, - return sat, else return unsat and keep the old model. */ + /** Update the model, attempting to make the propositional literals in assumps true. If possible, + return sat, else return unsat and keep the old model. */ - check_result CheckUpdateModel(Node *root, std::vector assumps); + check_result CheckUpdateModel(Node *root, std::vector assumps); - /** Determines the value in the counterexample of a symbol occuring in the transformer formula of - * a given edge. */ + /** Determines the value in the counterexample of a symbol occuring in the transformer formula of + * a given edge. */ - Term Eval(Edge *e, Term t); + Term Eval(Edge *e, Term t); - /** Return the fact derived at node p in a counterexample. */ + /** Return the fact derived at node p in a counterexample. */ - Term EvalNode(Node *p); + Term EvalNode(Node *p); - /** Returns true if the given node is empty in the primal solution. For proecudure summaries, - this means that the procedure is not called in the current counter-model. */ + /** Returns true if the given node is empty in the primal solution. For proecudure summaries, + this means that the procedure is not called in the current counter-model. */ - bool Empty(Node *p); + bool Empty(Node *p); - /** Compute an underapproximation of every node in a tree rooted at "root", - based on a previously computed counterexample. */ + /** Compute an underapproximation of every node in a tree rooted at "root", + based on a previously computed counterexample. */ - Term ComputeUnderapprox(Node *root, int persist); + Term ComputeUnderapprox(Node *root, int persist); - /** Try to strengthen the annotation of a node by removing disjuncts. */ - void Generalize(Node *root, Node *node); + /** Try to strengthen the annotation of a node by removing disjuncts. */ + void Generalize(Node *root, Node *node); - /** Compute disjunctive interpolant for node by case splitting */ - void InterpolateByCases(Node *root, Node *node); + /** Compute disjunctive interpolant for node by case splitting */ + void InterpolateByCases(Node *root, Node *node); - /** Push a scope. Assertions made after Push can be undone by Pop. */ + /** Push a scope. Assertions made after Push can be undone by Pop. */ - void Push(); + void Push(); - /** Exception thrown when bad clause is encountered */ + /** Exception thrown when bad clause is encountered */ - struct bad_clause { - std::string msg; - int i; - bad_clause(const std::string &_msg, int _i){ - msg = _msg; - i = _i; - } - }; + struct bad_clause { + std::string msg; + int i; + bad_clause(const std::string &_msg, int _i){ + msg = _msg; + i = _i; + } + }; - struct parse_error { - std::string msg; - parse_error(const std::string &_msg){ - msg = _msg; - } - }; + struct parse_error { + std::string msg; + parse_error(const std::string &_msg){ + msg = _msg; + } + }; - struct file_not_found { - }; + struct file_not_found { + }; - struct bad_format { - }; + struct bad_format { + }; - // thrown on internal error - struct Bad { - }; + // thrown on internal error + struct Bad { + }; - // thrown on more serious internal error - struct ReallyBad { - }; + // thrown on more serious internal error + struct ReallyBad { + }; - /** Pop a scope (see Push). Note, you cannot pop axioms. */ + /** Pop a scope (see Push). Note, you cannot pop axioms. */ - void Pop(int num_scopes); + void Pop(int num_scopes); - /** Erase the proof by performing a Pop, Push and re-assertion of - all the popped constraints */ - void PopPush(); + /** Erase the proof by performing a Pop, Push and re-assertion of + all the popped constraints */ + void PopPush(); - /** Return true if the given edge is used in the proof of unsat. - Can be called only after Solve or Check returns an unsat result. */ + /** Return true if the given edge is used in the proof of unsat. + Can be called only after Solve or Check returns an unsat result. */ - bool EdgeUsedInProof(Edge *edge); + bool EdgeUsedInProof(Edge *edge); - /** Convert a collection of clauses to Nodes and Edges in the RPFP. + /** Convert a collection of clauses to Nodes and Edges in the RPFP. - Predicate unknowns are uninterpreted predicates not - occurring in the background theory. + Predicate unknowns are uninterpreted predicates not + occurring in the background theory. - Clauses are of the form + Clauses are of the form - B => P(t_1,...,t_k) + B => P(t_1,...,t_k) - where P is a predicate unknown and predicate unknowns - occur only positivey in H and only under existential - quantifiers in prenex form. + where P is a predicate unknown and predicate unknowns + occur only positivey in H and only under existential + quantifiers in prenex form. - Each predicate unknown maps to a node. Each clause maps to - an edge. Let C be a clause B => P(t_1,...,t_k) where the - sequence of predicate unknowns occurring in B (in order - of occurrence) is P_1..P_n. The clause maps to a transformer - T where: + Each predicate unknown maps to a node. Each clause maps to + an edge. Let C be a clause B => P(t_1,...,t_k) where the + sequence of predicate unknowns occurring in B (in order + of occurrence) is P_1..P_n. The clause maps to a transformer + T where: - T.Relparams = P_1..P_n - T.Indparams = x_1...x+k - T.Formula = B /\ t_1 = x_1 /\ ... /\ t_k = x_k + T.Relparams = P_1..P_n + T.Indparams = x_1...x+k + T.Formula = B /\ t_1 = x_1 /\ ... /\ t_k = x_k - Throws exception bad_clause(msg,i) if a clause i is - in the wrong form. + Throws exception bad_clause(msg,i) if a clause i is + in the wrong form. - */ + */ - struct label_struct { - symbol name; - expr value; - bool pos; + struct label_struct { + symbol name; + expr value; + bool pos; label_struct(const symbol &s, const expr &e, bool b) : name(s), value(e), pos(b) {} - }; + }; #ifdef _WINDOWS - __declspec(dllexport) + __declspec(dllexport) #endif - void FromClauses(const std::vector &clauses, const std::vector *bounds = 0); + void FromClauses(const std::vector &clauses, const std::vector *bounds = 0); - void FromFixpointContext(fixedpoint fp, std::vector &queries); + void FromFixpointContext(fixedpoint fp, std::vector &queries); - void WriteSolution(std::ostream &s); + void WriteSolution(std::ostream &s); - void WriteCounterexample(std::ostream &s, Node *node); + void WriteCounterexample(std::ostream &s, Node *node); - enum FileFormat {DualityFormat, SMT2Format, HornFormat}; + enum FileFormat {DualityFormat, SMT2Format, HornFormat}; - /** Write the RPFP to a file (currently in SMTLIB 1.2 format) */ - void WriteProblemToFile(std::string filename, FileFormat format = DualityFormat); + /** Write the RPFP to a file (currently in SMTLIB 1.2 format) */ + void WriteProblemToFile(std::string filename, FileFormat format = DualityFormat); - /** Read the RPFP from a file (in specificed format) */ - void ReadProblemFromFile(std::string filename, FileFormat format = DualityFormat); + /** Read the RPFP from a file (in specificed format) */ + void ReadProblemFromFile(std::string filename, FileFormat format = DualityFormat); - /** Translate problem to Horn clause form */ - void ToClauses(std::vector &cnsts, FileFormat format = DualityFormat); + /** Translate problem to Horn clause form */ + void ToClauses(std::vector &cnsts, FileFormat format = DualityFormat); - /** Translate the RPFP to a fixed point context, with queries */ - fixedpoint ToFixedPointProblem(std::vector &queries); + /** Translate the RPFP to a fixed point context, with queries */ + fixedpoint ToFixedPointProblem(std::vector &queries); - /** Nodes of the graph. */ - std::vector nodes; + /** Nodes of the graph. */ + std::vector nodes; - /** Edges of the graph. */ - std::vector edges; + /** Edges of the graph. */ + std::vector edges; - /** Fuse a vector of transformers. If the total number of inputs of the transformers - is N, then the result is an N-ary transfomer whose output is the union of - the outputs of the given transformers. The is, suppose we have a vetor of transfoermers - {T_i(r_i1,...,r_iN(i) : i=1..M}. The the result is a transformer + /** Fuse a vector of transformers. If the total number of inputs of the transformers + is N, then the result is an N-ary transfomer whose output is the union of + the outputs of the given transformers. The is, suppose we have a vetor of transfoermers + {T_i(r_i1,...,r_iN(i) : i=1..M}. The the result is a transformer - F(r_11,...,r_iN(1),...,r_M1,...,r_MN(M)) = - T_1(r_11,...,r_iN(1)) U ... U T_M(r_M1,...,r_MN(M)) - */ + F(r_11,...,r_iN(1),...,r_M1,...,r_MN(M)) = + T_1(r_11,...,r_iN(1)) U ... U T_M(r_M1,...,r_MN(M)) + */ - Transformer Fuse(const std::vector &trs); + Transformer Fuse(const std::vector &trs); - /** Fuse edges so that each node is the output of at most one edge. This - transformation is solution-preserving, but changes the numbering of edges in - counterexamples. - */ - void FuseEdges(); + /** Fuse edges so that each node is the output of at most one edge. This + transformation is solution-preserving, but changes the numbering of edges in + counterexamples. + */ + void FuseEdges(); - void RemoveDeadNodes(); + void RemoveDeadNodes(); - Term SubstParams(const std::vector &from, - const std::vector &to, const Term &t); + Term SubstParams(const std::vector &from, + const std::vector &to, const Term &t); - Term SubstParamsNoCapture(const std::vector &from, - const std::vector &to, const Term &t); + Term SubstParamsNoCapture(const std::vector &from, + const std::vector &to, const Term &t); - Term Localize(Edge *e, const Term &t); + Term Localize(Edge *e, const Term &t); - void EvalNodeAsConstraint(Node *p, Transformer &res); + void EvalNodeAsConstraint(Node *p, Transformer &res); - TermTree *GetGoalTree(Node *root); + TermTree *GetGoalTree(Node *root); - int EvalTruth(hash_map &memo, Edge *e, const Term &f); + int EvalTruth(hash_map &memo, Edge *e, const Term &f); - void GetLabels(Edge *e, std::vector &labels); + void GetLabels(Edge *e, std::vector &labels); - // int GetLabelsRec(hash_map *memo, const Term &f, std::vector &labels, bool labpos); + // int GetLabelsRec(hash_map *memo, const Term &f, std::vector &labels, bool labpos); - /** Compute and save the proof core for future calls to - EdgeUsedInProof. You only need to call this if you will pop - the solver before calling EdgeUsedInProof. - */ - void ComputeProofCore(); + /** Compute and save the proof core for future calls to + EdgeUsedInProof. You only need to call this if you will pop + the solver before calling EdgeUsedInProof. + */ + void ComputeProofCore(); - int CumulativeDecisions(); + int CumulativeDecisions(); - void GreedyReduceNodes(std::vector &nodes); + void GreedyReduceNodes(std::vector &nodes); - check_result CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes); + check_result CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes); - solver &slvr(){ - return *ls->slvr; - } + solver &slvr(){ + return *ls->slvr; + } protected: - void ClearProofCore(){ - if(proof_core) - delete proof_core; - proof_core = 0; - } + void ClearProofCore(){ + if(proof_core) + delete proof_core; + proof_core = 0; + } - Term SuffixVariable(const Term &t, int n); + Term SuffixVariable(const Term &t, int n); - Term HideVariable(const Term &t, int n); + Term HideVariable(const Term &t, int n); - void RedVars(Node *node, Term &b, std::vector &v); + void RedVars(Node *node, Term &b, std::vector &v); - Term RedDualRela(Edge *e, std::vector &args, int idx); + Term RedDualRela(Edge *e, std::vector &args, int idx); - Term LocalizeRec(Edge *e, hash_map &memo, const Term &t); + Term LocalizeRec(Edge *e, hash_map &memo, const Term &t); - void SetEdgeMaps(Edge *e); + void SetEdgeMaps(Edge *e); - Term ReducedDualEdge(Edge *e); + Term ReducedDualEdge(Edge *e); - TermTree *ToTermTree(Node *root, Node *skip_descendant = 0); + TermTree *ToTermTree(Node *root, Node *skip_descendant = 0); - TermTree *ToGoalTree(Node *root); + TermTree *ToGoalTree(Node *root); - void CollapseTermTreeRec(TermTree *root, TermTree *node); + void CollapseTermTreeRec(TermTree *root, TermTree *node); - TermTree *CollapseTermTree(TermTree *node); + TermTree *CollapseTermTree(TermTree *node); - void DecodeTree(Node *root, TermTree *interp, int persist); + void DecodeTree(Node *root, TermTree *interp, int persist); - Term GetUpperBound(Node *n); + Term GetUpperBound(Node *n); - TermTree *AddUpperBound(Node *root, TermTree *t); + TermTree *AddUpperBound(Node *root, TermTree *t); #if 0 - void WriteInterps(System.IO.StreamWriter f, TermTree t); + void WriteInterps(System.IO.StreamWriter f, TermTree t); #endif - void WriteEdgeVars(Edge *e, hash_map &memo, const Term &t, std::ostream &s); + void WriteEdgeVars(Edge *e, hash_map &memo, const Term &t, std::ostream &s); - void WriteEdgeAssignment(std::ostream &s, Edge *e); + void WriteEdgeAssignment(std::ostream &s, Edge *e); - // Scan the clause body for occurrences of the predicate unknowns + // Scan the clause body for occurrences of the predicate unknowns - Term ScanBody(hash_map &memo, - const Term &t, - hash_map &pmap, - std::vector &res, - std::vector &nodes); + Term ScanBody(hash_map &memo, + const Term &t, + hash_map &pmap, + std::vector &res, + std::vector &nodes); - Term RemoveLabelsRec(hash_map &memo, const Term &t, std::vector &lbls); + Term RemoveLabelsRec(hash_map &memo, const Term &t, std::vector &lbls); - Term RemoveLabels(const Term &t, std::vector &lbls); + Term RemoveLabels(const Term &t, std::vector &lbls); - Term GetAnnotation(Node *n); + Term GetAnnotation(Node *n); - Term GetUnderapprox(Node *n); + Term GetUnderapprox(Node *n); - Term UnderapproxFlag(Node *n); + Term UnderapproxFlag(Node *n); - hash_map underapprox_flag_rev; + hash_map underapprox_flag_rev; - Node *UnderapproxFlagRev(const Term &flag); + Node *UnderapproxFlagRev(const Term &flag); - Term ProjectFormula(std::vector &keep_vec, const Term &f); + Term ProjectFormula(std::vector &keep_vec, const Term &f); - int SubtermTruth(hash_map &memo, const Term &); + int SubtermTruth(hash_map &memo, const Term &); - void ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set *done, bool truth, hash_set &dont_cares); + void ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set *done, bool truth, hash_set &dont_cares); - void Implicant(hash_map &memo, const Term &f, std::vector &lits, hash_set &dont_cares); + void Implicant(hash_map &memo, const Term &f, std::vector &lits, hash_set &dont_cares); - Term UnderapproxFormula(const Term &f, hash_set &dont_cares); + Term UnderapproxFormula(const Term &f, hash_set &dont_cares); - void ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set &done, hash_set &dont_cares, bool extensional = true); + void ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set &done, hash_set &dont_cares, bool extensional = true); public: - Term UnderapproxFullFormula(const Term &f, bool extensional = true); + Term UnderapproxFullFormula(const Term &f, bool extensional = true); protected: - Term ToRuleRec(Edge *e, hash_map &memo, const Term &t, std::vector &quants); + Term ToRuleRec(Edge *e, hash_map &memo, const Term &t, std::vector &quants); - hash_map resolve_ite_memo; + hash_map resolve_ite_memo; - Term ResolveIte(hash_map &memo, const Term &t, std::vector &lits, - hash_set *done, hash_set &dont_cares); + Term ResolveIte(hash_map &memo, const Term &t, std::vector &lits, + hash_set *done, hash_set &dont_cares); - struct ArrayValue { - bool defined; - std::map entries; - expr def_val; - }; + struct ArrayValue { + bool defined; + std::map entries; + expr def_val; + }; - void EvalArrayTerm(const Term &t, ArrayValue &res); + void EvalArrayTerm(const Term &t, ArrayValue &res); - Term EvalArrayEquality(const Term &f); + Term EvalArrayEquality(const Term &f); - Term ModelValueAsConstraint(const Term &t); + Term ModelValueAsConstraint(const Term &t); - void GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, - hash_set *done, bool truth); + void GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, + hash_set *done, bool truth); - Term SubstBoundRec(hash_map > &memo, hash_map &subst, int level, const Term &t); + Term SubstBoundRec(hash_map > &memo, hash_map &subst, int level, const Term &t); - Term SubstBound(hash_map &subst, const Term &t); + Term SubstBound(hash_map &subst, const Term &t); - void ConstrainEdgeLocalized(Edge *e, const Term &t); + void ConstrainEdgeLocalized(Edge *e, const Term &t); - void GreedyReduce(solver &s, std::vector &conjuncts); + void GreedyReduce(solver &s, std::vector &conjuncts); - void NegateLits(std::vector &lits); + void NegateLits(std::vector &lits); - expr SimplifyOr(std::vector &lits); + expr SimplifyOr(std::vector &lits); - expr SimplifyAnd(std::vector &lits); + expr SimplifyAnd(std::vector &lits); - void SetAnnotation(Node *root, const expr &t); + void SetAnnotation(Node *root, const expr &t); - void AddEdgeToSolver(Edge *edge); + void AddEdgeToSolver(Edge *edge); - void AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge); + void AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge); - void AddToProofCore(hash_set &core); + void AddToProofCore(hash_set &core); - void GetGroundLitsUnderQuants(hash_set *memo, const Term &f, std::vector &res, int under); + void GetGroundLitsUnderQuants(hash_set *memo, const Term &f, std::vector &res, int under); - Term StrengthenFormulaByCaseSplitting(const Term &f, std::vector &case_lits); + Term StrengthenFormulaByCaseSplitting(const Term &f, std::vector &case_lits); - expr NegateLit(const expr &f); + expr NegateLit(const expr &f); - expr GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox); + expr GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox); - bool IsVar(const expr &t); + bool IsVar(const expr &t); - void GetVarsRec(hash_set &memo, const expr &cnst, std::vector &vars); + void GetVarsRec(hash_set &memo, const expr &cnst, std::vector &vars); - expr UnhoistPullRec(hash_map & memo, const expr &w, hash_map & init_defs, hash_map & const_params, hash_map &const_params_inv, std::vector &new_params); + expr UnhoistPullRec(hash_map & memo, const expr &w, hash_map & init_defs, hash_map & const_params, hash_map &const_params_inv, std::vector &new_params); - void AddParamsToTransformer(Transformer &trans, const std::vector ¶ms); + void AddParamsToTransformer(Transformer &trans, const std::vector ¶ms); - expr AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector ¶ms); + expr AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector ¶ms); - expr GetRelRec(hash_set &memo, const expr &t, const func_decl &rel); + expr GetRelRec(hash_set &memo, const expr &t, const func_decl &rel); - expr GetRel(Edge *edge, int child_idx); + expr GetRel(Edge *edge, int child_idx); - void GetDefs(const expr &cnst, hash_map &defs); + void GetDefs(const expr &cnst, hash_map &defs); - void GetDefsRec(const expr &cnst, hash_map &defs); + void GetDefsRec(const expr &cnst, hash_map &defs); - void AddParamsToNode(Node *node, const std::vector ¶ms); + void AddParamsToNode(Node *node, const std::vector ¶ms); - void UnhoistLoop(Edge *loop_edge, Edge *init_edge); + void UnhoistLoop(Edge *loop_edge, Edge *init_edge); - void Unhoist(); + void Unhoist(); - Term ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts); + Term ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts); - Term ElimIte(const Term &t); + Term ElimIte(const Term &t); - void MarkLiveNodes(hash_map > &outgoing, hash_set &live_nodes, Node *node); + void MarkLiveNodes(hash_map > &outgoing, hash_set &live_nodes, Node *node); - virtual void slvr_add(const expr &e); + virtual void slvr_add(const expr &e); - virtual void slvr_pop(int i); + virtual void slvr_pop(int i); - virtual void slvr_push(); + virtual void slvr_push(); - virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0); + virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0); - virtual lbool ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals = 0, - bool weak = false); + virtual lbool ls_interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals = 0, + bool weak = false); - virtual bool proof_core_contains(const expr &e); + virtual bool proof_core_contains(const expr &e); }; - /** RPFP solver base class. */ + /** RPFP solver base class. */ class Solver { public: - class Counterexample { - private: - RPFP *tree; - RPFP::Node *root; - public: - Counterexample(){ - tree = 0; - root = 0; - } - Counterexample(RPFP *_tree, RPFP::Node *_root){ - tree = _tree; - root = _root; - } - ~Counterexample(){ - if(tree) delete tree; - } - void swap(Counterexample &other){ - std::swap(tree,other.tree); - std::swap(root,other.root); - } - void set(RPFP *_tree, RPFP::Node *_root){ - if(tree) delete tree; - tree = _tree; - root = _root; - } - void clear(){ - if(tree) delete tree; - tree = 0; - } - RPFP *get_tree() const {return tree;} - RPFP::Node *get_root() const {return root;} - private: - Counterexample &operator=(const Counterexample &); - Counterexample(const Counterexample &); - }; + class Counterexample { + private: + RPFP *tree; + RPFP::Node *root; + public: + Counterexample(){ + tree = 0; + root = 0; + } + Counterexample(RPFP *_tree, RPFP::Node *_root){ + tree = _tree; + root = _root; + } + ~Counterexample(){ + if(tree) delete tree; + } + void swap(Counterexample &other){ + std::swap(tree,other.tree); + std::swap(root,other.root); + } + void set(RPFP *_tree, RPFP::Node *_root){ + if(tree) delete tree; + tree = _tree; + root = _root; + } + void clear(){ + if(tree) delete tree; + tree = 0; + } + RPFP *get_tree() const {return tree;} + RPFP::Node *get_root() const {return root;} + private: + Counterexample &operator=(const Counterexample &); + Counterexample(const Counterexample &); + }; - /** Solve the problem. You can optionally give an old - counterexample to use as a guide. This is chiefly useful for - abstraction refinement metholdologies, and is only used as a - heuristic. */ + /** Solve the problem. You can optionally give an old + counterexample to use as a guide. This is chiefly useful for + abstraction refinement metholdologies, and is only used as a + heuristic. */ - virtual bool Solve() = 0; + virtual bool Solve() = 0; - virtual Counterexample &GetCounterexample() = 0; + virtual Counterexample &GetCounterexample() = 0; - virtual bool SetOption(const std::string &option, const std::string &value) = 0; + virtual bool SetOption(const std::string &option, const std::string &value) = 0; - /** Learn heuristic information from another solver. This - is chiefly useful for abstraction refinement, when we want to - solve a series of similar problems. */ + /** Learn heuristic information from another solver. This + is chiefly useful for abstraction refinement, when we want to + solve a series of similar problems. */ - virtual void LearnFrom(Solver *old_solver) = 0; + virtual void LearnFrom(Solver *old_solver) = 0; - /** Return true if the solution be incorrect due to recursion bounding. - That is, the returned "solution" might contain all derivable facts up to the - given recursion bound, but not be actually a fixed point. - */ + /** Return true if the solution be incorrect due to recursion bounding. + That is, the returned "solution" might contain all derivable facts up to the + given recursion bound, but not be actually a fixed point. + */ - virtual bool IsResultRecursionBounded() = 0; + virtual bool IsResultRecursionBounded() = 0; - virtual ~Solver(){} + virtual ~Solver(){} - static Solver *Create(const std::string &solver_class, RPFP *rpfp); + static Solver *Create(const std::string &solver_class, RPFP *rpfp); - /** This can be called asynchrnously to cause Solve to throw a - Canceled exception at some time in the future. - */ - virtual void Cancel() = 0; + /** This can be called asynchrnously to cause Solve to throw a + Canceled exception at some time in the future. + */ + virtual void Cancel() = 0; - /** Object thrown on cancellation */ - struct Canceled {}; + /** Object thrown on cancellation */ + struct Canceled {}; - /** Object thrown on incompleteness */ - struct Incompleteness {}; + /** Object thrown on incompleteness */ + struct Incompleteness {}; }; } @@ -1191,35 +1191,35 @@ protected: // Allow to hash on nodes and edges in deterministic way namespace hash_space { - template <> - class hash { - public: - size_t operator()(const Duality::RPFP::Node *p) const { - return p->number; - } - }; + template <> + class hash { + public: + size_t operator()(const Duality::RPFP::Node *p) const { + return p->number; + } + }; } namespace hash_space { - template <> - class hash { - public: - size_t operator()(const Duality::RPFP::Edge *p) const { - return p->number; - } - }; + template <> + class hash { + public: + size_t operator()(const Duality::RPFP::Edge *p) const { + return p->number; + } + }; } // allow to walk sets of nodes without address dependency namespace std { - template <> - class less { - public: - bool operator()(Duality::RPFP::Node * const &s, Duality::RPFP::Node * const &t) const { - return s->number < t->number; // s.raw()->get_id() < t.raw()->get_id(); - } - }; + template <> + class less { + public: + bool operator()(Duality::RPFP::Node * const &s, Duality::RPFP::Node * const &t) const { + return s->number < t->number; // s.raw()->get_id() < t.raw()->get_id(); + } + }; } // #define LIMIT_STACK_WEIGHT 5 @@ -1229,131 +1229,131 @@ namespace Duality { /** Caching version of RPFP. Instead of asserting constraints, returns assumption literals */ class RPFP_caching : public RPFP { - public: + public: - /** appends assumption literals for edge to lits. if with_children is true, - includes that annotation of the edge's children. - */ - void AssertEdgeCache(Edge *e, std::vector &lits, bool with_children = false); + /** appends assumption literals for edge to lits. if with_children is true, + includes that annotation of the edge's children. + */ + void AssertEdgeCache(Edge *e, std::vector &lits, bool with_children = false); - /** appends assumption literals for node to lits */ - void AssertNodeCache(Node *, std::vector lits); + /** appends assumption literals for node to lits */ + void AssertNodeCache(Node *, std::vector lits); - /** check assumption lits, and return core */ - check_result CheckCore(const std::vector &assumps, std::vector &core); + /** check assumption lits, and return core */ + check_result CheckCore(const std::vector &assumps, std::vector &core); - /** Clone another RPFP into this one, keeping a map */ - void Clone(RPFP *other); + /** Clone another RPFP into this one, keeping a map */ + void Clone(RPFP *other); - /** Get the clone of a node */ - Node *GetNodeClone(Node *other_node); + /** Get the clone of a node */ + Node *GetNodeClone(Node *other_node); - /** Get the clone of an edge */ - Edge *GetEdgeClone(Edge *other_edge); + /** Get the clone of an edge */ + Edge *GetEdgeClone(Edge *other_edge); - /** Try to strengthen the parent of an edge */ - void GeneralizeCache(Edge *edge); + /** Try to strengthen the parent of an edge */ + void GeneralizeCache(Edge *edge); - /** Try to propagate some facts from children to parents of edge. - Return true if success. */ - bool PropagateCache(Edge *edge); + /** Try to propagate some facts from children to parents of edge. + Return true if success. */ + bool PropagateCache(Edge *edge); - /** Construct a caching RPFP using a LogicSolver */ - RPFP_caching(LogicSolver *_ls) : RPFP(_ls) {} + /** Construct a caching RPFP using a LogicSolver */ + RPFP_caching(LogicSolver *_ls) : RPFP(_ls) {} - /** Constraint an edge by its child's annotation. Return - assumption lits. */ - void ConstrainParentCache(Edge *parent, Node *child, std::vector &lits); + /** Constraint an edge by its child's annotation. Return + assumption lits. */ + void ConstrainParentCache(Edge *parent, Node *child, std::vector &lits); #ifdef LIMIT_STACK_WEIGHT - virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false); + virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false); #endif - virtual ~RPFP_caching(){} + virtual ~RPFP_caching(){} - protected: - hash_map AssumptionLits; - hash_map NodeCloneMap; - hash_map EdgeCloneMap; - std::vector alit_stack; - std::vector alit_stack_sizes; + protected: + hash_map AssumptionLits; + hash_map NodeCloneMap; + hash_map EdgeCloneMap; + std::vector alit_stack; + std::vector alit_stack_sizes; - // to let us use one solver per edge - struct edge_solver { - hash_map AssumptionLits; - uptr slvr; - }; - hash_map edge_solvers; + // to let us use one solver per edge + struct edge_solver { + hash_map AssumptionLits; + uptr slvr; + }; + hash_map edge_solvers; #ifdef LIMIT_STACK_WEIGHT - struct weight_counter { - int val; - weight_counter(){val = 0;} - void swap(weight_counter &other){ - std::swap(val,other.val); - } - }; + struct weight_counter { + int val; + weight_counter(){val = 0;} + void swap(weight_counter &other){ + std::swap(val,other.val); + } + }; - struct big_stack_entry { - weight_counter weight_added; - std::vector new_alits; - std::vector alit_stack; - std::vector alit_stack_sizes; - }; + struct big_stack_entry { + weight_counter weight_added; + std::vector new_alits; + std::vector alit_stack; + std::vector alit_stack_sizes; + }; - std::vector new_alits; - weight_counter weight_added; - std::vector big_stack; + std::vector new_alits; + weight_counter weight_added; + std::vector big_stack; #endif - void GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map = 0); + void GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map = 0); - void GreedyReduceCache(std::vector &assumps, std::vector &core); + void GreedyReduceCache(std::vector &assumps, std::vector &core); - void FilterCore(std::vector &core, std::vector &full_core); - void ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector &lits); + void FilterCore(std::vector &core, std::vector &full_core); + void ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector &lits); - virtual void slvr_add(const expr &e); + virtual void slvr_add(const expr &e); - virtual void slvr_pop(int i); + virtual void slvr_pop(int i); - virtual void slvr_push(); + virtual void slvr_push(); - virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0); + virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0); - virtual lbool ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals = 0, - bool weak = false); + virtual lbool ls_interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals = 0, + bool weak = false); - virtual bool proof_core_contains(const expr &e); + virtual bool proof_core_contains(const expr &e); - void GetTermTreeAssertionLiterals(TermTree *assumptions); + void GetTermTreeAssertionLiterals(TermTree *assumptions); - void GetTermTreeAssertionLiteralsRec(TermTree *assumptions); + void GetTermTreeAssertionLiteralsRec(TermTree *assumptions); - edge_solver &SolverForEdge(Edge *edge, bool models, bool axioms); + edge_solver &SolverForEdge(Edge *edge, bool models, bool axioms); - public: - struct scoped_solver_for_edge { - solver *orig_slvr; - RPFP_caching *rpfp; - edge_solver *es; - scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false, bool axioms = false){ - rpfp = _rpfp; - orig_slvr = rpfp->ls->slvr; - es = &(rpfp->SolverForEdge(edge,models,axioms)); - rpfp->ls->slvr = es->slvr.get(); - rpfp->AssumptionLits.swap(es->AssumptionLits); - } - ~scoped_solver_for_edge(){ - rpfp->ls->slvr = orig_slvr; - rpfp->AssumptionLits.swap(es->AssumptionLits); - } - }; + public: + struct scoped_solver_for_edge { + solver *orig_slvr; + RPFP_caching *rpfp; + edge_solver *es; + scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false, bool axioms = false){ + rpfp = _rpfp; + orig_slvr = rpfp->ls->slvr; + es = &(rpfp->SolverForEdge(edge,models,axioms)); + rpfp->ls->slvr = es->slvr.get(); + rpfp->AssumptionLits.swap(es->AssumptionLits); + } + ~scoped_solver_for_edge(){ + rpfp->ls->slvr = orig_slvr; + rpfp->AssumptionLits.swap(es->AssumptionLits); + } + }; }; diff --git a/src/duality/duality_profiling.cpp b/src/duality/duality_profiling.cpp index 13a379946..e841f674b 100755 --- a/src/duality/duality_profiling.cpp +++ b/src/duality/duality_profiling.cpp @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - duality_profiling.cpp + duality_profiling.cpp -Abstract: + Abstract: - collection performance information for duality + collection performance information for duality -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #include @@ -36,109 +36,109 @@ Revision History: namespace Duality { - void show_time(){ - output_time(std::cout,current_time()); - std::cout << "\n"; - } + void show_time(){ + output_time(std::cout,current_time()); + std::cout << "\n"; + } - typedef std::map nmap; + typedef std::map nmap; - struct node { - std::string name; - clock_t time; - clock_t start_time; - nmap sub; - struct node *parent; + struct node { + std::string name; + clock_t time; + clock_t start_time; + nmap sub; + struct node *parent; - node(); - } top; + node(); + } top; - node::node(){ - time = 0; - parent = 0; - } - - struct node *current; - - struct init { - init(){ - top.name = "TOTAL"; - current = ⊤ + node::node(){ + time = 0; + parent = 0; } - } initializer; - struct time_entry { - clock_t t; - time_entry(){t = 0;}; - void add(clock_t incr){t += incr;} - }; + struct node *current; - struct ltstr - { - bool operator()(const char* s1, const char* s2) const + struct init { + init(){ + top.name = "TOTAL"; + current = ⊤ + } + } initializer; + + struct time_entry { + clock_t t; + time_entry(){t = 0;}; + void add(clock_t incr){t += incr;} + }; + + struct ltstr { - return strcmp(s1, s2) < 0; - } - }; + bool operator()(const char* s1, const char* s2) const + { + return strcmp(s1, s2) < 0; + } + }; - typedef std::map tmap; + typedef std::map tmap; - static std::ostream *pfs; + static std::ostream *pfs; - void print_node(node &top, int indent, tmap &totals){ - for(int i = 0; i < indent; i++) (*pfs) << " "; - (*pfs) << top.name; - int dots = 70 - 2 * indent - top.name.size(); - for(int i = 0; i second,indent+1,totals); - } - - void print_profile(std::ostream &os) { - pfs = &os; - top.time = 0; - for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) - top.time += it->second.time; - tmap totals; - print_node(top,0,totals); - (*pfs) << "TOTALS:" << std::endl; - for(tmap::iterator it = totals.begin(); it != totals.end(); it++){ - (*pfs) << (it->first) << " "; - output_time(*pfs, it->second.t); - (*pfs) << std::endl; + void print_node(node &top, int indent, tmap &totals){ + for(int i = 0; i < indent; i++) (*pfs) << " "; + (*pfs) << top.name; + int dots = 70 - 2 * indent - top.name.size(); + for(int i = 0; i second,indent+1,totals); } - profiling::print(os); // print the interpolation stats - } - void timer_start(const char *name){ - node &child = current->sub[name]; - if(child.name.empty()){ // a new node - child.parent = current; - child.name = name; + void print_profile(std::ostream &os) { + pfs = &os; + top.time = 0; + for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) + top.time += it->second.time; + tmap totals; + print_node(top,0,totals); + (*pfs) << "TOTALS:" << std::endl; + for(tmap::iterator it = totals.begin(); it != totals.end(); it++){ + (*pfs) << (it->first) << " "; + output_time(*pfs, it->second.t); + (*pfs) << std::endl; + } + profiling::print(os); // print the interpolation stats + } + + void timer_start(const char *name){ + node &child = current->sub[name]; + if(child.name.empty()){ // a new node + child.parent = current; + child.name = name; + } + child.start_time = current_time(); + current = &child; } - child.start_time = current_time(); - current = &child; - } - void timer_stop(const char *name){ - if (current->name != name || !current->parent) { + void timer_stop(const char *name){ + if (current->name != name || !current->parent) { #if 0 - std::cerr << "imbalanced timer_start and timer_stop"; - exit(1); + std::cerr << "imbalanced timer_start and timer_stop"; + exit(1); #endif - // in case we lost a timer stop due to an exception - while (current->name != name && current->parent) - current = current->parent; - if (current->parent) { - current->time += (current_time() - current->start_time); - current = current->parent; - } - return; - } - current->time += (current_time() - current->start_time); - current = current->parent; - } + // in case we lost a timer stop due to an exception + while (current->name != name && current->parent) + current = current->parent; + if (current->parent) { + current->time += (current_time() - current->start_time); + current = current->parent; + } + return; + } + current->time += (current_time() - current->start_time); + current = current->parent; + } } diff --git a/src/duality/duality_profiling.h b/src/duality/duality_profiling.h index 2b2264405..5f0e5120c 100755 --- a/src/duality/duality_profiling.h +++ b/src/duality/duality_profiling.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - duality_profiling.h + duality_profiling.h -Abstract: + Abstract: - collection performance information for duality + collection performance information for duality -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef DUALITYPROFILING_H #define DUALITYPROFILING_H @@ -24,14 +24,14 @@ Revision History: #include namespace Duality { - /** Start a timer with given name */ - void timer_start(const char *); - /** Stop a timer with given name */ - void timer_stop(const char *); - /** Print out timings */ - void print_profile(std::ostream &s); - /** Show the current time. */ - void show_time(); + /** Start a timer with given name */ + void timer_start(const char *); + /** Stop a timer with given name */ + void timer_stop(const char *); + /** Print out timings */ + void print_profile(std::ostream &s); + /** Show the current time. */ + void show_time(); } #endif diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index eefb3b85f..0a3692295 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -1,23 +1,23 @@ /*++ -Copyright (c) 2012 Microsoft Corporation + Copyright (c) 2012 Microsoft Corporation -Module Name: + Module Name: - duality_rpfp.h + duality_rpfp.h -Abstract: + Abstract: - implements relational post-fixedpoint problem - (RPFP) data structure. + implements relational post-fixedpoint problem + (RPFP) data structure. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ @@ -40,9 +40,9 @@ Revision History: #ifdef Z3OPS class Z3_subterm_truth { - public: - virtual bool eval(Z3_ast f) = 0; - ~Z3_subterm_truth(){} +public: + virtual bool eval(Z3_ast f) = 0; + ~Z3_subterm_truth(){} }; Z3_subterm_truth *Z3_mk_subterm_truth(Z3_context ctx, Z3_model model); @@ -56,4237 +56,4237 @@ int debug_gauss = 0; namespace Duality { - static char string_of_int_buffer[20]; + static char string_of_int_buffer[20]; - const char *Z3User::string_of_int(int n){ - sprintf(string_of_int_buffer,"%d",n); - return string_of_int_buffer; - } - - RPFP::Term RPFP::SuffixVariable(const Term &t, int n) - { - std::string name = t.decl().name().str() + "_" + string_of_int(n); - return ctx.constant(name.c_str(), t.get_sort()); - } - - RPFP::Term RPFP::HideVariable(const Term &t, int n) - { - std::string name = std::string("@p_") + t.decl().name().str() + "_" + string_of_int(n); - return ctx.constant(name.c_str(), t.get_sort()); - } - - void RPFP::RedVars(Node *node, Term &b, std::vector &v) - { - int idx = node->number; - if(HornClauses) - b = ctx.bool_val(true); - else { - std::string name = std::string("@b_") + string_of_int(idx); - symbol sym = ctx.str_symbol(name.c_str()); - b = ctx.constant(sym,ctx.bool_sort()); + const char *Z3User::string_of_int(int n){ + sprintf(string_of_int_buffer,"%d",n); + return string_of_int_buffer; } - // ctx.constant(name.c_str(), ctx.bool_sort()); - v = node->Annotation.IndParams; - for(unsigned i = 0; i < v.size(); i++) - v[i] = SuffixVariable(v[i],idx); - } - void Z3User::SummarizeRec(hash_set &memo, std::vector &lits, int &ops, const Term &t){ - if(memo.find(t) != memo.end()) - return; - memo.insert(t); - if(t.is_app()){ - decl_kind k = t.decl().get_decl_kind(); - if (k == And || k == Or || k == Not || k == Implies || k == Iff) { - ops++; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - SummarizeRec(memo, lits, ops, t.arg(i)); - return; - } + RPFP::Term RPFP::SuffixVariable(const Term &t, int n) + { + std::string name = t.decl().name().str() + "_" + string_of_int(n); + return ctx.constant(name.c_str(), t.get_sort()); } - lits.push_back(t); - } - int RPFP::CumulativeDecisions(){ -#if 0 - std::string stats = Z3_statistics_to_string(ctx); - int pos = stats.find("decisions:"); - pos += 10; - int end = stats.find('\n',pos); - std::string val = stats.substr(pos,end-pos); - return atoi(val.c_str()); -#endif - return slvr().get_num_decisions(); - } - - - void Z3User::Summarize(const Term &t){ - hash_set memo; std::vector lits; int ops = 0; - SummarizeRec(memo, lits, ops, t); - std::cout << ops << ": "; - for(unsigned i = 0; i < lits.size(); i++){ - if(i > 0) std::cout << ", "; - std::cout << lits[i]; + RPFP::Term RPFP::HideVariable(const Term &t, int n) + { + std::string name = std::string("@p_") + t.decl().name().str() + "_" + string_of_int(n); + return ctx.constant(name.c_str(), t.get_sort()); } - } - int Z3User::CountOperatorsRec(hash_set &memo, const Term &t){ - if(memo.find(t) != memo.end()) - return 0; - memo.insert(t); - if(t.is_app()){ - decl_kind k = t.decl().get_decl_kind(); - if (k == And || k == Or) { - int count = 1; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - count += CountOperatorsRec(memo, t.arg(i)); - return count; - } - return 0; - } - if(t.is_quantifier()){ - int nbv = t.get_quantifier_num_bound(); - return CountOperatorsRec(memo,t.body()) + 2 * nbv; // count 2 for each quantifier - } - return 0; - } - - int Z3User::CountOperators(const Term &t){ - hash_set memo; - return CountOperatorsRec(memo,t); - } - - - Z3User::Term Z3User::conjoin(const std::vector &args){ - return ctx.make(And,args); - } - - Z3User::Term Z3User::sum(const std::vector &args){ - return ctx.make(Plus,args); - } - - RPFP::Term RPFP::RedDualRela(Edge *e, std::vector &args, int idx){ - Node *child = e->Children[idx]; - Term b(ctx); - std::vector v; - RedVars(child, b, v); - for (unsigned i = 0; i < args.size(); i++) { - if (eq(args[i].get_sort(), ctx.bool_sort())) - args[i] = ctx.make(Iff, args[i], v[i]); - else - args[i] = args[i] == v[i]; - } - return args.size() > 0 ? (b && conjoin(args)) : b; - } - - Z3User::Term Z3User::CloneQuantifier(const Term &t, const Term &new_body){ -#if 0 - Z3_context c = ctx; - Z3_ast a = t; - std::vector pats; - int num_pats = Z3_get_quantifier_num_patterns(c,a); - for(int i = 0; i < num_pats; i++) - pats.push_back(Z3_get_quantifier_pattern_ast(c,a,i)); - std::vector no_pats; - int num_no_pats = Z3_get_quantifier_num_patterns(c,a); - for(int i = 0; i < num_no_pats; i++) - no_pats.push_back(Z3_get_quantifier_no_pattern_ast(c,a,i)); - int bound = Z3_get_quantifier_num_bound(c,a); - std::vector sorts; - std::vector names; - for(int i = 0; i < bound; i++){ - sorts.push_back(Z3_get_quantifier_bound_sort(c,a,i)); - names.push_back(Z3_get_quantifier_bound_name(c,a,i)); - } - Z3_ast foo = Z3_mk_quantifier_ex(c, - Z3_is_quantifier_forall(c,a), - Z3_get_quantifier_weight(c,a), - 0, - 0, - num_pats, - &pats[0], - num_no_pats, - &no_pats[0], - bound, - &sorts[0], - &names[0], - new_body); - return expr(ctx,foo); -#endif - return clone_quantifier(t,new_body); - } - - - RPFP::Term RPFP::LocalizeRec(Edge *e, hash_map &memo, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - hash_map::iterator it = e->varMap.find(t); - if (it != e->varMap.end()){ - res = it->second; - return res; - } - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(LocalizeRec(e, memo, t.arg(i))); - hash_map::iterator rit = e->relMap.find(f); - if (rit != e->relMap.end()) - res = RedDualRela(e, args, (rit->second)); + void RPFP::RedVars(Node *node, Term &b, std::vector &v) + { + int idx = node->number; + if(HornClauses) + b = ctx.bool_val(true); else { - if (args.size() == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)) { - res = HideVariable(t, e->number); + std::string name = std::string("@b_") + string_of_int(idx); + symbol sym = ctx.str_symbol(name.c_str()); + b = ctx.constant(sym,ctx.bool_sort()); + } + // ctx.constant(name.c_str(), ctx.bool_sort()); + v = node->Annotation.IndParams; + for(unsigned i = 0; i < v.size(); i++) + v[i] = SuffixVariable(v[i],idx); + } + + void Z3User::SummarizeRec(hash_set &memo, std::vector &lits, int &ops, const Term &t){ + if(memo.find(t) != memo.end()) + return; + memo.insert(t); + if(t.is_app()){ + decl_kind k = t.decl().get_decl_kind(); + if (k == And || k == Or || k == Not || k == Implies || k == Iff) { + ops++; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + SummarizeRec(memo, lits, ops, t.arg(i)); + return; + } + } + lits.push_back(t); + } + + int RPFP::CumulativeDecisions(){ +#if 0 + std::string stats = Z3_statistics_to_string(ctx); + int pos = stats.find("decisions:"); + pos += 10; + int end = stats.find('\n',pos); + std::string val = stats.substr(pos,end-pos); + return atoi(val.c_str()); +#endif + return slvr().get_num_decisions(); + } + + + void Z3User::Summarize(const Term &t){ + hash_set memo; std::vector lits; int ops = 0; + SummarizeRec(memo, lits, ops, t); + std::cout << ops << ": "; + for(unsigned i = 0; i < lits.size(); i++){ + if(i > 0) std::cout << ", "; + std::cout << lits[i]; + } + } + + int Z3User::CountOperatorsRec(hash_set &memo, const Term &t){ + if(memo.find(t) != memo.end()) + return 0; + memo.insert(t); + if(t.is_app()){ + decl_kind k = t.decl().get_decl_kind(); + if (k == And || k == Or) { + int count = 1; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + count += CountOperatorsRec(memo, t.arg(i)); + return count; + } + return 0; + } + if(t.is_quantifier()){ + int nbv = t.get_quantifier_num_bound(); + return CountOperatorsRec(memo,t.body()) + 2 * nbv; // count 2 for each quantifier + } + return 0; + } + + int Z3User::CountOperators(const Term &t){ + hash_set memo; + return CountOperatorsRec(memo,t); + } + + + Z3User::Term Z3User::conjoin(const std::vector &args){ + return ctx.make(And,args); + } + + Z3User::Term Z3User::sum(const std::vector &args){ + return ctx.make(Plus,args); + } + + RPFP::Term RPFP::RedDualRela(Edge *e, std::vector &args, int idx){ + Node *child = e->Children[idx]; + Term b(ctx); + std::vector v; + RedVars(child, b, v); + for (unsigned i = 0; i < args.size(); i++) { + if (eq(args[i].get_sort(), ctx.bool_sort())) + args[i] = ctx.make(Iff, args[i], v[i]); + else + args[i] = args[i] == v[i]; + } + return args.size() > 0 ? (b && conjoin(args)) : b; + } + + Z3User::Term Z3User::CloneQuantifier(const Term &t, const Term &new_body){ +#if 0 + Z3_context c = ctx; + Z3_ast a = t; + std::vector pats; + int num_pats = Z3_get_quantifier_num_patterns(c,a); + for(int i = 0; i < num_pats; i++) + pats.push_back(Z3_get_quantifier_pattern_ast(c,a,i)); + std::vector no_pats; + int num_no_pats = Z3_get_quantifier_num_patterns(c,a); + for(int i = 0; i < num_no_pats; i++) + no_pats.push_back(Z3_get_quantifier_no_pattern_ast(c,a,i)); + int bound = Z3_get_quantifier_num_bound(c,a); + std::vector sorts; + std::vector names; + for(int i = 0; i < bound; i++){ + sorts.push_back(Z3_get_quantifier_bound_sort(c,a,i)); + names.push_back(Z3_get_quantifier_bound_name(c,a,i)); + } + Z3_ast foo = Z3_mk_quantifier_ex(c, + Z3_is_quantifier_forall(c,a), + Z3_get_quantifier_weight(c,a), + 0, + 0, + num_pats, + &pats[0], + num_no_pats, + &no_pats[0], + bound, + &sorts[0], + &names[0], + new_body); + return expr(ctx,foo); +#endif + return clone_quantifier(t,new_body); + } + + + RPFP::Term RPFP::LocalizeRec(Edge *e, hash_map &memo, const Term &t) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + hash_map::iterator it = e->varMap.find(t); + if (it != e->varMap.end()){ + res = it->second; + return res; + } + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(LocalizeRec(e, memo, t.arg(i))); + hash_map::iterator rit = e->relMap.find(f); + if (rit != e->relMap.end()) + res = RedDualRela(e, args, (rit->second)); + else { + if (args.size() == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)) { + res = HideVariable(t, e->number); + } + else { + res = f(args.size(), &args[0]); + } + } + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = LocalizeRec(e, memo, pats[i]); + Term body = LocalizeRec(e, memo, t.body()); + res = clone_quantifier(t, body, pats); + } + else res = t; + return res; + } + + void RPFP::SetEdgeMaps(Edge *e){ + timer_start("SetEdgeMaps"); + e->relMap.clear(); + e->varMap.clear(); + for(unsigned i = 0; i < e->F.RelParams.size(); i++){ + e->relMap[e->F.RelParams[i]] = i; + } + Term b(ctx); + std::vector v; + RedVars(e->Parent, b, v); + for(unsigned i = 0; i < e->F.IndParams.size(); i++){ + // func_decl parentParam = e->Parent.Annotation.IndParams[i]; + expr oldname = e->F.IndParams[i]; + expr newname = v[i]; + e->varMap[oldname] = newname; + } + timer_stop("SetEdgeMaps"); + + } + + + RPFP::Term RPFP::Localize(Edge *e, const Term &t){ + timer_start("Localize"); + hash_map memo; + if(e->F.IndParams.size() > 0 && e->varMap.empty()) + SetEdgeMaps(e); // TODO: why is this needed? + Term res = LocalizeRec(e,memo,t); + timer_stop("Localize"); + return res; + } + + + RPFP::Term RPFP::ReducedDualEdge(Edge *e) + { + SetEdgeMaps(e); + timer_start("RedVars"); + Term b(ctx); + std::vector v; + RedVars(e->Parent, b, v); + timer_stop("RedVars"); + // ast_to_track = (ast)b; + return implies(b, Localize(e, e->F.Formula)); + } + + TermTree *RPFP::ToTermTree(Node *root, Node *skip_descendant) + { + if(skip_descendant && root == skip_descendant) + return new TermTree(ctx.bool_val(true)); + Edge *e = root->Outgoing; + if(!e) return new TermTree(ctx.bool_val(true), std::vector()); + std::vector children(e->Children.size()); + for(unsigned i = 0; i < children.size(); i++) + children[i] = ToTermTree(e->Children[i],skip_descendant); + // Term top = ReducedDualEdge(e); + Term top = e->dual.null() ? ctx.bool_val(true) : e->dual; + TermTree *res = new TermTree(top, children); + for(unsigned i = 0; i < e->constraints.size(); i++) + res->addTerm(e->constraints[i]); + return res; + } + + TermTree *RPFP::GetGoalTree(Node *root){ + std::vector children(1); + children[0] = ToGoalTree(root); + return new TermTree(ctx.bool_val(false),children); + } + + TermTree *RPFP::ToGoalTree(Node *root) + { + Term b(ctx); + std::vector v; + RedVars(root, b, v); + Term goal = root->Name(v); + Edge *e = root->Outgoing; + if(!e) return new TermTree(goal, std::vector()); + std::vector children(e->Children.size()); + for(unsigned i = 0; i < children.size(); i++) + children[i] = ToGoalTree(e->Children[i]); + // Term top = ReducedDualEdge(e); + return new TermTree(goal, children); + } + + Z3User::Term Z3User::SubstRec(hash_map &memo, const Term &t) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(SubstRec(memo, t.arg(i))); + res = f(args.size(), &args[0]); + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = SubstRec(memo, pats[i]); + Term body = SubstRec(memo, t.body()); + res = clone_quantifier(t, body, pats); + } + // res = CloneQuantifier(t,SubstRec(memo, t.body())); + else res = t; + return res; + } + + Z3User::Term Z3User::SubstRec(hash_map &memo, hash_map &map, const Term &t) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(SubstRec(memo, map, t.arg(i))); + hash_map::iterator it = map.find(f); + if (it != map.end()) + f = it->second; + res = f(args.size(), &args[0]); + } + else if (t.is_quantifier()) { + std::vector pats; + t.get_patterns(pats); + for (unsigned i = 0; i < pats.size(); i++) + pats[i] = SubstRec(memo, map, pats[i]); + Term body = SubstRec(memo, map, t.body()); + res = clone_quantifier(t, body, pats); + } + // res = CloneQuantifier(t,SubstRec(memo, t.body())); + else res = t; + return res; + } + + Z3User::Term Z3User::ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(ExtractStores(memo, t.arg(i), cnstrs, renaming)); + res = f(args.size(), &args[0]); + if (f.get_decl_kind() == Store) { + func_decl fresh = ctx.fresh_func_decl("@arr", res.get_sort()); + expr y = fresh(); + expr equ = ctx.make(Equal, y, res); + cnstrs.push_back(equ); + renaming[y] = res; + res = y; + } + } + else res = t; + return res; + } + + + bool Z3User::IsLiteral(const expr &lit, expr &atom, expr &val){ + if (!(lit.is_quantifier() && IsClosedFormula(lit))) { + if (!lit.is_app()) + return false; + decl_kind k = lit.decl().get_decl_kind(); + if (k == Not) { + if (IsLiteral(lit.arg(0), atom, val)) { + val = eq(val, ctx.bool_val(true)) ? ctx.bool_val(false) : ctx.bool_val(true); + return true; + } + return false; + } + if (k == And || k == Or || k == Iff || k == Implies) + return false; + } + atom = lit; + val = ctx.bool_val(true); + return true; + } + + expr Z3User::Negate(const expr &f){ + if(f.is_app() && f.decl().get_decl_kind() == Not) + return f.arg(0); + else if(eq(f,ctx.bool_val(true))) + return ctx.bool_val(false); + else if(eq(f,ctx.bool_val(false))) + return ctx.bool_val(true); + return !f; + } + + expr Z3User::ReduceAndOr(const std::vector &args, bool is_and, std::vector &res){ + for(unsigned i = 0; i < args.size(); i++) + if (!eq(args[i], ctx.bool_val(is_and))) { + if (eq(args[i], ctx.bool_val(!is_and))) + return ctx.bool_val(!is_and); + res.push_back(args[i]); + } + return expr(); + } + + expr Z3User::FinishAndOr(const std::vector &args, bool is_and){ + if(args.size() == 0) + return ctx.bool_val(is_and); + if(args.size() == 1) + return args[0]; + return ctx.make(is_and ? And : Or,args); + } + + expr Z3User::SimplifyAndOr(const std::vector &args, bool is_and){ + std::vector sargs; + expr res = ReduceAndOr(args,is_and,sargs); + if(!res.null()) return res; + return FinishAndOr(sargs,is_and); + } + + expr Z3User::PullCommonFactors(std::vector &args, bool is_and){ + + // first check if there's anything to do... + if(args.size() < 2) + return FinishAndOr(args,is_and); + for (unsigned i = 0; i < args.size(); i++) { + const expr &a = args[i]; + if (!(a.is_app() && a.decl().get_decl_kind() == (is_and ? Or : And))) + return FinishAndOr(args, is_and); + } + std::vector common; + for (unsigned i = 0; i < args.size(); i++) { + unsigned n = args[i].num_args(); + std::vector v(n), w; + for (unsigned j = 0; j < n; j++) + v[j] = args[i].arg(j); + std::less comp; + std::sort(v.begin(), v.end(), comp); + if (i == 0) + common.swap(v); + else { + std::set_intersection(common.begin(), common.end(), v.begin(), v.end(), std::inserter(w, w.begin()), comp); + common.swap(w); + } + } + if(common.empty()) + return FinishAndOr(args,is_and); + std::set common_set(common.begin(),common.end()); + for(unsigned i = 0; i < args.size(); i++){ + unsigned n = args[i].num_args(); + std::vector lits; + for (unsigned j = 0; j < n; j++) { + const expr b = args[i].arg(j); + if (common_set.find(b) == common_set.end()) + lits.push_back(b); + } + args[i] = SimplifyAndOr(lits,!is_and); + } + common.push_back(SimplifyAndOr(args,is_and)); + return SimplifyAndOr(common,!is_and); + } + + expr Z3User::ReallySimplifyAndOr(const std::vector &args, bool is_and){ + std::vector sargs; + expr res = ReduceAndOr(args,is_and,sargs); + if(!res.null()) return res; + return PullCommonFactors(sargs,is_and); + } + + Z3User::Term Z3User::SubstAtomTriv(const expr &foo, const expr &atom, const expr &val){ + if(eq(foo,atom)) + return val; + else if(foo.is_app() && foo.decl().get_decl_kind() == Not && eq(foo.arg(0),atom)) + return Negate(val); + else + return foo; + } + + Z3User::Term Z3User::PushQuantifier(const expr &t, const expr &body, bool is_forall){ + if (t.get_quantifier_num_bound() == 1) { + std::vector fmlas, free, not_free; + CollectJuncts(body, fmlas, is_forall ? Or : And, false); + for (unsigned i = 0; i < fmlas.size(); i++) { + const expr &fmla = fmlas[i]; + if (fmla.has_free(0)) + free.push_back(fmla); + else + not_free.push_back(fmla); + } + decl_kind op = is_forall ? Or : And; + if (free.empty()) + return DeleteBound(0, 1, SimplifyAndOr(not_free, op == And)); + expr q = clone_quantifier(is_forall ? Forall : Exists, t, SimplifyAndOr(free, op == And)); + if (!not_free.empty()) + q = ctx.make(op, q, DeleteBound(0, 1, SimplifyAndOr(not_free, op == And))); + return q; + } + return clone_quantifier(is_forall ? Forall : Exists,t,body); + } + + Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall) { + if (body.is_app()) { + if (body.decl().get_decl_kind() == (is_forall ? And : Or)) { // quantifier distributes + int nargs = body.num_args(); + std::vector args(nargs); + for (int i = 0; i < nargs; i++) + args[i] = CloneQuantAndSimp(t, body.arg(i), is_forall); + return SimplifyAndOr(args, body.decl().get_decl_kind() == And); + } + else if (body.decl().get_decl_kind() == (is_forall ? Or : And)) { // quantifier distributes + return PushQuantifier(t, body, is_forall); // may distribute partially + } + else if (body.decl().get_decl_kind() == Not) { + return ctx.make(Not, CloneQuantAndSimp(t, body.arg(0), !is_forall)); + } + } + if (t.get_quantifier_num_bound() == 1 && !body.has_free(0)) + return DeleteBound(0, 1, body); // drop the quantifier + return clone_quantifier(is_forall ? Forall : Exists, t, body); + } + + Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body){ + return CloneQuantAndSimp(t,body,t.is_quantifier_forall()); + } + + Z3User::Term Z3User::SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + decl_kind k = f.get_decl_kind(); + + // TODO: recur here, but how much? We don't want to be quadractic in formula size + + if (k == And || k == Or) { + int nargs = t.num_args(); + std::vector args(nargs); + for (int i = 0; i < nargs; i++) + args[i] = SubstAtom(memo, t.arg(i), atom, val); + res = ReallySimplifyAndOr(args, k == And); + return res; + } + } + else if (t.is_quantifier() && atom.is_quantifier()) { + if (eq(t, atom)) + res = val; + else + res = clone_quantifier(t, SubstAtom(memo, t.body(), atom, val)); + return res; + } + res = SubstAtomTriv(t, atom, val); + return res; + } + + void Z3User::RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo) { + for (unsigned i = 0; i < args.size(); i++) { + const expr &lit = args[i]; + expr atom, val; + if (IsLiteral(lit, atom, val)) { + if (atom.is_app() && atom.decl().get_decl_kind() == Equal) + if (pol ? eq(val, ctx.bool_val(true)) : eq(val, ctx.bool_val(false))) { + expr lhs = atom.arg(0), rhs = atom.arg(1); + if (lhs.is_numeral()) + std::swap(lhs, rhs); + if (rhs.is_numeral() && lhs.is_app()) { + for (unsigned j = 0; j < args.size(); j++) + if (j != i) { + smemo.clear(); + smemo[lhs] = rhs; + args[j] = SubstRec(smemo, args[j]); + } + } + } + for (unsigned j = 0; j < args.size(); j++) + if (j != i) { + smemo.clear(); + args[j] = SubstAtom(smemo, args[j], atom, pol ? val : !val); + } + } + } + } + + + Z3User::Term Z3User::RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(RemoveRedundancyRec(memo, smemo, t.arg(i))); + + decl_kind k = f.get_decl_kind(); + if (k == And) { + RemoveRedundancyOp(true, args, smemo); + res = ReallySimplifyAndOr(args, true); + } + else if (k == Or) { + RemoveRedundancyOp(false, args, smemo); + res = ReallySimplifyAndOr(args, false); } else { + if (k == Equal && args[0].get_id() > args[1].get_id()) + std::swap(args[0], args[1]); res = f(args.size(), &args[0]); } } - } - else if (t.is_quantifier()) { - std::vector pats; - t.get_patterns(pats); - for (unsigned i = 0; i < pats.size(); i++) - pats[i] = LocalizeRec(e, memo, pats[i]); - Term body = LocalizeRec(e, memo, t.body()); - res = clone_quantifier(t, body, pats); - } - else res = t; - return res; - } - - void RPFP::SetEdgeMaps(Edge *e){ - timer_start("SetEdgeMaps"); - e->relMap.clear(); - e->varMap.clear(); - for(unsigned i = 0; i < e->F.RelParams.size(); i++){ - e->relMap[e->F.RelParams[i]] = i; - } - Term b(ctx); - std::vector v; - RedVars(e->Parent, b, v); - for(unsigned i = 0; i < e->F.IndParams.size(); i++){ - // func_decl parentParam = e->Parent.Annotation.IndParams[i]; - expr oldname = e->F.IndParams[i]; - expr newname = v[i]; - e->varMap[oldname] = newname; - } - timer_stop("SetEdgeMaps"); - - } - - - RPFP::Term RPFP::Localize(Edge *e, const Term &t){ - timer_start("Localize"); - hash_map memo; - if(e->F.IndParams.size() > 0 && e->varMap.empty()) - SetEdgeMaps(e); // TODO: why is this needed? - Term res = LocalizeRec(e,memo,t); - timer_stop("Localize"); - return res; - } - - - RPFP::Term RPFP::ReducedDualEdge(Edge *e) - { - SetEdgeMaps(e); - timer_start("RedVars"); - Term b(ctx); - std::vector v; - RedVars(e->Parent, b, v); - timer_stop("RedVars"); - // ast_to_track = (ast)b; - return implies(b, Localize(e, e->F.Formula)); - } - - TermTree *RPFP::ToTermTree(Node *root, Node *skip_descendant) - { - if(skip_descendant && root == skip_descendant) - return new TermTree(ctx.bool_val(true)); - Edge *e = root->Outgoing; - if(!e) return new TermTree(ctx.bool_val(true), std::vector()); - std::vector children(e->Children.size()); - for(unsigned i = 0; i < children.size(); i++) - children[i] = ToTermTree(e->Children[i],skip_descendant); - // Term top = ReducedDualEdge(e); - Term top = e->dual.null() ? ctx.bool_val(true) : e->dual; - TermTree *res = new TermTree(top, children); - for(unsigned i = 0; i < e->constraints.size(); i++) - res->addTerm(e->constraints[i]); - return res; - } - - TermTree *RPFP::GetGoalTree(Node *root){ - std::vector children(1); - children[0] = ToGoalTree(root); - return new TermTree(ctx.bool_val(false),children); - } - - TermTree *RPFP::ToGoalTree(Node *root) - { - Term b(ctx); - std::vector v; - RedVars(root, b, v); - Term goal = root->Name(v); - Edge *e = root->Outgoing; - if(!e) return new TermTree(goal, std::vector()); - std::vector children(e->Children.size()); - for(unsigned i = 0; i < children.size(); i++) - children[i] = ToGoalTree(e->Children[i]); - // Term top = ReducedDualEdge(e); - return new TermTree(goal, children); - } - - Z3User::Term Z3User::SubstRec(hash_map &memo, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, t.arg(i))); - res = f(args.size(), &args[0]); - } - else if (t.is_quantifier()) { - std::vector pats; - t.get_patterns(pats); - for (unsigned i = 0; i < pats.size(); i++) - pats[i] = SubstRec(memo, pats[i]); - Term body = SubstRec(memo, t.body()); - res = clone_quantifier(t, body, pats); - } - // res = CloneQuantifier(t,SubstRec(memo, t.body())); - else res = t; - return res; - } - - Z3User::Term Z3User::SubstRec(hash_map &memo, hash_map &map, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, map, t.arg(i))); - hash_map::iterator it = map.find(f); - if (it != map.end()) - f = it->second; - res = f(args.size(), &args[0]); - } - else if (t.is_quantifier()) { - std::vector pats; - t.get_patterns(pats); - for (unsigned i = 0; i < pats.size(); i++) - pats[i] = SubstRec(memo, map, pats[i]); - Term body = SubstRec(memo, map, t.body()); - res = clone_quantifier(t, body, pats); - } - // res = CloneQuantifier(t,SubstRec(memo, t.body())); - else res = t; - return res; - } - - Z3User::Term Z3User::ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(ExtractStores(memo, t.arg(i), cnstrs, renaming)); - res = f(args.size(), &args[0]); - if (f.get_decl_kind() == Store) { - func_decl fresh = ctx.fresh_func_decl("@arr", res.get_sort()); - expr y = fresh(); - expr equ = ctx.make(Equal, y, res); - cnstrs.push_back(equ); - renaming[y] = res; - res = y; + else if (t.is_quantifier()) { + Term body = RemoveRedundancyRec(memo, smemo, t.body()); + res = CloneQuantAndSimp(t, body); } - } - else res = t; - return res; - } - - - bool Z3User::IsLiteral(const expr &lit, expr &atom, expr &val){ - if (!(lit.is_quantifier() && IsClosedFormula(lit))) { - if (!lit.is_app()) - return false; - decl_kind k = lit.decl().get_decl_kind(); - if (k == Not) { - if (IsLiteral(lit.arg(0), atom, val)) { - val = eq(val, ctx.bool_val(true)) ? ctx.bool_val(false) : ctx.bool_val(true); - return true; - } - return false; - } - if (k == And || k == Or || k == Iff || k == Implies) - return false; - } - atom = lit; - val = ctx.bool_val(true); - return true; - } - - expr Z3User::Negate(const expr &f){ - if(f.is_app() && f.decl().get_decl_kind() == Not) - return f.arg(0); - else if(eq(f,ctx.bool_val(true))) - return ctx.bool_val(false); - else if(eq(f,ctx.bool_val(false))) - return ctx.bool_val(true); - return !f; - } - - expr Z3User::ReduceAndOr(const std::vector &args, bool is_and, std::vector &res){ - for(unsigned i = 0; i < args.size(); i++) - if (!eq(args[i], ctx.bool_val(is_and))) { - if (eq(args[i], ctx.bool_val(!is_and))) - return ctx.bool_val(!is_and); - res.push_back(args[i]); - } - return expr(); - } - - expr Z3User::FinishAndOr(const std::vector &args, bool is_and){ - if(args.size() == 0) - return ctx.bool_val(is_and); - if(args.size() == 1) - return args[0]; - return ctx.make(is_and ? And : Or,args); - } - - expr Z3User::SimplifyAndOr(const std::vector &args, bool is_and){ - std::vector sargs; - expr res = ReduceAndOr(args,is_and,sargs); - if(!res.null()) return res; - return FinishAndOr(sargs,is_and); - } - - expr Z3User::PullCommonFactors(std::vector &args, bool is_and){ - - // first check if there's anything to do... - if(args.size() < 2) - return FinishAndOr(args,is_and); - for (unsigned i = 0; i < args.size(); i++) { - const expr &a = args[i]; - if (!(a.is_app() && a.decl().get_decl_kind() == (is_and ? Or : And))) - return FinishAndOr(args, is_and); - } - std::vector common; - for (unsigned i = 0; i < args.size(); i++) { - unsigned n = args[i].num_args(); - std::vector v(n), w; - for (unsigned j = 0; j < n; j++) - v[j] = args[i].arg(j); - std::less comp; - std::sort(v.begin(), v.end(), comp); - if (i == 0) - common.swap(v); - else { - std::set_intersection(common.begin(), common.end(), v.begin(), v.end(), std::inserter(w, w.begin()), comp); - common.swap(w); - } - } - if(common.empty()) - return FinishAndOr(args,is_and); - std::set common_set(common.begin(),common.end()); - for(unsigned i = 0; i < args.size(); i++){ - unsigned n = args[i].num_args(); - std::vector lits; - for (unsigned j = 0; j < n; j++) { - const expr b = args[i].arg(j); - if (common_set.find(b) == common_set.end()) - lits.push_back(b); - } - args[i] = SimplifyAndOr(lits,!is_and); - } - common.push_back(SimplifyAndOr(args,is_and)); - return SimplifyAndOr(common,!is_and); - } - - expr Z3User::ReallySimplifyAndOr(const std::vector &args, bool is_and){ - std::vector sargs; - expr res = ReduceAndOr(args,is_and,sargs); - if(!res.null()) return res; - return PullCommonFactors(sargs,is_and); - } - - Z3User::Term Z3User::SubstAtomTriv(const expr &foo, const expr &atom, const expr &val){ - if(eq(foo,atom)) - return val; - else if(foo.is_app() && foo.decl().get_decl_kind() == Not && eq(foo.arg(0),atom)) - return Negate(val); - else - return foo; - } - - Z3User::Term Z3User::PushQuantifier(const expr &t, const expr &body, bool is_forall){ - if (t.get_quantifier_num_bound() == 1) { - std::vector fmlas, free, not_free; - CollectJuncts(body, fmlas, is_forall ? Or : And, false); - for (unsigned i = 0; i < fmlas.size(); i++) { - const expr &fmla = fmlas[i]; - if (fmla.has_free(0)) - free.push_back(fmla); - else - not_free.push_back(fmla); - } - decl_kind op = is_forall ? Or : And; - if (free.empty()) - return DeleteBound(0, 1, SimplifyAndOr(not_free, op == And)); - expr q = clone_quantifier(is_forall ? Forall : Exists, t, SimplifyAndOr(free, op == And)); - if (!not_free.empty()) - q = ctx.make(op, q, DeleteBound(0, 1, SimplifyAndOr(not_free, op == And))); - return q; - } - return clone_quantifier(is_forall ? Forall : Exists,t,body); - } - - Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body, bool is_forall) { - if (body.is_app()) { - if (body.decl().get_decl_kind() == (is_forall ? And : Or)) { // quantifier distributes - int nargs = body.num_args(); - std::vector args(nargs); - for (int i = 0; i < nargs; i++) - args[i] = CloneQuantAndSimp(t, body.arg(i), is_forall); - return SimplifyAndOr(args, body.decl().get_decl_kind() == And); - } - else if (body.decl().get_decl_kind() == (is_forall ? Or : And)) { // quantifier distributes - return PushQuantifier(t, body, is_forall); // may distribute partially - } - else if (body.decl().get_decl_kind() == Not) { - return ctx.make(Not, CloneQuantAndSimp(t, body.arg(0), !is_forall)); - } - } - if (t.get_quantifier_num_bound() == 1 && !body.has_free(0)) - return DeleteBound(0, 1, body); // drop the quantifier - return clone_quantifier(is_forall ? Forall : Exists, t, body); - } - - Z3User::Term Z3User::CloneQuantAndSimp(const expr &t, const expr &body){ - return CloneQuantAndSimp(t,body,t.is_quantifier_forall()); - } - - Z3User::Term Z3User::SubstAtom(hash_map &memo, const expr &t, const expr &atom, const expr &val) { - std::pair foo(t, expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if (!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - decl_kind k = f.get_decl_kind(); - - // TODO: recur here, but how much? We don't want to be quadractic in formula size - - if (k == And || k == Or) { - int nargs = t.num_args(); - std::vector args(nargs); - for (int i = 0; i < nargs; i++) - args[i] = SubstAtom(memo, t.arg(i), atom, val); - res = ReallySimplifyAndOr(args, k == And); - return res; - } - } - else if (t.is_quantifier() && atom.is_quantifier()) { - if (eq(t, atom)) - res = val; - else - res = clone_quantifier(t, SubstAtom(memo, t.body(), atom, val)); - return res; - } - res = SubstAtomTriv(t, atom, val); - return res; - } - - void Z3User::RemoveRedundancyOp(bool pol, std::vector &args, hash_map &smemo) { - for (unsigned i = 0; i < args.size(); i++) { - const expr &lit = args[i]; - expr atom, val; - if (IsLiteral(lit, atom, val)) { - if (atom.is_app() && atom.decl().get_decl_kind() == Equal) - if (pol ? eq(val, ctx.bool_val(true)) : eq(val, ctx.bool_val(false))) { - expr lhs = atom.arg(0), rhs = atom.arg(1); - if (lhs.is_numeral()) - std::swap(lhs, rhs); - if (rhs.is_numeral() && lhs.is_app()) { - for (unsigned j = 0; j < args.size(); j++) - if (j != i) { - smemo.clear(); - smemo[lhs] = rhs; - args[j] = SubstRec(smemo, args[j]); - } - } - } - for (unsigned j = 0; j < args.size(); j++) - if (j != i) { - smemo.clear(); - args[j] = SubstAtom(smemo, args[j], atom, pol ? val : !val); - } - } - } - } - - - Z3User::Term Z3User::RemoveRedundancyRec(hash_map &memo, hash_map &smemo, const Term &t) { - std::pair foo(t, expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if (!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(RemoveRedundancyRec(memo, smemo, t.arg(i))); - - decl_kind k = f.get_decl_kind(); - if (k == And) { - RemoveRedundancyOp(true, args, smemo); - res = ReallySimplifyAndOr(args, true); - } - else if (k == Or) { - RemoveRedundancyOp(false, args, smemo); - res = ReallySimplifyAndOr(args, false); - } - else { - if (k == Equal && args[0].get_id() > args[1].get_id()) - std::swap(args[0], args[1]); - res = f(args.size(), &args[0]); - } - } - else if (t.is_quantifier()) { - Term body = RemoveRedundancyRec(memo, smemo, t.body()); - res = CloneQuantAndSimp(t, body); - } - else res = t; - return res; - } - - Z3User::Term Z3User::RemoveRedundancy(const Term &t){ - hash_map memo; - hash_map smemo; - return RemoveRedundancyRec(memo,smemo,t); - } - - Z3User::Term Z3User::AdjustQuantifiers(const Term &t) - { - if(t.is_quantifier() || (t.is_app() && t.has_quantifiers())) - return t.qe_lite(); - return t; - } - - Z3User::Term Z3User::IneqToEqRec(hash_map &memo, const Term &t) { - std::pair foo(t, expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if (!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - args.push_back(IneqToEqRec(memo, t.arg(i))); - - decl_kind k = f.get_decl_kind(); - if (k == And) { - for (int i = 0; i < nargs - 1; i++) { - if ((args[i].is_app() && args[i].decl().get_decl_kind() == Geq && - args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Leq) - || - (args[i].is_app() && args[i].decl().get_decl_kind() == Leq && - args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Geq)) - if (eq(args[i].arg(0), args[i + 1].arg(0)) && eq(args[i].arg(1), args[i + 1].arg(1))) { - args[i] = ctx.make(Equal, args[i].arg(0), args[i].arg(1)); - args[i + 1] = ctx.bool_val(true); - } - } - } - res = f(args.size(), &args[0]); - } - else if (t.is_quantifier()) { - Term body = IneqToEqRec(memo, t.body()); - res = clone_quantifier(t, body); - } - else res = t; - return res; - } - - Z3User::Term Z3User::IneqToEq(const Term &t){ - hash_map memo; - return IneqToEqRec(memo,t); - } - - Z3User::Term Z3User::SubstRecHide(hash_map &memo, const Term &t, int number) { - std::pair foo(t, expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if (!bar.second) return res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if (nargs == 0 && f.get_decl_kind() == Uninterpreted) { - std::string name = std::string("@q_") + t.decl().name().str() + "_" + string_of_int(number); - res = ctx.constant(name.c_str(), t.get_sort()); - return res; - } - for (int i = 0; i < nargs; i++) - args.push_back(SubstRec(memo, t.arg(i))); - res = f(args.size(), &args[0]); - } - else if (t.is_quantifier()) - res = CloneQuantifier(t, SubstRec(memo, t.body())); - else res = t; - return res; - } - - RPFP::Term RPFP::SubstParams(const std::vector &from, - const std::vector &to, const Term &t) { - hash_map memo; - bool some_diff = false; - for (unsigned i = 0; i < from.size(); i++) - if (i < to.size() && !eq(from[i], to[i])) { - memo[from[i]] = to[i]; - some_diff = true; - } - return some_diff ? SubstRec(memo, t) : t; - } - - RPFP::Term RPFP::SubstParamsNoCapture(const std::vector &from, - const std::vector &to, const Term &t) { - hash_map memo; - bool some_diff = false; - for (unsigned i = 0; i < from.size(); i++) - if (i < to.size() && !eq(from[i], to[i])) { - memo[from[i]] = to[i]; - // if the new param is not being mapped to anything else, we need to rename it to prevent capture - // note, if the new param *is* mapped later in the list, it will override this substitution - const expr &w = to[i]; - if (memo.find(w) == memo.end()) { - std::string old_name = w.decl().name().str(); - func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); - expr y = fresh(); - memo[w] = y; - } - some_diff = true; - } - return some_diff ? SubstRec(memo, t) : t; - } - - - - RPFP::Transformer RPFP::Fuse(const std::vector &trs) { - assert(!trs.empty()); - const std::vector ¶ms = trs[0]->IndParams; - std::vector fmlas(trs.size()); - fmlas[0] = trs[0]->Formula; - for (unsigned i = 1; i < trs.size(); i++) - fmlas[i] = SubstParamsNoCapture(trs[i]->IndParams, params, trs[i]->Formula); - std::vector rel_params = trs[0]->RelParams; - for (unsigned i = 1; i < trs.size(); i++) { - const std::vector ¶ms2 = trs[i]->RelParams; - hash_map map; - for (unsigned j = 0; j < params2.size(); j++) { - func_decl rel = RenumberPred(params2[j], rel_params.size()); - rel_params.push_back(rel); - map[params2[j]] = rel; - } - hash_map memo; - fmlas[i] = SubstRec(memo, map, fmlas[i]); - } - return Transformer(rel_params, params, ctx.make(Or, fmlas), trs[0]->owner); - } - - - void Z3User::Strengthen(Term &x, const Term &y) - { - if (eq(x,ctx.bool_val(true))) - x = y; - else - x = x && y; - } - - void RPFP::SetAnnotation(Node *root, const expr &t){ - hash_map memo; - Term b; - std::vector v; - RedVars(root, b, v); - memo[b] = ctx.bool_val(true); - for (unsigned i = 0; i < v.size(); i++) - memo[v[i]] = root->Annotation.IndParams[i]; - Term annot = SubstRec(memo, t); - // Strengthen(ref root.Annotation.Formula, annot); - root->Annotation.Formula = annot; - } - - void RPFP::DecodeTree(Node *root, TermTree *interp, int persist) { - std::vector &ic = interp->getChildren(); - if (ic.size() > 0) { - std::vector &nc = root->Outgoing->Children; - for (unsigned i = 0; i < nc.size(); i++) - DecodeTree(nc[i], ic[i], persist); - } - SetAnnotation(root, interp->getTerm()); -#if 0 - if(persist != 0) - Z3_persist_ast(ctx,root->Annotation.Formula,persist); -#endif - } - - RPFP::Term RPFP::GetUpperBound(Node *n) - { - // TODO: cache this - Term b(ctx); std::vector v; - RedVars(n, b, v); - hash_map memo; - for (unsigned int i = 0; i < v.size(); i++) - memo[n->Bound.IndParams[i]] = v[i]; - Term cnst = SubstRec(memo, n->Bound.Formula); - return b && !cnst; - } - - RPFP::Term RPFP::GetAnnotation(Node *n) - { - if(eq(n->Annotation.Formula,ctx.bool_val(true))) - return n->Annotation.Formula; - // TODO: cache this - Term b(ctx); std::vector v; - RedVars(n, b, v); - hash_map memo; - for (unsigned i = 0; i < v.size(); i++) - memo[n->Annotation.IndParams[i]] = v[i]; - Term cnst = SubstRec(memo, n->Annotation.Formula); - return !b || cnst; - } - - RPFP::Term RPFP::GetUnderapprox(Node *n) - { - // TODO: cache this - Term b(ctx); std::vector v; - RedVars(n, b, v); - hash_map memo; - for (unsigned i = 0; i < v.size(); i++) - memo[n->Underapprox.IndParams[i]] = v[i]; - Term cnst = SubstRecHide(memo, n->Underapprox.Formula, n->number); - return !b || cnst; - } - - TermTree *RPFP::AddUpperBound(Node *root, TermTree *t) - { - Term f = !((ast)(root->dual)) ? ctx.bool_val(true) : root->dual; - std::vector c(1); c[0] = t; - return new TermTree(f, c); - } - -#if 0 - void RPFP::WriteInterps(System.IO.StreamWriter f, TermTree t) - { - foreach (var c in t.getChildren()) - WriteInterps(f, c); - f.WriteLine(t.getTerm()); - } -#endif - - - expr RPFP::GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox) { - if (e->dual.null()) { - timer_start("ReducedDualEdge"); - e->dual = ReducedDualEdge(e); - timer_stop("ReducedDualEdge"); - timer_start("getting children"); - if (underapprox) { - std::vector cus(e->Children.size()); - for (unsigned i = 0; i < e->Children.size(); i++) - cus[i] = !UnderapproxFlag(e->Children[i]) || GetUnderapprox(e->Children[i]); - expr cnst = conjoin(cus); - e->dual = e->dual && cnst; - } - timer_stop("getting children"); - timer_start("Persisting"); - std::list::reverse_iterator it = stack.rbegin(); - for (int i = 0; i < persist && it != stack.rend(); i++) - it++; - if (it != stack.rend()) - it->edges.push_back(e); - timer_stop("Persisting"); - //Console.WriteLine("{0}", cnst); - } - return e->dual; - } - - /** For incremental solving, asserts the constraint associated - * with this edge in the SMT context. If this edge is removed, - * you must pop the context accordingly. The second argument is - * the number of pushes we are inside. The constraint formula - * will survive "persist" pops of the context. If you plan - * to reassert the edge after popping the context once, - * you can save time re-constructing the formula by setting - * "persist" to one. If you set "persist" too high, however, - * you could have a memory leak. - * - * The flag "with children" causes the annotations of the children - * to be asserted. The flag underapprox causes the underapproximations - * of the children to be asserted *conditionally*. See Check() on - * how to actually enforce these constraints. - * - */ - - void RPFP::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) { - if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); - timer_start("solver add"); - slvr_add(e->dual); - timer_stop("solver add"); - if (with_children) - for (unsigned i = 0; i < e->Children.size(); i++) - ConstrainParent(e, e->Children[i]); - } - - -#ifdef LIMIT_STACK_WEIGHT - void RPFP_caching::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) - { - unsigned old_new_alits = new_alits.size(); - if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); - timer_start("solver add"); - slvr_add(e->dual); - timer_stop("solver add"); - if(old_new_alits < new_alits.size()) - weight_added.val++; - if(with_children) - for(unsigned i = 0; i < e->Children.size(); i++) - ConstrainParent(e,e->Children[i]); - } -#endif - - // caching verion of above - void RPFP_caching::AssertEdgeCache(Edge *e, std::vector &lits, bool with_children) { - if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) - return; - expr fmla = GetEdgeFormula(e, 0, with_children, false); - GetAssumptionLits(fmla, lits); - if (with_children) - for (unsigned i = 0; i < e->Children.size(); i++) - ConstrainParentCache(e, e->Children[i], lits); - } - - void RPFP::slvr_add(const expr &e){ - slvr().add(e); - } - - void RPFP_caching::slvr_add(const expr &e){ - GetAssumptionLits(e,alit_stack); - } - - void RPFP::slvr_pop(int i){ - slvr().pop(i); - } - - void RPFP::slvr_push(){ - slvr().push(); - } - - void RPFP_caching::slvr_pop(int i){ - for(int j = 0; j < i; j++){ -#ifdef LIMIT_STACK_WEIGHT - if(alit_stack_sizes.empty()){ - if(big_stack.empty()) - throw "stack underflow"; - for(unsigned k = 0; k < new_alits.size(); k++){ - if(AssumptionLits.find(new_alits[k]) == AssumptionLits.end()) - throw "foo!"; - AssumptionLits.erase(new_alits[k]); - } - big_stack_entry &bsb = big_stack.back(); - bsb.alit_stack_sizes.swap(alit_stack_sizes); - bsb.alit_stack.swap(alit_stack); - bsb.new_alits.swap(new_alits); - bsb.weight_added.swap(weight_added); - big_stack.pop_back(); - slvr().pop(1); - continue; - } -#endif - alit_stack.resize(alit_stack_sizes.back()); - alit_stack_sizes.pop_back(); - } - } - - void RPFP_caching::slvr_push(){ -#ifdef LIMIT_STACK_WEIGHT - if(weight_added.val > LIMIT_STACK_WEIGHT){ - big_stack.resize(big_stack.size()+1); - big_stack_entry &bsb = big_stack.back(); - bsb.alit_stack_sizes.swap(alit_stack_sizes); - bsb.alit_stack.swap(alit_stack); - bsb.new_alits.swap(new_alits); - bsb.weight_added.swap(weight_added); - slvr().push(); - for(unsigned i = 0; i < bsb.alit_stack.size(); i++) - slvr().add(bsb.alit_stack[i]); - return; - } -#endif - alit_stack_sizes.push_back(alit_stack.size()); - } - - check_result RPFP::slvr_check(unsigned n, expr * const assumptions, unsigned *core_size, expr *core){ - return slvr().check(n, assumptions, core_size, core); - } - - check_result RPFP_caching::slvr_check(unsigned n, expr * const assumptions, unsigned *core_size, expr *core){ - unsigned oldsiz = alit_stack.size(); - if(n && assumptions) - std::copy(assumptions,assumptions+n,std::inserter(alit_stack,alit_stack.end())); - check_result res; - if (core_size && core) { - std::vector full_core(alit_stack.size()), core1(n); - std::copy(assumptions, assumptions + n, core1.begin()); - res = slvr().check(alit_stack.size(), &alit_stack[0], core_size, &full_core[0]); - full_core.resize(*core_size); - if (res == unsat) { - FilterCore(core1, full_core); - *core_size = core1.size(); - std::copy(core1.begin(), core1.end(), core); - } - } - else - res = slvr().check(alit_stack.size(), &alit_stack[0]); - alit_stack.resize(oldsiz); - return res; - } - - lbool RPFP::ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals, - bool weak) { - return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); - } - - lbool RPFP_caching::ls_interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - TermTree *goals, - bool weak) { - GetTermTreeAssertionLiterals(assumptions); - return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); - } - - void RPFP_caching::GetTermTreeAssertionLiteralsRec(TermTree *assumptions){ - std::vector alits; - hash_map map; - GetAssumptionLits(assumptions->getTerm(),alits,&map); - std::vector &ts = assumptions->getTerms(); - for(unsigned i = 0; i < ts.size(); i++) - GetAssumptionLits(ts[i],alits,&map); - assumptions->setTerm(ctx.bool_val(true)); - ts = alits; - for(unsigned i = 0; i < alits.size(); i++) - ts.push_back(ctx.make(Implies,alits[i],map[alits[i]])); - for(unsigned i = 0; i < assumptions->getChildren().size(); i++) - GetTermTreeAssertionLiterals(assumptions->getChildren()[i]); - return; - } - - void RPFP_caching::GetTermTreeAssertionLiterals(TermTree *assumptions) { - // optimize binary case - if (assumptions->getChildren().size() == 1 - && assumptions->getChildren()[0]->getChildren().size() == 0) { - hash_map map; - TermTree *child = assumptions->getChildren()[0]; - std::vector dummy; - GetAssumptionLits(child->getTerm(), dummy, &map); - std::vector &ts = child->getTerms(); - for (unsigned i = 0; i < ts.size(); i++) - GetAssumptionLits(ts[i], dummy, &map); - std::vector assumps; - slvr().get_proof().get_assumptions(assumps); - if (!proof_core) { // save the proof core for later use - proof_core = new hash_set < ast > ; - for (unsigned i = 0; i < assumps.size(); i++) - proof_core->insert(assumps[i]); - } - std::vector *cnsts[2] = { &child->getTerms(), &assumptions->getTerms() }; - for (unsigned i = 0; i < assumps.size(); i++) { - expr &as = assumps[i]; - expr alit = (as.is_app() && as.decl().get_decl_kind() == Implies) ? as.arg(0) : as; - bool isA = map.find(alit) != map.end(); - cnsts[isA ? 0 : 1]->push_back(as); - } - } - else - GetTermTreeAssertionLiteralsRec(assumptions); - } - - void RPFP::AddToProofCore(hash_set &core){ - std::vector assumps; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++) - core.insert(assumps[i]); - } - - void RPFP::ComputeProofCore(){ - if(!proof_core){ - proof_core = new hash_set; - AddToProofCore(*proof_core); - } - } - - - void RPFP_caching::GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map) { - std::vector conjs; - CollectConjuncts(fmla, conjs); - for (unsigned i = 0; i < conjs.size(); i++) { - const expr &conj = conjs[i]; - std::pair foo(conj, expr(ctx)); - std::pair::iterator, bool> bar = AssumptionLits.insert(foo); - Term &res = bar.first->second; - if (bar.second) { - func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); - res = pred(); -#ifdef LIMIT_STACK_WEIGHT - new_alits.push_back(conj); -#endif - slvr().add(ctx.make(Implies, res, conj)); - // std::cout << res << ": " << conj << "\n"; - } - if (opt_map) - (*opt_map)[res] = conj; - lits.push_back(res); - } - } - - void RPFP::ConstrainParent(Edge *parent, Node *child){ - ConstrainEdgeLocalized(parent,GetAnnotation(child)); - } - - void RPFP_caching::ConstrainParentCache(Edge *parent, Node *child, std::vector &lits){ - ConstrainEdgeLocalizedCache(parent,GetAnnotation(child),lits); - } - - - /** For incremental solving, asserts the negation of the upper bound associated - * with a node. - * */ - - void RPFP::AssertNode(Node *n) - { - if (n->dual.null()) { - n->dual = GetUpperBound(n); - stack.back().nodes.push_back(n); - slvr_add(n->dual); - } - } - - // caching version of above - void RPFP_caching::AssertNodeCache(Node *n, std::vector lits){ - if (n->dual.null()) { - n->dual = GetUpperBound(n); - stack.back().nodes.push_back(n); - GetAssumptionLits(n->dual, lits); - } - } - - /** Clone another RPFP into this one, keeping a map */ - void RPFP_caching::Clone(RPFP *other) { -#if 0 - for(unsigned i = 0; i < other->nodes.size(); i++) - NodeCloneMap[other->nodes[i]] = CloneNode(other->nodes[i]); -#endif - for (unsigned i = 0; i < other->edges.size(); i++) { - Edge *edge = other->edges[i]; - Node *parent = CloneNode(edge->Parent); - std::vector cs; - for (unsigned j = 0; j < edge->Children.size(); j++) - // cs.push_back(NodeCloneMap[edge->Children[j]]); - cs.push_back(CloneNode(edge->Children[j])); - EdgeCloneMap[edge] = CreateEdge(parent, edge->F, cs); - } - } - - /** Get the clone of a node */ - RPFP::Node *RPFP_caching::GetNodeClone(Node *other_node){ - return NodeCloneMap[other_node]; - } - - /** Get the clone of an edge */ - RPFP::Edge *RPFP_caching::GetEdgeClone(Edge *other_edge){ - return EdgeCloneMap[other_edge]; - } - - /** check assumption lits, and return core */ - check_result RPFP_caching::CheckCore(const std::vector &assumps, std::vector &core){ - core.resize(assumps.size()); - unsigned core_size; - check_result res = slvr().check(assumps.size(),(expr *)&assumps[0],&core_size,&core[0]); - if(res == unsat) - core.resize(core_size); - else - core.clear(); - return res; - } - - - /** Assert a constraint on an edge in the SMT context. - */ - - void RPFP::ConstrainEdge(Edge *e, const Term &t) - { - Term tl = Localize(e, t); - ConstrainEdgeLocalized(e,tl); - } - - void RPFP::ConstrainEdgeLocalized(Edge *e, const Term &tl) - { - e->constraints.push_back(tl); - stack.back().constraints.push_back(std::pair(e,tl)); - slvr_add(tl); - } - - void RPFP_caching::ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector &lits) - { - e->constraints.push_back(tl); - stack.back().constraints.push_back(std::pair(e,tl)); - GetAssumptionLits(tl,lits); - } - - - /** Declare a constant in the background theory. */ - - void RPFP::DeclareConstant(const FuncDecl &f){ - ls->declare_constant(f); - } - - /** Assert a background axiom. Background axioms can be used to provide the - * theory of auxilliary functions or relations. All symbols appearing in - * background axioms are considered global, and may appear in both transformer - * and relational solutions. Semantically, a solution to the RPFP gives - * an interpretation of the unknown relations for each interpretation of the - * auxilliary symbols that is consistent with the axioms. Axioms should be - * asserted before any calls to Push. They cannot be de-asserted by Pop. */ - - void RPFP::AssertAxiom(const Term &t) - { - ls->assert_axiom(t); - axioms.push_back(t); // for printing only - } - -#if 0 - /** Do not call this. */ - - void RPFP::RemoveAxiom(const Term &t) - { - slvr().RemoveInterpolationAxiom(t); - } -#endif - - /** Solve an RPFP graph. This means either strengthen the annotation - * so that the bound at the given root node is satisfied, or - * show that this cannot be done by giving a dual solution - * (i.e., a counterexample). - * - * In the current implementation, this only works for graphs that - * are: - * - tree-like - * - * - closed. - * - * In a tree-like graph, every nod has out most one incoming and one out-going edge, - * and there are no cycles. In a closed graph, every node has exactly one out-going - * edge. This means that the leaves of the tree are all hyper-edges with no - * children. Such an edge represents a relation (nullary transformer) and thus - * a lower bound on its parent. The parameter root must be the root of this tree. - * - * If Solve returns LBool.False, this indicates success. The annotation of the tree - * has been updated to satisfy the upper bound at the root. - * - * If Solve returns LBool.True, this indicates a counterexample. For each edge, - * you can then call Eval to determine the values of symbols in the transformer formula. - * You can also call Empty on a node to determine if its value in the counterexample - * is the empty relation. - * - * \param root The root of the tree - * \param persist Number of context pops through which result should persist - * - * - */ - - lbool RPFP::Solve(Node *root, int persist) - { - timer_start("Solve"); - TermTree *tree = GetConstraintTree(root); - TermTree *interpolant = NULL; - TermTree *goals = NULL; - if(ls->need_goals) - goals = GetGoalTree(root); - ClearProofCore(); - - // if (dualModel != null) dualModel.Dispose(); - // if (dualLabels != null) dualLabels.Dispose(); - - timer_start("interpolate_tree"); - lbool res = ls_interpolate_tree(tree, interpolant, dualModel,goals,true); - timer_stop("interpolate_tree"); - if (res == l_false) { - DecodeTree(root, interpolant->getChildren()[0], persist); - delete interpolant; + else res = t; + return res; } - delete tree; - if(goals) - delete goals; - - timer_stop("Solve"); - return res; - } - - void RPFP::CollapseTermTreeRec(TermTree *root, TermTree *node){ - root->addTerm(node->getTerm()); - std::vector &cnsts = node->getTerms(); - for(unsigned i = 0; i < cnsts.size(); i++) - root->addTerm(cnsts[i]); - std::vector &chs = node->getChildren(); - for(unsigned i = 0; i < chs.size(); i++){ - CollapseTermTreeRec(root,chs[i]); - } - } - - TermTree *RPFP::CollapseTermTree(TermTree *node){ - std::vector &chs = node->getChildren(); - for(unsigned i = 0; i < chs.size(); i++) - CollapseTermTreeRec(node,chs[i]); - for(unsigned i = 0; i < chs.size(); i++) - delete chs[i]; - chs.clear(); - return node; - } - - lbool RPFP::SolveSingleNode(Node *root, Node *node) - { - timer_start("Solve"); - TermTree *tree = CollapseTermTree(GetConstraintTree(root,node)); - tree->getChildren().push_back(CollapseTermTree(ToTermTree(node))); - TermTree *interpolant = NULL; - ClearProofCore(); - - timer_start("interpolate_tree"); - lbool res = ls_interpolate_tree(tree, interpolant, dualModel,0,true); - timer_stop("interpolate_tree"); - if (res == l_false) { - DecodeTree(node, interpolant->getChildren()[0], 0); - delete interpolant; + Z3User::Term Z3User::RemoveRedundancy(const Term &t){ + hash_map memo; + hash_map smemo; + return RemoveRedundancyRec(memo,smemo,t); } - delete tree; - timer_stop("Solve"); - return res; - } - - /** Get the constraint tree (but don't solve it) */ - - TermTree *RPFP::GetConstraintTree(Node *root, Node *skip_descendant) - { - return AddUpperBound(root, ToTermTree(root,skip_descendant)); - } - - /** Dispose of the dual model (counterexample) if there is one. */ - - void RPFP::DisposeDualModel() - { - dualModel = model(ctx,NULL); - } - - RPFP::Term RPFP::UnderapproxFlag(Node *n){ - expr flag = ctx.constant((std::string("@under") + string_of_int(n->number)).c_str(), ctx.bool_sort()); - underapprox_flag_rev[flag] = n; - return flag; - } - - RPFP::Node *RPFP::UnderapproxFlagRev(const Term &flag){ - return underapprox_flag_rev[flag]; - } - - /** Check satisfiability of asserted edges and nodes. Same functionality as - * Solve, except no primal solution (interpolant) is generated in the unsat case. - * The vector underapproxes gives the set of node underapproximations to be enforced - * (assuming these were conditionally asserted by AssertEdge). - * - */ - - check_result RPFP::Check(Node *root, std::vector underapproxes, std::vector *underapprox_core) { - timer_start("Check"); - ClearProofCore(); - // if (dualModel != null) dualModel.Dispose(); - check_result res; - if (!underapproxes.size()) - res = slvr_check(); - else { - std::vector us(underapproxes.size()); - for (unsigned i = 0; i < underapproxes.size(); i++) - us[i] = UnderapproxFlag(underapproxes[i]); - slvr_check(); // TODO: no idea why I need to do this - if (underapprox_core) { - std::vector unsat_core(us.size()); - unsigned core_size = 0; - res = slvr_check(us.size(), &us[0], &core_size, &unsat_core[0]); - underapprox_core->resize(core_size); - for (unsigned i = 0; i < core_size; i++) - (*underapprox_core)[i] = UnderapproxFlagRev(unsat_core[i]); - } - else { - res = slvr_check(us.size(), &us[0]); - bool dump = false; - if (dump) { - std::vector cnsts; - // cnsts.push_back(axioms[0]); - cnsts.push_back(root->dual); - cnsts.push_back(root->Outgoing->dual); - ls->write_interpolation_problem("temp.smt", cnsts, std::vector()); - } - } - // check_result temp = slvr_check(); - } - dualModel = slvr().get_model(); - timer_stop("Check"); - return res; - } - - check_result RPFP::CheckUpdateModel(Node *root, std::vector assumps){ - // check_result temp1 = slvr_check(); // no idea why I need to do this - ClearProofCore(); - check_result res = slvr_check(assumps.size(),&assumps[0]); - model mod = slvr().get_model(); - if(!mod.null()) - dualModel = mod;; - return res; - } - - /** Determines the value in the counterexample of a symbol occuring in the transformer formula of - * a given edge. */ - - RPFP::Term RPFP::Eval(Edge *e, Term t) - { - Term tl = Localize(e, t); - return dualModel.eval(tl); - } - - /** Returns true if the given node is empty in the primal solution. For proecudure summaries, - this means that the procedure is not called in the current counter-model. */ - - bool RPFP::Empty(Node *p) - { - Term b; std::vector v; - RedVars(p, b, v); - // dualModel.show_internals(); - // std::cout << "b: " << b << std::endl; - expr bv = dualModel.eval(b); - // std::cout << "bv: " << bv << std::endl; - bool res = !eq(bv,ctx.bool_val(true)); - return res; - } - - RPFP::Term RPFP::EvalNode(Node *p) - { - Term b; std::vector v; - RedVars(p, b, v); - std::vector args; - for(unsigned i = 0; i < v.size(); i++) - args.push_back(dualModel.eval(v[i])); - return (p->Name)(args); - } - - void RPFP::EvalArrayTerm(const RPFP::Term &t, ArrayValue &res){ - if (t.is_app()) { - decl_kind k = t.decl().get_decl_kind(); - if (k == AsArray) { - func_decl fd = t.decl().get_func_decl_parameter(0); - func_interp r = dualModel.get_func_interp(fd); - int num = r.num_entries(); - res.defined = true; - for (int i = 0; i < num; i++) { - expr arg = r.get_arg(i, 0); - expr value = r.get_value(i); - res.entries[arg] = value; - } - res.def_val = r.else_value(); - return; - } - else if (k == Store) { - EvalArrayTerm(t.arg(0), res); - if (!res.defined)return; - expr addr = t.arg(1); - expr val = t.arg(2); - if (addr.is_numeral() && val.is_numeral()) { - if (eq(val, res.def_val)) - res.entries.erase(addr); - else - res.entries[addr] = val; - } - else - res.defined = false; - return; - } - } - res.defined = false; - } - - int eae_count = 0; - - RPFP::Term RPFP::EvalArrayEquality(const RPFP::Term &f) { - ArrayValue lhs, rhs; - eae_count++; - EvalArrayTerm(f.arg(0), lhs); - EvalArrayTerm(f.arg(1), rhs); - if (lhs.defined && rhs.defined) { - if (eq(lhs.def_val, rhs.def_val)) - if (lhs.entries == rhs.entries) - return ctx.bool_val(true); - return ctx.bool_val(false); - } - return f; - } - - /** Compute truth values of all boolean subterms in current model. - Assumes formulas has been simplified by Z3, so only boolean ops - ands and, or, not. Returns result in memo. - */ - - int RPFP::SubtermTruth(hash_map &memo, const Term &f) { - if (memo.find(f) != memo.end()) { - return memo[f]; - } - int res; - if (f.is_app()) { - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if (k == Implies) { - res = SubtermTruth(memo, !f.arg(0) || f.arg(1)); - goto done; - } - if (k == And) { - res = 1; - for (int i = 0; i < nargs; i++) { - int ar = SubtermTruth(memo, f.arg(i)); - if (ar == 0) { - res = 0; - goto done; - } - if (ar == 2)res = 2; - } - goto done; - } - else if (k == Or) { - res = 0; - for (int i = 0; i < nargs; i++) { - int ar = SubtermTruth(memo, f.arg(i)); - if (ar == 1) { - res = 1; - goto done; - } - if (ar == 2)res = 2; - } - goto done; - } - else if (k == Not) { - int ar = SubtermTruth(memo, f.arg(0)); - res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); - goto done; - } - } + Z3User::Term Z3User::AdjustQuantifiers(const Term &t) { - bool pos; std::vector names; - if (f.is_label(pos, names)) { - res = SubtermTruth(memo, f.arg(0)); - goto done; - } + if(t.is_quantifier() || (t.is_app() && t.has_quantifiers())) + return t.qe_lite(); + return t; } - { - expr bv = dualModel.eval(f); - if (bv.is_app() && bv.decl().get_decl_kind() == Equal && - bv.arg(0).is_array()) { - bv = EvalArrayEquality(bv); - } - // Hack!!!! array equalities can occur negatively! - if (bv.is_app() && bv.decl().get_decl_kind() == Not && - bv.arg(0).decl().get_decl_kind() == Equal && - bv.arg(0).arg(0).is_array()) { - bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); - } - if (eq(bv, ctx.bool_val(true))) - res = 1; - else if (eq(bv, ctx.bool_val(false))) - res = 0; - else - res = 2; - } -done: - memo[f] = res; - return res; - } - int RPFP::EvalTruth(hash_map &memo, Edge *e, const Term &f){ - Term tl = Localize(e, f); - return SubtermTruth(memo,tl); - } + Z3User::Term Z3User::IneqToEqRec(hash_map &memo, const Term &t) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + args.push_back(IneqToEqRec(memo, t.arg(i))); - /** Compute truth values of all boolean subterms in current model. - Assumes formulas has been simplified by Z3, so only boolean ops - ands and, or, not. Returns result in memo. - */ - -#if 0 - int RPFP::GetLabelsRec(hash_map *memo, const Term &f, std::vector &labels, bool labpos){ - if(memo[labpos].find(f) != memo[labpos].end()){ - return memo[labpos][f]; - } - int res; - if(f.is_app()){ - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if(k == Implies){ - res = GetLabelsRec(memo,f.arg(1) || !f.arg(0), labels, labpos); - goto done; - } - if(k == And) { - res = 1; - for(int i = 0; i < nargs; i++){ - int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); - if(ar == 0){ - res = 0; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Or) { - res = 0; - for(int i = 0; i < nargs; i++){ - int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); - if(ar == 1){ - res = 1; - goto done; - } - if(ar == 2)res = 2; - } - goto done; - } - else if(k == Not) { - int ar = GetLabelsRec(memo,f.arg(0), labels, !labpos); - res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); - goto done; - } - } - { - bool pos; std::vector names; - if(f.is_label(pos,names)){ - res = GetLabelsRec(memo,f.arg(0), labels, labpos); - if(pos == labpos && res == (pos ? 1 : 0)) - for(unsigned i = 0; i < names.size(); i++) - labels.push_back(names[i]); - goto done; - } - } - { - expr bv = dualModel.eval(f); - if(bv.is_app() && bv.decl().get_decl_kind() == Equal && - bv.arg(0).is_array()){ - bv = EvalArrayEquality(bv); - } - // Hack!!!! array equalities can occur negatively! - if(bv.is_app() && bv.decl().get_decl_kind() == Not && - bv.arg(0).decl().get_decl_kind() == Equal && - bv.arg(0).arg(0).is_array()){ - bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); - } - if(eq(bv,ctx.bool_val(true))) - res = 1; - else if(eq(bv,ctx.bool_val(false))) - res = 0; - else - res = 2; - } -done: - memo[labpos][f] = res; - return res; - } -#endif - - void RPFP::GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, - hash_set *done, bool truth) { - if (done[truth].find(f) != done[truth].end()) - return; /* already processed */ - if (f.is_app()) { - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if (k == Implies) { - GetLabelsRec(memo, f.arg(1) || !f.arg(0), labels, done, truth); - goto done; - } - if (k == Iff) { - int b = SubtermTruth(memo, f.arg(0)); - if (b == 2) - throw "disaster in GetLabelsRec"; - GetLabelsRec(memo, f.arg(1), labels, done, truth ? b : !b); - goto done; - } - if (truth ? k == And : k == Or) { - for (int i = 0; i < nargs; i++) - GetLabelsRec(memo, f.arg(i), labels, done, truth); - goto done; - } - if (truth ? k == Or : k == And) { - for (int i = 0; i < nargs; i++) { - Term a = f.arg(i); - timer_start("SubtermTruth"); - int b = SubtermTruth(memo, a); - timer_stop("SubtermTruth"); - if (truth ? (b == 1) : (b == 0)) { - GetLabelsRec(memo, a, labels, done, truth); - goto done; - } - } - /* Unreachable! */ - // throw "error in RPFP::GetLabelsRec"; - goto done; - } - else if (k == Not) { - GetLabelsRec(memo, f.arg(0), labels, done, !truth); - goto done; - } - else { - bool pos; std::vector names; - if (f.is_label(pos, names)) { - GetLabelsRec(memo, f.arg(0), labels, done, truth); - if (pos == truth) - for (unsigned i = 0; i < names.size(); i++) - labels.push_back(names[i]); - goto done; - } - } - } - done: - done[truth].insert(f); - } - - void RPFP::GetLabels(Edge *e, std::vector &labels){ - if(!e->map || e->map->labeled.null()) - return; - Term tl = Localize(e, e->map->labeled); - hash_map memo; - hash_set done[2]; - GetLabelsRec(memo,tl,labels,done,true); - } - -#ifdef Z3OPS - static Z3_subterm_truth *stt; -#endif - - int ir_count = 0; - - void RPFP::ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set *done, bool truth, hash_set &dont_cares) { - if (done[truth].find(f) != done[truth].end()) - return; /* already processed */ -#if 0 - int this_count = ir_count++; - if(this_count == 50092) - std::cout << "foo!\n"; -#endif - if (f.is_app()) { - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if (k == Implies) { - ImplicantRed(memo, f.arg(1) || !f.arg(0), lits, done, truth, dont_cares); - goto done; - } - if (k == Iff) { - int b = SubtermTruth(memo, f.arg(0)); - if (b == 2) - throw "disaster in ImplicantRed"; - ImplicantRed(memo, f.arg(1), lits, done, truth ? b : !b, dont_cares); - goto done; - } - if (truth ? k == And : k == Or) { - for (int i = 0; i < nargs; i++) - ImplicantRed(memo, f.arg(i), lits, done, truth, dont_cares); - goto done; - } - if (truth ? k == Or : k == And) { - for (int i = 0; i < nargs; i++) { - Term a = f.arg(i); -#if 0 - if(i == nargs - 1){ // last chance! - ImplicantRed(memo,a,lits,done,truth,dont_cares); - goto done; - } -#endif - timer_start("SubtermTruth"); -#ifdef Z3OPS - bool b = stt->eval(a); -#else - int b = SubtermTruth(memo, a); -#endif - timer_stop("SubtermTruth"); - if (truth ? (b == 1) : (b == 0)) { - ImplicantRed(memo, a, lits, done, truth, dont_cares); - goto done; - } - } - /* Unreachable! */ - // TODO: need to indicate this failure to caller - // std::cerr << "error in RPFP::ImplicantRed"; - goto done; - } - else if (k == Not) { - ImplicantRed(memo, f.arg(0), lits, done, !truth, dont_cares); - goto done; - } - } - { - if (dont_cares.find(f) == dont_cares.end()) { - expr rf = ResolveIte(memo, f, lits, done, dont_cares); - expr bv = truth ? rf : !rf; - lits.push_back(bv); - } - } -done: - done[truth].insert(f); - } - - void RPFP::ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, - hash_set &done, hash_set &dont_cares, bool extensional) { - if (done.find(f) != done.end()) - return; /* already processed */ - if (f.is_app()) { - int nargs = f.num_args(); - decl_kind k = f.decl().get_decl_kind(); - if (k == Implies || k == Iff || k == And || k == Or || k == Not) { - for (int i = 0; i < nargs; i++) - ImplicantFullRed(memo, f.arg(i), lits, done, dont_cares, extensional); - goto done; - } - } - { - if (dont_cares.find(f) == dont_cares.end()) { - int b = SubtermTruth(memo, f); - if (b != 0 && b != 1) goto done; - if (f.is_app() && f.decl().get_decl_kind() == Equal && f.arg(0).is_array()) { - if (b == 1 && !extensional) { - expr x = dualModel.eval(f.arg(0)); expr y = dualModel.eval(f.arg(1)); - if (!eq(x, y)) - b = 0; + decl_kind k = f.get_decl_kind(); + if (k == And) { + for (int i = 0; i < nargs - 1; i++) { + if ((args[i].is_app() && args[i].decl().get_decl_kind() == Geq && + args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Leq) + || + (args[i].is_app() && args[i].decl().get_decl_kind() == Leq && + args[i + 1].is_app() && args[i + 1].decl().get_decl_kind() == Geq)) + if (eq(args[i].arg(0), args[i + 1].arg(0)) && eq(args[i].arg(1), args[i + 1].arg(1))) { + args[i] = ctx.make(Equal, args[i].arg(0), args[i].arg(1)); + args[i + 1] = ctx.bool_val(true); + } } - if (b == 0) - goto done; } - expr bv = (b == 1) ? f : !f; - lits.push_back(bv); + res = f(args.size(), &args[0]); } - } -done: - done.insert(f); - } - - RPFP::Term RPFP::ResolveIte(hash_map &memo, const Term &t, std::vector &lits, - hash_set *done, hash_set &dont_cares) { - if (resolve_ite_memo.find(t) != resolve_ite_memo.end()) - return resolve_ite_memo[t]; - Term res; - if (t.is_app()) { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if (f.get_decl_kind() == Ite) { - timer_start("SubtermTruth"); -#ifdef Z3OPS - bool sel = stt->eval(t.arg(0)); -#else - int xval = SubtermTruth(memo, t.arg(0)); - bool sel; - if (xval == 0)sel = false; - else if (xval == 1)sel = true; - else - throw "unresolved ite in model"; -#endif - timer_stop("SubtermTruth"); - ImplicantRed(memo, t.arg(0), lits, done, sel, dont_cares); - res = ResolveIte(memo, t.arg(sel ? 1 : 2), lits, done, dont_cares); - } - else { - for (int i = 0; i < nargs; i++) - args.push_back(ResolveIte(memo, t.arg(i), lits, done, dont_cares)); - res = f(args.size(), &args[0]); - } - } - else res = t; - resolve_ite_memo[t] = res; - return res; - } - - RPFP::Term RPFP::ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts) { - std::pair foo(t, expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if (bar.second) { - if (t.is_app()) { - int nargs = t.num_args(); - std::vector args; - if (t.decl().get_decl_kind() == Equal) { - expr lhs = t.arg(0); - expr rhs = t.arg(1); - if (rhs.decl().get_decl_kind() == Ite) { - expr rhs_args[3]; - lhs = ElimIteRec(memo, lhs, cnsts); - for (int i = 0; i < 3; i++) - rhs_args[i] = ElimIteRec(memo, rhs.arg(i), cnsts); - res = (rhs_args[0] && (lhs == rhs_args[1])) || ((!rhs_args[0]) && (lhs == rhs_args[2])); - goto done; - } - } - if (t.decl().get_decl_kind() == Ite) { - func_decl sym = ctx.fresh_func_decl("@ite", t.get_sort()); - res = sym(); - cnsts.push_back(ElimIteRec(memo, ctx.make(Equal, res, t), cnsts)); - } - else { - for (int i = 0; i < nargs; i++) - args.push_back(ElimIteRec(memo, t.arg(i), cnsts)); - res = t.decl()(args.size(), &args[0]); - } - } - else if (t.is_quantifier()) - res = clone_quantifier(t, ElimIteRec(memo, t.body(), cnsts)); - else - res = t; - } - done: - return res; - } - - RPFP::Term RPFP::ElimIte(const Term &t){ - hash_map memo; - std::vector cnsts; - expr res = ElimIteRec(memo,t,cnsts); - if(!cnsts.empty()){ - cnsts.push_back(res); - res = ctx.make(And,cnsts); - } - return res; - } - - void RPFP::Implicant(hash_map &memo, const Term &f, std::vector &lits, hash_set &dont_cares){ - hash_set done[2]; - ImplicantRed(memo,f,lits,done,true, dont_cares); - } - - - /** Underapproximate a formula using current counterexample. */ - - RPFP::Term RPFP::UnderapproxFormula(const Term &f, hash_set &dont_cares){ - /* first compute truth values of subterms */ - hash_map memo; - #ifdef Z3OPS - stt = Z3_mk_subterm_truth(ctx,dualModel); - #endif - // SubtermTruth(memo,f); - /* now compute an implicant */ - std::vector lits; - Implicant(memo,f,lits, dont_cares); -#ifdef Z3OPS - delete stt; stt = 0; -#endif - /* return conjunction of literals */ - return conjoin(lits); - } - - RPFP::Term RPFP::UnderapproxFullFormula(const Term &f, bool extensional){ - hash_set dont_cares; - resolve_ite_memo.clear(); - timer_start("UnderapproxFormula"); - /* first compute truth values of subterms */ - hash_map memo; - hash_set done; - std::vector lits; - ImplicantFullRed(memo,f,lits,done,dont_cares, extensional); - timer_stop("UnderapproxFormula"); - /* return conjunction of literals */ - return conjoin(lits); - } - - struct VariableProjector : Z3User { - - struct elim_cand { - Term var; - int sup; - Term val; - }; - - typedef expr Term; - - hash_set keep; - hash_map var_ord; - int num_vars; - std::vector elim_cands; - hash_map > sup_map; - hash_map elim_map; - std::vector ready_cands; - hash_map cand_map; - params simp_params; - - VariableProjector(Z3User &_user, std::vector &keep_vec) : - Z3User(_user), simp_params() { - num_vars = 0; - for (unsigned i = 0; i < keep_vec.size(); i++) { - keep.insert(keep_vec[i]); - var_ord[keep_vec[i]] = num_vars++; + else if (t.is_quantifier()) { + Term body = IneqToEqRec(memo, t.body()); + res = clone_quantifier(t, body); } - } - int VarNum(const Term &v) { - if (var_ord.find(v) == var_ord.end()) - var_ord[v] = num_vars++; - return var_ord[v]; + else res = t; + return res; } - bool IsVar(const Term &t){ - return t.is_app() && t.num_args() == 0 && t.decl().get_decl_kind() == Uninterpreted; + Z3User::Term Z3User::IneqToEq(const Term &t){ + hash_map memo; + return IneqToEqRec(memo,t); } - - bool IsPropLit(const Term &t, Term &a) { - if (IsVar(t)) { - a = t; - return true; - } - else if (t.is_app() && t.decl().get_decl_kind() == Not) - return IsPropLit(t.arg(0), a); - return false; - } - - void CountOtherVarsRec(hash_map &memo, - const Term &t, - int id, - int &count) { - std::pair foo(t, 0); - std::pair::iterator, bool> bar = memo.insert(foo); - // int &res = bar.first->second; - if (!bar.second) return; + + Z3User::Term Z3User::SubstRecHide(hash_map &memo, const Term &t, int number) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (!bar.second) return res; if (t.is_app()) { func_decl f = t.decl(); std::vector args; int nargs = t.num_args(); if (nargs == 0 && f.get_decl_kind() == Uninterpreted) { - if (cand_map.find(t) != cand_map.end()) { - count++; - sup_map[t].push_back(id); - } + std::string name = std::string("@q_") + t.decl().name().str() + "_" + string_of_int(number); + res = ctx.constant(name.c_str(), t.get_sort()); + return res; } for (int i = 0; i < nargs; i++) - CountOtherVarsRec(memo, t.arg(i), id, count); + args.push_back(SubstRec(memo, t.arg(i))); + res = f(args.size(), &args[0]); } else if (t.is_quantifier()) - CountOtherVarsRec(memo, t.body(), id, count); - } - - void NewElimCand(const Term &lhs, const Term &rhs) { - if (debug_gauss) { - std::cout << "mapping " << lhs << " to " << rhs << std::endl; - } - elim_cand cand; - cand.var = lhs; - cand.sup = 0; - cand.val = rhs; - elim_cands.push_back(cand); - cand_map[lhs] = elim_cands.size() - 1; + res = CloneQuantifier(t, SubstRec(memo, t.body())); + else res = t; + return res; } - void MakeElimCand(const Term &lhs, const Term &rhs) { - if (eq(lhs, rhs)) + RPFP::Term RPFP::SubstParams(const std::vector &from, + const std::vector &to, const Term &t) { + hash_map memo; + bool some_diff = false; + for (unsigned i = 0; i < from.size(); i++) + if (i < to.size() && !eq(from[i], to[i])) { + memo[from[i]] = to[i]; + some_diff = true; + } + return some_diff ? SubstRec(memo, t) : t; + } + + RPFP::Term RPFP::SubstParamsNoCapture(const std::vector &from, + const std::vector &to, const Term &t) { + hash_map memo; + bool some_diff = false; + for (unsigned i = 0; i < from.size(); i++) + if (i < to.size() && !eq(from[i], to[i])) { + memo[from[i]] = to[i]; + // if the new param is not being mapped to anything else, we need to rename it to prevent capture + // note, if the new param *is* mapped later in the list, it will override this substitution + const expr &w = to[i]; + if (memo.find(w) == memo.end()) { + std::string old_name = w.decl().name().str(); + func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); + expr y = fresh(); + memo[w] = y; + } + some_diff = true; + } + return some_diff ? SubstRec(memo, t) : t; + } + + + + RPFP::Transformer RPFP::Fuse(const std::vector &trs) { + assert(!trs.empty()); + const std::vector ¶ms = trs[0]->IndParams; + std::vector fmlas(trs.size()); + fmlas[0] = trs[0]->Formula; + for (unsigned i = 1; i < trs.size(); i++) + fmlas[i] = SubstParamsNoCapture(trs[i]->IndParams, params, trs[i]->Formula); + std::vector rel_params = trs[0]->RelParams; + for (unsigned i = 1; i < trs.size(); i++) { + const std::vector ¶ms2 = trs[i]->RelParams; + hash_map map; + for (unsigned j = 0; j < params2.size(); j++) { + func_decl rel = RenumberPred(params2[j], rel_params.size()); + rel_params.push_back(rel); + map[params2[j]] = rel; + } + hash_map memo; + fmlas[i] = SubstRec(memo, map, fmlas[i]); + } + return Transformer(rel_params, params, ctx.make(Or, fmlas), trs[0]->owner); + } + + + void Z3User::Strengthen(Term &x, const Term &y) + { + if (eq(x,ctx.bool_val(true))) + x = y; + else + x = x && y; + } + + void RPFP::SetAnnotation(Node *root, const expr &t){ + hash_map memo; + Term b; + std::vector v; + RedVars(root, b, v); + memo[b] = ctx.bool_val(true); + for (unsigned i = 0; i < v.size(); i++) + memo[v[i]] = root->Annotation.IndParams[i]; + Term annot = SubstRec(memo, t); + // Strengthen(ref root.Annotation.Formula, annot); + root->Annotation.Formula = annot; + } + + void RPFP::DecodeTree(Node *root, TermTree *interp, int persist) { + std::vector &ic = interp->getChildren(); + if (ic.size() > 0) { + std::vector &nc = root->Outgoing->Children; + for (unsigned i = 0; i < nc.size(); i++) + DecodeTree(nc[i], ic[i], persist); + } + SetAnnotation(root, interp->getTerm()); +#if 0 + if(persist != 0) + Z3_persist_ast(ctx,root->Annotation.Formula,persist); +#endif + } + + RPFP::Term RPFP::GetUpperBound(Node *n) + { + // TODO: cache this + Term b(ctx); std::vector v; + RedVars(n, b, v); + hash_map memo; + for (unsigned int i = 0; i < v.size(); i++) + memo[n->Bound.IndParams[i]] = v[i]; + Term cnst = SubstRec(memo, n->Bound.Formula); + return b && !cnst; + } + + RPFP::Term RPFP::GetAnnotation(Node *n) + { + if(eq(n->Annotation.Formula,ctx.bool_val(true))) + return n->Annotation.Formula; + // TODO: cache this + Term b(ctx); std::vector v; + RedVars(n, b, v); + hash_map memo; + for (unsigned i = 0; i < v.size(); i++) + memo[n->Annotation.IndParams[i]] = v[i]; + Term cnst = SubstRec(memo, n->Annotation.Formula); + return !b || cnst; + } + + RPFP::Term RPFP::GetUnderapprox(Node *n) + { + // TODO: cache this + Term b(ctx); std::vector v; + RedVars(n, b, v); + hash_map memo; + for (unsigned i = 0; i < v.size(); i++) + memo[n->Underapprox.IndParams[i]] = v[i]; + Term cnst = SubstRecHide(memo, n->Underapprox.Formula, n->number); + return !b || cnst; + } + + TermTree *RPFP::AddUpperBound(Node *root, TermTree *t) + { + Term f = !((ast)(root->dual)) ? ctx.bool_val(true) : root->dual; + std::vector c(1); c[0] = t; + return new TermTree(f, c); + } + +#if 0 + void RPFP::WriteInterps(System.IO.StreamWriter f, TermTree t) + { + foreach (var c in t.getChildren()) + WriteInterps(f, c); + f.WriteLine(t.getTerm()); + } +#endif + + + expr RPFP::GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox) { + if (e->dual.null()) { + timer_start("ReducedDualEdge"); + e->dual = ReducedDualEdge(e); + timer_stop("ReducedDualEdge"); + timer_start("getting children"); + if (underapprox) { + std::vector cus(e->Children.size()); + for (unsigned i = 0; i < e->Children.size(); i++) + cus[i] = !UnderapproxFlag(e->Children[i]) || GetUnderapprox(e->Children[i]); + expr cnst = conjoin(cus); + e->dual = e->dual && cnst; + } + timer_stop("getting children"); + timer_start("Persisting"); + std::list::reverse_iterator it = stack.rbegin(); + for (int i = 0; i < persist && it != stack.rend(); i++) + it++; + if (it != stack.rend()) + it->edges.push_back(e); + timer_stop("Persisting"); + //Console.WriteLine("{0}", cnst); + } + return e->dual; + } + + /** For incremental solving, asserts the constraint associated + * with this edge in the SMT context. If this edge is removed, + * you must pop the context accordingly. The second argument is + * the number of pushes we are inside. The constraint formula + * will survive "persist" pops of the context. If you plan + * to reassert the edge after popping the context once, + * you can save time re-constructing the formula by setting + * "persist" to one. If you set "persist" too high, however, + * you could have a memory leak. + * + * The flag "with children" causes the annotations of the children + * to be asserted. The flag underapprox causes the underapproximations + * of the children to be asserted *conditionally*. See Check() on + * how to actually enforce these constraints. + * + */ + + void RPFP::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) { + if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) return; - if (!IsVar(lhs)) { - if (IsVar(rhs)) { + expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); + timer_start("solver add"); + slvr_add(e->dual); + timer_stop("solver add"); + if (with_children) + for (unsigned i = 0; i < e->Children.size(); i++) + ConstrainParent(e, e->Children[i]); + } + + +#ifdef LIMIT_STACK_WEIGHT + void RPFP_caching::AssertEdge(Edge *e, int persist, bool with_children, bool underapprox) + { + unsigned old_new_alits = new_alits.size(); + if(eq(e->F.Formula,ctx.bool_val(true)) && (!with_children || e->Children.empty())) + return; + expr fmla = GetEdgeFormula(e, persist, with_children, underapprox); + timer_start("solver add"); + slvr_add(e->dual); + timer_stop("solver add"); + if(old_new_alits < new_alits.size()) + weight_added.val++; + if(with_children) + for(unsigned i = 0; i < e->Children.size(); i++) + ConstrainParent(e,e->Children[i]); + } +#endif + + // caching verion of above + void RPFP_caching::AssertEdgeCache(Edge *e, std::vector &lits, bool with_children) { + if (eq(e->F.Formula, ctx.bool_val(true)) && (!with_children || e->Children.empty())) + return; + expr fmla = GetEdgeFormula(e, 0, with_children, false); + GetAssumptionLits(fmla, lits); + if (with_children) + for (unsigned i = 0; i < e->Children.size(); i++) + ConstrainParentCache(e, e->Children[i], lits); + } + + void RPFP::slvr_add(const expr &e){ + slvr().add(e); + } + + void RPFP_caching::slvr_add(const expr &e){ + GetAssumptionLits(e,alit_stack); + } + + void RPFP::slvr_pop(int i){ + slvr().pop(i); + } + + void RPFP::slvr_push(){ + slvr().push(); + } + + void RPFP_caching::slvr_pop(int i){ + for(int j = 0; j < i; j++){ +#ifdef LIMIT_STACK_WEIGHT + if(alit_stack_sizes.empty()){ + if(big_stack.empty()) + throw "stack underflow"; + for(unsigned k = 0; k < new_alits.size(); k++){ + if(AssumptionLits.find(new_alits[k]) == AssumptionLits.end()) + throw "foo!"; + AssumptionLits.erase(new_alits[k]); + } + big_stack_entry &bsb = big_stack.back(); + bsb.alit_stack_sizes.swap(alit_stack_sizes); + bsb.alit_stack.swap(alit_stack); + bsb.new_alits.swap(new_alits); + bsb.weight_added.swap(weight_added); + big_stack.pop_back(); + slvr().pop(1); + continue; + } +#endif + alit_stack.resize(alit_stack_sizes.back()); + alit_stack_sizes.pop_back(); + } + } + + void RPFP_caching::slvr_push(){ +#ifdef LIMIT_STACK_WEIGHT + if(weight_added.val > LIMIT_STACK_WEIGHT){ + big_stack.resize(big_stack.size()+1); + big_stack_entry &bsb = big_stack.back(); + bsb.alit_stack_sizes.swap(alit_stack_sizes); + bsb.alit_stack.swap(alit_stack); + bsb.new_alits.swap(new_alits); + bsb.weight_added.swap(weight_added); + slvr().push(); + for(unsigned i = 0; i < bsb.alit_stack.size(); i++) + slvr().add(bsb.alit_stack[i]); + return; + } +#endif + alit_stack_sizes.push_back(alit_stack.size()); + } + + check_result RPFP::slvr_check(unsigned n, expr * const assumptions, unsigned *core_size, expr *core){ + return slvr().check(n, assumptions, core_size, core); + } + + check_result RPFP_caching::slvr_check(unsigned n, expr * const assumptions, unsigned *core_size, expr *core){ + unsigned oldsiz = alit_stack.size(); + if(n && assumptions) + std::copy(assumptions,assumptions+n,std::inserter(alit_stack,alit_stack.end())); + check_result res; + if (core_size && core) { + std::vector full_core(alit_stack.size()), core1(n); + std::copy(assumptions, assumptions + n, core1.begin()); + res = slvr().check(alit_stack.size(), &alit_stack[0], core_size, &full_core[0]); + full_core.resize(*core_size); + if (res == unsat) { + FilterCore(core1, full_core); + *core_size = core1.size(); + std::copy(core1.begin(), core1.end(), core); + } + } + else + res = slvr().check(alit_stack.size(), &alit_stack[0]); + alit_stack.resize(oldsiz); + return res; + } + + lbool RPFP::ls_interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals, + bool weak) { + return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); + } + + lbool RPFP_caching::ls_interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + TermTree *goals, + bool weak) { + GetTermTreeAssertionLiterals(assumptions); + return ls->interpolate_tree(assumptions, interpolants, _model, goals, weak); + } + + void RPFP_caching::GetTermTreeAssertionLiteralsRec(TermTree *assumptions){ + std::vector alits; + hash_map map; + GetAssumptionLits(assumptions->getTerm(),alits,&map); + std::vector &ts = assumptions->getTerms(); + for(unsigned i = 0; i < ts.size(); i++) + GetAssumptionLits(ts[i],alits,&map); + assumptions->setTerm(ctx.bool_val(true)); + ts = alits; + for(unsigned i = 0; i < alits.size(); i++) + ts.push_back(ctx.make(Implies,alits[i],map[alits[i]])); + for(unsigned i = 0; i < assumptions->getChildren().size(); i++) + GetTermTreeAssertionLiterals(assumptions->getChildren()[i]); + return; + } + + void RPFP_caching::GetTermTreeAssertionLiterals(TermTree *assumptions) { + // optimize binary case + if (assumptions->getChildren().size() == 1 + && assumptions->getChildren()[0]->getChildren().size() == 0) { + hash_map map; + TermTree *child = assumptions->getChildren()[0]; + std::vector dummy; + GetAssumptionLits(child->getTerm(), dummy, &map); + std::vector &ts = child->getTerms(); + for (unsigned i = 0; i < ts.size(); i++) + GetAssumptionLits(ts[i], dummy, &map); + std::vector assumps; + slvr().get_proof().get_assumptions(assumps); + if (!proof_core) { // save the proof core for later use + proof_core = new hash_set < ast > ; + for (unsigned i = 0; i < assumps.size(); i++) + proof_core->insert(assumps[i]); + } + std::vector *cnsts[2] = { &child->getTerms(), &assumptions->getTerms() }; + for (unsigned i = 0; i < assumps.size(); i++) { + expr &as = assumps[i]; + expr alit = (as.is_app() && as.decl().get_decl_kind() == Implies) ? as.arg(0) : as; + bool isA = map.find(alit) != map.end(); + cnsts[isA ? 0 : 1]->push_back(as); + } + } + else + GetTermTreeAssertionLiteralsRec(assumptions); + } + + void RPFP::AddToProofCore(hash_set &core){ + std::vector assumps; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++) + core.insert(assumps[i]); + } + + void RPFP::ComputeProofCore(){ + if(!proof_core){ + proof_core = new hash_set; + AddToProofCore(*proof_core); + } + } + + + void RPFP_caching::GetAssumptionLits(const expr &fmla, std::vector &lits, hash_map *opt_map) { + std::vector conjs; + CollectConjuncts(fmla, conjs); + for (unsigned i = 0; i < conjs.size(); i++) { + const expr &conj = conjs[i]; + std::pair foo(conj, expr(ctx)); + std::pair::iterator, bool> bar = AssumptionLits.insert(foo); + Term &res = bar.first->second; + if (bar.second) { + func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); + res = pred(); +#ifdef LIMIT_STACK_WEIGHT + new_alits.push_back(conj); +#endif + slvr().add(ctx.make(Implies, res, conj)); + // std::cout << res << ": " << conj << "\n"; + } + if (opt_map) + (*opt_map)[res] = conj; + lits.push_back(res); + } + } + + void RPFP::ConstrainParent(Edge *parent, Node *child){ + ConstrainEdgeLocalized(parent,GetAnnotation(child)); + } + + void RPFP_caching::ConstrainParentCache(Edge *parent, Node *child, std::vector &lits){ + ConstrainEdgeLocalizedCache(parent,GetAnnotation(child),lits); + } + + + /** For incremental solving, asserts the negation of the upper bound associated + * with a node. + * */ + + void RPFP::AssertNode(Node *n) + { + if (n->dual.null()) { + n->dual = GetUpperBound(n); + stack.back().nodes.push_back(n); + slvr_add(n->dual); + } + } + + // caching version of above + void RPFP_caching::AssertNodeCache(Node *n, std::vector lits){ + if (n->dual.null()) { + n->dual = GetUpperBound(n); + stack.back().nodes.push_back(n); + GetAssumptionLits(n->dual, lits); + } + } + + /** Clone another RPFP into this one, keeping a map */ + void RPFP_caching::Clone(RPFP *other) { +#if 0 + for(unsigned i = 0; i < other->nodes.size(); i++) + NodeCloneMap[other->nodes[i]] = CloneNode(other->nodes[i]); +#endif + for (unsigned i = 0; i < other->edges.size(); i++) { + Edge *edge = other->edges[i]; + Node *parent = CloneNode(edge->Parent); + std::vector cs; + for (unsigned j = 0; j < edge->Children.size(); j++) + // cs.push_back(NodeCloneMap[edge->Children[j]]); + cs.push_back(CloneNode(edge->Children[j])); + EdgeCloneMap[edge] = CreateEdge(parent, edge->F, cs); + } + } + + /** Get the clone of a node */ + RPFP::Node *RPFP_caching::GetNodeClone(Node *other_node){ + return NodeCloneMap[other_node]; + } + + /** Get the clone of an edge */ + RPFP::Edge *RPFP_caching::GetEdgeClone(Edge *other_edge){ + return EdgeCloneMap[other_edge]; + } + + /** check assumption lits, and return core */ + check_result RPFP_caching::CheckCore(const std::vector &assumps, std::vector &core){ + core.resize(assumps.size()); + unsigned core_size; + check_result res = slvr().check(assumps.size(),(expr *)&assumps[0],&core_size,&core[0]); + if(res == unsat) + core.resize(core_size); + else + core.clear(); + return res; + } + + + /** Assert a constraint on an edge in the SMT context. + */ + + void RPFP::ConstrainEdge(Edge *e, const Term &t) + { + Term tl = Localize(e, t); + ConstrainEdgeLocalized(e,tl); + } + + void RPFP::ConstrainEdgeLocalized(Edge *e, const Term &tl) + { + e->constraints.push_back(tl); + stack.back().constraints.push_back(std::pair(e,tl)); + slvr_add(tl); + } + + void RPFP_caching::ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector &lits) + { + e->constraints.push_back(tl); + stack.back().constraints.push_back(std::pair(e,tl)); + GetAssumptionLits(tl,lits); + } + + + /** Declare a constant in the background theory. */ + + void RPFP::DeclareConstant(const FuncDecl &f){ + ls->declare_constant(f); + } + + /** Assert a background axiom. Background axioms can be used to provide the + * theory of auxilliary functions or relations. All symbols appearing in + * background axioms are considered global, and may appear in both transformer + * and relational solutions. Semantically, a solution to the RPFP gives + * an interpretation of the unknown relations for each interpretation of the + * auxilliary symbols that is consistent with the axioms. Axioms should be + * asserted before any calls to Push. They cannot be de-asserted by Pop. */ + + void RPFP::AssertAxiom(const Term &t) + { + ls->assert_axiom(t); + axioms.push_back(t); // for printing only + } + +#if 0 + /** Do not call this. */ + + void RPFP::RemoveAxiom(const Term &t) + { + slvr().RemoveInterpolationAxiom(t); + } +#endif + + /** Solve an RPFP graph. This means either strengthen the annotation + * so that the bound at the given root node is satisfied, or + * show that this cannot be done by giving a dual solution + * (i.e., a counterexample). + * + * In the current implementation, this only works for graphs that + * are: + * - tree-like + * + * - closed. + * + * In a tree-like graph, every nod has out most one incoming and one out-going edge, + * and there are no cycles. In a closed graph, every node has exactly one out-going + * edge. This means that the leaves of the tree are all hyper-edges with no + * children. Such an edge represents a relation (nullary transformer) and thus + * a lower bound on its parent. The parameter root must be the root of this tree. + * + * If Solve returns LBool.False, this indicates success. The annotation of the tree + * has been updated to satisfy the upper bound at the root. + * + * If Solve returns LBool.True, this indicates a counterexample. For each edge, + * you can then call Eval to determine the values of symbols in the transformer formula. + * You can also call Empty on a node to determine if its value in the counterexample + * is the empty relation. + * + * \param root The root of the tree + * \param persist Number of context pops through which result should persist + * + * + */ + + lbool RPFP::Solve(Node *root, int persist) + { + timer_start("Solve"); + TermTree *tree = GetConstraintTree(root); + TermTree *interpolant = NULL; + TermTree *goals = NULL; + if(ls->need_goals) + goals = GetGoalTree(root); + ClearProofCore(); + + // if (dualModel != null) dualModel.Dispose(); + // if (dualLabels != null) dualLabels.Dispose(); + + timer_start("interpolate_tree"); + lbool res = ls_interpolate_tree(tree, interpolant, dualModel,goals,true); + timer_stop("interpolate_tree"); + if (res == l_false) { + DecodeTree(root, interpolant->getChildren()[0], persist); + delete interpolant; + } + + delete tree; + if(goals) + delete goals; + + timer_stop("Solve"); + return res; + } + + void RPFP::CollapseTermTreeRec(TermTree *root, TermTree *node){ + root->addTerm(node->getTerm()); + std::vector &cnsts = node->getTerms(); + for(unsigned i = 0; i < cnsts.size(); i++) + root->addTerm(cnsts[i]); + std::vector &chs = node->getChildren(); + for(unsigned i = 0; i < chs.size(); i++){ + CollapseTermTreeRec(root,chs[i]); + } + } + + TermTree *RPFP::CollapseTermTree(TermTree *node){ + std::vector &chs = node->getChildren(); + for(unsigned i = 0; i < chs.size(); i++) + CollapseTermTreeRec(node,chs[i]); + for(unsigned i = 0; i < chs.size(); i++) + delete chs[i]; + chs.clear(); + return node; + } + + lbool RPFP::SolveSingleNode(Node *root, Node *node) + { + timer_start("Solve"); + TermTree *tree = CollapseTermTree(GetConstraintTree(root,node)); + tree->getChildren().push_back(CollapseTermTree(ToTermTree(node))); + TermTree *interpolant = NULL; + ClearProofCore(); + + timer_start("interpolate_tree"); + lbool res = ls_interpolate_tree(tree, interpolant, dualModel,0,true); + timer_stop("interpolate_tree"); + if (res == l_false) { + DecodeTree(node, interpolant->getChildren()[0], 0); + delete interpolant; + } + + delete tree; + timer_stop("Solve"); + return res; + } + + /** Get the constraint tree (but don't solve it) */ + + TermTree *RPFP::GetConstraintTree(Node *root, Node *skip_descendant) + { + return AddUpperBound(root, ToTermTree(root,skip_descendant)); + } + + /** Dispose of the dual model (counterexample) if there is one. */ + + void RPFP::DisposeDualModel() + { + dualModel = model(ctx,NULL); + } + + RPFP::Term RPFP::UnderapproxFlag(Node *n){ + expr flag = ctx.constant((std::string("@under") + string_of_int(n->number)).c_str(), ctx.bool_sort()); + underapprox_flag_rev[flag] = n; + return flag; + } + + RPFP::Node *RPFP::UnderapproxFlagRev(const Term &flag){ + return underapprox_flag_rev[flag]; + } + + /** Check satisfiability of asserted edges and nodes. Same functionality as + * Solve, except no primal solution (interpolant) is generated in the unsat case. + * The vector underapproxes gives the set of node underapproximations to be enforced + * (assuming these were conditionally asserted by AssertEdge). + * + */ + + check_result RPFP::Check(Node *root, std::vector underapproxes, std::vector *underapprox_core) { + timer_start("Check"); + ClearProofCore(); + // if (dualModel != null) dualModel.Dispose(); + check_result res; + if (!underapproxes.size()) + res = slvr_check(); + else { + std::vector us(underapproxes.size()); + for (unsigned i = 0; i < underapproxes.size(); i++) + us[i] = UnderapproxFlag(underapproxes[i]); + slvr_check(); // TODO: no idea why I need to do this + if (underapprox_core) { + std::vector unsat_core(us.size()); + unsigned core_size = 0; + res = slvr_check(us.size(), &us[0], &core_size, &unsat_core[0]); + underapprox_core->resize(core_size); + for (unsigned i = 0; i < core_size; i++) + (*underapprox_core)[i] = UnderapproxFlagRev(unsat_core[i]); + } + else { + res = slvr_check(us.size(), &us[0]); + bool dump = false; + if (dump) { + std::vector cnsts; + // cnsts.push_back(axioms[0]); + cnsts.push_back(root->dual); + cnsts.push_back(root->Outgoing->dual); + ls->write_interpolation_problem("temp.smt", cnsts, std::vector()); + } + } + // check_result temp = slvr_check(); + } + dualModel = slvr().get_model(); + timer_stop("Check"); + return res; + } + + check_result RPFP::CheckUpdateModel(Node *root, std::vector assumps){ + // check_result temp1 = slvr_check(); // no idea why I need to do this + ClearProofCore(); + check_result res = slvr_check(assumps.size(),&assumps[0]); + model mod = slvr().get_model(); + if(!mod.null()) + dualModel = mod;; + return res; + } + + /** Determines the value in the counterexample of a symbol occuring in the transformer formula of + * a given edge. */ + + RPFP::Term RPFP::Eval(Edge *e, Term t) + { + Term tl = Localize(e, t); + return dualModel.eval(tl); + } + + /** Returns true if the given node is empty in the primal solution. For proecudure summaries, + this means that the procedure is not called in the current counter-model. */ + + bool RPFP::Empty(Node *p) + { + Term b; std::vector v; + RedVars(p, b, v); + // dualModel.show_internals(); + // std::cout << "b: " << b << std::endl; + expr bv = dualModel.eval(b); + // std::cout << "bv: " << bv << std::endl; + bool res = !eq(bv,ctx.bool_val(true)); + return res; + } + + RPFP::Term RPFP::EvalNode(Node *p) + { + Term b; std::vector v; + RedVars(p, b, v); + std::vector args; + for(unsigned i = 0; i < v.size(); i++) + args.push_back(dualModel.eval(v[i])); + return (p->Name)(args); + } + + void RPFP::EvalArrayTerm(const RPFP::Term &t, ArrayValue &res){ + if (t.is_app()) { + decl_kind k = t.decl().get_decl_kind(); + if (k == AsArray) { + func_decl fd = t.decl().get_func_decl_parameter(0); + func_interp r = dualModel.get_func_interp(fd); + int num = r.num_entries(); + res.defined = true; + for (int i = 0; i < num; i++) { + expr arg = r.get_arg(i, 0); + expr value = r.get_value(i); + res.entries[arg] = value; + } + res.def_val = r.else_value(); + return; + } + else if (k == Store) { + EvalArrayTerm(t.arg(0), res); + if (!res.defined)return; + expr addr = t.arg(1); + expr val = t.arg(2); + if (addr.is_numeral() && val.is_numeral()) { + if (eq(val, res.def_val)) + res.entries.erase(addr); + else + res.entries[addr] = val; + } + else + res.defined = false; + return; + } + } + res.defined = false; + } + + int eae_count = 0; + + RPFP::Term RPFP::EvalArrayEquality(const RPFP::Term &f) { + ArrayValue lhs, rhs; + eae_count++; + EvalArrayTerm(f.arg(0), lhs); + EvalArrayTerm(f.arg(1), rhs); + if (lhs.defined && rhs.defined) { + if (eq(lhs.def_val, rhs.def_val)) + if (lhs.entries == rhs.entries) + return ctx.bool_val(true); + return ctx.bool_val(false); + } + return f; + } + + /** Compute truth values of all boolean subterms in current model. + Assumes formulas has been simplified by Z3, so only boolean ops + ands and, or, not. Returns result in memo. + */ + + int RPFP::SubtermTruth(hash_map &memo, const Term &f) { + if (memo.find(f) != memo.end()) { + return memo[f]; + } + int res; + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + res = SubtermTruth(memo, !f.arg(0) || f.arg(1)); + goto done; + } + if (k == And) { + res = 1; + for (int i = 0; i < nargs; i++) { + int ar = SubtermTruth(memo, f.arg(i)); + if (ar == 0) { + res = 0; + goto done; + } + if (ar == 2)res = 2; + } + goto done; + } + else if (k == Or) { + res = 0; + for (int i = 0; i < nargs; i++) { + int ar = SubtermTruth(memo, f.arg(i)); + if (ar == 1) { + res = 1; + goto done; + } + if (ar == 2)res = 2; + } + goto done; + } + else if (k == Not) { + int ar = SubtermTruth(memo, f.arg(0)); + res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); + goto done; + } + } + { + bool pos; std::vector names; + if (f.is_label(pos, names)) { + res = SubtermTruth(memo, f.arg(0)); + goto done; + } + } + { + expr bv = dualModel.eval(f); + if (bv.is_app() && bv.decl().get_decl_kind() == Equal && + bv.arg(0).is_array()) { + bv = EvalArrayEquality(bv); + } + // Hack!!!! array equalities can occur negatively! + if (bv.is_app() && bv.decl().get_decl_kind() == Not && + bv.arg(0).decl().get_decl_kind() == Equal && + bv.arg(0).arg(0).is_array()) { + bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); + } + if (eq(bv, ctx.bool_val(true))) + res = 1; + else if (eq(bv, ctx.bool_val(false))) + res = 0; + else + res = 2; + } + done: + memo[f] = res; + return res; + } + + int RPFP::EvalTruth(hash_map &memo, Edge *e, const Term &f){ + Term tl = Localize(e, f); + return SubtermTruth(memo,tl); + } + + /** Compute truth values of all boolean subterms in current model. + Assumes formulas has been simplified by Z3, so only boolean ops + ands and, or, not. Returns result in memo. + */ + +#if 0 + int RPFP::GetLabelsRec(hash_map *memo, const Term &f, std::vector &labels, bool labpos){ + if(memo[labpos].find(f) != memo[labpos].end()){ + return memo[labpos][f]; + } + int res; + if(f.is_app()){ + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if(k == Implies){ + res = GetLabelsRec(memo,f.arg(1) || !f.arg(0), labels, labpos); + goto done; + } + if(k == And) { + res = 1; + for(int i = 0; i < nargs; i++){ + int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); + if(ar == 0){ + res = 0; + goto done; + } + if(ar == 2)res = 2; + } + goto done; + } + else if(k == Or) { + res = 0; + for(int i = 0; i < nargs; i++){ + int ar = GetLabelsRec(memo,f.arg(i), labels, labpos); + if(ar == 1){ + res = 1; + goto done; + } + if(ar == 2)res = 2; + } + goto done; + } + else if(k == Not) { + int ar = GetLabelsRec(memo,f.arg(0), labels, !labpos); + res = (ar == 0) ? 1 : ((ar == 1) ? 0 : 2); + goto done; + } + } + { + bool pos; std::vector names; + if(f.is_label(pos,names)){ + res = GetLabelsRec(memo,f.arg(0), labels, labpos); + if(pos == labpos && res == (pos ? 1 : 0)) + for(unsigned i = 0; i < names.size(); i++) + labels.push_back(names[i]); + goto done; + } + } + { + expr bv = dualModel.eval(f); + if(bv.is_app() && bv.decl().get_decl_kind() == Equal && + bv.arg(0).is_array()){ + bv = EvalArrayEquality(bv); + } + // Hack!!!! array equalities can occur negatively! + if(bv.is_app() && bv.decl().get_decl_kind() == Not && + bv.arg(0).decl().get_decl_kind() == Equal && + bv.arg(0).arg(0).is_array()){ + bv = dualModel.eval(!EvalArrayEquality(bv.arg(0))); + } + if(eq(bv,ctx.bool_val(true))) + res = 1; + else if(eq(bv,ctx.bool_val(false))) + res = 0; + else + res = 2; + } + done: + memo[labpos][f] = res; + return res; + } +#endif + + void RPFP::GetLabelsRec(hash_map &memo, const Term &f, std::vector &labels, + hash_set *done, bool truth) { + if (done[truth].find(f) != done[truth].end()) + return; /* already processed */ + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + GetLabelsRec(memo, f.arg(1) || !f.arg(0), labels, done, truth); + goto done; + } + if (k == Iff) { + int b = SubtermTruth(memo, f.arg(0)); + if (b == 2) + throw "disaster in GetLabelsRec"; + GetLabelsRec(memo, f.arg(1), labels, done, truth ? b : !b); + goto done; + } + if (truth ? k == And : k == Or) { + for (int i = 0; i < nargs; i++) + GetLabelsRec(memo, f.arg(i), labels, done, truth); + goto done; + } + if (truth ? k == Or : k == And) { + for (int i = 0; i < nargs; i++) { + Term a = f.arg(i); + timer_start("SubtermTruth"); + int b = SubtermTruth(memo, a); + timer_stop("SubtermTruth"); + if (truth ? (b == 1) : (b == 0)) { + GetLabelsRec(memo, a, labels, done, truth); + goto done; + } + } + /* Unreachable! */ + // throw "error in RPFP::GetLabelsRec"; + goto done; + } + else if (k == Not) { + GetLabelsRec(memo, f.arg(0), labels, done, !truth); + goto done; + } + else { + bool pos; std::vector names; + if (f.is_label(pos, names)) { + GetLabelsRec(memo, f.arg(0), labels, done, truth); + if (pos == truth) + for (unsigned i = 0; i < names.size(); i++) + labels.push_back(names[i]); + goto done; + } + } + } + done: + done[truth].insert(f); + } + + void RPFP::GetLabels(Edge *e, std::vector &labels){ + if(!e->map || e->map->labeled.null()) + return; + Term tl = Localize(e, e->map->labeled); + hash_map memo; + hash_set done[2]; + GetLabelsRec(memo,tl,labels,done,true); + } + +#ifdef Z3OPS + static Z3_subterm_truth *stt; +#endif + + int ir_count = 0; + + void RPFP::ImplicantRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set *done, bool truth, hash_set &dont_cares) { + if (done[truth].find(f) != done[truth].end()) + return; /* already processed */ +#if 0 + int this_count = ir_count++; + if(this_count == 50092) + std::cout << "foo!\n"; +#endif + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies) { + ImplicantRed(memo, f.arg(1) || !f.arg(0), lits, done, truth, dont_cares); + goto done; + } + if (k == Iff) { + int b = SubtermTruth(memo, f.arg(0)); + if (b == 2) + throw "disaster in ImplicantRed"; + ImplicantRed(memo, f.arg(1), lits, done, truth ? b : !b, dont_cares); + goto done; + } + if (truth ? k == And : k == Or) { + for (int i = 0; i < nargs; i++) + ImplicantRed(memo, f.arg(i), lits, done, truth, dont_cares); + goto done; + } + if (truth ? k == Or : k == And) { + for (int i = 0; i < nargs; i++) { + Term a = f.arg(i); +#if 0 + if(i == nargs - 1){ // last chance! + ImplicantRed(memo,a,lits,done,truth,dont_cares); + goto done; + } +#endif + timer_start("SubtermTruth"); +#ifdef Z3OPS + bool b = stt->eval(a); +#else + int b = SubtermTruth(memo, a); +#endif + timer_stop("SubtermTruth"); + if (truth ? (b == 1) : (b == 0)) { + ImplicantRed(memo, a, lits, done, truth, dont_cares); + goto done; + } + } + /* Unreachable! */ + // TODO: need to indicate this failure to caller + // std::cerr << "error in RPFP::ImplicantRed"; + goto done; + } + else if (k == Not) { + ImplicantRed(memo, f.arg(0), lits, done, !truth, dont_cares); + goto done; + } + } + { + if (dont_cares.find(f) == dont_cares.end()) { + expr rf = ResolveIte(memo, f, lits, done, dont_cares); + expr bv = truth ? rf : !rf; + lits.push_back(bv); + } + } + done: + done[truth].insert(f); + } + + void RPFP::ImplicantFullRed(hash_map &memo, const Term &f, std::vector &lits, + hash_set &done, hash_set &dont_cares, bool extensional) { + if (done.find(f) != done.end()) + return; /* already processed */ + if (f.is_app()) { + int nargs = f.num_args(); + decl_kind k = f.decl().get_decl_kind(); + if (k == Implies || k == Iff || k == And || k == Or || k == Not) { + for (int i = 0; i < nargs; i++) + ImplicantFullRed(memo, f.arg(i), lits, done, dont_cares, extensional); + goto done; + } + } + { + if (dont_cares.find(f) == dont_cares.end()) { + int b = SubtermTruth(memo, f); + if (b != 0 && b != 1) goto done; + if (f.is_app() && f.decl().get_decl_kind() == Equal && f.arg(0).is_array()) { + if (b == 1 && !extensional) { + expr x = dualModel.eval(f.arg(0)); expr y = dualModel.eval(f.arg(1)); + if (!eq(x, y)) + b = 0; + } + if (b == 0) + goto done; + } + expr bv = (b == 1) ? f : !f; + lits.push_back(bv); + } + } + done: + done.insert(f); + } + + RPFP::Term RPFP::ResolveIte(hash_map &memo, const Term &t, std::vector &lits, + hash_set *done, hash_set &dont_cares) { + if (resolve_ite_memo.find(t) != resolve_ite_memo.end()) + return resolve_ite_memo[t]; + Term res; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if (f.get_decl_kind() == Ite) { + timer_start("SubtermTruth"); +#ifdef Z3OPS + bool sel = stt->eval(t.arg(0)); +#else + int xval = SubtermTruth(memo, t.arg(0)); + bool sel; + if (xval == 0)sel = false; + else if (xval == 1)sel = true; + else + throw "unresolved ite in model"; +#endif + timer_stop("SubtermTruth"); + ImplicantRed(memo, t.arg(0), lits, done, sel, dont_cares); + res = ResolveIte(memo, t.arg(sel ? 1 : 2), lits, done, dont_cares); + } + else { + for (int i = 0; i < nargs; i++) + args.push_back(ResolveIte(memo, t.arg(i), lits, done, dont_cares)); + res = f(args.size(), &args[0]); + } + } + else res = t; + resolve_ite_memo[t] = res; + return res; + } + + RPFP::Term RPFP::ElimIteRec(hash_map &memo, const Term &t, std::vector &cnsts) { + std::pair foo(t, expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if (bar.second) { + if (t.is_app()) { + int nargs = t.num_args(); + std::vector args; + if (t.decl().get_decl_kind() == Equal) { + expr lhs = t.arg(0); + expr rhs = t.arg(1); + if (rhs.decl().get_decl_kind() == Ite) { + expr rhs_args[3]; + lhs = ElimIteRec(memo, lhs, cnsts); + for (int i = 0; i < 3; i++) + rhs_args[i] = ElimIteRec(memo, rhs.arg(i), cnsts); + res = (rhs_args[0] && (lhs == rhs_args[1])) || ((!rhs_args[0]) && (lhs == rhs_args[2])); + goto done; + } + } + if (t.decl().get_decl_kind() == Ite) { + func_decl sym = ctx.fresh_func_decl("@ite", t.get_sort()); + res = sym(); + cnsts.push_back(ElimIteRec(memo, ctx.make(Equal, res, t), cnsts)); + } + else { + for (int i = 0; i < nargs; i++) + args.push_back(ElimIteRec(memo, t.arg(i), cnsts)); + res = t.decl()(args.size(), &args[0]); + } + } + else if (t.is_quantifier()) + res = clone_quantifier(t, ElimIteRec(memo, t.body(), cnsts)); + else + res = t; + } + done: + return res; + } + + RPFP::Term RPFP::ElimIte(const Term &t){ + hash_map memo; + std::vector cnsts; + expr res = ElimIteRec(memo,t,cnsts); + if(!cnsts.empty()){ + cnsts.push_back(res); + res = ctx.make(And,cnsts); + } + return res; + } + + void RPFP::Implicant(hash_map &memo, const Term &f, std::vector &lits, hash_set &dont_cares){ + hash_set done[2]; + ImplicantRed(memo,f,lits,done,true, dont_cares); + } + + + /** Underapproximate a formula using current counterexample. */ + + RPFP::Term RPFP::UnderapproxFormula(const Term &f, hash_set &dont_cares){ + /* first compute truth values of subterms */ + hash_map memo; +#ifdef Z3OPS + stt = Z3_mk_subterm_truth(ctx,dualModel); +#endif + // SubtermTruth(memo,f); + /* now compute an implicant */ + std::vector lits; + Implicant(memo,f,lits, dont_cares); +#ifdef Z3OPS + delete stt; stt = 0; +#endif + /* return conjunction of literals */ + return conjoin(lits); + } + + RPFP::Term RPFP::UnderapproxFullFormula(const Term &f, bool extensional){ + hash_set dont_cares; + resolve_ite_memo.clear(); + timer_start("UnderapproxFormula"); + /* first compute truth values of subterms */ + hash_map memo; + hash_set done; + std::vector lits; + ImplicantFullRed(memo,f,lits,done,dont_cares, extensional); + timer_stop("UnderapproxFormula"); + /* return conjunction of literals */ + return conjoin(lits); + } + + struct VariableProjector : Z3User { + + struct elim_cand { + Term var; + int sup; + Term val; + }; + + typedef expr Term; + + hash_set keep; + hash_map var_ord; + int num_vars; + std::vector elim_cands; + hash_map > sup_map; + hash_map elim_map; + std::vector ready_cands; + hash_map cand_map; + params simp_params; + + VariableProjector(Z3User &_user, std::vector &keep_vec) : + Z3User(_user), simp_params() { + num_vars = 0; + for (unsigned i = 0; i < keep_vec.size(); i++) { + keep.insert(keep_vec[i]); + var_ord[keep_vec[i]] = num_vars++; + } + } + int VarNum(const Term &v) { + if (var_ord.find(v) == var_ord.end()) + var_ord[v] = num_vars++; + return var_ord[v]; + } + + bool IsVar(const Term &t){ + return t.is_app() && t.num_args() == 0 && t.decl().get_decl_kind() == Uninterpreted; + } + + bool IsPropLit(const Term &t, Term &a) { + if (IsVar(t)) { + a = t; + return true; + } + else if (t.is_app() && t.decl().get_decl_kind() == Not) + return IsPropLit(t.arg(0), a); + return false; + } + + void CountOtherVarsRec(hash_map &memo, + const Term &t, + int id, + int &count) { + std::pair foo(t, 0); + std::pair::iterator, bool> bar = memo.insert(foo); + // int &res = bar.first->second; + if (!bar.second) return; + if (t.is_app()) { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if (nargs == 0 && f.get_decl_kind() == Uninterpreted) { + if (cand_map.find(t) != cand_map.end()) { + count++; + sup_map[t].push_back(id); + } + } + for (int i = 0; i < nargs; i++) + CountOtherVarsRec(memo, t.arg(i), id, count); + } + else if (t.is_quantifier()) + CountOtherVarsRec(memo, t.body(), id, count); + } + + void NewElimCand(const Term &lhs, const Term &rhs) { + if (debug_gauss) { + std::cout << "mapping " << lhs << " to " << rhs << std::endl; + } + elim_cand cand; + cand.var = lhs; + cand.sup = 0; + cand.val = rhs; + elim_cands.push_back(cand); + cand_map[lhs] = elim_cands.size() - 1; + } + + void MakeElimCand(const Term &lhs, const Term &rhs) { + if (eq(lhs, rhs)) + return; + if (!IsVar(lhs)) { + if (IsVar(rhs)) { + MakeElimCand(rhs, lhs); + return; + } + else { + std::cout << "would have mapped a non-var\n"; + return; + } + } + if (IsVar(rhs) && VarNum(rhs) > VarNum(lhs)) { MakeElimCand(rhs, lhs); return; } + if (keep.find(lhs) != keep.end()) + return; + if (cand_map.find(lhs) == cand_map.end()) + NewElimCand(lhs, rhs); else { - std::cout << "would have mapped a non-var\n"; + int cand_idx = cand_map[lhs]; + if (IsVar(rhs) && cand_map.find(rhs) == cand_map.end() + && keep.find(rhs) == keep.end()) + NewElimCand(rhs, elim_cands[cand_idx].val); + elim_cands[cand_idx].val = rhs; + } + } + + Term FindRep(const Term &t) { + if (cand_map.find(t) == cand_map.end()) + return t; + Term &res = elim_cands[cand_map[t]].val; + if (IsVar(res)) { + assert(VarNum(res) < VarNum(t)); + res = FindRep(res); + return res; + } + return t; + } + + void GaussElimCheap(const std::vector &lits_in, + std::vector &lits_out) { + for (unsigned i = 0; i < lits_in.size(); i++) { + Term lit = lits_in[i]; + if (lit.is_app()) { + decl_kind k = lit.decl().get_decl_kind(); + if (k == Equal || k == Iff) + MakeElimCand(FindRep(lit.arg(0)), FindRep(lit.arg(1))); + } + } + + for (unsigned i = 0; i < elim_cands.size(); i++) { + elim_cand &cand = elim_cands[i]; + hash_map memo; + CountOtherVarsRec(memo, cand.val, i, cand.sup); + if (cand.sup == 0) + ready_cands.push_back(i); + } + + while (!ready_cands.empty()) { + elim_cand &cand = elim_cands[ready_cands.back()]; + ready_cands.pop_back(); + Term rep = FindRep(cand.var); + if (!eq(rep, cand.var)) + if (cand_map.find(rep) != cand_map.end()) { + int rep_pos = cand_map[rep]; + cand.val = elim_cands[rep_pos].val; + } + Term val = SubstRec(elim_map, cand.val); + if (debug_gauss) { + std::cout << "subbing " << cand.var << " --> " << val << std::endl; + } + elim_map[cand.var] = val; + std::vector &sup = sup_map[cand.var]; + for (unsigned i = 0; i < sup.size(); i++) { + int c = sup[i]; + if ((--elim_cands[c].sup) == 0) + ready_cands.push_back(c); + } + } + + for (unsigned i = 0; i < lits_in.size(); i++) { + Term lit = lits_in[i]; + lit = SubstRec(elim_map, lit); + lit = lit.simplify(); + if (eq(lit, ctx.bool_val(true))) + continue; + Term a; + if (IsPropLit(lit, a)) + if (keep.find(lit) == keep.end()) + continue; + lits_out.push_back(lit); + } + } + + // maps variables to constrains in which the occur pos, neg + hash_map la_index[2]; + hash_map la_coeffs[2]; + std::vector la_pos_vars; + bool fixing; + + void IndexLAcoeff(const Term &coeff1, const Term &coeff2, Term t, int id) { + Term coeff = coeff1 * coeff2; + coeff = coeff.simplify(); + Term is_pos = (coeff >= ctx.int_val(0)); + is_pos = is_pos.simplify(); + if (eq(is_pos, ctx.bool_val(true))) + IndexLA(true, coeff, t, id); + else + IndexLA(false, coeff, t, id); + } + + void IndexLAremove(const Term &t) { + if (IsVar(t)) { + la_index[0][t] = -1; // means ineligible to be eliminated + la_index[1][t] = -1; // (more that one occurrence, or occurs not in linear comb) + } + else if (t.is_app()) { + int nargs = t.num_args(); + for (int i = 0; i < nargs; i++) + IndexLAremove(t.arg(i)); + } + // TODO: quantifiers? + } + + + void IndexLA(bool pos, const Term &coeff, const Term &t, int id) { + if (t.is_numeral()) + return; + if (t.is_app()) { + int nargs = t.num_args(); + switch (t.decl().get_decl_kind()) { + case Plus: + for (int i = 0; i < nargs; i++) + IndexLA(pos, coeff, t.arg(i), id); + break; + case Sub: + IndexLA(pos, coeff, t.arg(0), id); + IndexLA(!pos, coeff, t.arg(1), id); + break; + case Times: + if (t.arg(0).is_numeral()) + IndexLAcoeff(coeff, t.arg(0), t.arg(1), id); + else if (t.arg(1).is_numeral()) + IndexLAcoeff(coeff, t.arg(1), t.arg(0), id); + break; + default: + if (IsVar(t) && (fixing || la_index[pos].find(t) == la_index[pos].end())) { + la_index[pos][t] = id; + la_coeffs[pos][t] = coeff; + if (pos && !fixing) + la_pos_vars.push_back(t); // this means we only add a var once + } + else + IndexLAremove(t); + } + } + } + + void IndexLAstart(bool pos, const Term &t, int id){ + IndexLA(pos,(pos ? ctx.int_val(1) : ctx.int_val(-1)), t, id); + } + + void IndexLApred(bool pos, const Term &p, int id) { + if (p.is_app()) { + switch (p.decl().get_decl_kind()) { + case Not: + IndexLApred(!pos, p.arg(0), id); + break; + case Leq: + case Lt: + IndexLAstart(!pos, p.arg(0), id); + IndexLAstart(pos, p.arg(1), id); + break; + case Geq: + case Gt: + IndexLAstart(pos, p.arg(0), id); + IndexLAstart(!pos, p.arg(1), id); + break; + default: + IndexLAremove(p); + } + } + } + + void IndexLAfix(const Term &p, int id){ + fixing = true; + IndexLApred(true,p,id); + fixing = false; + } + + bool IsCanonIneq(const Term &lit, Term &term, Term &bound) { + // std::cout << Z3_simplify_get_help(ctx) << std::endl; + bool pos = lit.decl().get_decl_kind() != Not; + Term atom = pos ? lit : lit.arg(0); + if (atom.decl().get_decl_kind() == Leq) { + if (pos) { + bound = atom.arg(0); + term = atom.arg(1).simplify(simp_params); +#if Z3_MAJOR_VERSION < 4 + term = SortSum(term); +#endif + } + else { + bound = (atom.arg(1) + ctx.int_val(1)); + term = atom.arg(0); + // std::cout << "simplifying bound: " << bound << std::endl; + bound = bound.simplify(); + term = term.simplify(simp_params); +#if Z3_MAJOR_VERSION < 4 + term = SortSum(term); +#endif + } + return true; + } + else if (atom.decl().get_decl_kind() == Geq) { + if (pos) { + bound = atom.arg(1); // integer axiom + term = atom.arg(0).simplify(simp_params); +#if Z3_MAJOR_VERSION < 4 + term = SortSum(term); +#endif + return true; + } + else { + bound = -(atom.arg(1) - ctx.int_val(1)); // integer axiom + term = -atom.arg(0); + bound = bound.simplify(); + term = term.simplify(simp_params); +#if Z3_MAJOR_VERSION < 4 + term = SortSum(term); +#endif + } + return true; + } + return false; + } + + Term CanonIneqTerm(const Term &p){ + Term term,bound; + Term ps = p.simplify(); + bool ok = IsCanonIneq(ps,term,bound); + assert(ok); + return term - bound; + } + + void ElimRedundantBounds(std::vector &lits) { + hash_map best_bound; + for (unsigned i = 0; i < lits.size(); i++) { + lits[i] = lits[i].simplify(simp_params); + Term term, bound; + if (IsCanonIneq(lits[i], term, bound)) { + if (best_bound.find(term) == best_bound.end()) + best_bound[term] = i; + else { + int best = best_bound[term]; + Term bterm, bbound; + IsCanonIneq(lits[best], bterm, bbound); + Term comp = bound > bbound; + comp = comp.simplify(); + if (eq(comp, ctx.bool_val(true))) { + lits[best] = ctx.bool_val(true); + best_bound[term] = i; + } + else { + lits[i] = ctx.bool_val(true); + } + } + } + } + } + + void FourierMotzkinCheap(const std::vector &lits_in, + std::vector &lits_out) { + simp_params.set(":som", true); + simp_params.set(":sort-sums", true); + fixing = false; lits_out = lits_in; + ElimRedundantBounds(lits_out); + for (unsigned i = 0; i < lits_out.size(); i++) + IndexLApred(true, lits_out[i], i); + + for (unsigned i = 0; i < la_pos_vars.size(); i++) { + Term var = la_pos_vars[i]; + if (la_index[false].find(var) != la_index[false].end()) { + int pos_idx = la_index[true][var]; + int neg_idx = la_index[false][var]; + if (pos_idx >= 0 && neg_idx >= 0) { + if (keep.find(var) != keep.end()) { + std::cout << "would have eliminated keep var\n"; + continue; + } + Term tpos = CanonIneqTerm(lits_out[pos_idx]); + Term tneg = CanonIneqTerm(lits_out[neg_idx]); + Term pos_coeff = la_coeffs[true][var]; + Term neg_coeff = -la_coeffs[false][var]; + Term comb = neg_coeff * tpos + pos_coeff * tneg; + Term ineq = ctx.int_val(0) <= comb; + ineq = ineq.simplify(); + lits_out[pos_idx] = ineq; + lits_out[neg_idx] = ctx.bool_val(true); + IndexLAfix(ineq, pos_idx); + } + } + } + } + + Term ProjectFormula(const Term &f){ + std::vector lits, new_lits1, new_lits2; + CollectConjuncts(f,lits); + timer_start("GaussElimCheap"); + GaussElimCheap(lits,new_lits1); + timer_stop("GaussElimCheap"); + timer_start("FourierMotzkinCheap"); + FourierMotzkinCheap(new_lits1,new_lits2); + timer_stop("FourierMotzkinCheap"); + return conjoin(new_lits2); + } + }; + + void Z3User::CollectConjuncts(const Term &f, std::vector &lits, bool pos) { + if (f.is_app() && f.decl().get_decl_kind() == Not) + CollectConjuncts(f.arg(0), lits, !pos); + else if (pos && f.is_app() && f.decl().get_decl_kind() == And) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectConjuncts(f.arg(i), lits, true); + } + else if (!pos && f.is_app() && f.decl().get_decl_kind() == Or) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectConjuncts(f.arg(i), lits, false); + } + else if (pos) { + if (!eq(f, ctx.bool_val(true))) + lits.push_back(f); + } + else { + if (!eq(f, ctx.bool_val(false))) + lits.push_back(!f); + } + } + + void Z3User::CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate) { + if (f.is_app() && f.decl().get_decl_kind() == Not) + CollectJuncts(f.arg(0), lits, (op == And) ? Or : And, !negate); + else if (f.is_app() && f.decl().get_decl_kind() == op) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + CollectJuncts(f.arg(i), lits, op, negate); + } + else { + expr junct = negate ? Negate(f) : f; + lits.push_back(junct); + } + } + + struct TermLt { + bool operator()(const expr &x, const expr &y){ + unsigned xid = x.get_id(); + unsigned yid = y.get_id(); + return xid < yid; + } + }; + + void Z3User::SortTerms(std::vector &terms){ + TermLt foo; + std::sort(terms.begin(),terms.end(),foo); + } + + Z3User::Term Z3User::SortSum(const Term &t){ + if(!(t.is_app() && t.decl().get_decl_kind() == Plus)) + return t; + int nargs = t.num_args(); + if(nargs < 2) return t; + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = t.arg(i); + SortTerms(args); + if(nargs == 2) + return args[0] + args[1]; + return sum(args); + } + + + RPFP::Term RPFP::ProjectFormula(std::vector &keep_vec, const Term &f){ + VariableProjector vp(*this,keep_vec); + return vp.ProjectFormula(f); + } + + /** Compute an underapproximation of every node in a tree rooted at "root", + based on a previously computed counterexample. The underapproximation + may contain free variables that are implicitly existentially quantified. + */ + + RPFP::Term RPFP::ComputeUnderapprox(Node *root, int persist){ + /* if terminated underapprox is empty set (false) */ + bool show_model = false; + if(show_model) + std::cout << dualModel << std::endl; + if(!root->Outgoing){ + root->Underapprox.SetEmpty(); + return ctx.bool_val(true); + } + /* if not used in cex, underapprox is empty set (false) */ + if(Empty(root)){ + root->Underapprox.SetEmpty(); + return ctx.bool_val(true); + } + /* compute underapprox of children first */ + std::vector &chs = root->Outgoing->Children; + std::vector chu(chs.size()); + for(unsigned i = 0; i < chs.size(); i++) + chu[i] = ComputeUnderapprox(chs[i],persist); + + Term b; std::vector v; + RedVars(root, b, v); + /* underapproximate the edge formula */ + hash_set dont_cares; + dont_cares.insert(b); + resolve_ite_memo.clear(); + timer_start("UnderapproxFormula"); + Term dual = root->Outgoing->dual.null() ? ctx.bool_val(true) : root->Outgoing->dual; + Term eu = UnderapproxFormula(dual,dont_cares); + timer_stop("UnderapproxFormula"); + /* combine with children */ + chu.push_back(eu); + eu = conjoin(chu); + /* project onto appropriate variables */ + eu = ProjectFormula(v,eu); + eu = eu.simplify(); + +#if 0 + /* check the result is consistent */ + { + hash_map memo; + int res = SubtermTruth(memo, eu); + if(res != 1) + throw "inconsistent projection"; + } +#endif + + /* rename to appropriate variable names */ + hash_map memo; + for (unsigned i = 0; i < v.size(); i++) + memo[v[i]] = root->Annotation.IndParams[i]; /* copy names from annotation */ + Term funder = SubstRec(memo, eu); + root->Underapprox = CreateRelation(root->Annotation.IndParams,funder); +#if 0 + if(persist) + Z3_persist_ast(ctx,root->Underapprox.Formula,persist); +#endif + return eu; + } + + void RPFP::FixCurrentState(Edge *edge){ + hash_set dont_cares; + resolve_ite_memo.clear(); + timer_start("UnderapproxFormula"); + Term dual = edge->dual.null() ? ctx.bool_val(true) : edge->dual; + Term eu = UnderapproxFormula(dual,dont_cares); + timer_stop("UnderapproxFormula"); + ConstrainEdgeLocalized(edge,eu); + } + + void RPFP::GetGroundLitsUnderQuants(hash_set *memo, const Term &f, std::vector &res, int under){ + if(memo[under].find(f) != memo[under].end()) + return; + memo[under].insert(f); + if (f.is_app()) { + if (!under && !f.has_quantifiers()) + return; + decl_kind k = f.decl().get_decl_kind(); + if (k == And || k == Or || k == Implies || k == Iff) { + int num_args = f.num_args(); + for (int i = 0; i < num_args; i++) + GetGroundLitsUnderQuants(memo, f.arg(i), res, under); return; } } - if (IsVar(rhs) && VarNum(rhs) > VarNum(lhs)) { - MakeElimCand(rhs, lhs); + else if (f.is_quantifier()){ +#if 0 + // treat closed quantified formula as a literal 'cause we hate nested quantifiers + if(under && IsClosedFormula(f)) + res.push_back(f); + else +#endif + GetGroundLitsUnderQuants(memo,f.body(),res,1); return; } - if (keep.find(lhs) != keep.end()) + if(f.is_var()){ + // std::cout << "foo!\n"; return; - if (cand_map.find(lhs) == cand_map.end()) - NewElimCand(lhs, rhs); - else { - int cand_idx = cand_map[lhs]; - if (IsVar(rhs) && cand_map.find(rhs) == cand_map.end() - && keep.find(rhs) == keep.end()) - NewElimCand(rhs, elim_cands[cand_idx].val); - elim_cands[cand_idx].val = rhs; } + if(under && f.is_ground()) + res.push_back(f); } - Term FindRep(const Term &t) { - if (cand_map.find(t) == cand_map.end()) - return t; - Term &res = elim_cands[cand_map[t]].val; - if (IsVar(res)) { - assert(VarNum(res) < VarNum(t)); - res = FindRep(res); - return res; - } - return t; - } - - void GaussElimCheap(const std::vector &lits_in, - std::vector &lits_out) { - for (unsigned i = 0; i < lits_in.size(); i++) { - Term lit = lits_in[i]; - if (lit.is_app()) { - decl_kind k = lit.decl().get_decl_kind(); - if (k == Equal || k == Iff) - MakeElimCand(FindRep(lit.arg(0)), FindRep(lit.arg(1))); - } - } - - for (unsigned i = 0; i < elim_cands.size(); i++) { - elim_cand &cand = elim_cands[i]; - hash_map memo; - CountOtherVarsRec(memo, cand.val, i, cand.sup); - if (cand.sup == 0) - ready_cands.push_back(i); - } - - while (!ready_cands.empty()) { - elim_cand &cand = elim_cands[ready_cands.back()]; - ready_cands.pop_back(); - Term rep = FindRep(cand.var); - if (!eq(rep, cand.var)) - if (cand_map.find(rep) != cand_map.end()) { - int rep_pos = cand_map[rep]; - cand.val = elim_cands[rep_pos].val; + RPFP::Term RPFP::StrengthenFormulaByCaseSplitting(const Term &f, std::vector &case_lits){ + hash_set memo[2]; + std::vector lits; + GetGroundLitsUnderQuants(memo, f, lits, 0); + hash_set lits_hash; + for(unsigned i = 0; i < lits.size(); i++) + lits_hash.insert(lits[i]); + hash_map subst; + hash_map stt_memo; + std::vector conjuncts; + for(unsigned i = 0; i < lits.size(); i++){ + const expr &lit = lits[i]; + if(lits_hash.find(NegateLit(lit)) == lits_hash.end()){ + case_lits.push_back(lit); + bool tval = false; + expr atom = lit; + if(lit.is_app() && lit.decl().get_decl_kind() == Not){ + tval = true; + atom = lit.arg(0); } - Term val = SubstRec(elim_map, cand.val); - if (debug_gauss) { - std::cout << "subbing " << cand.var << " --> " << val << std::endl; - } - elim_map[cand.var] = val; - std::vector &sup = sup_map[cand.var]; - for (unsigned i = 0; i < sup.size(); i++) { - int c = sup[i]; - if ((--elim_cands[c].sup) == 0) - ready_cands.push_back(c); - } - } - - for (unsigned i = 0; i < lits_in.size(); i++) { - Term lit = lits_in[i]; - lit = SubstRec(elim_map, lit); - lit = lit.simplify(); - if (eq(lit, ctx.bool_val(true))) - continue; - Term a; - if (IsPropLit(lit, a)) - if (keep.find(lit) == keep.end()) - continue; - lits_out.push_back(lit); - } - } - - // maps variables to constrains in which the occur pos, neg - hash_map la_index[2]; - hash_map la_coeffs[2]; - std::vector la_pos_vars; - bool fixing; - - void IndexLAcoeff(const Term &coeff1, const Term &coeff2, Term t, int id) { - Term coeff = coeff1 * coeff2; - coeff = coeff.simplify(); - Term is_pos = (coeff >= ctx.int_val(0)); - is_pos = is_pos.simplify(); - if (eq(is_pos, ctx.bool_val(true))) - IndexLA(true, coeff, t, id); - else - IndexLA(false, coeff, t, id); - } - - void IndexLAremove(const Term &t) { - if (IsVar(t)) { - la_index[0][t] = -1; // means ineligible to be eliminated - la_index[1][t] = -1; // (more that one occurrence, or occurs not in linear comb) - } - else if (t.is_app()) { - int nargs = t.num_args(); - for (int i = 0; i < nargs; i++) - IndexLAremove(t.arg(i)); - } - // TODO: quantifiers? - } - - - void IndexLA(bool pos, const Term &coeff, const Term &t, int id) { - if (t.is_numeral()) - return; - if (t.is_app()) { - int nargs = t.num_args(); - switch (t.decl().get_decl_kind()) { - case Plus: - for (int i = 0; i < nargs; i++) - IndexLA(pos, coeff, t.arg(i), id); - break; - case Sub: - IndexLA(pos, coeff, t.arg(0), id); - IndexLA(!pos, coeff, t.arg(1), id); - break; - case Times: - if (t.arg(0).is_numeral()) - IndexLAcoeff(coeff, t.arg(0), t.arg(1), id); - else if (t.arg(1).is_numeral()) - IndexLAcoeff(coeff, t.arg(1), t.arg(0), id); - break; - default: - if (IsVar(t) && (fixing || la_index[pos].find(t) == la_index[pos].end())) { - la_index[pos][t] = id; - la_coeffs[pos][t] = coeff; - if (pos && !fixing) - la_pos_vars.push_back(t); // this means we only add a var once - } - else - IndexLAremove(t); - } - } - } - - void IndexLAstart(bool pos, const Term &t, int id){ - IndexLA(pos,(pos ? ctx.int_val(1) : ctx.int_val(-1)), t, id); - } - - void IndexLApred(bool pos, const Term &p, int id) { - if (p.is_app()) { - switch (p.decl().get_decl_kind()) { - case Not: - IndexLApred(!pos, p.arg(0), id); - break; - case Leq: - case Lt: - IndexLAstart(!pos, p.arg(0), id); - IndexLAstart(pos, p.arg(1), id); - break; - case Geq: - case Gt: - IndexLAstart(pos, p.arg(0), id); - IndexLAstart(!pos, p.arg(1), id); - break; - default: - IndexLAremove(p); - } - } - } - - void IndexLAfix(const Term &p, int id){ - fixing = true; - IndexLApred(true,p,id); - fixing = false; - } - - bool IsCanonIneq(const Term &lit, Term &term, Term &bound) { - // std::cout << Z3_simplify_get_help(ctx) << std::endl; - bool pos = lit.decl().get_decl_kind() != Not; - Term atom = pos ? lit : lit.arg(0); - if (atom.decl().get_decl_kind() == Leq) { - if (pos) { - bound = atom.arg(0); - term = atom.arg(1).simplify(simp_params); -#if Z3_MAJOR_VERSION < 4 - term = SortSum(term); -#endif - } - else { - bound = (atom.arg(1) + ctx.int_val(1)); - term = atom.arg(0); - // std::cout << "simplifying bound: " << bound << std::endl; - bound = bound.simplify(); - term = term.simplify(simp_params); -#if Z3_MAJOR_VERSION < 4 - term = SortSum(term); -#endif - } - return true; - } - else if (atom.decl().get_decl_kind() == Geq) { - if (pos) { - bound = atom.arg(1); // integer axiom - term = atom.arg(0).simplify(simp_params); -#if Z3_MAJOR_VERSION < 4 - term = SortSum(term); -#endif - return true; - } - else { - bound = -(atom.arg(1) - ctx.int_val(1)); // integer axiom - term = -atom.arg(0); - bound = bound.simplify(); - term = term.simplify(simp_params); -#if Z3_MAJOR_VERSION < 4 - term = SortSum(term); -#endif - } - return true; - } - return false; - } - - Term CanonIneqTerm(const Term &p){ - Term term,bound; - Term ps = p.simplify(); - bool ok = IsCanonIneq(ps,term,bound); - assert(ok); - return term - bound; - } - - void ElimRedundantBounds(std::vector &lits) { - hash_map best_bound; - for (unsigned i = 0; i < lits.size(); i++) { - lits[i] = lits[i].simplify(simp_params); - Term term, bound; - if (IsCanonIneq(lits[i], term, bound)) { - if (best_bound.find(term) == best_bound.end()) - best_bound[term] = i; + expr etval = ctx.bool_val(tval); + if(atom.is_quantifier()) + subst[atom] = etval; // this is a bit desperate, since we can't eval quants else { - int best = best_bound[term]; - Term bterm, bbound; - IsCanonIneq(lits[best], bterm, bbound); - Term comp = bound > bbound; - comp = comp.simplify(); - if (eq(comp, ctx.bool_val(true))) { - lits[best] = ctx.bool_val(true); - best_bound[term] = i; - } + int b = SubtermTruth(stt_memo,atom); + if(b == (tval ? 1 : 0)) + subst[atom] = etval; else { - lits[i] = ctx.bool_val(true); + if(b == 0 || b == 1){ + etval = ctx.bool_val(b ? true : false); + subst[atom] = etval; + conjuncts.push_back(b ? atom : !atom); + } } } } } - } - - void FourierMotzkinCheap(const std::vector &lits_in, - std::vector &lits_out) { - simp_params.set(":som", true); - simp_params.set(":sort-sums", true); - fixing = false; lits_out = lits_in; - ElimRedundantBounds(lits_out); - for (unsigned i = 0; i < lits_out.size(); i++) - IndexLApred(true, lits_out[i], i); - - for (unsigned i = 0; i < la_pos_vars.size(); i++) { - Term var = la_pos_vars[i]; - if (la_index[false].find(var) != la_index[false].end()) { - int pos_idx = la_index[true][var]; - int neg_idx = la_index[false][var]; - if (pos_idx >= 0 && neg_idx >= 0) { - if (keep.find(var) != keep.end()) { - std::cout << "would have eliminated keep var\n"; - continue; - } - Term tpos = CanonIneqTerm(lits_out[pos_idx]); - Term tneg = CanonIneqTerm(lits_out[neg_idx]); - Term pos_coeff = la_coeffs[true][var]; - Term neg_coeff = -la_coeffs[false][var]; - Term comb = neg_coeff * tpos + pos_coeff * tneg; - Term ineq = ctx.int_val(0) <= comb; - ineq = ineq.simplify(); - lits_out[pos_idx] = ineq; - lits_out[neg_idx] = ctx.bool_val(true); - IndexLAfix(ineq, pos_idx); - } - } + expr g = f; + if(!subst.empty()){ + g = SubstRec(subst,f); + if(conjuncts.size()) + g = g && ctx.make(And,conjuncts); + g = g.simplify(); } - } - - Term ProjectFormula(const Term &f){ - std::vector lits, new_lits1, new_lits2; - CollectConjuncts(f,lits); - timer_start("GaussElimCheap"); - GaussElimCheap(lits,new_lits1); - timer_stop("GaussElimCheap"); - timer_start("FourierMotzkinCheap"); - FourierMotzkinCheap(new_lits1,new_lits2); - timer_stop("FourierMotzkinCheap"); - return conjoin(new_lits2); - } - }; - - void Z3User::CollectConjuncts(const Term &f, std::vector &lits, bool pos) { - if (f.is_app() && f.decl().get_decl_kind() == Not) - CollectConjuncts(f.arg(0), lits, !pos); - else if (pos && f.is_app() && f.decl().get_decl_kind() == And) { - int num_args = f.num_args(); - for (int i = 0; i < num_args; i++) - CollectConjuncts(f.arg(i), lits, true); - } - else if (!pos && f.is_app() && f.decl().get_decl_kind() == Or) { - int num_args = f.num_args(); - for (int i = 0; i < num_args; i++) - CollectConjuncts(f.arg(i), lits, false); - } - else if (pos) { - if (!eq(f, ctx.bool_val(true))) - lits.push_back(f); - } - else { - if (!eq(f, ctx.bool_val(false))) - lits.push_back(!f); - } - } - - void Z3User::CollectJuncts(const Term &f, std::vector &lits, decl_kind op, bool negate) { - if (f.is_app() && f.decl().get_decl_kind() == Not) - CollectJuncts(f.arg(0), lits, (op == And) ? Or : And, !negate); - else if (f.is_app() && f.decl().get_decl_kind() == op) { - int num_args = f.num_args(); - for (int i = 0; i < num_args; i++) - CollectJuncts(f.arg(i), lits, op, negate); - } - else { - expr junct = negate ? Negate(f) : f; - lits.push_back(junct); - } - } - - struct TermLt { - bool operator()(const expr &x, const expr &y){ - unsigned xid = x.get_id(); - unsigned yid = y.get_id(); - return xid < yid; - } - }; - - void Z3User::SortTerms(std::vector &terms){ - TermLt foo; - std::sort(terms.begin(),terms.end(),foo); - } - - Z3User::Term Z3User::SortSum(const Term &t){ - if(!(t.is_app() && t.decl().get_decl_kind() == Plus)) - return t; - int nargs = t.num_args(); - if(nargs < 2) return t; - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = t.arg(i); - SortTerms(args); - if(nargs == 2) - return args[0] + args[1]; - return sum(args); - } - - - RPFP::Term RPFP::ProjectFormula(std::vector &keep_vec, const Term &f){ - VariableProjector vp(*this,keep_vec); - return vp.ProjectFormula(f); - } - - /** Compute an underapproximation of every node in a tree rooted at "root", - based on a previously computed counterexample. The underapproximation - may contain free variables that are implicitly existentially quantified. - */ - - RPFP::Term RPFP::ComputeUnderapprox(Node *root, int persist){ - /* if terminated underapprox is empty set (false) */ - bool show_model = false; - if(show_model) - std::cout << dualModel << std::endl; - if(!root->Outgoing){ - root->Underapprox.SetEmpty(); - return ctx.bool_val(true); - } - /* if not used in cex, underapprox is empty set (false) */ - if(Empty(root)){ - root->Underapprox.SetEmpty(); - return ctx.bool_val(true); - } - /* compute underapprox of children first */ - std::vector &chs = root->Outgoing->Children; - std::vector chu(chs.size()); - for(unsigned i = 0; i < chs.size(); i++) - chu[i] = ComputeUnderapprox(chs[i],persist); - - Term b; std::vector v; - RedVars(root, b, v); - /* underapproximate the edge formula */ - hash_set dont_cares; - dont_cares.insert(b); - resolve_ite_memo.clear(); - timer_start("UnderapproxFormula"); - Term dual = root->Outgoing->dual.null() ? ctx.bool_val(true) : root->Outgoing->dual; - Term eu = UnderapproxFormula(dual,dont_cares); - timer_stop("UnderapproxFormula"); - /* combine with children */ - chu.push_back(eu); - eu = conjoin(chu); - /* project onto appropriate variables */ - eu = ProjectFormula(v,eu); - eu = eu.simplify(); - -#if 0 - /* check the result is consistent */ - { - hash_map memo; - int res = SubtermTruth(memo, eu); - if(res != 1) - throw "inconsistent projection"; - } -#endif - - /* rename to appropriate variable names */ - hash_map memo; - for (unsigned i = 0; i < v.size(); i++) - memo[v[i]] = root->Annotation.IndParams[i]; /* copy names from annotation */ - Term funder = SubstRec(memo, eu); - root->Underapprox = CreateRelation(root->Annotation.IndParams,funder); -#if 0 - if(persist) - Z3_persist_ast(ctx,root->Underapprox.Formula,persist); -#endif - return eu; - } - - void RPFP::FixCurrentState(Edge *edge){ - hash_set dont_cares; - resolve_ite_memo.clear(); - timer_start("UnderapproxFormula"); - Term dual = edge->dual.null() ? ctx.bool_val(true) : edge->dual; - Term eu = UnderapproxFormula(dual,dont_cares); - timer_stop("UnderapproxFormula"); - ConstrainEdgeLocalized(edge,eu); - } - - void RPFP::GetGroundLitsUnderQuants(hash_set *memo, const Term &f, std::vector &res, int under){ - if(memo[under].find(f) != memo[under].end()) - return; - memo[under].insert(f); - if (f.is_app()) { - if (!under && !f.has_quantifiers()) - return; - decl_kind k = f.decl().get_decl_kind(); - if (k == And || k == Or || k == Implies || k == Iff) { - int num_args = f.num_args(); - for (int i = 0; i < num_args; i++) - GetGroundLitsUnderQuants(memo, f.arg(i), res, under); - return; - } - } - else if (f.is_quantifier()){ -#if 0 - // treat closed quantified formula as a literal 'cause we hate nested quantifiers - if(under && IsClosedFormula(f)) - res.push_back(f); - else -#endif - GetGroundLitsUnderQuants(memo,f.body(),res,1); - return; - } - if(f.is_var()){ - // std::cout << "foo!\n"; - return; - } - if(under && f.is_ground()) - res.push_back(f); - } - - RPFP::Term RPFP::StrengthenFormulaByCaseSplitting(const Term &f, std::vector &case_lits){ - hash_set memo[2]; - std::vector lits; - GetGroundLitsUnderQuants(memo, f, lits, 0); - hash_set lits_hash; - for(unsigned i = 0; i < lits.size(); i++) - lits_hash.insert(lits[i]); - hash_map subst; - hash_map stt_memo; - std::vector conjuncts; - for(unsigned i = 0; i < lits.size(); i++){ - const expr &lit = lits[i]; - if(lits_hash.find(NegateLit(lit)) == lits_hash.end()){ - case_lits.push_back(lit); - bool tval = false; - expr atom = lit; - if(lit.is_app() && lit.decl().get_decl_kind() == Not){ - tval = true; - atom = lit.arg(0); - } - expr etval = ctx.bool_val(tval); - if(atom.is_quantifier()) - subst[atom] = etval; // this is a bit desperate, since we can't eval quants - else { - int b = SubtermTruth(stt_memo,atom); - if(b == (tval ? 1 : 0)) - subst[atom] = etval; - else { - if(b == 0 || b == 1){ - etval = ctx.bool_val(b ? true : false); - subst[atom] = etval; - conjuncts.push_back(b ? atom : !atom); - } - } - } - } - } - expr g = f; - if(!subst.empty()){ - g = SubstRec(subst,f); - if(conjuncts.size()) - g = g && ctx.make(And,conjuncts); - g = g.simplify(); - } #if 1 - expr g_old = g; - g = RemoveRedundancy(g); - bool changed = !eq(g,g_old); - g = g.simplify(); - if(changed) { // a second pass can get some more simplification - g = RemoveRedundancy(g); - g = g.simplify(); - } + expr g_old = g; + g = RemoveRedundancy(g); + bool changed = !eq(g,g_old); + g = g.simplify(); + if(changed) { // a second pass can get some more simplification + g = RemoveRedundancy(g); + g = g.simplify(); + } #else - g = RemoveRedundancy(g); - g = g.simplify(); + g = RemoveRedundancy(g); + g = g.simplify(); #endif - g = AdjustQuantifiers(g); - return g; - } - - RPFP::Term RPFP::ModelValueAsConstraint(const Term &t) { - if (t.is_array()) { - ArrayValue arr; - Term e = dualModel.eval(t); - EvalArrayTerm(e, arr); - if (arr.defined) { - std::vector cs; - for (std::map::iterator it = arr.entries.begin(), en = arr.entries.end(); it != en; ++it) { - expr foo = select(t, expr(ctx, it->first)) == expr(ctx, it->second); - cs.push_back(foo); - } - return conjoin(cs); - } - } - else { - expr r = dualModel.get_const_interp(t.decl()); - if (!r.null()) { - expr res = t == expr(ctx, r); - return res; - } - } - return ctx.bool_val(true); - } - - void RPFP::EvalNodeAsConstraint(Node *p, Transformer &res) - { - Term b; std::vector v; - RedVars(p, b, v); - std::vector args; - for(unsigned i = 0; i < v.size(); i++){ - expr val = ModelValueAsConstraint(v[i]); - if(!eq(val,ctx.bool_val(true))) - args.push_back(val); + g = AdjustQuantifiers(g); + return g; + } + + RPFP::Term RPFP::ModelValueAsConstraint(const Term &t) { + if (t.is_array()) { + ArrayValue arr; + Term e = dualModel.eval(t); + EvalArrayTerm(e, arr); + if (arr.defined) { + std::vector cs; + for (std::map::iterator it = arr.entries.begin(), en = arr.entries.end(); it != en; ++it) { + expr foo = select(t, expr(ctx, it->first)) == expr(ctx, it->second); + cs.push_back(foo); + } + return conjoin(cs); + } + } + else { + expr r = dualModel.get_const_interp(t.decl()); + if (!r.null()) { + expr res = t == expr(ctx, r); + return res; + } + } + return ctx.bool_val(true); + } + + void RPFP::EvalNodeAsConstraint(Node *p, Transformer &res) + { + Term b; std::vector v; + RedVars(p, b, v); + std::vector args; + for(unsigned i = 0; i < v.size(); i++){ + expr val = ModelValueAsConstraint(v[i]); + if(!eq(val,ctx.bool_val(true))) + args.push_back(val); + } + expr cnst = conjoin(args); + hash_map memo; + for (unsigned i = 0; i < v.size(); i++) + memo[v[i]] = p->Annotation.IndParams[i]; /* copy names from annotation */ + Term funder = SubstRec(memo, cnst); + res = CreateRelation(p->Annotation.IndParams,funder); } - expr cnst = conjoin(args); - hash_map memo; - for (unsigned i = 0; i < v.size(); i++) - memo[v[i]] = p->Annotation.IndParams[i]; /* copy names from annotation */ - Term funder = SubstRec(memo, cnst); - res = CreateRelation(p->Annotation.IndParams,funder); - } #if 0 - void RPFP::GreedyReduce(solver &s, std::vector &conjuncts){ - // verify - s.push(); - expr conj = ctx.make(And,conjuncts); - s.add(conj); - check_result res = s.check(); - if(res != unsat) - throw "should be unsat"; - s.pop(1); + void RPFP::GreedyReduce(solver &s, std::vector &conjuncts){ + // verify + s.push(); + expr conj = ctx.make(And,conjuncts); + s.add(conj); + check_result res = s.check(); + if(res != unsat) + throw "should be unsat"; + s.pop(1); - for(unsigned i = 0; i < conjuncts.size(); ){ - std::swap(conjuncts[i],conjuncts.back()); - expr save = conjuncts.back(); - conjuncts.pop_back(); - s.push(); - expr conj = ctx.make(And,conjuncts); - s.add(conj); - check_result res = s.check(); - s.pop(1); - if(res != unsat){ - conjuncts.push_back(save); - std::swap(conjuncts[i],conjuncts.back()); - i++; - } + for(unsigned i = 0; i < conjuncts.size(); ){ + std::swap(conjuncts[i],conjuncts.back()); + expr save = conjuncts.back(); + conjuncts.pop_back(); + s.push(); + expr conj = ctx.make(And,conjuncts); + s.add(conj); + check_result res = s.check(); + s.pop(1); + if(res != unsat){ + conjuncts.push_back(save); + std::swap(conjuncts[i],conjuncts.back()); + i++; + } + } } - } #endif - void RPFP::GreedyReduce(solver &s, std::vector &conjuncts){ - std::vector lits(conjuncts.size()); - for(unsigned i = 0; i < lits.size(); i++){ - func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); - lits[i] = pred(); - s.add(ctx.make(Implies,lits[i],conjuncts[i])); - } + void RPFP::GreedyReduce(solver &s, std::vector &conjuncts){ + std::vector lits(conjuncts.size()); + for(unsigned i = 0; i < lits.size(); i++){ + func_decl pred = ctx.fresh_func_decl("@alit", ctx.bool_sort()); + lits[i] = pred(); + s.add(ctx.make(Implies,lits[i],conjuncts[i])); + } - // verify - check_result res = s.check(lits.size(),&lits[0]); - if(res != unsat){ - // add the axioms in the off chance they are useful - const std::vector &theory = ls->get_axioms(); - for(unsigned i = 0; i < theory.size(); i++) - s.add(theory[i]); - for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something! - if(s.check(lits.size(),&lits[0]) == unsat) - goto is_unsat; - throw "should be unsat"; + // verify + check_result res = s.check(lits.size(),&lits[0]); + if(res != unsat){ + // add the axioms in the off chance they are useful + const std::vector &theory = ls->get_axioms(); + for(unsigned i = 0; i < theory.size(); i++) + s.add(theory[i]); + for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something! + if(s.check(lits.size(),&lits[0]) == unsat) + goto is_unsat; + throw "should be unsat"; + } + is_unsat: + for(unsigned i = 0; i < conjuncts.size(); ){ + std::swap(conjuncts[i],conjuncts.back()); + std::swap(lits[i],lits.back()); + check_result res = s.check(lits.size()-1,&lits[0]); + if(res != unsat){ + std::swap(conjuncts[i],conjuncts.back()); + std::swap(lits[i],lits.back()); + i++; + } + else { + conjuncts.pop_back(); + lits.pop_back(); + } + } } - is_unsat: - for(unsigned i = 0; i < conjuncts.size(); ){ - std::swap(conjuncts[i],conjuncts.back()); - std::swap(lits[i],lits.back()); - check_result res = s.check(lits.size()-1,&lits[0]); - if(res != unsat){ - std::swap(conjuncts[i],conjuncts.back()); - std::swap(lits[i],lits.back()); - i++; - } - else { - conjuncts.pop_back(); - lits.pop_back(); - } - } - } - void foobar(){ - } + void foobar(){ + } - void RPFP::GreedyReduceNodes(std::vector &nodes){ - std::vector lits; - for(unsigned i = 0; i < nodes.size(); i++){ - Term b; std::vector v; - RedVars(nodes[i], b, v); - lits.push_back(!b); - expr bv = dualModel.eval(b); - if(eq(bv,ctx.bool_val(true))){ - check_result res = slvr_check(lits.size(),&lits[0]); - if(res == unsat) - lits.pop_back(); - else - foobar(); - } + void RPFP::GreedyReduceNodes(std::vector &nodes){ + std::vector lits; + for(unsigned i = 0; i < nodes.size(); i++){ + Term b; std::vector v; + RedVars(nodes[i], b, v); + lits.push_back(!b); + expr bv = dualModel.eval(b); + if(eq(bv,ctx.bool_val(true))){ + check_result res = slvr_check(lits.size(),&lits[0]); + if(res == unsat) + lits.pop_back(); + else + foobar(); + } + } } - } - check_result RPFP::CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes){ - timer_start("Check"); - std::vector lits; - for(unsigned i = 0; i < posnodes.size(); i++){ - Term b; std::vector v; - RedVars(posnodes[i], b, v); - lits.push_back(b); - } - for(unsigned i = 0; i < negnodes.size(); i++){ - Term b; std::vector v; - RedVars(negnodes[i], b, v); - lits.push_back(!b); - } - check_result res = slvr_check(lits.size(),&lits[0]); - if(res == unsat && posnodes.size()){ - lits.resize(posnodes.size()); - res = slvr_check(lits.size(),&lits[0]); - } - dualModel = slvr().get_model(); + check_result RPFP::CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes){ + timer_start("Check"); + std::vector lits; + for(unsigned i = 0; i < posnodes.size(); i++){ + Term b; std::vector v; + RedVars(posnodes[i], b, v); + lits.push_back(b); + } + for(unsigned i = 0; i < negnodes.size(); i++){ + Term b; std::vector v; + RedVars(negnodes[i], b, v); + lits.push_back(!b); + } + check_result res = slvr_check(lits.size(),&lits[0]); + if(res == unsat && posnodes.size()){ + lits.resize(posnodes.size()); + res = slvr_check(lits.size(),&lits[0]); + } + dualModel = slvr().get_model(); #if 0 - if(!dualModel.null()){ - std::cout << "posnodes called:\n"; - for(unsigned i = 0; i < posnodes.size(); i++) - if(!Empty(posnodes[i])) - std::cout << posnodes[i]->Name.name() << "\n"; - std::cout << "negnodes called:\n"; - for(unsigned i = 0; i < negnodes.size(); i++) - if(!Empty(negnodes[i])) - std::cout << negnodes[i]->Name.name() << "\n"; - } + if(!dualModel.null()){ + std::cout << "posnodes called:\n"; + for(unsigned i = 0; i < posnodes.size(); i++) + if(!Empty(posnodes[i])) + std::cout << posnodes[i]->Name.name() << "\n"; + std::cout << "negnodes called:\n"; + for(unsigned i = 0; i < negnodes.size(); i++) + if(!Empty(negnodes[i])) + std::cout << negnodes[i]->Name.name() << "\n"; + } #endif - timer_stop("Check"); - return res; - } + timer_stop("Check"); + return res; + } - void RPFP_caching::FilterCore(std::vector &core, std::vector &full_core){ - hash_set core_set; - std::copy(full_core.begin(),full_core.end(),std::inserter(core_set,core_set.begin())); - std::vector new_core; - for(unsigned i = 0; i < core.size(); i++) - if(core_set.find(core[i]) != core_set.end()) - new_core.push_back(core[i]); - core.swap(new_core); - } + void RPFP_caching::FilterCore(std::vector &core, std::vector &full_core){ + hash_set core_set; + std::copy(full_core.begin(),full_core.end(),std::inserter(core_set,core_set.begin())); + std::vector new_core; + for(unsigned i = 0; i < core.size(); i++) + if(core_set.find(core[i]) != core_set.end()) + new_core.push_back(core[i]); + core.swap(new_core); + } - void RPFP_caching::GreedyReduceCache(std::vector &assumps, std::vector &core){ - std::vector lits = assumps, full_core; - std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); + void RPFP_caching::GreedyReduceCache(std::vector &assumps, std::vector &core){ + std::vector lits = assumps, full_core; + std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); - // verify - check_result res = CheckCore(lits,full_core); - if(res != unsat){ - // add the axioms in the off chance they are useful - const std::vector &theory = ls->get_axioms(); - for(unsigned i = 0; i < theory.size(); i++) - GetAssumptionLits(theory[i],assumps); - lits = assumps; - std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); + // verify + check_result res = CheckCore(lits,full_core); + if(res != unsat){ + // add the axioms in the off chance they are useful + const std::vector &theory = ls->get_axioms(); + for(unsigned i = 0; i < theory.size(); i++) + GetAssumptionLits(theory[i],assumps); + lits = assumps; + std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); - for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something! - if((res = CheckCore(lits,full_core)) == unsat) - goto is_unsat; - throw "should be unsat"; - } - is_unsat: - FilterCore(core,full_core); + for(int k = 0; k < 100; k++) // keep trying, maybe MBQI will do something! + if((res = CheckCore(lits,full_core)) == unsat) + goto is_unsat; + throw "should be unsat"; + } + is_unsat: + FilterCore(core,full_core); - std::vector dummy; - if(CheckCore(full_core,dummy) != unsat) - throw "should be unsat"; + std::vector dummy; + if(CheckCore(full_core,dummy) != unsat) + throw "should be unsat"; - for(unsigned i = 0; i < core.size(); ){ - expr temp = core[i]; - std::swap(core[i],core.back()); - core.pop_back(); - lits.resize(assumps.size()); - std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); - res = CheckCore(lits,full_core); - if(res != unsat){ - core.push_back(temp); - std::swap(core[i],core.back()); - i++; - } + for(unsigned i = 0; i < core.size(); ){ + expr temp = core[i]; + std::swap(core[i],core.back()); + core.pop_back(); + lits.resize(assumps.size()); + std::copy(core.begin(),core.end(),std::inserter(lits,lits.end())); + res = CheckCore(lits,full_core); + if(res != unsat){ + core.push_back(temp); + std::swap(core[i],core.back()); + i++; + } + } } - } - expr RPFP::NegateLit(const expr &f){ - if(f.is_app() && f.decl().get_decl_kind() == Not) - return f.arg(0); - else - return !f; - } - - void RPFP::NegateLits(std::vector &lits){ - for(unsigned i = 0; i < lits.size(); i++){ - expr &f = lits[i]; - if(f.is_app() && f.decl().get_decl_kind() == Not) - f = f.arg(0); - else - f = !f; + expr RPFP::NegateLit(const expr &f){ + if(f.is_app() && f.decl().get_decl_kind() == Not) + return f.arg(0); + else + return !f; } - } - expr RPFP::SimplifyOr(std::vector &lits){ - if(lits.size() == 0) - return ctx.bool_val(false); - if(lits.size() == 1) - return lits[0]; - return ctx.make(Or,lits); - } + void RPFP::NegateLits(std::vector &lits){ + for(unsigned i = 0; i < lits.size(); i++){ + expr &f = lits[i]; + if(f.is_app() && f.decl().get_decl_kind() == Not) + f = f.arg(0); + else + f = !f; + } + } - expr RPFP::SimplifyAnd(std::vector &lits){ - if(lits.size() == 0) - return ctx.bool_val(true); - if(lits.size() == 1) - return lits[0]; - return ctx.make(And,lits); - } + expr RPFP::SimplifyOr(std::vector &lits){ + if(lits.size() == 0) + return ctx.bool_val(false); + if(lits.size() == 1) + return lits[0]; + return ctx.make(Or,lits); + } + + expr RPFP::SimplifyAnd(std::vector &lits){ + if(lits.size() == 0) + return ctx.bool_val(true); + if(lits.size() == 1) + return lits[0]; + return ctx.make(And,lits); + } - /* This is a wrapper for a solver that is intended to compute - implicants from models. It works around a problem in Z3 with - models in the non-extensional array theory. It does this by - naming all of the store terms in a formula. That is, (store ...) - is replaced by "name" with an added constraint name = (store - ...). This allows us to determine from the model whether an array - equality is true or false (it is false if the two sides are - mapped to different function symbols, even if they have the same - contents). - */ + /* This is a wrapper for a solver that is intended to compute + implicants from models. It works around a problem in Z3 with + models in the non-extensional array theory. It does this by + naming all of the store terms in a formula. That is, (store ...) + is replaced by "name" with an added constraint name = (store + ...). This allows us to determine from the model whether an array + equality is true or false (it is false if the two sides are + mapped to different function symbols, even if they have the same + contents). + */ - struct implicant_solver { - RPFP *owner; - solver &aux_solver; - std::vector assumps, namings; - std::vector assump_stack, naming_stack; - hash_map renaming, renaming_memo; + struct implicant_solver { + RPFP *owner; + solver &aux_solver; + std::vector assumps, namings; + std::vector assump_stack, naming_stack; + hash_map renaming, renaming_memo; - void add(const expr &e){ - expr t = e; - if(!aux_solver.extensional_array_theory()){ - unsigned i = namings.size(); - t = owner->ExtractStores(renaming_memo,t,namings,renaming); - for(; i < namings.size(); i++) - aux_solver.add(namings[i]); - } - assumps.push_back(t); - aux_solver.add(t); - } + void add(const expr &e){ + expr t = e; + if(!aux_solver.extensional_array_theory()){ + unsigned i = namings.size(); + t = owner->ExtractStores(renaming_memo,t,namings,renaming); + for(; i < namings.size(); i++) + aux_solver.add(namings[i]); + } + assumps.push_back(t); + aux_solver.add(t); + } - void push() { - assump_stack.push_back(assumps.size()); - naming_stack.push_back(namings.size()); - aux_solver.push(); - } + void push() { + assump_stack.push_back(assumps.size()); + naming_stack.push_back(namings.size()); + aux_solver.push(); + } - // When we pop the solver, we have to re-add any namings that were lost + // When we pop the solver, we have to re-add any namings that were lost - void pop(int n) { - aux_solver.pop(n); - int new_assumps = assump_stack[assump_stack.size()-n]; - int new_namings = naming_stack[naming_stack.size()-n]; - for(unsigned i = new_namings; i < namings.size(); i++) - aux_solver.add(namings[i]); - assumps.resize(new_assumps); - namings.resize(new_namings); - assump_stack.resize(assump_stack.size()-1); - naming_stack.resize(naming_stack.size()-1); - } + void pop(int n) { + aux_solver.pop(n); + int new_assumps = assump_stack[assump_stack.size()-n]; + int new_namings = naming_stack[naming_stack.size()-n]; + for(unsigned i = new_namings; i < namings.size(); i++) + aux_solver.add(namings[i]); + assumps.resize(new_assumps); + namings.resize(new_namings); + assump_stack.resize(assump_stack.size()-1); + naming_stack.resize(naming_stack.size()-1); + } - check_result check() { - return aux_solver.check(); - } + check_result check() { + return aux_solver.check(); + } - model get_model() { - return aux_solver.get_model(); - } + model get_model() { + return aux_solver.get_model(); + } - expr get_implicant() { - owner->dualModel = aux_solver.get_model(); - expr dual = owner->ctx.make(And,assumps); - bool ext = aux_solver.extensional_array_theory(); - expr eu = owner->UnderapproxFullFormula(dual,ext); - // if we renamed store terms, we have to undo - if(!ext) - eu = owner->SubstRec(renaming,eu); - return eu; - } + expr get_implicant() { + owner->dualModel = aux_solver.get_model(); + expr dual = owner->ctx.make(And,assumps); + bool ext = aux_solver.extensional_array_theory(); + expr eu = owner->UnderapproxFullFormula(dual,ext); + // if we renamed store terms, we have to undo + if(!ext) + eu = owner->SubstRec(renaming,eu); + return eu; + } - implicant_solver(RPFP *_owner, solver &_aux_solver) - : owner(_owner), aux_solver(_aux_solver) - {} - }; + implicant_solver(RPFP *_owner, solver &_aux_solver) + : owner(_owner), aux_solver(_aux_solver) + {} + }; - // set up edge constraint in aux solver - void RPFP::AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge){ - if(!edge->dual.null()) - aux_solver.add(edge->dual); - for(unsigned i = 0; i < edge->constraints.size(); i++){ - expr tl = edge->constraints[i]; - aux_solver.add(tl); + // set up edge constraint in aux solver + void RPFP::AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge){ + if(!edge->dual.null()) + aux_solver.add(edge->dual); + for(unsigned i = 0; i < edge->constraints.size(); i++){ + expr tl = edge->constraints[i]; + aux_solver.add(tl); + } } - } - void RPFP::AddEdgeToSolver(Edge *edge){ - if(!edge->dual.null()) - aux_solver.add(edge->dual); - for(unsigned i = 0; i < edge->constraints.size(); i++){ - expr tl = edge->constraints[i]; - aux_solver.add(tl); + void RPFP::AddEdgeToSolver(Edge *edge){ + if(!edge->dual.null()) + aux_solver.add(edge->dual); + for(unsigned i = 0; i < edge->constraints.size(); i++){ + expr tl = edge->constraints[i]; + aux_solver.add(tl); + } } - } - static int by_case_counter = 0; + static int by_case_counter = 0; - void RPFP::InterpolateByCases(Node *root, Node *node){ - timer_start("InterpolateByCases"); - bool axioms_added = false; - hash_set axioms_needed; - const std::vector &theory = ls->get_axioms(); - for(unsigned i = 0; i < theory.size(); i++) - axioms_needed.insert(theory[i]); - implicant_solver is(this,aux_solver); - is.push(); - AddEdgeToSolver(is,node->Outgoing); - node->Annotation.SetEmpty(); - hash_set *core = new hash_set; - core->insert(node->Outgoing->dual); - expr prev_annot = ctx.bool_val(false); - expr prev_impl = ctx.bool_val(false); - int repeated_case_count = 0; - while(1){ - by_case_counter++; - is.push(); - expr annot = !GetAnnotation(node); - Transformer old_annot = node->Annotation; - is.add(annot); - if(is.check() == unsat){ - is.pop(1); - break; - } - is.pop(1); - Push(); - expr the_impl = is.get_implicant(); - if(eq(the_impl,prev_impl)){ - // std::cout << "got old implicant\n"; - repeated_case_count++; - } - prev_impl = the_impl; - ConstrainEdgeLocalized(node->Outgoing,the_impl); - ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this? + void RPFP::InterpolateByCases(Node *root, Node *node){ + timer_start("InterpolateByCases"); + bool axioms_added = false; + hash_set axioms_needed; + const std::vector &theory = ls->get_axioms(); + for(unsigned i = 0; i < theory.size(); i++) + axioms_needed.insert(theory[i]); + implicant_solver is(this,aux_solver); + is.push(); + AddEdgeToSolver(is,node->Outgoing); + node->Annotation.SetEmpty(); + hash_set *core = new hash_set; + core->insert(node->Outgoing->dual); + expr prev_annot = ctx.bool_val(false); + expr prev_impl = ctx.bool_val(false); + int repeated_case_count = 0; + while(1){ + by_case_counter++; + is.push(); + expr annot = !GetAnnotation(node); + Transformer old_annot = node->Annotation; + is.add(annot); + if(is.check() == unsat){ + is.pop(1); + break; + } + is.pop(1); + Push(); + expr the_impl = is.get_implicant(); + if(eq(the_impl,prev_impl)){ + // std::cout << "got old implicant\n"; + repeated_case_count++; + } + prev_impl = the_impl; + ConstrainEdgeLocalized(node->Outgoing,the_impl); + ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this? - { - check_result foo = Check(root); - if(foo != unsat){ - Pop(1); - is.pop(1); - delete core; - timer_stop("InterpolateByCases"); - throw ReallyBad(); - // slvr().print("should_be_unsat.smt2"); - // throw "should be unsat"; - } - std::vector assumps, axioms_to_add; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++){ - (*core).insert(assumps[i]); - if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ - axioms_to_add.push_back(assumps[i]); - axioms_needed.erase(assumps[i]); - } - } - // AddToProofCore(*core); - SolveSingleNode(root,node); + { + check_result foo = Check(root); + if(foo != unsat){ + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw ReallyBad(); + // slvr().print("should_be_unsat.smt2"); + // throw "should be unsat"; + } + std::vector assumps, axioms_to_add; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++){ + (*core).insert(assumps[i]); + if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ + axioms_to_add.push_back(assumps[i]); + axioms_needed.erase(assumps[i]); + } + } + // AddToProofCore(*core); + SolveSingleNode(root,node); - { - expr itp = GetAnnotation(node); - dualModel = is.get_model(); // TODO: what does this mean? - std::vector case_lits; - itp = StrengthenFormulaByCaseSplitting(itp, case_lits); - SetAnnotation(node,itp); - node->Annotation.Formula = node->Annotation.Formula.simplify(); - } + { + expr itp = GetAnnotation(node); + dualModel = is.get_model(); // TODO: what does this mean? + std::vector case_lits; + itp = StrengthenFormulaByCaseSplitting(itp, case_lits); + SetAnnotation(node,itp); + node->Annotation.Formula = node->Annotation.Formula.simplify(); + } - for(unsigned i = 0; i < axioms_to_add.size(); i++) - is.add(axioms_to_add[i]); + for(unsigned i = 0; i < axioms_to_add.size(); i++) + is.add(axioms_to_add[i]); #define TEST_BAD #ifdef TEST_BAD - { - static int bad_count = 0, num_bads = 1; - if(bad_count >= num_bads){ - bad_count = 0; - num_bads = num_bads * 2; - Pop(1); - is.pop(1); - delete core; - timer_stop("InterpolateByCases"); - throw Bad(); - } - bad_count++; - } + { + static int bad_count = 0, num_bads = 1; + if(bad_count >= num_bads){ + bad_count = 0; + num_bads = num_bads * 2; + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw Bad(); + } + bad_count++; + } #endif - } + } - if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ - //looks_bad: - if(!axioms_added){ - // add the axioms in the off chance they are useful - const std::vector &theory = ls->get_axioms(); - for(unsigned i = 0; i < theory.size(); i++) - is.add(theory[i]); - axioms_added = true; - } - else { - //#define KILL_ON_BAD_INTERPOLANT + if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ + //looks_bad: + if(!axioms_added){ + // add the axioms in the off chance they are useful + const std::vector &theory = ls->get_axioms(); + for(unsigned i = 0; i < theory.size(); i++) + is.add(theory[i]); + axioms_added = true; + } + else { + //#define KILL_ON_BAD_INTERPOLANT #ifdef KILL_ON_BAD_INTERPOLANT - std::cout << "bad in InterpolateByCase -- core:\n"; + std::cout << "bad in InterpolateByCase -- core:\n"; #if 0 - std::vector assumps; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++) - assumps[i].show(); + std::vector assumps; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++) + assumps[i].show(); #endif - std::cout << "checking for inconsistency\n"; - std::cout << "model:\n"; - is.get_model().show(); - expr impl = is.get_implicant(); - std::vector conjuncts; - CollectConjuncts(impl,conjuncts,true); - std::cout << "impl:\n"; - for(unsigned i = 0; i < conjuncts.size(); i++) - conjuncts[i].show(); - std::cout << "annot:\n"; - annot.show(); - is.add(annot); - for(unsigned i = 0; i < conjuncts.size(); i++) - is.add(conjuncts[i]); - if(is.check() == unsat){ - std::cout << "inconsistent!\n"; - std::vector is_assumps; - is.aux_solver.get_proof().get_assumptions(is_assumps); - std::cout << "core:\n"; - for(unsigned i = 0; i < is_assumps.size(); i++) - is_assumps[i].show(); - } - else { - std::cout << "consistent!\n"; - is.aux_solver.print("should_be_inconsistent.smt2"); - } - std::cout << "by_case_counter = " << by_case_counter << "\n"; - throw "ack!"; + std::cout << "checking for inconsistency\n"; + std::cout << "model:\n"; + is.get_model().show(); + expr impl = is.get_implicant(); + std::vector conjuncts; + CollectConjuncts(impl,conjuncts,true); + std::cout << "impl:\n"; + for(unsigned i = 0; i < conjuncts.size(); i++) + conjuncts[i].show(); + std::cout << "annot:\n"; + annot.show(); + is.add(annot); + for(unsigned i = 0; i < conjuncts.size(); i++) + is.add(conjuncts[i]); + if(is.check() == unsat){ + std::cout << "inconsistent!\n"; + std::vector is_assumps; + is.aux_solver.get_proof().get_assumptions(is_assumps); + std::cout << "core:\n"; + for(unsigned i = 0; i < is_assumps.size(); i++) + is_assumps[i].show(); + } + else { + std::cout << "consistent!\n"; + is.aux_solver.print("should_be_inconsistent.smt2"); + } + std::cout << "by_case_counter = " << by_case_counter << "\n"; + throw "ack!"; #endif - Pop(1); - is.pop(1); - delete core; - timer_stop("InterpolateByCases"); - throw ReallyBad(); - } - } - Pop(1); - prev_annot = node->Annotation.Formula; - node->Annotation.UnionWith(old_annot); + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw ReallyBad(); + } + } + Pop(1); + prev_annot = node->Annotation.Formula; + node->Annotation.UnionWith(old_annot); + } + if(proof_core) + delete proof_core; // shouldn't happen + proof_core = core; + is.pop(1); + timer_stop("InterpolateByCases"); } - if(proof_core) - delete proof_core; // shouldn't happen - proof_core = core; - is.pop(1); - timer_stop("InterpolateByCases"); - } - void RPFP::Generalize(Node *root, Node *node){ - timer_start("Generalize"); - aux_solver.push(); - AddEdgeToSolver(node->Outgoing); - expr fmla = GetAnnotation(node); - std::vector conjuncts; - CollectConjuncts(fmla,conjuncts,false); - GreedyReduce(aux_solver,conjuncts); // try to remove conjuncts one at a tme - aux_solver.pop(1); - NegateLits(conjuncts); - SetAnnotation(node,SimplifyOr(conjuncts)); - timer_stop("Generalize"); - } - - RPFP_caching::edge_solver &RPFP_caching::SolverForEdge(Edge *edge, bool models, bool axioms){ - edge_solver &es = edge_solvers[edge]; - uptr &p = es.slvr; - if(!p.get()){ - scoped_no_proof no_proofs_please(ctx.m()); // no proofs - p.set(new solver(ctx,true,models)); // no models - if(axioms){ - RPFP::LogicSolver *ls = edge->owner->ls; - const std::vector &axs = ls->get_axioms(); - for(unsigned i = 0; i < axs.size(); i++) - p.get()->add(axs[i]); - } + void RPFP::Generalize(Node *root, Node *node){ + timer_start("Generalize"); + aux_solver.push(); + AddEdgeToSolver(node->Outgoing); + expr fmla = GetAnnotation(node); + std::vector conjuncts; + CollectConjuncts(fmla,conjuncts,false); + GreedyReduce(aux_solver,conjuncts); // try to remove conjuncts one at a tme + aux_solver.pop(1); + NegateLits(conjuncts); + SetAnnotation(node,SimplifyOr(conjuncts)); + timer_stop("Generalize"); + } + + RPFP_caching::edge_solver &RPFP_caching::SolverForEdge(Edge *edge, bool models, bool axioms){ + edge_solver &es = edge_solvers[edge]; + uptr &p = es.slvr; + if(!p.get()){ + scoped_no_proof no_proofs_please(ctx.m()); // no proofs + p.set(new solver(ctx,true,models)); // no models + if(axioms){ + RPFP::LogicSolver *ls = edge->owner->ls; + const std::vector &axs = ls->get_axioms(); + for(unsigned i = 0; i < axs.size(); i++) + p.get()->add(axs[i]); + } + } + return es; } - return es; - } - // caching version of above - void RPFP_caching::GeneralizeCache(Edge *edge){ - timer_start("Generalize"); - scoped_solver_for_edge ssfe(this,edge); - Node *node = edge->Parent; - std::vector assumps, core, conjuncts; - AssertEdgeCache(edge,assumps); - for(unsigned i = 0; i < edge->Children.size(); i++){ - expr as = GetAnnotation(edge->Children[i]); - std::vector clauses; - if(!as.is_true()){ - CollectConjuncts(as.arg(1),clauses); - for(unsigned j = 0; j < clauses.size(); j++) - GetAssumptionLits(as.arg(0) || clauses[j],assumps); - } - } - expr fmla = GetAnnotation(node); - std::vector lits; - if(fmla.is_true()){ - timer_stop("Generalize"); - return; - } - assumps.push_back(fmla.arg(0).arg(0)); - CollectConjuncts(!fmla.arg(1),lits); + // caching version of above + void RPFP_caching::GeneralizeCache(Edge *edge){ + timer_start("Generalize"); + scoped_solver_for_edge ssfe(this,edge); + Node *node = edge->Parent; + std::vector assumps, core, conjuncts; + AssertEdgeCache(edge,assumps); + for(unsigned i = 0; i < edge->Children.size(); i++){ + expr as = GetAnnotation(edge->Children[i]); + std::vector clauses; + if(!as.is_true()){ + CollectConjuncts(as.arg(1),clauses); + for(unsigned j = 0; j < clauses.size(); j++) + GetAssumptionLits(as.arg(0) || clauses[j],assumps); + } + } + expr fmla = GetAnnotation(node); + std::vector lits; + if(fmla.is_true()){ + timer_stop("Generalize"); + return; + } + assumps.push_back(fmla.arg(0).arg(0)); + CollectConjuncts(!fmla.arg(1),lits); #if 0 - for(unsigned i = 0; i < lits.size(); i++){ - const expr &lit = lits[i]; - if(lit.is_app() && lit.decl().get_decl_kind() == Equal){ - lits[i] = ctx.make(Leq,lit.arg(0),lit.arg(1)); - lits.push_back(ctx.make(Leq,lit.arg(1),lit.arg(0))); - } - } + for(unsigned i = 0; i < lits.size(); i++){ + const expr &lit = lits[i]; + if(lit.is_app() && lit.decl().get_decl_kind() == Equal){ + lits[i] = ctx.make(Leq,lit.arg(0),lit.arg(1)); + lits.push_back(ctx.make(Leq,lit.arg(1),lit.arg(0))); + } + } #endif - hash_map lit_map; - for(unsigned i = 0; i < lits.size(); i++) - GetAssumptionLits(lits[i],core,&lit_map); - GreedyReduceCache(assumps,core); - for(unsigned i = 0; i < core.size(); i++) - conjuncts.push_back(lit_map[core[i]]); - NegateLits(conjuncts); - SetAnnotation(node,SimplifyOr(conjuncts)); - timer_stop("Generalize"); - } + hash_map lit_map; + for(unsigned i = 0; i < lits.size(); i++) + GetAssumptionLits(lits[i],core,&lit_map); + GreedyReduceCache(assumps,core); + for(unsigned i = 0; i < core.size(); i++) + conjuncts.push_back(lit_map[core[i]]); + NegateLits(conjuncts); + SetAnnotation(node,SimplifyOr(conjuncts)); + timer_stop("Generalize"); + } - // caching version of above - bool RPFP_caching::PropagateCache(Edge *edge){ - timer_start("PropagateCache"); - scoped_solver_for_edge ssfe(this,edge); - bool some = false; + // caching version of above + bool RPFP_caching::PropagateCache(Edge *edge){ + timer_start("PropagateCache"); + scoped_solver_for_edge ssfe(this,edge); + bool some = false; + { + std::vector candidates, skip; + Node *node = edge->Parent; + CollectConjuncts(node->Annotation.Formula,skip); + for(unsigned i = 0; i < edge->Children.size(); i++){ + Node *child = edge->Children[i]; + if(child->map == node->map){ + CollectConjuncts(child->Annotation.Formula,candidates); + break; + } + } + if(candidates.empty()) goto done; + hash_set skip_set; + std::copy(skip.begin(),skip.end(),std::inserter(skip_set,skip_set.begin())); + std::vector new_candidates; + for(unsigned i = 0; i < candidates.size(); i++) + if(skip_set.find(candidates[i]) == skip_set.end()) + new_candidates.push_back(candidates[i]); + candidates.swap(new_candidates); + if(candidates.empty()) goto done; + std::vector assumps, core, conjuncts; + AssertEdgeCache(edge,assumps); + for(unsigned i = 0; i < edge->Children.size(); i++){ + expr ass = GetAnnotation(edge->Children[i]); + if(eq(ass,ctx.bool_val(true))) + continue; + std::vector clauses; + CollectConjuncts(ass.arg(1),clauses); + for(unsigned j = 0; j < clauses.size(); j++) + GetAssumptionLits(ass.arg(0) || clauses[j],assumps); + } + for(unsigned i = 0; i < candidates.size(); i++){ + unsigned old_size = assumps.size(); + node->Annotation.Formula = candidates[i]; + expr fmla = GetAnnotation(node); + assumps.push_back(fmla.arg(0).arg(0)); + GetAssumptionLits(!fmla.arg(1),assumps); + std::vector full_core; + check_result res = CheckCore(assumps,full_core); + if(res == unsat) + conjuncts.push_back(candidates[i]); + assumps.resize(old_size); + } + if(conjuncts.empty()) + goto done; + SetAnnotation(node,SimplifyAnd(conjuncts)); + some = true; + } + done: + timer_stop("PropagateCache"); + return some; + } + + + /** Push a scope. Assertions made after Push can be undone by Pop. */ + + void RPFP::Push() { - std::vector candidates, skip; - Node *node = edge->Parent; - CollectConjuncts(node->Annotation.Formula,skip); - for(unsigned i = 0; i < edge->Children.size(); i++){ - Node *child = edge->Children[i]; - if(child->map == node->map){ - CollectConjuncts(child->Annotation.Formula,candidates); - break; - } - } - if(candidates.empty()) goto done; - hash_set skip_set; - std::copy(skip.begin(),skip.end(),std::inserter(skip_set,skip_set.begin())); - std::vector new_candidates; - for(unsigned i = 0; i < candidates.size(); i++) - if(skip_set.find(candidates[i]) == skip_set.end()) - new_candidates.push_back(candidates[i]); - candidates.swap(new_candidates); - if(candidates.empty()) goto done; - std::vector assumps, core, conjuncts; - AssertEdgeCache(edge,assumps); - for(unsigned i = 0; i < edge->Children.size(); i++){ - expr ass = GetAnnotation(edge->Children[i]); - if(eq(ass,ctx.bool_val(true))) - continue; - std::vector clauses; - CollectConjuncts(ass.arg(1),clauses); - for(unsigned j = 0; j < clauses.size(); j++) - GetAssumptionLits(ass.arg(0) || clauses[j],assumps); - } - for(unsigned i = 0; i < candidates.size(); i++){ - unsigned old_size = assumps.size(); - node->Annotation.Formula = candidates[i]; - expr fmla = GetAnnotation(node); - assumps.push_back(fmla.arg(0).arg(0)); - GetAssumptionLits(!fmla.arg(1),assumps); - std::vector full_core; - check_result res = CheckCore(assumps,full_core); - if(res == unsat) - conjuncts.push_back(candidates[i]); - assumps.resize(old_size); - } - if(conjuncts.empty()) - goto done; - SetAnnotation(node,SimplifyAnd(conjuncts)); - some = true; + stack.push_back(stack_entry()); + slvr_push(); } - done: - timer_stop("PropagateCache"); - return some; - } - - - /** Push a scope. Assertions made after Push can be undone by Pop. */ - - void RPFP::Push() - { - stack.push_back(stack_entry()); - slvr_push(); - } - /** Pop a scope (see Push). Note, you cannot pop axioms. */ + /** Pop a scope (see Push). Note, you cannot pop axioms. */ - void RPFP::Pop(int num_scopes) - { - slvr_pop(num_scopes); - for (int i = 0; i < num_scopes; i++) - { - stack_entry &back = stack.back(); - for(std::list::iterator it = back.edges.begin(), en = back.edges.end(); it != en; ++it) - (*it)->dual = expr(ctx,NULL); - for(std::list::iterator it = back.nodes.begin(), en = back.nodes.end(); it != en; ++it) - (*it)->dual = expr(ctx,NULL); - for(std::list >::iterator it = back.constraints.begin(), en = back.constraints.end(); it != en; ++it) - (*it).first->constraints.pop_back(); - stack.pop_back(); - } - } + void RPFP::Pop(int num_scopes) + { + slvr_pop(num_scopes); + for (int i = 0; i < num_scopes; i++) + { + stack_entry &back = stack.back(); + for(std::list::iterator it = back.edges.begin(), en = back.edges.end(); it != en; ++it) + (*it)->dual = expr(ctx,NULL); + for(std::list::iterator it = back.nodes.begin(), en = back.nodes.end(); it != en; ++it) + (*it)->dual = expr(ctx,NULL); + for(std::list >::iterator it = back.constraints.begin(), en = back.constraints.end(); it != en; ++it) + (*it).first->constraints.pop_back(); + stack.pop_back(); + } + } - /** Erase the proof by performing a Pop, Push and re-assertion of - all the popped constraints */ + /** Erase the proof by performing a Pop, Push and re-assertion of + all the popped constraints */ - void RPFP::PopPush(){ - slvr_pop(1); - slvr_push(); - stack_entry &back = stack.back(); - for(std::list::iterator it = back.edges.begin(), en = back.edges.end(); it != en; ++it) - slvr_add((*it)->dual); - for(std::list::iterator it = back.nodes.begin(), en = back.nodes.end(); it != en; ++it) - slvr_add((*it)->dual); - for(std::list >::iterator it = back.constraints.begin(), en = back.constraints.end(); it != en; ++it) - slvr_add((*it).second); - } + void RPFP::PopPush(){ + slvr_pop(1); + slvr_push(); + stack_entry &back = stack.back(); + for(std::list::iterator it = back.edges.begin(), en = back.edges.end(); it != en; ++it) + slvr_add((*it)->dual); + for(std::list::iterator it = back.nodes.begin(), en = back.nodes.end(); it != en; ++it) + slvr_add((*it)->dual); + for(std::list >::iterator it = back.constraints.begin(), en = back.constraints.end(); it != en; ++it) + slvr_add((*it).second); + } - // This returns a new FuncDel with same sort as top-level function - // of term t, but with numeric suffix appended to name. + // This returns a new FuncDel with same sort as top-level function + // of term t, but with numeric suffix appended to name. - Z3User::FuncDecl Z3User::SuffixFuncDecl(Term t, int n) - { - std::string name = t.decl().name().str() + "_" + string_of_int(n); - std::vector sorts; + Z3User::FuncDecl Z3User::SuffixFuncDecl(Term t, int n) + { + std::string name = t.decl().name().str() + "_" + string_of_int(n); + std::vector sorts; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + sorts.push_back(t.arg(i).get_sort()); + return ctx.function(name.c_str(), nargs, &sorts[0], t.get_sort()); + } + + Z3User::FuncDecl Z3User::RenumberPred(const FuncDecl &f, int n) + { + std::string name = f.name().str(); + name = name.substr(0,name.rfind('_')) + "_" + string_of_int(n); + int arity = f.arity(); + std::vector domain; + for(int i = 0; i < arity; i++) + domain.push_back(f.domain(i)); + return ctx.function(name.c_str(), arity, &domain[0], f.range()); + } + + Z3User::FuncDecl Z3User::NumberPred(const FuncDecl &f, int n) + { + std::string name = f.name().str(); + name = name + "_" + string_of_int(n); + int arity = f.arity(); + std::vector domain; + for(int i = 0; i < arity; i++) + domain.push_back(f.domain(i)); + return ctx.function(name.c_str(), arity, &domain[0], f.range()); + } + + // Scan the clause body for occurrences of the predicate unknowns + + RPFP::Term RPFP::ScanBody(hash_map &memo, + const Term &t, + hash_map &pmap, + std::vector &parms, + std::vector &nodes) + { + if(memo.find(t) != memo.end()) + return memo[t]; + Term res(ctx); + if (t.is_app()) { + func_decl f = t.decl(); + if(pmap.find(f) != pmap.end()){ + nodes.push_back(pmap[f]); + f = SuffixFuncDecl(t,parms.size()); + parms.push_back(f); + } int nargs = t.num_args(); + std::vector args; for(int i = 0; i < nargs; i++) - sorts.push_back(t.arg(i).get_sort()); - return ctx.function(name.c_str(), nargs, &sorts[0], t.get_sort()); + args.push_back(ScanBody(memo,t.arg(i),pmap,parms,nodes)); + res = f(nargs,&args[0]); } + else if (t.is_quantifier()) + res = CloneQuantifier(t,ScanBody(memo,t.body(),pmap,parms,nodes)); + else + res = t; + memo[t] = res; + return res; + } - Z3User::FuncDecl Z3User::RenumberPred(const FuncDecl &f, int n) - { - std::string name = f.name().str(); - name = name.substr(0,name.rfind('_')) + "_" + string_of_int(n); - int arity = f.arity(); - std::vector domain; - for(int i = 0; i < arity; i++) - domain.push_back(f.domain(i)); - return ctx.function(name.c_str(), arity, &domain[0], f.range()); + // return the func_del of an app if it is uninterpreted + + bool Z3User::get_relation(const Term &t, func_decl &R){ + if(!t.is_app()) + return false; + R = t.decl(); + return R.get_decl_kind() == Uninterpreted; + } + + // return true if term is an individual variable + // TODO: have to check that it is not a background symbol + + bool Z3User::is_variable(const Term &t){ + if(!t.is_app()) + return t.is_var(); + return t.decl().get_decl_kind() == Uninterpreted + && t.num_args() == 0; + } + + RPFP::Term RPFP::RemoveLabelsRec(hash_map &memo, const Term &t, + std::vector &lbls){ + if(memo.find(t) != memo.end()) + return memo[t]; + Term res(ctx); + if (t.is_app()){ + func_decl f = t.decl(); + std::vector names; + bool pos; + if(t.is_label(pos,names)){ + res = RemoveLabelsRec(memo,t.arg(0),lbls); + for(unsigned i = 0; i < names.size(); i++) + lbls.push_back(label_struct(names[i],res,pos)); + } + else { + int nargs = t.num_args(); + std::vector args; + for(int i = 0; i < nargs; i++) + args.push_back(RemoveLabelsRec(memo,t.arg(i),lbls)); + res = f(nargs,&args[0]); + } } + else if (t.is_quantifier()) + res = CloneQuantifier(t,RemoveLabelsRec(memo,t.body(),lbls)); + else + res = t; + memo[t] = res; + return res; + } - Z3User::FuncDecl Z3User::NumberPred(const FuncDecl &f, int n) - { - std::string name = f.name().str(); - name = name + "_" + string_of_int(n); - int arity = f.arity(); - std::vector domain; - for(int i = 0; i < arity; i++) - domain.push_back(f.domain(i)); - return ctx.function(name.c_str(), arity, &domain[0], f.range()); + RPFP::Term RPFP::RemoveLabels(const Term &t, std::vector &lbls){ + hash_map memo ; + return RemoveLabelsRec(memo,t,lbls); + } + + RPFP::Term RPFP::SubstBoundRec(hash_map > &memo, hash_map &subst, int level, const Term &t) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo[level].insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) + { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + if(nargs == 0 && f.get_decl_kind() == Uninterpreted) + ls->declare_constant(f); // keep track of background constants + for(int i = 0; i < nargs; i++) + args.push_back(SubstBoundRec(memo, subst, level, t.arg(i))); + res = f(args.size(),&args[0]); + } + else if (t.is_quantifier()){ + int bound = t.get_quantifier_num_bound(); + std::vector pats; + t.get_patterns(pats); + for(unsigned i = 0; i < pats.size(); i++) + pats[i] = SubstBoundRec(memo, subst, level + bound, pats[i]); + res = clone_quantifier(t, SubstBoundRec(memo, subst, level + bound, t.body()), pats); } - - // Scan the clause body for occurrences of the predicate unknowns - - RPFP::Term RPFP::ScanBody(hash_map &memo, - const Term &t, - hash_map &pmap, - std::vector &parms, - std::vector &nodes) - { - if(memo.find(t) != memo.end()) - return memo[t]; - Term res(ctx); - if (t.is_app()) { - func_decl f = t.decl(); - if(pmap.find(f) != pmap.end()){ - nodes.push_back(pmap[f]); - f = SuffixFuncDecl(t,parms.size()); - parms.push_back(f); - } - int nargs = t.num_args(); - std::vector args; - for(int i = 0; i < nargs; i++) - args.push_back(ScanBody(memo,t.arg(i),pmap,parms,nodes)); - res = f(nargs,&args[0]); + else if (t.is_var()) { + int idx = t.get_index_value(); + if(idx >= level && subst.find(idx-level) != subst.end()){ + res = subst[idx-level]; + } + else res = t; + } + else res = t; + return res; } - else if (t.is_quantifier()) - res = CloneQuantifier(t,ScanBody(memo,t.body(),pmap,parms,nodes)); - else - res = t; - memo[t] = res; - return res; - } - // return the func_del of an app if it is uninterpreted - - bool Z3User::get_relation(const Term &t, func_decl &R){ - if(!t.is_app()) - return false; - R = t.decl(); - return R.get_decl_kind() == Uninterpreted; - } - - // return true if term is an individual variable - // TODO: have to check that it is not a background symbol - - bool Z3User::is_variable(const Term &t){ - if(!t.is_app()) - return t.is_var(); - return t.decl().get_decl_kind() == Uninterpreted - && t.num_args() == 0; - } - - RPFP::Term RPFP::RemoveLabelsRec(hash_map &memo, const Term &t, - std::vector &lbls){ - if(memo.find(t) != memo.end()) - return memo[t]; - Term res(ctx); - if (t.is_app()){ - func_decl f = t.decl(); - std::vector names; - bool pos; - if(t.is_label(pos,names)){ - res = RemoveLabelsRec(memo,t.arg(0),lbls); - for(unsigned i = 0; i < names.size(); i++) - lbls.push_back(label_struct(names[i],res,pos)); - } - else { - int nargs = t.num_args(); - std::vector args; - for(int i = 0; i < nargs; i++) - args.push_back(RemoveLabelsRec(memo,t.arg(i),lbls)); - res = f(nargs,&args[0]); - } + RPFP::Term RPFP::SubstBound(hash_map &subst, const Term &t){ + hash_map > memo; + return SubstBoundRec(memo, subst, 0, t); } - else if (t.is_quantifier()) - res = CloneQuantifier(t,RemoveLabelsRec(memo,t.body(),lbls)); - else - res = t; - memo[t] = res; - return res; - } - RPFP::Term RPFP::RemoveLabels(const Term &t, std::vector &lbls){ - hash_map memo ; - return RemoveLabelsRec(memo,t,lbls); - } - - RPFP::Term RPFP::SubstBoundRec(hash_map > &memo, hash_map &subst, int level, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo[level].insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - if(nargs == 0 && f.get_decl_kind() == Uninterpreted) - ls->declare_constant(f); // keep track of background constants - for(int i = 0; i < nargs; i++) - args.push_back(SubstBoundRec(memo, subst, level, t.arg(i))); - res = f(args.size(),&args[0]); - } - else if (t.is_quantifier()){ - int bound = t.get_quantifier_num_bound(); - std::vector pats; - t.get_patterns(pats); - for(unsigned i = 0; i < pats.size(); i++) - pats[i] = SubstBoundRec(memo, subst, level + bound, pats[i]); - res = clone_quantifier(t, SubstBoundRec(memo, subst, level + bound, t.body()), pats); + // Eliminate the deBruijn indices from level to level+num-1 + Z3User::Term Z3User::DeleteBoundRec(hash_map > &memo, int level, int num, const Term &t) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo[level].insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) + { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + args.push_back(DeleteBoundRec(memo, level, num, t.arg(i))); + res = f(args.size(),&args[0]); + } + else if (t.is_quantifier()){ + int bound = t.get_quantifier_num_bound(); + std::vector pats; + t.get_patterns(pats); + for(unsigned i = 0; i < pats.size(); i++) + pats[i] = DeleteBoundRec(memo, level + bound, num, pats[i]); + res = clone_quantifier(t, DeleteBoundRec(memo, level + bound, num, t.body()), pats); + } + else if (t.is_var()) { + int idx = t.get_index_value(); + if(idx >= level){ + res = ctx.make_var(idx-num,t.get_sort()); + } + else res = t; + } + else res = t; + return res; } - else if (t.is_var()) { - int idx = t.get_index_value(); - if(idx >= level && subst.find(idx-level) != subst.end()){ - res = subst[idx-level]; - } - else res = t; - } - else res = t; - return res; - } - - RPFP::Term RPFP::SubstBound(hash_map &subst, const Term &t){ - hash_map > memo; - return SubstBoundRec(memo, subst, 0, t); - } - - // Eliminate the deBruijn indices from level to level+num-1 - Z3User::Term Z3User::DeleteBoundRec(hash_map > &memo, int level, int num, const Term &t) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo[level].insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(DeleteBoundRec(memo, level, num, t.arg(i))); - res = f(args.size(),&args[0]); - } - else if (t.is_quantifier()){ - int bound = t.get_quantifier_num_bound(); - std::vector pats; - t.get_patterns(pats); - for(unsigned i = 0; i < pats.size(); i++) - pats[i] = DeleteBoundRec(memo, level + bound, num, pats[i]); - res = clone_quantifier(t, DeleteBoundRec(memo, level + bound, num, t.body()), pats); - } - else if (t.is_var()) { - int idx = t.get_index_value(); - if(idx >= level){ - res = ctx.make_var(idx-num,t.get_sort()); - } - else res = t; - } - else res = t; - return res; - } - Z3User::Term Z3User::DeleteBound(int level, int num, const Term &t){ - hash_map > memo; - return DeleteBoundRec(memo, level, num, t); - } + Z3User::Term Z3User::DeleteBound(int level, int num, const Term &t){ + hash_map > memo; + return DeleteBoundRec(memo, level, num, t); + } - int Z3User::MaxIndex(hash_map &memo, const Term &t) - { - std::pair foo(t,-1); - std::pair::iterator, bool> bar = memo.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()){ - func_decl f = t.decl(); - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++){ - int m = MaxIndex(memo, t.arg(i)); - if(m > res) - res = m; - } + int Z3User::MaxIndex(hash_map &memo, const Term &t) + { + std::pair foo(t,-1); + std::pair::iterator, bool> bar = memo.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()){ + func_decl f = t.decl(); + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++){ + int m = MaxIndex(memo, t.arg(i)); + if(m > res) + res = m; + } + } + else if (t.is_quantifier()){ + int bound = t.get_quantifier_num_bound(); + res = MaxIndex(memo,t.body()) - bound; + } + else if (t.is_var()) { + res = t.get_index_value(); + } + return res; } - else if (t.is_quantifier()){ - int bound = t.get_quantifier_num_bound(); - res = MaxIndex(memo,t.body()) - bound; - } - else if (t.is_var()) { - res = t.get_index_value(); - } - return res; - } - bool Z3User::IsClosedFormula(const Term &t){ - hash_map memo; - return MaxIndex(memo,t) < 0; - } + bool Z3User::IsClosedFormula(const Term &t){ + hash_map memo; + return MaxIndex(memo,t) < 0; + } - /** Convert a collection of clauses to Nodes and Edges in the RPFP. + /** Convert a collection of clauses to Nodes and Edges in the RPFP. - Predicate unknowns are uninterpreted predicates not - occurring in the background theory. + Predicate unknowns are uninterpreted predicates not + occurring in the background theory. - Clauses are of the form + Clauses are of the form - B => P(t_1,...,t_k) + B => P(t_1,...,t_k) - where P is a predicate unknown and predicate unknowns - occur only positivey in H and only under existential - quantifiers in prenex form. + where P is a predicate unknown and predicate unknowns + occur only positivey in H and only under existential + quantifiers in prenex form. - Each predicate unknown maps to a node. Each clause maps to - an edge. Let C be a clause B => P(t_1,...,t_k) where the - sequence of predicate unknowns occurring in B (in order - of occurrence) is P_1..P_n. The clause maps to a transformer - T where: + Each predicate unknown maps to a node. Each clause maps to + an edge. Let C be a clause B => P(t_1,...,t_k) where the + sequence of predicate unknowns occurring in B (in order + of occurrence) is P_1..P_n. The clause maps to a transformer + T where: - T.Relparams = P_1..P_n - T.Indparams = x_1...x+k - T.Formula = B /\ t_1 = x_1 /\ ... /\ t_k = x_k + T.Relparams = P_1..P_n + T.Indparams = x_1...x+k + T.Formula = B /\ t_1 = x_1 /\ ... /\ t_k = x_k - Throws exception bad_clause(msg,i) if a clause i is - in the wrong form. + Throws exception bad_clause(msg,i) if a clause i is + in the wrong form. - */ + */ - static bool canonical_clause(const expr &clause){ - if(clause.decl().get_decl_kind() != Implies) - return false; - expr arg = clause.arg(1); - return arg.is_app() && (arg.decl().get_decl_kind() == False || - arg.decl().get_decl_kind() == Uninterpreted); - } + static bool canonical_clause(const expr &clause){ + if(clause.decl().get_decl_kind() != Implies) + return false; + expr arg = clause.arg(1); + return arg.is_app() && (arg.decl().get_decl_kind() == False || + arg.decl().get_decl_kind() == Uninterpreted); + } #define USE_QE_LITE - void RPFP::FromClauses(const std::vector &unskolemized_clauses, const std::vector *bounds){ - hash_map pmap; - func_decl fail_pred = ctx.fresh_func_decl("@Fail", ctx.bool_sort()); + void RPFP::FromClauses(const std::vector &unskolemized_clauses, const std::vector *bounds){ + hash_map pmap; + func_decl fail_pred = ctx.fresh_func_decl("@Fail", ctx.bool_sort()); - std::vector clauses(unskolemized_clauses); - // first, skolemize the clauses + std::vector clauses(unskolemized_clauses); + // first, skolemize the clauses #ifndef USE_QE_LITE - for(unsigned i = 0; i < clauses.size(); i++){ - expr &t = clauses[i]; - if (t.is_quantifier() && t.is_quantifier_forall()) { - int bound = t.get_quantifier_num_bound(); - std::vector sorts; - std::vector names; - hash_map subst; - for(int j = 0; j < bound; j++){ - sort the_sort = t.get_quantifier_bound_sort(j); - symbol name = t.get_quantifier_bound_name(j); - expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); - subst[bound-1-j] = skolem; - } - t = SubstBound(subst,t.body()); - } - } + for(unsigned i = 0; i < clauses.size(); i++){ + expr &t = clauses[i]; + if (t.is_quantifier() && t.is_quantifier_forall()) { + int bound = t.get_quantifier_num_bound(); + std::vector sorts; + std::vector names; + hash_map subst; + for(int j = 0; j < bound; j++){ + sort the_sort = t.get_quantifier_bound_sort(j); + symbol name = t.get_quantifier_bound_name(j); + expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); + subst[bound-1-j] = skolem; + } + t = SubstBound(subst,t.body()); + } + } #else - std::vector > substs(clauses.size()); + std::vector > substs(clauses.size()); #endif - // create the nodes from the heads of the clauses + // create the nodes from the heads of the clauses - for(unsigned i = 0; i < clauses.size(); i++){ - Term &clause = clauses[i]; + for(unsigned i = 0; i < clauses.size(); i++){ + Term &clause = clauses[i]; #ifdef USE_QE_LITE - Term &t = clause; - if (t.is_quantifier() && t.is_quantifier_forall()) { - int bound = t.get_quantifier_num_bound(); - std::vector sorts; - std::vector names; - for(int j = 0; j < bound; j++){ - sort the_sort = t.get_quantifier_bound_sort(j); - symbol name = t.get_quantifier_bound_name(j); - expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); - substs[i][bound-1-j] = skolem; - } - clause = t.body(); - } + Term &t = clause; + if (t.is_quantifier() && t.is_quantifier_forall()) { + int bound = t.get_quantifier_num_bound(); + std::vector sorts; + std::vector names; + for(int j = 0; j < bound; j++){ + sort the_sort = t.get_quantifier_bound_sort(j); + symbol name = t.get_quantifier_bound_name(j); + expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); + substs[i][bound-1-j] = skolem; + } + clause = t.body(); + } #endif - if(clause.is_app() && clause.decl().get_decl_kind() == Uninterpreted) - clause = implies(ctx.bool_val(true),clause); - if(!canonical_clause(clause)) - clause = implies((!clause).simplify(),ctx.bool_val(false)); - Term head = clause.arg(1); - func_decl R(ctx); - bool is_query = false; - if (eq(head,ctx.bool_val(false))){ - R = fail_pred; - // R = ctx.constant("@Fail", ctx.bool_sort()).decl(); - is_query = true; - } - else if(!get_relation(head,R)) - throw bad_clause("rhs must be a predicate application",i); - if(pmap.find(R) == pmap.end()){ + if(clause.is_app() && clause.decl().get_decl_kind() == Uninterpreted) + clause = implies(ctx.bool_val(true),clause); + if(!canonical_clause(clause)) + clause = implies((!clause).simplify(),ctx.bool_val(false)); + Term head = clause.arg(1); + func_decl R(ctx); + bool is_query = false; + if (eq(head,ctx.bool_val(false))){ + R = fail_pred; + // R = ctx.constant("@Fail", ctx.bool_sort()).decl(); + is_query = true; + } + else if(!get_relation(head,R)) + throw bad_clause("rhs must be a predicate application",i); + if(pmap.find(R) == pmap.end()){ - // If the node doesn't exitst, create it. The Indparams - // are arbitrary, but we use the rhs arguments if they - // are variables for mnomonic value. + // If the node doesn't exitst, create it. The Indparams + // are arbitrary, but we use the rhs arguments if they + // are variables for mnomonic value. - hash_set seen; - std::vector Indparams; - for(unsigned j = 0; j < head.num_args(); j++){ - Term arg = head.arg(j); - if(!is_variable(arg) || seen.find(arg) != seen.end()){ - std::string name = std::string("@a_") + string_of_int(j); - arg = ctx.constant(name.c_str(),arg.get_sort()); - } - seen.insert(arg); - Indparams.push_back(arg); - } + hash_set seen; + std::vector Indparams; + for(unsigned j = 0; j < head.num_args(); j++){ + Term arg = head.arg(j); + if(!is_variable(arg) || seen.find(arg) != seen.end()){ + std::string name = std::string("@a_") + string_of_int(j); + arg = ctx.constant(name.c_str(),arg.get_sort()); + } + seen.insert(arg); + Indparams.push_back(arg); + } #ifdef USE_QE_LITE - { - hash_map > sb_memo; - for(unsigned j = 0; j < Indparams.size(); j++) - Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]); - } + { + hash_map > sb_memo; + for(unsigned j = 0; j < Indparams.size(); j++) + Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]); + } #endif - Node *node = CreateNode(R(Indparams.size(),&Indparams[0])); - //nodes.push_back(node); - pmap[R] = node; - if (is_query) - node->Bound = CreateRelation(std::vector(), ctx.bool_val(false)); - node->recursion_bound = bounds ? 0 : UINT_MAX; - } - } + Node *node = CreateNode(R(Indparams.size(),&Indparams[0])); + //nodes.push_back(node); + pmap[R] = node; + if (is_query) + node->Bound = CreateRelation(std::vector(), ctx.bool_val(false)); + node->recursion_bound = bounds ? 0 : UINT_MAX; + } + } - bool some_labels = false; + bool some_labels = false; - // create the edges + // create the edges - for(unsigned i = 0; i < clauses.size(); i++){ - Term clause = clauses[i]; - Term body = clause.arg(0); - Term head = clause.arg(1); - func_decl R(ctx); - if (eq(head,ctx.bool_val(false))) - R = fail_pred; - //R = ctx.constant("@Fail", ctx.bool_sort()).decl(); - else get_relation(head,R); - Node *Parent = pmap[R]; - std::vector Indparams; - hash_set seen; - for(unsigned j = 0; j < head.num_args(); j++){ - Term arg = head.arg(j); - if(!is_variable(arg) || seen.find(arg) != seen.end()){ - std::string name = std::string("@a_") + string_of_int(j); - Term var = ctx.constant(name.c_str(),arg.get_sort()); - body = body && (arg == var); - arg = var; - } - seen.insert(arg); - Indparams.push_back(arg); - } + for(unsigned i = 0; i < clauses.size(); i++){ + Term clause = clauses[i]; + Term body = clause.arg(0); + Term head = clause.arg(1); + func_decl R(ctx); + if (eq(head,ctx.bool_val(false))) + R = fail_pred; + //R = ctx.constant("@Fail", ctx.bool_sort()).decl(); + else get_relation(head,R); + Node *Parent = pmap[R]; + std::vector Indparams; + hash_set seen; + for(unsigned j = 0; j < head.num_args(); j++){ + Term arg = head.arg(j); + if(!is_variable(arg) || seen.find(arg) != seen.end()){ + std::string name = std::string("@a_") + string_of_int(j); + Term var = ctx.constant(name.c_str(),arg.get_sort()); + body = body && (arg == var); + arg = var; + } + seen.insert(arg); + Indparams.push_back(arg); + } - // We extract the relparams positionally + // We extract the relparams positionally - std::vector Relparams; - hash_map scan_memo; - std::vector Children; - body = ScanBody(scan_memo,body,pmap,Relparams,Children); - Term labeled = body; - std::vector lbls; // TODO: throw this away for now - body = RemoveLabels(body,lbls); - if(!eq(labeled,body)) - some_labels = true; // remember if there are labels, as we then can't do qe_lite - // body = IneqToEq(body); // UFO converts x=y to (x<=y & x >= y). Undo this. - body = body.simplify(); + std::vector Relparams; + hash_map scan_memo; + std::vector Children; + body = ScanBody(scan_memo,body,pmap,Relparams,Children); + Term labeled = body; + std::vector lbls; // TODO: throw this away for now + body = RemoveLabels(body,lbls); + if(!eq(labeled,body)) + some_labels = true; // remember if there are labels, as we then can't do qe_lite + // body = IneqToEq(body); // UFO converts x=y to (x<=y & x >= y). Undo this. + body = body.simplify(); #ifdef USE_QE_LITE - std::set idxs; - if(!some_labels){ // can't do qe_lite if we have to reconstruct labels - for(unsigned j = 0; j < Indparams.size(); j++) - if(Indparams[j].is_var()) - idxs.insert(Indparams[j].get_index_value()); - body = body.qe_lite(idxs,false); - } - hash_map > sb_memo; - body = SubstBoundRec(sb_memo,substs[i],0,body); - if(some_labels) - labeled = SubstBoundRec(sb_memo,substs[i],0,labeled); - for(unsigned j = 0; j < Indparams.size(); j++) - Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]); + std::set idxs; + if(!some_labels){ // can't do qe_lite if we have to reconstruct labels + for(unsigned j = 0; j < Indparams.size(); j++) + if(Indparams[j].is_var()) + idxs.insert(Indparams[j].get_index_value()); + body = body.qe_lite(idxs,false); + } + hash_map > sb_memo; + body = SubstBoundRec(sb_memo,substs[i],0,body); + if(some_labels) + labeled = SubstBoundRec(sb_memo,substs[i],0,labeled); + for(unsigned j = 0; j < Indparams.size(); j++) + Indparams[j] = SubstBoundRec(sb_memo, substs[i], 0, Indparams[j]); #endif - // Create the edge - Transformer T = CreateTransformer(Relparams,Indparams,body); - Edge *edge = CreateEdge(Parent,T,Children); - edge->labeled = labeled;; // remember for label extraction - if(bounds) - Parent->recursion_bound = std::max(Parent->recursion_bound,(*bounds)[i]); - // edges.push_back(edge); + // Create the edge + Transformer T = CreateTransformer(Relparams,Indparams,body); + Edge *edge = CreateEdge(Parent,T,Children); + edge->labeled = labeled;; // remember for label extraction + if(bounds) + Parent->recursion_bound = std::max(Parent->recursion_bound,(*bounds)[i]); + // edges.push_back(edge); + } + + // undo hoisting of expressions out of loops + RemoveDeadNodes(); + Unhoist(); + // FuseEdges(); } - // undo hoisting of expressions out of loops - RemoveDeadNodes(); - Unhoist(); - // FuseEdges(); - } - - // The following mess is used to undo hoisting of expressions outside loops by compilers + // The following mess is used to undo hoisting of expressions outside loops by compilers - expr RPFP::UnhoistPullRec(hash_map & memo, const expr &w, hash_map & init_defs, hash_map & const_params, hash_map &const_params_inv, std::vector &new_params){ - if(memo.find(w) != memo.end()) - return memo[w]; - expr res; - if(init_defs.find(w) != init_defs.end()){ - expr d = init_defs[w]; - std::vector vars; - hash_set get_vars_memo; - GetVarsRec(get_vars_memo,d,vars); - hash_map map; - for(unsigned j = 0; j < vars.size(); j++){ - expr x = vars[j]; - map[x] = UnhoistPullRec(memo,x,init_defs,const_params,const_params_inv,new_params); - } - expr defn = SubstRec(map,d); - res = defn; + expr RPFP::UnhoistPullRec(hash_map & memo, const expr &w, hash_map & init_defs, hash_map & const_params, hash_map &const_params_inv, std::vector &new_params){ + if(memo.find(w) != memo.end()) + return memo[w]; + expr res; + if(init_defs.find(w) != init_defs.end()){ + expr d = init_defs[w]; + std::vector vars; + hash_set get_vars_memo; + GetVarsRec(get_vars_memo,d,vars); + hash_map map; + for(unsigned j = 0; j < vars.size(); j++){ + expr x = vars[j]; + map[x] = UnhoistPullRec(memo,x,init_defs,const_params,const_params_inv,new_params); + } + expr defn = SubstRec(map,d); + res = defn; + } + else if(const_params_inv.find(w) == const_params_inv.end()){ + std::string old_name = w.decl().name().str(); + func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); + expr y = fresh(); + const_params[y] = w; + const_params_inv[w] = y; + new_params.push_back(y); + res = y; + } + else + res = const_params_inv[w]; + memo[w] = res; + return res; } - else if(const_params_inv.find(w) == const_params_inv.end()){ - std::string old_name = w.decl().name().str(); - func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), w.get_sort()); - expr y = fresh(); - const_params[y] = w; - const_params_inv[w] = y; - new_params.push_back(y); - res = y; + + void RPFP::AddParamsToTransformer(Transformer &trans, const std::vector ¶ms){ + std::copy(params.begin(),params.end(),std::inserter(trans.IndParams,trans.IndParams.end())); } - else - res = const_params_inv[w]; - memo[w] = res; - return res; - } - void RPFP::AddParamsToTransformer(Transformer &trans, const std::vector ¶ms){ - std::copy(params.begin(),params.end(),std::inserter(trans.IndParams,trans.IndParams.end())); - } - - expr RPFP::AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector ¶ms){ - int n = app.num_args(); - std::vector args(n); - for (int i = 0; i < n; i++) - args[i] = app.arg(i); - std::copy(params.begin(),params.end(),std::inserter(args,args.end())); - return new_decl(args); - } - - expr RPFP::GetRelRec(hash_set &memo, const expr &t, const func_decl &rel){ - if(memo.find(t) != memo.end()) - return expr(); - memo.insert(t); - if (t.is_app()) - { - func_decl f = t.decl(); - if(f == rel) - return t; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++){ - expr res = GetRelRec(memo,t.arg(i),rel); - if(!res.null()) - return res; - } - } - else if (t.is_quantifier()) - return GetRelRec(memo,t.body(),rel); - return expr(); - } - - expr RPFP::GetRel(Edge *edge, int child_idx){ - func_decl &rel = edge->F.RelParams[child_idx]; - hash_set memo; - return GetRelRec(memo,edge->F.Formula,rel); - } - - void RPFP::GetDefsRec(const expr &cnst, hash_map &defs){ - if(cnst.is_app()){ - switch(cnst.decl().get_decl_kind()){ - case And: { - int n = cnst.num_args(); - for(int i = 0; i < n; i++) - GetDefsRec(cnst.arg(i),defs); - break; - } - case Equal: { - expr lhs = cnst.arg(0); - expr rhs = cnst.arg(1); - if(IsVar(lhs)) - defs[lhs] = rhs; - break; - } - default: - break; - } + expr RPFP::AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector ¶ms){ + int n = app.num_args(); + std::vector args(n); + for (int i = 0; i < n; i++) + args[i] = app.arg(i); + std::copy(params.begin(),params.end(),std::inserter(args,args.end())); + return new_decl(args); + } + + expr RPFP::GetRelRec(hash_set &memo, const expr &t, const func_decl &rel){ + if(memo.find(t) != memo.end()) + return expr(); + memo.insert(t); + if (t.is_app()) + { + func_decl f = t.decl(); + if(f == rel) + return t; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++){ + expr res = GetRelRec(memo,t.arg(i),rel); + if(!res.null()) + return res; + } + } + else if (t.is_quantifier()) + return GetRelRec(memo,t.body(),rel); + return expr(); + } + + expr RPFP::GetRel(Edge *edge, int child_idx){ + func_decl &rel = edge->F.RelParams[child_idx]; + hash_set memo; + return GetRelRec(memo,edge->F.Formula,rel); + } + + void RPFP::GetDefsRec(const expr &cnst, hash_map &defs){ + if(cnst.is_app()){ + switch(cnst.decl().get_decl_kind()){ + case And: { + int n = cnst.num_args(); + for(int i = 0; i < n; i++) + GetDefsRec(cnst.arg(i),defs); + break; + } + case Equal: { + expr lhs = cnst.arg(0); + expr rhs = cnst.arg(1); + if(IsVar(lhs)) + defs[lhs] = rhs; + break; + } + default: + break; + } + } } - } - void RPFP::GetDefs(const expr &cnst, hash_map &defs){ - // GetDefsRec(IneqToEq(cnst),defs); - GetDefsRec(cnst,defs); - } - - bool RPFP::IsVar(const expr &t){ - return t.is_app() && t.num_args() == 0 && t.decl().get_decl_kind() == Uninterpreted; - } - - void RPFP::GetVarsRec(hash_set &memo, const expr &t, std::vector &vars){ - if(memo.find(t) != memo.end()) - return; - memo.insert(t); - if (t.is_app()) - { - if(IsVar(t)){ - vars.push_back(t); - return; - } - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++){ - GetVarsRec(memo,t.arg(i),vars); - } - } - else if (t.is_quantifier()) - GetVarsRec(memo,t.body(),vars); - } - - void RPFP::AddParamsToNode(Node *node, const std::vector ¶ms){ - int arity = node->Annotation.IndParams.size(); - std::vector domain; - for(int i = 0; i < arity; i++) - domain.push_back(node->Annotation.IndParams[i].get_sort()); - for(unsigned i = 0; i < params.size(); i++) - domain.push_back(params[i].get_sort()); - std::string old_name = node->Name.name().str(); - func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), domain, ctx.bool_sort()); - node->Name = fresh; - AddParamsToTransformer(node->Annotation,params); - AddParamsToTransformer(node->Bound,params); - AddParamsToTransformer(node->Underapprox,params); - } - - void RPFP::UnhoistLoop(Edge *loop_edge, Edge *init_edge){ - loop_edge->F.Formula = IneqToEq(loop_edge->F.Formula); - init_edge->F.Formula = IneqToEq(init_edge->F.Formula); - expr pre = GetRel(loop_edge,0); - if(pre.null()) - return; // this means the loop got simplified away - int nparams = loop_edge->F.IndParams.size(); - hash_map const_params, const_params_inv; - std::vector work_list; - // find the parameters that are constant in the loop - for(int i = 0; i < nparams; i++){ - if(eq(pre.arg(i),loop_edge->F.IndParams[i])){ - const_params[pre.arg(i)] = init_edge->F.IndParams[i]; - const_params_inv[init_edge->F.IndParams[i]] = pre.arg(i); - work_list.push_back(pre.arg(i)); - } + void RPFP::GetDefs(const expr &cnst, hash_map &defs){ + // GetDefsRec(IneqToEq(cnst),defs); + GetDefsRec(cnst,defs); } - // get the definitions in the initialization - hash_map defs,memo,subst; - GetDefs(init_edge->F.Formula,defs); - // try to pull them inside the loop - std::vector new_params; - for(unsigned i = 0; i < work_list.size(); i++){ - expr v = work_list[i]; - expr w = const_params[v]; - expr def = UnhoistPullRec(memo,w,defs,const_params,const_params_inv,new_params); - if(!eq(def,v)) - subst[v] = def; - } - // do the substitutions - if(subst.empty()) - return; - subst[pre] = pre; // don't substitute inside the precondition itself - loop_edge->F.Formula = SubstRec(subst,loop_edge->F.Formula); - loop_edge->F.Formula = ElimIte(loop_edge->F.Formula); - init_edge->F.Formula = ElimIte(init_edge->F.Formula); - // add the new parameters - if(new_params.empty()) - return; - Node *parent = loop_edge->Parent; - AddParamsToNode(parent,new_params); - AddParamsToTransformer(loop_edge->F,new_params); - AddParamsToTransformer(init_edge->F,new_params); - std::vector &incoming = parent->Incoming; - for(unsigned i = 0; i < incoming.size(); i++){ - Edge *in_edge = incoming[i]; - std::vector &chs = in_edge->Children; - for(unsigned j = 0; j < chs.size(); j++) - if(chs[j] == parent){ - expr lit = GetRel(in_edge,j); - expr new_lit = AddParamsToApp(lit,parent->Name,new_params); - func_decl fd = SuffixFuncDecl(new_lit,j); - int nargs = new_lit.num_args(); - std::vector args; - for(int k = 0; k < nargs; k++) - args.push_back(new_lit.arg(k)); - new_lit = fd(nargs,&args[0]); - in_edge->F.RelParams[j] = fd; - hash_map map; - map[lit] = new_lit; - in_edge->F.Formula = SubstRec(map,in_edge->F.Formula); - } - } - } - void RPFP::Unhoist(){ - hash_map > outgoing; - for(unsigned i = 0; i < edges.size(); i++) - outgoing[edges[i]->Parent].push_back(edges[i]); - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - std::vector &outs = outgoing[node]; - // if we're not a simple loop with one entry, give up - if(outs.size() == 2){ - for(int j = 0; j < 2; j++){ - Edge *loop_edge = outs[j]; - Edge *init_edge = outs[1-j]; - if(loop_edge->Children.size() == 1 && loop_edge->Children[0] == loop_edge->Parent){ - UnhoistLoop(loop_edge,init_edge); - break; - } - } - } + bool RPFP::IsVar(const expr &t){ + return t.is_app() && t.num_args() == 0 && t.decl().get_decl_kind() == Uninterpreted; } - } - void RPFP::FuseEdges(){ - hash_map > outgoing; - for(unsigned i = 0; i < edges.size(); i++){ - outgoing[edges[i]->Parent].push_back(edges[i]); + void RPFP::GetVarsRec(hash_set &memo, const expr &t, std::vector &vars){ + if(memo.find(t) != memo.end()) + return; + memo.insert(t); + if (t.is_app()) + { + if(IsVar(t)){ + vars.push_back(t); + return; + } + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++){ + GetVarsRec(memo,t.arg(i),vars); + } + } + else if (t.is_quantifier()) + GetVarsRec(memo,t.body(),vars); } - hash_set edges_to_delete; - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - std::vector &outs = outgoing[node]; - if(outs.size() > 1 && outs.size() <= 16){ - std::vector trs(outs.size()); - for(unsigned j = 0; j < outs.size(); j++) - trs[j] = &outs[j]->F; - Transformer tr = Fuse(trs); - std::vector chs; - for(unsigned j = 0; j < outs.size(); j++) - for(unsigned k = 0; k < outs[j]->Children.size(); k++) - chs.push_back(outs[j]->Children[k]); - CreateEdge(node,tr,chs); - for(unsigned j = 0; j < outs.size(); j++) - edges_to_delete.insert(outs[j]); - } + + void RPFP::AddParamsToNode(Node *node, const std::vector ¶ms){ + int arity = node->Annotation.IndParams.size(); + std::vector domain; + for(int i = 0; i < arity; i++) + domain.push_back(node->Annotation.IndParams[i].get_sort()); + for(unsigned i = 0; i < params.size(); i++) + domain.push_back(params[i].get_sort()); + std::string old_name = node->Name.name().str(); + func_decl fresh = ctx.fresh_func_decl(old_name.c_str(), domain, ctx.bool_sort()); + node->Name = fresh; + AddParamsToTransformer(node->Annotation,params); + AddParamsToTransformer(node->Bound,params); + AddParamsToTransformer(node->Underapprox,params); } - std::vector new_edges; - hash_set all_nodes; - for(unsigned j = 0; j < edges.size(); j++){ - if(edges_to_delete.find(edges[j]) == edges_to_delete.end()){ + + void RPFP::UnhoistLoop(Edge *loop_edge, Edge *init_edge){ + loop_edge->F.Formula = IneqToEq(loop_edge->F.Formula); + init_edge->F.Formula = IneqToEq(init_edge->F.Formula); + expr pre = GetRel(loop_edge,0); + if(pre.null()) + return; // this means the loop got simplified away + int nparams = loop_edge->F.IndParams.size(); + hash_map const_params, const_params_inv; + std::vector work_list; + // find the parameters that are constant in the loop + for(int i = 0; i < nparams; i++){ + if(eq(pre.arg(i),loop_edge->F.IndParams[i])){ + const_params[pre.arg(i)] = init_edge->F.IndParams[i]; + const_params_inv[init_edge->F.IndParams[i]] = pre.arg(i); + work_list.push_back(pre.arg(i)); + } + } + // get the definitions in the initialization + hash_map defs,memo,subst; + GetDefs(init_edge->F.Formula,defs); + // try to pull them inside the loop + std::vector new_params; + for(unsigned i = 0; i < work_list.size(); i++){ + expr v = work_list[i]; + expr w = const_params[v]; + expr def = UnhoistPullRec(memo,w,defs,const_params,const_params_inv,new_params); + if(!eq(def,v)) + subst[v] = def; + } + // do the substitutions + if(subst.empty()) + return; + subst[pre] = pre; // don't substitute inside the precondition itself + loop_edge->F.Formula = SubstRec(subst,loop_edge->F.Formula); + loop_edge->F.Formula = ElimIte(loop_edge->F.Formula); + init_edge->F.Formula = ElimIte(init_edge->F.Formula); + // add the new parameters + if(new_params.empty()) + return; + Node *parent = loop_edge->Parent; + AddParamsToNode(parent,new_params); + AddParamsToTransformer(loop_edge->F,new_params); + AddParamsToTransformer(init_edge->F,new_params); + std::vector &incoming = parent->Incoming; + for(unsigned i = 0; i < incoming.size(); i++){ + Edge *in_edge = incoming[i]; + std::vector &chs = in_edge->Children; + for(unsigned j = 0; j < chs.size(); j++) + if(chs[j] == parent){ + expr lit = GetRel(in_edge,j); + expr new_lit = AddParamsToApp(lit,parent->Name,new_params); + func_decl fd = SuffixFuncDecl(new_lit,j); + int nargs = new_lit.num_args(); + std::vector args; + for(int k = 0; k < nargs; k++) + args.push_back(new_lit.arg(k)); + new_lit = fd(nargs,&args[0]); + in_edge->F.RelParams[j] = fd; + hash_map map; + map[lit] = new_lit; + in_edge->F.Formula = SubstRec(map,in_edge->F.Formula); + } + } + } + + void RPFP::Unhoist(){ + hash_map > outgoing; + for(unsigned i = 0; i < edges.size(); i++) + outgoing[edges[i]->Parent].push_back(edges[i]); + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + std::vector &outs = outgoing[node]; + // if we're not a simple loop with one entry, give up + if(outs.size() == 2){ + for(int j = 0; j < 2; j++){ + Edge *loop_edge = outs[j]; + Edge *init_edge = outs[1-j]; + if(loop_edge->Children.size() == 1 && loop_edge->Children[0] == loop_edge->Parent){ + UnhoistLoop(loop_edge,init_edge); + break; + } + } + } + } + } + + void RPFP::FuseEdges(){ + hash_map > outgoing; + for(unsigned i = 0; i < edges.size(); i++){ + outgoing[edges[i]->Parent].push_back(edges[i]); + } + hash_set edges_to_delete; + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + std::vector &outs = outgoing[node]; + if(outs.size() > 1 && outs.size() <= 16){ + std::vector trs(outs.size()); + for(unsigned j = 0; j < outs.size(); j++) + trs[j] = &outs[j]->F; + Transformer tr = Fuse(trs); + std::vector chs; + for(unsigned j = 0; j < outs.size(); j++) + for(unsigned k = 0; k < outs[j]->Children.size(); k++) + chs.push_back(outs[j]->Children[k]); + CreateEdge(node,tr,chs); + for(unsigned j = 0; j < outs.size(); j++) + edges_to_delete.insert(outs[j]); + } + } + std::vector new_edges; + hash_set all_nodes; + for(unsigned j = 0; j < edges.size(); j++){ + if(edges_to_delete.find(edges[j]) == edges_to_delete.end()){ #if 0 - if(all_nodes.find(edges[j]->Parent) != all_nodes.end()) - throw "help!"; - all_nodes.insert(edges[j]->Parent); + if(all_nodes.find(edges[j]->Parent) != all_nodes.end()) + throw "help!"; + all_nodes.insert(edges[j]->Parent); #endif - new_edges.push_back(edges[j]); - } - else - delete edges[j]; + new_edges.push_back(edges[j]); + } + else + delete edges[j]; + } + edges.swap(new_edges); } - edges.swap(new_edges); - } - void RPFP::MarkLiveNodes(hash_map > &outgoing, hash_set &live_nodes, Node *node){ - if(live_nodes.find(node) != live_nodes.end()) - return; - live_nodes.insert(node); - std::vector &outs = outgoing[node]; - for(unsigned i = 0; i < outs.size(); i++) - for(unsigned j = 0; j < outs[i]->Children.size(); j++) - MarkLiveNodes(outgoing, live_nodes,outs[i]->Children[j]); - } + void RPFP::MarkLiveNodes(hash_map > &outgoing, hash_set &live_nodes, Node *node){ + if(live_nodes.find(node) != live_nodes.end()) + return; + live_nodes.insert(node); + std::vector &outs = outgoing[node]; + for(unsigned i = 0; i < outs.size(); i++) + for(unsigned j = 0; j < outs[i]->Children.size(); j++) + MarkLiveNodes(outgoing, live_nodes,outs[i]->Children[j]); + } - void RPFP::RemoveDeadNodes(){ - hash_map > outgoing; - for(unsigned i = 0; i < edges.size(); i++) - outgoing[edges[i]->Parent].push_back(edges[i]); - hash_set live_nodes; - for(unsigned i = 0; i < nodes.size(); i++) - if(!nodes[i]->Bound.IsFull()) - MarkLiveNodes(outgoing,live_nodes,nodes[i]); - std::vector new_edges; - for(unsigned j = 0; j < edges.size(); j++){ - if(live_nodes.find(edges[j]->Parent) != live_nodes.end()) - new_edges.push_back(edges[j]); - else { - Edge *edge = edges[j]; - for(unsigned int i = 0; i < edge->Children.size(); i++){ - std::vector &ic = edge->Children[i]->Incoming; - for(std::vector::iterator it = ic.begin(), en = ic.end(); it != en; ++it){ - if(*it == edge){ - ic.erase(it); - break; - } - } - } - delete edge; - } + void RPFP::RemoveDeadNodes(){ + hash_map > outgoing; + for(unsigned i = 0; i < edges.size(); i++) + outgoing[edges[i]->Parent].push_back(edges[i]); + hash_set live_nodes; + for(unsigned i = 0; i < nodes.size(); i++) + if(!nodes[i]->Bound.IsFull()) + MarkLiveNodes(outgoing,live_nodes,nodes[i]); + std::vector new_edges; + for(unsigned j = 0; j < edges.size(); j++){ + if(live_nodes.find(edges[j]->Parent) != live_nodes.end()) + new_edges.push_back(edges[j]); + else { + Edge *edge = edges[j]; + for(unsigned int i = 0; i < edge->Children.size(); i++){ + std::vector &ic = edge->Children[i]->Incoming; + for(std::vector::iterator it = ic.begin(), en = ic.end(); it != en; ++it){ + if(*it == edge){ + ic.erase(it); + break; + } + } + } + delete edge; + } + } + edges.swap(new_edges); + std::vector new_nodes; + for(unsigned j = 0; j < nodes.size(); j++){ + if(live_nodes.find(nodes[j]) != live_nodes.end()) + new_nodes.push_back(nodes[j]); + else + delete nodes[j]; + } + nodes.swap(new_nodes); } - edges.swap(new_edges); - std::vector new_nodes; - for(unsigned j = 0; j < nodes.size(); j++){ - if(live_nodes.find(nodes[j]) != live_nodes.end()) - new_nodes.push_back(nodes[j]); - else - delete nodes[j]; - } - nodes.swap(new_nodes); - } - void RPFP::WriteSolution(std::ostream &s){ - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - Term asgn = (node->Name)(node->Annotation.IndParams) == node->Annotation.Formula; - s << asgn << std::endl; + void RPFP::WriteSolution(std::ostream &s){ + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + Term asgn = (node->Name)(node->Annotation.IndParams) == node->Annotation.Formula; + s << asgn << std::endl; + } } - } - void RPFP::WriteEdgeVars(Edge *e, hash_map &memo, const Term &t, std::ostream &s) - { - std::pair foo(t,0); - std::pair::iterator, bool> bar = memo.insert(foo); - // int &res = bar.first->second; - if(!bar.second) return; - hash_map::iterator it = e->varMap.find(t); - if (it != e->varMap.end()){ - return; + void RPFP::WriteEdgeVars(Edge *e, hash_map &memo, const Term &t, std::ostream &s) + { + std::pair foo(t,0); + std::pair::iterator, bool> bar = memo.insert(foo); + // int &res = bar.first->second; + if(!bar.second) return; + hash_map::iterator it = e->varMap.find(t); + if (it != e->varMap.end()){ + return; + } + if (t.is_app()) + { + func_decl f = t.decl(); + // int idx; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + WriteEdgeVars(e, memo, t.arg(i),s); + if (nargs == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)){ + Term rename = HideVariable(t,e->number); + Term value = dualModel.eval(rename); + s << " (= " << t << " " << value << ")\n"; + } + } + else if (t.is_quantifier()) + WriteEdgeVars(e,memo,t.body(),s); + return; } - if (t.is_app()) - { - func_decl f = t.decl(); - // int idx; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - WriteEdgeVars(e, memo, t.arg(i),s); - if (nargs == 0 && f.get_decl_kind() == Uninterpreted && !ls->is_constant(f)){ - Term rename = HideVariable(t,e->number); - Term value = dualModel.eval(rename); - s << " (= " << t << " " << value << ")\n"; - } - } - else if (t.is_quantifier()) - WriteEdgeVars(e,memo,t.body(),s); - return; - } - void RPFP::WriteEdgeAssignment(std::ostream &s, Edge *e){ - s << "(\n"; - hash_map memo; - WriteEdgeVars(e, memo, e->F.Formula ,s); - s << ")\n"; - } - - void RPFP::WriteCounterexample(std::ostream &s, Node *node){ - for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ - Node *child = node->Outgoing->Children[i]; - if(!Empty(child)) - WriteCounterexample(s,child); + void RPFP::WriteEdgeAssignment(std::ostream &s, Edge *e){ + s << "(\n"; + hash_map memo; + WriteEdgeVars(e, memo, e->F.Formula ,s); + s << ")\n"; } - s << "(" << node->number << " : " << EvalNode(node) << " <- "; - for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ - Node *child = node->Outgoing->Children[i]; - if(!Empty(child)) - s << " " << node->Outgoing->Children[i]->number; - } - s << ")" << std::endl; - WriteEdgeAssignment(s,node->Outgoing); - } - RPFP::Term RPFP::ToRuleRec(Edge *e, hash_map &memo, const Term &t, std::vector &quants) - { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - Term &res = bar.first->second; - if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - // int idx; - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(ToRuleRec(e, memo, t.arg(i),quants)); - hash_map::iterator rit = e->relMap.find(f); - if(rit != e->relMap.end()){ - Node* child = e->Children[rit->second]; - FuncDecl op = child->Name; - res = op(args.size(),&args[0]); - } - else { - res = f(args.size(),&args[0]); - if(nargs == 0 && t.decl().get_decl_kind() == Uninterpreted) - quants.push_back(t); - } - } - else if (t.is_quantifier()) - { - Term body = ToRuleRec(e,memo,t.body(),quants); - res = CloneQuantifier(t,body); - } - else res = t; - return res; - } + void RPFP::WriteCounterexample(std::ostream &s, Node *node){ + for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ + Node *child = node->Outgoing->Children[i]; + if(!Empty(child)) + WriteCounterexample(s,child); + } + s << "(" << node->number << " : " << EvalNode(node) << " <- "; + for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ + Node *child = node->Outgoing->Children[i]; + if(!Empty(child)) + s << " " << node->Outgoing->Children[i]->number; + } + s << ")" << std::endl; + WriteEdgeAssignment(s,node->Outgoing); + } + + RPFP::Term RPFP::ToRuleRec(Edge *e, hash_map &memo, const Term &t, std::vector &quants) + { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + Term &res = bar.first->second; + if(!bar.second) return res; + if (t.is_app()) + { + func_decl f = t.decl(); + // int idx; + std::vector args; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + args.push_back(ToRuleRec(e, memo, t.arg(i),quants)); + hash_map::iterator rit = e->relMap.find(f); + if(rit != e->relMap.end()){ + Node* child = e->Children[rit->second]; + FuncDecl op = child->Name; + res = op(args.size(),&args[0]); + } + else { + res = f(args.size(),&args[0]); + if(nargs == 0 && t.decl().get_decl_kind() == Uninterpreted) + quants.push_back(t); + } + } + else if (t.is_quantifier()) + { + Term body = ToRuleRec(e,memo,t.body(),quants); + res = CloneQuantifier(t,body); + } + else res = t; + return res; + } - void RPFP::ToClauses(std::vector &cnsts, FileFormat format){ - cnsts.resize(edges.size()); - for(unsigned i = 0; i < edges.size(); i++){ - Edge *edge = edges[i]; - SetEdgeMaps(edge); - std::vector quants; - hash_map memo; - Term lhs = ToRuleRec(edge, memo, edge->F.Formula,quants); - Term rhs = (edge->Parent->Name)(edge->F.IndParams.size(),&edge->F.IndParams[0]); - for(unsigned j = 0; j < edge->F.IndParams.size(); j++) - ToRuleRec(edge,memo,edge->F.IndParams[j],quants); // just to get quants - Term cnst = implies(lhs,rhs); + void RPFP::ToClauses(std::vector &cnsts, FileFormat format){ + cnsts.resize(edges.size()); + for(unsigned i = 0; i < edges.size(); i++){ + Edge *edge = edges[i]; + SetEdgeMaps(edge); + std::vector quants; + hash_map memo; + Term lhs = ToRuleRec(edge, memo, edge->F.Formula,quants); + Term rhs = (edge->Parent->Name)(edge->F.IndParams.size(),&edge->F.IndParams[0]); + for(unsigned j = 0; j < edge->F.IndParams.size(); j++) + ToRuleRec(edge,memo,edge->F.IndParams[j],quants); // just to get quants + Term cnst = implies(lhs,rhs); #if 0 - for(unsigned i = 0; i < quants.size(); i++){ - std::cout << expr(ctx,(Z3_ast)quants[i]) << " : " << sort(ctx,Z3_get_sort(ctx,(Z3_ast)quants[i])) << std::endl; - } + for(unsigned i = 0; i < quants.size(); i++){ + std::cout << expr(ctx,(Z3_ast)quants[i]) << " : " << sort(ctx,Z3_get_sort(ctx,(Z3_ast)quants[i])) << std::endl; + } #endif - if(format != DualityFormat) - cnst= forall(quants,cnst); - cnsts[i] = cnst; - } - // int num_rules = cnsts.size(); + if(format != DualityFormat) + cnst= forall(quants,cnst); + cnsts[i] = cnst; + } + // int num_rules = cnsts.size(); - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - if(!node->Bound.IsFull()){ - Term lhs = (node->Name)(node->Bound.IndParams) && !node->Bound.Formula; - Term cnst = implies(lhs,ctx.bool_val(false)); - if(format != DualityFormat){ - std::vector quants; - for(unsigned j = 0; j < node->Bound.IndParams.size(); j++) - quants.push_back(node->Bound.IndParams[j]); - if(format == HornFormat) - cnst= exists(quants,!cnst); - else - cnst= forall(quants, cnst); - } - cnsts.push_back(cnst); - } - } + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + if(!node->Bound.IsFull()){ + Term lhs = (node->Name)(node->Bound.IndParams) && !node->Bound.Formula; + Term cnst = implies(lhs,ctx.bool_val(false)); + if(format != DualityFormat){ + std::vector quants; + for(unsigned j = 0; j < node->Bound.IndParams.size(); j++) + quants.push_back(node->Bound.IndParams[j]); + if(format == HornFormat) + cnst= exists(quants,!cnst); + else + cnst= forall(quants, cnst); + } + cnsts.push_back(cnst); + } + } - } + } - bool RPFP::proof_core_contains(const expr &e){ - return proof_core->find(e) != proof_core->end(); - } + bool RPFP::proof_core_contains(const expr &e){ + return proof_core->find(e) != proof_core->end(); + } - bool RPFP_caching::proof_core_contains(const expr &e){ - std::vector foo; - GetAssumptionLits(e,foo); - for(unsigned i = 0; i < foo.size(); i++) - if(proof_core->find(foo[i]) != proof_core->end()) - return true; - return false; - } + bool RPFP_caching::proof_core_contains(const expr &e){ + std::vector foo; + GetAssumptionLits(e,foo); + for(unsigned i = 0; i < foo.size(); i++) + if(proof_core->find(foo[i]) != proof_core->end()) + return true; + return false; + } - bool RPFP::EdgeUsedInProof(Edge *edge){ - ComputeProofCore(); - if(!edge->dual.null() && proof_core_contains(edge->dual)) - return true; - for(unsigned i = 0; i < edge->constraints.size(); i++) - if(proof_core_contains(edge->constraints[i])) - return true; - return false; - } + bool RPFP::EdgeUsedInProof(Edge *edge){ + ComputeProofCore(); + if(!edge->dual.null() && proof_core_contains(edge->dual)) + return true; + for(unsigned i = 0; i < edge->constraints.size(); i++) + if(proof_core_contains(edge->constraints[i])) + return true; + return false; + } -RPFP::~RPFP(){ - ClearProofCore(); - for(unsigned i = 0; i < nodes.size(); i++) - delete nodes[i]; - for(unsigned i = 0; i < edges.size(); i++) - delete edges[i]; - } + RPFP::~RPFP(){ + ClearProofCore(); + for(unsigned i = 0; i < nodes.size(); i++) + delete nodes[i]; + for(unsigned i = 0; i < edges.size(); i++) + delete edges[i]; + } } #if 0 void show_ast(expr *a){ - std::cout << *a; + std::cout << *a; } #endif diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index b40ab9370..1c441e5d2 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -1,23 +1,23 @@ /*++ -Copyright (c) 2012 Microsoft Corporation + Copyright (c) 2012 Microsoft Corporation -Module Name: + Module Name: - duality_solver.h + duality_solver.h -Abstract: + Abstract: - implements relational post-fixedpoint problem - (RPFP) solver + implements relational post-fixedpoint problem + (RPFP) solver -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -66,3532 +66,3532 @@ Revision History: namespace Duality { - // TODO: must be a better place for this... - static char string_of_int_buffer[20]; + // TODO: must be a better place for this... + static char string_of_int_buffer[20]; - static const char *string_of_int(int n){ - sprintf(string_of_int_buffer,"%d",n); - return string_of_int_buffer; - } - - /** Generic object for producing diagnostic output. */ - - class Reporter { - protected: - RPFP *rpfp; - public: - Reporter(RPFP *_rpfp){ - rpfp = _rpfp; + static const char *string_of_int(int n){ + sprintf(string_of_int_buffer,"%d",n); + return string_of_int_buffer; } - virtual void Extend(RPFP::Node *node){} - virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){} - virtual void Bound(RPFP::Node *node){} - virtual void Expand(RPFP::Edge *edge){} - virtual void AddCover(RPFP::Node *covered, std::vector &covering){} - virtual void RemoveCover(RPFP::Node *covered, RPFP::Node *covering){} - virtual void Conjecture(RPFP::Node *node, const RPFP::Transformer &t){} - virtual void Forcing(RPFP::Node *covered, RPFP::Node *covering){} - virtual void Dominates(RPFP::Node *node, RPFP::Node *other){} - virtual void InductionFailure(RPFP::Edge *edge, const std::vector &children){} - virtual void UpdateUnderapprox(RPFP::Node *node, const RPFP::Transformer &update){} - virtual void Reject(RPFP::Edge *edge, const std::vector &Children){} - virtual void Message(const std::string &msg){} - virtual void Depth(int){} - virtual ~Reporter(){} - }; - Reporter *CreateStdoutReporter(RPFP *rpfp); - Reporter *CreateConjectureFileReporter(RPFP *rpfp, const std::string &fname); + /** Generic object for producing diagnostic output. */ + + class Reporter { + protected: + RPFP *rpfp; + public: + Reporter(RPFP *_rpfp){ + rpfp = _rpfp; + } + virtual void Extend(RPFP::Node *node){} + virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){} + virtual void Bound(RPFP::Node *node){} + virtual void Expand(RPFP::Edge *edge){} + virtual void AddCover(RPFP::Node *covered, std::vector &covering){} + virtual void RemoveCover(RPFP::Node *covered, RPFP::Node *covering){} + virtual void Conjecture(RPFP::Node *node, const RPFP::Transformer &t){} + virtual void Forcing(RPFP::Node *covered, RPFP::Node *covering){} + virtual void Dominates(RPFP::Node *node, RPFP::Node *other){} + virtual void InductionFailure(RPFP::Edge *edge, const std::vector &children){} + virtual void UpdateUnderapprox(RPFP::Node *node, const RPFP::Transformer &update){} + virtual void Reject(RPFP::Edge *edge, const std::vector &Children){} + virtual void Message(const std::string &msg){} + virtual void Depth(int){} + virtual ~Reporter(){} + }; + + Reporter *CreateStdoutReporter(RPFP *rpfp); + Reporter *CreateConjectureFileReporter(RPFP *rpfp, const std::string &fname); - /** Object we throw in case of catastrophe. */ + /** Object we throw in case of catastrophe. */ - struct InternalError { - std::string msg; - InternalError(const std::string _msg) - : msg(_msg) {} - }; - - - /** This is the main solver. It takes anarbitrary (possibly cyclic) - RPFP and either annotates it with a solution, or returns a - counterexample derivation in the form of an embedd RPFP tree. */ - - class Duality : public Solver { - - public: - Duality(RPFP *_rpfp) - : ctx(_rpfp->ctx), - slvr(_rpfp->slvr()), - nodes(_rpfp->nodes), - edges(_rpfp->edges) - { - rpfp = _rpfp; - reporter = 0; - conj_reporter = 0; - heuristic = 0; - unwinding = 0; - FullExpand = false; - NoConj = false; - FeasibleEdges = true; - UseUnderapprox = true; - Report = false; - StratifiedInlining = false; - RecursionBound = -1; - BatchExpand = false; - { - scoped_no_proof no_proofs_please(ctx.m()); -#ifdef USE_RPFP_CLONE - clone_rpfp = new RPFP_caching(rpfp->ls); - clone_rpfp->Clone(rpfp); -#endif -#ifdef USE_NEW_GEN_CANDS - gen_cands_rpfp = new RPFP_caching(rpfp->ls); - gen_cands_rpfp->Clone(rpfp); -#endif - } - } - - ~Duality(){ -#ifdef USE_RPFP_CLONE - delete clone_rpfp; -#endif -#ifdef USE_NEW_GEN_CANDS - delete gen_cands_rpfp; -#endif - if(unwinding) delete unwinding; - } - -#ifdef USE_RPFP_CLONE - RPFP_caching *clone_rpfp; -#endif -#ifdef USE_NEW_GEN_CANDS - RPFP_caching *gen_cands_rpfp; -#endif - - - typedef RPFP::Node Node; - typedef RPFP::Edge Edge; - - /** This struct represents a candidate for extending the - unwinding. It consists of an edge to instantiate - and a vector of children for the new instance. */ - - struct Candidate { - Edge *edge; std::vector - Children; - }; - - /** Comparison operator, allowing us to sort Nodes - by their number field. */ - - struct lnode - { - bool operator()(const Node* s1, const Node* s2) const - { - return s1->number < s2->number; - } + struct InternalError { + std::string msg; + InternalError(const std::string _msg) + : msg(_msg) {} }; - typedef std::set Unexpanded; // sorted set of Nodes - /** This class provides a heuristic for expanding a derivation - tree. */ + /** This is the main solver. It takes anarbitrary (possibly cyclic) + RPFP and either annotates it with a solution, or returns a + counterexample derivation in the form of an embedd RPFP tree. */ - class Heuristic { - RPFP *rpfp; + class Duality : public Solver { - /** Heuristic score for unwinding nodes. Currently this - counts the number of updates. */ - struct score { - int updates; - score() : updates(0) {} - }; - hash_map scores; - public: - Heuristic(RPFP *_rpfp){ - rpfp = _rpfp; - } + Duality(RPFP *_rpfp) + : ctx(_rpfp->ctx), + slvr(_rpfp->slvr()), + nodes(_rpfp->nodes), + edges(_rpfp->edges) + { + rpfp = _rpfp; + reporter = 0; + conj_reporter = 0; + heuristic = 0; + unwinding = 0; + FullExpand = false; + NoConj = false; + FeasibleEdges = true; + UseUnderapprox = true; + Report = false; + StratifiedInlining = false; + RecursionBound = -1; + BatchExpand = false; + { + scoped_no_proof no_proofs_please(ctx.m()); +#ifdef USE_RPFP_CLONE + clone_rpfp = new RPFP_caching(rpfp->ls); + clone_rpfp->Clone(rpfp); +#endif +#ifdef USE_NEW_GEN_CANDS + gen_cands_rpfp = new RPFP_caching(rpfp->ls); + gen_cands_rpfp->Clone(rpfp); +#endif + } + } - virtual ~Heuristic(){} + ~Duality(){ +#ifdef USE_RPFP_CLONE + delete clone_rpfp; +#endif +#ifdef USE_NEW_GEN_CANDS + delete gen_cands_rpfp; +#endif + if(unwinding) delete unwinding; + } - virtual void Update(RPFP::Node *node){ - scores[node].updates++; - } +#ifdef USE_RPFP_CLONE + RPFP_caching *clone_rpfp; +#endif +#ifdef USE_NEW_GEN_CANDS + RPFP_caching *gen_cands_rpfp; +#endif - /** Heuristic choice of nodes to expand. Takes a set "choices" - and returns a subset "best". We currently choose the - nodes with the fewest updates. - */ + + typedef RPFP::Node Node; + typedef RPFP::Edge Edge; + + /** This struct represents a candidate for extending the + unwinding. It consists of an edge to instantiate + and a vector of children for the new instance. */ + + struct Candidate { + Edge *edge; std::vector + Children; + }; + + /** Comparison operator, allowing us to sort Nodes + by their number field. */ + + struct lnode + { + bool operator()(const Node* s1, const Node* s2) const + { + return s1->number < s2->number; + } + }; + + typedef std::set Unexpanded; // sorted set of Nodes + + /** This class provides a heuristic for expanding a derivation + tree. */ + + class Heuristic { + RPFP *rpfp; + + /** Heuristic score for unwinding nodes. Currently this + counts the number of updates. */ + struct score { + int updates; + score() : updates(0) {} + }; + hash_map scores; + + public: + Heuristic(RPFP *_rpfp){ + rpfp = _rpfp; + } + + virtual ~Heuristic(){} + + virtual void Update(RPFP::Node *node){ + scores[node].updates++; + } + + /** Heuristic choice of nodes to expand. Takes a set "choices" + and returns a subset "best". We currently choose the + nodes with the fewest updates. + */ #if 0 - virtual void ChooseExpand(const std::set &choices, std::set &best){ - int best_score = INT_MAX; - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ - Node *node = (*it)->map; - int score = scores[node].updates; - best_score = std::min(best_score,score); - } - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it) - if(scores[(*it)->map].updates == best_score) - best.insert(*it); - } + virtual void ChooseExpand(const std::set &choices, std::set &best){ + int best_score = INT_MAX; + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ + Node *node = (*it)->map; + int score = scores[node].updates; + best_score = std::min(best_score,score); + } + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it) + if(scores[(*it)->map].updates == best_score) + best.insert(*it); + } #else - virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority=false, bool best_only=false){ - if(high_priority) return; - int best_score = INT_MAX; - int worst_score = 0; - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ - Node *node = (*it)->map; - int score = scores[node].updates; - best_score = std::min(best_score,score); - worst_score = std::max(worst_score,score); - } - int cutoff = best_only ? best_score : (best_score + (worst_score-best_score)/2); - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it) - if(scores[(*it)->map].updates <= cutoff) - best.insert(*it); - } + virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority=false, bool best_only=false){ + if(high_priority) return; + int best_score = INT_MAX; + int worst_score = 0; + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ + Node *node = (*it)->map; + int score = scores[node].updates; + best_score = std::min(best_score,score); + worst_score = std::max(worst_score,score); + } + int cutoff = best_only ? best_score : (best_score + (worst_score-best_score)/2); + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it) + if(scores[(*it)->map].updates <= cutoff) + best.insert(*it); + } #endif - /** Called when done expanding a tree */ - virtual void Done() {} + /** Called when done expanding a tree */ + virtual void Done() {} - /** Ask whether a node should be used/unused in the tree. Returns, - 1 if yes, -1 if no, and 0 if don't care. */ + /** Ask whether a node should be used/unused in the tree. Returns, + 1 if yes, -1 if no, and 0 if don't care. */ - virtual int UseNode(Node *node){ - return 0; - } - }; + virtual int UseNode(Node *node){ + return 0; + } + }; - /** The Proposer class proposes conjectures eagerly. These can come - from any source, including predicate abstraction, templates, or - previous solver runs. The proposed conjectures are checked - with low effort when the unwinding is expanded. - */ + /** The Proposer class proposes conjectures eagerly. These can come + from any source, including predicate abstraction, templates, or + previous solver runs. The proposed conjectures are checked + with low effort when the unwinding is expanded. + */ - class Proposer { - public: - /** Given a node in the unwinding, propose some conjectures */ - virtual std::vector &Propose(Node *node) = 0; - virtual ~Proposer(){}; - }; + class Proposer { + public: + /** Given a node in the unwinding, propose some conjectures */ + virtual std::vector &Propose(Node *node) = 0; + virtual ~Proposer(){}; + }; - class Covering; // see below + class Covering; // see below - // These members represent the state of the algorithm. + // These members represent the state of the algorithm. - RPFP *rpfp; // the input RPFP - Reporter *reporter; // object for logging - Reporter *conj_reporter; // object for logging conjectures - Heuristic *heuristic; // expansion heuristic - context &ctx; // Z3 context - solver &slvr; // Z3 solver - std::vector &nodes; // Nodes of input RPFP - std::vector &edges; // Edges of input RPFP - std::vector leaves; // leaf nodes of unwinding (unused) - Unexpanded unexpanded; // unexpanded nodes - std::list candidates; // candidates for expansion - // maps children to edges in input RPFP - hash_map > edges_by_child; - // maps each node in input RPFP to its expanded instances - hash_map > insts_of_node; - // maps each node in input RPFP to all its instances - hash_map > all_of_node; - RPFP *unwinding; // the unwinding - Covering *indset; // proposed inductive subset - Counterexample cex; // counterexample - std::list to_expand; - hash_set updated_nodes; - hash_map underapprox_map; // maps underapprox nodes to the nodes they approximate - int last_decisions; - hash_set overapproxes; - std::vector proposers; - std::string ConjectureFile; - bool stratified_inlining_done; + RPFP *rpfp; // the input RPFP + Reporter *reporter; // object for logging + Reporter *conj_reporter; // object for logging conjectures + Heuristic *heuristic; // expansion heuristic + context &ctx; // Z3 context + solver &slvr; // Z3 solver + std::vector &nodes; // Nodes of input RPFP + std::vector &edges; // Edges of input RPFP + std::vector leaves; // leaf nodes of unwinding (unused) + Unexpanded unexpanded; // unexpanded nodes + std::list candidates; // candidates for expansion + // maps children to edges in input RPFP + hash_map > edges_by_child; + // maps each node in input RPFP to its expanded instances + hash_map > insts_of_node; + // maps each node in input RPFP to all its instances + hash_map > all_of_node; + RPFP *unwinding; // the unwinding + Covering *indset; // proposed inductive subset + Counterexample cex; // counterexample + std::list to_expand; + hash_set updated_nodes; + hash_map underapprox_map; // maps underapprox nodes to the nodes they approximate + int last_decisions; + hash_set overapproxes; + std::vector proposers; + std::string ConjectureFile; + bool stratified_inlining_done; #ifdef BOUNDED - struct Counter { - unsigned val; - Counter(){val = 0;} - }; - typedef std::map NodeToCounter; - hash_map back_edges; // counts of back edges + struct Counter { + unsigned val; + Counter(){val = 0;} + }; + typedef std::map NodeToCounter; + hash_map back_edges; // counts of back edges #endif - /** Solve the problem. */ - virtual bool Solve(){ - PreSolve(); - bool res = SolveMain(); // does the actual work - PostSolve(); - return res; - } + /** Solve the problem. */ + virtual bool Solve(){ + PreSolve(); + bool res = SolveMain(); // does the actual work + PostSolve(); + return res; + } - void PreSolve(){ - reporter = Report ? CreateStdoutReporter(rpfp) : new Reporter(rpfp); - conj_reporter = ConjectureFile.empty() ? 0 : CreateConjectureFileReporter(rpfp,ConjectureFile); + void PreSolve(){ + reporter = Report ? CreateStdoutReporter(rpfp) : new Reporter(rpfp); + conj_reporter = ConjectureFile.empty() ? 0 : CreateConjectureFileReporter(rpfp,ConjectureFile); #ifndef LOCALIZE_CONJECTURES - heuristic = !cex.get_tree() ? new Heuristic(rpfp) : new ReplayHeuristic(rpfp,cex); + heuristic = !cex.get_tree() ? new Heuristic(rpfp) : new ReplayHeuristic(rpfp,cex); #else - heuristic = !cex.get_tree() ? (Heuristic *)(new LocalHeuristic(rpfp)) - : (Heuristic *)(new ReplayHeuristic(rpfp,cex)); + heuristic = !cex.get_tree() ? (Heuristic *)(new LocalHeuristic(rpfp)) + : (Heuristic *)(new ReplayHeuristic(rpfp,cex)); #endif - // determine if we are recursion bounded - for(unsigned i = 0; i < rpfp->nodes.size(); i++) - if(rpfp->nodes[i]->recursion_bound < UINT_MAX) - RecursionBound = 0; - cex.clear(); // in case we didn't use it for heuristic - if(unwinding) delete unwinding; - unwinding = new RPFP(rpfp->ls); - unwinding->HornClauses = rpfp->HornClauses; - indset = new Covering(this); - last_decisions = 0; - CreateEdgesByChildMap(); + // determine if we are recursion bounded + for(unsigned i = 0; i < rpfp->nodes.size(); i++) + if(rpfp->nodes[i]->recursion_bound < UINT_MAX) + RecursionBound = 0; + cex.clear(); // in case we didn't use it for heuristic + if(unwinding) delete unwinding; + unwinding = new RPFP(rpfp->ls); + unwinding->HornClauses = rpfp->HornClauses; + indset = new Covering(this); + last_decisions = 0; + CreateEdgesByChildMap(); #ifndef TOP_DOWN - CreateInitialUnwinding(); + CreateInitialUnwinding(); #else - CreateLeaves(); - for(unsigned i = 0; i < leaves.size(); i++) - if(!SatisfyUpperBound(leaves[i])) - return false; + CreateLeaves(); + for(unsigned i = 0; i < leaves.size(); i++) + if(!SatisfyUpperBound(leaves[i])) + return false; #endif - StratifiedLeafCount = -1; - stratified_inlining_done = false; - } + StratifiedLeafCount = -1; + stratified_inlining_done = false; + } - void PostSolve(){ - // print_profile(std::cout); - delete indset; - delete heuristic; - // delete unwinding; // keep the unwinding for future mining of predicates - delete reporter; - if(conj_reporter) - delete conj_reporter; - for(unsigned i = 0; i < proposers.size(); i++) - delete proposers[i]; - } + void PostSolve(){ + // print_profile(std::cout); + delete indset; + delete heuristic; + // delete unwinding; // keep the unwinding for future mining of predicates + delete reporter; + if(conj_reporter) + delete conj_reporter; + for(unsigned i = 0; i < proposers.size(); i++) + delete proposers[i]; + } - bool RecheckBounds(){ - for(unsigned i = 0; i < unwinding->nodes.size(); i++){ - Node *node = unwinding->nodes[i]; - node->Bound = node->map->Bound; - if(!SatisfyUpperBound(node)) - return false; - } - return true; - } + bool RecheckBounds(){ + for(unsigned i = 0; i < unwinding->nodes.size(); i++){ + Node *node = unwinding->nodes[i]; + node->Bound = node->map->Bound; + if(!SatisfyUpperBound(node)) + return false; + } + return true; + } - void CreateInitialUnwinding(){ - if(!StratifiedInlining){ - CreateLeaves(); - if(FeasibleEdges)NullaryCandidates(); - else InstantiateAllEdges(); - } - else { + void CreateInitialUnwinding(){ + if(!StratifiedInlining){ + CreateLeaves(); + if(FeasibleEdges)NullaryCandidates(); + else InstantiateAllEdges(); + } + else { #ifdef NEW_STRATIFIED_INLINING #else - CreateLeaves(); + CreateLeaves(); #endif - } + } - } + } - void Cancel(){ - // TODO - } + void Cancel(){ + // TODO + } #if 0 - virtual void Restart(RPFP *_rpfp){ - rpfp = _rpfp; - delete unwinding; - nodes = _rpfp->nodes; - edges = _rpfp->edges; - leaves.clear(); - unexpanded.clear(); // unexpanded nodes - candidates.clear(); // candidates for expansion - edges_by_child.clear(); - insts_of_node.clear(); - all_of_node.clear(); - to_expand.clear(); - } + virtual void Restart(RPFP *_rpfp){ + rpfp = _rpfp; + delete unwinding; + nodes = _rpfp->nodes; + edges = _rpfp->edges; + leaves.clear(); + unexpanded.clear(); // unexpanded nodes + candidates.clear(); // candidates for expansion + edges_by_child.clear(); + insts_of_node.clear(); + all_of_node.clear(); + to_expand.clear(); + } #endif - virtual void LearnFrom(Solver *other_solver){ - // get the counterexample as a guide - cex.swap(other_solver->GetCounterexample()); + virtual void LearnFrom(Solver *other_solver){ + // get the counterexample as a guide + cex.swap(other_solver->GetCounterexample()); - // propose conjectures based on old unwinding - Duality *old_duality = dynamic_cast(other_solver); - if(old_duality) - proposers.push_back(new HistoryProposer(old_duality,this)); - } + // propose conjectures based on old unwinding + Duality *old_duality = dynamic_cast(other_solver); + if(old_duality) + proposers.push_back(new HistoryProposer(old_duality,this)); + } - /** Return a reference to the counterexample */ - virtual Counterexample &GetCounterexample(){ - return cex; - } + /** Return a reference to the counterexample */ + virtual Counterexample &GetCounterexample(){ + return cex; + } - // options - bool FullExpand; // do not use partial expansion of derivation tree - bool NoConj; // do not use conjectures (no forced covering) - bool FeasibleEdges; // use only feasible edges in unwinding - bool UseUnderapprox; // use underapproximations - bool Report; // spew on stdout - bool StratifiedInlining; // Do stratified inlining as preprocessing step - int RecursionBound; // Recursion bound for bounded verification - bool BatchExpand; - bool EnableRestarts; + // options + bool FullExpand; // do not use partial expansion of derivation tree + bool NoConj; // do not use conjectures (no forced covering) + bool FeasibleEdges; // use only feasible edges in unwinding + bool UseUnderapprox; // use underapproximations + bool Report; // spew on stdout + bool StratifiedInlining; // Do stratified inlining as preprocessing step + int RecursionBound; // Recursion bound for bounded verification + bool BatchExpand; + bool EnableRestarts; - bool SetBoolOption(bool &opt, const std::string &value){ - if(value == "0") { - opt = false; - return true; - } - if(value == "1") { - opt = true; - return true; - } - return false; - } + bool SetBoolOption(bool &opt, const std::string &value){ + if(value == "0") { + opt = false; + return true; + } + if(value == "1") { + opt = true; + return true; + } + return false; + } - bool SetIntOption(int &opt, const std::string &value){ - opt = atoi(value.c_str()); - return true; - } + bool SetIntOption(int &opt, const std::string &value){ + opt = atoi(value.c_str()); + return true; + } - /** Set options (not currently used) */ - virtual bool SetOption(const std::string &option, const std::string &value){ - if(option == "full_expand"){ - return SetBoolOption(FullExpand,value); - } - if(option == "no_conj"){ - return SetBoolOption(NoConj,value); - } - if(option == "feasible_edges"){ - return SetBoolOption(FeasibleEdges,value); - } - if(option == "use_underapprox"){ - return SetBoolOption(UseUnderapprox,value); - } - if(option == "report"){ - return SetBoolOption(Report,value); - } - if(option == "stratified_inlining"){ - return SetBoolOption(StratifiedInlining,value); - } - if(option == "batch_expand"){ - return SetBoolOption(BatchExpand,value); - } - if(option == "recursion_bound"){ - return SetIntOption(RecursionBound,value); - } - if(option == "conjecture_file"){ - ConjectureFile = value; - } - if(option == "enable_restarts"){ - return SetBoolOption(EnableRestarts,value); - } - return false; - } + /** Set options (not currently used) */ + virtual bool SetOption(const std::string &option, const std::string &value){ + if(option == "full_expand"){ + return SetBoolOption(FullExpand,value); + } + if(option == "no_conj"){ + return SetBoolOption(NoConj,value); + } + if(option == "feasible_edges"){ + return SetBoolOption(FeasibleEdges,value); + } + if(option == "use_underapprox"){ + return SetBoolOption(UseUnderapprox,value); + } + if(option == "report"){ + return SetBoolOption(Report,value); + } + if(option == "stratified_inlining"){ + return SetBoolOption(StratifiedInlining,value); + } + if(option == "batch_expand"){ + return SetBoolOption(BatchExpand,value); + } + if(option == "recursion_bound"){ + return SetIntOption(RecursionBound,value); + } + if(option == "conjecture_file"){ + ConjectureFile = value; + } + if(option == "enable_restarts"){ + return SetBoolOption(EnableRestarts,value); + } + return false; + } - /** Create an instance of a node in the unwinding. Set its - annotation to true, and mark it unexpanded. */ - Node* CreateNodeInstance(Node *node, int number = 0){ - RPFP::Node *inst = unwinding->CloneNode(node); - inst->Annotation.SetFull(); - if(number < 0) inst->number = number; - unexpanded.insert(inst); - all_of_node[node].push_back(inst); - return inst; - } + /** Create an instance of a node in the unwinding. Set its + annotation to true, and mark it unexpanded. */ + Node* CreateNodeInstance(Node *node, int number = 0){ + RPFP::Node *inst = unwinding->CloneNode(node); + inst->Annotation.SetFull(); + if(number < 0) inst->number = number; + unexpanded.insert(inst); + all_of_node[node].push_back(inst); + return inst; + } - /** Create an instance of an edge in the unwinding, with given - parent and children. */ - void CreateEdgeInstance(Edge *edge, Node *parent, const std::vector &children){ - RPFP::Edge *inst = unwinding->CreateEdge(parent,edge->F,children); - inst->map = edge; - } + /** Create an instance of an edge in the unwinding, with given + parent and children. */ + void CreateEdgeInstance(Edge *edge, Node *parent, const std::vector &children){ + RPFP::Edge *inst = unwinding->CreateEdge(parent,edge->F,children); + inst->map = edge; + } - void MakeLeaf(Node *node, bool do_not_expand = false){ - node->Annotation.SetEmpty(); - Edge *e = unwinding->CreateLowerBoundEdge(node); + void MakeLeaf(Node *node, bool do_not_expand = false){ + node->Annotation.SetEmpty(); + Edge *e = unwinding->CreateLowerBoundEdge(node); #ifdef TOP_DOWN - node->Annotation.SetFull(); // allow this node to cover others + node->Annotation.SetFull(); // allow this node to cover others #endif - if(StratifiedInlining) - node->Annotation.SetFull(); // allow this node to cover others - else - updated_nodes.insert(node); - e->map = 0; - reporter->Extend(node); + if(StratifiedInlining) + node->Annotation.SetFull(); // allow this node to cover others + else + updated_nodes.insert(node); + e->map = 0; + reporter->Extend(node); #ifdef EARLY_EXPAND - if(!do_not_expand) - TryExpandNode(node); + if(!do_not_expand) + TryExpandNode(node); #endif - // e->F.SetEmpty(); - } + // e->F.SetEmpty(); + } - void MakeOverapprox(Node *node){ - node->Annotation.SetFull(); - Edge *e = unwinding->CreateLowerBoundEdge(node); - overapproxes.insert(node); - e->map = 0; - } + void MakeOverapprox(Node *node){ + node->Annotation.SetFull(); + Edge *e = unwinding->CreateLowerBoundEdge(node); + overapproxes.insert(node); + e->map = 0; + } - /** We start the unwinding with leaves that under-approximate - each relation with false. */ - void CreateLeaves(){ - unexpanded.clear(); - leaves.clear(); - for(unsigned i = 0; i < nodes.size(); i++){ - RPFP::Node *node = CreateNodeInstance(nodes[i]); - if(0 && nodes[i]->Outgoing->Children.size() == 0) - CreateEdgeInstance(nodes[i]->Outgoing,node,std::vector()); - else { - if(!StratifiedInlining) - MakeLeaf(node); - else { - MakeOverapprox(node); - LeafMap[nodes[i]] = node; - } - } - leaves.push_back(node); - } - } + /** We start the unwinding with leaves that under-approximate + each relation with false. */ + void CreateLeaves(){ + unexpanded.clear(); + leaves.clear(); + for(unsigned i = 0; i < nodes.size(); i++){ + RPFP::Node *node = CreateNodeInstance(nodes[i]); + if(0 && nodes[i]->Outgoing->Children.size() == 0) + CreateEdgeInstance(nodes[i]->Outgoing,node,std::vector()); + else { + if(!StratifiedInlining) + MakeLeaf(node); + else { + MakeOverapprox(node); + LeafMap[nodes[i]] = node; + } + } + leaves.push_back(node); + } + } - /** Create the map from children to edges in the input RPFP. This - is used to generate candidates for expansion. */ - void CreateEdgesByChildMap(){ - edges_by_child.clear(); - for(unsigned i = 0; i < edges.size(); i++){ - Edge *e = edges[i]; - std::set done; - for(unsigned j = 0; j < e->Children.size(); j++){ - Node *c = e->Children[j]; - if(done.find(c) == done.end()) // avoid duplicates - edges_by_child[c].push_back(e); - done.insert(c); - } - } - } + /** Create the map from children to edges in the input RPFP. This + is used to generate candidates for expansion. */ + void CreateEdgesByChildMap(){ + edges_by_child.clear(); + for(unsigned i = 0; i < edges.size(); i++){ + Edge *e = edges[i]; + std::set done; + for(unsigned j = 0; j < e->Children.size(); j++){ + Node *c = e->Children[j]; + if(done.find(c) == done.end()) // avoid duplicates + edges_by_child[c].push_back(e); + done.insert(c); + } + } + } - void NullaryCandidates(){ - for(unsigned i = 0; i < edges.size(); i++){ - RPFP::Edge *edge = edges[i]; - if(edge->Children.size() == 0){ - Candidate cand; - cand.edge = edge; - candidates.push_back(cand); - } - } - } + void NullaryCandidates(){ + for(unsigned i = 0; i < edges.size(); i++){ + RPFP::Edge *edge = edges[i]; + if(edge->Children.size() == 0){ + Candidate cand; + cand.edge = edge; + candidates.push_back(cand); + } + } + } - void InstantiateAllEdges(){ - hash_map leaf_map; - for(unsigned i = 0; i < leaves.size(); i++){ - leaf_map[leaves[i]->map] = leaves[i]; - insts_of_node[leaves[i]->map].push_back(leaves[i]); - } - unexpanded.clear(); - for(unsigned i = 0; i < edges.size(); i++){ - Edge *edge = edges[i]; - Candidate c; c.edge = edge; - c.Children.resize(edge->Children.size()); - for(unsigned j = 0; j < c.Children.size(); j++) - c.Children[j] = leaf_map[edge->Children[j]]; - Node *new_node; - Extend(c,new_node); + void InstantiateAllEdges(){ + hash_map leaf_map; + for(unsigned i = 0; i < leaves.size(); i++){ + leaf_map[leaves[i]->map] = leaves[i]; + insts_of_node[leaves[i]->map].push_back(leaves[i]); + } + unexpanded.clear(); + for(unsigned i = 0; i < edges.size(); i++){ + Edge *edge = edges[i]; + Candidate c; c.edge = edge; + c.Children.resize(edge->Children.size()); + for(unsigned j = 0; j < c.Children.size(); j++) + c.Children[j] = leaf_map[edge->Children[j]]; + Node *new_node; + Extend(c,new_node); #ifdef EARLY_EXPAND - TryExpandNode(new_node); + TryExpandNode(new_node); #endif - } - for(Unexpanded::iterator it = unexpanded.begin(), en = unexpanded.end(); it != en; ++it) - indset->Add(*it); - for(unsigned i = 0; i < leaves.size(); i++){ - std::vector &foo = insts_of_node[leaves[i]->map]; - foo.erase(foo.begin()); - } - } + } + for(Unexpanded::iterator it = unexpanded.begin(), en = unexpanded.end(); it != en; ++it) + indset->Add(*it); + for(unsigned i = 0; i < leaves.size(); i++){ + std::vector &foo = insts_of_node[leaves[i]->map]; + foo.erase(foo.begin()); + } + } - bool ProducedBySI(Edge *edge, std::vector &children){ - if(LeafMap.find(edge->Parent) == LeafMap.end()) return false; - Node *other = LeafMap[edge->Parent]; - if(other->Outgoing->map != edge) return false; - std::vector &ochs = other->Outgoing->Children; - for(unsigned i = 0; i < children.size(); i++) - if(ochs[i] != children[i]) return false; - return true; - } + bool ProducedBySI(Edge *edge, std::vector &children){ + if(LeafMap.find(edge->Parent) == LeafMap.end()) return false; + Node *other = LeafMap[edge->Parent]; + if(other->Outgoing->map != edge) return false; + std::vector &ochs = other->Outgoing->Children; + for(unsigned i = 0; i < children.size(); i++) + if(ochs[i] != children[i]) return false; + return true; + } - /** Add a candidate for expansion, but not if Stratified inlining has already - produced it */ + /** Add a candidate for expansion, but not if Stratified inlining has already + produced it */ - void AddCandidate(Edge *edge, std::vector &children){ - if(StratifiedInlining && ProducedBySI(edge,children)) - return; - candidates.push_back(Candidate()); - candidates.back().edge = edge; - candidates.back().Children = children; - } + void AddCandidate(Edge *edge, std::vector &children){ + if(StratifiedInlining && ProducedBySI(edge,children)) + return; + candidates.push_back(Candidate()); + candidates.back().edge = edge; + candidates.back().Children = children; + } - /** Generate candidates for expansion, given a vector of candidate - sets for each argument position. This recursively produces - the cross product. - */ - void GenCandidatesRec(int pos, Edge *edge, - const std::vector > &vec, - std::vector &children){ - if(pos == (int)vec.size()){ - AddCandidate(edge,children); - } - else { - for(unsigned i = 0; i < vec[pos].size(); i++){ - children[pos] = vec[pos][i]; - GenCandidatesRec(pos+1,edge,vec,children); - } - } - } + /** Generate candidates for expansion, given a vector of candidate + sets for each argument position. This recursively produces + the cross product. + */ + void GenCandidatesRec(int pos, Edge *edge, + const std::vector > &vec, + std::vector &children){ + if(pos == (int)vec.size()){ + AddCandidate(edge,children); + } + else { + for(unsigned i = 0; i < vec[pos].size(); i++){ + children[pos] = vec[pos][i]; + GenCandidatesRec(pos+1,edge,vec,children); + } + } + } - /** Setup for above recursion. */ - void GenCandidates(int pos, Edge *edge, - const std::vector > &vec){ - std::vector children(vec.size()); - GenCandidatesRec(0,edge,vec,children); - } + /** Setup for above recursion. */ + void GenCandidates(int pos, Edge *edge, + const std::vector > &vec){ + std::vector children(vec.size()); + GenCandidatesRec(0,edge,vec,children); + } - /** Expand a node. We find all the candidates for expansion using - this node and other already expanded nodes. This is a little - tricky, since a node may be used for multiple argument - positions of an edge, and we don't want to produce duplicates. - */ + /** Expand a node. We find all the candidates for expansion using + this node and other already expanded nodes. This is a little + tricky, since a node may be used for multiple argument + positions of an edge, and we don't want to produce duplicates. + */ #ifndef NEW_EXPAND - void ExpandNode(Node *node){ - std::vector &nedges = edges_by_child[node->map]; - for(unsigned i = 0; i < nedges.size(); i++){ - Edge *edge = nedges[i]; - for(unsigned npos = 0; npos < edge->Children.size(); ++npos){ - if(edge->Children[npos] == node->map){ - std::vector > vec(edge->Children.size()); - vec[npos].push_back(node); - for(unsigned j = 0; j < edge->Children.size(); j++){ - if(j != npos){ - std::vector &insts = insts_of_node[edge->Children[j]]; - for(unsigned k = 0; k < insts.size(); k++) - if(indset->Candidate(insts[k])) - vec[j].push_back(insts[k]); - } - if(j < npos && edge->Children[j] == node->map) - vec[j].push_back(node); - } - GenCandidates(0,edge,vec); - } - } - } - unexpanded.erase(node); - insts_of_node[node->map].push_back(node); - } + void ExpandNode(Node *node){ + std::vector &nedges = edges_by_child[node->map]; + for(unsigned i = 0; i < nedges.size(); i++){ + Edge *edge = nedges[i]; + for(unsigned npos = 0; npos < edge->Children.size(); ++npos){ + if(edge->Children[npos] == node->map){ + std::vector > vec(edge->Children.size()); + vec[npos].push_back(node); + for(unsigned j = 0; j < edge->Children.size(); j++){ + if(j != npos){ + std::vector &insts = insts_of_node[edge->Children[j]]; + for(unsigned k = 0; k < insts.size(); k++) + if(indset->Candidate(insts[k])) + vec[j].push_back(insts[k]); + } + if(j < npos && edge->Children[j] == node->map) + vec[j].push_back(node); + } + GenCandidates(0,edge,vec); + } + } + } + unexpanded.erase(node); + insts_of_node[node->map].push_back(node); + } #else - /** If the current proposed solution is not inductive, - use the induction failure to generate candidates for extension. */ - void ExpandNode(Node *node){ - unexpanded.erase(node); - insts_of_node[node->map].push_back(node); - timer_start("GenCandIndFailUsing"); - std::vector &nedges = edges_by_child[node->map]; - for(unsigned i = 0; i < nedges.size(); i++){ - Edge *edge = nedges[i]; - slvr.push(); - RPFP *checker = new RPFP(rpfp->ls); - Node *root = CheckerJustForEdge(edge,checker,true); - if(root){ - expr using_cond = ctx.bool_val(false); - for(unsigned npos = 0; npos < edge->Children.size(); ++npos) - if(edge->Children[npos] == node->map) - using_cond = using_cond || checker->Localize(root->Outgoing->Children[npos]->Outgoing,NodeMarker(node)); - slvr.add(using_cond); - if(checker->Check(root) != unsat){ - Candidate candidate; - ExtractCandidateFromCex(edge,checker,root,candidate); - reporter->InductionFailure(edge,candidate.Children); - candidates.push_back(candidate); - } - } - slvr.pop(1); - delete checker; - } - timer_stop("GenCandIndFailUsing"); - } + /** If the current proposed solution is not inductive, + use the induction failure to generate candidates for extension. */ + void ExpandNode(Node *node){ + unexpanded.erase(node); + insts_of_node[node->map].push_back(node); + timer_start("GenCandIndFailUsing"); + std::vector &nedges = edges_by_child[node->map]; + for(unsigned i = 0; i < nedges.size(); i++){ + Edge *edge = nedges[i]; + slvr.push(); + RPFP *checker = new RPFP(rpfp->ls); + Node *root = CheckerJustForEdge(edge,checker,true); + if(root){ + expr using_cond = ctx.bool_val(false); + for(unsigned npos = 0; npos < edge->Children.size(); ++npos) + if(edge->Children[npos] == node->map) + using_cond = using_cond || checker->Localize(root->Outgoing->Children[npos]->Outgoing,NodeMarker(node)); + slvr.add(using_cond); + if(checker->Check(root) != unsat){ + Candidate candidate; + ExtractCandidateFromCex(edge,checker,root,candidate); + reporter->InductionFailure(edge,candidate.Children); + candidates.push_back(candidate); + } + } + slvr.pop(1); + delete checker; + } + timer_stop("GenCandIndFailUsing"); + } #endif - void ExpandNodeFromOther(Node *node, Node *other){ - std::vector &in = other->Incoming; - for(unsigned i = 0; i < in.size(); i++){ - Edge *edge = in[i]; - Candidate cand; - cand.edge = edge->map; - cand.Children = edge->Children; - for(unsigned j = 0; j < cand.Children.size(); j++) - if(cand.Children[j] == other) - cand.Children[j] = node; - candidates.push_front(cand); - } - // unexpanded.erase(node); - // insts_of_node[node->map].push_back(node); - } + void ExpandNodeFromOther(Node *node, Node *other){ + std::vector &in = other->Incoming; + for(unsigned i = 0; i < in.size(); i++){ + Edge *edge = in[i]; + Candidate cand; + cand.edge = edge->map; + cand.Children = edge->Children; + for(unsigned j = 0; j < cand.Children.size(); j++) + if(cand.Children[j] == other) + cand.Children[j] = node; + candidates.push_front(cand); + } + // unexpanded.erase(node); + // insts_of_node[node->map].push_back(node); + } - /** Expand a node based on some uncovered node it dominates. - This pushes cahdidates onto the *front* of the candidate - queue, so these expansions are done depth-first. */ - bool ExpandNodeFromCoverFail(Node *node){ - if(!node->Outgoing || node->Outgoing->Children.size() == 0) - return false; - Node *other = indset->GetSimilarNode(node); - if(!other) - return false; + /** Expand a node based on some uncovered node it dominates. + This pushes cahdidates onto the *front* of the candidate + queue, so these expansions are done depth-first. */ + bool ExpandNodeFromCoverFail(Node *node){ + if(!node->Outgoing || node->Outgoing->Children.size() == 0) + return false; + Node *other = indset->GetSimilarNode(node); + if(!other) + return false; #ifdef UNDERAPPROX_NODES - Node *under_node = CreateUnderapproxNode(node); - underapprox_map[under_node] = node; - indset->CoverByNode(node,under_node); - ExpandNodeFromOther(under_node,other); - ExpandNode(under_node); + Node *under_node = CreateUnderapproxNode(node); + underapprox_map[under_node] = node; + indset->CoverByNode(node,under_node); + ExpandNodeFromOther(under_node,other); + ExpandNode(under_node); #else - ExpandNodeFromOther(node,other); - unexpanded.erase(node); - insts_of_node[node->map].push_back(node); + ExpandNodeFromOther(node,other); + unexpanded.erase(node); + insts_of_node[node->map].push_back(node); #endif - return true; - } + return true; + } - /** Make a boolean variable to act as a "marker" for a node. */ - expr NodeMarker(Node *node){ - std::string name = std::string("@m_") + string_of_int(node->number); - return ctx.constant(name.c_str(),ctx.bool_sort()); - } + /** Make a boolean variable to act as a "marker" for a node. */ + expr NodeMarker(Node *node){ + std::string name = std::string("@m_") + string_of_int(node->number); + return ctx.constant(name.c_str(),ctx.bool_sort()); + } - /** Make a boolean variable to act as a "marker" for a pair of nodes. */ - expr NodeMarker(Node *node1, Node *node2){ - std::string name = std::string("@m_") + string_of_int(node1->number); - name += std::string("_") + string_of_int(node2->number); - return ctx.constant(name.c_str(),ctx.bool_sort()); - } + /** Make a boolean variable to act as a "marker" for a pair of nodes. */ + expr NodeMarker(Node *node1, Node *node2){ + std::string name = std::string("@m_") + string_of_int(node1->number); + name += std::string("_") + string_of_int(node2->number); + return ctx.constant(name.c_str(),ctx.bool_sort()); + } - /** Union the annotation of dst into src. If with_markers is - true, we conjoin the annotation formula of dst with its - marker. This allows us to discover which disjunct is - true in a satisfying assignment. */ - void UnionAnnotations(RPFP::Transformer &dst, Node *src, bool with_markers = false){ - if(!with_markers) - dst.UnionWith(src->Annotation); - else { - RPFP::Transformer t = src->Annotation; - t.Formula = t.Formula && NodeMarker(src); - dst.UnionWith(t); - } - } + /** Union the annotation of dst into src. If with_markers is + true, we conjoin the annotation formula of dst with its + marker. This allows us to discover which disjunct is + true in a satisfying assignment. */ + void UnionAnnotations(RPFP::Transformer &dst, Node *src, bool with_markers = false){ + if(!with_markers) + dst.UnionWith(src->Annotation); + else { + RPFP::Transformer t = src->Annotation; + t.Formula = t.Formula && NodeMarker(src); + dst.UnionWith(t); + } + } - void GenNodeSolutionFromIndSet(Node *node, RPFP::Transformer &annot, bool with_markers = false){ - annot.SetEmpty(); - std::vector &insts = insts_of_node[node]; - for(unsigned j = 0; j < insts.size(); j++) - if(indset->Contains(insts[j])) - UnionAnnotations(annot,insts[j],with_markers); - annot.Simplify(); - } + void GenNodeSolutionFromIndSet(Node *node, RPFP::Transformer &annot, bool with_markers = false){ + annot.SetEmpty(); + std::vector &insts = insts_of_node[node]; + for(unsigned j = 0; j < insts.size(); j++) + if(indset->Contains(insts[j])) + UnionAnnotations(annot,insts[j],with_markers); + annot.Simplify(); + } - bool NodeSolutionFromIndSetFull(Node *node){ - std::vector &insts = insts_of_node[node]; - for(unsigned j = 0; j < insts.size(); j++) - if(indset->Contains(insts[j])) - if(insts[j]->Annotation.IsFull()) - return true; - return false; - } + bool NodeSolutionFromIndSetFull(Node *node){ + std::vector &insts = insts_of_node[node]; + for(unsigned j = 0; j < insts.size(); j++) + if(indset->Contains(insts[j])) + if(insts[j]->Annotation.IsFull()) + return true; + return false; + } - bool recursionBounded; + bool recursionBounded; - /** See if the solution might be bounded. */ - void TestRecursionBounded(){ - recursionBounded = false; - if(RecursionBound == -1) - return; - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - std::vector &insts = insts_of_node[node]; - for(unsigned j = 0; j < insts.size(); j++) - if(indset->Contains(insts[j])) - if(NodePastRecursionBound(insts[j],true)) - recursionBounded = true; - } - } + /** See if the solution might be bounded. */ + void TestRecursionBounded(){ + recursionBounded = false; + if(RecursionBound == -1) + return; + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + std::vector &insts = insts_of_node[node]; + for(unsigned j = 0; j < insts.size(); j++) + if(indset->Contains(insts[j])) + if(NodePastRecursionBound(insts[j],true)) + recursionBounded = true; + } + } - bool IsResultRecursionBounded(){ - return recursionBounded; - } + bool IsResultRecursionBounded(){ + return recursionBounded; + } - /** Generate a proposed solution of the input RPFP from - the unwinding, by unioning the instances of each node. */ - void GenSolutionFromIndSet(bool with_markers = false){ - for(unsigned i = 0; i < nodes.size(); i++){ - Node *node = nodes[i]; - GenNodeSolutionFromIndSet(node,node->Annotation,with_markers); - } - } + /** Generate a proposed solution of the input RPFP from + the unwinding, by unioning the instances of each node. */ + void GenSolutionFromIndSet(bool with_markers = false){ + for(unsigned i = 0; i < nodes.size(); i++){ + Node *node = nodes[i]; + GenNodeSolutionFromIndSet(node,node->Annotation,with_markers); + } + } #ifdef BOUNDED - bool NodePastRecursionBound(Node *node, bool report = false){ - if(RecursionBound < 0) return false; - NodeToCounter &backs = back_edges[node]; - for(NodeToCounter::iterator it = backs.begin(), en = backs.end(); it != en; ++it){ - if(it->second.val > it->first->recursion_bound){ - if(report){ - std::ostringstream os; - os << "cut off " << it->first->Name.name() << " at depth " << it->second.val; - reporter->Message(os.str()); - } - return true; - } - } - return false; - } + bool NodePastRecursionBound(Node *node, bool report = false){ + if(RecursionBound < 0) return false; + NodeToCounter &backs = back_edges[node]; + for(NodeToCounter::iterator it = backs.begin(), en = backs.end(); it != en; ++it){ + if(it->second.val > it->first->recursion_bound){ + if(report){ + std::ostringstream os; + os << "cut off " << it->first->Name.name() << " at depth " << it->second.val; + reporter->Message(os.str()); + } + return true; + } + } + return false; + } #endif - /** Test whether a given extension candidate actually represents - an induction failure. Right now we approximate this: if - the resulting node in the unwinding could be labeled false, - it clearly is not an induction failure. */ + /** Test whether a given extension candidate actually represents + an induction failure. Right now we approximate this: if + the resulting node in the unwinding could be labeled false, + it clearly is not an induction failure. */ - bool CandidateFeasible(const Candidate &cand){ - if(!FeasibleEdges) return true; - timer_start("CandidateFeasible"); - RPFP *checker = new RPFP(rpfp->ls); - // std::cout << "Checking feasibility of extension " << cand.edge->Parent->number << std::endl; - checker->Push(); - std::vector chs(cand.Children.size()); - Node *root = checker->CloneNode(cand.edge->Parent); + bool CandidateFeasible(const Candidate &cand){ + if(!FeasibleEdges) return true; + timer_start("CandidateFeasible"); + RPFP *checker = new RPFP(rpfp->ls); + // std::cout << "Checking feasibility of extension " << cand.edge->Parent->number << std::endl; + checker->Push(); + std::vector chs(cand.Children.size()); + Node *root = checker->CloneNode(cand.edge->Parent); #ifdef BOUNDED - for(unsigned i = 0; i < cand.Children.size(); i++) - if(NodePastRecursionBound(cand.Children[i])){ - timer_stop("CandidateFeasible"); - return false; - } + for(unsigned i = 0; i < cand.Children.size(); i++) + if(NodePastRecursionBound(cand.Children[i])){ + timer_stop("CandidateFeasible"); + return false; + } #endif #ifdef NEW_CAND_SEL - GenNodeSolutionFromIndSet(cand.edge->Parent,root->Bound); + GenNodeSolutionFromIndSet(cand.edge->Parent,root->Bound); #else - root->Bound.SetEmpty(); + root->Bound.SetEmpty(); #endif - checker->AssertNode(root); - for(unsigned i = 0; i < cand.Children.size(); i++) - chs[i] = checker->CloneNode(cand.Children[i]); - Edge *e = checker->CreateEdge(root,cand.edge->F,chs); - checker->AssertEdge(e,0,true); - // std::cout << "Checking SAT: " << e->dual << std::endl; - bool res = checker->Check(root) != unsat; - // std::cout << "Result: " << res << std::endl; - if(!res)reporter->Reject(cand.edge,cand.Children); - checker->Pop(1); - delete checker; - timer_stop("CandidateFeasible"); - return res; - } + checker->AssertNode(root); + for(unsigned i = 0; i < cand.Children.size(); i++) + chs[i] = checker->CloneNode(cand.Children[i]); + Edge *e = checker->CreateEdge(root,cand.edge->F,chs); + checker->AssertEdge(e,0,true); + // std::cout << "Checking SAT: " << e->dual << std::endl; + bool res = checker->Check(root) != unsat; + // std::cout << "Result: " << res << std::endl; + if(!res)reporter->Reject(cand.edge,cand.Children); + checker->Pop(1); + delete checker; + timer_stop("CandidateFeasible"); + return res; + } - hash_map TopoSort; - int TopoSortCounter; - std::vector SortedEdges; + hash_map TopoSort; + int TopoSortCounter; + std::vector SortedEdges; - void DoTopoSortRec(Node *node){ - if(TopoSort.find(node) != TopoSort.end()) - return; - TopoSort[node] = INT_MAX; // just to break cycles - Edge *edge = node->Outgoing; // note, this is just *one* outgoing edge - if(edge){ - std::vector &chs = edge->Children; - for(unsigned i = 0; i < chs.size(); i++) - DoTopoSortRec(chs[i]); - } - TopoSort[node] = TopoSortCounter++; - SortedEdges.push_back(edge); - } + void DoTopoSortRec(Node *node){ + if(TopoSort.find(node) != TopoSort.end()) + return; + TopoSort[node] = INT_MAX; // just to break cycles + Edge *edge = node->Outgoing; // note, this is just *one* outgoing edge + if(edge){ + std::vector &chs = edge->Children; + for(unsigned i = 0; i < chs.size(); i++) + DoTopoSortRec(chs[i]); + } + TopoSort[node] = TopoSortCounter++; + SortedEdges.push_back(edge); + } - void DoTopoSort(){ - TopoSort.clear(); - SortedEdges.clear(); - TopoSortCounter = 0; - for(unsigned i = 0; i < nodes.size(); i++) - DoTopoSortRec(nodes[i]); - } + void DoTopoSort(){ + TopoSort.clear(); + SortedEdges.clear(); + TopoSortCounter = 0; + for(unsigned i = 0; i < nodes.size(); i++) + DoTopoSortRec(nodes[i]); + } - int StratifiedLeafCount; + int StratifiedLeafCount; #ifdef NEW_STRATIFIED_INLINING - /** Stratified inlining builds an initial layered unwinding before - switching to the LAWI strategy. Currently the number of layers - is one. Only nodes that are the targets of back edges are - consider to be leaves. This assumes we have already computed a - topological sort. - */ + /** Stratified inlining builds an initial layered unwinding before + switching to the LAWI strategy. Currently the number of layers + is one. Only nodes that are the targets of back edges are + consider to be leaves. This assumes we have already computed a + topological sort. + */ - bool DoStratifiedInlining(){ - if(stratified_inlining_done) - return true; - stratified_inlining_done = true; - DoTopoSort(); - int depth = 1; // TODO: make this an option - std::vector > unfolding_levels(depth+1); - for(int level = 1; level <= depth; level++) - for(unsigned i = 0; i < SortedEdges.size(); i++){ - Edge *edge = SortedEdges[i]; - Node *parent = edge->Parent; - std::vector &chs = edge->Children; - std::vector my_chs(chs.size()); - for(unsigned j = 0; j < chs.size(); j++){ - Node *child = chs[j]; - int ch_level = TopoSort[child] >= TopoSort[parent] ? level-1 : level; - if(unfolding_levels[ch_level].find(child) == unfolding_levels[ch_level].end()){ - if(ch_level == 0) - unfolding_levels[0][child] = CreateLeaf(child); - else - throw InternalError("in levelized unwinding"); - } - my_chs[j] = unfolding_levels[ch_level][child]; - } - Candidate cand; cand.edge = edge; cand.Children = my_chs; - Node *new_node; - bool ok = Extend(cand,new_node); - MarkExpanded(new_node); // we don't expand here -- just mark it done - if(!ok) return false; // got a counterexample - unfolding_levels[level][parent] = new_node; - } - return true; - } + bool DoStratifiedInlining(){ + if(stratified_inlining_done) + return true; + stratified_inlining_done = true; + DoTopoSort(); + int depth = 1; // TODO: make this an option + std::vector > unfolding_levels(depth+1); + for(int level = 1; level <= depth; level++) + for(unsigned i = 0; i < SortedEdges.size(); i++){ + Edge *edge = SortedEdges[i]; + Node *parent = edge->Parent; + std::vector &chs = edge->Children; + std::vector my_chs(chs.size()); + for(unsigned j = 0; j < chs.size(); j++){ + Node *child = chs[j]; + int ch_level = TopoSort[child] >= TopoSort[parent] ? level-1 : level; + if(unfolding_levels[ch_level].find(child) == unfolding_levels[ch_level].end()){ + if(ch_level == 0) + unfolding_levels[0][child] = CreateLeaf(child); + else + throw InternalError("in levelized unwinding"); + } + my_chs[j] = unfolding_levels[ch_level][child]; + } + Candidate cand; cand.edge = edge; cand.Children = my_chs; + Node *new_node; + bool ok = Extend(cand,new_node); + MarkExpanded(new_node); // we don't expand here -- just mark it done + if(!ok) return false; // got a counterexample + unfolding_levels[level][parent] = new_node; + } + return true; + } - Node *CreateLeaf(Node *node){ - RPFP::Node *nchild = CreateNodeInstance(node); - MakeLeaf(nchild, /* do_not_expand = */ true); - nchild->Annotation.SetEmpty(); - return nchild; - } + Node *CreateLeaf(Node *node){ + RPFP::Node *nchild = CreateNodeInstance(node); + MakeLeaf(nchild, /* do_not_expand = */ true); + nchild->Annotation.SetEmpty(); + return nchild; + } - void MarkExpanded(Node *node){ - if(unexpanded.find(node) != unexpanded.end()){ - unexpanded.erase(node); - insts_of_node[node->map].push_back(node); - } - } + void MarkExpanded(Node *node){ + if(unexpanded.find(node) != unexpanded.end()){ + unexpanded.erase(node); + insts_of_node[node->map].push_back(node); + } + } #else - /** In stratified inlining, we build the unwinding from the bottom - down, trying to satisfy the node bounds. We do this as a pre-pass, - limiting the expansion. If we get a counterexample, we are done, - else we continue as usual expanding the unwinding upward. - */ + /** In stratified inlining, we build the unwinding from the bottom + down, trying to satisfy the node bounds. We do this as a pre-pass, + limiting the expansion. If we get a counterexample, we are done, + else we continue as usual expanding the unwinding upward. + */ - bool DoStratifiedInlining(){ - timer_start("StratifiedInlining"); - DoTopoSort(); - for(unsigned i = 0; i < leaves.size(); i++){ - Node *node = leaves[i]; - bool res = SatisfyUpperBound(node); - if(!res){ - timer_stop("StratifiedInlining"); - return false; - } - } - // don't leave any dangling nodes! + bool DoStratifiedInlining(){ + timer_start("StratifiedInlining"); + DoTopoSort(); + for(unsigned i = 0; i < leaves.size(); i++){ + Node *node = leaves[i]; + bool res = SatisfyUpperBound(node); + if(!res){ + timer_stop("StratifiedInlining"); + return false; + } + } + // don't leave any dangling nodes! #ifndef EFFORT_BOUNDED_STRAT - for(unsigned i = 0; i < leaves.size(); i++) - if(!leaves[i]->Outgoing) - MakeLeaf(leaves[i],true); + for(unsigned i = 0; i < leaves.size(); i++) + if(!leaves[i]->Outgoing) + MakeLeaf(leaves[i],true); #endif - timer_stop("StratifiedInlining"); - return true; - } + timer_stop("StratifiedInlining"); + return true; + } #endif - /** Here, we do the downward expansion for stratified inlining */ + /** Here, we do the downward expansion for stratified inlining */ - hash_map LeafMap, StratifiedLeafMap; + hash_map LeafMap, StratifiedLeafMap; - Edge *GetNodeOutgoing(Node *node, int last_decs = 0){ - if(overapproxes.find(node) == overapproxes.end()) return node->Outgoing; /* already expanded */ - overapproxes.erase(node); + Edge *GetNodeOutgoing(Node *node, int last_decs = 0){ + if(overapproxes.find(node) == overapproxes.end()) return node->Outgoing; /* already expanded */ + overapproxes.erase(node); #ifdef EFFORT_BOUNDED_STRAT - if(last_decs > 5000){ - // RPFP::Transformer save = node->Annotation; - node->Annotation.SetEmpty(); - Edge *e = unwinding->CreateLowerBoundEdge(node); - // node->Annotation = save; - insts_of_node[node->map].push_back(node); - // std::cout << "made leaf: " << node->number << std::endl; - return e; - } + if(last_decs > 5000){ + // RPFP::Transformer save = node->Annotation; + node->Annotation.SetEmpty(); + Edge *e = unwinding->CreateLowerBoundEdge(node); + // node->Annotation = save; + insts_of_node[node->map].push_back(node); + // std::cout << "made leaf: " << node->number << std::endl; + return e; + } #endif - Edge *edge = node->map->Outgoing; - std::vector &chs = edge->Children; + Edge *edge = node->map->Outgoing; + std::vector &chs = edge->Children; - // make sure we don't create a covered node in this process! + // make sure we don't create a covered node in this process! - for(unsigned i = 0; i < chs.size(); i++){ - Node *child = chs[i]; - if(TopoSort[child] < TopoSort[node->map]){ - Node *leaf = LeafMap[child]; - if(!indset->Contains(leaf)){ - node->Outgoing->F.Formula = ctx.bool_val(false); // make this a proper leaf, else bogus cex - return node->Outgoing; - } - } - } + for(unsigned i = 0; i < chs.size(); i++){ + Node *child = chs[i]; + if(TopoSort[child] < TopoSort[node->map]){ + Node *leaf = LeafMap[child]; + if(!indset->Contains(leaf)){ + node->Outgoing->F.Formula = ctx.bool_val(false); // make this a proper leaf, else bogus cex + return node->Outgoing; + } + } + } - std::vector nchs(chs.size()); - for(unsigned i = 0; i < chs.size(); i++){ - Node *child = chs[i]; - if(TopoSort[child] < TopoSort[node->map]){ - Node *leaf = LeafMap[child]; - nchs[i] = leaf; - if(unexpanded.find(leaf) != unexpanded.end()){ - unexpanded.erase(leaf); - insts_of_node[child].push_back(leaf); - } - } - else { - if(StratifiedLeafMap.find(child) == StratifiedLeafMap.end()){ - RPFP::Node *nchild = CreateNodeInstance(child,StratifiedLeafCount--); - MakeLeaf(nchild); - nchild->Annotation.SetEmpty(); - StratifiedLeafMap[child] = nchild; - indset->SetDominated(nchild); - } - nchs[i] = StratifiedLeafMap[child]; - } - } - CreateEdgeInstance(edge,node,nchs); - reporter->Extend(node); - return node->Outgoing; - } + std::vector nchs(chs.size()); + for(unsigned i = 0; i < chs.size(); i++){ + Node *child = chs[i]; + if(TopoSort[child] < TopoSort[node->map]){ + Node *leaf = LeafMap[child]; + nchs[i] = leaf; + if(unexpanded.find(leaf) != unexpanded.end()){ + unexpanded.erase(leaf); + insts_of_node[child].push_back(leaf); + } + } + else { + if(StratifiedLeafMap.find(child) == StratifiedLeafMap.end()){ + RPFP::Node *nchild = CreateNodeInstance(child,StratifiedLeafCount--); + MakeLeaf(nchild); + nchild->Annotation.SetEmpty(); + StratifiedLeafMap[child] = nchild; + indset->SetDominated(nchild); + } + nchs[i] = StratifiedLeafMap[child]; + } + } + CreateEdgeInstance(edge,node,nchs); + reporter->Extend(node); + return node->Outgoing; + } - void SetHeuristicOldNode(Node *node){ - LocalHeuristic *h = dynamic_cast(heuristic); - if(h) - h->SetOldNode(node); - } + void SetHeuristicOldNode(Node *node){ + LocalHeuristic *h = dynamic_cast(heuristic); + if(h) + h->SetOldNode(node); + } - bool SolveMain(){ - timer_start("SolveMain"); - bool res = SolveMainInt(); // does the actual work - timer_stop("SolveMain"); - return res; - } + bool SolveMain(){ + timer_start("SolveMain"); + bool res = SolveMainInt(); // does the actual work + timer_stop("SolveMain"); + return res; + } - /** This does the actual solving work. We try to generate - candidates for extension. If we succed, we extend the - unwinding. If we fail, we have a solution. */ - bool SolveMainInt(){ - if(StratifiedInlining && !DoStratifiedInlining()) - return false; + /** This does the actual solving work. We try to generate + candidates for extension. If we succed, we extend the + unwinding. If we fail, we have a solution. */ + bool SolveMainInt(){ + if(StratifiedInlining && !DoStratifiedInlining()) + return false; #ifdef BOUNDED - DoTopoSort(); + DoTopoSort(); #endif - while(true){ - timer_start("ProduceCandidatesForExtension"); - ProduceCandidatesForExtension(); - timer_stop("ProduceCandidatesForExtension"); - if(candidates.empty()){ - GenSolutionFromIndSet(); - TestRecursionBounded(); - return true; - } - Candidate cand = candidates.front(); - candidates.pop_front(); - if(CandidateFeasible(cand)){ - Node *new_node; - if(!Extend(cand,new_node)) - return false; + while(true){ + timer_start("ProduceCandidatesForExtension"); + ProduceCandidatesForExtension(); + timer_stop("ProduceCandidatesForExtension"); + if(candidates.empty()){ + GenSolutionFromIndSet(); + TestRecursionBounded(); + return true; + } + Candidate cand = candidates.front(); + candidates.pop_front(); + if(CandidateFeasible(cand)){ + Node *new_node; + if(!Extend(cand,new_node)) + return false; #ifdef EARLY_EXPAND - TryExpandNode(new_node); + TryExpandNode(new_node); #endif - } - } - } + } + } + } - // hack: put something local into the underapproximation formula - // without this, interpolants can be pretty bad - void AddThing(expr &conj){ - std::string name = "@thing"; - expr thing = ctx.constant(name.c_str(),ctx.bool_sort()); - if(conj.is_app() && conj.decl().get_decl_kind() == And){ - std::vector conjs(conj.num_args()+1); - for(unsigned i = 0; i+1 < conjs.size(); i++) - conjs[i] = conj.arg(i); - conjs[conjs.size()-1] = thing; - conj = rpfp->conjoin(conjs); - } - } + // hack: put something local into the underapproximation formula + // without this, interpolants can be pretty bad + void AddThing(expr &conj){ + std::string name = "@thing"; + expr thing = ctx.constant(name.c_str(),ctx.bool_sort()); + if(conj.is_app() && conj.decl().get_decl_kind() == And){ + std::vector conjs(conj.num_args()+1); + for(unsigned i = 0; i+1 < conjs.size(); i++) + conjs[i] = conj.arg(i); + conjs[conjs.size()-1] = thing; + conj = rpfp->conjoin(conjs); + } + } - Node *CreateUnderapproxNode(Node *node){ - // cex.get_tree()->ComputeUnderapprox(cex.get_root(),0); - RPFP::Node *under_node = CreateNodeInstance(node->map /* ,StratifiedLeafCount-- */); - under_node->Annotation.IntersectWith(cex.get_root()->Underapprox); - AddThing(under_node->Annotation.Formula); - Edge *e = unwinding->CreateLowerBoundEdge(under_node); - under_node->Annotation.SetFull(); // allow this node to cover others - back_edges[under_node] = back_edges[node]; - e->map = 0; - reporter->Extend(under_node); - return under_node; - } + Node *CreateUnderapproxNode(Node *node){ + // cex.get_tree()->ComputeUnderapprox(cex.get_root(),0); + RPFP::Node *under_node = CreateNodeInstance(node->map /* ,StratifiedLeafCount-- */); + under_node->Annotation.IntersectWith(cex.get_root()->Underapprox); + AddThing(under_node->Annotation.Formula); + Edge *e = unwinding->CreateLowerBoundEdge(under_node); + under_node->Annotation.SetFull(); // allow this node to cover others + back_edges[under_node] = back_edges[node]; + e->map = 0; + reporter->Extend(under_node); + return under_node; + } - /** Try to prove a conjecture about a node. If successful - update the unwinding annotation appropriately. */ - bool ProveConjecture(Node *node, const RPFP::Transformer &t,Node *other = 0, Counterexample *_cex = 0){ - reporter->Conjecture(node,t); - timer_start("ProveConjecture"); - RPFP::Transformer save = node->Bound; - node->Bound.IntersectWith(t); + /** Try to prove a conjecture about a node. If successful + update the unwinding annotation appropriately. */ + bool ProveConjecture(Node *node, const RPFP::Transformer &t,Node *other = 0, Counterexample *_cex = 0){ + reporter->Conjecture(node,t); + timer_start("ProveConjecture"); + RPFP::Transformer save = node->Bound; + node->Bound.IntersectWith(t); #ifndef LOCALIZE_CONJECTURES - bool ok = SatisfyUpperBound(node); + bool ok = SatisfyUpperBound(node); #else - SetHeuristicOldNode(other); - bool ok = SatisfyUpperBound(node); - SetHeuristicOldNode(0); + SetHeuristicOldNode(other); + bool ok = SatisfyUpperBound(node); + SetHeuristicOldNode(0); #endif - if(ok){ - timer_stop("ProveConjecture"); - return true; - } + if(ok){ + timer_stop("ProveConjecture"); + return true; + } #ifdef UNDERAPPROX_NODES - if(UseUnderapprox && last_decisions > 500){ - std::cout << "making an underapprox\n"; - ExpandNodeFromCoverFail(node); - } + if(UseUnderapprox && last_decisions > 500){ + std::cout << "making an underapprox\n"; + ExpandNodeFromCoverFail(node); + } #endif - if(_cex) (*_cex).swap(cex); // return the cex if asked - cex.clear(); // throw away the useless cex - node->Bound = save; // put back original bound - timer_stop("ProveConjecture"); - return false; - } + if(_cex) (*_cex).swap(cex); // return the cex if asked + cex.clear(); // throw away the useless cex + node->Bound = save; // put back original bound + timer_stop("ProveConjecture"); + return false; + } - /** If a node is part of the inductive subset, expand it. - We ask the inductive subset to exclude the node if possible. - */ - void TryExpandNode(RPFP::Node *node){ - if(indset->Close(node)) return; - if(!NoConj && indset->Conjecture(node)){ + /** If a node is part of the inductive subset, expand it. + We ask the inductive subset to exclude the node if possible. + */ + void TryExpandNode(RPFP::Node *node){ + if(indset->Close(node)) return; + if(!NoConj && indset->Conjecture(node)){ #ifdef UNDERAPPROX_NODES - /* TODO: temporary fix. this prevents an infinite loop in case - the node is covered by multiple others. This should be - removed when covering by a set is implemented. - */ - if(indset->Contains(node)){ - unexpanded.erase(node); - insts_of_node[node->map].push_back(node); - } + /* TODO: temporary fix. this prevents an infinite loop in case + the node is covered by multiple others. This should be + removed when covering by a set is implemented. + */ + if(indset->Contains(node)){ + unexpanded.erase(node); + insts_of_node[node->map].push_back(node); + } #endif - return; - } + return; + } #ifdef UNDERAPPROX_NODES - if(!indset->Contains(node)) - return; // could be covered by an underapprox node + if(!indset->Contains(node)) + return; // could be covered by an underapprox node #endif - indset->Add(node); + indset->Add(node); #if defined(CANDS_FROM_COVER_FAIL) && !defined(UNDERAPPROX_NODES) - if(ExpandNodeFromCoverFail(node)) - return; + if(ExpandNodeFromCoverFail(node)) + return; #endif - ExpandNode(node); - } + ExpandNode(node); + } - /** Make the conjunction of markers for all (expanded) instances of - a node in the input RPFP. */ - expr AllNodeMarkers(Node *node){ - expr res = ctx.bool_val(true); - std::vector &insts = insts_of_node[node]; - for(int k = insts.size()-1; k >= 0; k--) - res = res && NodeMarker(insts[k]); - return res; - } + /** Make the conjunction of markers for all (expanded) instances of + a node in the input RPFP. */ + expr AllNodeMarkers(Node *node){ + expr res = ctx.bool_val(true); + std::vector &insts = insts_of_node[node]; + for(int k = insts.size()-1; k >= 0; k--) + res = res && NodeMarker(insts[k]); + return res; + } - void RuleOutNodesPastBound(Node *node, RPFP::Transformer &t){ + void RuleOutNodesPastBound(Node *node, RPFP::Transformer &t){ #ifdef BOUNDED - if(RecursionBound < 0)return; - std::vector &insts = insts_of_node[node]; - for(unsigned i = 0; i < insts.size(); i++) - if(NodePastRecursionBound(insts[i])) - t.Formula = t.Formula && !NodeMarker(insts[i]); + if(RecursionBound < 0)return; + std::vector &insts = insts_of_node[node]; + for(unsigned i = 0; i < insts.size(); i++) + if(NodePastRecursionBound(insts[i])) + t.Formula = t.Formula && !NodeMarker(insts[i]); #endif - } + } - void GenNodeSolutionWithMarkersAux(Node *node, RPFP::Transformer &annot, expr &marker_disjunction, Node *other_node){ + void GenNodeSolutionWithMarkersAux(Node *node, RPFP::Transformer &annot, expr &marker_disjunction, Node *other_node){ #ifdef BOUNDED - if(RecursionBound >= 0 && NodePastRecursionBound(node)) - return; + if(RecursionBound >= 0 && NodePastRecursionBound(node)) + return; #endif - RPFP::Transformer temp = node->Annotation; - expr marker = (!other_node) ? NodeMarker(node) : NodeMarker(node, other_node); - temp.Formula = (!marker || temp.Formula); - annot.IntersectWith(temp); - marker_disjunction = marker_disjunction || marker; - } + RPFP::Transformer temp = node->Annotation; + expr marker = (!other_node) ? NodeMarker(node) : NodeMarker(node, other_node); + temp.Formula = (!marker || temp.Formula); + annot.IntersectWith(temp); + marker_disjunction = marker_disjunction || marker; + } - bool GenNodeSolutionWithMarkers(Node *node, RPFP::Transformer &annot, bool expanded_only = false, Node *other_node = 0){ - bool res = false; - annot.SetFull(); - expr marker_disjunction = ctx.bool_val(false); - std::vector &insts = expanded_only ? insts_of_node[node] : all_of_node[node]; - for(unsigned j = 0; j < insts.size(); j++){ - Node *node = insts[j]; - if(indset->Contains(insts[j])){ - GenNodeSolutionWithMarkersAux(node, annot, marker_disjunction, other_node); res = true; - } - } - annot.Formula = annot.Formula && marker_disjunction; - annot.Simplify(); - return res; - } + bool GenNodeSolutionWithMarkers(Node *node, RPFP::Transformer &annot, bool expanded_only = false, Node *other_node = 0){ + bool res = false; + annot.SetFull(); + expr marker_disjunction = ctx.bool_val(false); + std::vector &insts = expanded_only ? insts_of_node[node] : all_of_node[node]; + for(unsigned j = 0; j < insts.size(); j++){ + Node *node = insts[j]; + if(indset->Contains(insts[j])){ + GenNodeSolutionWithMarkersAux(node, annot, marker_disjunction, other_node); res = true; + } + } + annot.Formula = annot.Formula && marker_disjunction; + annot.Simplify(); + return res; + } - /** Make a checker to determine if an edge in the input RPFP - is satisfied. */ - Node *CheckerJustForEdge(Edge *edge, RPFP *checker, bool expanded_only = false){ - Node *root = checker->CloneNode(edge->Parent); - GenNodeSolutionFromIndSet(edge->Parent, root->Bound); - if(root->Bound.IsFull()) - return 0; - checker->AssertNode(root); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = checker->CloneNode(oc); - if(!GenNodeSolutionWithMarkers(oc,nc->Annotation,expanded_only)) - return 0; - Edge *e = checker->CreateLowerBoundEdge(nc); - checker->AssertEdge(e); - cs.push_back(nc); - } - checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); - return root; - } + /** Make a checker to determine if an edge in the input RPFP + is satisfied. */ + Node *CheckerJustForEdge(Edge *edge, RPFP *checker, bool expanded_only = false){ + Node *root = checker->CloneNode(edge->Parent); + GenNodeSolutionFromIndSet(edge->Parent, root->Bound); + if(root->Bound.IsFull()) + return 0; + checker->AssertNode(root); + std::vector cs; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = checker->CloneNode(oc); + if(!GenNodeSolutionWithMarkers(oc,nc->Annotation,expanded_only)) + return 0; + Edge *e = checker->CreateLowerBoundEdge(nc); + checker->AssertEdge(e); + cs.push_back(nc); + } + checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); + return root; + } #ifndef MINIMIZE_CANDIDATES_HARDER #if 0 - /** Make a checker to detheermine if an edge in the input RPFP - is satisfied. */ - Node *CheckerForEdge(Edge *edge, RPFP *checker){ - Node *root = checker->CloneNode(edge->Parent); - root->Bound = edge->Parent->Annotation; - root->Bound.Formula = (!AllNodeMarkers(edge->Parent)) || root->Bound.Formula; - checker->AssertNode(root); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = checker->CloneNode(oc); - nc->Annotation = oc->Annotation; - RuleOutNodesPastBound(oc,nc->Annotation); - Edge *e = checker->CreateLowerBoundEdge(nc); - checker->AssertEdge(e); - cs.push_back(nc); - } - checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); - return root; - } + /** Make a checker to detheermine if an edge in the input RPFP + is satisfied. */ + Node *CheckerForEdge(Edge *edge, RPFP *checker){ + Node *root = checker->CloneNode(edge->Parent); + root->Bound = edge->Parent->Annotation; + root->Bound.Formula = (!AllNodeMarkers(edge->Parent)) || root->Bound.Formula; + checker->AssertNode(root); + std::vector cs; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = checker->CloneNode(oc); + nc->Annotation = oc->Annotation; + RuleOutNodesPastBound(oc,nc->Annotation); + Edge *e = checker->CreateLowerBoundEdge(nc); + checker->AssertEdge(e); + cs.push_back(nc); + } + checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); + return root; + } #else - /** Make a checker to determine if an edge in the input RPFP - is satisfied. */ - Node *CheckerForEdge(Edge *edge, RPFP *checker){ - Node *root = checker->CloneNode(edge->Parent); - GenNodeSolutionFromIndSet(edge->Parent, root->Bound); + /** Make a checker to determine if an edge in the input RPFP + is satisfied. */ + Node *CheckerForEdge(Edge *edge, RPFP *checker){ + Node *root = checker->CloneNode(edge->Parent); + GenNodeSolutionFromIndSet(edge->Parent, root->Bound); #if 0 - if(root->Bound.IsFull()) - return = 0; + if(root->Bound.IsFull()) + return = 0; #endif - checker->AssertNode(root); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = checker->CloneNode(oc); - GenNodeSolutionWithMarkers(oc,nc->Annotation,true); - Edge *e = checker->CreateLowerBoundEdge(nc); - checker->AssertEdge(e); - cs.push_back(nc); - } - checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); - return root; - } + checker->AssertNode(root); + std::vector cs; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = checker->CloneNode(oc); + GenNodeSolutionWithMarkers(oc,nc->Annotation,true); + Edge *e = checker->CreateLowerBoundEdge(nc); + checker->AssertEdge(e); + cs.push_back(nc); + } + checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); + return root; + } #endif - /** If an edge is not satisfied, produce an extension candidate - using instances of its children that violate the parent annotation. - We find these using the marker predicates. */ - void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){ - candidate.edge = edge; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *node = root->Outgoing->Children[j]; - Edge *lb = node->Outgoing; - std::vector &insts = insts_of_node[edge->Children[j]]; + /** If an edge is not satisfied, produce an extension candidate + using instances of its children that violate the parent annotation. + We find these using the marker predicates. */ + void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){ + candidate.edge = edge; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *node = root->Outgoing->Children[j]; + Edge *lb = node->Outgoing; + std::vector &insts = insts_of_node[edge->Children[j]]; #ifndef MINIMIZE_CANDIDATES - for(int k = insts.size()-1; k >= 0; k--) + for(int k = insts.size()-1; k >= 0; k--) #else - for(unsigned k = 0; k < insts.size(); k++) + for(unsigned k = 0; k < insts.size(); k++) #endif - { - Node *inst = insts[k]; - if(indset->Contains(inst)){ - if(checker->Empty(node) || - eq(lb ? checker->Eval(lb,NodeMarker(inst)) : checker->dualModel.eval(NodeMarker(inst,node)),ctx.bool_val(true))){ - candidate.Children.push_back(inst); - goto next_child; - } - } - } - throw InternalError("No candidate from induction failure"); - next_child:; - } - } + { + Node *inst = insts[k]; + if(indset->Contains(inst)){ + if(checker->Empty(node) || + eq(lb ? checker->Eval(lb,NodeMarker(inst)) : checker->dualModel.eval(NodeMarker(inst,node)),ctx.bool_val(true))){ + candidate.Children.push_back(inst); + goto next_child; + } + } + } + throw InternalError("No candidate from induction failure"); + next_child:; + } + } #else - /** Make a checker to determine if an edge in the input RPFP - is satisfied. */ - Node *CheckerForEdge(Edge *edge, RPFP *checker){ - Node *root = checker->CloneNode(edge->Parent); - GenNodeSolutionFromIndSet(edge->Parent, root->Bound); - if(root->Bound.IsFull()) - return = 0; - checker->AssertNode(root); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = checker->CloneNode(oc); - GenNodeSolutionWithMarkers(oc,nc->Annotation,true); - Edge *e = checker->CreateLowerBoundEdge(nc); - checker->AssertEdge(e); - cs.push_back(nc); - } - checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); - return root; - } + /** Make a checker to determine if an edge in the input RPFP + is satisfied. */ + Node *CheckerForEdge(Edge *edge, RPFP *checker){ + Node *root = checker->CloneNode(edge->Parent); + GenNodeSolutionFromIndSet(edge->Parent, root->Bound); + if(root->Bound.IsFull()) + return = 0; + checker->AssertNode(root); + std::vector cs; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = checker->CloneNode(oc); + GenNodeSolutionWithMarkers(oc,nc->Annotation,true); + Edge *e = checker->CreateLowerBoundEdge(nc); + checker->AssertEdge(e); + cs.push_back(nc); + } + checker->AssertEdge(checker->CreateEdge(root,edge->F,cs)); + return root; + } - /** If an edge is not satisfied, produce an extension candidate - using instances of its children that violate the parent annotation. - We find these using the marker predicates. */ - void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){ - candidate.edge = edge; - std::vector assumps; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Edge *lb = root->Outgoing->Children[j]->Outgoing; - std::vector &insts = insts_of_node[edge->Children[j]]; - for(unsigned k = 0; k < insts.size(); k++) - { - Node *inst = insts[k]; - expr marker = NodeMarker(inst); - if(indset->Contains(inst)){ - if(checker->Empty(lb->Parent) || - eq(checker->Eval(lb,marker),ctx.bool_val(true))){ - candidate.Children.push_back(inst); - assumps.push_back(checker->Localize(lb,marker)); - goto next_child; - } - assumps.push_back(checker->Localize(lb,marker)); - if(checker->CheckUpdateModel(root,assumps) != unsat){ - candidate.Children.push_back(inst); - goto next_child; - } - assumps.pop_back(); - } - } - throw InternalError("No candidate from induction failure"); - next_child:; - } - } + /** If an edge is not satisfied, produce an extension candidate + using instances of its children that violate the parent annotation. + We find these using the marker predicates. */ + void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){ + candidate.edge = edge; + std::vector assumps; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Edge *lb = root->Outgoing->Children[j]->Outgoing; + std::vector &insts = insts_of_node[edge->Children[j]]; + for(unsigned k = 0; k < insts.size(); k++) + { + Node *inst = insts[k]; + expr marker = NodeMarker(inst); + if(indset->Contains(inst)){ + if(checker->Empty(lb->Parent) || + eq(checker->Eval(lb,marker),ctx.bool_val(true))){ + candidate.Children.push_back(inst); + assumps.push_back(checker->Localize(lb,marker)); + goto next_child; + } + assumps.push_back(checker->Localize(lb,marker)); + if(checker->CheckUpdateModel(root,assumps) != unsat){ + candidate.Children.push_back(inst); + goto next_child; + } + assumps.pop_back(); + } + } + throw InternalError("No candidate from induction failure"); + next_child:; + } + } #endif - Node *CheckerForEdgeClone(Edge *edge, RPFP_caching *checker){ - Edge *gen_cands_edge = checker->GetEdgeClone(edge); - Node *root = gen_cands_edge->Parent; - root->Outgoing = gen_cands_edge; - GenNodeSolutionFromIndSet(edge->Parent, root->Bound); + Node *CheckerForEdgeClone(Edge *edge, RPFP_caching *checker){ + Edge *gen_cands_edge = checker->GetEdgeClone(edge); + Node *root = gen_cands_edge->Parent; + root->Outgoing = gen_cands_edge; + GenNodeSolutionFromIndSet(edge->Parent, root->Bound); #if 0 - if(root->Bound.IsFull()) - return = 0; + if(root->Bound.IsFull()) + return = 0; #endif - checker->AssertNode(root); - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = gen_cands_edge->Children[j]; - GenNodeSolutionWithMarkers(oc,nc->Annotation,true,nc); - } - checker->AssertEdge(gen_cands_edge,1,true); - return root; - } + checker->AssertNode(root); + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = gen_cands_edge->Children[j]; + GenNodeSolutionWithMarkers(oc,nc->Annotation,true,nc); + } + checker->AssertEdge(gen_cands_edge,1,true); + return root; + } - /** If the current proposed solution is not inductive, - use the induction failure to generate candidates for extension. */ - void GenCandidatesFromInductionFailure(bool full_scan = false){ - timer_start("GenCandIndFail"); - GenSolutionFromIndSet(true /* add markers */); - for(unsigned i = 0; i < edges.size(); i++){ - Edge *edge = edges[i]; - if(!full_scan && updated_nodes.find(edge->Parent) == updated_nodes.end()) - continue; + /** If the current proposed solution is not inductive, + use the induction failure to generate candidates for extension. */ + void GenCandidatesFromInductionFailure(bool full_scan = false){ + timer_start("GenCandIndFail"); + GenSolutionFromIndSet(true /* add markers */); + for(unsigned i = 0; i < edges.size(); i++){ + Edge *edge = edges[i]; + if(!full_scan && updated_nodes.find(edge->Parent) == updated_nodes.end()) + continue; #ifndef USE_NEW_GEN_CANDS - slvr.push(); - RPFP *checker = new RPFP(rpfp->ls); - Node *root = CheckerForEdge(edge,checker); - if(checker->Check(root) != unsat){ - Candidate candidate; - ExtractCandidateFromCex(edge,checker,root,candidate); - reporter->InductionFailure(edge,candidate.Children); - candidates.push_back(candidate); - } - slvr.pop(1); - delete checker; + slvr.push(); + RPFP *checker = new RPFP(rpfp->ls); + Node *root = CheckerForEdge(edge,checker); + if(checker->Check(root) != unsat){ + Candidate candidate; + ExtractCandidateFromCex(edge,checker,root,candidate); + reporter->InductionFailure(edge,candidate.Children); + candidates.push_back(candidate); + } + slvr.pop(1); + delete checker; #else - if(!NodeSolutionFromIndSetFull(edge->Parent)){ - RPFP_caching::scoped_solver_for_edge ssfe(gen_cands_rpfp,edge,true /* models */, true /*axioms*/); - gen_cands_rpfp->Push(); - Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp); - if(gen_cands_rpfp->Check(root) != unsat){ - Candidate candidate; - ExtractCandidateFromCex(edge,gen_cands_rpfp,root,candidate); - reporter->InductionFailure(edge,candidate.Children); - candidates.push_back(candidate); - } - gen_cands_rpfp->Pop(1); - } + if(!NodeSolutionFromIndSetFull(edge->Parent)){ + RPFP_caching::scoped_solver_for_edge ssfe(gen_cands_rpfp,edge,true /* models */, true /*axioms*/); + gen_cands_rpfp->Push(); + Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp); + if(gen_cands_rpfp->Check(root) != unsat){ + Candidate candidate; + ExtractCandidateFromCex(edge,gen_cands_rpfp,root,candidate); + reporter->InductionFailure(edge,candidate.Children); + candidates.push_back(candidate); + } + gen_cands_rpfp->Pop(1); + } #endif - } - updated_nodes.clear(); - timer_stop("GenCandIndFail"); + } + updated_nodes.clear(); + timer_stop("GenCandIndFail"); #ifdef CHECK_CANDS_FROM_IND_SET - for(std::list::iterator it = candidates.begin(), en = candidates.end(); it != en; ++it){ - if(!CandidateFeasible(*it)) - throw "produced infeasible candidate"; - } + for(std::list::iterator it = candidates.begin(), en = candidates.end(); it != en; ++it){ + if(!CandidateFeasible(*it)) + throw "produced infeasible candidate"; + } #endif - if(!full_scan && candidates.empty()){ - reporter->Message("No candidates from updates. Trying full scan."); - GenCandidatesFromInductionFailure(true); - } - } + if(!full_scan && candidates.empty()){ + reporter->Message("No candidates from updates. Trying full scan."); + GenCandidatesFromInductionFailure(true); + } + } #ifdef CANDS_FROM_UPDATES - /** If the given edge is not inductive in the current proposed solution, - use the induction failure to generate candidates for extension. */ - void GenCandidatesFromEdgeInductionFailure(RPFP::Edge *edge){ - GenSolutionFromIndSet(true /* add markers */); - for(unsigned i = 0; i < edges.size(); i++){ - slvr.push(); - Edge *edge = edges[i]; - RPFP *checker = new RPFP(rpfp->ls); - Node *root = CheckerForEdge(edge,checker); - if(checker->Check(root) != unsat){ - Candidate candidate; - ExtractCandidateFromCex(edge,checker,root,candidate); - reporter->InductionFailure(edge,candidate.Children); - candidates.push_back(candidate); - } - slvr.pop(1); - delete checker; - } - } + /** If the given edge is not inductive in the current proposed solution, + use the induction failure to generate candidates for extension. */ + void GenCandidatesFromEdgeInductionFailure(RPFP::Edge *edge){ + GenSolutionFromIndSet(true /* add markers */); + for(unsigned i = 0; i < edges.size(); i++){ + slvr.push(); + Edge *edge = edges[i]; + RPFP *checker = new RPFP(rpfp->ls); + Node *root = CheckerForEdge(edge,checker); + if(checker->Check(root) != unsat){ + Candidate candidate; + ExtractCandidateFromCex(edge,checker,root,candidate); + reporter->InductionFailure(edge,candidate.Children); + candidates.push_back(candidate); + } + slvr.pop(1); + delete checker; + } + } #endif - /** Find the unexpanded nodes in the inductive subset. */ - void FindNodesToExpand(){ - for(Unexpanded::iterator it = unexpanded.begin(), en = unexpanded.end(); it != en; ++it){ - Node *node = *it; - if(indset->Candidate(node)) - to_expand.push_back(node); - } - } + /** Find the unexpanded nodes in the inductive subset. */ + void FindNodesToExpand(){ + for(Unexpanded::iterator it = unexpanded.begin(), en = unexpanded.end(); it != en; ++it){ + Node *node = *it; + if(indset->Candidate(node)) + to_expand.push_back(node); + } + } - /** Try to create some extension candidates from the unexpanded - nodes. */ - void ProduceSomeCandidates(){ - while(candidates.empty() && !to_expand.empty()){ - Node *node = to_expand.front(); - to_expand.pop_front(); - TryExpandNode(node); - } - } + /** Try to create some extension candidates from the unexpanded + nodes. */ + void ProduceSomeCandidates(){ + while(candidates.empty() && !to_expand.empty()){ + Node *node = to_expand.front(); + to_expand.pop_front(); + TryExpandNode(node); + } + } - std::list postponed_candidates; + std::list postponed_candidates; - /** Try to produce some extension candidates, first from unexpanded - nides, and if this fails, from induction failure. */ - void ProduceCandidatesForExtension(){ - if(candidates.empty()) - ProduceSomeCandidates(); - while(candidates.empty()){ - FindNodesToExpand(); - if(to_expand.empty()) break; - ProduceSomeCandidates(); - } - if(candidates.empty()){ + /** Try to produce some extension candidates, first from unexpanded + nides, and if this fails, from induction failure. */ + void ProduceCandidatesForExtension(){ + if(candidates.empty()) + ProduceSomeCandidates(); + while(candidates.empty()){ + FindNodesToExpand(); + if(to_expand.empty()) break; + ProduceSomeCandidates(); + } + if(candidates.empty()){ #ifdef DEPTH_FIRST_EXPAND - if(postponed_candidates.empty()){ - GenCandidatesFromInductionFailure(); - postponed_candidates.swap(candidates); - } - if(!postponed_candidates.empty()){ - candidates.push_back(postponed_candidates.front()); - postponed_candidates.pop_front(); - } + if(postponed_candidates.empty()){ + GenCandidatesFromInductionFailure(); + postponed_candidates.swap(candidates); + } + if(!postponed_candidates.empty()){ + candidates.push_back(postponed_candidates.front()); + postponed_candidates.pop_front(); + } #else - GenCandidatesFromInductionFailure(); + GenCandidatesFromInductionFailure(); #endif - } - } + } + } - bool Update(Node *node, const RPFP::Transformer &fact, bool eager=false){ - if(!node->Annotation.SubsetEq(fact)){ - reporter->Update(node,fact,eager); - if(conj_reporter) - conj_reporter->Update(node,fact,eager); - indset->Update(node,fact); - updated_nodes.insert(node->map); - node->Annotation.IntersectWith(fact); - return true; - } - return false; - } + bool Update(Node *node, const RPFP::Transformer &fact, bool eager=false){ + if(!node->Annotation.SubsetEq(fact)){ + reporter->Update(node,fact,eager); + if(conj_reporter) + conj_reporter->Update(node,fact,eager); + indset->Update(node,fact); + updated_nodes.insert(node->map); + node->Annotation.IntersectWith(fact); + return true; + } + return false; + } - bool UpdateNodeToNode(Node *node, Node *top){ - return Update(node,top->Annotation); - } + bool UpdateNodeToNode(Node *node, Node *top){ + return Update(node,top->Annotation); + } - /** Update the unwinding solution, using an interpolant for the - derivation tree. */ - void UpdateWithInterpolant(Node *node, RPFP *tree, Node *top){ - if(top->Outgoing) - for(unsigned i = 0; i < top->Outgoing->Children.size(); i++) - UpdateWithInterpolant(node->Outgoing->Children[i],tree,top->Outgoing->Children[i]); - UpdateNodeToNode(node, top); - heuristic->Update(node); - } + /** Update the unwinding solution, using an interpolant for the + derivation tree. */ + void UpdateWithInterpolant(Node *node, RPFP *tree, Node *top){ + if(top->Outgoing) + for(unsigned i = 0; i < top->Outgoing->Children.size(); i++) + UpdateWithInterpolant(node->Outgoing->Children[i],tree,top->Outgoing->Children[i]); + UpdateNodeToNode(node, top); + heuristic->Update(node); + } - /** Update unwinding lower bounds, using a counterexample. */ + /** Update unwinding lower bounds, using a counterexample. */ - void UpdateWithCounterexample(Node *node, RPFP *tree, Node *top){ - if(top->Outgoing) - for(unsigned i = 0; i < top->Outgoing->Children.size(); i++) - UpdateWithCounterexample(node->Outgoing->Children[i],tree,top->Outgoing->Children[i]); - if(!top->Underapprox.SubsetEq(node->Underapprox)){ - reporter->UpdateUnderapprox(node,top->Underapprox); - // indset->Update(node,top->Annotation); - node->Underapprox.UnionWith(top->Underapprox); - heuristic->Update(node); - } - } + void UpdateWithCounterexample(Node *node, RPFP *tree, Node *top){ + if(top->Outgoing) + for(unsigned i = 0; i < top->Outgoing->Children.size(); i++) + UpdateWithCounterexample(node->Outgoing->Children[i],tree,top->Outgoing->Children[i]); + if(!top->Underapprox.SubsetEq(node->Underapprox)){ + reporter->UpdateUnderapprox(node,top->Underapprox); + // indset->Update(node,top->Annotation); + node->Underapprox.UnionWith(top->Underapprox); + heuristic->Update(node); + } + } - /** Try to update the unwinding to satisfy the upper bound of a - node. */ - bool SatisfyUpperBound(Node *node){ - if(node->Bound.IsFull()) return true; + /** Try to update the unwinding to satisfy the upper bound of a + node. */ + bool SatisfyUpperBound(Node *node){ + if(node->Bound.IsFull()) return true; #ifdef PROPAGATE_BEFORE_CHECK - Propagate(); + Propagate(); #endif - reporter->Bound(node); - int start_decs = rpfp->CumulativeDecisions(); - DerivationTree *dtp = new DerivationTreeSlow(this,unwinding,reporter,heuristic,FullExpand); - DerivationTree &dt = *dtp; - bool res = dt.Derive(unwinding,node,UseUnderapprox); - int end_decs = rpfp->CumulativeDecisions(); - // std::cout << "decisions: " << (end_decs - start_decs) << std::endl; - last_decisions = end_decs - start_decs; - if(res){ - cex.set(dt.tree,dt.top); // note tree is now owned by cex - if(UseUnderapprox){ - UpdateWithCounterexample(node,dt.tree,dt.top); - } - } - else { - UpdateWithInterpolant(node,dt.tree,dt.top); - delete dt.tree; - } - delete dtp; - return !res; - } + reporter->Bound(node); + int start_decs = rpfp->CumulativeDecisions(); + DerivationTree *dtp = new DerivationTreeSlow(this,unwinding,reporter,heuristic,FullExpand); + DerivationTree &dt = *dtp; + bool res = dt.Derive(unwinding,node,UseUnderapprox); + int end_decs = rpfp->CumulativeDecisions(); + // std::cout << "decisions: " << (end_decs - start_decs) << std::endl; + last_decisions = end_decs - start_decs; + if(res){ + cex.set(dt.tree,dt.top); // note tree is now owned by cex + if(UseUnderapprox){ + UpdateWithCounterexample(node,dt.tree,dt.top); + } + } + else { + UpdateWithInterpolant(node,dt.tree,dt.top); + delete dt.tree; + } + delete dtp; + return !res; + } - /* For a given nod in the unwinding, get conjectures from the - proposers and check them locally. Update the node with any true - conjectures. - */ + /* For a given nod in the unwinding, get conjectures from the + proposers and check them locally. Update the node with any true + conjectures. + */ - void DoEagerDeduction(Node *node){ - for(unsigned i = 0; i < proposers.size(); i++){ - const std::vector &conjectures = proposers[i]->Propose(node); - for(unsigned j = 0; j < conjectures.size(); j++){ - const RPFP::Transformer &conjecture = conjectures[j]; - RPFP::Transformer bound(conjecture); - std::vector conj_vec; - unwinding->CollectConjuncts(bound.Formula,conj_vec); - for(unsigned k = 0; k < conj_vec.size(); k++){ - bound.Formula = conj_vec[k]; - if(CheckEdgeCaching(node->Outgoing,bound) == unsat) - Update(node,bound, /* eager = */ true); - //else - //std::cout << "conjecture failed\n"; - } - } - } - } + void DoEagerDeduction(Node *node){ + for(unsigned i = 0; i < proposers.size(); i++){ + const std::vector &conjectures = proposers[i]->Propose(node); + for(unsigned j = 0; j < conjectures.size(); j++){ + const RPFP::Transformer &conjecture = conjectures[j]; + RPFP::Transformer bound(conjecture); + std::vector conj_vec; + unwinding->CollectConjuncts(bound.Formula,conj_vec); + for(unsigned k = 0; k < conj_vec.size(); k++){ + bound.Formula = conj_vec[k]; + if(CheckEdgeCaching(node->Outgoing,bound) == unsat) + Update(node,bound, /* eager = */ true); + //else + //std::cout << "conjecture failed\n"; + } + } + } + } - check_result CheckEdge(RPFP *checker, Edge *edge){ - Node *root = edge->Parent; - checker->Push(); - checker->AssertNode(root); - checker->AssertEdge(edge,1,true); - check_result res = checker->Check(root); - checker->Pop(1); - return res; - } + check_result CheckEdge(RPFP *checker, Edge *edge){ + Node *root = edge->Parent; + checker->Push(); + checker->AssertNode(root); + checker->AssertEdge(edge,1,true); + check_result res = checker->Check(root); + checker->Pop(1); + return res; + } - check_result CheckEdgeCaching(Edge *unwinding_edge, const RPFP::Transformer &bound){ + check_result CheckEdgeCaching(Edge *unwinding_edge, const RPFP::Transformer &bound){ - // use a dedicated solver for this edge - // TODO: can this mess be hidden somehow? + // use a dedicated solver for this edge + // TODO: can this mess be hidden somehow? - RPFP_caching *checker = gen_cands_rpfp; // TODO: a good choice? - Edge *edge = unwinding_edge->map; // get the edge in the original RPFP - RPFP_caching::scoped_solver_for_edge ssfe(checker,edge,true /* models */, true /*axioms*/); - Edge *checker_edge = checker->GetEdgeClone(edge); + RPFP_caching *checker = gen_cands_rpfp; // TODO: a good choice? + Edge *edge = unwinding_edge->map; // get the edge in the original RPFP + RPFP_caching::scoped_solver_for_edge ssfe(checker,edge,true /* models */, true /*axioms*/); + Edge *checker_edge = checker->GetEdgeClone(edge); - // copy the annotations and bound to the clone - Node *root = checker_edge->Parent; - root->Bound = bound; - for(unsigned j = 0; j < checker_edge->Children.size(); j++){ - Node *oc = unwinding_edge->Children[j]; - Node *nc = checker_edge->Children[j]; - nc->Annotation = oc->Annotation; - } + // copy the annotations and bound to the clone + Node *root = checker_edge->Parent; + root->Bound = bound; + for(unsigned j = 0; j < checker_edge->Children.size(); j++){ + Node *oc = unwinding_edge->Children[j]; + Node *nc = checker_edge->Children[j]; + nc->Annotation = oc->Annotation; + } - return CheckEdge(checker,checker_edge); - } + return CheckEdge(checker,checker_edge); + } - /* If the counterexample derivation is partial due to - use of underapproximations, complete it. */ + /* If the counterexample derivation is partial due to + use of underapproximations, complete it. */ - void BuildFullCex(Node *node){ - DerivationTree dt(this,unwinding,reporter,heuristic,FullExpand); - bool res = dt.Derive(unwinding,node,UseUnderapprox,true); // build full tree - if(!res) throw "Duality internal error in BuildFullCex"; - cex.set(dt.tree,dt.top); - } + void BuildFullCex(Node *node){ + DerivationTree dt(this,unwinding,reporter,heuristic,FullExpand); + bool res = dt.Derive(unwinding,node,UseUnderapprox,true); // build full tree + if(!res) throw "Duality internal error in BuildFullCex"; + cex.set(dt.tree,dt.top); + } - void UpdateBackEdges(Node *node){ + void UpdateBackEdges(Node *node){ #ifdef BOUNDED - std::vector &chs = node->Outgoing->Children; - for(unsigned i = 0; i < chs.size(); i++){ - Node *child = chs[i]; - bool is_back = TopoSort[child->map] >= TopoSort[node->map]; - NodeToCounter &nov = back_edges[node]; - NodeToCounter chv = back_edges[child]; - if(is_back) - chv[child->map].val++; - for(NodeToCounter::iterator it = chv.begin(), en = chv.end(); it != en; ++it){ - Node *back = it->first; - Counter &c = nov[back]; - c.val = std::max(c.val,it->second.val); - } - } + std::vector &chs = node->Outgoing->Children; + for(unsigned i = 0; i < chs.size(); i++){ + Node *child = chs[i]; + bool is_back = TopoSort[child->map] >= TopoSort[node->map]; + NodeToCounter &nov = back_edges[node]; + NodeToCounter chv = back_edges[child]; + if(is_back) + chv[child->map].val++; + for(NodeToCounter::iterator it = chv.begin(), en = chv.end(); it != en; ++it){ + Node *back = it->first; + Counter &c = nov[back]; + c.val = std::max(c.val,it->second.val); + } + } #endif - } + } - /** Extend the unwinding, keeping it solved. */ - bool Extend(Candidate &cand, Node *&node){ - timer_start("Extend"); - node = CreateNodeInstance(cand.edge->Parent); - CreateEdgeInstance(cand.edge,node,cand.Children); - UpdateBackEdges(node); - reporter->Extend(node); - DoEagerDeduction(node); // first be eager... - bool res = SatisfyUpperBound(node); // then be lazy - if(res) indset->CloseDescendants(node); - else { + /** Extend the unwinding, keeping it solved. */ + bool Extend(Candidate &cand, Node *&node){ + timer_start("Extend"); + node = CreateNodeInstance(cand.edge->Parent); + CreateEdgeInstance(cand.edge,node,cand.Children); + UpdateBackEdges(node); + reporter->Extend(node); + DoEagerDeduction(node); // first be eager... + bool res = SatisfyUpperBound(node); // then be lazy + if(res) indset->CloseDescendants(node); + else { #ifdef UNDERAPPROX_NODES - ExpandUnderapproxNodes(cex.get_tree(), cex.get_root()); + ExpandUnderapproxNodes(cex.get_tree(), cex.get_root()); #endif - if(UseUnderapprox) BuildFullCex(node); - timer_stop("Extend"); - return res; - } - timer_stop("Extend"); - return res; - } + if(UseUnderapprox) BuildFullCex(node); + timer_stop("Extend"); + return res; + } + timer_stop("Extend"); + return res; + } - void ExpandUnderapproxNodes(RPFP *tree, Node *root){ - Node *node = root->map; - if(underapprox_map.find(node) != underapprox_map.end()){ - RPFP::Transformer cnst = root->Annotation; - tree->EvalNodeAsConstraint(root, cnst); - cnst.Complement(); - Node *orig = underapprox_map[node]; - RPFP::Transformer save = orig->Bound; - orig->Bound = cnst; - DerivationTree dt(this,unwinding,reporter,heuristic,FullExpand); - bool res = dt.Derive(unwinding,orig,UseUnderapprox,true,tree); - if(!res){ - UpdateWithInterpolant(orig,dt.tree,dt.top); - throw "bogus underapprox!"; - } - ExpandUnderapproxNodes(tree,dt.top); - } - else if(root->Outgoing){ - std::vector &chs = root->Outgoing->Children; - for(unsigned i = 0; i < chs.size(); i++) - ExpandUnderapproxNodes(tree,chs[i]); - } - } + void ExpandUnderapproxNodes(RPFP *tree, Node *root){ + Node *node = root->map; + if(underapprox_map.find(node) != underapprox_map.end()){ + RPFP::Transformer cnst = root->Annotation; + tree->EvalNodeAsConstraint(root, cnst); + cnst.Complement(); + Node *orig = underapprox_map[node]; + RPFP::Transformer save = orig->Bound; + orig->Bound = cnst; + DerivationTree dt(this,unwinding,reporter,heuristic,FullExpand); + bool res = dt.Derive(unwinding,orig,UseUnderapprox,true,tree); + if(!res){ + UpdateWithInterpolant(orig,dt.tree,dt.top); + throw "bogus underapprox!"; + } + ExpandUnderapproxNodes(tree,dt.top); + } + else if(root->Outgoing){ + std::vector &chs = root->Outgoing->Children; + for(unsigned i = 0; i < chs.size(); i++) + ExpandUnderapproxNodes(tree,chs[i]); + } + } - // Propagate conjuncts up the unwinding - void Propagate(){ - reporter->Message("beginning propagation"); - timer_start("Propagate"); - std::vector sorted_nodes = unwinding->nodes; - std::sort(sorted_nodes.begin(),sorted_nodes.end(),std::less()); // sorts by sequence number - hash_map > facts; - for(unsigned i = 0; i < sorted_nodes.size(); i++){ - Node *node = sorted_nodes[i]; - std::set &node_facts = facts[node->map]; - if(!(node->Outgoing && indset->Contains(node))) - continue; - std::vector conj_vec; - unwinding->CollectConjuncts(node->Annotation.Formula,conj_vec); - std::set conjs; - std::copy(conj_vec.begin(),conj_vec.end(),std::inserter(conjs,conjs.begin())); - if(!node_facts.empty()){ - RPFP *checker = new RPFP(rpfp->ls); - slvr.push(); - Node *root = checker->CloneNode(node); - Edge *edge = node->Outgoing; - // checker->AssertNode(root); - std::vector cs; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *oc = edge->Children[j]; - Node *nc = checker->CloneNode(oc); - nc->Annotation = oc->Annotation; // is this needed? - cs.push_back(nc); - } - Edge *checker_edge = checker->CreateEdge(root,edge->F,cs); - checker->AssertEdge(checker_edge, 0, true, false); - std::vector propagated; - for(std::set ::iterator it = node_facts.begin(), en = node_facts.end(); it != en;){ - const expr &fact = *it; - if(conjs.find(fact) == conjs.end()){ - root->Bound.Formula = fact; - slvr.push(); - checker->AssertNode(root); - check_result res = checker->Check(root); - slvr.pop(); - if(res != unsat){ - std::set ::iterator victim = it; - ++it; - node_facts.erase(victim); // if it ain't true, nix it - continue; - } - propagated.push_back(fact); - } - ++it; - } - slvr.pop(); - for(unsigned i = 0; i < propagated.size(); i++){ - root->Annotation.Formula = propagated[i]; - UpdateNodeToNode(node,root); - } - delete checker; - } - for(std::set ::iterator it = conjs.begin(), en = conjs.end(); it != en; ++it){ - expr foo = *it; - node_facts.insert(foo); - } - } - timer_stop("Propagate"); - } + // Propagate conjuncts up the unwinding + void Propagate(){ + reporter->Message("beginning propagation"); + timer_start("Propagate"); + std::vector sorted_nodes = unwinding->nodes; + std::sort(sorted_nodes.begin(),sorted_nodes.end(),std::less()); // sorts by sequence number + hash_map > facts; + for(unsigned i = 0; i < sorted_nodes.size(); i++){ + Node *node = sorted_nodes[i]; + std::set &node_facts = facts[node->map]; + if(!(node->Outgoing && indset->Contains(node))) + continue; + std::vector conj_vec; + unwinding->CollectConjuncts(node->Annotation.Formula,conj_vec); + std::set conjs; + std::copy(conj_vec.begin(),conj_vec.end(),std::inserter(conjs,conjs.begin())); + if(!node_facts.empty()){ + RPFP *checker = new RPFP(rpfp->ls); + slvr.push(); + Node *root = checker->CloneNode(node); + Edge *edge = node->Outgoing; + // checker->AssertNode(root); + std::vector cs; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *oc = edge->Children[j]; + Node *nc = checker->CloneNode(oc); + nc->Annotation = oc->Annotation; // is this needed? + cs.push_back(nc); + } + Edge *checker_edge = checker->CreateEdge(root,edge->F,cs); + checker->AssertEdge(checker_edge, 0, true, false); + std::vector propagated; + for(std::set ::iterator it = node_facts.begin(), en = node_facts.end(); it != en;){ + const expr &fact = *it; + if(conjs.find(fact) == conjs.end()){ + root->Bound.Formula = fact; + slvr.push(); + checker->AssertNode(root); + check_result res = checker->Check(root); + slvr.pop(); + if(res != unsat){ + std::set ::iterator victim = it; + ++it; + node_facts.erase(victim); // if it ain't true, nix it + continue; + } + propagated.push_back(fact); + } + ++it; + } + slvr.pop(); + for(unsigned i = 0; i < propagated.size(); i++){ + root->Annotation.Formula = propagated[i]; + UpdateNodeToNode(node,root); + } + delete checker; + } + for(std::set ::iterator it = conjs.begin(), en = conjs.end(); it != en; ++it){ + expr foo = *it; + node_facts.insert(foo); + } + } + timer_stop("Propagate"); + } - /** This class represents a derivation tree. */ - class DerivationTree { - public: + /** This class represents a derivation tree. */ + class DerivationTree { + public: - virtual ~DerivationTree(){} + virtual ~DerivationTree(){} - DerivationTree(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand) - : slvr(rpfp->slvr()), - ctx(rpfp->ctx) - { - duality = _duality; - reporter = _reporter; - heuristic = _heuristic; - full_expand = _full_expand; - } + DerivationTree(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand) + : slvr(rpfp->slvr()), + ctx(rpfp->ctx) + { + duality = _duality; + reporter = _reporter; + heuristic = _heuristic; + full_expand = _full_expand; + } - Duality *duality; - Reporter *reporter; - Heuristic *heuristic; - solver &slvr; - context &ctx; - RPFP *tree; - RPFP::Node *top; - std::list leaves; - bool full_expand; - bool underapprox; - bool constrained; - bool false_approx; - std::vector underapprox_core; - int start_decs, last_decs; + Duality *duality; + Reporter *reporter; + Heuristic *heuristic; + solver &slvr; + context &ctx; + RPFP *tree; + RPFP::Node *top; + std::list leaves; + bool full_expand; + bool underapprox; + bool constrained; + bool false_approx; + std::vector underapprox_core; + int start_decs, last_decs; - /* We build derivation trees in one of three modes: + /* We build derivation trees in one of three modes: - 1) In normal mode, we build the full tree without considering - underapproximations. + 1) In normal mode, we build the full tree without considering + underapproximations. - 2) In underapprox mode, we use underapproximations to cut off - the tree construction. THis means the resulting tree may not - be complete. + 2) In underapprox mode, we use underapproximations to cut off + the tree construction. THis means the resulting tree may not + be complete. - 3) In constrained mode, we build the full tree but use - underapproximations as upper bounds. This mode is used to - complete the partial derivation constructed in underapprox - mode. - */ + 3) In constrained mode, we build the full tree but use + underapproximations as upper bounds. This mode is used to + complete the partial derivation constructed in underapprox + mode. + */ - bool Derive(RPFP *rpfp, RPFP::Node *root, bool _underapprox, bool _constrained = false, RPFP *_tree = 0){ - underapprox = _underapprox; - constrained = _constrained; - false_approx = true; - timer_start("Derive"); + bool Derive(RPFP *rpfp, RPFP::Node *root, bool _underapprox, bool _constrained = false, RPFP *_tree = 0){ + underapprox = _underapprox; + constrained = _constrained; + false_approx = true; + timer_start("Derive"); #ifndef USE_CACHING_RPFP - tree = _tree ? _tree : new RPFP(rpfp->ls); + tree = _tree ? _tree : new RPFP(rpfp->ls); #else - RPFP::LogicSolver *cache_ls = new RPFP::iZ3LogicSolver(ctx); - cache_ls->slvr->push(); - tree = _tree ? _tree : new RPFP_caching(cache_ls); + RPFP::LogicSolver *cache_ls = new RPFP::iZ3LogicSolver(ctx); + cache_ls->slvr->push(); + tree = _tree ? _tree : new RPFP_caching(cache_ls); #endif - tree->HornClauses = rpfp->HornClauses; - tree->Push(); // so we can clear out the solver later when finished - top = CreateApproximatedInstance(root); - tree->AssertNode(top); // assert the negation of the top-level spec - timer_start("Build"); - bool res = Build(); - heuristic->Done(); - timer_stop("Build"); - timer_start("Pop"); - tree->Pop(1); - timer_stop("Pop"); + tree->HornClauses = rpfp->HornClauses; + tree->Push(); // so we can clear out the solver later when finished + top = CreateApproximatedInstance(root); + tree->AssertNode(top); // assert the negation of the top-level spec + timer_start("Build"); + bool res = Build(); + heuristic->Done(); + timer_stop("Build"); + timer_start("Pop"); + tree->Pop(1); + timer_stop("Pop"); #ifdef USE_CACHING_RPFP - cache_ls->slvr->pop(1); - delete cache_ls; - tree->ls = rpfp->ls; + cache_ls->slvr->pop(1); + delete cache_ls; + tree->ls = rpfp->ls; #endif - timer_stop("Derive"); - return res; - } + timer_stop("Derive"); + return res; + } #define WITH_CHILDREN - void InitializeApproximatedInstance(RPFP::Node *to){ - to->Annotation = to->map->Annotation; + void InitializeApproximatedInstance(RPFP::Node *to){ + to->Annotation = to->map->Annotation; #ifndef WITH_CHILDREN - tree->CreateLowerBoundEdge(to); + tree->CreateLowerBoundEdge(to); #endif - leaves.push_back(to); - } + leaves.push_back(to); + } - Node *CreateApproximatedInstance(RPFP::Node *from){ - Node *to = tree->CloneNode(from); - InitializeApproximatedInstance(to); - return to; - } + Node *CreateApproximatedInstance(RPFP::Node *from){ + Node *to = tree->CloneNode(from); + InitializeApproximatedInstance(to); + return to; + } - bool CheckWithUnderapprox(){ - timer_start("CheckWithUnderapprox"); - std::vector leaves_vector(leaves.size()); - std::copy(leaves.begin(),leaves.end(),leaves_vector.begin()); - check_result res = tree->Check(top,leaves_vector); - timer_stop("CheckWithUnderapprox"); - return res != unsat; - } + bool CheckWithUnderapprox(){ + timer_start("CheckWithUnderapprox"); + std::vector leaves_vector(leaves.size()); + std::copy(leaves.begin(),leaves.end(),leaves_vector.begin()); + check_result res = tree->Check(top,leaves_vector); + timer_stop("CheckWithUnderapprox"); + return res != unsat; + } - virtual bool Build(){ + virtual bool Build(){ #ifdef EFFORT_BOUNDED_STRAT - start_decs = tree->CumulativeDecisions(); + start_decs = tree->CumulativeDecisions(); #endif - while(ExpandSomeNodes(true)); // do high-priority expansions - while (true) - { + while(ExpandSomeNodes(true)); // do high-priority expansions + while (true) + { #ifndef WITH_CHILDREN - timer_start("asserting leaves"); - timer_start("pushing"); - tree->Push(); - timer_stop("pushing"); - for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) - tree->AssertEdge((*it)->Outgoing,1); // assert the overapproximation, and keep it past pop - timer_stop("asserting leaves"); - lbool res = tree->Solve(top, 2); // incremental solve, keep interpolants for two pops - timer_start("popping leaves"); - tree->Pop(1); - timer_stop("popping leaves"); + timer_start("asserting leaves"); + timer_start("pushing"); + tree->Push(); + timer_stop("pushing"); + for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) + tree->AssertEdge((*it)->Outgoing,1); // assert the overapproximation, and keep it past pop + timer_stop("asserting leaves"); + lbool res = tree->Solve(top, 2); // incremental solve, keep interpolants for two pops + timer_start("popping leaves"); + tree->Pop(1); + timer_stop("popping leaves"); #else - lbool res; - if((underapprox || false_approx) && top->Outgoing && CheckWithUnderapprox()){ - if(constrained) goto expand_some_nodes; // in constrained mode, keep expanding - goto we_are_sat; // else if underapprox is sat, we stop - } - // tree->Check(top); - res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop + lbool res; + if((underapprox || false_approx) && top->Outgoing && CheckWithUnderapprox()){ + if(constrained) goto expand_some_nodes; // in constrained mode, keep expanding + goto we_are_sat; // else if underapprox is sat, we stop + } + // tree->Check(top); + res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop #endif - if (res == l_false) - return false; + if (res == l_false) + return false; - expand_some_nodes: - if(ExpandSomeNodes()) - continue; + expand_some_nodes: + if(ExpandSomeNodes()) + continue; - we_are_sat: - if(underapprox && !constrained){ - timer_start("ComputeUnderapprox"); - tree->ComputeUnderapprox(top,1); - timer_stop("ComputeUnderapprox"); - } - else { + we_are_sat: + if(underapprox && !constrained){ + timer_start("ComputeUnderapprox"); + tree->ComputeUnderapprox(top,1); + timer_stop("ComputeUnderapprox"); + } + else { #ifdef UNDERAPPROX_NODES #ifndef SKIP_UNDERAPPROX_NODES - timer_start("ComputeUnderapprox"); - tree->ComputeUnderapprox(top,1); - timer_stop("ComputeUnderapprox"); + timer_start("ComputeUnderapprox"); + tree->ComputeUnderapprox(top,1); + timer_stop("ComputeUnderapprox"); #endif #endif - } - return true; - } - } + } + return true; + } + } - virtual void ExpandNode(RPFP::Node *p){ - // tree->RemoveEdge(p->Outgoing); - Edge *ne = p->Outgoing; - if(ne) { - // reporter->Message("Recycling edge..."); - std::vector &cs = ne->Children; - for(unsigned i = 0; i < cs.size(); i++) - InitializeApproximatedInstance(cs[i]); - // ne->dual = expr(); - } - else { - Edge *edge = duality->GetNodeOutgoing(p->map,last_decs); - std::vector &cs = edge->Children; - std::vector children(cs.size()); - for(unsigned i = 0; i < cs.size(); i++) - children[i] = CreateApproximatedInstance(cs[i]); - ne = tree->CreateEdge(p, p->map->Outgoing->F, children); - ne->map = p->map->Outgoing->map; - } + virtual void ExpandNode(RPFP::Node *p){ + // tree->RemoveEdge(p->Outgoing); + Edge *ne = p->Outgoing; + if(ne) { + // reporter->Message("Recycling edge..."); + std::vector &cs = ne->Children; + for(unsigned i = 0; i < cs.size(); i++) + InitializeApproximatedInstance(cs[i]); + // ne->dual = expr(); + } + else { + Edge *edge = duality->GetNodeOutgoing(p->map,last_decs); + std::vector &cs = edge->Children; + std::vector children(cs.size()); + for(unsigned i = 0; i < cs.size(); i++) + children[i] = CreateApproximatedInstance(cs[i]); + ne = tree->CreateEdge(p, p->map->Outgoing->F, children); + ne->map = p->map->Outgoing->map; + } #ifndef WITH_CHILDREN - tree->AssertEdge(ne); // assert the edge in the solver + tree->AssertEdge(ne); // assert the edge in the solver #else - tree->AssertEdge(ne,0,!full_expand,(underapprox || false_approx)); // assert the edge in the solver + tree->AssertEdge(ne,0,!full_expand,(underapprox || false_approx)); // assert the edge in the solver #endif - reporter->Expand(ne); - } + reporter->Expand(ne); + } #define UNDERAPPROXCORE #ifndef UNDERAPPROXCORE - void ExpansionChoices(std::set &best){ - std::set choices; - for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) - if (!tree->Empty(*it)) // if used in the counter-model - choices.insert(*it); - heuristic->ChooseExpand(choices, best); - } + void ExpansionChoices(std::set &best){ + std::set choices; + for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) + if (!tree->Empty(*it)) // if used in the counter-model + choices.insert(*it); + heuristic->ChooseExpand(choices, best); + } #else #if 0 - void ExpansionChoices(std::set &best){ - std::vector unused_set, used_set; - std::set choices; - for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it){ - Node *n = *it; - if (!tree->Empty(n)) - used_set.push_back(n); - else - unused_set.push_back(n); - } - if(tree->Check(top,unused_set) == unsat) - throw "error in ExpansionChoices"; - for(unsigned i = 0; i < used_set.size(); i++){ - Node *n = used_set[i]; - unused_set.push_back(n); - if(!top->Outgoing || tree->Check(top,unused_set) == unsat){ - unused_set.pop_back(); - choices.insert(n); - } - else - std::cout << "Using underapprox of " << n->number << std::endl; - } - heuristic->ChooseExpand(choices, best); - } + void ExpansionChoices(std::set &best){ + std::vector unused_set, used_set; + std::set choices; + for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it){ + Node *n = *it; + if (!tree->Empty(n)) + used_set.push_back(n); + else + unused_set.push_back(n); + } + if(tree->Check(top,unused_set) == unsat) + throw "error in ExpansionChoices"; + for(unsigned i = 0; i < used_set.size(); i++){ + Node *n = used_set[i]; + unused_set.push_back(n); + if(!top->Outgoing || tree->Check(top,unused_set) == unsat){ + unused_set.pop_back(); + choices.insert(n); + } + else + std::cout << "Using underapprox of " << n->number << std::endl; + } + heuristic->ChooseExpand(choices, best); + } #else - void ExpansionChoicesFull(std::set &best, bool high_priority, bool best_only = false){ - std::set choices; - for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) - if (high_priority || !tree->Empty(*it)) // if used in the counter-model - choices.insert(*it); - heuristic->ChooseExpand(choices, best, high_priority, best_only); - } + void ExpansionChoicesFull(std::set &best, bool high_priority, bool best_only = false){ + std::set choices; + for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it) + if (high_priority || !tree->Empty(*it)) // if used in the counter-model + choices.insert(*it); + heuristic->ChooseExpand(choices, best, high_priority, best_only); + } - void ExpansionChoicesRec(std::vector &unused_set, std::vector &used_set, - std::set &choices, int from, int to){ - if(from == to) return; - int orig_unused = unused_set.size(); - unused_set.resize(orig_unused + (to - from)); - std::copy(used_set.begin()+from,used_set.begin()+to,unused_set.begin()+orig_unused); - if(!top->Outgoing || tree->Check(top,unused_set) == unsat){ - unused_set.resize(orig_unused); - if(to - from == 1){ + void ExpansionChoicesRec(std::vector &unused_set, std::vector &used_set, + std::set &choices, int from, int to){ + if(from == to) return; + int orig_unused = unused_set.size(); + unused_set.resize(orig_unused + (to - from)); + std::copy(used_set.begin()+from,used_set.begin()+to,unused_set.begin()+orig_unused); + if(!top->Outgoing || tree->Check(top,unused_set) == unsat){ + unused_set.resize(orig_unused); + if(to - from == 1){ #if 1 - std::cout << "Not using underapprox of " << used_set[from] ->number << std::endl; + std::cout << "Not using underapprox of " << used_set[from] ->number << std::endl; #endif - choices.insert(used_set[from]); - } - else { - int mid = from + (to - from)/2; - ExpansionChoicesRec(unused_set, used_set, choices, from, mid); - ExpansionChoicesRec(unused_set, used_set, choices, mid, to); - } - } - else { + choices.insert(used_set[from]); + } + else { + int mid = from + (to - from)/2; + ExpansionChoicesRec(unused_set, used_set, choices, from, mid); + ExpansionChoicesRec(unused_set, used_set, choices, mid, to); + } + } + else { #if 1 - std::cout << "Using underapprox of "; - for(int i = from; i < to; i++){ - std::cout << used_set[i]->number << " "; - if(used_set[i]->map->Underapprox.IsEmpty()) - std::cout << "(false!) "; - } - std::cout << std::endl; + std::cout << "Using underapprox of "; + for(int i = from; i < to; i++){ + std::cout << used_set[i]->number << " "; + if(used_set[i]->map->Underapprox.IsEmpty()) + std::cout << "(false!) "; + } + std::cout << std::endl; #endif - } - } + } + } - std::set old_choices; + std::set old_choices; - void ExpansionChoices(std::set &best, bool high_priority, bool best_only = false){ - if(!underapprox || constrained || high_priority){ - ExpansionChoicesFull(best, high_priority,best_only); - return; - } - std::vector unused_set, used_set; - std::set choices; - for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it){ - Node *n = *it; - if (!tree->Empty(n)){ - if(old_choices.find(n) != old_choices.end() || n->map->Underapprox.IsEmpty()) - choices.insert(n); - else - used_set.push_back(n); - } - else - unused_set.push_back(n); - } - if(tree->Check(top,unused_set) == unsat) - throw "error in ExpansionChoices"; - ExpansionChoicesRec(unused_set, used_set, choices, 0, used_set.size()); - old_choices = choices; - heuristic->ChooseExpand(choices, best, high_priority); - } + void ExpansionChoices(std::set &best, bool high_priority, bool best_only = false){ + if(!underapprox || constrained || high_priority){ + ExpansionChoicesFull(best, high_priority,best_only); + return; + } + std::vector unused_set, used_set; + std::set choices; + for(std::list::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it){ + Node *n = *it; + if (!tree->Empty(n)){ + if(old_choices.find(n) != old_choices.end() || n->map->Underapprox.IsEmpty()) + choices.insert(n); + else + used_set.push_back(n); + } + else + unused_set.push_back(n); + } + if(tree->Check(top,unused_set) == unsat) + throw "error in ExpansionChoices"; + ExpansionChoicesRec(unused_set, used_set, choices, 0, used_set.size()); + old_choices = choices; + heuristic->ChooseExpand(choices, best, high_priority); + } #endif #endif - bool ExpandSomeNodes(bool high_priority = false, int max = INT_MAX){ + bool ExpandSomeNodes(bool high_priority = false, int max = INT_MAX){ #ifdef EFFORT_BOUNDED_STRAT - last_decs = tree->CumulativeDecisions() - start_decs; + last_decs = tree->CumulativeDecisions() - start_decs; #endif - timer_start("ExpandSomeNodes"); - timer_start("ExpansionChoices"); - std::set choices; - ExpansionChoices(choices,high_priority,max != INT_MAX); - timer_stop("ExpansionChoices"); - std::list leaves_copy = leaves; // copy so can modify orig - leaves.clear(); - int count = 0; - for(std::list::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){ - if(choices.find(*it) != choices.end() && count < max){ - count++; - ExpandNode(*it); - } - else leaves.push_back(*it); - } - timer_stop("ExpandSomeNodes"); - return !choices.empty(); - } + timer_start("ExpandSomeNodes"); + timer_start("ExpansionChoices"); + std::set choices; + ExpansionChoices(choices,high_priority,max != INT_MAX); + timer_stop("ExpansionChoices"); + std::list leaves_copy = leaves; // copy so can modify orig + leaves.clear(); + int count = 0; + for(std::list::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){ + if(choices.find(*it) != choices.end() && count < max){ + count++; + ExpandNode(*it); + } + else leaves.push_back(*it); + } + timer_stop("ExpandSomeNodes"); + return !choices.empty(); + } - void RemoveExpansion(RPFP::Node *p){ - Edge *edge = p->Outgoing; - Node *parent = edge->Parent; + void RemoveExpansion(RPFP::Node *p){ + Edge *edge = p->Outgoing; + Node *parent = edge->Parent; #ifndef KEEP_EXPANSIONS - std::vector cs = edge->Children; - tree->DeleteEdge(edge); - for(unsigned i = 0; i < cs.size(); i++) - tree->DeleteNode(cs[i]); + std::vector cs = edge->Children; + tree->DeleteEdge(edge); + for(unsigned i = 0; i < cs.size(); i++) + tree->DeleteNode(cs[i]); #endif - leaves.push_back(parent); - } + leaves.push_back(parent); + } - // remove all the descendants of tree root (but not root itself) - void RemoveTree(RPFP *tree, RPFP::Node *root){ - Edge *edge = root->Outgoing; - std::vector cs = edge->Children; - tree->DeleteEdge(edge); - for(unsigned i = 0; i < cs.size(); i++){ - RemoveTree(tree,cs[i]); - tree->DeleteNode(cs[i]); - } - } - }; + // remove all the descendants of tree root (but not root itself) + void RemoveTree(RPFP *tree, RPFP::Node *root){ + Edge *edge = root->Outgoing; + std::vector cs = edge->Children; + tree->DeleteEdge(edge); + for(unsigned i = 0; i < cs.size(); i++){ + RemoveTree(tree,cs[i]); + tree->DeleteNode(cs[i]); + } + } + }; - class DerivationTreeSlow : public DerivationTree { - public: + class DerivationTreeSlow : public DerivationTree { + public: - struct stack_entry { - unsigned level; // SMT solver stack level - std::vector expansions; - }; + struct stack_entry { + unsigned level; // SMT solver stack level + std::vector expansions; + }; - std::vector stack; + std::vector stack; - hash_map updates; + hash_map updates; - int restart_interval; + int restart_interval; - DerivationTreeSlow(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand) - : DerivationTree(_duality, rpfp, _reporter, _heuristic, _full_expand) { - stack.push_back(stack_entry()); - } + DerivationTreeSlow(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand) + : DerivationTree(_duality, rpfp, _reporter, _heuristic, _full_expand) { + stack.push_back(stack_entry()); + } - struct DoRestart {}; + struct DoRestart {}; - virtual bool Build(){ - restart_interval = 3; - while (true) { - try { - return BuildMain(); - } - catch (const DoRestart &) { - // clear the statck and try again - updated_nodes.clear(); - while(stack.size() > 1) - PopLevel(); - reporter->Message("restarted"); - restart_interval += 1; - } - } - } + virtual bool Build(){ + restart_interval = 3; + while (true) { + try { + return BuildMain(); + } + catch (const DoRestart &) { + // clear the statck and try again + updated_nodes.clear(); + while(stack.size() > 1) + PopLevel(); + reporter->Message("restarted"); + restart_interval += 1; + } + } + } - // When we check, try to use the same children that were used in the - // previous counterexample. - check_result Check(){ + // When we check, try to use the same children that were used in the + // previous counterexample. + check_result Check(){ #if 0 - std::vector posnodes, negnodes; - std::vector &expansions = stack.back().expansions; - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - std::vector &chs = node->Outgoing->Children; - for(unsigned j = 0; j < chs.size(); j++){ - Node *ch = chs[j]; - int use = heuristic->UseNode(ch); - if(use == 1) - posnodes.push_back(ch); - else if (use == -1) - negnodes.push_back(ch); - } - } - if(!(posnodes.empty() && negnodes.empty())){ - check_result res = tree->CheckWithConstrainedNodes(posnodes,negnodes); - if(res != unsat){ - reporter->Message("matched previous counterexample"); - return res; - } - } + std::vector posnodes, negnodes; + std::vector &expansions = stack.back().expansions; + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + std::vector &chs = node->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++){ + Node *ch = chs[j]; + int use = heuristic->UseNode(ch); + if(use == 1) + posnodes.push_back(ch); + else if (use == -1) + negnodes.push_back(ch); + } + } + if(!(posnodes.empty() && negnodes.empty())){ + check_result res = tree->CheckWithConstrainedNodes(posnodes,negnodes); + if(res != unsat){ + reporter->Message("matched previous counterexample"); + return res; + } + } #endif - return tree->Check(top); - } + return tree->Check(top); + } - bool BuildMain(){ + bool BuildMain(){ - stack.back().level = tree->slvr().get_scope_level(); - bool was_sat = true; - int update_failures = 0; - int total_updates = 0; + stack.back().level = tree->slvr().get_scope_level(); + bool was_sat = true; + int update_failures = 0; + int total_updates = 0; - while (true) - { - lbool res; + while (true) + { + lbool res; - unsigned slvr_level = tree->slvr().get_scope_level(); - if(slvr_level != stack.back().level) - throw "stacks out of sync!"; - reporter->Depth(stack.size()); + unsigned slvr_level = tree->slvr().get_scope_level(); + if(slvr_level != stack.back().level) + throw "stacks out of sync!"; + reporter->Depth(stack.size()); - // res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop - check_result foo = Check(); - res = foo == unsat ? l_false : l_true; + // res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop + check_result foo = Check(); + res = foo == unsat ? l_false : l_true; - if (res == l_false) { - if (stack.empty()) // should never happen - return false; + if (res == l_false) { + if (stack.empty()) // should never happen + return false; - { - std::vector &expansions = stack.back().expansions; - int update_count = 0; - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - try { - tree->SolveSingleNode(top,node); + { + std::vector &expansions = stack.back().expansions; + int update_count = 0; + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + try { + tree->SolveSingleNode(top,node); #ifdef NO_GENERALIZE - node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); + node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); #else - if(expansions.size() == 1 && NodeTooComplicated(node)) - SimplifyNode(node); - else - node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); - Generalize(node); + if(expansions.size() == 1 && NodeTooComplicated(node)) + SimplifyNode(node); + else + node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); + Generalize(node); #endif - } - catch(const RPFP::Bad &){ - // bad interpolants can get us here - throw DoRestart(); - } - catch(const RPFP::ReallyBad &){ - // this could be caused by incompleteness - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - node->map->Annotation.SetFull(); - std::vector &chs = node->map->Outgoing->Children; - for(unsigned j = 0; j < chs.size(); j++) - chs[j]->Annotation.SetFull(); - reporter->Message("incompleteness: cleared annotation and child annotations"); - } - throw DoRestart(); - } - catch(char const *msg){ - // bad interpolants can get us here - reporter->Message(std::string("interpolation failure:") + msg); - throw DoRestart(); - } - if(RecordUpdate(node)){ - update_count++; - total_updates++; - } - else - heuristic->Update(node->map); // make it less likely to expand this node in future - } + } + catch(const RPFP::Bad &){ + // bad interpolants can get us here + throw DoRestart(); + } + catch(const RPFP::ReallyBad &){ + // this could be caused by incompleteness + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + std::vector &chs = node->map->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++) + chs[j]->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation and child annotations"); + } + throw DoRestart(); + } + catch(char const *msg){ + // bad interpolants can get us here + reporter->Message(std::string("interpolation failure:") + msg); + throw DoRestart(); + } + if(RecordUpdate(node)){ + update_count++; + total_updates++; + } + else + heuristic->Update(node->map); // make it less likely to expand this node in future + } #if 1 - if(duality->EnableRestarts) - if(total_updates >= restart_interval) - throw DoRestart(); + if(duality->EnableRestarts) + if(total_updates >= restart_interval) + throw DoRestart(); #endif - if(update_count == 0){ - if(was_sat){ - update_failures++; - if(update_failures > 10){ - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - node->map->Annotation.SetFull(); - reporter->Message("incompleteness: cleared annotation"); - } - throw DoRestart(); - } - } - reporter->Message("backtracked without learning"); - } - else update_failures = 0; - } - tree->ComputeProofCore(); // need to compute the proof core before popping solver - bool propagated = false; - while(1) { - bool prev_level_used = LevelUsedInProof(stack.size()-2); // need to compute this before pop - PopLevel(); - if(stack.size() == 1)break; - if(prev_level_used){ - Node *node = stack.back().expansions[0]; + if(update_count == 0){ + if(was_sat){ + update_failures++; + if(update_failures > 10){ + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation"); + } + throw DoRestart(); + } + } + reporter->Message("backtracked without learning"); + } + else update_failures = 0; + } + tree->ComputeProofCore(); // need to compute the proof core before popping solver + bool propagated = false; + while(1) { + bool prev_level_used = LevelUsedInProof(stack.size()-2); // need to compute this before pop + PopLevel(); + if(stack.size() == 1)break; + if(prev_level_used){ + Node *node = stack.back().expansions[0]; #ifndef NO_PROPAGATE - if(!Propagate(node)) break; + if(!Propagate(node)) break; #endif - if(!RecordUpdate(node)) break; // shouldn't happen! - RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list - propagated = true; - continue; - } - if(propagated) break; // propagation invalidates the proof core, so disable non-chron backtrack - RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list - std::vector &unused_ex = stack.back().expansions; - for(unsigned i = 0; i < unused_ex.size(); i++) - heuristic->Update(unused_ex[i]->map); // make it less likely to expand this node in future - } - HandleUpdatedNodes(); - if(stack.size() == 1){ - if(top->Outgoing) - tree->DeleteEdge(top->Outgoing); // in case we kept the tree - return false; - } - was_sat = false; - } - else { - was_sat = true; - tree->Push(); - std::vector &expansions = stack.back().expansions; + if(!RecordUpdate(node)) break; // shouldn't happen! + RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list + propagated = true; + continue; + } + if(propagated) break; // propagation invalidates the proof core, so disable non-chron backtrack + RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list + std::vector &unused_ex = stack.back().expansions; + for(unsigned i = 0; i < unused_ex.size(); i++) + heuristic->Update(unused_ex[i]->map); // make it less likely to expand this node in future + } + HandleUpdatedNodes(); + if(stack.size() == 1){ + if(top->Outgoing) + tree->DeleteEdge(top->Outgoing); // in case we kept the tree + return false; + } + was_sat = false; + } + else { + was_sat = true; + tree->Push(); + std::vector &expansions = stack.back().expansions; #ifndef NO_DECISIONS #if 0 - if(expansions.size() > 0) - tree->GreedyReduceNodes(expansions[0]->Outgoing->Children); // try to reduce number of children + if(expansions.size() > 0) + tree->GreedyReduceNodes(expansions[0]->Outgoing->Children); // try to reduce number of children #endif - for(unsigned i = 0; i < expansions.size(); i++){ - tree->FixCurrentState(expansions[i]->Outgoing); - } + for(unsigned i = 0; i < expansions.size(); i++){ + tree->FixCurrentState(expansions[i]->Outgoing); + } #endif #if 0 - if(tree->slvr().check() == unsat) - throw "help!"; + if(tree->slvr().check() == unsat) + throw "help!"; #endif - int expand_max = 1; - if(0&&duality->BatchExpand){ - int thing = stack.size() / 10; // * 0.1; - expand_max = std::max(1,thing); - if(expand_max > 1) - std::cout << "foo!\n"; - } + int expand_max = 1; + if(0&&duality->BatchExpand){ + int thing = stack.size() / 10; // * 0.1; + expand_max = std::max(1,thing); + if(expand_max > 1) + std::cout << "foo!\n"; + } - if(ExpandSomeNodes(false,expand_max)) - continue; - tree->Pop(1); - node_order.clear(); - while(stack.size() > 1){ - tree->Pop(1); - std::vector &expansions = stack.back().expansions; - for(unsigned i = 0; i < expansions.size(); i++) - node_order.push_back(expansions[i]); - stack.pop_back(); - } + if(ExpandSomeNodes(false,expand_max)) + continue; + tree->Pop(1); + node_order.clear(); + while(stack.size() > 1){ + tree->Pop(1); + std::vector &expansions = stack.back().expansions; + for(unsigned i = 0; i < expansions.size(); i++) + node_order.push_back(expansions[i]); + stack.pop_back(); + } #if 0 - Reduce(); + Reduce(); #endif - return true; - } - } - } + return true; + } + } + } - std::vector node_order; + std::vector node_order; - void Reduce(){ - tree->Push(); - // tree->AssertNode(top); // assert the negation of the top-level spec - for(int i = node_order.size()-1; i >= 0; --i){ - Edge *edge = node_order[i]->Outgoing; - if(edge){ - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *ch = edge->Children[j]; - if(!ch->Outgoing) - ch->Annotation.SetEmpty(); - } - tree->AssertEdge(edge,0,true); - } - } - tree->GreedyReduceNodes(node_order); // try to reduce the counterexample size - tree->Pop(1); - } + void Reduce(){ + tree->Push(); + // tree->AssertNode(top); // assert the negation of the top-level spec + for(int i = node_order.size()-1; i >= 0; --i){ + Edge *edge = node_order[i]->Outgoing; + if(edge){ + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *ch = edge->Children[j]; + if(!ch->Outgoing) + ch->Annotation.SetEmpty(); + } + tree->AssertEdge(edge,0,true); + } + } + tree->GreedyReduceNodes(node_order); // try to reduce the counterexample size + tree->Pop(1); + } - void PopLevel(){ - std::vector &expansions = stack.back().expansions; - tree->Pop(1); - hash_set leaves_to_remove; - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - // if(node != top) - // tree->ConstrainParent(node->Incoming[0],node); - std::vector &cs = node->Outgoing->Children; - for(unsigned i = 0; i < cs.size(); i++){ - leaves_to_remove.insert(cs[i]); - UnmapNode(cs[i]); - if(std::find(updated_nodes.begin(),updated_nodes.end(),cs[i]) != updated_nodes.end()) - throw "help!"; - } - } - RemoveLeaves(leaves_to_remove); // have to do this before actually deleting the children - for(unsigned i = 0; i < expansions.size(); i++){ - Node *node = expansions[i]; - RemoveExpansion(node); - } - stack.pop_back(); - } + void PopLevel(){ + std::vector &expansions = stack.back().expansions; + tree->Pop(1); + hash_set leaves_to_remove; + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + // if(node != top) + // tree->ConstrainParent(node->Incoming[0],node); + std::vector &cs = node->Outgoing->Children; + for(unsigned i = 0; i < cs.size(); i++){ + leaves_to_remove.insert(cs[i]); + UnmapNode(cs[i]); + if(std::find(updated_nodes.begin(),updated_nodes.end(),cs[i]) != updated_nodes.end()) + throw "help!"; + } + } + RemoveLeaves(leaves_to_remove); // have to do this before actually deleting the children + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + RemoveExpansion(node); + } + stack.pop_back(); + } - bool NodeTooComplicated(Node *node){ - int ops = tree->CountOperators(node->Annotation.Formula); - if(ops > 10) return true; - node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); - return tree->CountOperators(node->Annotation.Formula) > 3; - } + bool NodeTooComplicated(Node *node){ + int ops = tree->CountOperators(node->Annotation.Formula); + if(ops > 10) return true; + node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); + return tree->CountOperators(node->Annotation.Formula) > 3; + } - void SimplifyNode(Node *node){ - // have to destroy the old proof to get a new interpolant - timer_start("SimplifyNode"); - tree->PopPush(); - try { - tree->InterpolateByCases(top,node); - } - catch(const RPFP::Bad&){ - timer_stop("SimplifyNode"); - throw RPFP::Bad(); - } - timer_stop("SimplifyNode"); - } + void SimplifyNode(Node *node){ + // have to destroy the old proof to get a new interpolant + timer_start("SimplifyNode"); + tree->PopPush(); + try { + tree->InterpolateByCases(top,node); + } + catch(const RPFP::Bad&){ + timer_stop("SimplifyNode"); + throw RPFP::Bad(); + } + timer_stop("SimplifyNode"); + } - bool LevelUsedInProof(unsigned level){ - std::vector &expansions = stack[level].expansions; - for(unsigned i = 0; i < expansions.size(); i++) - if(tree->EdgeUsedInProof(expansions[i]->Outgoing)) - return true; - return false; - } + bool LevelUsedInProof(unsigned level){ + std::vector &expansions = stack[level].expansions; + for(unsigned i = 0; i < expansions.size(); i++) + if(tree->EdgeUsedInProof(expansions[i]->Outgoing)) + return true; + return false; + } - void RemoveUpdateNodesAtCurrentLevel() { - for(std::list::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){ - Node *node = *it; - if(AtCurrentStackLevel(node->Incoming[0]->Parent)){ - std::list::iterator victim = it; - ++it; - updated_nodes.erase(victim); - } - else - ++it; - } - } + void RemoveUpdateNodesAtCurrentLevel() { + for(std::list::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){ + Node *node = *it; + if(AtCurrentStackLevel(node->Incoming[0]->Parent)){ + std::list::iterator victim = it; + ++it; + updated_nodes.erase(victim); + } + else + ++it; + } + } - void RemoveLeaves(hash_set &leaves_to_remove){ - std::list leaves_copy; - leaves_copy.swap(leaves); - for(std::list::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){ - if(leaves_to_remove.find(*it) == leaves_to_remove.end()) - leaves.push_back(*it); - } - } + void RemoveLeaves(hash_set &leaves_to_remove){ + std::list leaves_copy; + leaves_copy.swap(leaves); + for(std::list::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){ + if(leaves_to_remove.find(*it) == leaves_to_remove.end()) + leaves.push_back(*it); + } + } - hash_map > node_map; - std::list updated_nodes; + hash_map > node_map; + std::list updated_nodes; - virtual void ExpandNode(RPFP::Node *p){ - stack.push_back(stack_entry()); - stack.back().level = tree->slvr().get_scope_level(); - stack.back().expansions.push_back(p); - DerivationTree::ExpandNode(p); - std::vector &new_nodes = p->Outgoing->Children; - for(unsigned i = 0; i < new_nodes.size(); i++){ - Node *n = new_nodes[i]; - node_map[n->map].push_back(n); - } - } + virtual void ExpandNode(RPFP::Node *p){ + stack.push_back(stack_entry()); + stack.back().level = tree->slvr().get_scope_level(); + stack.back().expansions.push_back(p); + DerivationTree::ExpandNode(p); + std::vector &new_nodes = p->Outgoing->Children; + for(unsigned i = 0; i < new_nodes.size(); i++){ + Node *n = new_nodes[i]; + node_map[n->map].push_back(n); + } + } - bool RecordUpdate(Node *node){ - bool res = duality->UpdateNodeToNode(node->map,node); - if(res){ - std::vector to_update = node_map[node->map]; - for(unsigned i = 0; i < to_update.size(); i++){ - Node *node2 = to_update[i]; - // maintain invariant that no nodes on updated list are created at current stack level - if(node2 == node || !(node->Incoming.size() > 0 && AtCurrentStackLevel(node2->Incoming[0]->Parent))){ - updated_nodes.push_back(node2); - if(node2 != node) - node2->Annotation = node->Annotation; - } - } - } - return res; - } + bool RecordUpdate(Node *node){ + bool res = duality->UpdateNodeToNode(node->map,node); + if(res){ + std::vector to_update = node_map[node->map]; + for(unsigned i = 0; i < to_update.size(); i++){ + Node *node2 = to_update[i]; + // maintain invariant that no nodes on updated list are created at current stack level + if(node2 == node || !(node->Incoming.size() > 0 && AtCurrentStackLevel(node2->Incoming[0]->Parent))){ + updated_nodes.push_back(node2); + if(node2 != node) + node2->Annotation = node->Annotation; + } + } + } + return res; + } - void HandleUpdatedNodes(){ - for(std::list::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){ - Node *node = *it; - node->Annotation = node->map->Annotation; - if(node->Incoming.size() > 0) - tree->ConstrainParent(node->Incoming[0],node); - if(AtCurrentStackLevel(node->Incoming[0]->Parent)){ - std::list::iterator victim = it; - ++it; - updated_nodes.erase(victim); - } - else - ++it; - } - } + void HandleUpdatedNodes(){ + for(std::list::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){ + Node *node = *it; + node->Annotation = node->map->Annotation; + if(node->Incoming.size() > 0) + tree->ConstrainParent(node->Incoming[0],node); + if(AtCurrentStackLevel(node->Incoming[0]->Parent)){ + std::list::iterator victim = it; + ++it; + updated_nodes.erase(victim); + } + else + ++it; + } + } - bool AtCurrentStackLevel(Node *node){ - std::vector vec = stack.back().expansions; - for(unsigned i = 0; i < vec.size(); i++) - if(vec[i] == node) - return true; - return false; - } + bool AtCurrentStackLevel(Node *node){ + std::vector vec = stack.back().expansions; + for(unsigned i = 0; i < vec.size(); i++) + if(vec[i] == node) + return true; + return false; + } - void UnmapNode(Node *node){ - std::vector &vec = node_map[node->map]; - for(unsigned i = 0; i < vec.size(); i++){ - if(vec[i] == node){ - std::swap(vec[i],vec.back()); - vec.pop_back(); - return; - } - } - throw "can't unmap node"; - } + void UnmapNode(Node *node){ + std::vector &vec = node_map[node->map]; + for(unsigned i = 0; i < vec.size(); i++){ + if(vec[i] == node){ + std::swap(vec[i],vec.back()); + vec.pop_back(); + return; + } + } + throw "can't unmap node"; + } - void Generalize(Node *node){ + void Generalize(Node *node){ #ifndef USE_RPFP_CLONE - tree->Generalize(top,node); + tree->Generalize(top,node); #else - RPFP_caching *clone_rpfp = duality->clone_rpfp; - if(!node->Outgoing->map) return; - Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map); - Node *clone_node = clone_edge->Parent; - clone_node->Annotation = node->Annotation; - for(unsigned i = 0; i < clone_edge->Children.size(); i++) - clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation; - clone_rpfp->GeneralizeCache(clone_edge); - node->Annotation = clone_node->Annotation; + RPFP_caching *clone_rpfp = duality->clone_rpfp; + if(!node->Outgoing->map) return; + Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map); + Node *clone_node = clone_edge->Parent; + clone_node->Annotation = node->Annotation; + for(unsigned i = 0; i < clone_edge->Children.size(); i++) + clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation; + clone_rpfp->GeneralizeCache(clone_edge); + node->Annotation = clone_node->Annotation; #endif - } + } - bool Propagate(Node *node){ + bool Propagate(Node *node){ #ifdef USE_RPFP_CLONE - RPFP_caching *clone_rpfp = duality->clone_rpfp; - Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map); - Node *clone_node = clone_edge->Parent; - clone_node->Annotation = node->map->Annotation; - for(unsigned i = 0; i < clone_edge->Children.size(); i++) - clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation; - bool res = clone_rpfp->PropagateCache(clone_edge); - if(res) - node->Annotation = clone_node->Annotation; - return res; + RPFP_caching *clone_rpfp = duality->clone_rpfp; + Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map); + Node *clone_node = clone_edge->Parent; + clone_node->Annotation = node->map->Annotation; + for(unsigned i = 0; i < clone_edge->Children.size(); i++) + clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation; + bool res = clone_rpfp->PropagateCache(clone_edge); + if(res) + node->Annotation = clone_node->Annotation; + return res; #else - return false; + return false; #endif - } + } - }; + }; - class Covering { + class Covering { - struct cover_info { - Node *covered_by; - std::list covers; - bool dominated; - std::set dominates; - cover_info(){ - covered_by = 0; - dominated = false; - } - }; + struct cover_info { + Node *covered_by; + std::list covers; + bool dominated; + std::set dominates; + cover_info(){ + covered_by = 0; + dominated = false; + } + }; - typedef hash_map cover_map; - cover_map cm; - Duality *parent; - bool some_updates; + typedef hash_map cover_map; + cover_map cm; + Duality *parent; + bool some_updates; #define NO_CONJ_ON_SIMPLE_LOOPS #ifdef NO_CONJ_ON_SIMPLE_LOOPS - hash_set simple_loops; + hash_set simple_loops; #endif - Node *&covered_by(Node *node){ - return cm[node].covered_by; - } + Node *&covered_by(Node *node){ + return cm[node].covered_by; + } - std::list &covers(Node *node){ - return cm[node].covers; - } + std::list &covers(Node *node){ + return cm[node].covers; + } - std::vector &insts_of_node(Node *node){ - return parent->insts_of_node[node]; - } + std::vector &insts_of_node(Node *node){ + return parent->insts_of_node[node]; + } - Reporter *reporter(){ - return parent->reporter; - } + Reporter *reporter(){ + return parent->reporter; + } - std::set &dominates(Node *x){ - return cm[x].dominates; - } + std::set &dominates(Node *x){ + return cm[x].dominates; + } - bool dominates(Node *x, Node *y){ - std::set &d = cm[x].dominates; - return d.find(y) != d.end(); - } + bool dominates(Node *x, Node *y){ + std::set &d = cm[x].dominates; + return d.find(y) != d.end(); + } - bool &dominated(Node *x){ - return cm[x].dominated; - } + bool &dominated(Node *x){ + return cm[x].dominated; + } - public: + public: - Covering(Duality *_parent){ - parent = _parent; - some_updates = false; + Covering(Duality *_parent){ + parent = _parent; + some_updates = false; #ifdef NO_CONJ_ON_SIMPLE_LOOPS - hash_map > outgoing; - for(unsigned i = 0; i < parent->rpfp->edges.size(); i++) - outgoing[parent->rpfp->edges[i]->Parent].push_back(parent->rpfp->edges[i]); - for(unsigned i = 0; i < parent->rpfp->nodes.size(); i++){ - Node * node = parent->rpfp->nodes[i]; - std::vector &outs = outgoing[node]; - if(outs.size() == 2){ - for(int j = 0; j < 2; j++){ - Edge *loop_edge = outs[j]; - if(loop_edge->Children.size() == 1 && loop_edge->Children[0] == loop_edge->Parent) - simple_loops.insert(node); - } - } - } + hash_map > outgoing; + for(unsigned i = 0; i < parent->rpfp->edges.size(); i++) + outgoing[parent->rpfp->edges[i]->Parent].push_back(parent->rpfp->edges[i]); + for(unsigned i = 0; i < parent->rpfp->nodes.size(); i++){ + Node * node = parent->rpfp->nodes[i]; + std::vector &outs = outgoing[node]; + if(outs.size() == 2){ + for(int j = 0; j < 2; j++){ + Edge *loop_edge = outs[j]; + if(loop_edge->Children.size() == 1 && loop_edge->Children[0] == loop_edge->Parent) + simple_loops.insert(node); + } + } + } #endif - } + } - bool IsCoveredRec(hash_set &memo, Node *node){ - if(memo.find(node) != memo.end()) - return false; - memo.insert(node); - if(covered_by(node)) return true; - for(unsigned i = 0; i < node->Outgoing->Children.size(); i++) - if(IsCoveredRec(memo,node->Outgoing->Children[i])) - return true; - return false; - } + bool IsCoveredRec(hash_set &memo, Node *node){ + if(memo.find(node) != memo.end()) + return false; + memo.insert(node); + if(covered_by(node)) return true; + for(unsigned i = 0; i < node->Outgoing->Children.size(); i++) + if(IsCoveredRec(memo,node->Outgoing->Children[i])) + return true; + return false; + } - bool IsCovered(Node *node){ - hash_set memo; - return IsCoveredRec(memo,node); - } + bool IsCovered(Node *node){ + hash_set memo; + return IsCoveredRec(memo,node); + } #ifndef UNDERAPPROX_NODES - void RemoveCoveringsBy(Node *node){ - std::list &cs = covers(node); - for(std::list::iterator it = cs.begin(), en = cs.end(); it != en; it++){ - covered_by(*it) = 0; - reporter()->RemoveCover(*it,node); - } - cs.clear(); - } + void RemoveCoveringsBy(Node *node){ + std::list &cs = covers(node); + for(std::list::iterator it = cs.begin(), en = cs.end(); it != en; it++){ + covered_by(*it) = 0; + reporter()->RemoveCover(*it,node); + } + cs.clear(); + } #else - void RemoveCoveringsBy(Node *node){ - std::vector &cs = parent->all_of_node[node->map]; - for(std::vector::iterator it = cs.begin(), en = cs.end(); it != en; it++){ - Node *other = *it; - if(covered_by(other) && CoverOrder(node,other)){ - covered_by(other) = 0; - reporter()->RemoveCover(*it,node); - } - } - } + void RemoveCoveringsBy(Node *node){ + std::vector &cs = parent->all_of_node[node->map]; + for(std::vector::iterator it = cs.begin(), en = cs.end(); it != en; it++){ + Node *other = *it; + if(covered_by(other) && CoverOrder(node,other)){ + covered_by(other) = 0; + reporter()->RemoveCover(*it,node); + } + } + } #endif - void RemoveAscendantCoveringsRec(hash_set &memo, Node *node){ - if(memo.find(node) != memo.end()) - return; - memo.insert(node); - RemoveCoveringsBy(node); - for(std::vector::iterator it = node->Incoming.begin(), en = node->Incoming.end(); it != en; ++it) - RemoveAscendantCoveringsRec(memo,(*it)->Parent); - } + void RemoveAscendantCoveringsRec(hash_set &memo, Node *node){ + if(memo.find(node) != memo.end()) + return; + memo.insert(node); + RemoveCoveringsBy(node); + for(std::vector::iterator it = node->Incoming.begin(), en = node->Incoming.end(); it != en; ++it) + RemoveAscendantCoveringsRec(memo,(*it)->Parent); + } - void RemoveAscendantCoverings(Node *node){ - hash_set memo; - RemoveAscendantCoveringsRec(memo,node); - } + void RemoveAscendantCoverings(Node *node){ + hash_set memo; + RemoveAscendantCoveringsRec(memo,node); + } - bool CoverOrder(Node *covering, Node *covered){ + bool CoverOrder(Node *covering, Node *covered){ #ifdef UNDERAPPROX_NODES - if(parent->underapprox_map.find(covered) != parent->underapprox_map.end()) - return false; - if(parent->underapprox_map.find(covering) != parent->underapprox_map.end()) - return covering->number < covered->number || parent->underapprox_map[covering] == covered; + if(parent->underapprox_map.find(covered) != parent->underapprox_map.end()) + return false; + if(parent->underapprox_map.find(covering) != parent->underapprox_map.end()) + return covering->number < covered->number || parent->underapprox_map[covering] == covered; #endif - return covering->number < covered->number; - } + return covering->number < covered->number; + } - bool CheckCover(Node *covered, Node *covering){ - return - CoverOrder(covering,covered) - && covered->Annotation.SubsetEq(covering->Annotation) - && !IsCovered(covering); - } + bool CheckCover(Node *covered, Node *covering){ + return + CoverOrder(covering,covered) + && covered->Annotation.SubsetEq(covering->Annotation) + && !IsCovered(covering); + } - bool CoverByNode(Node *covered, Node *covering){ - if(CheckCover(covered,covering)){ - covered_by(covered) = covering; - covers(covering).push_back(covered); - std::vector others; others.push_back(covering); - reporter()->AddCover(covered,others); - RemoveAscendantCoverings(covered); - return true; - } - else - return false; - } + bool CoverByNode(Node *covered, Node *covering){ + if(CheckCover(covered,covering)){ + covered_by(covered) = covering; + covers(covering).push_back(covered); + std::vector others; others.push_back(covering); + reporter()->AddCover(covered,others); + RemoveAscendantCoverings(covered); + return true; + } + else + return false; + } #ifdef UNDERAPPROX_NODES - bool CoverByAll(Node *covered){ - RPFP::Transformer all = covered->Annotation; - all.SetEmpty(); - std::vector &insts = parent->insts_of_node[covered->map]; - std::vector others; - for(unsigned i = 0; i < insts.size(); i++){ - Node *covering = insts[i]; - if(CoverOrder(covering,covered) && !IsCovered(covering)){ - others.push_back(covering); - all.UnionWith(covering->Annotation); - } - } - if(others.size() && covered->Annotation.SubsetEq(all)){ - covered_by(covered) = covered; // anything non-null will do - reporter()->AddCover(covered,others); - RemoveAscendantCoverings(covered); - return true; - } - else - return false; - } + bool CoverByAll(Node *covered){ + RPFP::Transformer all = covered->Annotation; + all.SetEmpty(); + std::vector &insts = parent->insts_of_node[covered->map]; + std::vector others; + for(unsigned i = 0; i < insts.size(); i++){ + Node *covering = insts[i]; + if(CoverOrder(covering,covered) && !IsCovered(covering)){ + others.push_back(covering); + all.UnionWith(covering->Annotation); + } + } + if(others.size() && covered->Annotation.SubsetEq(all)){ + covered_by(covered) = covered; // anything non-null will do + reporter()->AddCover(covered,others); + RemoveAscendantCoverings(covered); + return true; + } + else + return false; + } #endif - bool Close(Node *node){ - if(covered_by(node)) - return true; + bool Close(Node *node){ + if(covered_by(node)) + return true; #ifndef UNDERAPPROX_NODES - std::vector &insts = insts_of_node(node->map); - for(unsigned i = 0; i < insts.size(); i++) - if(CoverByNode(node,insts[i])) - return true; + std::vector &insts = insts_of_node(node->map); + for(unsigned i = 0; i < insts.size(); i++) + if(CoverByNode(node,insts[i])) + return true; #else - if(CoverByAll(node)) - return true; + if(CoverByAll(node)) + return true; #endif - return false; - } + return false; + } - bool CloseDescendantsRec(hash_set &memo, Node *node){ - if(memo.find(node) != memo.end()) - return false; - for(unsigned i = 0; i < node->Outgoing->Children.size(); i++) - if(CloseDescendantsRec(memo,node->Outgoing->Children[i])) - return true; - if(Close(node)) - return true; - memo.insert(node); - return false; - } + bool CloseDescendantsRec(hash_set &memo, Node *node){ + if(memo.find(node) != memo.end()) + return false; + for(unsigned i = 0; i < node->Outgoing->Children.size(); i++) + if(CloseDescendantsRec(memo,node->Outgoing->Children[i])) + return true; + if(Close(node)) + return true; + memo.insert(node); + return false; + } - bool CloseDescendants(Node *node){ - timer_start("CloseDescendants"); - hash_set memo; - bool res = CloseDescendantsRec(memo,node); - timer_stop("CloseDescendants"); - return res; - } + bool CloseDescendants(Node *node){ + timer_start("CloseDescendants"); + hash_set memo; + bool res = CloseDescendantsRec(memo,node); + timer_stop("CloseDescendants"); + return res; + } - bool Contains(Node *node){ - timer_start("Contains"); - bool res = !IsCovered(node); - timer_stop("Contains"); - return res; - } + bool Contains(Node *node){ + timer_start("Contains"); + bool res = !IsCovered(node); + timer_stop("Contains"); + return res; + } - bool Candidate(Node *node){ - timer_start("Candidate"); - bool res = !IsCovered(node) && !dominated(node); - timer_stop("Candidate"); - return res; - } + bool Candidate(Node *node){ + timer_start("Candidate"); + bool res = !IsCovered(node) && !dominated(node); + timer_stop("Candidate"); + return res; + } - void SetDominated(Node *node){ - dominated(node) = true; - } + void SetDominated(Node *node){ + dominated(node) = true; + } - bool CouldCover(Node *covered, Node *covering){ + bool CouldCover(Node *covered, Node *covering){ #ifdef NO_CONJ_ON_SIMPLE_LOOPS - // Forsimple loops, we rely on propagation, not covering - if(simple_loops.find(covered->map) != simple_loops.end()) - return false; + // Forsimple loops, we rely on propagation, not covering + if(simple_loops.find(covered->map) != simple_loops.end()) + return false; #endif #ifdef UNDERAPPROX_NODES - // if(parent->underapprox_map.find(covering) != parent->underapprox_map.end()) - // return parent->underapprox_map[covering] == covered; + // if(parent->underapprox_map.find(covering) != parent->underapprox_map.end()) + // return parent->underapprox_map[covering] == covered; #endif - if(CoverOrder(covering,covered) - && !IsCovered(covering)){ - RPFP::Transformer f(covering->Annotation); f.SetEmpty(); + if(CoverOrder(covering,covered) + && !IsCovered(covering)){ + RPFP::Transformer f(covering->Annotation); f.SetEmpty(); #if defined(TOP_DOWN) || defined(EFFORT_BOUNDED_STRAT) - if(parent->StratifiedInlining) - return true; + if(parent->StratifiedInlining) + return true; #endif - return !covering->Annotation.SubsetEq(f); - } - return false; - } + return !covering->Annotation.SubsetEq(f); + } + return false; + } - bool ContainsCex(Node *node, Counterexample &cex){ - expr val = cex.get_tree()->Eval(cex.get_root()->Outgoing,node->Annotation.Formula); - return eq(val,parent->ctx.bool_val(true)); - } + bool ContainsCex(Node *node, Counterexample &cex){ + expr val = cex.get_tree()->Eval(cex.get_root()->Outgoing,node->Annotation.Formula); + return eq(val,parent->ctx.bool_val(true)); + } - /** We conjecture that the annotations of similar nodes may be - true of this one. We start with later nodes, on the - principle that their annotations are likely weaker. We save - a counterexample -- if annotations of other nodes are true - in this counterexample, we don't need to check them. - */ + /** We conjecture that the annotations of similar nodes may be + true of this one. We start with later nodes, on the + principle that their annotations are likely weaker. We save + a counterexample -- if annotations of other nodes are true + in this counterexample, we don't need to check them. + */ #ifndef UNDERAPPROX_NODES - bool Conjecture(Node *node){ - std::vector &insts = insts_of_node(node->map); - Counterexample cex; - for(int i = insts.size() - 1; i >= 0; i--){ - Node *other = insts[i]; - if(CouldCover(node,other)){ - reporter()->Forcing(node,other); - if(cex.get_tree() && !ContainsCex(other,cex)) - continue; - cex.clear(); - if(parent->ProveConjecture(node,other->Annotation,other,&cex)) - if(CloseDescendants(node)) - return true; - } - } - cex.clear(); - return false; - } + bool Conjecture(Node *node){ + std::vector &insts = insts_of_node(node->map); + Counterexample cex; + for(int i = insts.size() - 1; i >= 0; i--){ + Node *other = insts[i]; + if(CouldCover(node,other)){ + reporter()->Forcing(node,other); + if(cex.get_tree() && !ContainsCex(other,cex)) + continue; + cex.clear(); + if(parent->ProveConjecture(node,other->Annotation,other,&cex)) + if(CloseDescendants(node)) + return true; + } + } + cex.clear(); + return false; + } #else - bool Conjecture(Node *node){ - std::vector &insts = insts_of_node(node->map); - Counterexample cex; - RPFP::Transformer Bound = node->Annotation; - Bound.SetEmpty(); - bool some_other = false; - for(int i = insts.size() - 1; i >= 0; i--){ - Node *other = insts[i]; - if(CouldCover(node,other)){ - reporter()->Forcing(node,other); - Bound.UnionWith(other->Annotation); - some_other = true; - } - } - if(some_other && parent->ProveConjecture(node,Bound)){ - CloseDescendants(node); - return true; - } - return false; - } + bool Conjecture(Node *node){ + std::vector &insts = insts_of_node(node->map); + Counterexample cex; + RPFP::Transformer Bound = node->Annotation; + Bound.SetEmpty(); + bool some_other = false; + for(int i = insts.size() - 1; i >= 0; i--){ + Node *other = insts[i]; + if(CouldCover(node,other)){ + reporter()->Forcing(node,other); + Bound.UnionWith(other->Annotation); + some_other = true; + } + } + if(some_other && parent->ProveConjecture(node,Bound)){ + CloseDescendants(node); + return true; + } + return false; + } #endif - void Update(Node *node, const RPFP::Transformer &update){ - RemoveCoveringsBy(node); - some_updates = true; - } + void Update(Node *node, const RPFP::Transformer &update){ + RemoveCoveringsBy(node); + some_updates = true; + } #ifndef UNDERAPPROX_NODES - Node *GetSimilarNode(Node *node){ - if(!some_updates) - return 0; - std::vector &insts = insts_of_node(node->map); - for(int i = insts.size()-1; i >= 0; i--){ - Node *other = insts[i]; - if(dominates(node,other)) - if(CoverOrder(other,node) - && !IsCovered(other)) - return other; - } - return 0; - } + Node *GetSimilarNode(Node *node){ + if(!some_updates) + return 0; + std::vector &insts = insts_of_node(node->map); + for(int i = insts.size()-1; i >= 0; i--){ + Node *other = insts[i]; + if(dominates(node,other)) + if(CoverOrder(other,node) + && !IsCovered(other)) + return other; + } + return 0; + } #else - Node *GetSimilarNode(Node *node){ - if(!some_updates) - return 0; - std::vector &insts = insts_of_node(node->map); - for(int i = insts.size() - 1; i >= 0; i--){ - Node *other = insts[i]; - if(CoverOrder(other,node) - && !IsCovered(other)) - return other; - } - return 0; - } + Node *GetSimilarNode(Node *node){ + if(!some_updates) + return 0; + std::vector &insts = insts_of_node(node->map); + for(int i = insts.size() - 1; i >= 0; i--){ + Node *other = insts[i]; + if(CoverOrder(other,node) + && !IsCovered(other)) + return other; + } + return 0; + } #endif - bool Dominates(Node * node, Node *other){ - if(node == other) return false; - if(other->Outgoing->map == 0) return true; - if(node->Outgoing->map == other->Outgoing->map){ - assert(node->Outgoing->Children.size() == other->Outgoing->Children.size()); - for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ - Node *nc = node->Outgoing->Children[i]; - Node *oc = other->Outgoing->Children[i]; - if(!(nc == oc || oc->Outgoing->map ==0 || dominates(nc,oc))) - return false; - } - return true; - } - return false; - } + bool Dominates(Node * node, Node *other){ + if(node == other) return false; + if(other->Outgoing->map == 0) return true; + if(node->Outgoing->map == other->Outgoing->map){ + assert(node->Outgoing->Children.size() == other->Outgoing->Children.size()); + for(unsigned i = 0; i < node->Outgoing->Children.size(); i++){ + Node *nc = node->Outgoing->Children[i]; + Node *oc = other->Outgoing->Children[i]; + if(!(nc == oc || oc->Outgoing->map ==0 || dominates(nc,oc))) + return false; + } + return true; + } + return false; + } - void Add(Node *node){ - std::vector &insts = insts_of_node(node->map); - for(unsigned i = 0; i < insts.size(); i++){ - Node *other = insts[i]; - if(Dominates(node,other)){ - cm[node].dominates.insert(other); - cm[other].dominated = true; - reporter()->Dominates(node, other); - } - } - } + void Add(Node *node){ + std::vector &insts = insts_of_node(node->map); + for(unsigned i = 0; i < insts.size(); i++){ + Node *other = insts[i]; + if(Dominates(node,other)){ + cm[node].dominates.insert(other); + cm[other].dominated = true; + reporter()->Dominates(node, other); + } + } + } - }; + }; - /* This expansion heuristic makes use of a previuosly obtained - counterexample as a guide. This is for use in abstraction - refinement schemes.*/ + /* This expansion heuristic makes use of a previuosly obtained + counterexample as a guide. This is for use in abstraction + refinement schemes.*/ - class ReplayHeuristic : public Heuristic { + class ReplayHeuristic : public Heuristic { - Counterexample old_cex; - public: - ReplayHeuristic(RPFP *_rpfp, Counterexample &_old_cex) - : Heuristic(_rpfp) - { - old_cex.swap(_old_cex); // take ownership from caller - } + Counterexample old_cex; + public: + ReplayHeuristic(RPFP *_rpfp, Counterexample &_old_cex) + : Heuristic(_rpfp) + { + old_cex.swap(_old_cex); // take ownership from caller + } - ~ReplayHeuristic(){ - } + ~ReplayHeuristic(){ + } - // Maps nodes of derivation tree into old cex - hash_map cex_map; + // Maps nodes of derivation tree into old cex + hash_map cex_map; - void Done() { - cex_map.clear(); - old_cex.clear(); - } + void Done() { + cex_map.clear(); + old_cex.clear(); + } - void ShowNodeAndChildren(Node *n){ - std::cout << n->Name.name() << ": "; - std::vector &chs = n->Outgoing->Children; - for(unsigned i = 0; i < chs.size(); i++) - std::cout << chs[i]->Name.name() << " " ; - std::cout << std::endl; - } + void ShowNodeAndChildren(Node *n){ + std::cout << n->Name.name() << ": "; + std::vector &chs = n->Outgoing->Children; + for(unsigned i = 0; i < chs.size(); i++) + std::cout << chs[i]->Name.name() << " " ; + std::cout << std::endl; + } - // HACK: When matching relation names, we drop suffixes used to - // make the names unique between runs. For compatibility - // with boggie, we drop suffixes beginning with @@ - std::string BaseName(const std::string &name){ - int pos = name.find("@@"); - if(pos >= 1) - return name.substr(0,pos); - return name; - } + // HACK: When matching relation names, we drop suffixes used to + // make the names unique between runs. For compatibility + // with boggie, we drop suffixes beginning with @@ + std::string BaseName(const std::string &name){ + int pos = name.find("@@"); + if(pos >= 1) + return name.substr(0,pos); + return name; + } - Node *MatchNode(Node *node){ - if(cex_map.find(node) == cex_map.end()){ // try to match an unmatched node - Node *parent = node->Incoming[0]->Parent; // assumes we are a tree! - if(cex_map.find(parent) == cex_map.end()) - throw "catastrophe in ReplayHeuristic::ChooseExpand"; - Node *old_parent = cex_map[parent]; - std::vector &chs = parent->Outgoing->Children; - if(old_parent && old_parent->Outgoing){ - std::vector &old_chs = old_parent->Outgoing->Children; - for(unsigned i = 0, j=0; i < chs.size(); i++){ - if(j < old_chs.size() && BaseName(chs[i]->Name.name().str()) == BaseName(old_chs[j]->Name.name().str())) - cex_map[chs[i]] = old_chs[j++]; - else { - std::cerr << "WARNING: duality: unmatched child: " << chs[i]->Name.name() << std::endl; - cex_map[chs[i]] = 0; - } - } - goto matching_done; - } - for(unsigned i = 0; i < chs.size(); i++) - cex_map[chs[i]] = 0; - } - matching_done: - return cex_map[node]; - } + Node *MatchNode(Node *node){ + if(cex_map.find(node) == cex_map.end()){ // try to match an unmatched node + Node *parent = node->Incoming[0]->Parent; // assumes we are a tree! + if(cex_map.find(parent) == cex_map.end()) + throw "catastrophe in ReplayHeuristic::ChooseExpand"; + Node *old_parent = cex_map[parent]; + std::vector &chs = parent->Outgoing->Children; + if(old_parent && old_parent->Outgoing){ + std::vector &old_chs = old_parent->Outgoing->Children; + for(unsigned i = 0, j=0; i < chs.size(); i++){ + if(j < old_chs.size() && BaseName(chs[i]->Name.name().str()) == BaseName(old_chs[j]->Name.name().str())) + cex_map[chs[i]] = old_chs[j++]; + else { + std::cerr << "WARNING: duality: unmatched child: " << chs[i]->Name.name() << std::endl; + cex_map[chs[i]] = 0; + } + } + goto matching_done; + } + for(unsigned i = 0; i < chs.size(); i++) + cex_map[chs[i]] = 0; + } + matching_done: + return cex_map[node]; + } - int UseNode(Node *node){ - if (!old_cex.get_tree()) - return 0; - Node *old_node = MatchNode(node); - if(!old_node) - return 0; - return old_cex.get_tree()->Empty(old_node) ? -1 : 1; - } + int UseNode(Node *node){ + if (!old_cex.get_tree()) + return 0; + Node *old_node = MatchNode(node); + if(!old_node) + return 0; + return old_cex.get_tree()->Empty(old_node) ? -1 : 1; + } - virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority, bool best_only){ - if(cex_map.empty()) - cex_map[*(choices.begin())] = old_cex.get_root(); // match the root nodes - if(!high_priority || !old_cex.get_tree()){ - Heuristic::ChooseExpand(choices,best,false); - return; - } - // first, try to match the derivatino tree nodes to the old cex - std::set matched, unmatched; - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ - Node *node = (*it); - Node *old_node = MatchNode(node); - if(!old_node) - unmatched.insert(node); - else if(old_cex.get_tree()->Empty(old_node)) - unmatched.insert(node); - else - matched.insert(node); - } - if (matched.empty() && !high_priority) - Heuristic::ChooseExpand(unmatched,best,false); - else - Heuristic::ChooseExpand(matched,best,false); - } - }; + virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority, bool best_only){ + if(cex_map.empty()) + cex_map[*(choices.begin())] = old_cex.get_root(); // match the root nodes + if(!high_priority || !old_cex.get_tree()){ + Heuristic::ChooseExpand(choices,best,false); + return; + } + // first, try to match the derivatino tree nodes to the old cex + std::set matched, unmatched; + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ + Node *node = (*it); + Node *old_node = MatchNode(node); + if(!old_node) + unmatched.insert(node); + else if(old_cex.get_tree()->Empty(old_node)) + unmatched.insert(node); + else + matched.insert(node); + } + if (matched.empty() && !high_priority) + Heuristic::ChooseExpand(unmatched,best,false); + else + Heuristic::ChooseExpand(matched,best,false); + } + }; - class LocalHeuristic : public Heuristic { + class LocalHeuristic : public Heuristic { - RPFP::Node *old_node; - public: - LocalHeuristic(RPFP *_rpfp) - : Heuristic(_rpfp) - { - old_node = 0; - } + RPFP::Node *old_node; + public: + LocalHeuristic(RPFP *_rpfp) + : Heuristic(_rpfp) + { + old_node = 0; + } - void SetOldNode(RPFP::Node *_old_node){ - old_node = _old_node; - cex_map.clear(); - } + void SetOldNode(RPFP::Node *_old_node){ + old_node = _old_node; + cex_map.clear(); + } - // Maps nodes of derivation tree into old subtree - hash_map cex_map; + // Maps nodes of derivation tree into old subtree + hash_map cex_map; - virtual void ChooseExpand(const std::set &choices, std::set &best){ - if(old_node == 0){ - Heuristic::ChooseExpand(choices,best); - return; - } - // first, try to match the derivatino tree nodes to the old cex - std::set matched, unmatched; - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ - Node *node = (*it); - if(cex_map.empty()) - cex_map[node] = old_node; // match the root nodes - if(cex_map.find(node) == cex_map.end()){ // try to match an unmatched node - Node *parent = node->Incoming[0]->Parent; // assumes we are a tree! - if(cex_map.find(parent) == cex_map.end()) - throw "catastrophe in ReplayHeuristic::ChooseExpand"; - Node *old_parent = cex_map[parent]; - std::vector &chs = parent->Outgoing->Children; - if(old_parent && old_parent->Outgoing){ - std::vector &old_chs = old_parent->Outgoing->Children; - if(chs.size() == old_chs.size()){ - for(unsigned i = 0; i < chs.size(); i++) - cex_map[chs[i]] = old_chs[i]; - goto matching_done; - } - else - std::cout << "derivation tree does not match old cex" << std::endl; - } - for(unsigned i = 0; i < chs.size(); i++) - cex_map[chs[i]] = 0; - } - matching_done: - Node *old_node = cex_map[node]; - if(!old_node) - unmatched.insert(node); - else if(old_node != node->map) - unmatched.insert(node); - else - matched.insert(node); - } - Heuristic::ChooseExpand(unmatched,best); - } - }; + virtual void ChooseExpand(const std::set &choices, std::set &best){ + if(old_node == 0){ + Heuristic::ChooseExpand(choices,best); + return; + } + // first, try to match the derivatino tree nodes to the old cex + std::set matched, unmatched; + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ + Node *node = (*it); + if(cex_map.empty()) + cex_map[node] = old_node; // match the root nodes + if(cex_map.find(node) == cex_map.end()){ // try to match an unmatched node + Node *parent = node->Incoming[0]->Parent; // assumes we are a tree! + if(cex_map.find(parent) == cex_map.end()) + throw "catastrophe in ReplayHeuristic::ChooseExpand"; + Node *old_parent = cex_map[parent]; + std::vector &chs = parent->Outgoing->Children; + if(old_parent && old_parent->Outgoing){ + std::vector &old_chs = old_parent->Outgoing->Children; + if(chs.size() == old_chs.size()){ + for(unsigned i = 0; i < chs.size(); i++) + cex_map[chs[i]] = old_chs[i]; + goto matching_done; + } + else + std::cout << "derivation tree does not match old cex" << std::endl; + } + for(unsigned i = 0; i < chs.size(); i++) + cex_map[chs[i]] = 0; + } + matching_done: + Node *old_node = cex_map[node]; + if(!old_node) + unmatched.insert(node); + else if(old_node != node->map) + unmatched.insert(node); + else + matched.insert(node); + } + Heuristic::ChooseExpand(unmatched,best); + } + }; - /** This proposer class generates conjectures based on the - unwinding generated by a previous solver. The assumption is - that the provious solver was working on a different - abstraction of the same system. The trick is to adapt the - annotations in the old unwinding to the new predicates. We - start by generating a map from predicates and parameters in - the old problem to the new. + /** This proposer class generates conjectures based on the + unwinding generated by a previous solver. The assumption is + that the provious solver was working on a different + abstraction of the same system. The trick is to adapt the + annotations in the old unwinding to the new predicates. We + start by generating a map from predicates and parameters in + the old problem to the new. - HACK: mapping is done by cheesy name comparison. - */ + HACK: mapping is done by cheesy name comparison. + */ - class HistoryProposer : public Proposer - { - Duality *old_solver; - Duality *new_solver; - hash_map > conjectures; + class HistoryProposer : public Proposer + { + Duality *old_solver; + Duality *new_solver; + hash_map > conjectures; - public: - /** Construct a history solver. */ - HistoryProposer(Duality *_old_solver, Duality *_new_solver) - : old_solver(_old_solver), new_solver(_new_solver) { + public: + /** Construct a history solver. */ + HistoryProposer(Duality *_old_solver, Duality *_new_solver) + : old_solver(_old_solver), new_solver(_new_solver) { - // tricky: names in the axioms may have changed -- map them - hash_set &old_constants = old_solver->unwinding->ls->get_constants(); - hash_set &new_constants = new_solver->rpfp->ls->get_constants(); - hash_map cmap; - for(hash_set::iterator it = new_constants.begin(), en = new_constants.end(); it != en; ++it) - cmap[GetKey(*it)] = *it; - hash_map bckg_map; - for(hash_set::iterator it = old_constants.begin(), en = old_constants.end(); it != en; ++it){ - func_decl f = new_solver->ctx.translate(*it); // move to new context - if(cmap.find(GetKey(f)) != cmap.end()) - bckg_map[f] = cmap[GetKey(f)]; - // else - // std::cout << "constant not matched\n"; - } + // tricky: names in the axioms may have changed -- map them + hash_set &old_constants = old_solver->unwinding->ls->get_constants(); + hash_set &new_constants = new_solver->rpfp->ls->get_constants(); + hash_map cmap; + for(hash_set::iterator it = new_constants.begin(), en = new_constants.end(); it != en; ++it) + cmap[GetKey(*it)] = *it; + hash_map bckg_map; + for(hash_set::iterator it = old_constants.begin(), en = old_constants.end(); it != en; ++it){ + func_decl f = new_solver->ctx.translate(*it); // move to new context + if(cmap.find(GetKey(f)) != cmap.end()) + bckg_map[f] = cmap[GetKey(f)]; + // else + // std::cout << "constant not matched\n"; + } - RPFP *old_unwinding = old_solver->unwinding; - hash_map > pred_match; + RPFP *old_unwinding = old_solver->unwinding; + hash_map > pred_match; - // index all the predicates in the old unwinding - for(unsigned i = 0; i < old_unwinding->nodes.size(); i++){ - Node *node = old_unwinding->nodes[i]; - std::string key = GetKey(node); - pred_match[key].push_back(node); - } + // index all the predicates in the old unwinding + for(unsigned i = 0; i < old_unwinding->nodes.size(); i++){ + Node *node = old_unwinding->nodes[i]; + std::string key = GetKey(node); + pred_match[key].push_back(node); + } - // match with predicates in the new RPFP - RPFP *rpfp = new_solver->rpfp; - for(unsigned i = 0; i < rpfp->nodes.size(); i++){ - Node *node = rpfp->nodes[i]; - std::string key = GetKey(node); - std::vector &matches = pred_match[key]; - for(unsigned j = 0; j < matches.size(); j++) - MatchNodes(node,matches[j],bckg_map); - } - } + // match with predicates in the new RPFP + RPFP *rpfp = new_solver->rpfp; + for(unsigned i = 0; i < rpfp->nodes.size(); i++){ + Node *node = rpfp->nodes[i]; + std::string key = GetKey(node); + std::vector &matches = pred_match[key]; + for(unsigned j = 0; j < matches.size(); j++) + MatchNodes(node,matches[j],bckg_map); + } + } - virtual std::vector &Propose(Node *node){ - return conjectures[node->map]; - } + virtual std::vector &Propose(Node *node){ + return conjectures[node->map]; + } - virtual ~HistoryProposer(){ - }; + virtual ~HistoryProposer(){ + }; - private: - void MatchNodes(Node *new_node, Node *old_node, hash_map &bckg_map){ - if(old_node->Annotation.IsFull()) - return; // don't conjecture true! - hash_map var_match; - std::vector &new_params = new_node->Annotation.IndParams; - // Index the new parameters by their keys - for(unsigned i = 0; i < new_params.size(); i++) - var_match[GetKey(new_params[i])] = new_params[i]; - RPFP::Transformer &old = old_node->Annotation; - std::vector from_params = old.IndParams; - for(unsigned j = 0; j < from_params.size(); j++) - from_params[j] = new_solver->ctx.translate(from_params[j]); // get in new context - std::vector to_params = from_params; - for(unsigned j = 0; j < to_params.size(); j++){ - std::string key = GetKey(to_params[j]); - if(var_match.find(key) == var_match.end()){ - // std::cout << "unmatched parameter!\n"; - return; - } - to_params[j] = var_match[key]; - } - expr fmla = new_solver->ctx.translate(old.Formula); // get in new context - fmla = new_solver->rpfp->SubstParams(old.IndParams,to_params,fmla); // substitute parameters - hash_map memo; - fmla = new_solver->rpfp->SubstRec(memo,bckg_map,fmla); // substitute background constants - RPFP::Transformer new_annot = new_node->Annotation; - new_annot.Formula = fmla; - conjectures[new_node].push_back(new_annot); - } + private: + void MatchNodes(Node *new_node, Node *old_node, hash_map &bckg_map){ + if(old_node->Annotation.IsFull()) + return; // don't conjecture true! + hash_map var_match; + std::vector &new_params = new_node->Annotation.IndParams; + // Index the new parameters by their keys + for(unsigned i = 0; i < new_params.size(); i++) + var_match[GetKey(new_params[i])] = new_params[i]; + RPFP::Transformer &old = old_node->Annotation; + std::vector from_params = old.IndParams; + for(unsigned j = 0; j < from_params.size(); j++) + from_params[j] = new_solver->ctx.translate(from_params[j]); // get in new context + std::vector to_params = from_params; + for(unsigned j = 0; j < to_params.size(); j++){ + std::string key = GetKey(to_params[j]); + if(var_match.find(key) == var_match.end()){ + // std::cout << "unmatched parameter!\n"; + return; + } + to_params[j] = var_match[key]; + } + expr fmla = new_solver->ctx.translate(old.Formula); // get in new context + fmla = new_solver->rpfp->SubstParams(old.IndParams,to_params,fmla); // substitute parameters + hash_map memo; + fmla = new_solver->rpfp->SubstRec(memo,bckg_map,fmla); // substitute background constants + RPFP::Transformer new_annot = new_node->Annotation; + new_annot.Formula = fmla; + conjectures[new_node].push_back(new_annot); + } - // We match names by removing suffixes beginning with double at sign + // We match names by removing suffixes beginning with double at sign - std::string GetKey(Node *node){ - return GetKey(node->Name); - } + std::string GetKey(Node *node){ + return GetKey(node->Name); + } - std::string GetKey(const expr &var){ - return GetKey(var.decl()); - } + std::string GetKey(const expr &var){ + return GetKey(var.decl()); + } - std::string GetKey(const func_decl &f){ - std::string name = f.name().str(); - int idx = name.find("@@"); - if(idx >= 0) - name.erase(idx); - return name; - } + std::string GetKey(const func_decl &f){ + std::string name = f.name().str(); + int idx = name.find("@@"); + if(idx >= 0) + name.erase(idx); + return name; + } + }; }; - }; - static int stop_event = -1; + static int stop_event = -1; - class StreamReporter : public Reporter { - std::ostream &s; - public: - StreamReporter(RPFP *_rpfp, std::ostream &_s) - : Reporter(_rpfp), s(_s) {event = 0; depth = -1;} - int event; - int depth; - void ev(){ - if(stop_event == event){ - std::cout << "stop!\n"; - } - s << "[" << event++ << "]" ; - } - virtual void Extend(RPFP::Node *node){ - ev(); s << "node " << node->number << ": " << node->Name.name(); - std::vector &rps = node->Outgoing->Children; - for(unsigned i = 0; i < rps.size(); i++) - s << " " << rps[i]->number; - s << std::endl; - } - virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){ - ev(); s << "update " << node->number << " " << node->Name.name() << ": "; - rpfp->Summarize(update.Formula); - if(depth > 0) s << " (depth=" << depth << ")"; - if(eager) s << " (eager)"; - s << std::endl; - } - virtual void Bound(RPFP::Node *node){ - ev(); s << "check " << node->number << std::endl; - } - virtual void Expand(RPFP::Edge *edge){ - RPFP::Node *node = edge->Parent; - ev(); s << "expand " << node->map->number << " " << node->Name.name(); - if(depth > 0) s << " (depth=" << depth << ")"; - s << std::endl; - } - virtual void Depth(int d){ - depth = d; - } - virtual void AddCover(RPFP::Node *covered, std::vector &covering){ - ev(); s << "cover " << covered->Name.name() << ": " << covered->number << " by "; - for(unsigned i = 0; i < covering.size(); i++) - s << covering[i]->number << " "; - s << std::endl; - } - virtual void RemoveCover(RPFP::Node *covered, RPFP::Node *covering){ - ev(); s << "uncover " << covered->Name.name() << ": " << covered->number << " by " << covering->number << std::endl; - } - virtual void Forcing(RPFP::Node *covered, RPFP::Node *covering){ - ev(); s << "forcing " << covered->Name.name() << ": " << covered->number << " by " << covering->number << std::endl; - } - virtual void Conjecture(RPFP::Node *node, const RPFP::Transformer &t){ - ev(); s << "conjecture " << node->number << " " << node->Name.name() << ": "; - rpfp->Summarize(t.Formula); - s << std::endl; - } - virtual void Dominates(RPFP::Node *node, RPFP::Node *other){ - ev(); s << "dominates " << node->Name.name() << ": " << node->number << " > " << other->number << std::endl; - } - virtual void InductionFailure(RPFP::Edge *edge, const std::vector &children){ - ev(); s << "induction failure: " << edge->Parent->Name.name() << ", children ="; - for(unsigned i = 0; i < children.size(); i++) - s << " " << children[i]->number; - s << std::endl; - } - virtual void UpdateUnderapprox(RPFP::Node *node, const RPFP::Transformer &update){ - ev(); s << "underapprox " << node->number << " " << node->Name.name() << ": " << update.Formula << std::endl; - } - virtual void Reject(RPFP::Edge *edge, const std::vector &children){ - ev(); s << "reject " << edge->Parent->number << " " << edge->Parent->Name.name() << ": "; - for(unsigned i = 0; i < children.size(); i++) - s << " " << children[i]->number; - s << std::endl; - } - virtual void Message(const std::string &msg){ - ev(); s << "msg " << msg << std::endl; - } + class StreamReporter : public Reporter { + std::ostream &s; + public: + StreamReporter(RPFP *_rpfp, std::ostream &_s) + : Reporter(_rpfp), s(_s) {event = 0; depth = -1;} + int event; + int depth; + void ev(){ + if(stop_event == event){ + std::cout << "stop!\n"; + } + s << "[" << event++ << "]" ; + } + virtual void Extend(RPFP::Node *node){ + ev(); s << "node " << node->number << ": " << node->Name.name(); + std::vector &rps = node->Outgoing->Children; + for(unsigned i = 0; i < rps.size(); i++) + s << " " << rps[i]->number; + s << std::endl; + } + virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){ + ev(); s << "update " << node->number << " " << node->Name.name() << ": "; + rpfp->Summarize(update.Formula); + if(depth > 0) s << " (depth=" << depth << ")"; + if(eager) s << " (eager)"; + s << std::endl; + } + virtual void Bound(RPFP::Node *node){ + ev(); s << "check " << node->number << std::endl; + } + virtual void Expand(RPFP::Edge *edge){ + RPFP::Node *node = edge->Parent; + ev(); s << "expand " << node->map->number << " " << node->Name.name(); + if(depth > 0) s << " (depth=" << depth << ")"; + s << std::endl; + } + virtual void Depth(int d){ + depth = d; + } + virtual void AddCover(RPFP::Node *covered, std::vector &covering){ + ev(); s << "cover " << covered->Name.name() << ": " << covered->number << " by "; + for(unsigned i = 0; i < covering.size(); i++) + s << covering[i]->number << " "; + s << std::endl; + } + virtual void RemoveCover(RPFP::Node *covered, RPFP::Node *covering){ + ev(); s << "uncover " << covered->Name.name() << ": " << covered->number << " by " << covering->number << std::endl; + } + virtual void Forcing(RPFP::Node *covered, RPFP::Node *covering){ + ev(); s << "forcing " << covered->Name.name() << ": " << covered->number << " by " << covering->number << std::endl; + } + virtual void Conjecture(RPFP::Node *node, const RPFP::Transformer &t){ + ev(); s << "conjecture " << node->number << " " << node->Name.name() << ": "; + rpfp->Summarize(t.Formula); + s << std::endl; + } + virtual void Dominates(RPFP::Node *node, RPFP::Node *other){ + ev(); s << "dominates " << node->Name.name() << ": " << node->number << " > " << other->number << std::endl; + } + virtual void InductionFailure(RPFP::Edge *edge, const std::vector &children){ + ev(); s << "induction failure: " << edge->Parent->Name.name() << ", children ="; + for(unsigned i = 0; i < children.size(); i++) + s << " " << children[i]->number; + s << std::endl; + } + virtual void UpdateUnderapprox(RPFP::Node *node, const RPFP::Transformer &update){ + ev(); s << "underapprox " << node->number << " " << node->Name.name() << ": " << update.Formula << std::endl; + } + virtual void Reject(RPFP::Edge *edge, const std::vector &children){ + ev(); s << "reject " << edge->Parent->number << " " << edge->Parent->Name.name() << ": "; + for(unsigned i = 0; i < children.size(); i++) + s << " " << children[i]->number; + s << std::endl; + } + virtual void Message(const std::string &msg){ + ev(); s << "msg " << msg << std::endl; + } - }; + }; - class DualityDepthBounded : public Solver { + class DualityDepthBounded : public Solver { - Duality *duality; - context &ctx; // Z3 context - solver &slvr; // Z3 solver + Duality *duality; + context &ctx; // Z3 context + solver &slvr; // Z3 solver - public: - DualityDepthBounded(RPFP *_rpfp) : - ctx(_rpfp->ctx), - slvr(_rpfp->slvr()){ - rpfp = _rpfp; - DepthBoundRPFP(); - duality = alloc(Duality,drpfp); - } + public: + DualityDepthBounded(RPFP *_rpfp) : + ctx(_rpfp->ctx), + slvr(_rpfp->slvr()){ + rpfp = _rpfp; + DepthBoundRPFP(); + duality = alloc(Duality,drpfp); + } - ~DualityDepthBounded(){ - dealloc(duality); - delete drpfp; - } + ~DualityDepthBounded(){ + dealloc(duality); + delete drpfp; + } - bool Solve(){ - int depth_bound = 10; - bool res; - SetMaxDepthRPFP(depth_bound); - duality->PreSolve(); - while(true){ - res = duality->SolveMain(); - if(!res || GetSolution()) - break; - depth_bound++; - SetMaxDepthRPFP(depth_bound); - res = duality->RecheckBounds(); - if(!res) - break; - } - duality->PostSolve(); - if(!res) - ConvertCex(); - return res; - } + bool Solve(){ + int depth_bound = 10; + bool res; + SetMaxDepthRPFP(depth_bound); + duality->PreSolve(); + while(true){ + res = duality->SolveMain(); + if(!res || GetSolution()) + break; + depth_bound++; + SetMaxDepthRPFP(depth_bound); + res = duality->RecheckBounds(); + if(!res) + break; + } + duality->PostSolve(); + if(!res) + ConvertCex(); + return res; + } - Counterexample &GetCounterexample(){ - return cex; - } + Counterexample &GetCounterexample(){ + return cex; + } - bool SetOption(const std::string &option, const std::string &value){ - return duality->SetOption(option,value); - } + bool SetOption(const std::string &option, const std::string &value){ + return duality->SetOption(option,value); + } - virtual void LearnFrom(Solver *old_solver){ - DualityDepthBounded *old = dynamic_cast(old_solver); - if(old){ - duality->LearnFrom(old->duality); - } - } + virtual void LearnFrom(Solver *old_solver){ + DualityDepthBounded *old = dynamic_cast(old_solver); + if(old){ + duality->LearnFrom(old->duality); + } + } - bool IsResultRecursionBounded(){ - return duality->IsResultRecursionBounded(); - } + bool IsResultRecursionBounded(){ + return duality->IsResultRecursionBounded(); + } - void Cancel(){ - duality->Cancel(); - } + void Cancel(){ + duality->Cancel(); + } - typedef RPFP::Node Node; - typedef RPFP::Edge Edge; - RPFP *rpfp, *drpfp; - hash_map db_map, db_rev_map; - hash_map db_edge_rev_map; - std::vector db_saved_bounds; - Counterexample cex; + typedef RPFP::Node Node; + typedef RPFP::Edge Edge; + RPFP *rpfp, *drpfp; + hash_map db_map, db_rev_map; + hash_map db_edge_rev_map; + std::vector db_saved_bounds; + Counterexample cex; - expr AddParamToRels(hash_map &memo, hash_map &rmap, const expr &p, const expr &t) { - std::pair foo(t,expr(ctx)); - std::pair::iterator, bool> bar = memo.insert(foo); - expr &res = bar.first->second; - if(!bar.second) return res; + expr AddParamToRels(hash_map &memo, hash_map &rmap, const expr &p, const expr &t) { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + expr &res = bar.first->second; + if(!bar.second) return res; - if (t.is_app()) - { - func_decl f = t.decl(); - std::vector args; - int nargs = t.num_args(); - for(int i = 0; i < nargs; i++) - args.push_back(AddParamToRels(memo, rmap, p, t.arg(i))); - hash_map::iterator rit = rmap.find(f); - if(rit != rmap.end()){ - args.push_back(p); - res = (rit->second)(args); - res = ctx.make(And,res,ctx.make(Geq,p,ctx.int_val(0))); - } - else - res = f(args); - } - else if (t.is_quantifier()) - { - expr body = AddParamToRels(memo, rmap, p, t.body()); - res = clone_quantifier(t, body); - } - else res = t; - return res; - } + if (t.is_app()) + { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + args.push_back(AddParamToRels(memo, rmap, p, t.arg(i))); + hash_map::iterator rit = rmap.find(f); + if(rit != rmap.end()){ + args.push_back(p); + res = (rit->second)(args); + res = ctx.make(And,res,ctx.make(Geq,p,ctx.int_val(0))); + } + else + res = f(args); + } + else if (t.is_quantifier()) + { + expr body = AddParamToRels(memo, rmap, p, t.body()); + res = clone_quantifier(t, body); + } + else res = t; + return res; + } - void DepthBoundRPFP(){ - drpfp = new RPFP(rpfp->ls); - expr dvar = ctx.int_const("@depth"); - expr dmax = ctx.int_const("@depth_max"); - for(unsigned i = 0; i < rpfp->nodes.size(); i++){ - Node *node = rpfp->nodes[i]; - std::vector arg_sorts; - const std::vector ¶ms = node->Annotation.IndParams; - for(unsigned j = 0; j < params.size(); j++) - arg_sorts.push_back(params[j].get_sort()); - arg_sorts.push_back(ctx.int_sort()); - std::string new_name = std::string("@db@") + node->Name.name().str(); - func_decl f = ctx.function(new_name.c_str(),arg_sorts.size(), &arg_sorts[0],ctx.bool_sort()); - std::vector args = params; - args.push_back(dvar); - expr pat = f(args); - Node *dnode = drpfp->CreateNode(pat); - db_map[node] = dnode; - db_rev_map[dnode] = node; - expr bound_fmla = node->Bound.Formula; - if(!eq(bound_fmla,ctx.bool_val(true))){ - bound_fmla = implies(dvar == dmax,bound_fmla); - dnode->Bound.Formula = bound_fmla; - } - db_saved_bounds.push_back(bound_fmla); - // dnode->Annotation.Formula = ctx.make(And,node->Annotation.Formula,ctx.make(Geq,dvar,ctx.int_val(0))); - } - for(unsigned i = 0; i < rpfp->edges.size(); i++){ - Edge *edge = rpfp->edges[i]; - std::vector new_children; - std::vector new_relparams; - hash_map rmap; - for(unsigned j = 0; j < edge->Children.size(); j++){ - Node *ch = edge->Children[j]; - Node *nch = db_map[ch]; - func_decl f = nch->Name; - func_decl sf = drpfp->NumberPred(f,j); - new_children.push_back(nch); - new_relparams.push_back(sf); - rmap[edge->F.RelParams[j]] = sf; - } - std::vector new_indparams = edge->F.IndParams; - new_indparams.push_back(dvar); - hash_map memo; - expr new_fmla = AddParamToRels(memo,rmap,ctx.make(Sub,dvar,ctx.int_val(1)),edge->F.Formula); - RPFP::Transformer new_t = drpfp->CreateTransformer(new_relparams,new_indparams,new_fmla); - Node *new_parent = db_map[edge->Parent]; - db_edge_rev_map[drpfp->CreateEdge(new_parent,new_t,new_children)] = edge; - } - } + void DepthBoundRPFP(){ + drpfp = new RPFP(rpfp->ls); + expr dvar = ctx.int_const("@depth"); + expr dmax = ctx.int_const("@depth_max"); + for(unsigned i = 0; i < rpfp->nodes.size(); i++){ + Node *node = rpfp->nodes[i]; + std::vector arg_sorts; + const std::vector ¶ms = node->Annotation.IndParams; + for(unsigned j = 0; j < params.size(); j++) + arg_sorts.push_back(params[j].get_sort()); + arg_sorts.push_back(ctx.int_sort()); + std::string new_name = std::string("@db@") + node->Name.name().str(); + func_decl f = ctx.function(new_name.c_str(),arg_sorts.size(), &arg_sorts[0],ctx.bool_sort()); + std::vector args = params; + args.push_back(dvar); + expr pat = f(args); + Node *dnode = drpfp->CreateNode(pat); + db_map[node] = dnode; + db_rev_map[dnode] = node; + expr bound_fmla = node->Bound.Formula; + if(!eq(bound_fmla,ctx.bool_val(true))){ + bound_fmla = implies(dvar == dmax,bound_fmla); + dnode->Bound.Formula = bound_fmla; + } + db_saved_bounds.push_back(bound_fmla); + // dnode->Annotation.Formula = ctx.make(And,node->Annotation.Formula,ctx.make(Geq,dvar,ctx.int_val(0))); + } + for(unsigned i = 0; i < rpfp->edges.size(); i++){ + Edge *edge = rpfp->edges[i]; + std::vector new_children; + std::vector new_relparams; + hash_map rmap; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *ch = edge->Children[j]; + Node *nch = db_map[ch]; + func_decl f = nch->Name; + func_decl sf = drpfp->NumberPred(f,j); + new_children.push_back(nch); + new_relparams.push_back(sf); + rmap[edge->F.RelParams[j]] = sf; + } + std::vector new_indparams = edge->F.IndParams; + new_indparams.push_back(dvar); + hash_map memo; + expr new_fmla = AddParamToRels(memo,rmap,ctx.make(Sub,dvar,ctx.int_val(1)),edge->F.Formula); + RPFP::Transformer new_t = drpfp->CreateTransformer(new_relparams,new_indparams,new_fmla); + Node *new_parent = db_map[edge->Parent]; + db_edge_rev_map[drpfp->CreateEdge(new_parent,new_t,new_children)] = edge; + } + } - void SetMaxDepthRPFP(int depth){ - hash_map subst; - expr dmax = ctx.int_const("@depth_max"); - subst[dmax] = ctx.int_val(depth); - for(unsigned i = 0; i < drpfp->nodes.size(); i++){ - Node *node = drpfp->nodes[i]; - expr fmla = db_saved_bounds[i]; - fmla = drpfp->SubstRec(subst,fmla); - node->Bound.Formula = fmla; - } - } + void SetMaxDepthRPFP(int depth){ + hash_map subst; + expr dmax = ctx.int_const("@depth_max"); + subst[dmax] = ctx.int_val(depth); + for(unsigned i = 0; i < drpfp->nodes.size(); i++){ + Node *node = drpfp->nodes[i]; + expr fmla = db_saved_bounds[i]; + fmla = drpfp->SubstRec(subst,fmla); + node->Bound.Formula = fmla; + } + } - void ConvertCex(){ - cex.clear(); - RPFP *tree = new RPFP(rpfp->ls); - Node *root; - Counterexample &dctx = duality->GetCounterexample(); - hash_map ctx_node_map; - for(unsigned i = 0; i < dctx.get_tree()->nodes.size(); i++){ - Node *dnode = dctx.get_tree()->nodes[i]; - Node *onode = db_rev_map[dnode->map->map]; - Node *node = tree->CloneNode(onode); - node->number = dnode->number; // numbers have to match for model to make sense - ctx_node_map[dnode] = node; - if(dnode == dctx.get_root()) - root = node; - } - for(unsigned i = 0; i < dctx.get_tree()->edges.size(); i++){ - Edge *dedge = dctx.get_tree()->edges[i]; - Edge *oedge = db_edge_rev_map[dedge->map]; - Node *parent = ctx_node_map[dedge->Parent]; - std::vector chs; - for(unsigned j = 0; j < dedge->Children.size(); j++) - chs.push_back(ctx_node_map[dedge->Children[j]]); - Edge *edge = tree->CreateEdge(parent,oedge->F,chs); - edge->number = dedge->number; // numbers have to match for model to make sense - edge->map = oedge; - } - tree->dualModel = dctx.get_tree()->dualModel; - cex.set(tree,root); - } + void ConvertCex(){ + cex.clear(); + RPFP *tree = new RPFP(rpfp->ls); + Node *root; + Counterexample &dctx = duality->GetCounterexample(); + hash_map ctx_node_map; + for(unsigned i = 0; i < dctx.get_tree()->nodes.size(); i++){ + Node *dnode = dctx.get_tree()->nodes[i]; + Node *onode = db_rev_map[dnode->map->map]; + Node *node = tree->CloneNode(onode); + node->number = dnode->number; // numbers have to match for model to make sense + ctx_node_map[dnode] = node; + if(dnode == dctx.get_root()) + root = node; + } + for(unsigned i = 0; i < dctx.get_tree()->edges.size(); i++){ + Edge *dedge = dctx.get_tree()->edges[i]; + Edge *oedge = db_edge_rev_map[dedge->map]; + Node *parent = ctx_node_map[dedge->Parent]; + std::vector chs; + for(unsigned j = 0; j < dedge->Children.size(); j++) + chs.push_back(ctx_node_map[dedge->Children[j]]); + Edge *edge = tree->CreateEdge(parent,oedge->F,chs); + edge->number = dedge->number; // numbers have to match for model to make sense + edge->map = oedge; + } + tree->dualModel = dctx.get_tree()->dualModel; + cex.set(tree,root); + } - bool GetSolution(){ - for(unsigned i = 0; i < rpfp->nodes.size(); i++) - if(!drpfp->nodes[i]->Annotation.SubsetEq(rpfp->nodes[i]->Bound)) - return false; - expr dvar = ctx.int_const("@depth"); - hash_map subst; - subst[dvar] = ctx.int_val(INT_MAX); - for(unsigned i = 0; i < rpfp->nodes.size(); i++){ - expr fmla = drpfp->nodes[i]->Annotation.Formula; - fmla = drpfp->SubstRec(subst,fmla); - fmla = fmla.simplify(); - rpfp->nodes[i]->Annotation.Formula = fmla; - } - return true; - } + bool GetSolution(){ + for(unsigned i = 0; i < rpfp->nodes.size(); i++) + if(!drpfp->nodes[i]->Annotation.SubsetEq(rpfp->nodes[i]->Bound)) + return false; + expr dvar = ctx.int_const("@depth"); + hash_map subst; + subst[dvar] = ctx.int_val(INT_MAX); + for(unsigned i = 0; i < rpfp->nodes.size(); i++){ + expr fmla = drpfp->nodes[i]->Annotation.Formula; + fmla = drpfp->SubstRec(subst,fmla); + fmla = fmla.simplify(); + rpfp->nodes[i]->Annotation.Formula = fmla; + } + return true; + } - void UndoDepthBoundRPFP(){ + void UndoDepthBoundRPFP(){ #if 0 - if(cex.get_tree()){ - // here, need to map the cex back... - } - // also need to map the proof back, but we don't... + if(cex.get_tree()){ + // here, need to map the cex back... + } + // also need to map the proof back, but we don't... #endif + } + }; + + Solver *Solver::Create(const std::string &solver_class, RPFP *rpfp){ + // Solver *s = alloc(DualityDepthBounded,rpfp); + Solver *s = alloc(Duality,rpfp); + return s; } - }; - Solver *Solver::Create(const std::string &solver_class, RPFP *rpfp){ - // Solver *s = alloc(DualityDepthBounded,rpfp); - Solver *s = alloc(Duality,rpfp); - return s; - } - - Reporter *CreateStdoutReporter(RPFP *rpfp){ - return new StreamReporter(rpfp, std::cout); - } - - class ConjectureFileReporter : public Reporter { - std::ofstream s; - public: - ConjectureFileReporter(RPFP *_rpfp, const std::string &fname) - : Reporter(_rpfp), s(fname.c_str()) {} - virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){ - s << "(define-fun " << node->Name.name() << " ("; - for(unsigned i = 0; i < update.IndParams.size(); i++){ - if(i != 0) - s << " "; - s << "(" << update.IndParams[i] << " " << update.IndParams[i].get_sort() << ")"; - } - s << ") Bool \n"; - s << update.Formula << ")\n"; - s << std::endl; + Reporter *CreateStdoutReporter(RPFP *rpfp){ + return new StreamReporter(rpfp, std::cout); } - }; - Reporter *CreateConjectureFileReporter(RPFP *rpfp, const std::string &fname){ - return new ConjectureFileReporter(rpfp, fname); - } + class ConjectureFileReporter : public Reporter { + std::ofstream s; + public: + ConjectureFileReporter(RPFP *_rpfp, const std::string &fname) + : Reporter(_rpfp), s(fname.c_str()) {} + virtual void Update(RPFP::Node *node, const RPFP::Transformer &update, bool eager){ + s << "(define-fun " << node->Name.name() << " ("; + for(unsigned i = 0; i < update.IndParams.size(); i++){ + if(i != 0) + s << " "; + s << "(" << update.IndParams[i] << " " << update.IndParams[i].get_sort() << ")"; + } + s << ") Bool \n"; + s << update.Formula << ")\n"; + s << std::endl; + } + }; + + Reporter *CreateConjectureFileReporter(RPFP *rpfp, const std::string &fname){ + return new ConjectureFileReporter(rpfp, fname); + } } diff --git a/src/duality/duality_wrapper.cpp b/src/duality/duality_wrapper.cpp index 604192ebc..0cb5df056 100755 --- a/src/duality/duality_wrapper.cpp +++ b/src/duality/duality_wrapper.cpp @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2012 Microsoft Corporation + Copyright (c) 2012 Microsoft Corporation -Module Name: + Module Name: - wrapper.cpp + wrapper.cpp -Abstract: + Abstract: - wrap various objects in the style expected by duality + wrap various objects in the style expected by duality -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -37,699 +37,699 @@ Revision History: namespace Duality { - solver::solver(Duality::context& c, bool _extensional, bool models) : object(c), the_model(c) { - params_ref p; - p.set_bool("proof", true); // this is currently useless - if(models) - p.set_bool("model", true); - p.set_bool("unsat_core", true); - bool mbqi = c.get_config().get().get_bool("mbqi",true); - p.set_bool("mbqi",mbqi); // just to test - p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants - p.set_uint("mbqi.max_iterations",1); // use mbqi for quantifiers in interpolants - extensional = mbqi && (true || _extensional); - if(extensional) - p.set_bool("array.extensional",true); - scoped_ptr sf = mk_smt_solver_factory(); - m_solver = (*sf)(m(), p, true, true, true, ::symbol::null); - m_solver->updt_params(p); // why do we have to do this? - canceled = false; - m_mode = m().proof_mode(); - } - -expr context::constant(const std::string &name, const sort &ty){ - symbol s = str_symbol(name.c_str()); - return cook(m().mk_const(m().mk_const_decl(s, ty))); -} - -expr context::make(decl_kind op, int n, ::expr **args){ - switch(op) { - case True: return mki(m_basic_fid,OP_TRUE,n,args); - case False: return mki(m_basic_fid,OP_FALSE,n,args); - case Equal: return mki(m_basic_fid,OP_EQ,n,args); - case Distinct: return mki(m_basic_fid,OP_DISTINCT,n,args); - case Ite: return mki(m_basic_fid,OP_ITE,n,args); - case And: return mki(m_basic_fid,OP_AND,n,args); - case Or: return mki(m_basic_fid,OP_OR,n,args); - case Iff: return mki(m_basic_fid,OP_IFF,n,args); - case Xor: return mki(m_basic_fid,OP_XOR,n,args); - case Not: return mki(m_basic_fid,OP_NOT,n,args); - case Implies: return mki(m_basic_fid,OP_IMPLIES,n,args); - case Oeq: return mki(m_basic_fid,OP_OEQ,n,args); - case Interp: return mki(m_basic_fid,OP_INTERP,n,args); - case Leq: return mki(m_arith_fid,OP_LE,n,args); - case Geq: return mki(m_arith_fid,OP_GE,n,args); - case Lt: return mki(m_arith_fid,OP_LT,n,args); - case Gt: return mki(m_arith_fid,OP_GT,n,args); - case Plus: return mki(m_arith_fid,OP_ADD,n,args); - case Sub: return mki(m_arith_fid,OP_SUB,n,args); - case Uminus: return mki(m_arith_fid,OP_UMINUS,n,args); - case Times: return mki(m_arith_fid,OP_MUL,n,args); - case Div: return mki(m_arith_fid,OP_DIV,n,args); - case Idiv: return mki(m_arith_fid,OP_IDIV,n,args); - case Rem: return mki(m_arith_fid,OP_REM,n,args); - case Mod: return mki(m_arith_fid,OP_MOD,n,args); - case Power: return mki(m_arith_fid,OP_POWER,n,args); - case ToReal: return mki(m_arith_fid,OP_TO_REAL,n,args); - case ToInt: return mki(m_arith_fid,OP_TO_INT,n,args); - case IsInt: return mki(m_arith_fid,OP_IS_INT,n,args); - case Store: return mki(m_array_fid,OP_STORE,n,args); - case Select: return mki(m_array_fid,OP_SELECT,n,args); - case ConstArray: return mki(m_array_fid,OP_CONST_ARRAY,n,args); - case ArrayDefault: return mki(m_array_fid,OP_ARRAY_DEFAULT,n,args); - case ArrayMap: return mki(m_array_fid,OP_ARRAY_MAP,n,args); - case SetUnion: return mki(m_array_fid,OP_SET_UNION,n,args); - case SetIntersect: return mki(m_array_fid,OP_SET_INTERSECT,n,args); - case SetDifference: return mki(m_array_fid,OP_SET_DIFFERENCE,n,args); - case SetComplement: return mki(m_array_fid,OP_SET_COMPLEMENT,n,args); - case SetSubSet: return mki(m_array_fid,OP_SET_SUBSET,n,args); - case AsArray: return mki(m_array_fid,OP_AS_ARRAY,n,args); - default: - assert(0); - return expr(*this); - } -} - - expr context::mki(family_id fid, ::decl_kind dk, int n, ::expr **args){ - return cook(m().mk_app(fid, dk, 0, 0, n, (::expr **)args)); -} - -expr context::make(decl_kind op, const std::vector &args){ - static std::vector< ::expr*> a(10); - if(a.size() < args.size()) - a.resize(args.size()); - for(unsigned i = 0; i < args.size(); i++) - a[i] = to_expr(args[i].raw()); - return make(op,args.size(), args.size() ? &a[0] : 0); -} - -expr context::make(decl_kind op){ - return make(op,0,0); -} - -expr context::make(decl_kind op, const expr &arg0){ - ::expr *a = to_expr(arg0.raw()); - return make(op,1,&a); -} - -expr context::make(decl_kind op, const expr &arg0, const expr &arg1){ - ::expr *args[2]; - args[0] = to_expr(arg0.raw()); - args[1] = to_expr(arg1.raw()); - return make(op,2,args); -} - -expr context::make(decl_kind op, const expr &arg0, const expr &arg1, const expr &arg2){ - ::expr *args[3]; - args[0] = to_expr(arg0.raw()); - args[1] = to_expr(arg1.raw()); - args[2] = to_expr(arg2.raw()); - return make(op,3,args); -} - -expr context::make_quant(decl_kind op, const std::vector &bvs, const expr &body){ - if(bvs.size() == 0) return body; - std::vector< ::expr *> foo(bvs.size()); - - - std::vector< ::symbol> names; - std::vector< ::sort *> types; - std::vector< ::expr *> bound_asts; - unsigned num_bound = bvs.size(); - - for (unsigned i = 0; i < num_bound; ++i) { - app* a = to_app(bvs[i].raw()); - ::symbol s(to_app(a)->get_decl()->get_name()); - names.push_back(s); - types.push_back(m().get_sort(a)); - bound_asts.push_back(a); - } - expr_ref abs_body(m()); - expr_abstract(m(), 0, num_bound, &bound_asts[0], to_expr(body.raw()), abs_body); - expr_ref result(m()); - result = m().mk_quantifier( - op == Forall, - names.size(), &types[0], &names[0], abs_body.get(), - 0, - ::symbol(), - ::symbol(), - 0, 0, - 0, 0 - ); - return cook(result.get()); -} - -expr context::make_quant(decl_kind op, const std::vector &_sorts, const std::vector &_names, const expr &body){ - if(_sorts.size() == 0) return body; - - - std::vector< ::symbol> names; - std::vector< ::sort *> types; - std::vector< ::expr *> bound_asts; - unsigned num_bound = _sorts.size(); - - for (unsigned i = 0; i < num_bound; ++i) { - names.push_back(_names[i]); - types.push_back(to_sort(_sorts[i].raw())); - } - expr_ref result(m()); - result = m().mk_quantifier( - op == Forall, - names.size(), &types[0], &names[0], to_expr(body.raw()), - 0, - ::symbol(), - ::symbol(), - 0, 0, - 0, 0 - ); - return cook(result.get()); -} - - - decl_kind func_decl::get_decl_kind() const { - return ctx().get_decl_kind(*this); - } - - decl_kind context::get_decl_kind(const func_decl &t){ - ::func_decl *d = to_func_decl(t.raw()); - if (null_family_id == d->get_family_id()) - return Uninterpreted; - // return (opr)d->get_decl_kind(); - if (m_basic_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_TRUE: return True; - case OP_FALSE: return False; - case OP_EQ: return Equal; - case OP_DISTINCT: return Distinct; - case OP_ITE: return Ite; - case OP_AND: return And; - case OP_OR: return Or; - case OP_IFF: return Iff; - case OP_XOR: return Xor; - case OP_NOT: return Not; - case OP_IMPLIES: return Implies; - case OP_OEQ: return Oeq; - case OP_INTERP: return Interp; - default: - return OtherBasic; - } + solver::solver(Duality::context& c, bool _extensional, bool models) : object(c), the_model(c) { + params_ref p; + p.set_bool("proof", true); // this is currently useless + if(models) + p.set_bool("model", true); + p.set_bool("unsat_core", true); + bool mbqi = c.get_config().get().get_bool("mbqi",true); + p.set_bool("mbqi",mbqi); // just to test + p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants + p.set_uint("mbqi.max_iterations",1); // use mbqi for quantifiers in interpolants + extensional = mbqi && (true || _extensional); + if(extensional) + p.set_bool("array.extensional",true); + scoped_ptr sf = mk_smt_solver_factory(); + m_solver = (*sf)(m(), p, true, true, true, ::symbol::null); + m_solver->updt_params(p); // why do we have to do this? + canceled = false; + m_mode = m().proof_mode(); } - if (m_arith_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_LE: return Leq; - case OP_GE: return Geq; - case OP_LT: return Lt; - case OP_GT: return Gt; - case OP_ADD: return Plus; - case OP_SUB: return Sub; - case OP_UMINUS: return Uminus; - case OP_MUL: return Times; - case OP_DIV: return Div; - case OP_IDIV: return Idiv; - case OP_REM: return Rem; - case OP_MOD: return Mod; - case OP_POWER: return Power; - case OP_TO_REAL: return ToReal; - case OP_TO_INT: return ToInt; - case OP_IS_INT: return IsInt; - default: - return OtherArith; - } + + expr context::constant(const std::string &name, const sort &ty){ + symbol s = str_symbol(name.c_str()); + return cook(m().mk_const(m().mk_const_decl(s, ty))); } - if (m_array_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_STORE: return Store; - case OP_SELECT: return Select; - case OP_CONST_ARRAY: return ConstArray; - case OP_ARRAY_DEFAULT: return ArrayDefault; - case OP_ARRAY_MAP: return ArrayMap; - case OP_SET_UNION: return SetUnion; - case OP_SET_INTERSECT: return SetIntersect; - case OP_SET_DIFFERENCE: return SetDifference; - case OP_SET_COMPLEMENT: return SetComplement; - case OP_SET_SUBSET: return SetSubSet; - case OP_AS_ARRAY: return AsArray; - default: - return OtherArray; - } + + expr context::make(decl_kind op, int n, ::expr **args){ + switch(op) { + case True: return mki(m_basic_fid,OP_TRUE,n,args); + case False: return mki(m_basic_fid,OP_FALSE,n,args); + case Equal: return mki(m_basic_fid,OP_EQ,n,args); + case Distinct: return mki(m_basic_fid,OP_DISTINCT,n,args); + case Ite: return mki(m_basic_fid,OP_ITE,n,args); + case And: return mki(m_basic_fid,OP_AND,n,args); + case Or: return mki(m_basic_fid,OP_OR,n,args); + case Iff: return mki(m_basic_fid,OP_IFF,n,args); + case Xor: return mki(m_basic_fid,OP_XOR,n,args); + case Not: return mki(m_basic_fid,OP_NOT,n,args); + case Implies: return mki(m_basic_fid,OP_IMPLIES,n,args); + case Oeq: return mki(m_basic_fid,OP_OEQ,n,args); + case Interp: return mki(m_basic_fid,OP_INTERP,n,args); + case Leq: return mki(m_arith_fid,OP_LE,n,args); + case Geq: return mki(m_arith_fid,OP_GE,n,args); + case Lt: return mki(m_arith_fid,OP_LT,n,args); + case Gt: return mki(m_arith_fid,OP_GT,n,args); + case Plus: return mki(m_arith_fid,OP_ADD,n,args); + case Sub: return mki(m_arith_fid,OP_SUB,n,args); + case Uminus: return mki(m_arith_fid,OP_UMINUS,n,args); + case Times: return mki(m_arith_fid,OP_MUL,n,args); + case Div: return mki(m_arith_fid,OP_DIV,n,args); + case Idiv: return mki(m_arith_fid,OP_IDIV,n,args); + case Rem: return mki(m_arith_fid,OP_REM,n,args); + case Mod: return mki(m_arith_fid,OP_MOD,n,args); + case Power: return mki(m_arith_fid,OP_POWER,n,args); + case ToReal: return mki(m_arith_fid,OP_TO_REAL,n,args); + case ToInt: return mki(m_arith_fid,OP_TO_INT,n,args); + case IsInt: return mki(m_arith_fid,OP_IS_INT,n,args); + case Store: return mki(m_array_fid,OP_STORE,n,args); + case Select: return mki(m_array_fid,OP_SELECT,n,args); + case ConstArray: return mki(m_array_fid,OP_CONST_ARRAY,n,args); + case ArrayDefault: return mki(m_array_fid,OP_ARRAY_DEFAULT,n,args); + case ArrayMap: return mki(m_array_fid,OP_ARRAY_MAP,n,args); + case SetUnion: return mki(m_array_fid,OP_SET_UNION,n,args); + case SetIntersect: return mki(m_array_fid,OP_SET_INTERSECT,n,args); + case SetDifference: return mki(m_array_fid,OP_SET_DIFFERENCE,n,args); + case SetComplement: return mki(m_array_fid,OP_SET_COMPLEMENT,n,args); + case SetSubSet: return mki(m_array_fid,OP_SET_SUBSET,n,args); + case AsArray: return mki(m_array_fid,OP_AS_ARRAY,n,args); + default: + assert(0); + return expr(*this); + } } + + expr context::mki(family_id fid, ::decl_kind dk, int n, ::expr **args){ + return cook(m().mk_app(fid, dk, 0, 0, n, (::expr **)args)); + } + + expr context::make(decl_kind op, const std::vector &args){ + static std::vector< ::expr*> a(10); + if(a.size() < args.size()) + a.resize(args.size()); + for(unsigned i = 0; i < args.size(); i++) + a[i] = to_expr(args[i].raw()); + return make(op,args.size(), args.size() ? &a[0] : 0); + } + + expr context::make(decl_kind op){ + return make(op,0,0); + } + + expr context::make(decl_kind op, const expr &arg0){ + ::expr *a = to_expr(arg0.raw()); + return make(op,1,&a); + } + + expr context::make(decl_kind op, const expr &arg0, const expr &arg1){ + ::expr *args[2]; + args[0] = to_expr(arg0.raw()); + args[1] = to_expr(arg1.raw()); + return make(op,2,args); + } + + expr context::make(decl_kind op, const expr &arg0, const expr &arg1, const expr &arg2){ + ::expr *args[3]; + args[0] = to_expr(arg0.raw()); + args[1] = to_expr(arg1.raw()); + args[2] = to_expr(arg2.raw()); + return make(op,3,args); + } + + expr context::make_quant(decl_kind op, const std::vector &bvs, const expr &body){ + if(bvs.size() == 0) return body; + std::vector< ::expr *> foo(bvs.size()); + + + std::vector< ::symbol> names; + std::vector< ::sort *> types; + std::vector< ::expr *> bound_asts; + unsigned num_bound = bvs.size(); + + for (unsigned i = 0; i < num_bound; ++i) { + app* a = to_app(bvs[i].raw()); + ::symbol s(to_app(a)->get_decl()->get_name()); + names.push_back(s); + types.push_back(m().get_sort(a)); + bound_asts.push_back(a); + } + expr_ref abs_body(m()); + expr_abstract(m(), 0, num_bound, &bound_asts[0], to_expr(body.raw()), abs_body); + expr_ref result(m()); + result = m().mk_quantifier( + op == Forall, + names.size(), &types[0], &names[0], abs_body.get(), + 0, + ::symbol(), + ::symbol(), + 0, 0, + 0, 0 + ); + return cook(result.get()); + } + + expr context::make_quant(decl_kind op, const std::vector &_sorts, const std::vector &_names, const expr &body){ + if(_sorts.size() == 0) return body; + + + std::vector< ::symbol> names; + std::vector< ::sort *> types; + std::vector< ::expr *> bound_asts; + unsigned num_bound = _sorts.size(); + + for (unsigned i = 0; i < num_bound; ++i) { + names.push_back(_names[i]); + types.push_back(to_sort(_sorts[i].raw())); + } + expr_ref result(m()); + result = m().mk_quantifier( + op == Forall, + names.size(), &types[0], &names[0], to_expr(body.raw()), + 0, + ::symbol(), + ::symbol(), + 0, 0, + 0, 0 + ); + return cook(result.get()); + } + + + decl_kind func_decl::get_decl_kind() const { + return ctx().get_decl_kind(*this); + } + + decl_kind context::get_decl_kind(const func_decl &t){ + ::func_decl *d = to_func_decl(t.raw()); + if (null_family_id == d->get_family_id()) + return Uninterpreted; + // return (opr)d->get_decl_kind(); + if (m_basic_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_TRUE: return True; + case OP_FALSE: return False; + case OP_EQ: return Equal; + case OP_DISTINCT: return Distinct; + case OP_ITE: return Ite; + case OP_AND: return And; + case OP_OR: return Or; + case OP_IFF: return Iff; + case OP_XOR: return Xor; + case OP_NOT: return Not; + case OP_IMPLIES: return Implies; + case OP_OEQ: return Oeq; + case OP_INTERP: return Interp; + default: + return OtherBasic; + } + } + if (m_arith_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_LE: return Leq; + case OP_GE: return Geq; + case OP_LT: return Lt; + case OP_GT: return Gt; + case OP_ADD: return Plus; + case OP_SUB: return Sub; + case OP_UMINUS: return Uminus; + case OP_MUL: return Times; + case OP_DIV: return Div; + case OP_IDIV: return Idiv; + case OP_REM: return Rem; + case OP_MOD: return Mod; + case OP_POWER: return Power; + case OP_TO_REAL: return ToReal; + case OP_TO_INT: return ToInt; + case OP_IS_INT: return IsInt; + default: + return OtherArith; + } + } + if (m_array_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_STORE: return Store; + case OP_SELECT: return Select; + case OP_CONST_ARRAY: return ConstArray; + case OP_ARRAY_DEFAULT: return ArrayDefault; + case OP_ARRAY_MAP: return ArrayMap; + case OP_SET_UNION: return SetUnion; + case OP_SET_INTERSECT: return SetIntersect; + case OP_SET_DIFFERENCE: return SetDifference; + case OP_SET_COMPLEMENT: return SetComplement; + case OP_SET_SUBSET: return SetSubSet; + case OP_AS_ARRAY: return AsArray; + default: + return OtherArray; + } + } - return Other; - } - - - sort_kind context::get_sort_kind(const sort &s){ - family_id fid = to_sort(s.raw())->get_family_id(); - ::decl_kind k = to_sort(s.raw())->get_decl_kind(); - if (m().is_uninterp(to_sort(s.raw()))) { - return UninterpretedSort; + return Other; } - else if (fid == m_basic_fid && k == BOOL_SORT) { - return BoolSort; + + + sort_kind context::get_sort_kind(const sort &s){ + family_id fid = to_sort(s.raw())->get_family_id(); + ::decl_kind k = to_sort(s.raw())->get_decl_kind(); + if (m().is_uninterp(to_sort(s.raw()))) { + return UninterpretedSort; + } + else if (fid == m_basic_fid && k == BOOL_SORT) { + return BoolSort; + } + else if (fid == m_arith_fid && k == INT_SORT) { + return IntSort; + } + else if (fid == m_arith_fid && k == REAL_SORT) { + return RealSort; + } + else if (fid == m_array_fid && k == ARRAY_SORT) { + return ArraySort; + } + else { + return UnknownSort; + } } - else if (fid == m_arith_fid && k == INT_SORT) { - return IntSort; + + expr func_decl::operator()(unsigned n, expr const * args) const { + std::vector< ::expr *> _args(n); + for(unsigned i = 0; i < n; i++) + _args[i] = to_expr(args[i].raw()); + return ctx().cook(m().mk_app(to_func_decl(raw()),n,&_args[0])); } - else if (fid == m_arith_fid && k == REAL_SORT) { - return RealSort; + + int solver::get_num_decisions(){ + ::statistics st; + m_solver->collect_statistics(st); + std::ostringstream ss; + st.display(ss); + std::string stats = ss.str(); + int pos = stats.find("decisions:"); + if(pos < 0) return 0; // for some reason, decisions are not reported if there are none + pos += 10; + int end = stats.find('\n',pos); + std::string val = stats.substr(pos,end-pos); + return atoi(val.c_str()); } - else if (fid == m_array_fid && k == ARRAY_SORT) { - return ArraySort; + + void context::print_expr(std::ostream &s, const ast &e){ + s << mk_pp(e.raw(), m()); } - else { - return UnknownSort; + + + expr expr::simplify(const params &_p) const { + ::expr * a = to_expr(raw()); + params_ref p = _p.get(); + th_rewriter m_rw(m(), p); + expr_ref result(m()); + m_rw(a, result); + return ctx().cook(result); } - } - expr func_decl::operator()(unsigned n, expr const * args) const { - std::vector< ::expr *> _args(n); - for(unsigned i = 0; i < n; i++) - _args[i] = to_expr(args[i].raw()); - return ctx().cook(m().mk_app(to_func_decl(raw()),n,&_args[0])); - } - - int solver::get_num_decisions(){ - ::statistics st; - m_solver->collect_statistics(st); - std::ostringstream ss; - st.display(ss); - std::string stats = ss.str(); - int pos = stats.find("decisions:"); - if(pos < 0) return 0; // for some reason, decisions are not reported if there are none - pos += 10; - int end = stats.find('\n',pos); - std::string val = stats.substr(pos,end-pos); - return atoi(val.c_str()); - } - - void context::print_expr(std::ostream &s, const ast &e){ - s << mk_pp(e.raw(), m()); - } - - - expr expr::simplify(const params &_p) const { - ::expr * a = to_expr(raw()); - params_ref p = _p.get(); - th_rewriter m_rw(m(), p); - expr_ref result(m()); - m_rw(a, result); - return ctx().cook(result); - } - - expr expr::simplify() const { - params p; - return simplify(p); - } + expr expr::simplify() const { + params p; + return simplify(p); + } - expr context::make_var(int idx, const sort &s){ - ::sort * a = to_sort(s.raw()); - return cook(m().mk_var(idx,a)); - } + expr context::make_var(int idx, const sort &s){ + ::sort * a = to_sort(s.raw()); + return cook(m().mk_var(idx,a)); + } - expr expr::qe_lite() const { - ::qe_lite qe(m()); - expr_ref result(to_expr(raw()),m()); - proof_ref pf(m()); - qe(result,pf); - return ctx().cook(result); - } + expr expr::qe_lite() const { + ::qe_lite qe(m()); + expr_ref result(to_expr(raw()),m()); + proof_ref pf(m()); + qe(result,pf); + return ctx().cook(result); + } - expr expr::qe_lite(const std::set &idxs, bool index_of_bound) const { - ::qe_lite qe(m()); - expr_ref result(to_expr(raw()),m()); - proof_ref pf(m()); - uint_set uis; - for(std::set::const_iterator it=idxs.begin(), en = idxs.end(); it != en; ++it) - uis.insert(*it); - qe(uis,index_of_bound,result); - return ctx().cook(result); - } + expr expr::qe_lite(const std::set &idxs, bool index_of_bound) const { + ::qe_lite qe(m()); + expr_ref result(to_expr(raw()),m()); + proof_ref pf(m()); + uint_set uis; + for(std::set::const_iterator it=idxs.begin(), en = idxs.end(); it != en; ++it) + uis.insert(*it); + qe(uis,index_of_bound,result); + return ctx().cook(result); + } - expr clone_quantifier(const expr &q, const expr &b){ - return q.ctx().cook(q.m().update_quantifier(to_quantifier(q.raw()), to_expr(b.raw()))); - } + expr clone_quantifier(const expr &q, const expr &b){ + return q.ctx().cook(q.m().update_quantifier(to_quantifier(q.raw()), to_expr(b.raw()))); + } - expr clone_quantifier(const expr &q, const expr &b, const std::vector &patterns){ - quantifier *thing = to_quantifier(q.raw()); - bool is_forall = thing->is_forall(); - unsigned num_patterns = patterns.size(); - std::vector< ::expr *> _patterns(num_patterns); - for(unsigned i = 0; i < num_patterns; i++) - _patterns[i] = to_expr(patterns[i].raw()); - return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw()))); - } + expr clone_quantifier(const expr &q, const expr &b, const std::vector &patterns){ + quantifier *thing = to_quantifier(q.raw()); + bool is_forall = thing->is_forall(); + unsigned num_patterns = patterns.size(); + std::vector< ::expr *> _patterns(num_patterns); + for(unsigned i = 0; i < num_patterns; i++) + _patterns[i] = to_expr(patterns[i].raw()); + return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw()))); + } - expr clone_quantifier(decl_kind dk, const expr &q, const expr &b){ - quantifier *thing = to_quantifier(q.raw()); - bool is_forall = dk == Forall; - return q.ctx().cook(q.m().update_quantifier(thing, is_forall, to_expr(b.raw()))); - } + expr clone_quantifier(decl_kind dk, const expr &q, const expr &b){ + quantifier *thing = to_quantifier(q.raw()); + bool is_forall = dk == Forall; + return q.ctx().cook(q.m().update_quantifier(thing, is_forall, to_expr(b.raw()))); + } - void expr::get_patterns(std::vector &pats) const { - quantifier *thing = to_quantifier(raw()); - unsigned num_patterns = thing->get_num_patterns(); - :: expr * const *it = thing->get_patterns(); - pats.resize(num_patterns); - for(unsigned i = 0; i < num_patterns; i++) - pats[i] = expr(ctx(),it[i]); - } + void expr::get_patterns(std::vector &pats) const { + quantifier *thing = to_quantifier(raw()); + unsigned num_patterns = thing->get_num_patterns(); + :: expr * const *it = thing->get_patterns(); + pats.resize(num_patterns); + for(unsigned i = 0; i < num_patterns; i++) + pats[i] = expr(ctx(),it[i]); + } - unsigned func_decl::arity() const { - return (to_func_decl(raw())->get_arity()); - } + unsigned func_decl::arity() const { + return (to_func_decl(raw())->get_arity()); + } - sort func_decl::domain(unsigned i) const { - return sort(ctx(),(to_func_decl(raw())->get_domain(i))); - } + sort func_decl::domain(unsigned i) const { + return sort(ctx(),(to_func_decl(raw())->get_domain(i))); + } - sort func_decl::range() const { - return sort(ctx(),(to_func_decl(raw())->get_range())); - } + sort func_decl::range() const { + return sort(ctx(),(to_func_decl(raw())->get_range())); + } - func_decl context::fresh_func_decl(char const * prefix, const std::vector &domain, sort const & range){ - std::vector < ::sort * > _domain(domain.size()); - for(unsigned i = 0; i < domain.size(); i++) - _domain[i] = to_sort(domain[i].raw()); - ::func_decl* d = m().mk_fresh_func_decl(prefix, - _domain.size(), - &_domain[0], - to_sort(range.raw())); - return func_decl(*this,d); - } + func_decl context::fresh_func_decl(char const * prefix, const std::vector &domain, sort const & range){ + std::vector < ::sort * > _domain(domain.size()); + for(unsigned i = 0; i < domain.size(); i++) + _domain[i] = to_sort(domain[i].raw()); + ::func_decl* d = m().mk_fresh_func_decl(prefix, + _domain.size(), + &_domain[0], + to_sort(range.raw())); + return func_decl(*this,d); + } - func_decl context::fresh_func_decl(char const * prefix, sort const & range){ - ::func_decl* d = m().mk_fresh_func_decl(prefix, - 0, - 0, - to_sort(range.raw())); - return func_decl(*this,d); - } + func_decl context::fresh_func_decl(char const * prefix, sort const & range){ + ::func_decl* d = m().mk_fresh_func_decl(prefix, + 0, + 0, + to_sort(range.raw())); + return func_decl(*this,d); + } #if 0 - lbool interpolating_solver::interpolate( - const std::vector &assumptions, - std::vector &interpolants, - model &model, - Z3_literals &labels, - bool incremental) - { - Z3_model _model = 0; - Z3_literals _labels = 0; - Z3_lbool lb; - std::vector _assumptions(assumptions.size()); - std::vector _interpolants(assumptions.size()-1); - for(unsigned i = 0; i < assumptions.size(); i++) - _assumptions[i] = assumptions[i]; - std::vector _theory(theory.size()); - for(unsigned i = 0; i < theory.size(); i++) - _theory[i] = theory[i]; + lbool interpolating_solver::interpolate( + const std::vector &assumptions, + std::vector &interpolants, + model &model, + Z3_literals &labels, + bool incremental) + { + Z3_model _model = 0; + Z3_literals _labels = 0; + Z3_lbool lb; + std::vector _assumptions(assumptions.size()); + std::vector _interpolants(assumptions.size()-1); + for(unsigned i = 0; i < assumptions.size(); i++) + _assumptions[i] = assumptions[i]; + std::vector _theory(theory.size()); + for(unsigned i = 0; i < theory.size(); i++) + _theory[i] = theory[i]; - lb = Z3_interpolate( - ctx(), - _assumptions.size(), - &_assumptions[0], - 0, - 0, - &_interpolants[0], - &_model, - &_labels, - incremental, - _theory.size(), - &_theory[0] - ); + lb = Z3_interpolate( + ctx(), + _assumptions.size(), + &_assumptions[0], + 0, + 0, + &_interpolants[0], + &_model, + &_labels, + incremental, + _theory.size(), + &_theory[0] + ); - if(lb == Z3_L_FALSE){ - interpolants.resize(_interpolants.size()); - for (unsigned i = 0; i < _interpolants.size(); ++i) { - interpolants[i] = expr(ctx(),_interpolants[i]); - } - } + if(lb == Z3_L_FALSE){ + interpolants.resize(_interpolants.size()); + for (unsigned i = 0; i < _interpolants.size(); ++i) { + interpolants[i] = expr(ctx(),_interpolants[i]); + } + } - if (_model) { - model = iz3wrapper::model(ctx(), _model); + if (_model) { + model = iz3wrapper::model(ctx(), _model); + } + + if(_labels){ + labels = _labels; + } + + return lb; } - - if(_labels){ - labels = _labels; - } - - return lb; - } #endif - static int linearize_assumptions(int num, - TermTree *assumptions, - std::vector > &linear_assumptions, - std::vector &parents){ - for(unsigned i = 0; i < assumptions->getChildren().size(); i++) - num = linearize_assumptions(num, assumptions->getChildren()[i], linear_assumptions, parents); - // linear_assumptions[num].push_back(assumptions->getTerm()); - for(unsigned i = 0; i < assumptions->getChildren().size(); i++) - parents[assumptions->getChildren()[i]->getNumber()] = num; - parents[num] = SHRT_MAX; // in case we have no parent - linear_assumptions[num].push_back(assumptions->getTerm()); - std::vector &ts = assumptions->getTerms(); - for(unsigned i = 0; i < ts.size(); i++) - linear_assumptions[num].push_back(ts[i]); - return num + 1; - } + static int linearize_assumptions(int num, + TermTree *assumptions, + std::vector > &linear_assumptions, + std::vector &parents){ + for(unsigned i = 0; i < assumptions->getChildren().size(); i++) + num = linearize_assumptions(num, assumptions->getChildren()[i], linear_assumptions, parents); + // linear_assumptions[num].push_back(assumptions->getTerm()); + for(unsigned i = 0; i < assumptions->getChildren().size(); i++) + parents[assumptions->getChildren()[i]->getNumber()] = num; + parents[num] = SHRT_MAX; // in case we have no parent + linear_assumptions[num].push_back(assumptions->getTerm()); + std::vector &ts = assumptions->getTerms(); + for(unsigned i = 0; i < ts.size(); i++) + linear_assumptions[num].push_back(ts[i]); + return num + 1; + } - static int unlinearize_interpolants(int num, - TermTree* assumptions, - const std::vector &interpolant, - TermTree * &tree_interpolant) - { - std::vector chs(assumptions->getChildren().size()); - for(unsigned i = 0; i < assumptions->getChildren().size(); i++) - num = unlinearize_interpolants(num, assumptions->getChildren()[i], interpolant,chs[i]); - expr f; - if(num < (int)interpolant.size()) // last interpolant is missing, presumed false - f = interpolant[num]; - tree_interpolant = new TermTree(f,chs); - return num + 1; - } + static int unlinearize_interpolants(int num, + TermTree* assumptions, + const std::vector &interpolant, + TermTree * &tree_interpolant) + { + std::vector chs(assumptions->getChildren().size()); + for(unsigned i = 0; i < assumptions->getChildren().size(); i++) + num = unlinearize_interpolants(num, assumptions->getChildren()[i], interpolant,chs[i]); + expr f; + if(num < (int)interpolant.size()) // last interpolant is missing, presumed false + f = interpolant[num]; + tree_interpolant = new TermTree(f,chs); + return num + 1; + } - lbool interpolating_solver::interpolate_tree(TermTree *assumptions, - TermTree *&interpolant, - model &model, - literals &labels, - bool incremental - ) + lbool interpolating_solver::interpolate_tree(TermTree *assumptions, + TermTree *&interpolant, + model &model, + literals &labels, + bool incremental + ) - { - int size = assumptions->number(0); - std::vector > linear_assumptions(size); - std::vector parents(size); - linearize_assumptions(0,assumptions,linear_assumptions,parents); + { + int size = assumptions->number(0); + std::vector > linear_assumptions(size); + std::vector parents(size); + linearize_assumptions(0,assumptions,linear_assumptions,parents); - ptr_vector< ::ast> _interpolants(size-1); - vector >_assumptions(size); - for(int i = 0; i < size; i++) - for(unsigned j = 0; j < linear_assumptions[i].size(); j++) - _assumptions[i].push_back(linear_assumptions[i][j]); - ::vector _parents; _parents.resize(parents.size()); - for(unsigned i = 0; i < parents.size(); i++) - _parents[i] = parents[i]; - ptr_vector< ::ast> _theory(theory.size()); - for(unsigned i = 0; i < theory.size(); i++) - _theory[i] = theory[i]; + ptr_vector< ::ast> _interpolants(size-1); + vector >_assumptions(size); + for(int i = 0; i < size; i++) + for(unsigned j = 0; j < linear_assumptions[i].size(); j++) + _assumptions[i].push_back(linear_assumptions[i][j]); + ::vector _parents; _parents.resize(parents.size()); + for(unsigned i = 0; i < parents.size(); i++) + _parents[i] = parents[i]; + ptr_vector< ::ast> _theory(theory.size()); + for(unsigned i = 0; i < theory.size(); i++) + _theory[i] = theory[i]; - if(!incremental){ - push(); - for(unsigned i = 0; i < linear_assumptions.size(); i++) - for(unsigned j = 0; j < linear_assumptions[i].size(); j++) - add(linear_assumptions[i][j]); - } + if(!incremental){ + push(); + for(unsigned i = 0; i < linear_assumptions.size(); i++) + for(unsigned j = 0; j < linear_assumptions[i].size(); j++) + add(linear_assumptions[i][j]); + } - check_result res = unsat; + check_result res = unsat; - if(!m_solver->get_proof()) - res = check(); + if(!m_solver->get_proof()) + res = check(); - if(res == unsat){ + if(res == unsat){ - interpolation_options_struct opts; - if(weak_mode) - opts.set("weak","1"); + interpolation_options_struct opts; + if(weak_mode) + opts.set("weak","1"); - ::ast *proof = m_solver->get_proof(); - iz3interpolate(m(),proof,_assumptions,_parents,_interpolants,_theory,&opts); + ::ast *proof = m_solver->get_proof(); + iz3interpolate(m(),proof,_assumptions,_parents,_interpolants,_theory,&opts); - std::vector linearized_interpolants(_interpolants.size()); - for(unsigned i = 0; i < _interpolants.size(); i++) - linearized_interpolants[i] = expr(ctx(),_interpolants[i]); + std::vector linearized_interpolants(_interpolants.size()); + for(unsigned i = 0; i < _interpolants.size(); i++) + linearized_interpolants[i] = expr(ctx(),_interpolants[i]); - // since iz3interpolant returns interpolants with one ref count, we decrement here - for(unsigned i = 0; i < _interpolants.size(); i++) - m().dec_ref(_interpolants[i]); + // since iz3interpolant returns interpolants with one ref count, we decrement here + for(unsigned i = 0; i < _interpolants.size(); i++) + m().dec_ref(_interpolants[i]); - unlinearize_interpolants(0,assumptions,linearized_interpolants,interpolant); - interpolant->setTerm(ctx().bool_val(false)); - } + unlinearize_interpolants(0,assumptions,linearized_interpolants,interpolant); + interpolant->setTerm(ctx().bool_val(false)); + } - model_ref _m; - m_solver->get_model(_m); - model = Duality::model(ctx(),_m.get()); + model_ref _m; + m_solver->get_model(_m); + model = Duality::model(ctx(),_m.get()); #if 0 - if(_labels){ - labels = _labels; - } + if(_labels){ + labels = _labels; + } #endif - if(!incremental) - pop(); + if(!incremental) + pop(); - return (res == unsat) ? l_false : ((res == sat) ? l_true : l_undef); + return (res == unsat) ? l_false : ((res == sat) ? l_true : l_undef); - } - - - void interpolating_solver::SetWeakInterpolants(bool weak){ - weak_mode = weak; - } - - - void interpolating_solver::SetPrintToFile(const std::string &filename){ - print_filename = filename; - } - - void interpolating_solver::AssertInterpolationAxiom(const expr & t){ - add(t); - theory.push_back(t); - } - - - void interpolating_solver::RemoveInterpolationAxiom(const expr & t){ - // theory.remove(t); - } - - - const char *interpolating_solver::profile(){ - // return Z3_interpolation_profile(ctx()); - return ""; - } - - - static void get_assumptions_rec(stl_ext::hash_set &memo, const proof &pf, std::vector &assumps){ - if(memo.find(pf) != memo.end())return; - memo.insert(pf); - pfrule dk = pf.rule(); - if(dk == PR_ASSERTED){ - expr con = pf.conc(); - assumps.push_back(con); } - else { - unsigned nprems = pf.num_prems(); - for(unsigned i = 0; i < nprems; i++){ - proof arg = pf.prem(i); - get_assumptions_rec(memo,arg,assumps); - } + + + void interpolating_solver::SetWeakInterpolants(bool weak){ + weak_mode = weak; } - } - - void proof::get_assumptions(std::vector &assumps){ - stl_ext::hash_set memo; - get_assumptions_rec(memo,*this,assumps); - } - - - void ast::show() const{ - std::cout << mk_pp(raw(), m()) << std::endl; - } - - void model::show() const { - model_smt2_pp(std::cout, m(), *m_model, 0); - std::cout << std::endl; - } - void model::show_hash() const { - std::ostringstream ss; - model_smt2_pp(ss, m(), *m_model, 0); - hash_space::hash hasher; - unsigned h = hasher(ss.str()); - std::cout << "model hash: " << h << "\n"; - } - void solver::show() { - unsigned n = m_solver->get_num_assertions(); - if(!n) - return; - ast_smt_pp pp(m()); - for (unsigned i = 0; i < n-1; ++i) - pp.add_assumption(m_solver->get_assertion(i)); - pp.display_smt2(std::cout, m_solver->get_assertion(n-1)); - } + void interpolating_solver::SetPrintToFile(const std::string &filename){ + print_filename = filename; + } - void solver::print(const char *filename) { - std::ofstream f(filename); - unsigned n = m_solver->get_num_assertions(); - if(!n) - return; - ast_smt_pp pp(m()); - for (unsigned i = 0; i < n-1; ++i) - pp.add_assumption(m_solver->get_assertion(i)); - pp.display_smt2(f, m_solver->get_assertion(n-1)); - } + void interpolating_solver::AssertInterpolationAxiom(const expr & t){ + add(t); + theory.push_back(t); + } - void solver::show_assertion_ids() { + void interpolating_solver::RemoveInterpolationAxiom(const expr & t){ + // theory.remove(t); + } + + + const char *interpolating_solver::profile(){ + // return Z3_interpolation_profile(ctx()); + return ""; + } + + + static void get_assumptions_rec(stl_ext::hash_set &memo, const proof &pf, std::vector &assumps){ + if(memo.find(pf) != memo.end())return; + memo.insert(pf); + pfrule dk = pf.rule(); + if(dk == PR_ASSERTED){ + expr con = pf.conc(); + assumps.push_back(con); + } + else { + unsigned nprems = pf.num_prems(); + for(unsigned i = 0; i < nprems; i++){ + proof arg = pf.prem(i); + get_assumptions_rec(memo,arg,assumps); + } + } + } + + void proof::get_assumptions(std::vector &assumps){ + stl_ext::hash_set memo; + get_assumptions_rec(memo,*this,assumps); + } + + + void ast::show() const{ + std::cout << mk_pp(raw(), m()) << std::endl; + } + + void model::show() const { + model_smt2_pp(std::cout, m(), *m_model, 0); + std::cout << std::endl; + } + + void model::show_hash() const { + std::ostringstream ss; + model_smt2_pp(ss, m(), *m_model, 0); + hash_space::hash hasher; + unsigned h = hasher(ss.str()); + std::cout << "model hash: " << h << "\n"; + } + + void solver::show() { + unsigned n = m_solver->get_num_assertions(); + if(!n) + return; + ast_smt_pp pp(m()); + for (unsigned i = 0; i < n-1; ++i) + pp.add_assumption(m_solver->get_assertion(i)); + pp.display_smt2(std::cout, m_solver->get_assertion(n-1)); + } + + void solver::print(const char *filename) { + std::ofstream f(filename); + unsigned n = m_solver->get_num_assertions(); + if(!n) + return; + ast_smt_pp pp(m()); + for (unsigned i = 0; i < n-1; ++i) + pp.add_assumption(m_solver->get_assertion(i)); + pp.display_smt2(f, m_solver->get_assertion(n-1)); + } + + + void solver::show_assertion_ids() { #if 0 - unsigned n = m_solver->get_num_assertions(); - std::cerr << "assertion ids: "; - for (unsigned i = 0; i < n-1; ++i) - std::cerr << " " << m_solver->get_assertion(i)->get_id(); - std::cerr << "\n"; + unsigned n = m_solver->get_num_assertions(); + std::cerr << "assertion ids: "; + for (unsigned i = 0; i < n-1; ++i) + std::cerr << " " << m_solver->get_assertion(i)->get_id(); + std::cerr << "\n"; #else - unsigned n = m_solver->get_num_assertions(); - std::cerr << "assertion ids hash: "; - unsigned h = 0; - for (unsigned i = 0; i < n-1; ++i) - h += m_solver->get_assertion(i)->get_id(); - std::cerr << h << "\n"; + unsigned n = m_solver->get_num_assertions(); + std::cerr << "assertion ids hash: "; + unsigned h = 0; + for (unsigned i = 0; i < n-1; ++i) + h += m_solver->get_assertion(i)->get_id(); + std::cerr << h << "\n"; #endif - } + } - void include_ast_show(ast &a){ - a.show(); - } + void include_ast_show(ast &a){ + a.show(); + } - void include_model_show(model &a){ - a.show(); - } + void include_model_show(model &a){ + a.show(); + } - void show_ast(::ast *a, ast_manager &m) { - std::cout << mk_pp(a, m) << std::endl; - } + void show_ast(::ast *a, ast_manager &m) { + std::cout << mk_pp(a, m) << std::endl; + } - bool expr::is_label (bool &pos,std::vector &names) const { - buffer< ::symbol> _names; - bool res = m().is_label(to_expr(raw()),pos,_names); - if(res) - for(unsigned i = 0; i < _names.size(); i++) - names.push_back(symbol(ctx(),_names[i])); - return res; - } + bool expr::is_label (bool &pos,std::vector &names) const { + buffer< ::symbol> _names; + bool res = m().is_label(to_expr(raw()),pos,_names); + if(res) + for(unsigned i = 0; i < _names.size(); i++) + names.push_back(symbol(ctx(),_names[i])); + return res; + } - double current_time() - { - static stopwatch sw; - static bool started = false; - if(!started){ - sw.start(); - started = true; + double current_time() + { + static stopwatch sw; + static bool started = false; + if(!started){ + sw.start(); + started = true; } - return sw.get_current_seconds(); - } + return sw.get_current_seconds(); + } } diff --git a/src/duality/duality_wrapper.h b/src/duality/duality_wrapper.h index 979717580..7583d5bf8 100755 --- a/src/duality/duality_wrapper.h +++ b/src/duality/duality_wrapper.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2012 Microsoft Corporation + Copyright (c) 2012 Microsoft Corporation -Module Name: + Module Name: - duality_wrapper.h + duality_wrapper.h -Abstract: + Abstract: - wrap various Z3 classes in the style expected by duality + wrap various Z3 classes in the style expected by duality -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef __DUALITY_WRAPPER_H_ #define __DUALITY_WRAPPER_H_ @@ -81,70 +81,70 @@ namespace Duality { */ class config { - params_ref m_params; - config & operator=(config const & s); + params_ref m_params; + config & operator=(config const & s); public: - config(config const & s) : m_params(s.m_params) {} - config(const params_ref &_params) : m_params(_params) {} - config() { } // TODO: create a new params object here - ~config() { } - void set(char const * param, char const * value) { m_params.set_str(param,value); } - void set(char const * param, bool value) { m_params.set_bool(param,value); } - void set(char const * param, int value) { m_params.set_uint(param,value); } - params_ref &get() {return m_params;} - const params_ref &get() const {return m_params;} + config(config const & s) : m_params(s.m_params) {} + config(const params_ref &_params) : m_params(_params) {} + config() { } // TODO: create a new params object here + ~config() { } + void set(char const * param, char const * value) { m_params.set_str(param,value); } + void set(char const * param, bool value) { m_params.set_bool(param,value); } + void set(char const * param, int value) { m_params.set_uint(param,value); } + params_ref &get() {return m_params;} + const params_ref &get() const {return m_params;} }; enum decl_kind { - True, - False, - And, - Or, - Not, - Iff, - Ite, - Equal, - Implies, - Distinct, - Xor, - Oeq, - Interp, - Leq, - Geq, - Lt, - Gt, - Plus, - Sub, - Uminus, - Times, - Div, - Idiv, - Rem, - Mod, - Power, - ToReal, - ToInt, - IsInt, - Select, - Store, - ConstArray, - ArrayDefault, - ArrayMap, - SetUnion, - SetIntersect, - SetDifference, - SetComplement, - SetSubSet, - AsArray, - Numeral, - Forall, - Exists, - Variable, - Uninterpreted, - OtherBasic, - OtherArith, - OtherArray, - Other + True, + False, + And, + Or, + Not, + Iff, + Ite, + Equal, + Implies, + Distinct, + Xor, + Oeq, + Interp, + Leq, + Geq, + Lt, + Gt, + Plus, + Sub, + Uminus, + Times, + Div, + Idiv, + Rem, + Mod, + Power, + ToReal, + ToInt, + IsInt, + Select, + Store, + ConstArray, + ArrayDefault, + ArrayMap, + SetUnion, + SetIntersect, + SetDifference, + SetComplement, + SetSubSet, + AsArray, + Numeral, + Forall, + Exists, + Variable, + Uninterpreted, + OtherBasic, + OtherArith, + OtherArray, + Other }; enum sort_kind {BoolSort,IntSort,RealSort,ArraySort,UninterpretedSort,UnknownSort}; @@ -155,115 +155,115 @@ namespace Duality { class context { protected: - ast_manager &mgr; - config m_config; + ast_manager &mgr; + config m_config; - 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; - arith_util m_arith_util; + 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; + arith_util m_arith_util; public: - context(ast_manager &_manager, const config &_config) : mgr(_manager), m_config(_config), m_arith_util(_manager) { - m_basic_fid = m().get_basic_family_id(); - m_arith_fid = m().mk_family_id("arith"); - m_bv_fid = m().mk_family_id("bv"); - m_array_fid = m().mk_family_id("array"); - m_dt_fid = m().mk_family_id("datatype"); - m_datalog_fid = m().mk_family_id("datalog_relation"); - } - ~context() { } + context(ast_manager &_manager, const config &_config) : mgr(_manager), m_config(_config), m_arith_util(_manager) { + m_basic_fid = m().get_basic_family_id(); + m_arith_fid = m().mk_family_id("arith"); + m_bv_fid = m().mk_family_id("bv"); + m_array_fid = m().mk_family_id("array"); + m_dt_fid = m().mk_family_id("datatype"); + m_datalog_fid = m().mk_family_id("datalog_relation"); + } + ~context() { } - ast_manager &m() const {return *(ast_manager *)&mgr;} + ast_manager &m() const {return *(ast_manager *)&mgr;} - void set(char const * param, char const * value) { m_config.set(param,value); } - void set(char const * param, bool value) { m_config.set(param,value); } - void set(char const * param, int value) { m_config.set(param,value); } - config &get_config() {return m_config;} + void set(char const * param, char const * value) { m_config.set(param,value); } + void set(char const * param, bool value) { m_config.set(param,value); } + void set(char const * param, int value) { m_config.set(param,value); } + config &get_config() {return m_config;} - symbol str_symbol(char const * s); - symbol int_symbol(int n); + symbol str_symbol(char const * s); + symbol int_symbol(int n); - sort bool_sort(); - sort int_sort(); - sort real_sort(); - sort bv_sort(unsigned sz); - sort array_sort(sort d, sort r); + sort bool_sort(); + sort int_sort(); + sort real_sort(); + sort bv_sort(unsigned sz); + sort array_sort(sort d, sort r); - func_decl function(symbol const & name, unsigned arity, sort const * domain, sort const & range); - func_decl function(char const * name, unsigned arity, sort const * domain, sort const & range); - func_decl function(char const * name, sort const & domain, sort const & range); - func_decl function(char const * name, sort const & d1, sort const & d2, sort const & range); - func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range); - func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & range); - func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range); - func_decl fresh_func_decl(char const * name, const std::vector &domain, sort const & range); - func_decl fresh_func_decl(char const * name, sort const & range); + func_decl function(symbol const & name, unsigned arity, sort const * domain, sort const & range); + func_decl function(char const * name, unsigned arity, sort const * domain, sort const & range); + func_decl function(char const * name, sort const & domain, sort const & range); + func_decl function(char const * name, sort const & d1, sort const & d2, sort const & range); + func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range); + func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & range); + func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range); + func_decl fresh_func_decl(char const * name, const std::vector &domain, sort const & range); + func_decl fresh_func_decl(char const * name, sort const & range); - expr constant(symbol const & name, sort const & s); - expr constant(char const * name, sort const & s); - expr constant(const std::string &name, sort const & s); - expr bool_const(char const * name); - expr int_const(char const * name); - expr real_const(char const * name); - expr bv_const(char const * name, unsigned sz); + expr constant(symbol const & name, sort const & s); + expr constant(char const * name, sort const & s); + expr constant(const std::string &name, sort const & s); + expr bool_const(char const * name); + expr int_const(char const * name); + expr real_const(char const * name); + expr bv_const(char const * name, unsigned sz); - expr bool_val(bool b); + expr bool_val(bool b); - expr int_val(int n); - expr int_val(unsigned n); - expr int_val(char const * n); + expr int_val(int n); + expr int_val(unsigned n); + expr int_val(char const * n); - expr real_val(int n, int d); - expr real_val(int n); - expr real_val(unsigned n); - expr real_val(char const * n); + expr real_val(int n, int d); + expr real_val(int n); + expr real_val(unsigned n); + expr real_val(char const * n); - expr bv_val(int n, unsigned sz); - expr bv_val(unsigned n, unsigned sz); - expr bv_val(char const * n, unsigned sz); + expr bv_val(int n, unsigned sz); + expr bv_val(unsigned n, unsigned sz); + expr bv_val(char const * n, unsigned sz); - expr num_val(int n, sort const & s); + expr num_val(int n, sort const & s); - expr mki(family_id fid, ::decl_kind dk, int n, ::expr **args); - expr make(decl_kind op, int n, ::expr **args); - expr make(decl_kind op, const std::vector &args); - expr make(decl_kind op); - expr make(decl_kind op, const expr &arg0); - expr make(decl_kind op, const expr &arg0, const expr &arg1); - expr make(decl_kind op, const expr &arg0, const expr &arg1, const expr &arg2); + expr mki(family_id fid, ::decl_kind dk, int n, ::expr **args); + expr make(decl_kind op, int n, ::expr **args); + expr make(decl_kind op, const std::vector &args); + expr make(decl_kind op); + expr make(decl_kind op, const expr &arg0); + expr make(decl_kind op, const expr &arg0, const expr &arg1); + expr make(decl_kind op, const expr &arg0, const expr &arg1, const expr &arg2); - expr make_quant(decl_kind op, const std::vector &bvs, const expr &body); - expr make_quant(decl_kind op, const std::vector &_sorts, const std::vector &_names, const expr &body); - expr make_var(int idx, const sort &s); + expr make_quant(decl_kind op, const std::vector &bvs, const expr &body); + expr make_quant(decl_kind op, const std::vector &_sorts, const std::vector &_names, const expr &body); + expr make_var(int idx, const sort &s); - decl_kind get_decl_kind(const func_decl &t); + decl_kind get_decl_kind(const func_decl &t); - sort_kind get_sort_kind(const sort &s); + sort_kind get_sort_kind(const sort &s); - expr translate(const expr &e); - func_decl translate(const func_decl &); + expr translate(const expr &e); + func_decl translate(const func_decl &); - void print_expr(std::ostream &s, const ast &e); + void print_expr(std::ostream &s, const ast &e); - fixedpoint mk_fixedpoint(); + fixedpoint mk_fixedpoint(); - expr cook(::expr *a); - std::vector cook(ptr_vector< ::expr> v); - ::expr *uncook(const expr &a); + expr cook(::expr *a); + std::vector cook(ptr_vector< ::expr> v); + ::expr *uncook(const expr &a); }; template - class z3array { + class z3array { T * m_array; unsigned m_size; z3array(z3array const & s); z3array & operator=(z3array const & s); public: - z3array(unsigned sz):m_size(sz) { m_array = new T[sz]; } + z3array(unsigned sz):m_size(sz) { m_array = new T[sz]; } ~z3array() { delete[] m_array; } unsigned size() const { return m_size; } T & operator[](unsigned i) { assert(i < m_size); return m_array[i]; } @@ -276,9 +276,9 @@ namespace Duality { protected: context * m_ctx; public: - object(): m_ctx((context *)0) {} - object(context & c):m_ctx(&c) {} - object(object const & s):m_ctx(s.m_ctx) {} + object(): m_ctx((context *)0) {} + object(context & c):m_ctx(&c) {} + object(object const & s):m_ctx(s.m_ctx) {} context & ctx() const { return *m_ctx; } friend void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); } ast_manager &m() const {return m_ctx->m();} @@ -287,25 +287,25 @@ namespace Duality { class symbol : public object { ::symbol m_sym; public: - symbol(context & c, ::symbol s):object(c), m_sym(s) {} - symbol(symbol const & s):object(s), m_sym(s.m_sym) {} + symbol(context & c, ::symbol s):object(c), m_sym(s) {} + symbol(symbol const & s):object(s), m_sym(s.m_sym) {} symbol & operator=(symbol const & s) { m_ctx = s.m_ctx; m_sym = s.m_sym; return *this; } operator ::symbol() const {return m_sym;} std::string str() const { - if (m_sym.is_numerical()) { - std::ostringstream buffer; - buffer << m_sym.get_num(); - return buffer.str(); - } - else { - return m_sym.bare_str(); - } + if (m_sym.is_numerical()) { + std::ostringstream buffer; + buffer << m_sym.get_num(); + return buffer.str(); + } + else { + return m_sym.bare_str(); + } } friend std::ostream & operator<<(std::ostream & out, symbol const & s){ - return out << s.str(); + return out << s.str(); } friend bool operator==(const symbol &x, const symbol &y){ - return x.m_sym == y.m_sym; + return x.m_sym == y.m_sym; } }; @@ -314,103 +314,103 @@ namespace Duality { /** Wrapper around an ast pointer */ class ast_i : public object { protected: - ::ast *_ast; + ::ast *_ast; public: - ::ast * const &raw() const {return _ast;} - ast_i(context & c, ::ast *a = 0) : object(c) {_ast = a;} + ::ast * const &raw() const {return _ast;} + ast_i(context & c, ::ast *a = 0) : object(c) {_ast = a;} - ast_i(){_ast = 0;} - bool eq(const ast_i &other) const { - return _ast == other._ast; - } - bool lt(const ast_i &other) const { - return _ast < other._ast; - } - friend bool operator==(const ast_i &x, const ast_i&y){ - return x.eq(y); - } - friend bool operator!=(const ast_i &x, const ast_i&y){ - return !x.eq(y); - } - friend bool operator<(const ast_i &x, const ast_i&y){ - return x.lt(y); - } - size_t hash() const {return (size_t)_ast;} - bool null() const {return !_ast;} + ast_i(){_ast = 0;} + bool eq(const ast_i &other) const { + return _ast == other._ast; + } + bool lt(const ast_i &other) const { + return _ast < other._ast; + } + friend bool operator==(const ast_i &x, const ast_i&y){ + return x.eq(y); + } + friend bool operator!=(const ast_i &x, const ast_i&y){ + return !x.eq(y); + } + friend bool operator<(const ast_i &x, const ast_i&y){ + return x.lt(y); + } + size_t hash() const {return (size_t)_ast;} + bool null() const {return !_ast;} }; /** Reference counting verison of above */ class ast : public ast_i { public: - operator ::ast*() const { return raw(); } - friend bool eq(ast const & a, ast const & b) { return a.raw() == b.raw(); } + operator ::ast*() const { return raw(); } + friend bool eq(ast const & a, ast const & b) { return a.raw() == b.raw(); } - ast(context &c, ::ast *a = 0) : ast_i(c,a) { - if(_ast) - m().inc_ref(a); - } + ast(context &c, ::ast *a = 0) : ast_i(c,a) { + if(_ast) + m().inc_ref(a); + } - ast() {} + ast() {} - ast(const ast &other) : ast_i(other) { - if(_ast) - m().inc_ref(_ast); - } + ast(const ast &other) : ast_i(other) { + if(_ast) + m().inc_ref(_ast); + } - ast &operator=(const ast &other) { - if(_ast) - m().dec_ref(_ast); - _ast = other._ast; - m_ctx = other.m_ctx; - if(_ast) - m().inc_ref(_ast); - return *this; - } + ast &operator=(const ast &other) { + if(_ast) + m().dec_ref(_ast); + _ast = other._ast; + m_ctx = other.m_ctx; + if(_ast) + m().inc_ref(_ast); + return *this; + } - ~ast(){ - if(_ast) - m().dec_ref(_ast); - } + ~ast(){ + if(_ast) + m().dec_ref(_ast); + } - void show() const; + void show() const; }; class sort : public ast { public: - sort(context & c):ast(c) {} - sort(context & c, ::sort *s):ast(c, s) {} - sort(sort const & s):ast(s) {} - operator ::sort*() const { return to_sort(raw()); } - sort & operator=(sort const & s) { return static_cast(ast::operator=(s)); } + sort(context & c):ast(c) {} + sort(context & c, ::sort *s):ast(c, s) {} + sort(sort const & s):ast(s) {} + operator ::sort*() const { return to_sort(raw()); } + sort & operator=(sort const & s) { return static_cast(ast::operator=(s)); } - bool is_bool() const { return m().is_bool(*this); } - bool is_int() const { return ctx().get_sort_kind(*this) == IntSort; } - bool is_real() const { return ctx().get_sort_kind(*this) == RealSort; } - bool is_arith() const; - bool is_array() const { return ctx().get_sort_kind(*this) == ArraySort; } - bool is_datatype() const; - bool is_relation() const; - bool is_finite_domain() const; + bool is_bool() const { return m().is_bool(*this); } + bool is_int() const { return ctx().get_sort_kind(*this) == IntSort; } + bool is_real() const { return ctx().get_sort_kind(*this) == RealSort; } + bool is_arith() const; + bool is_array() const { return ctx().get_sort_kind(*this) == ArraySort; } + bool is_datatype() const; + bool is_relation() const; + bool is_finite_domain() const; - sort array_domain() const; - sort array_range() const; + sort array_domain() const; + sort array_range() const; - friend std::ostream & operator<<(std::ostream & out, sort const & m){ - m.ctx().print_expr(out,m); - return out; - } + friend std::ostream & operator<<(std::ostream & out, sort const & m){ + m.ctx().print_expr(out,m); + return out; + } }; class func_decl : public ast { public: - func_decl() : ast() {} - func_decl(context & c):ast(c) {} - func_decl(context & c, ::func_decl *n):ast(c, n) {} - func_decl(func_decl const & s):ast(s) {} + func_decl() : ast() {} + func_decl(context & c):ast(c) {} + func_decl(context & c, ::func_decl *n):ast(c, n) {} + func_decl(func_decl const & s):ast(s) {} operator ::func_decl*() const { return to_func_decl(*this); } func_decl & operator=(func_decl const & s) { return static_cast(ast::operator=(s)); } @@ -435,17 +435,17 @@ namespace Duality { expr operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const; func_decl get_func_decl_parameter(unsigned idx){ - return func_decl(ctx(),to_func_decl(to_func_decl(raw())->get_parameters()[idx].get_ast())); + return func_decl(ctx(),to_func_decl(to_func_decl(raw())->get_parameters()[idx].get_ast())); } }; class expr : public ast { public: - expr() : ast() {} - expr(context & c):ast(c) {} - expr(context & c, ::ast *n):ast(c, n) {} - expr(expr const & n):ast(n) {} + expr() : ast() {} + expr(context & c):ast(c) {} + expr(context & c, ::ast *n):ast(c, n) {} + expr(expr const & n):ast(n) {} expr & operator=(expr const & n) { return static_cast(ast::operator=(n)); } operator ::expr*() const { return to_expr(raw()); } unsigned get_id() const {return to_expr(raw())->get_id();} @@ -463,7 +463,7 @@ namespace Duality { bool is_true() const {return is_app() && decl().get_decl_kind() == True; } bool is_numeral() const { - return is_app() && decl().get_decl_kind() == OtherArith && m().is_unique_value(to_expr(raw())); + return is_app() && decl().get_decl_kind() == OtherArith && m().is_unique_value(to_expr(raw())); } bool is_app() const {return raw()->get_kind() == AST_APP;} bool is_quantifier() const {return raw()->get_kind() == AST_QUANTIFIER;} @@ -472,108 +472,108 @@ namespace Duality { bool is_ground() const {return to_app(raw())->is_ground();} bool has_quantifiers() const {return to_app(raw())->has_quantifiers();} bool has_free(int idx) const { - used_vars proc; - proc.process(to_expr(raw())); - return proc.contains(idx); + used_vars proc; + proc.process(to_expr(raw())); + return proc.contains(idx); } unsigned get_max_var_idx_plus_1() const { - used_vars proc; - proc.process(to_expr(raw())); - return proc.get_max_found_var_idx_plus_1(); + used_vars proc; + proc.process(to_expr(raw())); + return proc.get_max_found_var_idx_plus_1(); } // operator Z3_app() const { assert(is_app()); return reinterpret_cast(m_ast); } func_decl decl() const {return func_decl(ctx(),to_app(raw())->get_decl());} unsigned num_args() const { - ast_kind dk = raw()->get_kind(); - switch(dk){ - case AST_APP: - return to_app(raw())->get_num_args(); - case AST_QUANTIFIER: - return 1; - case AST_VAR: - return 0; - default:; - } - SASSERT(0); - return 0; + ast_kind dk = raw()->get_kind(); + switch(dk){ + case AST_APP: + return to_app(raw())->get_num_args(); + case AST_QUANTIFIER: + return 1; + case AST_VAR: + return 0; + default:; + } + SASSERT(0); + return 0; } expr arg(unsigned i) const { - ast_kind dk = raw()->get_kind(); - switch(dk){ - case AST_APP: - return ctx().cook(to_app(raw())->get_arg(i)); - case AST_QUANTIFIER: - return ctx().cook(to_quantifier(raw())->get_expr()); - default:; - } - assert(0); - return expr(); + ast_kind dk = raw()->get_kind(); + switch(dk){ + case AST_APP: + return ctx().cook(to_app(raw())->get_arg(i)); + case AST_QUANTIFIER: + return ctx().cook(to_quantifier(raw())->get_expr()); + default:; + } + assert(0); + return expr(); } expr body() const { - return ctx().cook(to_quantifier(raw())->get_expr()); + return ctx().cook(to_quantifier(raw())->get_expr()); } friend expr operator!(expr const & a) { - // ::expr *e = a; - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_NOT,a)); + // ::expr *e = a; + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_NOT,a)); } friend expr operator&&(expr const & a, expr const & b) { - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_AND,a,b)); + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_AND,a,b)); } friend expr operator||(expr const & a, expr const & b) { - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_OR,a,b)); + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_OR,a,b)); } friend expr implies(expr const & a, expr const & b) { - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_IMPLIES,a,b)); + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_IMPLIES,a,b)); } friend expr operator==(expr const & a, expr const & b) { - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_EQ,a,b)); + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_EQ,a,b)); } friend expr operator!=(expr const & a, expr const & b) { - return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_DISTINCT,a,b)); + return expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_DISTINCT,a,b)); } friend expr operator+(expr const & a, expr const & b) { - return a.ctx().make(Plus,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_ADD,a,b)); + return a.ctx().make(Plus,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_ADD,a,b)); } friend expr operator*(expr const & a, expr const & b) { - return a.ctx().make(Times,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_MUL,a,b)); + return a.ctx().make(Times,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_MUL,a,b)); } friend expr operator/(expr const & a, expr const & b) { - return a.ctx().make(Div,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_DIV,a,b)); + return a.ctx().make(Div,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_DIV,a,b)); } friend expr operator-(expr const & a) { - return a.ctx().make(Uminus,a); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_UMINUS,a)); + return a.ctx().make(Uminus,a); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_UMINUS,a)); } friend expr operator-(expr const & a, expr const & b) { - return a.ctx().make(Sub,a,b); // expr(a.ctx(),a.m().mk_app(a.ctx().m_arith_fid,OP_SUB,a,b)); + return a.ctx().make(Sub,a,b); // expr(a.ctx(),a.m().mk_app(a.ctx().m_arith_fid,OP_SUB,a,b)); } friend expr operator<=(expr const & a, expr const & b) { - return a.ctx().make(Leq,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LE,a,b)); + return a.ctx().make(Leq,a,b); // expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LE,a,b)); } friend expr operator>=(expr const & a, expr const & b) { - return a.ctx().make(Geq,a,b); //expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GE,a,b)); + return a.ctx().make(Geq,a,b); //expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GE,a,b)); } friend expr operator<(expr const & a, expr const & b) { - return a.ctx().make(Lt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LT,a,b)); + return a.ctx().make(Lt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_LT,a,b)); } friend expr operator>(expr const & a, expr const & b) { - return a.ctx().make(Gt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GT,a,b)); + return a.ctx().make(Gt,a,b); expr(a.ctx(),a.m().mk_app(a.m().get_basic_family_id(),OP_GT,a,b)); } expr simplify() const; @@ -591,31 +591,31 @@ namespace Duality { friend expr clone_quantifier(decl_kind, const expr &, const expr &); friend std::ostream & operator<<(std::ostream & out, expr const & m){ - m.ctx().print_expr(out,m); - return out; + m.ctx().print_expr(out,m); + return out; } void get_patterns(std::vector &pats) const ; unsigned get_quantifier_num_bound() const { - return to_quantifier(raw())->get_num_decls(); + return to_quantifier(raw())->get_num_decls(); } unsigned get_index_value() const { - var* va = to_var(raw()); - return va->get_idx(); + var* va = to_var(raw()); + return va->get_idx(); } bool is_quantifier_forall() const { - return to_quantifier(raw())->is_forall(); + return to_quantifier(raw())->is_forall(); } sort get_quantifier_bound_sort(unsigned n) const { - return sort(ctx(),to_quantifier(raw())->get_decl_sort(n)); + return sort(ctx(),to_quantifier(raw())->get_decl_sort(n)); } symbol get_quantifier_bound_name(unsigned n) const { - return symbol(ctx(),to_quantifier(raw())->get_decl_names()[n]); + return symbol(ctx(),to_quantifier(raw())->get_decl_names()[n]); } friend expr forall(const std::vector &quants, const expr &body); @@ -629,43 +629,43 @@ namespace Duality { class proof : public ast { public: - proof(context & c):ast(c) {} - proof(context & c, ::proof *s):ast(c, s) {} - proof(proof const & s):ast(s) {} - operator ::proof*() const { return to_app(raw()); } - proof & operator=(proof const & s) { return static_cast(ast::operator=(s)); } + proof(context & c):ast(c) {} + proof(context & c, ::proof *s):ast(c, s) {} + proof(proof const & s):ast(s) {} + operator ::proof*() const { return to_app(raw()); } + proof & operator=(proof const & s) { return static_cast(ast::operator=(s)); } - pfrule rule() const { - ::func_decl *d = to_app(raw())->get_decl(); - return d->get_decl_kind(); - } + pfrule rule() const { + ::func_decl *d = to_app(raw())->get_decl(); + return d->get_decl_kind(); + } - unsigned num_prems() const { - return to_app(raw())->get_num_args() - 1; - } + unsigned num_prems() const { + return to_app(raw())->get_num_args() - 1; + } - expr conc() const { - return ctx().cook(to_app(raw())->get_arg(num_prems())); - } + expr conc() const { + return ctx().cook(to_app(raw())->get_arg(num_prems())); + } - proof prem(unsigned i) const { - return proof(ctx(),to_app(to_app(raw())->get_arg(i))); - } + proof prem(unsigned i) const { + return proof(ctx(),to_app(to_app(raw())->get_arg(i))); + } - void get_assumptions(std::vector &assumps); + void get_assumptions(std::vector &assumps); }; #if 0 #if Z3_MAJOR_VERSION > 4 || Z3_MAJOR_VERSION == 4 && Z3_MINOR_VERSION >= 3 template - class ast_vector_tpl : public object { + class ast_vector_tpl : public object { Z3_ast_vector m_vector; void init(Z3_ast_vector v) { Z3_ast_vector_inc_ref(ctx(), v); m_vector = v; } public: - ast_vector_tpl(context & c):object(c) { init(Z3_mk_ast_vector(c)); } - ast_vector_tpl(context & c, Z3_ast_vector v):object(c) { init(v); } - ast_vector_tpl(ast_vector_tpl const & s):object(s), m_vector(s.m_vector) { Z3_ast_vector_inc_ref(ctx(), m_vector); } + ast_vector_tpl(context & c):object(c) { init(Z3_mk_ast_vector(c)); } + ast_vector_tpl(context & c, Z3_ast_vector v):object(c) { init(v); } + ast_vector_tpl(ast_vector_tpl const & s):object(s), m_vector(s.m_vector) { Z3_ast_vector_inc_ref(ctx(), m_vector); } ~ast_vector_tpl() { /* Z3_ast_vector_dec_ref(ctx(), m_vector); */ } operator Z3_ast_vector() const { return m_vector; } unsigned size() const { return Z3_ast_vector_size(ctx(), m_vector); } @@ -695,30 +695,30 @@ namespace Duality { #endif class func_interp : public object { - ::func_interp * m_interp; - void init(::func_interp * e) { - m_interp = e; - } + ::func_interp * m_interp; + void init(::func_interp * e) { + m_interp = e; + } public: - func_interp(context & c, ::func_interp * e):object(c) { init(e); } - func_interp(func_interp const & s):object(s) { init(s.m_interp); } - ~func_interp() { } - operator ::func_interp *() const { return m_interp; } - func_interp & operator=(func_interp const & s) { - m_ctx = s.m_ctx; - m_interp = s.m_interp; - return *this; - } - unsigned num_entries() const { return m_interp->num_entries(); } - expr get_arg(unsigned ent, unsigned arg) const { - return expr(ctx(),m_interp->get_entry(ent)->get_arg(arg)); - } - expr get_value(unsigned ent) const { - return expr(ctx(),m_interp->get_entry(ent)->get_result()); - } - expr else_value() const { - return expr(ctx(),m_interp->get_else()); - } + func_interp(context & c, ::func_interp * e):object(c) { init(e); } + func_interp(func_interp const & s):object(s) { init(s.m_interp); } + ~func_interp() { } + operator ::func_interp *() const { return m_interp; } + func_interp & operator=(func_interp const & s) { + m_ctx = s.m_ctx; + m_interp = s.m_interp; + return *this; + } + unsigned num_entries() const { return m_interp->num_entries(); } + expr get_arg(unsigned ent, unsigned arg) const { + return expr(ctx(),m_interp->get_entry(ent)->get_arg(arg)); + } + expr get_value(unsigned ent) const { + return expr(ctx(),m_interp->get_entry(ent)->get_result()); + } + expr else_value() const { + return expr(ctx(),m_interp->get_else()); + } }; @@ -729,8 +729,8 @@ namespace Duality { m_model = m; } public: - model(context & c, ::model * m = 0):object(c), m_model(m) { } - model(model const & s):object(s), m_model(s.m_model) { } + model(context & c, ::model * m = 0):object(c), m_model(m) { } + model(model const & s):object(s), m_model(s.m_model) { } ~model() { } operator ::model *() const { return m_model.get(); } model & operator=(model const & s) { @@ -747,10 +747,10 @@ namespace Duality { bool null() const {return !m_model;} expr eval(expr const & n, bool model_completion=true) const { - ::model * _m = m_model.get(); - expr_ref result(ctx().m()); - _m->eval(n, result, model_completion); - return expr(ctx(), result); + ::model * _m = m_model.get(); + expr_ref result(ctx().m()); + _m->eval(n, result, model_completion); + return expr(ctx(), result); } void show() const; @@ -764,11 +764,11 @@ namespace Duality { func_decl operator[](unsigned i) const; expr get_const_interp(func_decl f) const { - return ctx().cook(m_model->get_const_interp(to_func_decl(f.raw()))); + return ctx().cook(m_model->get_const_interp(to_func_decl(f.raw()))); } func_interp get_func_interp(func_decl f) const { - return func_interp(ctx(),m_model->get_func_interp(to_func_decl(f.raw()))); + return func_interp(ctx(),m_model->get_func_interp(to_func_decl(f.raw()))); } #if 0 @@ -784,9 +784,9 @@ namespace Duality { Z3_stats_inc_ref(ctx(), m_stats); } public: - stats(context & c):object(c), m_stats(0) {} - stats(context & c, Z3_stats e):object(c) { init(e); } - stats(stats const & s):object(s) { init(s.m_stats); } + stats(context & c):object(c), m_stats(0) {} + stats(context & c, Z3_stats e):object(c) { init(e); } + stats(stats const & s):object(s) { init(s.m_stats); } ~stats() { if (m_stats) Z3_stats_dec_ref(ctx(), m_stats); } operator Z3_stats() const { return m_stats; } stats & operator=(stats const & s) { @@ -813,11 +813,11 @@ namespace Duality { class fixedpoint : public object { public: - void get_rules(std::vector &rules); - void get_assertions(std::vector &rules); - void register_relation(const func_decl &rela); - void add_rule(const expr &clause, const symbol &name); - void assert_cnst(const expr &cnst); + void get_rules(std::vector &rules); + void get_assertions(std::vector &rules); + void register_relation(const func_decl &rela); + void add_rule(const expr &clause, const symbol &name); + void assert_cnst(const expr &cnst); }; inline std::ostream & operator<<(std::ostream & out, check_result r) { @@ -842,11 +842,11 @@ namespace Duality { bool extensional; public: solver(context & c, bool extensional = false, bool models = true); - solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;} - solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;} + solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;} + solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;} ~solver() { - if(m_solver) - dealloc(m_solver); + if(m_solver) + dealloc(m_solver); } operator ::solver*() const { return m_solver; } solver & operator=(solver const & s) { @@ -858,8 +858,8 @@ namespace Duality { } struct cancel_exception {}; void checkpoint(){ - if(canceled) - throw(cancel_exception()); + if(canceled) + throw(cancel_exception()); } // void set(params const & p) { Z3_solver_set_params(ctx(), m_solver, p); check_error(); } void push() { scoped_proof_mode spm(m(),m_mode); m_solver->push(); } @@ -867,49 +867,49 @@ namespace Duality { // void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); } void add(expr const & e) { scoped_proof_mode spm(m(),m_mode); m_solver->assert_expr(e); } check_result check() { - scoped_proof_mode spm(m(),m_mode); - checkpoint(); - lbool r = m_solver->check_sat(0,0); - model_ref m; - m_solver->get_model(m); - the_model = m.get(); - return to_check_result(r); + scoped_proof_mode spm(m(),m_mode); + checkpoint(); + lbool r = m_solver->check_sat(0,0); + model_ref m; + m_solver->get_model(m); + the_model = m.get(); + return to_check_result(r); } check_result check_keep_model(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) { - scoped_proof_mode spm(m(),m_mode); - model old_model(the_model); - check_result res = check(n,assumptions,core_size,core); - if(the_model == 0) - the_model = old_model; - return res; + scoped_proof_mode spm(m(),m_mode); + model old_model(the_model); + check_result res = check(n,assumptions,core_size,core); + if(the_model == 0) + the_model = old_model; + return res; } check_result check(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) { - scoped_proof_mode spm(m(),m_mode); - checkpoint(); - std::vector< ::expr *> _assumptions(n); - for (unsigned i = 0; i < n; i++) { - _assumptions[i] = to_expr(assumptions[i]); - } - the_model = 0; - lbool r = m_solver->check_sat(n,&_assumptions[0]); + scoped_proof_mode spm(m(),m_mode); + checkpoint(); + std::vector< ::expr *> _assumptions(n); + for (unsigned i = 0; i < n; i++) { + _assumptions[i] = to_expr(assumptions[i]); + } + the_model = 0; + lbool r = m_solver->check_sat(n,&_assumptions[0]); - if(core_size && core){ - ptr_vector< ::expr> _core; - m_solver->get_unsat_core(_core); - *core_size = _core.size(); - for(unsigned i = 0; i < *core_size; i++) - core[i] = expr(ctx(),_core[i]); - } + if(core_size && core){ + ptr_vector< ::expr> _core; + m_solver->get_unsat_core(_core); + *core_size = _core.size(); + for(unsigned i = 0; i < *core_size; i++) + core[i] = expr(ctx(),_core[i]); + } - model_ref m; - m_solver->get_model(m); - the_model = m.get(); + model_ref m; + m_solver->get_model(m); + the_model = m.get(); - return to_check_result(r); + return to_check_result(r); } #if 0 check_result check(expr_vector assumptions) { - scoped_proof_mode spm(m(),m_mode); + scoped_proof_mode spm(m(),m_mode); unsigned n = assumptions.size(); z3array _assumptions(n); for (unsigned i = 0; i < n; i++) { @@ -934,10 +934,10 @@ namespace Duality { int get_num_decisions(); void cancel(){ - scoped_proof_mode spm(m(),m_mode); - canceled = true; - if(m_solver) - m_solver->cancel(); + scoped_proof_mode spm(m(),m_mode); + canceled = true; + if(m_solver) + m_solver->cancel(); } unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();} @@ -947,8 +947,8 @@ namespace Duality { void show_assertion_ids(); proof get_proof(){ - scoped_proof_mode spm(m(),m_mode); - return proof(ctx(),m_solver->get_proof()); + scoped_proof_mode spm(m(),m_mode); + return proof(ctx(),m_solver->get_proof()); } bool extensional_array_theory() {return extensional;} @@ -962,9 +962,9 @@ namespace Duality { Z3_goal_inc_ref(ctx(), s); } public: - goal(context & c, bool models=true, bool unsat_cores=false, bool proofs=false):object(c) { init(Z3_mk_goal(c, models, unsat_cores, proofs)); } - goal(context & c, Z3_goal s):object(c) { init(s); } - goal(goal const & s):object(s) { init(s.m_goal); } + goal(context & c, bool models=true, bool unsat_cores=false, bool proofs=false):object(c) { init(Z3_mk_goal(c, models, unsat_cores, proofs)); } + goal(context & c, Z3_goal s):object(c) { init(s); } + goal(goal const & s):object(s) { init(s.m_goal); } ~goal() { Z3_goal_dec_ref(ctx(), m_goal); } operator Z3_goal() const { return m_goal; } goal & operator=(goal const & s) { @@ -994,8 +994,8 @@ namespace Duality { Z3_apply_result_inc_ref(ctx(), s); } public: - apply_result(context & c, Z3_apply_result s):object(c) { init(s); } - apply_result(apply_result const & s):object(s) { init(s.m_apply_result); } + apply_result(context & c, Z3_apply_result s):object(c) { init(s); } + apply_result(apply_result const & s):object(s) { init(s.m_apply_result); } ~apply_result() { Z3_apply_result_dec_ref(ctx(), m_apply_result); } operator Z3_apply_result() const { return m_apply_result; } apply_result & operator=(apply_result const & s) { @@ -1024,9 +1024,9 @@ namespace Duality { Z3_tactic_inc_ref(ctx(), s); } public: - tactic(context & c, char const * name):object(c) { Z3_tactic r = Z3_mk_tactic(c, name); check_error(); init(r); } - tactic(context & c, Z3_tactic s):object(c) { init(s); } - tactic(tactic const & s):object(s) { init(s.m_tactic); } + tactic(context & c, char const * name):object(c) { Z3_tactic r = Z3_mk_tactic(c, name); check_error(); init(r); } + tactic(context & c, Z3_tactic s):object(c) { init(s); } + tactic(tactic const & s):object(s) { init(s.m_tactic); } ~tactic() { Z3_tactic_dec_ref(ctx(), m_tactic); } operator Z3_tactic() const { return m_tactic; } tactic & operator=(tactic const & s) { @@ -1083,10 +1083,10 @@ namespace Duality { Z3_probe_inc_ref(ctx(), s); } public: - probe(context & c, char const * name):object(c) { Z3_probe r = Z3_mk_probe(c, name); check_error(); init(r); } - probe(context & c, double val):object(c) { Z3_probe r = Z3_probe_const(c, val); check_error(); init(r); } - probe(context & c, Z3_probe s):object(c) { init(s); } - probe(probe const & s):object(s) { init(s.m_probe); } + probe(context & c, char const * name):object(c) { Z3_probe r = Z3_mk_probe(c, name); check_error(); init(r); } + probe(context & c, double val):object(c) { Z3_probe r = Z3_probe_const(c, val); check_error(); init(r); } + probe(context & c, Z3_probe s):object(c) { init(s); } + probe(probe const & s):object(s) { init(s.m_probe); } ~probe() { Z3_probe_dec_ref(ctx(), m_probe); } operator Z3_probe() const { return m_probe; } probe & operator=(probe const & s) { @@ -1160,39 +1160,39 @@ namespace Duality { inline symbol context::int_symbol(int n) { ::symbol r = ::symbol(n); return symbol(*this, r); } inline sort context::bool_sort() { - ::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT); - return sort(*this, s); + ::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT); + return sort(*this, s); } inline sort context::int_sort() { - ::sort *s = m().mk_sort(m_arith_fid, INT_SORT); - return sort(*this, s); + ::sort *s = m().mk_sort(m_arith_fid, INT_SORT); + return sort(*this, s); } inline sort context::real_sort() { - ::sort *s = m().mk_sort(m_arith_fid, REAL_SORT); - return sort(*this, s); + ::sort *s = m().mk_sort(m_arith_fid, REAL_SORT); + return sort(*this, s); } inline sort context::array_sort(sort d, sort r) { - parameter params[2] = { parameter(d), parameter(to_sort(r)) }; - ::sort * s = m().mk_sort(m_array_fid, ARRAY_SORT, 2, params); - return sort(*this, s); + parameter params[2] = { parameter(d), parameter(to_sort(r)) }; + ::sort * s = m().mk_sort(m_array_fid, ARRAY_SORT, 2, params); + return sort(*this, s); } inline func_decl context::function(symbol const & name, unsigned arity, sort const * domain, sort const & range) { - std::vector< ::sort *> sv(arity); - for(unsigned i = 0; i < arity; i++) - sv[i] = domain[i]; - ::func_decl* d = m().mk_func_decl(name,arity,&sv[0],range); - return func_decl(*this,d); + std::vector< ::sort *> sv(arity); + for(unsigned i = 0; i < arity; i++) + sv[i] = domain[i]; + ::func_decl* d = m().mk_func_decl(name,arity,&sv[0],range); + return func_decl(*this,d); } inline func_decl context::function(char const * name, unsigned arity, sort const * domain, sort const & range) { - return function(str_symbol(name), arity, domain, range); + return function(str_symbol(name), arity, domain, range); } inline func_decl context::function(char const * name, sort const & domain, sort const & range) { - sort args[1] = { domain }; - return function(name, 1, args, range); + sort args[1] = { domain }; + return function(name, 1, args, range); } inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & range) { @@ -1201,24 +1201,24 @@ namespace Duality { } inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range) { - sort args[3] = { d1, d2, d3 }; - return function(name, 3, args, range); + sort args[3] = { d1, d2, d3 }; + return function(name, 3, args, range); } inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & range) { - sort args[4] = { d1, d2, d3, d4 }; - return function(name, 4, args, range); + sort args[4] = { d1, d2, d3, d4 }; + return function(name, 4, args, range); } inline func_decl context::function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range) { - sort args[5] = { d1, d2, d3, d4, d5 }; - return function(name, 5, args, range); + sort args[5] = { d1, d2, d3, d4, d5 }; + return function(name, 5, args, range); } inline expr context::constant(symbol const & name, sort const & s) { - ::expr *r = m().mk_const(m().mk_const_decl(name, s)); - return expr(*this, r); + ::expr *r = m().mk_const(m().mk_const_decl(name, s)); + return expr(*this, r); } inline expr context::constant(char const * name, sort const & s) { return constant(str_symbol(name), s); } inline expr context::bool_const(char const * name) { return constant(name, bool_sort()); } @@ -1227,29 +1227,29 @@ namespace Duality { inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); } inline expr func_decl::operator()(const std::vector &args) const { - return operator()(args.size(),&args[0]); + return operator()(args.size(),&args[0]); } inline expr func_decl::operator()() const { - return operator()(0,0); + return operator()(0,0); } inline expr func_decl::operator()(expr const & a) const { - return operator()(1,&a); + return operator()(1,&a); } inline expr func_decl::operator()(expr const & a1, expr const & a2) const { - expr args[2] = {a1,a2}; - return operator()(2,args); + expr args[2] = {a1,a2}; + return operator()(2,args); } inline expr func_decl::operator()(expr const & a1, expr const & a2, expr const & a3) const { - expr args[3] = {a1,a2,a3}; - return operator()(3,args); + expr args[3] = {a1,a2,a3}; + return operator()(3,args); } inline expr func_decl::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4) const { - expr args[4] = {a1,a2,a3,a4}; - return operator()(4,args); + expr args[4] = {a1,a2,a3,a4}; + return operator()(4,args); } inline expr func_decl::operator()(expr const & a1, expr const & a2, expr const & a3, expr const & a4, expr const & a5) const { - expr args[5] = {a1,a2,a3,a4,a5}; - return operator()(5,args); + expr args[5] = {a1,a2,a3,a4,a5}; + return operator()(5,args); } @@ -1257,16 +1257,16 @@ namespace Duality { inline expr store(expr const & a, expr const & i, expr const & v) { return a.ctx().make(Store,a,i,v); } inline expr forall(const std::vector &quants, const expr &body){ - return body.ctx().make_quant(Forall,quants,body); + return body.ctx().make_quant(Forall,quants,body); } inline expr exists(const std::vector &quants, const expr &body){ - return body.ctx().make_quant(Exists,quants,body); + return body.ctx().make_quant(Exists,quants,body); } inline expr context::int_val(int n){ - :: sort *r = m().mk_sort(m_arith_fid, INT_SORT); - return cook(m_arith_util.mk_numeral(rational(n),r)); + :: sort *r = m().mk_sort(m_arith_fid, INT_SORT); + return cook(m_arith_util.mk_numeral(rational(n),r)); } @@ -1276,56 +1276,56 @@ namespace Duality { class TermTree { public: - TermTree(expr _term){ - term = _term; - } + TermTree(expr _term){ + term = _term; + } - TermTree(expr _term, const std::vector &_children){ - term = _term; - children = _children; - } + TermTree(expr _term, const std::vector &_children){ + term = _term; + children = _children; + } - inline expr getTerm(){return term;} + inline expr getTerm(){return term;} - inline std::vector &getTerms(){return terms;} + inline std::vector &getTerms(){return terms;} - inline std::vector &getChildren(){ - return children; - } + inline std::vector &getChildren(){ + return children; + } - inline int number(int from){ - for(unsigned i = 0; i < children.size(); i++) - from = children[i]->number(from); - num = from; - return from + 1; - } + inline int number(int from){ + for(unsigned i = 0; i < children.size(); i++) + from = children[i]->number(from); + num = from; + return from + 1; + } - inline int getNumber(){ - return num; - } + inline int getNumber(){ + return num; + } - inline void setTerm(expr t){term = t;} + inline void setTerm(expr t){term = t;} - inline void addTerm(expr t){terms.push_back(t);} + inline void addTerm(expr t){terms.push_back(t);} - inline void setChildren(const std::vector & _children){ - children = _children; - } + inline void setChildren(const std::vector & _children){ + children = _children; + } - inline void setNumber(int _num){ - num = _num; - } + inline void setNumber(int _num){ + num = _num; + } - ~TermTree(){ - for(unsigned i = 0; i < children.size(); i++) - delete children[i]; - } + ~TermTree(){ + for(unsigned i = 0; i < children.size(); i++) + delete children[i]; + } private: - expr term; - std::vector terms; - std::vector children; - int num; + expr term; + std::vector terms; + std::vector children; + int num; }; typedef context interpolating_context; @@ -1333,79 +1333,79 @@ namespace Duality { class interpolating_solver : public solver { public: interpolating_solver(context &ctx, bool models = true) - : solver(ctx, true, models) - { - weak_mode = false; - } + : solver(ctx, true, models) + { + weak_mode = false; + } public: - lbool interpolate(const std::vector &assumptions, - std::vector &interpolants, - model &_model, - literals &lits, - bool incremental - ); + lbool interpolate(const std::vector &assumptions, + std::vector &interpolants, + model &_model, + literals &lits, + bool incremental + ); - lbool interpolate_tree(TermTree *assumptions, - TermTree *&interpolants, - model &_model, - literals &lits, - bool incremental - ); + lbool interpolate_tree(TermTree *assumptions, + TermTree *&interpolants, + model &_model, + literals &lits, + bool incremental + ); - bool read_interpolation_problem(const std::string &file_name, - std::vector &assumptions, - std::vector &theory, - std::string &error_message - ); + bool read_interpolation_problem(const std::string &file_name, + std::vector &assumptions, + std::vector &theory, + std::string &error_message + ); - void write_interpolation_problem(const std::string &file_name, - const std::vector &assumptions, - const std::vector &theory - ); + void write_interpolation_problem(const std::string &file_name, + const std::vector &assumptions, + const std::vector &theory + ); - void AssertInterpolationAxiom(const expr &expr); - void RemoveInterpolationAxiom(const expr &expr); + void AssertInterpolationAxiom(const expr &expr); + void RemoveInterpolationAxiom(const expr &expr); - void SetWeakInterpolants(bool weak); - void SetPrintToFile(const std::string &file_name); + void SetWeakInterpolants(bool weak); + void SetPrintToFile(const std::string &file_name); - const std::vector &GetInterpolationAxioms() {return theory;} - const char *profile(); + const std::vector &GetInterpolationAxioms() {return theory;} + const char *profile(); private: - bool weak_mode; - std::string print_filename; - std::vector theory; + bool weak_mode; + std::string print_filename; + std::vector theory; }; inline expr context::cook(::expr *a) {return expr(*this,a);} inline std::vector context::cook(ptr_vector< ::expr> v) { - std::vector _v(v.size()); - for(unsigned i = 0; i < v.size(); i++) - _v[i] = cook(v[i]); - return _v; + std::vector _v(v.size()); + for(unsigned i = 0; i < v.size(); i++) + _v[i] = cook(v[i]); + return _v; } inline ::expr *context::uncook(const expr &a) { - m().inc_ref(a.raw()); - return to_expr(a.raw()); + m().inc_ref(a.raw()); + return to_expr(a.raw()); } inline expr context::translate(const expr &e) { - ::expr *f = to_expr(e.raw()); - if(&e.ctx().m() != &m()) // same ast manager -> no translation - throw "ast manager mismatch"; - return cook(f); + ::expr *f = to_expr(e.raw()); + if(&e.ctx().m() != &m()) // same ast manager -> no translation + throw "ast manager mismatch"; + return cook(f); } inline func_decl context::translate(const func_decl &e) { - ::func_decl *f = to_func_decl(e.raw()); - if(&e.ctx().m() != &m()) // same ast manager -> no translation - throw "ast manager mismatch"; - return func_decl(*this,f); + ::func_decl *f = to_func_decl(e.raw()); + if(&e.ctx().m() != &m()) // same ast manager -> no translation + throw "ast manager mismatch"; + return func_decl(*this,f); } typedef double clock_t; @@ -1414,78 +1414,78 @@ namespace Duality { template class uptr { public: - X *ptr; - uptr(){ptr = 0;} - void set(X *_ptr){ - if(ptr) delete ptr; - ptr = _ptr; - } - X *get(){ return ptr;} - ~uptr(){ - if(ptr) delete ptr; - } + X *ptr; + uptr(){ptr = 0;} + void set(X *_ptr){ + if(ptr) delete ptr; + ptr = _ptr; + } + X *get(){ return ptr;} + ~uptr(){ + if(ptr) delete ptr; + } }; }; // to make Duality::ast hashable namespace hash_space { - template <> - class hash { - public: - size_t operator()(const Duality::ast &s) const { - return s.raw()->get_id(); - } - }; + template <> + class hash { + public: + size_t operator()(const Duality::ast &s) const { + return s.raw()->get_id(); + } + }; } // to make Duality::ast usable in ordered collections namespace std { - template <> - class less { - public: - bool operator()(const Duality::ast &s, const Duality::ast &t) const { - // return s.raw() < t.raw(); - return s.raw()->get_id() < t.raw()->get_id(); - } - }; + template <> + class less { + public: + bool operator()(const Duality::ast &s, const Duality::ast &t) const { + // return s.raw() < t.raw(); + return s.raw()->get_id() < t.raw()->get_id(); + } + }; } // to make Duality::ast usable in ordered collections namespace std { - template <> - class less { - public: - bool operator()(const Duality::expr &s, const Duality::expr &t) const { - // return s.raw() < t.raw(); - return s.raw()->get_id() < t.raw()->get_id(); - } - }; + template <> + class less { + public: + bool operator()(const Duality::expr &s, const Duality::expr &t) const { + // return s.raw() < t.raw(); + return s.raw()->get_id() < t.raw()->get_id(); + } + }; } // to make Duality::func_decl hashable namespace hash_space { - template <> - class hash { - public: - size_t operator()(const Duality::func_decl &s) const { - return s.raw()->get_id(); - } - }; + template <> + class hash { + public: + size_t operator()(const Duality::func_decl &s) const { + return s.raw()->get_id(); + } + }; } // to make Duality::func_decl usable in ordered collections namespace std { - template <> - class less { - public: - bool operator()(const Duality::func_decl &s, const Duality::func_decl &t) const { - // return s.raw() < t.raw(); - return s.raw()->get_id() < t.raw()->get_id(); - } - }; + template <> + class less { + public: + bool operator()(const Duality::func_decl &s, const Duality::func_decl &t) const { + // return s.raw() < t.raw(); + return s.raw()->get_id() < t.raw()->get_id(); + } + }; } #endif diff --git a/src/interp/foci2.h b/src/interp/foci2.h index 0aa787c54..bd968f11e 100755 --- a/src/interp/foci2.h +++ b/src/interp/foci2.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - foci2.h + foci2.h -Abstract: + Abstract: - An interface class for foci2. + An interface class for foci2. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef FOCI2_H #define FOCI2_H @@ -31,45 +31,45 @@ Revision History: class foci2 { public: - virtual ~foci2(){} + virtual ~foci2(){} - typedef int ast; - typedef int symb; + typedef int ast; + typedef int symb; - /** Built-in operators */ - enum ops { - And = 0, Or, Not, Iff, Ite, Equal, Plus, Times, Floor, Leq, Div, Bool, Int, Array, Tsym, Fsym, Forall, Exists, Distinct, LastOp - }; + /** Built-in operators */ + enum ops { + And = 0, Or, Not, Iff, Ite, Equal, Plus, Times, Floor, Leq, Div, Bool, Int, Array, Tsym, Fsym, Forall, Exists, Distinct, LastOp + }; - virtual symb mk_func(const std::string &s) = 0; - virtual symb mk_pred(const std::string &s) = 0; - virtual ast mk_op(ops op, const std::vector args) = 0; - virtual ast mk_op(ops op, ast) = 0; - virtual ast mk_op(ops op, ast, ast) = 0; - virtual ast mk_op(ops op, ast, ast, ast) = 0; - virtual ast mk_int(const std::string &) = 0; - virtual ast mk_rat(const std::string &) = 0; - virtual ast mk_true() = 0; - virtual ast mk_false() = 0; - virtual ast mk_app(symb,const std::vector args) = 0; + virtual symb mk_func(const std::string &s) = 0; + virtual symb mk_pred(const std::string &s) = 0; + virtual ast mk_op(ops op, const std::vector args) = 0; + virtual ast mk_op(ops op, ast) = 0; + virtual ast mk_op(ops op, ast, ast) = 0; + virtual ast mk_op(ops op, ast, ast, ast) = 0; + virtual ast mk_int(const std::string &) = 0; + virtual ast mk_rat(const std::string &) = 0; + virtual ast mk_true() = 0; + virtual ast mk_false() = 0; + virtual ast mk_app(symb,const std::vector args) = 0; - virtual bool get_func(ast, symb &) = 0; - virtual bool get_pred(ast, symb &) = 0; - virtual bool get_op(ast, ops &) = 0; - virtual bool get_true(ast id) = 0; - virtual bool get_false(ast id) = 0; - virtual bool get_int(ast id, std::string &res) = 0; - virtual bool get_rat(ast id, std::string &res) = 0; - virtual const std::string &get_symb(symb) = 0; + virtual bool get_func(ast, symb &) = 0; + virtual bool get_pred(ast, symb &) = 0; + virtual bool get_op(ast, ops &) = 0; + virtual bool get_true(ast id) = 0; + virtual bool get_false(ast id) = 0; + virtual bool get_int(ast id, std::string &res) = 0; + virtual bool get_rat(ast id, std::string &res) = 0; + virtual const std::string &get_symb(symb) = 0; - virtual int get_num_args(ast) = 0; - virtual ast get_arg(ast, int) = 0; + virtual int get_num_args(ast) = 0; + virtual ast get_arg(ast, int) = 0; - virtual void show_ast(ast) = 0; + virtual void show_ast(ast) = 0; - virtual bool interpolate(const std::vector &frames, std::vector &itps, std::vector parents) = 0; + virtual bool interpolate(const std::vector &frames, std::vector &itps, std::vector parents) = 0; - FOCI2_EXPORT static foci2 *create(const std::string &); + FOCI2_EXPORT static foci2 *create(const std::string &); }; #endif diff --git a/src/interp/iz3base.cpp b/src/interp/iz3base.cpp index 8f98a23f9..bb4f760f5 100755 --- a/src/interp/iz3base.cpp +++ b/src/interp/iz3base.cpp @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3base.cpp + iz3base.cpp -Abstract: + Abstract: - Base class for interpolators. Includes an AST manager and a scoping - object as bases. + Base class for interpolators. Includes an AST manager and a scoping + object as bases. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -38,256 +38,256 @@ using namespace stl_ext; iz3base::range &iz3base::ast_range(ast t){ - return ast_ranges_hash[t].rng; + return ast_ranges_hash[t].rng; } iz3base::range &iz3base::sym_range(symb d){ - return sym_range_hash[d]; + return sym_range_hash[d]; } void iz3base::add_frame_range(int frame, ast t){ - range &rng = ast_range(t); - if(!in_range(frame,rng)){ - range_add(frame,rng); - for(int i = 0, n = num_args(t); i < n; ++i) - add_frame_range(frame,arg(t,i)); - if(op(t) == Uninterpreted) - range_add(frame,sym_range(sym(t))); - } + range &rng = ast_range(t); + if(!in_range(frame,rng)){ + range_add(frame,rng); + for(int i = 0, n = num_args(t); i < n; ++i) + add_frame_range(frame,arg(t,i)); + if(op(t) == Uninterpreted) + range_add(frame,sym_range(sym(t))); + } } #if 1 iz3base::range &iz3base::ast_scope(ast t){ - ranges &rngs = ast_ranges_hash[t]; - range &rng = rngs.scp; - if(!rngs.scope_computed){ // not computed yet - rng = range_full(); - for(int i = 0, n = num_args(t); i < n; ++i) - rng = range_glb(rng,ast_scope(arg(t,i))); - if(op(t) == Uninterpreted) - if(parents.empty() || num_args(t) == 0) // in tree mode, all function syms are global - rng = range_glb(rng,sym_range(sym(t))); - rngs.scope_computed = true; - } - return rng; + ranges &rngs = ast_ranges_hash[t]; + range &rng = rngs.scp; + if(!rngs.scope_computed){ // not computed yet + rng = range_full(); + for(int i = 0, n = num_args(t); i < n; ++i) + rng = range_glb(rng,ast_scope(arg(t,i))); + if(op(t) == Uninterpreted) + if(parents.empty() || num_args(t) == 0) // in tree mode, all function syms are global + rng = range_glb(rng,sym_range(sym(t))); + rngs.scope_computed = true; + } + return rng; } #else iz3base::range &iz3base::ast_scope(ast t){ - ranges &rngs = ast_ranges_hash[t]; - if(rngs.scope_computed) return rngs.scp; - range rng = range_full(); - for(int i = 0, n = num_args(t); i < n; ++i) - rng = range_glb(rng,ast_scope(arg(t,i))); - if(op(t) == Uninterpreted) - if(parents.empty() || num_args(t) == 0) // in tree mode, all function syms are global - rng = range_glb(rng,sym_range(sym(t))); - rngs = ast_ranges_hash[t]; - rngs.scope_computed = true; - rngs.scp = rng; - return rngs.scp; + ranges &rngs = ast_ranges_hash[t]; + if(rngs.scope_computed) return rngs.scp; + range rng = range_full(); + for(int i = 0, n = num_args(t); i < n; ++i) + rng = range_glb(rng,ast_scope(arg(t,i))); + if(op(t) == Uninterpreted) + if(parents.empty() || num_args(t) == 0) // in tree mode, all function syms are global + rng = range_glb(rng,sym_range(sym(t))); + rngs = ast_ranges_hash[t]; + rngs.scope_computed = true; + rngs.scp = rng; + return rngs.scp; } #endif void iz3base::print(const std::string &filename){ - ast t = make(And,cnsts); - std::ofstream f(filename.c_str()); - print_sat_problem(f,t); - f.close(); + ast t = make(And,cnsts); + std::ofstream f(filename.c_str()); + print_sat_problem(f,t); + f.close(); } void iz3base::gather_conjuncts_rec(ast n, std::vector &conjuncts, stl_ext::hash_set &memo){ - if(memo.find(n) == memo.end()){ - memo.insert(n); - if(op(n) == And){ - int nargs = num_args(n); - for(int i = 0; i < nargs; i++) - gather_conjuncts_rec(arg(n,i),conjuncts,memo); + if(memo.find(n) == memo.end()){ + memo.insert(n); + if(op(n) == And){ + int nargs = num_args(n); + for(int i = 0; i < nargs; i++) + gather_conjuncts_rec(arg(n,i),conjuncts,memo); + } + else + conjuncts.push_back(n); } - else - conjuncts.push_back(n); - } } void iz3base::gather_conjuncts(ast n, std::vector &conjuncts){ - hash_set memo; - gather_conjuncts_rec(n,conjuncts,memo); + hash_set memo; + gather_conjuncts_rec(n,conjuncts,memo); } bool iz3base::is_literal(ast n){ - if(is_not(n))n = arg(n,0); - if(is_true(n) || is_false(n)) return false; - if(op(n) == And) return false; - return true; + if(is_not(n))n = arg(n,0); + if(is_true(n) || is_false(n)) return false; + if(op(n) == And) return false; + return true; } iz3base::ast iz3base::simplify_and(std::vector &conjuncts){ - hash_set memo; - for(unsigned i = 0; i < conjuncts.size(); i++){ - if(is_false(conjuncts[i])) - return conjuncts[i]; - if(is_true(conjuncts[i]) || memo.find(conjuncts[i]) != memo.end()){ - std::swap(conjuncts[i],conjuncts.back()); - conjuncts.pop_back(); + hash_set memo; + for(unsigned i = 0; i < conjuncts.size(); i++){ + if(is_false(conjuncts[i])) + return conjuncts[i]; + if(is_true(conjuncts[i]) || memo.find(conjuncts[i]) != memo.end()){ + std::swap(conjuncts[i],conjuncts.back()); + conjuncts.pop_back(); + } + else if(memo.find(mk_not(conjuncts[i])) != memo.end()) + return mk_false(); // contradiction! + else + memo.insert(conjuncts[i]); } - else if(memo.find(mk_not(conjuncts[i])) != memo.end()) - return mk_false(); // contradiction! - else - memo.insert(conjuncts[i]); - } - if(conjuncts.empty())return mk_true(); - return make(And,conjuncts); + if(conjuncts.empty())return mk_true(); + return make(And,conjuncts); } iz3base::ast iz3base::simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map &memo, int depth){ - if(is_not(n))return mk_not(simplify_with_lit_rec(mk_not(n),lit,memo,depth)); - if(n == lit) return mk_true(); - ast not_lit = mk_not(lit); - if(n == not_lit) return mk_false(); - if(op(n) != And || depth <= 0) return n; - std::pair foo(n,ast()); - std::pair::iterator,bool> bar = memo.insert(foo); - ast &res = bar.first->second; - if(!bar.second) return res; - int nargs = num_args(n); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = simplify_with_lit_rec(arg(n,i),lit,memo,depth-1); - res = simplify_and(args); - return res; + if(is_not(n))return mk_not(simplify_with_lit_rec(mk_not(n),lit,memo,depth)); + if(n == lit) return mk_true(); + ast not_lit = mk_not(lit); + if(n == not_lit) return mk_false(); + if(op(n) != And || depth <= 0) return n; + std::pair foo(n,ast()); + std::pair::iterator,bool> bar = memo.insert(foo); + ast &res = bar.first->second; + if(!bar.second) return res; + int nargs = num_args(n); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = simplify_with_lit_rec(arg(n,i),lit,memo,depth-1); + res = simplify_and(args); + return res; } iz3base::ast iz3base::simplify_with_lit(ast n, ast lit){ - hash_map memo; - return simplify_with_lit_rec(n,lit,memo,1); + hash_map memo; + return simplify_with_lit_rec(n,lit,memo,1); } iz3base::ast iz3base::simplify(ast n){ - if(is_not(n)) return mk_not(simplify(mk_not(n))); - std::pair memo_obj(n,ast()); - std::pair::iterator,bool> memo = simplify_memo.insert(memo_obj); - ast &res = memo.first->second; - if(!memo.second) return res; - switch(op(n)){ - case And: { - std::vector conjuncts; - gather_conjuncts(n,conjuncts); - for(unsigned i = 0; i < conjuncts.size(); i++) - conjuncts[i] = simplify(conjuncts[i]); + if(is_not(n)) return mk_not(simplify(mk_not(n))); + std::pair memo_obj(n,ast()); + std::pair::iterator,bool> memo = simplify_memo.insert(memo_obj); + ast &res = memo.first->second; + if(!memo.second) return res; + switch(op(n)){ + case And: { + std::vector conjuncts; + gather_conjuncts(n,conjuncts); + for(unsigned i = 0; i < conjuncts.size(); i++) + conjuncts[i] = simplify(conjuncts[i]); #if 0 - for(unsigned i = 0; i < conjuncts.size(); i++) - if(is_literal(conjuncts[i])) - for(unsigned j = 0; j < conjuncts.size(); j++) - if(j != i) - conjuncts[j] = simplify_with_lit(conjuncts[j],conjuncts[i]); + for(unsigned i = 0; i < conjuncts.size(); i++) + if(is_literal(conjuncts[i])) + for(unsigned j = 0; j < conjuncts.size(); j++) + if(j != i) + conjuncts[j] = simplify_with_lit(conjuncts[j],conjuncts[i]); #endif - res = simplify_and(conjuncts); - } - break; - case Equal: { - ast x = arg(n,0); - ast y = arg(n,1); - if(ast_id(x) > ast_id(y)) - std::swap(x,y); - res = make(Equal,x,y); - break; - } - default: - res = n; - } - return res; + res = simplify_and(conjuncts); + } + break; + case Equal: { + ast x = arg(n,0); + ast y = arg(n,1); + if(ast_id(x) > ast_id(y)) + std::swap(x,y); + res = make(Equal,x,y); + break; + } + default: + res = n; + } + return res; } void iz3base::initialize(const std::vector &_parts, const std::vector &_parents, const std::vector &_theory){ - cnsts = _parts; - theory = _theory; - for(unsigned i = 0; i < cnsts.size(); i++) - add_frame_range(i, cnsts[i]); - for(unsigned i = 0; i < _theory.size(); i++){ - add_frame_range(SHRT_MIN, _theory[i]); - add_frame_range(SHRT_MAX, _theory[i]); - } - for(unsigned i = 0; i < cnsts.size(); i++) - frame_map[cnsts[i]] = i; - for(unsigned i = 0; i < theory.size(); i++) - frame_map[theory[i]] = INT_MAX; + cnsts = _parts; + theory = _theory; + for(unsigned i = 0; i < cnsts.size(); i++) + add_frame_range(i, cnsts[i]); + for(unsigned i = 0; i < _theory.size(); i++){ + add_frame_range(SHRT_MIN, _theory[i]); + add_frame_range(SHRT_MAX, _theory[i]); + } + for(unsigned i = 0; i < cnsts.size(); i++) + frame_map[cnsts[i]] = i; + for(unsigned i = 0; i < theory.size(); i++) + frame_map[theory[i]] = INT_MAX; } void iz3base::initialize(const std::vector > &_parts, const std::vector &_parents, const std::vector &_theory){ - cnsts.resize(_parts.size()); - theory = _theory; - for(unsigned i = 0; i < _parts.size(); i++) - for(unsigned j = 0; j < _parts[i].size(); j++){ - cnsts[i] = make(And,_parts[i]); - add_frame_range(i, _parts[i][j]); - frame_map[_parts[i][j]] = i; - } - for(unsigned i = 0; i < _theory.size(); i++){ - add_frame_range(SHRT_MIN, _theory[i]); - add_frame_range(SHRT_MAX, _theory[i]); - frame_map[theory[i]] = INT_MAX; - } + cnsts.resize(_parts.size()); + theory = _theory; + for(unsigned i = 0; i < _parts.size(); i++) + for(unsigned j = 0; j < _parts[i].size(); j++){ + cnsts[i] = make(And,_parts[i]); + add_frame_range(i, _parts[i][j]); + frame_map[_parts[i][j]] = i; + } + for(unsigned i = 0; i < _theory.size(); i++){ + add_frame_range(SHRT_MIN, _theory[i]); + add_frame_range(SHRT_MAX, _theory[i]); + frame_map[theory[i]] = INT_MAX; + } } void iz3base::check_interp(const std::vector &itps, std::vector &theory){ #if 0 - Z3_config config = Z3_mk_config(); - Z3_context vctx = Z3_mk_context(config); - int frames = cnsts.size(); - std::vector foocnsts(cnsts); - for(unsigned i = 0; i < frames; i++) - foocnsts[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),cnsts[i]); - Z3_write_interpolation_problem(ctx,frames,&foocnsts[0],0, "temp_lemma.smt", theory.size(), &theory[0]); - int vframes,*vparents; - Z3_ast *vcnsts; - const char *verror; - bool ok = Z3_read_interpolation_problem(vctx,&vframes,&vcnsts,0,"temp_lemma.smt",&verror); - assert(ok); - std::vector vvcnsts(vframes); - std::copy(vcnsts,vcnsts+vframes,vvcnsts.begin()); - std::vector vitps(itps.size()); - for(unsigned i = 0; i < itps.size(); i++) - vitps[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),itps[i]); - Z3_write_interpolation_problem(ctx,itps.size(),&vitps[0],0,"temp_interp.smt"); - int iframes,*iparents; - Z3_ast *icnsts; - const char *ierror; - ok = Z3_read_interpolation_problem(vctx,&iframes,&icnsts,0,"temp_interp.smt",&ierror); - assert(ok); - const char *error = 0; - bool iok = Z3_check_interpolant(vctx, frames, &vvcnsts[0], parents.size() ? &parents[0] : 0, icnsts, &error); - assert(iok); + Z3_config config = Z3_mk_config(); + Z3_context vctx = Z3_mk_context(config); + int frames = cnsts.size(); + std::vector foocnsts(cnsts); + for(unsigned i = 0; i < frames; i++) + foocnsts[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),cnsts[i]); + Z3_write_interpolation_problem(ctx,frames,&foocnsts[0],0, "temp_lemma.smt", theory.size(), &theory[0]); + int vframes,*vparents; + Z3_ast *vcnsts; + const char *verror; + bool ok = Z3_read_interpolation_problem(vctx,&vframes,&vcnsts,0,"temp_lemma.smt",&verror); + assert(ok); + std::vector vvcnsts(vframes); + std::copy(vcnsts,vcnsts+vframes,vvcnsts.begin()); + std::vector vitps(itps.size()); + for(unsigned i = 0; i < itps.size(); i++) + vitps[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),itps[i]); + Z3_write_interpolation_problem(ctx,itps.size(),&vitps[0],0,"temp_interp.smt"); + int iframes,*iparents; + Z3_ast *icnsts; + const char *ierror; + ok = Z3_read_interpolation_problem(vctx,&iframes,&icnsts,0,"temp_interp.smt",&ierror); + assert(ok); + const char *error = 0; + bool iok = Z3_check_interpolant(vctx, frames, &vvcnsts[0], parents.size() ? &parents[0] : 0, icnsts, &error); + assert(iok); #endif } bool iz3base::is_sat(const std::vector &q, ast &_proof, std::vector &vars){ - params_ref p; - p.set_bool("proof", true); // this is currently useless - p.set_bool("model", true); - p.set_bool("unsat_core", true); - scoped_ptr sf = mk_smt_solver_factory(); - ::solver *m_solver = (*sf)(m(), p, true, true, true, ::symbol::null); - ::solver &s = *m_solver; + params_ref p; + p.set_bool("proof", true); // this is currently useless + p.set_bool("model", true); + p.set_bool("unsat_core", true); + scoped_ptr sf = mk_smt_solver_factory(); + ::solver *m_solver = (*sf)(m(), p, true, true, true, ::symbol::null); + ::solver &s = *m_solver; - for(unsigned i = 0; i < q.size(); i++) - s.assert_expr(to_expr(q[i].raw())); - lbool res = s.check_sat(0,0); - if(res == l_false){ - ::ast *proof = s.get_proof(); - _proof = cook(proof); - } - else if(vars.size()) { - model_ref(_m); - s.get_model(_m); - for(unsigned i = 0; i < vars.size(); i++){ - expr_ref r(m()); - _m.get()->eval(to_expr(vars[i].raw()),r,true); - vars[i] = cook(r.get()); + for(unsigned i = 0; i < q.size(); i++) + s.assert_expr(to_expr(q[i].raw())); + lbool res = s.check_sat(0,0); + if(res == l_false){ + ::ast *proof = s.get_proof(); + _proof = cook(proof); } - } - dealloc(m_solver); - return res != l_false; + else if(vars.size()) { + model_ref(_m); + s.get_model(_m); + for(unsigned i = 0; i < vars.size(); i++){ + expr_ref r(m()); + _m.get()->eval(to_expr(vars[i].raw()),r,true); + vars[i] = cook(r.get()); + } + } + dealloc(m_solver); + return res != l_false; } @@ -300,39 +300,39 @@ void iz3base::find_children(const stl_ext::hash_set &cnsts_set, std::vector &pos_map, bool merge ){ - std::vector my_children; - std::vector my_conjuncts; - if(op(tree) == Interp){ // if we've hit an interpolation position... - find_children(cnsts_set,arg(tree,0),cnsts,parents,my_conjuncts,my_children,pos_map,merge); - if(my_conjuncts.empty()) - my_conjuncts.push_back(mk_true()); // need at least one conjunct - int root = cnsts.size() + my_conjuncts.size() - 1; - for(unsigned i = 0; i < my_conjuncts.size(); i++){ - parents.push_back(root); - cnsts.push_back(my_conjuncts[i]); + std::vector my_children; + std::vector my_conjuncts; + if(op(tree) == Interp){ // if we've hit an interpolation position... + find_children(cnsts_set,arg(tree,0),cnsts,parents,my_conjuncts,my_children,pos_map,merge); + if(my_conjuncts.empty()) + my_conjuncts.push_back(mk_true()); // need at least one conjunct + int root = cnsts.size() + my_conjuncts.size() - 1; + for(unsigned i = 0; i < my_conjuncts.size(); i++){ + parents.push_back(root); + cnsts.push_back(my_conjuncts[i]); + } + for(unsigned i = 0; i < my_children.size(); i++) + parents[my_children[i]] = root; + children.push_back(root); + pos_map.push_back(root); } - for(unsigned i = 0; i < my_children.size(); i++) - parents[my_children[i]] = root; - children.push_back(root); - pos_map.push_back(root); - } - else { - if(op(tree) == And){ - int nargs = num_args(tree); - for(int i = 0; i < nargs; i++) - find_children(cnsts_set,arg(tree,i),cnsts,parents,my_conjuncts,my_children,pos_map,merge); + else { + if(op(tree) == And){ + int nargs = num_args(tree); + for(int i = 0; i < nargs; i++) + find_children(cnsts_set,arg(tree,i),cnsts,parents,my_conjuncts,my_children,pos_map,merge); + } + if(cnsts_set.find(tree) != cnsts_set.end()){ + if(merge && !my_conjuncts.empty()) + my_conjuncts.back() = mk_and(my_conjuncts.back(),tree); + else + my_conjuncts.push_back(tree); + } + for(unsigned i = 0; i < my_children.size(); i++) + children.push_back(my_children[i]); + for(unsigned i = 0; i < my_conjuncts.size(); i++) + conjuncts.push_back(my_conjuncts[i]); } - if(cnsts_set.find(tree) != cnsts_set.end()){ - if(merge && !my_conjuncts.empty()) - my_conjuncts.back() = mk_and(my_conjuncts.back(),tree); - else - my_conjuncts.push_back(tree); - } - for(unsigned i = 0; i < my_children.size(); i++) - children.push_back(my_children[i]); - for(unsigned i = 0; i < my_conjuncts.size(); i++) - conjuncts.push_back(my_conjuncts[i]); - } } void iz3base::to_parents_vec_representation(const std::vector &_cnsts, @@ -343,23 +343,23 @@ void iz3base::to_parents_vec_representation(const std::vector &_cnsts, std::vector &pos_map, bool merge ){ - std::vector my_children; - std::vector my_conjuncts; - hash_set cnsts_set; - for(unsigned i = 0; i < _cnsts.size(); i++) - cnsts_set.insert(_cnsts[i]); - ast _tree = (op(tree) != Interp) ? make(Interp,tree) : tree; - find_children(cnsts_set,_tree,cnsts,parents,my_conjuncts,my_children,pos_map,merge); - if(op(tree) != Interp) pos_map.pop_back(); - parents[parents.size()-1] = SHRT_MAX; + std::vector my_children; + std::vector my_conjuncts; + hash_set cnsts_set; + for(unsigned i = 0; i < _cnsts.size(); i++) + cnsts_set.insert(_cnsts[i]); + ast _tree = (op(tree) != Interp) ? make(Interp,tree) : tree; + find_children(cnsts_set,_tree,cnsts,parents,my_conjuncts,my_children,pos_map,merge); + if(op(tree) != Interp) pos_map.pop_back(); + parents[parents.size()-1] = SHRT_MAX; - // rest of the constraints are the background theory + // rest of the constraints are the background theory - hash_set used_set; - for(unsigned i = 0; i < cnsts.size(); i++) - used_set.insert(cnsts[i]); - for(unsigned i = 0; i < _cnsts.size(); i++) - if(used_set.find(_cnsts[i]) == used_set.end()) - theory.push_back(_cnsts[i]); + hash_set used_set; + for(unsigned i = 0; i < cnsts.size(); i++) + used_set.insert(cnsts[i]); + for(unsigned i = 0; i < _cnsts.size(); i++) + if(used_set.find(_cnsts[i]) == used_set.end()) + theory.push_back(_cnsts[i]); } diff --git a/src/interp/iz3base.h b/src/interp/iz3base.h index 956191290..76ed6e3e2 100755 --- a/src/interp/iz3base.h +++ b/src/interp/iz3base.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3base.h + iz3base.h -Abstract: + Abstract: - Base class for interpolators. Includes an AST manager and a scoping - object as bases. + Base class for interpolators. Includes an AST manager and a scoping + object as bases. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3BASE_H #define IZ3BASE_H @@ -25,13 +25,13 @@ Revision History: #include "iz3scopes.h" namespace hash_space { - template <> - class hash { - public: - size_t operator()(func_decl * const &s) const { - return (size_t) s; - } - }; + template <> + class hash { + public: + size_t operator()(func_decl * const &s) const { + return (size_t) s; + } + }; } /* Base class for interpolators. Includes an AST manager and a scoping @@ -41,152 +41,152 @@ class iz3base : public iz3mgr, public scopes { public: - /** Get the range in which an expression occurs. This is the - smallest subtree containing all occurrences of the - expression. */ - range &ast_range(ast); + /** Get the range in which an expression occurs. This is the + smallest subtree containing all occurrences of the + expression. */ + range &ast_range(ast); - /** Get the scope of an expression. This is the set of tree nodes in - which all of the expression's symbols are in scope. */ - range &ast_scope(ast); + /** Get the scope of an expression. This is the set of tree nodes in + which all of the expression's symbols are in scope. */ + range &ast_scope(ast); - /** Get the range of a symbol. This is the smallest subtree containing - all occurrences of the symbol. */ - range &sym_range(symb); + /** Get the range of a symbol. This is the smallest subtree containing + all occurrences of the symbol. */ + range &sym_range(symb); - /** Is an expression local (in scope in some frame)? */ + /** Is an expression local (in scope in some frame)? */ - bool is_local(ast node){ - return !range_is_empty(ast_scope(node)); - } + bool is_local(ast node){ + return !range_is_empty(ast_scope(node)); + } - /** Simplify an expression */ + /** Simplify an expression */ - ast simplify(ast); + ast simplify(ast); - /** Constructor */ + /** Constructor */ - iz3base(ast_manager &_m_manager, + iz3base(ast_manager &_m_manager, const std::vector &_cnsts, const std::vector &_parents, const std::vector &_theory) - : iz3mgr(_m_manager), scopes(_parents) { - initialize(_cnsts,_parents,_theory); - weak = false; - } + : iz3mgr(_m_manager), scopes(_parents) { + initialize(_cnsts,_parents,_theory); + weak = false; + } - iz3base(const iz3mgr& other, + iz3base(const iz3mgr& other, const std::vector &_cnsts, const std::vector &_parents, const std::vector &_theory) - : iz3mgr(other), scopes(_parents) { - initialize(_cnsts,_parents,_theory); - weak = false; - } + : iz3mgr(other), scopes(_parents) { + initialize(_cnsts,_parents,_theory); + weak = false; + } - iz3base(const iz3mgr& other, - const std::vector > &_cnsts, + iz3base(const iz3mgr& other, + const std::vector > &_cnsts, const std::vector &_parents, const std::vector &_theory) - : iz3mgr(other), scopes(_parents) { - initialize(_cnsts,_parents,_theory); - weak = false; - } + : iz3mgr(other), scopes(_parents) { + initialize(_cnsts,_parents,_theory); + weak = false; + } - iz3base(const iz3mgr& other) - : iz3mgr(other), scopes() { - weak = false; - } + iz3base(const iz3mgr& other) + : iz3mgr(other), scopes() { + weak = false; + } - /* Set our options */ - void set_option(const std::string &name, const std::string &value){ - if(name == "weak" && value == "1") weak = true; - } + /* Set our options */ + void set_option(const std::string &name, const std::string &value){ + if(name == "weak" && value == "1") weak = true; + } - /* Are we doing weak interpolants? */ - bool weak_mode(){return weak;} + /* Are we doing weak interpolants? */ + bool weak_mode(){return weak;} - /** Print interpolation problem to an SMTLIB format file */ - void print(const std::string &filename); + /** Print interpolation problem to an SMTLIB format file */ + void print(const std::string &filename); - /** Check correctness of a solutino to this problem. */ - void check_interp(const std::vector &itps, std::vector &theory); + /** Check correctness of a solutino to this problem. */ + void check_interp(const std::vector &itps, std::vector &theory); - /** For convenience -- is this formula SAT? */ - bool is_sat(const std::vector &consts, ast &_proof, std::vector &vars); + /** For convenience -- is this formula SAT? */ + bool is_sat(const std::vector &consts, ast &_proof, std::vector &vars); - /** Interpolator for clauses, to be implemented */ - virtual void interpolate_clause(std::vector &lits, std::vector &itps){ - throw "no interpolator"; - } + /** Interpolator for clauses, to be implemented */ + virtual void interpolate_clause(std::vector &lits, std::vector &itps){ + throw "no interpolator"; + } - ast get_proof_check_assump(range &rng){ - std::vector cs(theory); - cs.push_back(cnsts[rng.hi]); - return make(And,cs); - } + ast get_proof_check_assump(range &rng){ + std::vector cs(theory); + cs.push_back(cnsts[rng.hi]); + return make(And,cs); + } - int frame_of_assertion(const ast &ass){ - stl_ext::hash_map::iterator it = frame_map.find(ass); - if(it == frame_map.end()) - throw "unknown assertion"; - return it->second; - } + int frame_of_assertion(const ast &ass){ + stl_ext::hash_map::iterator it = frame_map.find(ass); + if(it == frame_map.end()) + throw "unknown assertion"; + return it->second; + } - void to_parents_vec_representation(const std::vector &_cnsts, - const ast &tree, - std::vector &cnsts, - std::vector &parents, - std::vector &theory, - std::vector &pos_map, - bool merge = false - ); + void to_parents_vec_representation(const std::vector &_cnsts, + const ast &tree, + std::vector &cnsts, + std::vector &parents, + std::vector &theory, + std::vector &pos_map, + bool merge = false + ); protected: - std::vector cnsts; - std::vector theory; + std::vector cnsts; + std::vector theory; private: - struct ranges { - range rng; - range scp; - bool scope_computed; - ranges(){scope_computed = false;} - }; + struct ranges { + range rng; + range scp; + bool scope_computed; + ranges(){scope_computed = false;} + }; - stl_ext::hash_map sym_range_hash; - stl_ext::hash_map ast_ranges_hash; - stl_ext::hash_map simplify_memo; - stl_ext::hash_map frame_map; // map assertions to frames + stl_ext::hash_map sym_range_hash; + stl_ext::hash_map ast_ranges_hash; + stl_ext::hash_map simplify_memo; + stl_ext::hash_map frame_map; // map assertions to frames - // int frames; // number of frames + // int frames; // number of frames protected: - void add_frame_range(int frame, ast t); + void add_frame_range(int frame, ast t); private: - void initialize(const std::vector &_parts, const std::vector &_parents, const std::vector &_theory); + void initialize(const std::vector &_parts, const std::vector &_parents, const std::vector &_theory); - void initialize(const std::vector > &_parts, const std::vector &_parents, const std::vector &_theory); + void initialize(const std::vector > &_parts, const std::vector &_parents, const std::vector &_theory); - bool is_literal(ast n); - void gather_conjuncts_rec(ast n, std::vector &conjuncts, stl_ext::hash_set &memo); - void gather_conjuncts(ast n, std::vector &conjuncts); - ast simplify_and(std::vector &conjuncts); - ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map &memo, int depth); - ast simplify_with_lit(ast n, ast lit); - void find_children(const stl_ext::hash_set &cnsts_set, - const ast &tree, - std::vector &cnsts, - std::vector &parents, - std::vector &conjuncts, - std::vector &children, - std::vector &pos_map, - bool merge - ); - bool weak; + bool is_literal(ast n); + void gather_conjuncts_rec(ast n, std::vector &conjuncts, stl_ext::hash_set &memo); + void gather_conjuncts(ast n, std::vector &conjuncts); + ast simplify_and(std::vector &conjuncts); + ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map &memo, int depth); + ast simplify_with_lit(ast n, ast lit); + void find_children(const stl_ext::hash_set &cnsts_set, + const ast &tree, + std::vector &cnsts, + std::vector &parents, + std::vector &conjuncts, + std::vector &children, + std::vector &pos_map, + bool merge + ); + bool weak; }; diff --git a/src/interp/iz3checker.cpp b/src/interp/iz3checker.cpp index 223be0223..480e85274 100755 --- a/src/interp/iz3checker.cpp +++ b/src/interp/iz3checker.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3checker.cpp + iz3checker.cpp -Abstract: + Abstract: - check correctness of interpolant + check correctness of interpolant -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -40,154 +40,154 @@ using namespace stl_ext; struct iz3checker : iz3base { - /* HACK: for tree interpolants, we assume that uninterpreted functions - are global. This is because in the current state of the tree interpolation - code, symbols that appear in sibling sub-trees have to be global, and - we have no way to eliminate such function symbols. When tree interpoaltion is - fixed, we can tree function symbols the same as constant symbols. */ + /* HACK: for tree interpolants, we assume that uninterpreted functions + are global. This is because in the current state of the tree interpolation + code, symbols that appear in sibling sub-trees have to be global, and + we have no way to eliminate such function symbols. When tree interpoaltion is + fixed, we can tree function symbols the same as constant symbols. */ - bool is_tree; + bool is_tree; - void support(const ast &t, std::set &res, hash_set &memo){ - if(memo.find(t) != memo.end()) return; - memo.insert(t); + void support(const ast &t, std::set &res, hash_set &memo){ + if(memo.find(t) != memo.end()) return; + memo.insert(t); - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - support(arg(t,i),res,memo); + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + support(arg(t,i),res,memo); - switch(op(t)){ - case Uninterpreted: - if(nargs == 0 || !is_tree) { - std::string name = string_of_symbol(sym(t)); - res.insert(name); - } - break; - case Forall: - case Exists: - support(get_quantifier_body(t),res,memo); - break; - default:; + switch(op(t)){ + case Uninterpreted: + if(nargs == 0 || !is_tree) { + std::string name = string_of_symbol(sym(t)); + res.insert(name); + } + break; + case Forall: + case Exists: + support(get_quantifier_body(t),res,memo); + break; + default:; + } } - } - bool check(solver *s, std::ostream &err, - const std::vector &cnsts, - const std::vector &parents, - const std::vector &itp, - const std::vector &theory){ + bool check(solver *s, std::ostream &err, + const std::vector &cnsts, + const std::vector &parents, + const std::vector &itp, + const std::vector &theory){ - is_tree = !parents.empty(); - int num = cnsts.size(); - std::vector > children(num); + is_tree = !parents.empty(); + int num = cnsts.size(); + std::vector > children(num); - for(int i = 0; i < num-1; i++){ - if(parents.size()) - children[parents[i]].push_back(i); - else - children[i+1].push_back(i); - } + for(int i = 0; i < num-1; i++){ + if(parents.size()) + children[parents[i]].push_back(i); + else + children[i+1].push_back(i); + } - for(int i = 0; i < num; i++){ - s->push(); - for(unsigned j = 0; j < theory.size(); j++) - s->assert_expr(to_expr(theory[j].raw())); - s->assert_expr(to_expr(cnsts[i].raw())); - std::vector &cs = children[i]; - for(unsigned j = 0; j < cs.size(); j++) - s->assert_expr(to_expr(itp[cs[j]].raw())); - if(i != num-1) - s->assert_expr(to_expr(mk_not(itp[i]).raw())); - lbool result = s->check_sat(0,0); - if(result != l_false){ - err << "interpolant " << i << " is incorrect"; + for(int i = 0; i < num; i++){ + s->push(); + for(unsigned j = 0; j < theory.size(); j++) + s->assert_expr(to_expr(theory[j].raw())); + s->assert_expr(to_expr(cnsts[i].raw())); + std::vector &cs = children[i]; + for(unsigned j = 0; j < cs.size(); j++) + s->assert_expr(to_expr(itp[cs[j]].raw())); + if(i != num-1) + s->assert_expr(to_expr(mk_not(itp[i]).raw())); + lbool result = s->check_sat(0,0); + if(result != l_false){ + err << "interpolant " << i << " is incorrect"; - s->pop(1); - for(unsigned j = 0; j < theory.size(); j++) - s->assert_expr(to_expr(theory[j].raw())); - for(unsigned j = 0; j < cnsts.size(); j++) - if(in_range(j,range_downward(i))) - s->assert_expr(to_expr(cnsts[j].raw())); - if(i != num-1) - s->assert_expr(to_expr(mk_not(itp[i]).raw())); - lbool result = s->check_sat(0,0); - if(result != l_false) - err << "interpolant " << i << " is not implied by its downeard closurn"; + s->pop(1); + for(unsigned j = 0; j < theory.size(); j++) + s->assert_expr(to_expr(theory[j].raw())); + for(unsigned j = 0; j < cnsts.size(); j++) + if(in_range(j,range_downward(i))) + s->assert_expr(to_expr(cnsts[j].raw())); + if(i != num-1) + s->assert_expr(to_expr(mk_not(itp[i]).raw())); + lbool result = s->check_sat(0,0); + if(result != l_false) + err << "interpolant " << i << " is not implied by its downeard closurn"; - return false; - } - s->pop(1); - } + return false; + } + s->pop(1); + } - std::vector > supports(num); - for(int i = 0; i < num; i++){ - hash_set memo; - support(cnsts[i],supports[i],memo); + std::vector > supports(num); + for(int i = 0; i < num; i++){ + hash_set memo; + support(cnsts[i],supports[i],memo); + } + for(int i = 0; i < num-1; i++){ + std::vector Bside(num); + for(int j = num-1; j >= 0; j--) + Bside[j] = j != i; + for(int j = num-1; j >= 0; j--) + if(!Bside[j]){ + std::vector &cs = children[i]; + for(unsigned k = 0; k < cs.size(); k++) + Bside[cs[k]] = false; + } + std::set Asup, Bsup,common,Isup,bad; + for(int j = num-1; j >= 0; j--){ + std::set &side = Bside[j] ? Bsup : Asup; + side.insert(supports[j].begin(),supports[j].end()); + } + std::set_intersection(Asup.begin(),Asup.end(),Bsup.begin(),Bsup.end(),std::inserter(common,common.begin())); + { + hash_set tmemo; + for(unsigned j = 0; j < theory.size(); j++) + support(theory[j],common,tmemo); // all theory symbols allowed in interps + } + hash_set memo; + support(itp[i],Isup,memo); + std::set_difference(Isup.begin(),Isup.end(),common.begin(),common.end(),std::inserter(bad,bad.begin())); + if(!bad.empty()){ + err << "bad symbols in interpolant " << i << ":"; + std::copy(bad.begin(),bad.end(),std::ostream_iterator(err,",")); + return false; + } + } + return true; } - for(int i = 0; i < num-1; i++){ - std::vector Bside(num); - for(int j = num-1; j >= 0; j--) - Bside[j] = j != i; - for(int j = num-1; j >= 0; j--) - if(!Bside[j]){ - std::vector &cs = children[i]; - for(unsigned k = 0; k < cs.size(); k++) - Bside[cs[k]] = false; - } - std::set Asup, Bsup,common,Isup,bad; - for(int j = num-1; j >= 0; j--){ - std::set &side = Bside[j] ? Bsup : Asup; - side.insert(supports[j].begin(),supports[j].end()); - } - std::set_intersection(Asup.begin(),Asup.end(),Bsup.begin(),Bsup.end(),std::inserter(common,common.begin())); - { - hash_set tmemo; - for(unsigned j = 0; j < theory.size(); j++) - support(theory[j],common,tmemo); // all theory symbols allowed in interps - } - hash_set memo; - support(itp[i],Isup,memo); - std::set_difference(Isup.begin(),Isup.end(),common.begin(),common.end(),std::inserter(bad,bad.begin())); - if(!bad.empty()){ - err << "bad symbols in interpolant " << i << ":"; - std::copy(bad.begin(),bad.end(),std::ostream_iterator(err,",")); - return false; - } - } - return true; - } - bool check(solver *s, std::ostream &err, - const std::vector &_cnsts, - const ast &tree, - const std::vector &itp){ + bool check(solver *s, std::ostream &err, + const std::vector &_cnsts, + const ast &tree, + const std::vector &itp){ - std::vector pos_map; + std::vector pos_map; - // convert to the parents vector representation + // convert to the parents vector representation - to_parents_vec_representation(_cnsts, tree, cnsts, parents, theory, pos_map); + to_parents_vec_representation(_cnsts, tree, cnsts, parents, theory, pos_map); - //use the parents vector representation to compute interpolant - return check(s,err,cnsts,parents,itp,theory); - } + //use the parents vector representation to compute interpolant + return check(s,err,cnsts,parents,itp,theory); + } - iz3checker(ast_manager &_m) - : iz3base(_m) { - } + iz3checker(ast_manager &_m) + : iz3base(_m) { + } - iz3checker(iz3mgr &_m) - : iz3base(_m) { - } + iz3checker(iz3mgr &_m) + : iz3base(_m) { + } }; template std::vector to_std_vector(const ::vector &v){ - std::vector _v(v.size()); - for(unsigned i = 0; i < v.size(); i++) - _v[i] = v[i]; - return _v; + std::vector _v(v.size()); + for(unsigned i = 0; i < v.size(); i++) + _v[i] = v[i]; + return _v; } @@ -199,8 +199,8 @@ bool iz3check(ast_manager &_m_manager, const ptr_vector &interps, const ptr_vector &theory) { - iz3checker chk(_m_manager); - return chk.check(s,err,chk.cook(cnsts),to_std_vector(parents),chk.cook(interps),chk.cook(theory)); + iz3checker chk(_m_manager); + return chk.check(s,err,chk.cook(cnsts),to_std_vector(parents),chk.cook(interps),chk.cook(theory)); } bool iz3check(iz3mgr &mgr, @@ -211,8 +211,8 @@ bool iz3check(iz3mgr &mgr, const std::vector &interps, const std::vector &theory) { - iz3checker chk(mgr); - return chk.check(s,err,cnsts,parents,interps,theory); + iz3checker chk(mgr); + return chk.check(s,err,cnsts,parents,interps,theory); } bool iz3check(ast_manager &_m_manager, @@ -222,6 +222,6 @@ bool iz3check(ast_manager &_m_manager, ast *tree, const ptr_vector &interps) { - iz3checker chk(_m_manager); - return chk.check(s,err,chk.cook(_cnsts),chk.cook(tree),chk.cook(interps)); + iz3checker chk(_m_manager); + return chk.check(s,err,chk.cook(_cnsts),chk.cook(tree),chk.cook(interps)); } diff --git a/src/interp/iz3checker.h b/src/interp/iz3checker.h index d46ea0654..6028e60db 100644 --- a/src/interp/iz3checker.h +++ b/src/interp/iz3checker.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3checker.h + iz3checker.h -Abstract: + Abstract: - check correctness of an interpolant + check correctness of an interpolant -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3_CHECKER_H #define IZ3_CHECKER_H diff --git a/src/interp/iz3foci.cpp b/src/interp/iz3foci.cpp index 527e73ae4..e0773209b 100755 --- a/src/interp/iz3foci.cpp +++ b/src/interp/iz3foci.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3foci.cpp + iz3foci.cpp -Abstract: + Abstract: - Implements a secondary solver using foci2. + Implements a secondary solver using foci2. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #include #include @@ -29,329 +29,329 @@ using namespace stl_ext; class iz3foci_impl : public iz3secondary { - int frames; - int *parents; - foci2 *foci; - foci2::symb select_op; - foci2::symb store_op; - foci2::symb mod_op; + int frames; + int *parents; + foci2 *foci; + foci2::symb select_op; + foci2::symb store_op; + foci2::symb mod_op; public: - iz3foci_impl(iz3mgr *mgr, int _frames, int *_parents) : iz3secondary(*mgr) { - frames = _frames; - parents = _parents; - foci = 0; - } - - typedef hash_map AstToNode; - AstToNode ast_to_node; // maps Z3 ast's to foci expressions - - typedef hash_map NodeToAst; - NodeToAst node_to_ast; // maps Z3 ast's to foci expressions - - // We only use this for FuncDeclToSymbol, which has no range destructor - struct symb_hash { - size_t operator()(const symb &s) const { - return (size_t) s; - } - }; - - typedef hash_map FuncDeclToSymbol; - FuncDeclToSymbol func_decl_to_symbol; // maps Z3 func decls to symbols - - typedef hash_map SymbolToFuncDecl; - SymbolToFuncDecl symbol_to_func_decl; // maps symbols to Z3 func decls - - int from_symb(symb func){ - std::string name = string_of_symbol(func); - bool is_bool = is_bool_type(get_range_type(func)); - foci2::symb f; - if(is_bool) - f = foci->mk_pred(name); - else - f = foci->mk_func(name); - symbol_to_func_decl[f] = func; - func_decl_to_symbol[func] = f; - return f; - } - - // create a symbol corresponding to a DeBruijn index of a particular type - // the type has to be encoded into the name because the same index can - // occur with different types - foci2::symb make_deBruijn_symbol(int index, type ty){ - std::ostringstream s; - // s << "#" << index << "#" << type; - return foci->mk_func(s.str()); - } - - int from_Z3_ast(ast t){ - std::pair foo(t,0); - std::pair bar = ast_to_node.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - int nargs = num_args(t); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = from_Z3_ast(arg(t,i)); - - switch(op(t)){ - case True: - res = foci->mk_true(); break; - case False: - res = foci->mk_false(); break; - case And: - res = foci->mk_op(foci2::And,args); break; - case Or: - res = foci->mk_op(foci2::Or,args); break; - case Not: - res = foci->mk_op(foci2::Not,args[0]); break; - case Iff: - res = foci->mk_op(foci2::Iff,args); break; - case OP_OEQ: // bit of a mystery, this one... - if(args[0] == args[1]) res = foci->mk_true(); - else res = foci->mk_op(foci2::Iff,args); - break; - case Ite: - if(is_bool_type(get_type(t))) - res = foci->mk_op(foci2::And,foci->mk_op(foci2::Or,foci->mk_op(foci2::Not,args[0]),args[1]),foci->mk_op(foci2::Or,args[0],args[2])); - else - res = foci->mk_op(foci2::Ite,args); - break; - case Equal: - res = foci->mk_op(foci2::Equal,args); break; - case Implies: - args[0] = foci->mk_op(foci2::Not,args[0]); res = foci->mk_op(foci2::Or,args); break; - case Xor: - res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Iff,args)); break; - case Leq: - res = foci->mk_op(foci2::Leq,args); break; - case Geq: - std::swap(args[0],args[1]); res = foci->mk_op(foci2::Leq,args); break; - case Gt: - res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Leq,args)); break; - case Lt: - std::swap(args[0],args[1]); res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Leq,args)); break; - case Plus: - res = foci->mk_op(foci2::Plus,args); break; - case Sub: - args[1] = foci->mk_op(foci2::Times,foci->mk_int("-1"),args[1]); res = foci->mk_op(foci2::Plus,args); break; - case Uminus: - res = foci->mk_op(foci2::Times,foci->mk_int("-1"),args[0]); break; - case Times: - res = foci->mk_op(foci2::Times,args); break; - case Idiv: - res = foci->mk_op(foci2::Div,args); break; - case Mod: - res = foci->mk_app(mod_op,args); break; - case Select: - res = foci->mk_app(select_op,args); break; - case Store: - res = foci->mk_app(store_op,args); break; - case Distinct: - res = foci->mk_op(foci2::Distinct,args); break; - case Uninterpreted: { - symb func = sym(t); - FuncDeclToSymbol::iterator it = func_decl_to_symbol.find(func); - foci2::symb f = (it == func_decl_to_symbol.end()) ? from_symb(func) : it->second; - if(foci->get_symb(f).substr(0,3) == "lbl" && args.size()==1) // HACK to handle Z3 labels - res = args[0]; - else if(foci->get_symb(f).substr(0,3) == "lbl" && args.size()==0) // HACK to handle Z3 labels - res = foci->mk_true(); - else res = foci->mk_app(f,args); - break; - } - case Numeral: { - std::string s = string_of_numeral(t); - res = foci->mk_int(s); - break; - } - case Forall: - case Exists: { - bool is_forall = op(t) == Forall; - foci2::ops qop = is_forall ? foci2::Forall : foci2::Exists; - int bvs = get_quantifier_num_bound(t); - std::vector foci_bvs(bvs); - for(int i = 0; i < bvs; i++){ - std::string name = get_quantifier_bound_name(t,i); - //Z3_string name = Z3_get_symbol_string(ctx,sym); - // type ty = get_quantifier_bound_type(t,i); - foci2::symb f = foci->mk_func(name); - foci2::ast v = foci->mk_app(f,std::vector()); - foci_bvs[i] = v; - } - foci2::ast body = from_Z3_ast(get_quantifier_body(t)); - foci_bvs.push_back(body); - res = foci->mk_op(qop,foci_bvs); - node_to_ast[res] = t; // desperate - break; - } - case Variable: { // a deBruijn index - int index = get_variable_index_value(t); - type ty = get_type(t); - foci2::symb symbol = make_deBruijn_symbol(index,ty); - res = foci->mk_app(symbol,std::vector()); - break; - } - default: - { - std::cerr << "iZ3: unsupported Z3 operator in expression\n "; - print_expr(std::cerr,t); - std::cerr << "\n"; - assert(0 && "iZ3: unsupported Z3 operator"); - } - } - return res; - } - - // convert an expr to Z3 ast - ast to_Z3_ast(foci2::ast i){ - std::pair foo(i,ast()); - std::pair bar = node_to_ast.insert(foo); - if(!bar.second) return bar.first->second; - ast &res = bar.first->second; - - if(i < 0){ - res = mk_not(to_Z3_ast(-i)); - return res; + iz3foci_impl(iz3mgr *mgr, int _frames, int *_parents) : iz3secondary(*mgr) { + frames = _frames; + parents = _parents; + foci = 0; } - // get the arguments - unsigned n = foci->get_num_args(i); - std::vector args(n); - for(unsigned j = 0; j < n; j++) - args[j] = to_Z3_ast(foci->get_arg(i,j)); + typedef hash_map AstToNode; + AstToNode ast_to_node; // maps Z3 ast's to foci expressions - // handle operators - foci2::ops o; - foci2::symb f; - std::string nval; - if(foci->get_true(i)) - res = mk_true(); - else if(foci->get_false(i)) - res = mk_false(); - else if(foci->get_op(i,o)){ - switch(o){ - case foci2::And: - res = make(And,args); break; - case foci2::Or: - res = make(Or,args); break; - case foci2::Not: - res = mk_not(args[0]); break; - case foci2::Iff: - res = make(Iff,args[0],args[1]); break; - case foci2::Ite: - res = make(Ite,args[0],args[1],args[2]); break; - case foci2::Equal: - res = make(Equal,args[0],args[1]); break; - case foci2::Plus: - res = make(Plus,args); break; - case foci2::Times: - res = make(Times,args); break; - case foci2::Div: - res = make(Idiv,args[0],args[1]); break; - case foci2::Leq: - res = make(Leq,args[0],args[1]); break; - case foci2::Distinct: - res = make(Distinct,args); - break; - case foci2::Tsym: - res = mk_true(); - break; - case foci2::Fsym: - res = mk_false(); - break; - case foci2::Forall: - case foci2::Exists: - { - int nargs = n; - std::vector bounds(nargs-1); - for(int i = 0; i < nargs-1; i++) - bounds[i] = args[i]; - opr oz = o == foci2::Forall ? Forall : Exists; - res = make_quant(oz,bounds,args[nargs-1]); - } - break; - default: - assert("unknown built-in op"); - } - } - else if(foci->get_int(i,nval)){ - res = make_int(nval); - } - else if(foci->get_func(i,f)){ - if(f == select_op){ - assert(n == 2); - res = make(Select,args[0],args[1]); - } - else if(f == store_op){ - assert(n == 3); - res = make(Store,args[0],args[1],args[2]); - } - else if(f == mod_op){ - assert(n == 2); - res = make(Mod,args[0],args[1]); - } - else { - std::pair foo(f,(symb)0); - std::pair bar = symbol_to_func_decl.insert(foo); - symb &func_decl = bar.first->second; - if(bar.second){ - std::cout << "unknown function symbol:\n"; - foci->show_ast(i); - assert(0); + typedef hash_map NodeToAst; + NodeToAst node_to_ast; // maps Z3 ast's to foci expressions + + // We only use this for FuncDeclToSymbol, which has no range destructor + struct symb_hash { + size_t operator()(const symb &s) const { + return (size_t) s; } - res = make(func_decl,args); - } - } - else { - std::cerr << "iZ3: unknown FOCI expression kind\n"; - assert(0 && "iZ3: unknown FOCI expression kind"); - } - return res; - } + }; - int interpolate(const std::vector &cnsts, std::vector &itps){ - assert((int)cnsts.size() == frames); - std::string lia("lia"); + typedef hash_map FuncDeclToSymbol; + FuncDeclToSymbol func_decl_to_symbol; // maps Z3 func decls to symbols + + typedef hash_map SymbolToFuncDecl; + SymbolToFuncDecl symbol_to_func_decl; // maps symbols to Z3 func decls + + int from_symb(symb func){ + std::string name = string_of_symbol(func); + bool is_bool = is_bool_type(get_range_type(func)); + foci2::symb f; + if(is_bool) + f = foci->mk_pred(name); + else + f = foci->mk_func(name); + symbol_to_func_decl[f] = func; + func_decl_to_symbol[func] = f; + return f; + } + + // create a symbol corresponding to a DeBruijn index of a particular type + // the type has to be encoded into the name because the same index can + // occur with different types + foci2::symb make_deBruijn_symbol(int index, type ty){ + std::ostringstream s; + // s << "#" << index << "#" << type; + return foci->mk_func(s.str()); + } + + int from_Z3_ast(ast t){ + std::pair foo(t,0); + std::pair bar = ast_to_node.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + int nargs = num_args(t); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = from_Z3_ast(arg(t,i)); + + switch(op(t)){ + case True: + res = foci->mk_true(); break; + case False: + res = foci->mk_false(); break; + case And: + res = foci->mk_op(foci2::And,args); break; + case Or: + res = foci->mk_op(foci2::Or,args); break; + case Not: + res = foci->mk_op(foci2::Not,args[0]); break; + case Iff: + res = foci->mk_op(foci2::Iff,args); break; + case OP_OEQ: // bit of a mystery, this one... + if(args[0] == args[1]) res = foci->mk_true(); + else res = foci->mk_op(foci2::Iff,args); + break; + case Ite: + if(is_bool_type(get_type(t))) + res = foci->mk_op(foci2::And,foci->mk_op(foci2::Or,foci->mk_op(foci2::Not,args[0]),args[1]),foci->mk_op(foci2::Or,args[0],args[2])); + else + res = foci->mk_op(foci2::Ite,args); + break; + case Equal: + res = foci->mk_op(foci2::Equal,args); break; + case Implies: + args[0] = foci->mk_op(foci2::Not,args[0]); res = foci->mk_op(foci2::Or,args); break; + case Xor: + res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Iff,args)); break; + case Leq: + res = foci->mk_op(foci2::Leq,args); break; + case Geq: + std::swap(args[0],args[1]); res = foci->mk_op(foci2::Leq,args); break; + case Gt: + res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Leq,args)); break; + case Lt: + std::swap(args[0],args[1]); res = foci->mk_op(foci2::Not,foci->mk_op(foci2::Leq,args)); break; + case Plus: + res = foci->mk_op(foci2::Plus,args); break; + case Sub: + args[1] = foci->mk_op(foci2::Times,foci->mk_int("-1"),args[1]); res = foci->mk_op(foci2::Plus,args); break; + case Uminus: + res = foci->mk_op(foci2::Times,foci->mk_int("-1"),args[0]); break; + case Times: + res = foci->mk_op(foci2::Times,args); break; + case Idiv: + res = foci->mk_op(foci2::Div,args); break; + case Mod: + res = foci->mk_app(mod_op,args); break; + case Select: + res = foci->mk_app(select_op,args); break; + case Store: + res = foci->mk_app(store_op,args); break; + case Distinct: + res = foci->mk_op(foci2::Distinct,args); break; + case Uninterpreted: { + symb func = sym(t); + FuncDeclToSymbol::iterator it = func_decl_to_symbol.find(func); + foci2::symb f = (it == func_decl_to_symbol.end()) ? from_symb(func) : it->second; + if(foci->get_symb(f).substr(0,3) == "lbl" && args.size()==1) // HACK to handle Z3 labels + res = args[0]; + else if(foci->get_symb(f).substr(0,3) == "lbl" && args.size()==0) // HACK to handle Z3 labels + res = foci->mk_true(); + else res = foci->mk_app(f,args); + break; + } + case Numeral: { + std::string s = string_of_numeral(t); + res = foci->mk_int(s); + break; + } + case Forall: + case Exists: { + bool is_forall = op(t) == Forall; + foci2::ops qop = is_forall ? foci2::Forall : foci2::Exists; + int bvs = get_quantifier_num_bound(t); + std::vector foci_bvs(bvs); + for(int i = 0; i < bvs; i++){ + std::string name = get_quantifier_bound_name(t,i); + //Z3_string name = Z3_get_symbol_string(ctx,sym); + // type ty = get_quantifier_bound_type(t,i); + foci2::symb f = foci->mk_func(name); + foci2::ast v = foci->mk_app(f,std::vector()); + foci_bvs[i] = v; + } + foci2::ast body = from_Z3_ast(get_quantifier_body(t)); + foci_bvs.push_back(body); + res = foci->mk_op(qop,foci_bvs); + node_to_ast[res] = t; // desperate + break; + } + case Variable: { // a deBruijn index + int index = get_variable_index_value(t); + type ty = get_type(t); + foci2::symb symbol = make_deBruijn_symbol(index,ty); + res = foci->mk_app(symbol,std::vector()); + break; + } + default: + { + std::cerr << "iZ3: unsupported Z3 operator in expression\n "; + print_expr(std::cerr,t); + std::cerr << "\n"; + assert(0 && "iZ3: unsupported Z3 operator"); + } + } + return res; + } + + // convert an expr to Z3 ast + ast to_Z3_ast(foci2::ast i){ + std::pair foo(i,ast()); + std::pair bar = node_to_ast.insert(foo); + if(!bar.second) return bar.first->second; + ast &res = bar.first->second; + + if(i < 0){ + res = mk_not(to_Z3_ast(-i)); + return res; + } + + // get the arguments + unsigned n = foci->get_num_args(i); + std::vector args(n); + for(unsigned j = 0; j < n; j++) + args[j] = to_Z3_ast(foci->get_arg(i,j)); + + // handle operators + foci2::ops o; + foci2::symb f; + std::string nval; + if(foci->get_true(i)) + res = mk_true(); + else if(foci->get_false(i)) + res = mk_false(); + else if(foci->get_op(i,o)){ + switch(o){ + case foci2::And: + res = make(And,args); break; + case foci2::Or: + res = make(Or,args); break; + case foci2::Not: + res = mk_not(args[0]); break; + case foci2::Iff: + res = make(Iff,args[0],args[1]); break; + case foci2::Ite: + res = make(Ite,args[0],args[1],args[2]); break; + case foci2::Equal: + res = make(Equal,args[0],args[1]); break; + case foci2::Plus: + res = make(Plus,args); break; + case foci2::Times: + res = make(Times,args); break; + case foci2::Div: + res = make(Idiv,args[0],args[1]); break; + case foci2::Leq: + res = make(Leq,args[0],args[1]); break; + case foci2::Distinct: + res = make(Distinct,args); + break; + case foci2::Tsym: + res = mk_true(); + break; + case foci2::Fsym: + res = mk_false(); + break; + case foci2::Forall: + case foci2::Exists: + { + int nargs = n; + std::vector bounds(nargs-1); + for(int i = 0; i < nargs-1; i++) + bounds[i] = args[i]; + opr oz = o == foci2::Forall ? Forall : Exists; + res = make_quant(oz,bounds,args[nargs-1]); + } + break; + default: + assert("unknown built-in op"); + } + } + else if(foci->get_int(i,nval)){ + res = make_int(nval); + } + else if(foci->get_func(i,f)){ + if(f == select_op){ + assert(n == 2); + res = make(Select,args[0],args[1]); + } + else if(f == store_op){ + assert(n == 3); + res = make(Store,args[0],args[1],args[2]); + } + else if(f == mod_op){ + assert(n == 2); + res = make(Mod,args[0],args[1]); + } + else { + std::pair foo(f,(symb)0); + std::pair bar = symbol_to_func_decl.insert(foo); + symb &func_decl = bar.first->second; + if(bar.second){ + std::cout << "unknown function symbol:\n"; + foci->show_ast(i); + assert(0); + } + res = make(func_decl,args); + } + } + else { + std::cerr << "iZ3: unknown FOCI expression kind\n"; + assert(0 && "iZ3: unknown FOCI expression kind"); + } + return res; + } + + int interpolate(const std::vector &cnsts, std::vector &itps){ + assert((int)cnsts.size() == frames); + std::string lia("lia"); #ifdef _FOCI2 - foci = foci2::create(lia); + foci = foci2::create(lia); #else - foci = 0; + foci = 0; #endif - if(!foci){ - std::cerr << "iZ3: cannot find foci lia solver.\n"; - assert(0); + if(!foci){ + std::cerr << "iZ3: cannot find foci lia solver.\n"; + assert(0); + } + select_op = foci->mk_func("select"); + store_op = foci->mk_func("store"); + mod_op = foci->mk_func("mod"); + std::vector foci_cnsts(frames), foci_itps(frames-1), foci_parents; + if(parents) + foci_parents.resize(frames); + for(int i = 0; i < frames; i++){ + foci_cnsts[i] = from_Z3_ast(cnsts[i]); + if(parents) + foci_parents[i] = parents[i]; + } + int res = foci->interpolate(foci_cnsts, foci_itps, foci_parents); + if(res == 0){ + assert((int)foci_itps.size() == frames-1); + itps.resize(frames-1); + for(int i = 0; i < frames-1; i++){ + // foci->show_ast(foci_itps[i]); + itps[i] = to_Z3_ast(foci_itps[i]); + } + } + ast_to_node.clear(); + node_to_ast.clear(); + func_decl_to_symbol.clear(); + symbol_to_func_decl.clear(); + delete foci; + return res; } - select_op = foci->mk_func("select"); - store_op = foci->mk_func("store"); - mod_op = foci->mk_func("mod"); - std::vector foci_cnsts(frames), foci_itps(frames-1), foci_parents; - if(parents) - foci_parents.resize(frames); - for(int i = 0; i < frames; i++){ - foci_cnsts[i] = from_Z3_ast(cnsts[i]); - if(parents) - foci_parents[i] = parents[i]; - } - int res = foci->interpolate(foci_cnsts, foci_itps, foci_parents); - if(res == 0){ - assert((int)foci_itps.size() == frames-1); - itps.resize(frames-1); - for(int i = 0; i < frames-1; i++){ - // foci->show_ast(foci_itps[i]); - itps[i] = to_Z3_ast(foci_itps[i]); - } - } - ast_to_node.clear(); - node_to_ast.clear(); - func_decl_to_symbol.clear(); - symbol_to_func_decl.clear(); - delete foci; - return res; - } }; iz3secondary *iz3foci::create(iz3mgr *mgr, int num, int *parents){ - return new iz3foci_impl(mgr,num,parents); + return new iz3foci_impl(mgr,num,parents); } diff --git a/src/interp/iz3foci.h b/src/interp/iz3foci.h index 86b049f24..a84a3c3bf 100755 --- a/src/interp/iz3foci.h +++ b/src/interp/iz3foci.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3foci.h + iz3foci.h -Abstract: + Abstract: - Implements a secondary solver using foci2. + Implements a secondary solver using foci2. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3FOCI_H #define IZ3FOCI_H @@ -26,7 +26,7 @@ Revision History: class iz3foci { public: - static iz3secondary *create(iz3mgr *mgr, int num, int *parents); + static iz3secondary *create(iz3mgr *mgr, int num, int *parents); }; #endif diff --git a/src/interp/iz3hash.h b/src/interp/iz3hash.h index cd94f0e04..caf7e6ddc 100644 --- a/src/interp/iz3hash.h +++ b/src/interp/iz3hash.h @@ -1,30 +1,30 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3hash.h + iz3hash.h -Abstract: + Abstract: - Simple implementation of bucket-list hash tables conforming to SGI - hash_map and hash_set interfaces. Just enough members are - implemented to support iz3 and duality. + Simple implementation of bucket-list hash tables conforming to SGI + hash_map and hash_set interfaces. Just enough members are + implemented to support iz3 and duality. - iz3 and duality need this package because they assume that insert - preserves iterators and references to elements, which is not true - of the hashtable packages in util. + iz3 and duality need this package because they assume that insert + preserves iterators and references to elements, which is not true + of the hashtable packages in util. - This package lives in namespace hash_space. Specializations of - class "hash" should be made in this namespace. + This package lives in namespace hash_space. Specializations of + class "hash" should be made in this namespace. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3_HASH_H #define IZ3_HASH_H @@ -42,437 +42,437 @@ Revision History: namespace hash_space { - template class hash {}; + template class hash {}; - template <> - class hash { - public: - size_t operator()(const int &s) const { - return s; - } - }; - - template <> - class hash { - public: - size_t operator()(const std::string &s) const { - return string_hash(s.c_str(), s.size(), 0); - } - }; - - template <> - class hash > { - public: - size_t operator()(const std::pair &p) const { - return p.first + p.second; - } - }; - - template - class hash > { - public: - size_t operator()(const std::pair &p) const { - return (size_t)p.first + (size_t)p.second; - } - }; - - enum { num_primes = 29 }; - - static const unsigned long primes[num_primes] = - { - 7ul, - 53ul, - 97ul, - 193ul, - 389ul, - 769ul, - 1543ul, - 3079ul, - 6151ul, - 12289ul, - 24593ul, - 49157ul, - 98317ul, - 196613ul, - 393241ul, - 786433ul, - 1572869ul, - 3145739ul, - 6291469ul, - 12582917ul, - 25165843ul, - 50331653ul, - 100663319ul, - 201326611ul, - 402653189ul, - 805306457ul, - 1610612741ul, - 3221225473ul, - 4294967291ul + template <> + class hash { + public: + size_t operator()(const int &s) const { + return s; + } }; - inline unsigned long next_prime(unsigned long n) { - const unsigned long* to = primes + (int)num_primes; - for(const unsigned long* p = primes; p < to; p++) - if(*p >= n) return *p; - return primes[num_primes-1]; - } + template <> + class hash { + public: + size_t operator()(const std::string &s) const { + return string_hash(s.c_str(), s.size(), 0); + } + }; - template - class hashtable - { - public: + template <> + class hash > { + public: + size_t operator()(const std::pair &p) const { + return p.first + p.second; + } + }; - typedef Value &reference; - typedef const Value &const_reference; - - struct Entry + template + class hash > { + public: + size_t operator()(const std::pair &p) const { + return (size_t)p.first + (size_t)p.second; + } + }; + + enum { num_primes = 29 }; + + static const unsigned long primes[num_primes] = + { + 7ul, + 53ul, + 97ul, + 193ul, + 389ul, + 769ul, + 1543ul, + 3079ul, + 6151ul, + 12289ul, + 24593ul, + 49157ul, + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul + }; + + inline unsigned long next_prime(unsigned long n) { + const unsigned long* to = primes + (int)num_primes; + for(const unsigned long* p = primes; p < to; p++) + if(*p >= n) return *p; + return primes[num_primes-1]; + } + + template + class hashtable { - Entry* next; - Value val; + public: + + typedef Value &reference; + typedef const Value &const_reference; + + struct Entry + { + Entry* next; + Value val; - Entry(const Value &_val) : val(_val) {next = 0;} - }; + Entry(const Value &_val) : val(_val) {next = 0;} + }; - struct iterator - { - Entry* ent; - hashtable* tab; + struct iterator + { + Entry* ent; + hashtable* tab; - typedef std::forward_iterator_tag iterator_category; - typedef Value value_type; - typedef std::ptrdiff_t difference_type; - typedef size_t size_type; - typedef Value& reference; - typedef Value* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef Value value_type; + typedef std::ptrdiff_t difference_type; + typedef size_t size_type; + typedef Value& reference; + typedef Value* pointer; - iterator(Entry* _ent, hashtable* _tab) : ent(_ent), tab(_tab) { } + iterator(Entry* _ent, hashtable* _tab) : ent(_ent), tab(_tab) { } - iterator() { } + iterator() { } - Value &operator*() const { return ent->val; } + Value &operator*() const { return ent->val; } - Value *operator->() const { return &(operator*()); } + Value *operator->() const { return &(operator*()); } - iterator &operator++() { - Entry *old = ent; - ent = ent->next; - if (!ent) { - size_t bucket = tab->get_bucket(old->val); - while (!ent && ++bucket < tab->buckets.size()) - ent = tab->buckets[bucket]; - } - return *this; - } + iterator &operator++() { + Entry *old = ent; + ent = ent->next; + if (!ent) { + size_t bucket = tab->get_bucket(old->val); + while (!ent && ++bucket < tab->buckets.size()) + ent = tab->buckets[bucket]; + } + return *this; + } - iterator operator++(int) { - iterator tmp = *this; - operator++(); - return tmp; - } + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } - bool operator==(const iterator& it) const { - return ent == it.ent; - } + bool operator==(const iterator& it) const { + return ent == it.ent; + } - bool operator!=(const iterator& it) const { - return ent != it.ent; - } - }; + bool operator!=(const iterator& it) const { + return ent != it.ent; + } + }; - struct const_iterator - { - const Entry* ent; - const hashtable* tab; + struct const_iterator + { + const Entry* ent; + const hashtable* tab; - typedef std::forward_iterator_tag iterator_category; - typedef Value value_type; - typedef std::ptrdiff_t difference_type; - typedef size_t size_type; - typedef const Value& reference; - typedef const Value* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef Value value_type; + typedef std::ptrdiff_t difference_type; + typedef size_t size_type; + typedef const Value& reference; + typedef const Value* pointer; - const_iterator(const Entry* _ent, const hashtable* _tab) : ent(_ent), tab(_tab) { } + const_iterator(const Entry* _ent, const hashtable* _tab) : ent(_ent), tab(_tab) { } - const_iterator() { } + const_iterator() { } - const Value &operator*() const { return ent->val; } + const Value &operator*() const { return ent->val; } - const Value *operator->() const { return &(operator*()); } + const Value *operator->() const { return &(operator*()); } - const_iterator &operator++() { - Entry *old = ent; - ent = ent->next; - if (!ent) { - size_t bucket = tab->get_bucket(old->val); - while (!ent && ++bucket < tab->buckets.size()) - ent = tab->buckets[bucket]; - } - return *this; - } + const_iterator &operator++() { + Entry *old = ent; + ent = ent->next; + if (!ent) { + size_t bucket = tab->get_bucket(old->val); + while (!ent && ++bucket < tab->buckets.size()) + ent = tab->buckets[bucket]; + } + return *this; + } - const_iterator operator++(int) { - const_iterator tmp = *this; - operator++(); - return tmp; - } + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } - bool operator==(const const_iterator& it) const { - return ent == it.ent; - } + bool operator==(const const_iterator& it) const { + return ent == it.ent; + } - bool operator!=(const const_iterator& it) const { - return ent != it.ent; - } - }; + bool operator!=(const const_iterator& it) const { + return ent != it.ent; + } + }; private: - typedef std::vector Table; + typedef std::vector Table; - Table buckets; - size_t entries; - HashFun hash_fun ; - GetKey get_key; - KeyEqFun key_eq_fun; + Table buckets; + size_t entries; + HashFun hash_fun ; + GetKey get_key; + KeyEqFun key_eq_fun; public: hashtable(size_t init_size) : buckets(init_size,(Entry *)0) { - entries = 0; - } + entries = 0; + } - hashtable(const hashtable& other) { - dup(other); - } + hashtable(const hashtable& other) { + dup(other); + } - hashtable& operator= (const hashtable& other) { - if (&other != this) - dup(other); - return *this; - } + hashtable& operator= (const hashtable& other) { + if (&other != this) + dup(other); + return *this; + } - ~hashtable() { - clear(); - } + ~hashtable() { + clear(); + } - size_t size() const { - return entries; - } + size_t size() const { + return entries; + } - bool empty() const { - return size() == 0; - } + bool empty() const { + return size() == 0; + } - void swap(hashtable& other) { - buckets.swap(other.buckets); - std::swap(entries, other.entries); - } + void swap(hashtable& other) { + buckets.swap(other.buckets); + std::swap(entries, other.entries); + } - iterator begin() { - for (size_t i = 0; i < buckets.size(); ++i) - if (buckets[i]) - return iterator(buckets[i], this); - return end(); - } + iterator begin() { + for (size_t i = 0; i < buckets.size(); ++i) + if (buckets[i]) + return iterator(buckets[i], this); + return end(); + } - iterator end() { - return iterator(0, this); - } + iterator end() { + return iterator(0, this); + } - const_iterator begin() const { - for (size_t i = 0; i < buckets.size(); ++i) - if (buckets[i]) - return const_iterator(buckets[i], this); - return end(); - } + const_iterator begin() const { + for (size_t i = 0; i < buckets.size(); ++i) + if (buckets[i]) + return const_iterator(buckets[i], this); + return end(); + } - const_iterator end() const { - return const_iterator(0, this); - } + const_iterator end() const { + return const_iterator(0, this); + } - size_t get_bucket(const Value& val, size_t n) const { - return hash_fun(get_key(val)) % n; - } + size_t get_bucket(const Value& val, size_t n) const { + return hash_fun(get_key(val)) % n; + } - size_t get_key_bucket(const Key& key) const { - return hash_fun(key) % buckets.size(); - } + size_t get_key_bucket(const Key& key) const { + return hash_fun(key) % buckets.size(); + } - size_t get_bucket(const Value& val) const { - return get_bucket(val,buckets.size()); - } + size_t get_bucket(const Value& val) const { + return get_bucket(val,buckets.size()); + } - Entry *lookup(const Value& val, bool ins = false) - { - resize(entries + 1); + Entry *lookup(const Value& val, bool ins = false) + { + resize(entries + 1); - size_t n = get_bucket(val); - Entry* from = buckets[n]; + size_t n = get_bucket(val); + Entry* from = buckets[n]; - for (Entry* ent = from; ent; ent = ent->next) - if (key_eq_fun(get_key(ent->val), get_key(val))) - return ent; + for (Entry* ent = from; ent; ent = ent->next) + if (key_eq_fun(get_key(ent->val), get_key(val))) + return ent; - if(!ins) return 0; + if(!ins) return 0; - Entry* tmp = new Entry(val); - tmp->next = from; - buckets[n] = tmp; - ++entries; - return tmp; - } + Entry* tmp = new Entry(val); + tmp->next = from; + buckets[n] = tmp; + ++entries; + return tmp; + } - Entry *lookup_key(const Key& key) const - { - size_t n = get_key_bucket(key); - Entry* from = buckets[n]; + Entry *lookup_key(const Key& key) const + { + size_t n = get_key_bucket(key); + Entry* from = buckets[n]; - for (Entry* ent = from; ent; ent = ent->next) - if (key_eq_fun(get_key(ent->val), key)) - return ent; + for (Entry* ent = from; ent; ent = ent->next) + if (key_eq_fun(get_key(ent->val), key)) + return ent; - return 0; - } + return 0; + } - const_iterator find(const Key& key) const { - return const_iterator(lookup_key(key),this); - } + const_iterator find(const Key& key) const { + return const_iterator(lookup_key(key),this); + } - iterator find(const Key& key) { - return iterator(lookup_key(key),this); - } + iterator find(const Key& key) { + return iterator(lookup_key(key),this); + } - std::pair insert(const Value& val){ - size_t old_entries = entries; - Entry *ent = lookup(val,true); - return std::pair(iterator(ent,this),entries > old_entries); - } + std::pair insert(const Value& val){ + size_t old_entries = entries; + Entry *ent = lookup(val,true); + return std::pair(iterator(ent,this),entries > old_entries); + } - iterator insert(const iterator &it, const Value& val){ - Entry *ent = lookup(val,true); - return iterator(ent,this); - } + iterator insert(const iterator &it, const Value& val){ + Entry *ent = lookup(val,true); + return iterator(ent,this); + } - size_t erase(const Key& key) - { - Entry** p = &(buckets[get_key_bucket(key)]); - size_t count = 0; - while(*p){ - Entry *q = *p; - if (key_eq_fun(get_key(q->val), key)) { - ++count; - *p = q->next; - delete q; - } - else - p = &(q->next); - } - entries -= count; - return count; - } + size_t erase(const Key& key) + { + Entry** p = &(buckets[get_key_bucket(key)]); + size_t count = 0; + while(*p){ + Entry *q = *p; + if (key_eq_fun(get_key(q->val), key)) { + ++count; + *p = q->next; + delete q; + } + else + p = &(q->next); + } + entries -= count; + return count; + } - void resize(size_t new_size) { - const size_t old_n = buckets.size(); - if (new_size <= old_n) return; - const size_t n = next_prime(new_size); - if (n <= old_n) return; - Table tmp(n, (Entry*)(0)); - for (size_t i = 0; i < old_n; ++i) { - Entry* ent = buckets[i]; - while (ent) { - size_t new_bucket = get_bucket(ent->val, n); - buckets[i] = ent->next; - ent->next = tmp[new_bucket]; - tmp[new_bucket] = ent; - ent = buckets[i]; - } - } - buckets.swap(tmp); - } + void resize(size_t new_size) { + const size_t old_n = buckets.size(); + if (new_size <= old_n) return; + const size_t n = next_prime(new_size); + if (n <= old_n) return; + Table tmp(n, (Entry*)(0)); + for (size_t i = 0; i < old_n; ++i) { + Entry* ent = buckets[i]; + while (ent) { + size_t new_bucket = get_bucket(ent->val, n); + buckets[i] = ent->next; + ent->next = tmp[new_bucket]; + tmp[new_bucket] = ent; + ent = buckets[i]; + } + } + buckets.swap(tmp); + } - void clear() - { - for (size_t i = 0; i < buckets.size(); ++i) { - for (Entry* ent = buckets[i]; ent != 0;) { - Entry* next = ent->next; - delete ent; - ent = next; - } - buckets[i] = 0; - } - entries = 0; - } + void clear() + { + for (size_t i = 0; i < buckets.size(); ++i) { + for (Entry* ent = buckets[i]; ent != 0;) { + Entry* next = ent->next; + delete ent; + ent = next; + } + buckets[i] = 0; + } + entries = 0; + } - void dup(const hashtable& other) - { - buckets.resize(other.buckets.size()); - for (size_t i = 0; i < other.buckets.size(); ++i) { - Entry** to = &buckets[i]; - for (Entry* from = other.buckets[i]; from; from = from->next) - to = &((*to = new Entry(from->val))->next); - } - entries = other.entries; - } - }; + void dup(const hashtable& other) + { + buckets.resize(other.buckets.size()); + for (size_t i = 0; i < other.buckets.size(); ++i) { + Entry** to = &buckets[i]; + for (Entry* from = other.buckets[i]; from; from = from->next) + to = &((*to = new Entry(from->val))->next); + } + entries = other.entries; + } + }; - template - class equal { - public: - bool operator()(const T& x, const T &y) const { - return x == y; - } - }; + template + class equal { + public: + bool operator()(const T& x, const T &y) const { + return x == y; + } + }; - template - class identity { - public: - const T &operator()(const T &x) const { - return x; - } - }; + template + class identity { + public: + const T &operator()(const T &x) const { + return x; + } + }; - template - class proj1 { - public: - const T &operator()(const std::pair &x) const { - return x.first; - } - }; + template + class proj1 { + public: + const T &operator()(const std::pair &x) const { + return x.first; + } + }; - template , - class EqFun = equal > - class hash_set - : public hashtable,EqFun> { + template , + class EqFun = equal > + class hash_set + : public hashtable,EqFun> { - public: + public: - typedef Element value_type; + typedef Element value_type; - hash_set() - : hashtable,EqFun>(7) {} - }; + hash_set() + : hashtable,EqFun>(7) {} + }; - template , - class EqFun = equal > - class hash_map - : public hashtable,Key,HashFun,proj1,EqFun> { + template , + class EqFun = equal > + class hash_map + : public hashtable,Key,HashFun,proj1,EqFun> { - public: + public: - hash_map() - : hashtable,Key,HashFun,proj1,EqFun>(7) {} + hash_map() + : hashtable,Key,HashFun,proj1,EqFun>(7) {} - Value &operator[](const Key& key) { + Value &operator[](const Key& key) { std::pair kvp(key,Value()); return hashtable,Key,HashFun,proj1,EqFun>:: - lookup(kvp,true)->val.second; - } - }; + lookup(kvp,true)->val.second; + } + }; } #endif diff --git a/src/interp/iz3interp.cpp b/src/interp/iz3interp.cpp index 750c0c85e..9d90a05c7 100755 --- a/src/interp/iz3interp.cpp +++ b/src/interp/iz3interp.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3interp.cpp + iz3interp.cpp -Abstract: + Abstract: - Interpolation based on proof translation. + Interpolation based on proof translation. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ /* Copyright 2011 Microsoft Research. */ @@ -52,96 +52,96 @@ using namespace stl_ext; struct frame_reducer : public iz3mgr { - int frames; - hash_map frame_map; - std::vector assertions_map; - std::vector orig_parents_copy; - std::vector used_frames; + int frames; + hash_map frame_map; + std::vector assertions_map; + std::vector orig_parents_copy; + std::vector used_frames; - frame_reducer(const iz3mgr &other) - : iz3mgr(other) {} + frame_reducer(const iz3mgr &other) + : iz3mgr(other) {} - void get_proof_assumptions_rec(z3pf proof, hash_set &memo, std::vector &used_frames){ - if(memo.find(proof) != memo.end())return; - memo.insert(proof); - pfrule dk = pr(proof); - if(dk == PR_ASSERTED){ - ast con = conc(proof); - if(frame_map.find(con) != frame_map.end()){ // false for theory facts - int frame = frame_map[con]; - used_frames[frame] = true; - } + void get_proof_assumptions_rec(z3pf proof, hash_set &memo, std::vector &used_frames){ + if(memo.find(proof) != memo.end())return; + memo.insert(proof); + pfrule dk = pr(proof); + if(dk == PR_ASSERTED){ + ast con = conc(proof); + if(frame_map.find(con) != frame_map.end()){ // false for theory facts + int frame = frame_map[con]; + used_frames[frame] = true; + } + } + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + z3pf arg = prem(proof,i); + get_proof_assumptions_rec(arg,memo,used_frames); + } + } } - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - z3pf arg = prem(proof,i); - get_proof_assumptions_rec(arg,memo,used_frames); - } - } - } - void get_frames(const std::vector >&z3_preds, - const std::vector &orig_parents, - std::vector >&assertions, - std::vector &parents, - z3pf proof){ - frames = z3_preds.size(); - orig_parents_copy = orig_parents; - for(unsigned i = 0; i < z3_preds.size(); i++) - for(unsigned j = 0; j < z3_preds[i].size(); j++) - frame_map[z3_preds[i][j]] = i; - used_frames.resize(frames); - hash_set memo; - get_proof_assumptions_rec(proof,memo,used_frames); - std::vector assertions_back_map(frames); + void get_frames(const std::vector >&z3_preds, + const std::vector &orig_parents, + std::vector >&assertions, + std::vector &parents, + z3pf proof){ + frames = z3_preds.size(); + orig_parents_copy = orig_parents; + for(unsigned i = 0; i < z3_preds.size(); i++) + for(unsigned j = 0; j < z3_preds[i].size(); j++) + frame_map[z3_preds[i][j]] = i; + used_frames.resize(frames); + hash_set memo; + get_proof_assumptions_rec(proof,memo,used_frames); + std::vector assertions_back_map(frames); - // if multiple children of a tree node are used, we can't delete it - std::vector used_children; - for(int i = 0; i < frames; i++) - used_children.push_back(0); - for(int i = 0; i < frames; i++) - if(orig_parents[i] != SHRT_MAX) - if(used_frames[i] || used_children[i]){ - if(used_children[i] > 1) - used_frames[i] = true; - used_children[orig_parents[i]]++; - } + // if multiple children of a tree node are used, we can't delete it + std::vector used_children; + for(int i = 0; i < frames; i++) + used_children.push_back(0); + for(int i = 0; i < frames; i++) + if(orig_parents[i] != SHRT_MAX) + if(used_frames[i] || used_children[i]){ + if(used_children[i] > 1) + used_frames[i] = true; + used_children[orig_parents[i]]++; + } - for(unsigned i = 0; i < z3_preds.size(); i++) - if(used_frames[i] || i == z3_preds.size() - 1){ - assertions.push_back(z3_preds[i]); - assertions_map.push_back(i); - assertions_back_map[i] = assertions.size() - 1; - } + for(unsigned i = 0; i < z3_preds.size(); i++) + if(used_frames[i] || i == z3_preds.size() - 1){ + assertions.push_back(z3_preds[i]); + assertions_map.push_back(i); + assertions_back_map[i] = assertions.size() - 1; + } - if(orig_parents.size()){ - parents.resize(assertions.size()); - for(unsigned i = 0; i < assertions.size(); i++){ - int p = orig_parents[assertions_map[i]]; - while(p != SHRT_MAX && !used_frames[p]) - p = orig_parents[p]; - parents[i] = p == SHRT_MAX ? p : assertions_back_map[p]; - } + if(orig_parents.size()){ + parents.resize(assertions.size()); + for(unsigned i = 0; i < assertions.size(); i++){ + int p = orig_parents[assertions_map[i]]; + while(p != SHRT_MAX && !used_frames[p]) + p = orig_parents[p]; + parents[i] = p == SHRT_MAX ? p : assertions_back_map[p]; + } + } + + // std::cout << "used frames = " << frames << "\n"; } - // std::cout << "used frames = " << frames << "\n"; - } - - void fix_interpolants(std::vector &interpolants){ - std::vector unfixed = interpolants; - interpolants.resize(frames - 1); - for(int i = 0; i < frames - 1; i++) - interpolants[i] = mk_true(); - for(unsigned i = 0; i < unfixed.size(); i++) - interpolants[assertions_map[i]] = unfixed[i]; - for(int i = 0; i < frames-2; i++){ - int p = orig_parents_copy.size() == 0 ? i+1 : orig_parents_copy[i]; - if(p < frames - 1 && !used_frames[p]) - interpolants[p] = mk_and(interpolants[i],interpolants[p]); + void fix_interpolants(std::vector &interpolants){ + std::vector unfixed = interpolants; + interpolants.resize(frames - 1); + for(int i = 0; i < frames - 1; i++) + interpolants[i] = mk_true(); + for(unsigned i = 0; i < unfixed.size(); i++) + interpolants[assertions_map[i]] = unfixed[i]; + for(int i = 0; i < frames-2; i++){ + int p = orig_parents_copy.size() == 0 ? i+1 : orig_parents_copy[i]; + if(p < frames - 1 && !used_frames[p]) + interpolants[p] = mk_and(interpolants[i],interpolants[p]); + } } - } }; #else @@ -149,20 +149,20 @@ struct frame_reducer { - frame_reducer(context _ctx){ - } + frame_reducer(context _ctx){ + } - void get_frames(const std::vector &z3_preds, - const std::vector &orig_parents, - std::vector &assertions, - std::vector &parents, - ast proof){ - assertions = z3_preds; - parents = orig_parents; - } + void get_frames(const std::vector &z3_preds, + const std::vector &orig_parents, + std::vector &assertions, + std::vector &parents, + ast proof){ + assertions = z3_preds; + parents = orig_parents; + } - void fix_interpolants(std::vector &interpolants){ - } + void fix_interpolants(std::vector &interpolants){ + } }; #endif @@ -170,236 +170,236 @@ struct frame_reducer { #if 0 static lbool test_secondary(context ctx, - int num, - ast *cnsts, - ast *interps, - int *parents = 0 - ){ - iz3secondary *sp = iz3foci::create(ctx,num,parents); - std::vector frames(num), interpolants(num-1); - std::copy(cnsts,cnsts+num,frames.begin()); - int res = sp->interpolate(frames,interpolants); - if(res == 0) + int num, + ast *cnsts, + ast *interps, + int *parents = 0 + ){ + iz3secondary *sp = iz3foci::create(ctx,num,parents); + std::vector frames(num), interpolants(num-1); + std::copy(cnsts,cnsts+num,frames.begin()); + int res = sp->interpolate(frames,interpolants); + if(res == 0) std::copy(interpolants.begin(),interpolants.end(),interps); - return res ? L_TRUE : L_FALSE; + return res ? L_TRUE : L_FALSE; } #endif template struct killme { - T *p; - killme(){p = 0;} - void set(T *_p) {p = _p;} - ~killme(){ - if(p) - delete p; - } + T *p; + killme(){p = 0;} + void set(T *_p) {p = _p;} + ~killme(){ + if(p) + delete p; + } }; class iz3interp : public iz3base { public: - killme sp_killer; - killme tr_killer; + killme sp_killer; + killme tr_killer; - bool is_linear(std::vector &parents){ - for(int i = 0; i < ((int)parents.size())-1; i++) - if(parents[i] != i+1) - return false; - return true; - } + bool is_linear(std::vector &parents){ + for(int i = 0; i < ((int)parents.size())-1; i++) + if(parents[i] != i+1) + return false; + return true; + } - void test_secondary(const std::vector &cnsts, - const std::vector &parents, - std::vector &interps - ){ - int num = cnsts.size(); - iz3secondary *sp = iz3foci::create(this,num,(int *)(parents.empty()?0:&parents[0])); - int res = sp->interpolate(cnsts, interps); - if(res != 0) - throw "secondary failed"; - } + void test_secondary(const std::vector &cnsts, + const std::vector &parents, + std::vector &interps + ){ + int num = cnsts.size(); + iz3secondary *sp = iz3foci::create(this,num,(int *)(parents.empty()?0:&parents[0])); + int res = sp->interpolate(cnsts, interps); + if(res != 0) + throw "secondary failed"; + } - void proof_to_interpolant(z3pf proof, - const std::vector > &cnsts, - const std::vector &parents, - std::vector &interps, - const std::vector &theory, - interpolation_options_struct *options = 0 - ){ + void proof_to_interpolant(z3pf proof, + const std::vector > &cnsts, + const std::vector &parents, + std::vector &interps, + const std::vector &theory, + interpolation_options_struct *options = 0 + ){ #if 0 - test_secondary(cnsts,parents,interps); - return; + test_secondary(cnsts,parents,interps); + return; #endif - profiling::timer_start("Interpolation prep"); + profiling::timer_start("Interpolation prep"); - // get rid of frames not used in proof + // get rid of frames not used in proof - std::vector > cnsts_vec; - std::vector parents_vec; - frame_reducer fr(*this); - fr.get_frames(cnsts,parents,cnsts_vec,parents_vec,proof); + std::vector > cnsts_vec; + std::vector parents_vec; + frame_reducer fr(*this); + fr.get_frames(cnsts,parents,cnsts_vec,parents_vec,proof); - int num = cnsts_vec.size(); - std::vector interps_vec(num-1); + int num = cnsts_vec.size(); + std::vector interps_vec(num-1); - // if this is really a sequence problem, we can make it easier - if(is_linear(parents_vec)) - parents_vec.clear(); + // if this is really a sequence problem, we can make it easier + if(is_linear(parents_vec)) + parents_vec.clear(); - // create a secondary prover - iz3secondary *sp = iz3foci::create(this,num,parents_vec.empty()?0:&parents_vec[0]); - sp_killer.set(sp); // kill this on exit + // create a secondary prover + iz3secondary *sp = iz3foci::create(this,num,parents_vec.empty()?0:&parents_vec[0]); + sp_killer.set(sp); // kill this on exit #define BINARY_INTERPOLATION #ifndef BINARY_INTERPOLATION - // create a translator - iz3translation *tr = iz3translation::create(*this,sp,cnsts_vec,parents_vec,theory); - tr_killer.set(tr); + // create a translator + iz3translation *tr = iz3translation::create(*this,sp,cnsts_vec,parents_vec,theory); + tr_killer.set(tr); - // set the translation options, if needed - if(options) - for(hash_map::iterator it = options->map.begin(), en = options->map.end(); it != en; ++it) - tr->set_option(it->first, it->second); + // set the translation options, if needed + if(options) + for(hash_map::iterator it = options->map.begin(), en = options->map.end(); it != en; ++it) + tr->set_option(it->first, it->second); - // create a proof object to hold the translation - iz3proof pf(tr); + // create a proof object to hold the translation + iz3proof pf(tr); - profiling::timer_stop("Interpolation prep"); + profiling::timer_stop("Interpolation prep"); - // translate into an interpolatable proof - profiling::timer_start("Proof translation"); - tr->translate(proof,pf); - profiling::timer_stop("Proof translation"); + // translate into an interpolatable proof + profiling::timer_start("Proof translation"); + tr->translate(proof,pf); + profiling::timer_stop("Proof translation"); - // translate the proof into interpolants - profiling::timer_start("Proof interpolation"); - for(int i = 0; i < num-1; i++){ - interps_vec[i] = pf.interpolate(tr->range_downward(i),tr->weak_mode()); - interps_vec[i] = tr->quantify(interps_vec[i],tr->range_downward(i)); - } - profiling::timer_stop("Proof interpolation"); + // translate the proof into interpolants + profiling::timer_start("Proof interpolation"); + for(int i = 0; i < num-1; i++){ + interps_vec[i] = pf.interpolate(tr->range_downward(i),tr->weak_mode()); + interps_vec[i] = tr->quantify(interps_vec[i],tr->range_downward(i)); + } + profiling::timer_stop("Proof interpolation"); #else - iz3base the_base(*this,cnsts_vec,parents_vec,theory); + iz3base the_base(*this,cnsts_vec,parents_vec,theory); - profiling::timer_stop("Interpolation prep"); + profiling::timer_stop("Interpolation prep"); - for(int i = 0; i < num-1; i++){ - range rng = the_base.range_downward(i); - std::vector > cnsts_vec_vec(2); - for(unsigned j = 0; j < cnsts_vec.size(); j++){ - bool is_A = the_base.in_range(j,rng); - for(unsigned k = 0; k < cnsts_vec[j].size(); k++) - cnsts_vec_vec[is_A ? 0 : 1].push_back(cnsts_vec[j][k]); - } + for(int i = 0; i < num-1; i++){ + range rng = the_base.range_downward(i); + std::vector > cnsts_vec_vec(2); + for(unsigned j = 0; j < cnsts_vec.size(); j++){ + bool is_A = the_base.in_range(j,rng); + for(unsigned k = 0; k < cnsts_vec[j].size(); k++) + cnsts_vec_vec[is_A ? 0 : 1].push_back(cnsts_vec[j][k]); + } - killme tr_killer_i; - iz3translation *tr = iz3translation::create(*this,sp,cnsts_vec_vec,std::vector(),theory); - tr_killer_i.set(tr); + killme tr_killer_i; + iz3translation *tr = iz3translation::create(*this,sp,cnsts_vec_vec,std::vector(),theory); + tr_killer_i.set(tr); - // set the translation options, if needed - if(options) - for(hash_map::iterator it = options->map.begin(), en = options->map.end(); it != en; ++it) - tr->set_option(it->first, it->second); + // set the translation options, if needed + if(options) + for(hash_map::iterator it = options->map.begin(), en = options->map.end(); it != en; ++it) + tr->set_option(it->first, it->second); - // create a proof object to hold the translation - iz3proof pf(tr); + // create a proof object to hold the translation + iz3proof pf(tr); - // translate into an interpolatable proof - profiling::timer_start("Proof translation"); - tr->translate(proof,pf); - profiling::timer_stop("Proof translation"); + // translate into an interpolatable proof + profiling::timer_start("Proof translation"); + tr->translate(proof,pf); + profiling::timer_stop("Proof translation"); - // translate the proof into interpolants - profiling::timer_start("Proof interpolation"); - interps_vec[i] = pf.interpolate(tr->range_downward(0),tr->weak_mode()); - interps_vec[i] = tr->quantify(interps_vec[i],tr->range_downward(0)); - profiling::timer_stop("Proof interpolation"); - } + // translate the proof into interpolants + profiling::timer_start("Proof interpolation"); + interps_vec[i] = pf.interpolate(tr->range_downward(0),tr->weak_mode()); + interps_vec[i] = tr->quantify(interps_vec[i],tr->range_downward(0)); + profiling::timer_stop("Proof interpolation"); + } #endif - // put back in the removed frames - fr.fix_interpolants(interps_vec); + // put back in the removed frames + fr.fix_interpolants(interps_vec); - interps = interps_vec; + interps = interps_vec; - } - - - void proof_to_interpolant(z3pf proof, - std::vector &cnsts, - const std::vector &parents, - std::vector &interps, - const std::vector &theory, - interpolation_options_struct *options = 0 - ){ - std::vector > cnsts_vec(cnsts.size()); - for(unsigned i = 0; i < cnsts.size(); i++) - cnsts_vec[i].push_back(cnsts[i]); - proof_to_interpolant(proof,cnsts_vec,parents,interps,theory,options); - } - - // same as above, but represents the tree using an ast - - void proof_to_interpolant(const z3pf &proof, - const std::vector &_cnsts, - const ast &tree, - std::vector &interps, - interpolation_options_struct *options = 0 - ){ - std::vector pos_map; - - // convert to the parents vector representation - - to_parents_vec_representation(_cnsts, tree, cnsts, parents, theory, pos_map); - - //use the parents vector representation to compute interpolant - proof_to_interpolant(proof,cnsts,parents,interps,theory,options); - - // get the interps for the tree positions - std::vector _interps = interps; - interps.resize(pos_map.size()); - for(unsigned i = 0; i < pos_map.size(); i++){ - unsigned j = pos_map[i]; - interps[i] = j < _interps.size() ? _interps[j] : mk_false(); } - } - bool has_interp(hash_map &memo, const ast &t){ - if(memo.find(t) != memo.end()) - return memo[t]; - bool res = false; - if(op(t) == Interp) - res = true; - else if(op(t) == And){ - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - res |= has_interp(memo, arg(t,i)); - } - memo[t] = res; - return res; - } - void collect_conjuncts(std::vector &cnsts, hash_map &memo, const ast &t){ - if(!has_interp(memo,t)) - cnsts.push_back(t); - else { - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - collect_conjuncts(cnsts, memo, arg(t,i)); + void proof_to_interpolant(z3pf proof, + std::vector &cnsts, + const std::vector &parents, + std::vector &interps, + const std::vector &theory, + interpolation_options_struct *options = 0 + ){ + std::vector > cnsts_vec(cnsts.size()); + for(unsigned i = 0; i < cnsts.size(); i++) + cnsts_vec[i].push_back(cnsts[i]); + proof_to_interpolant(proof,cnsts_vec,parents,interps,theory,options); + } + + // same as above, but represents the tree using an ast + + void proof_to_interpolant(const z3pf &proof, + const std::vector &_cnsts, + const ast &tree, + std::vector &interps, + interpolation_options_struct *options = 0 + ){ + std::vector pos_map; + + // convert to the parents vector representation + + to_parents_vec_representation(_cnsts, tree, cnsts, parents, theory, pos_map); + + //use the parents vector representation to compute interpolant + proof_to_interpolant(proof,cnsts,parents,interps,theory,options); + + // get the interps for the tree positions + std::vector _interps = interps; + interps.resize(pos_map.size()); + for(unsigned i = 0; i < pos_map.size(); i++){ + unsigned j = pos_map[i]; + interps[i] = j < _interps.size() ? _interps[j] : mk_false(); + } + } + + bool has_interp(hash_map &memo, const ast &t){ + if(memo.find(t) != memo.end()) + return memo[t]; + bool res = false; + if(op(t) == Interp) + res = true; + else if(op(t) == And){ + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + res |= has_interp(memo, arg(t,i)); + } + memo[t] = res; + return res; + } + + void collect_conjuncts(std::vector &cnsts, hash_map &memo, const ast &t){ + if(!has_interp(memo,t)) + cnsts.push_back(t); + else { + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + collect_conjuncts(cnsts, memo, arg(t,i)); + } } - } - void assert_conjuncts(solver &s, std::vector &cnsts, const ast &t){ - hash_map memo; - collect_conjuncts(cnsts,memo,t); - for(unsigned i = 0; i < cnsts.size(); i++) - s.assert_expr(to_expr(cnsts[i].raw())); - } + void assert_conjuncts(solver &s, std::vector &cnsts, const ast &t){ + hash_map memo; + collect_conjuncts(cnsts,memo,t); + for(unsigned i = 0; i < cnsts.size(); i++) + s.assert_expr(to_expr(cnsts[i].raw())); + } - iz3interp(ast_manager &_m_manager) - : iz3base(_m_manager) {} + iz3interp(ast_manager &_m_manager) + : iz3base(_m_manager) {} }; void iz3interpolate(ast_manager &_m_manager, @@ -410,24 +410,24 @@ void iz3interpolate(ast_manager &_m_manager, const ptr_vector &theory, interpolation_options_struct * options) { - iz3interp itp(_m_manager); - if(options) - options->apply(itp); - std::vector _cnsts(cnsts.size()); - std::vector _parents(parents.size()); - std::vector _interps; - std::vector _theory(theory.size()); - for(unsigned i = 0; i < cnsts.size(); i++) - _cnsts[i] = itp.cook(cnsts[i]); - for(unsigned i = 0; i < parents.size(); i++) - _parents[i] = parents[i]; - for(unsigned i = 0; i < theory.size(); i++) - _theory[i] = itp.cook(theory[i]); - iz3mgr::ast _proof = itp.cook(proof); - itp.proof_to_interpolant(_proof,_cnsts,_parents,_interps,_theory,options); - interps.resize(_interps.size()); - for(unsigned i = 0; i < interps.size(); i++) - interps[i] = itp.uncook(_interps[i]); + iz3interp itp(_m_manager); + if(options) + options->apply(itp); + std::vector _cnsts(cnsts.size()); + std::vector _parents(parents.size()); + std::vector _interps; + std::vector _theory(theory.size()); + for(unsigned i = 0; i < cnsts.size(); i++) + _cnsts[i] = itp.cook(cnsts[i]); + for(unsigned i = 0; i < parents.size(); i++) + _parents[i] = parents[i]; + for(unsigned i = 0; i < theory.size(); i++) + _theory[i] = itp.cook(theory[i]); + iz3mgr::ast _proof = itp.cook(proof); + itp.proof_to_interpolant(_proof,_cnsts,_parents,_interps,_theory,options); + interps.resize(_interps.size()); + for(unsigned i = 0; i < interps.size(); i++) + interps[i] = itp.uncook(_interps[i]); } void iz3interpolate(ast_manager &_m_manager, @@ -438,25 +438,25 @@ void iz3interpolate(ast_manager &_m_manager, const ptr_vector &theory, interpolation_options_struct * options) { - iz3interp itp(_m_manager); - if(options) - options->apply(itp); - std::vector > _cnsts(cnsts.size()); - std::vector _parents(parents.size()); - std::vector _interps; - std::vector _theory(theory.size()); - for(unsigned i = 0; i < cnsts.size(); i++) - for(unsigned j = 0; j < cnsts[i].size(); j++) - _cnsts[i].push_back(itp.cook(cnsts[i][j])); - for(unsigned i = 0; i < parents.size(); i++) - _parents[i] = parents[i]; - for(unsigned i = 0; i < theory.size(); i++) - _theory[i] = itp.cook(theory[i]); - iz3mgr::ast _proof = itp.cook(proof); - itp.proof_to_interpolant(_proof,_cnsts,_parents,_interps,_theory,options); - interps.resize(_interps.size()); - for(unsigned i = 0; i < interps.size(); i++) - interps[i] = itp.uncook(_interps[i]); + iz3interp itp(_m_manager); + if(options) + options->apply(itp); + std::vector > _cnsts(cnsts.size()); + std::vector _parents(parents.size()); + std::vector _interps; + std::vector _theory(theory.size()); + for(unsigned i = 0; i < cnsts.size(); i++) + for(unsigned j = 0; j < cnsts[i].size(); j++) + _cnsts[i].push_back(itp.cook(cnsts[i][j])); + for(unsigned i = 0; i < parents.size(); i++) + _parents[i] = parents[i]; + for(unsigned i = 0; i < theory.size(); i++) + _theory[i] = itp.cook(theory[i]); + iz3mgr::ast _proof = itp.cook(proof); + itp.proof_to_interpolant(_proof,_cnsts,_parents,_interps,_theory,options); + interps.resize(_interps.size()); + for(unsigned i = 0; i < interps.size(); i++) + interps[i] = itp.uncook(_interps[i]); } void iz3interpolate(ast_manager &_m_manager, @@ -466,19 +466,19 @@ void iz3interpolate(ast_manager &_m_manager, ptr_vector &interps, interpolation_options_struct * options) { - iz3interp itp(_m_manager); - if(options) - options->apply(itp); - std::vector _cnsts(cnsts.size()); - std::vector _interps; - for(unsigned i = 0; i < cnsts.size(); i++) - _cnsts[i] = itp.cook(cnsts[i]); - iz3mgr::ast _proof = itp.cook(proof); - iz3mgr::ast _tree = itp.cook(tree); - itp.proof_to_interpolant(_proof,_cnsts,_tree,_interps,options); - interps.resize(_interps.size()); - for(unsigned i = 0; i < interps.size(); i++) - interps[i] = itp.uncook(_interps[i]); + iz3interp itp(_m_manager); + if(options) + options->apply(itp); + std::vector _cnsts(cnsts.size()); + std::vector _interps; + for(unsigned i = 0; i < cnsts.size(); i++) + _cnsts[i] = itp.cook(cnsts[i]); + iz3mgr::ast _proof = itp.cook(proof); + iz3mgr::ast _tree = itp.cook(tree); + itp.proof_to_interpolant(_proof,_cnsts,_tree,_interps,options); + interps.resize(_interps.size()); + for(unsigned i = 0; i < interps.size(); i++) + interps[i] = itp.uncook(_interps[i]); } lbool iz3interpolate(ast_manager &_m_manager, @@ -489,40 +489,40 @@ lbool iz3interpolate(ast_manager &_m_manager, model_ref &m, interpolation_options_struct * options) { - iz3interp itp(_m_manager); - if(options) - options->apply(itp); - iz3mgr::ast _tree = itp.cook(tree); - std::vector _cnsts; - itp.assert_conjuncts(s,_cnsts,_tree); - profiling::timer_start("solving"); - lbool res = s.check_sat(0,0); - profiling::timer_stop("solving"); - if(res == l_false){ - ast *proof = s.get_proof(); - iz3mgr::ast _proof = itp.cook(proof); - std::vector _interps; - itp.proof_to_interpolant(_proof,_cnsts,_tree,_interps,options); - interps.resize(_interps.size()); - for(unsigned i = 0; i < interps.size(); i++) - interps[i] = itp.uncook(_interps[i]); - } - else if(m){ - s.get_model(m); - } - cnsts.resize(_cnsts.size()); - for(unsigned i = 0; i < cnsts.size(); i++) - cnsts[i] = itp.uncook(_cnsts[i]); - return res; + iz3interp itp(_m_manager); + if(options) + options->apply(itp); + iz3mgr::ast _tree = itp.cook(tree); + std::vector _cnsts; + itp.assert_conjuncts(s,_cnsts,_tree); + profiling::timer_start("solving"); + lbool res = s.check_sat(0,0); + profiling::timer_stop("solving"); + if(res == l_false){ + ast *proof = s.get_proof(); + iz3mgr::ast _proof = itp.cook(proof); + std::vector _interps; + itp.proof_to_interpolant(_proof,_cnsts,_tree,_interps,options); + interps.resize(_interps.size()); + for(unsigned i = 0; i < interps.size(); i++) + interps[i] = itp.uncook(_interps[i]); + } + else if(m){ + s.get_model(m); + } + cnsts.resize(_cnsts.size()); + for(unsigned i = 0; i < cnsts.size(); i++) + cnsts[i] = itp.uncook(_cnsts[i]); + return res; } void interpolation_options_struct::apply(iz3base &b){ - for(stl_ext::hash_map::iterator it = map.begin(), en = map.end(); - it != en; - ++it) - b.set_option((*it).first,(*it).second); + for(stl_ext::hash_map::iterator it = map.begin(), en = map.end(); + it != en; + ++it) + b.set_option((*it).first,(*it).second); } // On linux and mac, unlimit stack space so we get recursion @@ -536,11 +536,11 @@ void interpolation_options_struct::apply(iz3base &b){ class iz3stack_unlimiter { public: - iz3stack_unlimiter() { - struct rlimit rl = {RLIM_INFINITY, RLIM_INFINITY}; - setrlimit(RLIMIT_STACK, &rl); - // nothing to be done if above fails - } + iz3stack_unlimiter() { + struct rlimit rl = {RLIM_INFINITY, RLIM_INFINITY}; + setrlimit(RLIMIT_STACK, &rl); + // nothing to be done if above fails + } }; // initializing this will unlimit stack diff --git a/src/interp/iz3interp.h b/src/interp/iz3interp.h index 1c6f9513e..2b1926994 100644 --- a/src/interp/iz3interp.h +++ b/src/interp/iz3interp.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3interp.h + iz3interp.h -Abstract: + Abstract: - Interpolation based on proof translation. + Interpolation based on proof translation. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3_INTERP_H #define IZ3_INTERP_H @@ -26,12 +26,12 @@ Revision History: class iz3base; struct interpolation_options_struct { - stl_ext::hash_map map; + stl_ext::hash_map map; public: - void set(const std::string &name, const std::string &value){ - map[name] = value; - } - void apply(iz3base &b); + void set(const std::string &name, const std::string &value){ + map[name] = value; + } + void apply(iz3base &b); }; /** This object is thrown if a tree interpolation problem is mal-formed */ diff --git a/src/interp/iz3mgr.cpp b/src/interp/iz3mgr.cpp index e3ac59dfd..5a7f71987 100755 --- a/src/interp/iz3mgr.cpp +++ b/src/interp/iz3mgr.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3mgr.cpp + iz3mgr.cpp -Abstract: + Abstract: - A wrapper around an ast manager, providing convenience methods. + A wrapper around an ast manager, providing convenience methods. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS @@ -42,253 +42,253 @@ using namespace stl_ext; std::ostream &operator <<(std::ostream &s, const iz3mgr::ast &a){ - return s; + return s; } iz3mgr::ast iz3mgr::make_var(const std::string &name, type ty){ - symbol s = symbol(name.c_str()); - return cook(m().mk_const(m().mk_const_decl(s, ty))); + symbol s = symbol(name.c_str()); + return cook(m().mk_const(m().mk_const_decl(s, ty))); } iz3mgr::ast iz3mgr::make(opr op, int n, raw_ast **args){ - switch(op) { - case True: return mki(m_basic_fid,OP_TRUE,n,args); - case False: return mki(m_basic_fid,OP_FALSE,n,args); - case Equal: return mki(m_basic_fid,OP_EQ,n,args); - case Distinct: return mki(m_basic_fid,OP_DISTINCT,n,args); - case Ite: return mki(m_basic_fid,OP_ITE,n,args); - case And: return mki(m_basic_fid,OP_AND,n,args); - case Or: return mki(m_basic_fid,OP_OR,n,args); - case Iff: return mki(m_basic_fid,OP_IFF,n,args); - case Xor: return mki(m_basic_fid,OP_XOR,n,args); - case Not: return mki(m_basic_fid,OP_NOT,n,args); - case Implies: return mki(m_basic_fid,OP_IMPLIES,n,args); - case Oeq: return mki(m_basic_fid,OP_OEQ,n,args); - case Interp: return mki(m_basic_fid,OP_INTERP,n,args); - case Leq: return mki(m_arith_fid,OP_LE,n,args); - case Geq: return mki(m_arith_fid,OP_GE,n,args); - case Lt: return mki(m_arith_fid,OP_LT,n,args); - case Gt: return mki(m_arith_fid,OP_GT,n,args); - case Plus: return mki(m_arith_fid,OP_ADD,n,args); - case Sub: return mki(m_arith_fid,OP_SUB,n,args); - case Uminus: return mki(m_arith_fid,OP_UMINUS,n,args); - case Times: return mki(m_arith_fid,OP_MUL,n,args); - case Div: return mki(m_arith_fid,OP_DIV,n,args); - case Idiv: return mki(m_arith_fid,OP_IDIV,n,args); - case Rem: return mki(m_arith_fid,OP_REM,n,args); - case Mod: return mki(m_arith_fid,OP_MOD,n,args); - case Power: return mki(m_arith_fid,OP_POWER,n,args); - case ToReal: return mki(m_arith_fid,OP_TO_REAL,n,args); - case ToInt: return mki(m_arith_fid,OP_TO_INT,n,args); - case IsInt: return mki(m_arith_fid,OP_IS_INT,n,args); - case Store: return mki(m_array_fid,OP_STORE,n,args); - case Select: return mki(m_array_fid,OP_SELECT,n,args); - case ConstArray: return mki(m_array_fid,OP_CONST_ARRAY,n,args); - case ArrayDefault: return mki(m_array_fid,OP_ARRAY_DEFAULT,n,args); - case ArrayMap: return mki(m_array_fid,OP_ARRAY_MAP,n,args); - case SetUnion: return mki(m_array_fid,OP_SET_UNION,n,args); - case SetIntersect: return mki(m_array_fid,OP_SET_INTERSECT,n,args); - case SetDifference: return mki(m_array_fid,OP_SET_DIFFERENCE,n,args); - case SetComplement: return mki(m_array_fid,OP_SET_COMPLEMENT,n,args); - case SetSubSet: return mki(m_array_fid,OP_SET_SUBSET,n,args); - case AsArray: return mki(m_array_fid,OP_AS_ARRAY,n,args); - default: - assert(0); - return ast(); - } + switch(op) { + case True: return mki(m_basic_fid,OP_TRUE,n,args); + case False: return mki(m_basic_fid,OP_FALSE,n,args); + case Equal: return mki(m_basic_fid,OP_EQ,n,args); + case Distinct: return mki(m_basic_fid,OP_DISTINCT,n,args); + case Ite: return mki(m_basic_fid,OP_ITE,n,args); + case And: return mki(m_basic_fid,OP_AND,n,args); + case Or: return mki(m_basic_fid,OP_OR,n,args); + case Iff: return mki(m_basic_fid,OP_IFF,n,args); + case Xor: return mki(m_basic_fid,OP_XOR,n,args); + case Not: return mki(m_basic_fid,OP_NOT,n,args); + case Implies: return mki(m_basic_fid,OP_IMPLIES,n,args); + case Oeq: return mki(m_basic_fid,OP_OEQ,n,args); + case Interp: return mki(m_basic_fid,OP_INTERP,n,args); + case Leq: return mki(m_arith_fid,OP_LE,n,args); + case Geq: return mki(m_arith_fid,OP_GE,n,args); + case Lt: return mki(m_arith_fid,OP_LT,n,args); + case Gt: return mki(m_arith_fid,OP_GT,n,args); + case Plus: return mki(m_arith_fid,OP_ADD,n,args); + case Sub: return mki(m_arith_fid,OP_SUB,n,args); + case Uminus: return mki(m_arith_fid,OP_UMINUS,n,args); + case Times: return mki(m_arith_fid,OP_MUL,n,args); + case Div: return mki(m_arith_fid,OP_DIV,n,args); + case Idiv: return mki(m_arith_fid,OP_IDIV,n,args); + case Rem: return mki(m_arith_fid,OP_REM,n,args); + case Mod: return mki(m_arith_fid,OP_MOD,n,args); + case Power: return mki(m_arith_fid,OP_POWER,n,args); + case ToReal: return mki(m_arith_fid,OP_TO_REAL,n,args); + case ToInt: return mki(m_arith_fid,OP_TO_INT,n,args); + case IsInt: return mki(m_arith_fid,OP_IS_INT,n,args); + case Store: return mki(m_array_fid,OP_STORE,n,args); + case Select: return mki(m_array_fid,OP_SELECT,n,args); + case ConstArray: return mki(m_array_fid,OP_CONST_ARRAY,n,args); + case ArrayDefault: return mki(m_array_fid,OP_ARRAY_DEFAULT,n,args); + case ArrayMap: return mki(m_array_fid,OP_ARRAY_MAP,n,args); + case SetUnion: return mki(m_array_fid,OP_SET_UNION,n,args); + case SetIntersect: return mki(m_array_fid,OP_SET_INTERSECT,n,args); + case SetDifference: return mki(m_array_fid,OP_SET_DIFFERENCE,n,args); + case SetComplement: return mki(m_array_fid,OP_SET_COMPLEMENT,n,args); + case SetSubSet: return mki(m_array_fid,OP_SET_SUBSET,n,args); + case AsArray: return mki(m_array_fid,OP_AS_ARRAY,n,args); + default: + assert(0); + return ast(); + } } iz3mgr::ast iz3mgr::mki(family_id fid, decl_kind dk, int n, raw_ast **args){ - return cook(m().mk_app(fid, dk, 0, 0, n, (expr **)args)); + return cook(m().mk_app(fid, dk, 0, 0, n, (expr **)args)); } iz3mgr::ast iz3mgr::make(opr op, const std::vector &args){ - static std::vector a(10); - if(a.size() < args.size()) - a.resize(args.size()); - for(unsigned i = 0; i < args.size(); i++) - a[i] = args[i].raw(); - return make(op,args.size(), args.size() ? &a[0] : 0); + static std::vector a(10); + if(a.size() < args.size()) + a.resize(args.size()); + for(unsigned i = 0; i < args.size(); i++) + a[i] = args[i].raw(); + return make(op,args.size(), args.size() ? &a[0] : 0); } iz3mgr::ast iz3mgr::make(opr op){ - return make(op,0,0); + return make(op,0,0); } iz3mgr::ast iz3mgr::make(opr op, const ast &arg0){ - raw_ast *a = arg0.raw(); - return make(op,1,&a); + raw_ast *a = arg0.raw(); + return make(op,1,&a); } iz3mgr::ast iz3mgr::make(opr op, const ast &arg0, const ast &arg1){ - raw_ast *args[2]; - args[0] = arg0.raw(); - args[1] = arg1.raw(); - return make(op,2,args); + raw_ast *args[2]; + args[0] = arg0.raw(); + args[1] = arg1.raw(); + return make(op,2,args); } iz3mgr::ast iz3mgr::make(opr op, const ast &arg0, const ast &arg1, const ast &arg2){ - raw_ast *args[3]; - args[0] = arg0.raw(); - args[1] = arg1.raw(); - args[2] = arg2.raw(); - return make(op,3,args); + raw_ast *args[3]; + args[0] = arg0.raw(); + args[1] = arg1.raw(); + args[2] = arg2.raw(); + return make(op,3,args); } iz3mgr::ast iz3mgr::make(symb sym, int n, raw_ast **args){ - return cook(m().mk_app(sym, n, (expr **) args)); + return cook(m().mk_app(sym, n, (expr **) args)); } iz3mgr::ast iz3mgr::make(symb sym, const std::vector &args){ - static std::vector a(10); - if(a.size() < args.size()) - a.resize(args.size()); - for(unsigned i = 0; i < args.size(); i++) - a[i] = args[i].raw(); - return make(sym,args.size(), args.size() ? &a[0] : 0); + static std::vector a(10); + if(a.size() < args.size()) + a.resize(args.size()); + for(unsigned i = 0; i < args.size(); i++) + a[i] = args[i].raw(); + return make(sym,args.size(), args.size() ? &a[0] : 0); } iz3mgr::ast iz3mgr::make(symb sym){ - return make(sym,0,0); + return make(sym,0,0); } iz3mgr::ast iz3mgr::make(symb sym, const ast &arg0){ - raw_ast *a = arg0.raw(); - return make(sym,1,&a); + raw_ast *a = arg0.raw(); + return make(sym,1,&a); } iz3mgr::ast iz3mgr::make(symb sym, const ast &arg0, const ast &arg1){ - raw_ast *args[2]; - args[0] = arg0.raw(); - args[1] = arg1.raw(); - return make(sym,2,args); + raw_ast *args[2]; + args[0] = arg0.raw(); + args[1] = arg1.raw(); + return make(sym,2,args); } iz3mgr::ast iz3mgr::make(symb sym, const ast &arg0, const ast &arg1, const ast &arg2){ - raw_ast *args[3]; - args[0] = arg0.raw(); - args[1] = arg1.raw(); - args[2] = arg2.raw(); - return make(sym,3,args); + raw_ast *args[3]; + args[0] = arg0.raw(); + args[1] = arg1.raw(); + args[2] = arg2.raw(); + return make(sym,3,args); } iz3mgr::ast iz3mgr::make_quant(opr op, const std::vector &bvs, ast &body){ - if(bvs.size() == 0) return body; - std::vector foo(bvs.size()); + if(bvs.size() == 0) return body; + std::vector foo(bvs.size()); - std::vector names; - std::vector types; - std::vector bound_asts; - unsigned num_bound = bvs.size(); + std::vector names; + std::vector types; + std::vector bound_asts; + unsigned num_bound = bvs.size(); - for (unsigned i = 0; i < num_bound; ++i) { - app* a = to_app(bvs[i].raw()); - symbol s(to_app(a)->get_decl()->get_name()); - names.push_back(s); - types.push_back(m().get_sort(a)); - bound_asts.push_back(a); - } - expr_ref abs_body(m()); - expr_abstract(m(), 0, num_bound, &bound_asts[0], to_expr(body.raw()), abs_body); - expr_ref result(m()); - result = m().mk_quantifier( - op == Forall, - names.size(), &types[0], &names[0], abs_body.get(), - 0, - symbol("itp"), - symbol(), - 0, 0, - 0, 0 - ); - return cook(result.get()); + for (unsigned i = 0; i < num_bound; ++i) { + app* a = to_app(bvs[i].raw()); + symbol s(to_app(a)->get_decl()->get_name()); + names.push_back(s); + types.push_back(m().get_sort(a)); + bound_asts.push_back(a); + } + expr_ref abs_body(m()); + expr_abstract(m(), 0, num_bound, &bound_asts[0], to_expr(body.raw()), abs_body); + expr_ref result(m()); + result = m().mk_quantifier( + op == Forall, + names.size(), &types[0], &names[0], abs_body.get(), + 0, + symbol("itp"), + symbol(), + 0, 0, + 0, 0 + ); + return cook(result.get()); } // FIXME replace this with existing Z3 functionality iz3mgr::ast iz3mgr::clone(const ast &t, const std::vector &_args){ - if(_args.size() == 0) - return t; + if(_args.size() == 0) + return t; - ast_manager& m = m_manager; - expr* a = to_expr(t.raw()); - static std::vector rargs(10); - if(rargs.size() < _args.size()) - rargs.resize(_args.size()); - for(unsigned i = 0; i < _args.size(); i++) - rargs[i] = _args[i].raw(); - expr* const* args = (expr **)&rargs[0]; - switch(a->get_kind()) { - case AST_APP: { - app* e = to_app(a); - if (e->get_num_args() != _args.size()) { - assert(0); + ast_manager& m = m_manager; + expr* a = to_expr(t.raw()); + static std::vector rargs(10); + if(rargs.size() < _args.size()) + rargs.resize(_args.size()); + for(unsigned i = 0; i < _args.size(); i++) + rargs[i] = _args[i].raw(); + expr* const* args = (expr **)&rargs[0]; + switch(a->get_kind()) { + case AST_APP: { + app* e = to_app(a); + if (e->get_num_args() != _args.size()) { + assert(0); + } + else { + a = m.mk_app(e->get_decl(), _args.size(), args); + } + break; } - else { - a = m.mk_app(e->get_decl(), _args.size(), args); + case AST_QUANTIFIER: { + if (_args.size() != 1) { + assert(0); + } + else { + a = m.update_quantifier(to_quantifier(a), args[0]); + } + break; } - break; - } - case AST_QUANTIFIER: { - if (_args.size() != 1) { - assert(0); - } - else { - a = m.update_quantifier(to_quantifier(a), args[0]); - } - break; - } - default: - break; - } - return cook(a); + default: + break; + } + return cook(a); } void iz3mgr::show(ast t){ - if(t.null()){ - std::cout << "(null)" << std::endl; - } - params_ref p; - p.set_bool("flat_assoc",false); - std::cout << mk_pp(t.raw(), m(), p) << std::endl; + if(t.null()){ + std::cout << "(null)" << std::endl; + } + params_ref p; + p.set_bool("flat_assoc",false); + std::cout << mk_pp(t.raw(), m(), p) << std::endl; } void iz3mgr::show_symb(symb s){ - std::cout << mk_pp(s, m()) << std::endl; + std::cout << mk_pp(s, m()) << std::endl; } void iz3mgr::print_expr(std::ostream &s, const ast &e){ - params_ref p; - p.set_bool("flat_assoc",false); - s << mk_pp(e.raw(), m(), p); + params_ref p; + p.set_bool("flat_assoc",false); + s << mk_pp(e.raw(), m(), p); } void iz3mgr::print_clause(std::ostream &s, std::vector &cls){ - s << "("; - for(unsigned i = 0; i < cls.size(); i++){ - if(i > 0) s << ","; - print_expr(s,cls[i]); - } - s << ")"; + s << "("; + for(unsigned i = 0; i < cls.size(); i++){ + if(i > 0) s << ","; + print_expr(s,cls[i]); + } + s << ")"; } void iz3mgr::show_clause(std::vector &cls){ - print_clause(std::cout,cls); - std::cout << std::endl; + print_clause(std::cout,cls); + std::cout << std::endl; } void iz3mgr::print_lit(ast lit){ - ast abslit = is_not(lit) ? arg(lit,0) : lit; - int f = op(abslit); - if(f == And || f == Or || f == Iff){ - if(is_not(lit)) std::cout << "~"; - std::cout << "[" << abslit << "]"; - } - else - std::cout << lit; + ast abslit = is_not(lit) ? arg(lit,0) : lit; + int f = op(abslit); + if(f == And || f == Or || f == Iff){ + if(is_not(lit)) std::cout << "~"; + std::cout << "[" << abslit << "]"; + } + else + std::cout << lit; } @@ -296,62 +296,62 @@ static int pretty_cols = 79; static int pretty_indent_chars = 2; static int pretty_find_delim(const std::string &s, int pos){ - int level = 0; - int end = s.size(); - for(; pos < end; pos++){ - int ch = s[pos]; - if(ch == '(')level++; - if(ch == ')')level--; - if(level < 0 || (level == 0 && ch == ','))break; - } - return pos; + int level = 0; + int end = s.size(); + for(; pos < end; pos++){ + int ch = s[pos]; + if(ch == '(')level++; + if(ch == ')')level--; + if(level < 0 || (level == 0 && ch == ','))break; + } + return pos; } static void pretty_newline(std::ostream &f, int indent){ - f << std::endl; - for(int i = 0; i < indent; i++) - f << " "; + f << std::endl; + for(int i = 0; i < indent; i++) + f << " "; } void iz3mgr::pretty_print(std::ostream &f, const std::string &s){ - int cur_indent = 0; - int indent = 0; - int col = 0; - int pos = 0; - while(pos < (int)s.size()){ - int delim = pretty_find_delim(s,pos); - if(s[pos] != ')' && s[pos] != ',' && cur_indent > indent){ - pretty_newline(f,indent); - cur_indent = indent; - col = indent; - continue; + int cur_indent = 0; + int indent = 0; + int col = 0; + int pos = 0; + while(pos < (int)s.size()){ + int delim = pretty_find_delim(s,pos); + if(s[pos] != ')' && s[pos] != ',' && cur_indent > indent){ + pretty_newline(f,indent); + cur_indent = indent; + col = indent; + continue; + } + if (col + delim - pos > pretty_cols) { + if (col > indent) { + pretty_newline(f,indent); + cur_indent = indent; + col = indent; + continue; + } + int paren = s.find('(',pos); + if(paren != (int)std::string::npos){ + int chars = paren - pos + 1; + f << s.substr(pos,chars); + indent += pretty_indent_chars; + if(col) pretty_newline(f,indent); + cur_indent = indent; + pos += chars; + col = indent; + continue; + } + } + int chars = delim - pos + 1; + f << s.substr(pos,chars); + pos += chars; + col += chars; + if(s[delim] == ')') + indent -= pretty_indent_chars; } - if (col + delim - pos > pretty_cols) { - if (col > indent) { - pretty_newline(f,indent); - cur_indent = indent; - col = indent; - continue; - } - int paren = s.find('(',pos); - if(paren != (int)std::string::npos){ - int chars = paren - pos + 1; - f << s.substr(pos,chars); - indent += pretty_indent_chars; - if(col) pretty_newline(f,indent); - cur_indent = indent; - pos += chars; - col = indent; - continue; - } - } - int chars = delim - pos + 1; - f << s.substr(pos,chars); - pos += chars; - col += chars; - if(s[delim] == ')') - indent -= pretty_indent_chars; - } } @@ -359,80 +359,80 @@ iz3mgr::opr iz3mgr::op(const ast &t){ ast_kind dk = t.raw()->get_kind(); switch(dk){ case AST_APP: { - expr * e = to_expr(t.raw()); - func_decl *d = to_app(t.raw())->get_decl(); - if (null_family_id == d->get_family_id()) - return Uninterpreted; - // return (opr)d->get_decl_kind(); - if (m_basic_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_TRUE: return True; - case OP_FALSE: return False; - case OP_EQ: return Equal; - case OP_DISTINCT: return Distinct; - case OP_ITE: return Ite; - case OP_AND: return And; - case OP_OR: return Or; - case OP_IFF: return Iff; - case OP_XOR: return Xor; - case OP_NOT: return Not; - case OP_IMPLIES: return Implies; - case OP_OEQ: return Oeq; - case OP_INTERP: return Interp; - default: - return Other; + expr * e = to_expr(t.raw()); + func_decl *d = to_app(t.raw())->get_decl(); + if (null_family_id == d->get_family_id()) + return Uninterpreted; + // return (opr)d->get_decl_kind(); + if (m_basic_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_TRUE: return True; + case OP_FALSE: return False; + case OP_EQ: return Equal; + case OP_DISTINCT: return Distinct; + case OP_ITE: return Ite; + case OP_AND: return And; + case OP_OR: return Or; + case OP_IFF: return Iff; + case OP_XOR: return Xor; + case OP_NOT: return Not; + case OP_IMPLIES: return Implies; + case OP_OEQ: return Oeq; + case OP_INTERP: return Interp; + default: + return Other; + } + } + if (m_arith_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_LE: return Leq; + case OP_GE: return Geq; + case OP_LT: return Lt; + case OP_GT: return Gt; + case OP_ADD: return Plus; + case OP_SUB: return Sub; + case OP_UMINUS: return Uminus; + case OP_MUL: return Times; + case OP_DIV: return Div; + case OP_IDIV: return Idiv; + case OP_REM: return Rem; + case OP_MOD: return Mod; + case OP_POWER: return Power; + case OP_TO_REAL: return ToReal; + case OP_TO_INT: return ToInt; + case OP_IS_INT: return IsInt; + default: + if (m().is_unique_value(e)) + return Numeral; + return Other; + } + } + if (m_array_fid == d->get_family_id()) { + switch(d->get_decl_kind()) { + case OP_STORE: return Store; + case OP_SELECT: return Select; + case OP_CONST_ARRAY: return ConstArray; + case OP_ARRAY_DEFAULT: return ArrayDefault; + case OP_ARRAY_MAP: return ArrayMap; + case OP_SET_UNION: return SetUnion; + case OP_SET_INTERSECT: return SetIntersect; + case OP_SET_DIFFERENCE: return SetDifference; + case OP_SET_COMPLEMENT: return SetComplement; + case OP_SET_SUBSET: return SetSubSet; + case OP_AS_ARRAY: return AsArray; + default: + return Other; + } } - } - if (m_arith_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_LE: return Leq; - case OP_GE: return Geq; - case OP_LT: return Lt; - case OP_GT: return Gt; - case OP_ADD: return Plus; - case OP_SUB: return Sub; - case OP_UMINUS: return Uminus; - case OP_MUL: return Times; - case OP_DIV: return Div; - case OP_IDIV: return Idiv; - case OP_REM: return Rem; - case OP_MOD: return Mod; - case OP_POWER: return Power; - case OP_TO_REAL: return ToReal; - case OP_TO_INT: return ToInt; - case OP_IS_INT: return IsInt; - default: - if (m().is_unique_value(e)) - return Numeral; - return Other; - } - } - if (m_array_fid == d->get_family_id()) { - switch(d->get_decl_kind()) { - case OP_STORE: return Store; - case OP_SELECT: return Select; - case OP_CONST_ARRAY: return ConstArray; - case OP_ARRAY_DEFAULT: return ArrayDefault; - case OP_ARRAY_MAP: return ArrayMap; - case OP_SET_UNION: return SetUnion; - case OP_SET_INTERSECT: return SetIntersect; - case OP_SET_DIFFERENCE: return SetDifference; - case OP_SET_COMPLEMENT: return SetComplement; - case OP_SET_SUBSET: return SetSubSet; - case OP_AS_ARRAY: return AsArray; - default: - return Other; - } - } - return Other; + return Other; } case AST_QUANTIFIER: - return to_quantifier(t.raw())->is_forall() ? Forall : Exists; + return to_quantifier(t.raw())->is_forall() ? Forall : Exists; case AST_VAR: - return Variable; + return Variable; default:; } return Other; @@ -440,15 +440,15 @@ iz3mgr::opr iz3mgr::op(const ast &t){ iz3mgr::pfrule iz3mgr::pr(const ast &t){ - func_decl *d = to_app(t.raw())->get_decl(); - assert(m_basic_fid == d->get_family_id()); - return d->get_decl_kind(); + func_decl *d = to_app(t.raw())->get_decl(); + assert(m_basic_fid == d->get_family_id()); + return d->get_decl_kind(); } void iz3mgr::print_sat_problem(std::ostream &out, const ast &t){ - ast_smt_pp pp(m()); - pp.set_simplify_implies(false); - pp.display_smt2(out, to_expr(t.raw())); + ast_smt_pp pp(m()); + pp.set_simplify_implies(false); + pp.display_smt2(out, to_expr(t.raw())); } iz3mgr::ast iz3mgr::z3_simplify(const ast &e){ @@ -461,335 +461,335 @@ iz3mgr::ast iz3mgr::z3_simplify(const ast &e){ } iz3mgr::ast iz3mgr::z3_really_simplify(const ast &e){ - ::expr * a = to_expr(e.raw()); - params_ref simp_params; - simp_params.set_bool(":som",true); - simp_params.set_bool(":sort-sums",true); - th_rewriter m_rw(m(), simp_params); - expr_ref result(m()); - m_rw(a, result); - return cook(result); + ::expr * a = to_expr(e.raw()); + params_ref simp_params; + simp_params.set_bool(":som",true); + simp_params.set_bool(":sort-sums",true); + th_rewriter m_rw(m(), simp_params); + expr_ref result(m()); + m_rw(a, result); + return cook(result); } #if 0 static rational lcm(const rational &x, const rational &y){ - int a = x.numerator(); - int b = y.numerator(); - return rational(a * b / gcd(a, b)); + int a = x.numerator(); + int b = y.numerator(); + return rational(a * b / gcd(a, b)); } #endif static rational extract_lcd(std::vector &res){ - if(res.size() == 0) return rational(1); // shouldn't happen - rational lcd = denominator(res[0]); - for(unsigned i = 1; i < res.size(); i++) - lcd = lcm(lcd,denominator(res[i])); - for(unsigned i = 0; i < res.size(); i++) - res[i] *= lcd; - return lcd; + if(res.size() == 0) return rational(1); // shouldn't happen + rational lcd = denominator(res[0]); + for(unsigned i = 1; i < res.size(); i++) + lcd = lcm(lcd,denominator(res[i])); + for(unsigned i = 0; i < res.size(); i++) + res[i] *= lcd; + return lcd; } void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector& coeffs){ - std::vector rats; - get_farkas_coeffs(proof,rats); - coeffs.resize(rats.size()); - for(unsigned i = 0; i < rats.size(); i++){ - class sort *is = m().mk_sort(m_arith_fid, INT_SORT); - ast coeff = cook(m_arith_util.mk_numeral(rats[i],is)); - coeffs[i] = coeff; - } + std::vector rats; + get_farkas_coeffs(proof,rats); + coeffs.resize(rats.size()); + for(unsigned i = 0; i < rats.size(); i++){ + class sort *is = m().mk_sort(m_arith_fid, INT_SORT); + ast coeff = cook(m_arith_util.mk_numeral(rats[i],is)); + coeffs[i] = coeff; + } } static void abs_rat(std::vector &rats){ - // check that they are all non-neg -- if neg, take abs val and warn! - for(unsigned i = 0; i < rats.size(); i++) - if(rats[i].is_neg()){ - // std::cout << "negative Farkas coeff!\n"; - rats[i] = -rats[i]; - } + // check that they are all non-neg -- if neg, take abs val and warn! + for(unsigned i = 0; i < rats.size(); i++) + if(rats[i].is_neg()){ + // std::cout << "negative Farkas coeff!\n"; + rats[i] = -rats[i]; + } } bool iz3mgr::is_farkas_coefficient_negative(const ast &proof, int n){ - rational r; - symb s = sym(proof); - bool ok = s->get_parameter(n+2).is_rational(r); - if(!ok) - throw "Bad Farkas coefficient"; - return r.is_neg(); + rational r; + symb s = sym(proof); + bool ok = s->get_parameter(n+2).is_rational(r); + if(!ok) + throw "Bad Farkas coefficient"; + return r.is_neg(); } void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector& rats){ - symb s = sym(proof); - int numps = s->get_num_parameters(); - rats.resize(numps-2); + symb s = sym(proof); + int numps = s->get_num_parameters(); + rats.resize(numps-2); #if 0 - if(num_prems(proof) < numps-2){ - std::cout << "bad farkas rule: " << num_prems(proof) << " premises should be " << numps-2 << "\n"; - } + if(num_prems(proof) < numps-2){ + std::cout << "bad farkas rule: " << num_prems(proof) << " premises should be " << numps-2 << "\n"; + } #endif - for(int i = 2; i < numps; i++){ - rational r; - bool ok = s->get_parameter(i).is_rational(r); - if(!ok) - throw "Bad Farkas coefficient"; + for(int i = 2; i < numps; i++){ + rational r; + bool ok = s->get_parameter(i).is_rational(r); + if(!ok) + throw "Bad Farkas coefficient"; #if 0 - { - ast con = conc(prem(proof,i-2)); - ast temp = make_real(r); // for debugging - opr o = is_not(con) ? op(arg(con,0)) : op(con); - if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) - r = -r; - } + { + ast con = conc(prem(proof,i-2)); + ast temp = make_real(r); // for debugging + opr o = is_not(con) ? op(arg(con,0)) : op(con); + if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) + r = -r; + } #endif - rats[i-2] = r; - } + rats[i-2] = r; + } #if 0 - if(rats.size() != 0 && rats[0].is_neg()){ - for(unsigned i = 0; i < rats.size(); i++){ - assert(rats[i].is_neg()); - rats[i] = -rats[i]; + if(rats.size() != 0 && rats[0].is_neg()){ + for(unsigned i = 0; i < rats.size(); i++){ + assert(rats[i].is_neg()); + rats[i] = -rats[i]; + } } - } #endif - abs_rat(rats); - extract_lcd(rats); + abs_rat(rats); + extract_lcd(rats); } void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector& coeffs){ - std::vector rats; - get_assign_bounds_coeffs(proof,rats); - coeffs.resize(rats.size()); - for(unsigned i = 0; i < rats.size(); i++){ - coeffs[i] = make_int(rats[i]); - } + std::vector rats; + get_assign_bounds_coeffs(proof,rats); + coeffs.resize(rats.size()); + for(unsigned i = 0; i < rats.size(); i++){ + coeffs[i] = make_int(rats[i]); + } } void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector& rats){ - symb s = sym(proof); - int numps = s->get_num_parameters(); - rats.resize(numps-1); - rats[0] = rational(1); - ast conseq = arg(conc(proof),0); - opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq); - bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt); - for(int i = 2; i < numps; i++){ - rational r; - bool ok = s->get_parameter(i).is_rational(r); - if(!ok) - throw "Bad Farkas coefficient"; - { - ast con = arg(conc(proof),i-1); - ast temp = make_real(r); // for debugging - opr o = is_not(con) ? op(arg(con,0)) : op(con); - if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) - r = -r; - if(conseq_neg) - r = -r; + symb s = sym(proof); + int numps = s->get_num_parameters(); + rats.resize(numps-1); + rats[0] = rational(1); + ast conseq = arg(conc(proof),0); + opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq); + bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt); + for(int i = 2; i < numps; i++){ + rational r; + bool ok = s->get_parameter(i).is_rational(r); + if(!ok) + throw "Bad Farkas coefficient"; + { + ast con = arg(conc(proof),i-1); + ast temp = make_real(r); // for debugging + opr o = is_not(con) ? op(arg(con,0)) : op(con); + if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) + r = -r; + if(conseq_neg) + r = -r; + } + rats[i-1] = r; } - rats[i-1] = r; - } #if 0 - if(rats[1].is_neg()){ // work around bug -- if all coeffs negative, negate them - for(unsigned i = 1; i < rats.size(); i++){ - if(!rats[i].is_neg()) - throw "Bad Farkas coefficients"; - rats[i] = -rats[i]; + if(rats[1].is_neg()){ // work around bug -- if all coeffs negative, negate them + for(unsigned i = 1; i < rats.size(); i++){ + if(!rats[i].is_neg()) + throw "Bad Farkas coefficients"; + rats[i] = -rats[i]; + } } - } #endif - abs_rat(rats); - extract_lcd(rats); + abs_rat(rats); + extract_lcd(rats); } void iz3mgr::get_assign_bounds_rule_coeffs(const ast &proof, std::vector& coeffs){ - std::vector rats; - get_assign_bounds_rule_coeffs(proof,rats); - coeffs.resize(rats.size()); - for(unsigned i = 0; i < rats.size(); i++){ - coeffs[i] = make_int(rats[i]); - } + std::vector rats; + get_assign_bounds_rule_coeffs(proof,rats); + coeffs.resize(rats.size()); + for(unsigned i = 0; i < rats.size(); i++){ + coeffs[i] = make_int(rats[i]); + } } void iz3mgr::get_assign_bounds_rule_coeffs(const ast &proof, std::vector& rats){ - symb s = sym(proof); - int numps = s->get_num_parameters(); - rats.resize(numps-1); - rats[0] = rational(1); - ast conseq = arg(conc(proof),0); - opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq); - bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt); - for(int i = 2; i < numps; i++){ - rational r; - bool ok = s->get_parameter(i).is_rational(r); - if(!ok) - throw "Bad Farkas coefficient"; - { - ast con = conc(prem(proof,i-2)); - ast temp = make_real(r); // for debugging - opr o = is_not(con) ? op(arg(con,0)) : op(con); - if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) - r = -r; - if(conseq_neg) - r = -r; + symb s = sym(proof); + int numps = s->get_num_parameters(); + rats.resize(numps-1); + rats[0] = rational(1); + ast conseq = arg(conc(proof),0); + opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq); + bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt); + for(int i = 2; i < numps; i++){ + rational r; + bool ok = s->get_parameter(i).is_rational(r); + if(!ok) + throw "Bad Farkas coefficient"; + { + ast con = conc(prem(proof,i-2)); + ast temp = make_real(r); // for debugging + opr o = is_not(con) ? op(arg(con,0)) : op(con); + if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt)) + r = -r; + if(conseq_neg) + r = -r; + } + rats[i-1] = r; } - rats[i-1] = r; - } #if 0 - if(rats[1].is_neg()){ // work around bug -- if all coeffs negative, negate them - for(unsigned i = 1; i < rats.size(); i++){ - if(!rats[i].is_neg()) - throw "Bad Farkas coefficients"; - rats[i] = -rats[i]; + if(rats[1].is_neg()){ // work around bug -- if all coeffs negative, negate them + for(unsigned i = 1; i < rats.size(); i++){ + if(!rats[i].is_neg()) + throw "Bad Farkas coefficients"; + rats[i] = -rats[i]; + } } - } #endif - abs_rat(rats); - extract_lcd(rats); + abs_rat(rats); + extract_lcd(rats); } - /** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */ +/** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */ void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q, bool round_off){ - ast Qrhs; - bool qstrict = false; - if(is_not(Q)){ - ast nQ = arg(Q,0); - switch(op(nQ)){ - case Gt: - Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); - break; - case Lt: - Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); - break; - case Geq: - Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); - qstrict = true; - break; - case Leq: - Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); - qstrict = true; - break; - default: - throw "not an inequality"; + ast Qrhs; + bool qstrict = false; + if(is_not(Q)){ + ast nQ = arg(Q,0); + switch(op(nQ)){ + case Gt: + Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); + break; + case Lt: + Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); + break; + case Geq: + Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); + qstrict = true; + break; + case Leq: + Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); + qstrict = true; + break; + default: + throw "not an inequality"; + } } - } - else { - switch(op(Q)){ - case Leq: - Qrhs = make(Sub,arg(Q,1),arg(Q,0)); - break; - case Geq: - Qrhs = make(Sub,arg(Q,0),arg(Q,1)); - break; - case Lt: - Qrhs = make(Sub,arg(Q,1),arg(Q,0)); - qstrict = true; - break; - case Gt: - Qrhs = make(Sub,arg(Q,0),arg(Q,1)); - qstrict = true; - break; - default: - throw "not an inequality"; + else { + switch(op(Q)){ + case Leq: + Qrhs = make(Sub,arg(Q,1),arg(Q,0)); + break; + case Geq: + Qrhs = make(Sub,arg(Q,0),arg(Q,1)); + break; + case Lt: + Qrhs = make(Sub,arg(Q,1),arg(Q,0)); + qstrict = true; + break; + case Gt: + Qrhs = make(Sub,arg(Q,0),arg(Q,1)); + qstrict = true; + break; + default: + throw "not an inequality"; + } } - } - bool pstrict = op(P) == Lt; - if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){ - Qrhs = make(Sub,Qrhs,make_int(rational(1))); - qstrict = false; - } - Qrhs = make(Times,c,Qrhs); - bool strict = pstrict || qstrict; - if(strict) - P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs)); - else - P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs)); + bool pstrict = op(P) == Lt; + if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){ + Qrhs = make(Sub,Qrhs,make_int(rational(1))); + qstrict = false; + } + Qrhs = make(Times,c,Qrhs); + bool strict = pstrict || qstrict; + if(strict) + P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs)); + else + P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs)); } iz3mgr::ast iz3mgr::sum_inequalities(const std::vector &coeffs, const std::vector &ineqs, bool round_off){ - ast zero = make_int("0"); - ast thing = make(Leq,zero,zero); - for(unsigned i = 0; i < ineqs.size(); i++){ - linear_comb(thing,coeffs[i],ineqs[i], round_off); - } - thing = simplify_ineq(thing); - return thing; + ast zero = make_int("0"); + ast thing = make(Leq,zero,zero); + for(unsigned i = 0; i < ineqs.size(); i++){ + linear_comb(thing,coeffs[i],ineqs[i], round_off); + } + thing = simplify_ineq(thing); + return thing; } void iz3mgr::mk_idiv(const ast& t, const rational &d, ast &whole, ast &frac){ - opr o = op(t); - if(o == Plus){ - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - mk_idiv(arg(t,i),d,whole,frac); - return; - } - else if(o == Times){ - rational coeff; - if(is_numeral(arg(t,0),coeff)){ - if(gcd(coeff,d) == d){ - whole = make(Plus,whole,make(Times,make_int(coeff/d),arg(t,1))); - return; - } + opr o = op(t); + if(o == Plus){ + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + mk_idiv(arg(t,i),d,whole,frac); + return; } - } - frac = make(Plus,frac,t); + else if(o == Times){ + rational coeff; + if(is_numeral(arg(t,0),coeff)){ + if(gcd(coeff,d) == d){ + whole = make(Plus,whole,make(Times,make_int(coeff/d),arg(t,1))); + return; + } + } + } + frac = make(Plus,frac,t); } iz3mgr::ast iz3mgr::mk_idiv(const ast& q, const rational &d){ - ast t = z3_simplify(q); - if(d == rational(1)) - return t; - else { - ast whole = make_int("0"); - ast frac = whole; - mk_idiv(t,d,whole,frac); - return z3_simplify(make(Plus,whole,make(Idiv,z3_simplify(frac),make_int(d)))); - } + ast t = z3_simplify(q); + if(d == rational(1)) + return t; + else { + ast whole = make_int("0"); + ast frac = whole; + mk_idiv(t,d,whole,frac); + return z3_simplify(make(Plus,whole,make(Idiv,z3_simplify(frac),make_int(d)))); + } } iz3mgr::ast iz3mgr::mk_idiv(const ast& t, const ast &d){ - rational r; - if(is_numeral(d,r)) - return mk_idiv(t,r); - return make(Idiv,t,d); + rational r; + if(is_numeral(d,r)) + return mk_idiv(t,r); + return make(Idiv,t,d); } // does variable occur in expression? int iz3mgr::occurs_in1(stl_ext::hash_map &occurs_in_memo,ast var, ast e){ - std::pair foo(e,false); - std::pair::iterator,bool> bar = occurs_in_memo.insert(foo); - bool &res = bar.first->second; - if(bar.second){ - if(e == var) res = true; - int nargs = num_args(e); - for(int i = 0; i < nargs; i++) - res |= occurs_in1(occurs_in_memo,var,arg(e,i)); - } - return res; + std::pair foo(e,false); + std::pair::iterator,bool> bar = occurs_in_memo.insert(foo); + bool &res = bar.first->second; + if(bar.second){ + if(e == var) res = true; + int nargs = num_args(e); + for(int i = 0; i < nargs; i++) + res |= occurs_in1(occurs_in_memo,var,arg(e,i)); + } + return res; } int iz3mgr::occurs_in(ast var, ast e){ - hash_map memo; - return occurs_in1(memo,var,e); + hash_map memo; + return occurs_in1(memo,var,e); } bool iz3mgr::solve_arith(const ast &v, const ast &x, const ast &y, ast &res){ - if(occurs_in(v,y)) - return false; - if(op(x) == Plus){ - int n = num_args(x); - for(int i = 0; i < n; i++){ - if(arg(x,i) == v){ - res = z3_simplify(make(Sub, y, make(Sub, x, v))); - return true; - } + if(occurs_in(v,y)) + return false; + if(op(x) == Plus){ + int n = num_args(x); + for(int i = 0; i < n; i++){ + if(arg(x,i) == v){ + res = z3_simplify(make(Sub, y, make(Sub, x, v))); + return true; + } + } } - } - return false; + return false; } // find a controlling equality for a given variable v in a term @@ -798,103 +798,103 @@ bool iz3mgr::solve_arith(const ast &v, const ast &x, const ast &y, ast &res){ // returns t, or null if no such iz3mgr::ast iz3mgr::cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, ast v, ast e){ - if(is_not(e)) return cont_eq(cont_eq_memo, !truth,v,arg(e,0)); - if(cont_eq_memo.find(e) != cont_eq_memo.end()) - return ast(); - cont_eq_memo.insert(e); - if(!truth && op(e) == Equal){ - if(arg(e,0) == v && !occurs_in(v,arg(e,1))) return(arg(e,1)); - if(arg(e,1) == v && !occurs_in(v,arg(e,0))) return(arg(e,0)); - ast res; - if(solve_arith(v,arg(e,0),arg(e,1),res)) return res; - if(solve_arith(v,arg(e,1),arg(e,0),res)) return res; - } - if((!truth && op(e) == And) || (truth && op(e) == Or)){ - int nargs = num_args(e); - for(int i = 0; i < nargs; i++){ - ast res = cont_eq(cont_eq_memo, truth, v, arg(e,i)); - if(!res.null()) return res; + if(is_not(e)) return cont_eq(cont_eq_memo, !truth,v,arg(e,0)); + if(cont_eq_memo.find(e) != cont_eq_memo.end()) + return ast(); + cont_eq_memo.insert(e); + if(!truth && op(e) == Equal){ + if(arg(e,0) == v && !occurs_in(v,arg(e,1))) return(arg(e,1)); + if(arg(e,1) == v && !occurs_in(v,arg(e,0))) return(arg(e,0)); + ast res; + if(solve_arith(v,arg(e,0),arg(e,1),res)) return res; + if(solve_arith(v,arg(e,1),arg(e,0),res)) return res; } - } - if(truth && op(e) == Implies){ - ast res = cont_eq(cont_eq_memo, !truth, v, arg(e,0)); - if(!res.null()) return res; - res = cont_eq(cont_eq_memo, truth, v, arg(e,1)); - if(!res.null()) return res; - } - return ast(); + if((!truth && op(e) == And) || (truth && op(e) == Or)){ + int nargs = num_args(e); + for(int i = 0; i < nargs; i++){ + ast res = cont_eq(cont_eq_memo, truth, v, arg(e,i)); + if(!res.null()) return res; + } + } + if(truth && op(e) == Implies){ + ast res = cont_eq(cont_eq_memo, !truth, v, arg(e,0)); + if(!res.null()) return res; + res = cont_eq(cont_eq_memo, truth, v, arg(e,1)); + if(!res.null()) return res; + } + return ast(); } - // substitute a term t for unbound occurrences of variable v in e +// substitute a term t for unbound occurrences of variable v in e iz3mgr::ast iz3mgr::subst(stl_ext::hash_map &subst_memo, ast var, ast t, ast e){ - if(e == var) return t; - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = subst_memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - int nargs = num_args(e); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = subst(subst_memo,var,t,arg(e,i)); - opr f = op(e); - if(f == Equal && args[0] == args[1]) res = mk_true(); - else res = clone(e,args); - } - return res; + if(e == var) return t; + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = subst_memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + int nargs = num_args(e); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = subst(subst_memo,var,t,arg(e,i)); + opr f = op(e); + if(f == Equal && args[0] == args[1]) res = mk_true(); + else res = clone(e,args); + } + return res; } iz3mgr::ast iz3mgr::subst(ast var, ast t, ast e){ - hash_map memo; - return subst(memo,var,t,e); + hash_map memo; + return subst(memo,var,t,e); } iz3mgr::ast iz3mgr::subst(stl_ext::hash_map &subst_memo,ast e){ - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = subst_memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - int nargs = num_args(e); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = subst(subst_memo,arg(e,i)); - opr f = op(e); - if(f == Equal && args[0] == args[1]) res = mk_true(); - else res = clone(e,args); - } - return res; + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = subst_memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + int nargs = num_args(e); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = subst(subst_memo,arg(e,i)); + opr f = op(e); + if(f == Equal && args[0] == args[1]) res = mk_true(); + else res = clone(e,args); + } + return res; } - // apply a quantifier to a formula, with some optimizations - // 1) bound variable does not occur -> no quantifier - // 2) bound variable must be equal to some term -> substitute +// apply a quantifier to a formula, with some optimizations +// 1) bound variable does not occur -> no quantifier +// 2) bound variable must be equal to some term -> substitute iz3mgr::ast iz3mgr::apply_quant(opr quantifier, ast var, ast e){ - if((quantifier == Forall && op(e) == And) - || (quantifier == Exists && op(e) == Or)){ - int n = num_args(e); - std::vector args(n); - for(int i = 0; i < n; i++) - args[i] = apply_quant(quantifier,var,arg(e,i)); - return make(op(e),args); - } - if(!occurs_in(var,e))return e; - hash_set cont_eq_memo; - ast cterm = cont_eq(cont_eq_memo, quantifier == Forall, var, e); - if(!cterm.null()){ - return subst(var,cterm,e); - } - std::vector bvs; bvs.push_back(var); - return make_quant(quantifier,bvs,e); + if((quantifier == Forall && op(e) == And) + || (quantifier == Exists && op(e) == Or)){ + int n = num_args(e); + std::vector args(n); + for(int i = 0; i < n; i++) + args[i] = apply_quant(quantifier,var,arg(e,i)); + return make(op(e),args); + } + if(!occurs_in(var,e))return e; + hash_set cont_eq_memo; + ast cterm = cont_eq(cont_eq_memo, quantifier == Forall, var, e); + if(!cterm.null()){ + return subst(var,cterm,e); + } + std::vector bvs; bvs.push_back(var); + return make_quant(quantifier,bvs,e); } #if 0 void iz3mgr::get_bound_substitutes(stl_ext::hash_map &memo, const ast &e, const ast &var, std::vector &substs){ - std::pair foo(e,false); - std::pair::iterator,bool> bar = memo.insert(foo); - if(bar.second){ - if(op(e) == - } + std::pair foo(e,false); + std::pair::iterator,bool> bar = memo.insert(foo); + if(bar.second){ + if(op(e) == + } -} + } #endif diff --git a/src/interp/iz3mgr.h b/src/interp/iz3mgr.h index 4ae39ef46..3f4138354 100755 --- a/src/interp/iz3mgr.h +++ b/src/interp/iz3mgr.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3mgr.h + iz3mgr.h -Abstract: + Abstract: - A wrapper around an ast manager, providing convenience methods. + A wrapper around an ast manager, providing convenience methods. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3MGR_H #define IZ3MGR_H @@ -58,87 +58,87 @@ typedef ast raw_ast; /** Wrapper around an ast pointer */ class ast_i { protected: - raw_ast *_ast; + raw_ast *_ast; public: - raw_ast * const &raw() const {return _ast;} - ast_i(raw_ast *a){_ast = a;} + raw_ast * const &raw() const {return _ast;} + ast_i(raw_ast *a){_ast = a;} - ast_i(){_ast = 0;} - bool eq(const ast_i &other) const { - return _ast == other._ast; - } - bool lt(const ast_i &other) const { - return _ast->get_id() < other._ast->get_id(); - } - friend bool operator==(const ast_i &x, const ast_i&y){ - return x.eq(y); - } - friend bool operator!=(const ast_i &x, const ast_i&y){ - return !x.eq(y); - } - friend bool operator<(const ast_i &x, const ast_i&y){ - return x.lt(y); - } - size_t hash() const {return _ast->get_id();} - bool null() const {return !_ast;} + ast_i(){_ast = 0;} + bool eq(const ast_i &other) const { + return _ast == other._ast; + } + bool lt(const ast_i &other) const { + return _ast->get_id() < other._ast->get_id(); + } + friend bool operator==(const ast_i &x, const ast_i&y){ + return x.eq(y); + } + friend bool operator!=(const ast_i &x, const ast_i&y){ + return !x.eq(y); + } + friend bool operator<(const ast_i &x, const ast_i&y){ + return x.lt(y); + } + size_t hash() const {return _ast->get_id();} + bool null() const {return !_ast;} }; /** Reference counting verison of above */ class ast_r : public ast_i { - ast_manager *_m; + ast_manager *_m; public: - ast_r(ast_manager *m, raw_ast *a) : ast_i(a) { - _m = m; - m->inc_ref(a); - } + ast_r(ast_manager *m, raw_ast *a) : ast_i(a) { + _m = m; + m->inc_ref(a); + } - ast_r() {_m = 0;} + ast_r() {_m = 0;} - ast_r(const ast_r &other) : ast_i(other) { - _m = other._m; - _m->inc_ref(_ast); - } + ast_r(const ast_r &other) : ast_i(other) { + _m = other._m; + _m->inc_ref(_ast); + } - ast_r &operator=(const ast_r &other) { - if(_ast) - _m->dec_ref(_ast); - _ast = other._ast; - _m = other._m; - _m->inc_ref(_ast); - return *this; - } + ast_r &operator=(const ast_r &other) { + if(_ast) + _m->dec_ref(_ast); + _ast = other._ast; + _m = other._m; + _m->inc_ref(_ast); + return *this; + } - ~ast_r(){ - if(_ast) - _m->dec_ref(_ast); - } + ~ast_r(){ + if(_ast) + _m->dec_ref(_ast); + } - ast_manager *mgr() const {return _m;} + ast_manager *mgr() const {return _m;} }; // to make ast_r hashable namespace hash_space { - template <> - class hash { - public: - size_t operator()(const ast_r &s) const { - return s.raw()->get_id(); - } - }; + template <> + class hash { + public: + size_t operator()(const ast_r &s) const { + return s.raw()->get_id(); + } + }; } // to make ast_r usable in ordered collections namespace std { - template <> - class less { - public: - bool operator()(const ast_r &s, const ast_r &t) const { - // return s.raw() < t.raw(); - return s.raw()->get_id() < t.raw()->get_id(); - } - }; + template <> + class less { + public: + bool operator()(const ast_r &s, const ast_r &t) const { + // return s.raw() < t.raw(); + return s.raw()->get_id() < t.raw()->get_id(); + } + }; } @@ -147,571 +147,571 @@ namespace std { class iz3mgr { public: - typedef ast_r ast; - // typedef decl_kind opr; - typedef func_decl *symb; - typedef sort *type; - typedef ast_r z3pf; - typedef decl_kind pfrule; - - enum opr { - True, - False, - And, - Or, - Not, - Iff, - Ite, - Equal, - Implies, - Distinct, - Xor, - Oeq, - Interp, - Leq, - Geq, - Lt, - Gt, - Plus, - Sub, - Uminus, - Times, - Div, - Idiv, - Rem, - Mod, - Power, - ToReal, - ToInt, - IsInt, - Select, - Store, - ConstArray, - ArrayDefault, - ArrayMap, - SetUnion, - SetIntersect, - SetDifference, - SetComplement, - SetSubSet, - AsArray, - Numeral, - Forall, - Exists, - Variable, - Uninterpreted, - Other - }; - - opr op(const ast &t); - - unsigned ast_id(const ast &x) - { - return to_expr(x.raw())->get_id(); - } - - /** Overloads for constructing ast. */ - - ast make_var(const std::string &name, type ty); - ast make(opr op, const std::vector &args); - ast make(opr op); - ast make(opr op, const ast &arg0); - ast make(opr op, const ast &arg0, const ast &arg1); - ast make(opr op, const ast &arg0, const ast &arg1, const ast &arg2); - ast make(symb sym, const std::vector &args); - ast make(symb sym); - ast make(symb sym, const ast &arg0); - ast make(symb sym, const ast &arg0, const ast &arg1); - ast make(symb sym, const ast &arg0, const ast &arg1, const ast &arg2); - ast make_quant(opr op, const std::vector &bvs, ast &body); - ast clone(const ast &t, const std::vector &args); - - ast_manager &m() {return m_manager;} - - ast cook(raw_ast *a) {return ast(&m_manager,a);} - - std::vector cook(ptr_vector v) { - std::vector _v(v.size()); - for(unsigned i = 0; i < v.size(); i++) - _v[i] = cook(v[i]); - return _v; - } - - raw_ast *uncook(const ast &a) { - m_manager.inc_ref(a.raw()); - return a.raw(); - } - - /** Methods for destructing ast. */ - - - int num_args(ast t){ - ast_kind dk = t.raw()->get_kind(); - switch(dk){ - case AST_APP: - return to_app(t.raw())->get_num_args(); - case AST_QUANTIFIER: - return 1; - case AST_VAR: - return 0; - default:; - } - assert(0); - return 0; - } - - ast arg(const ast &t, int i){ - ast_kind dk = t.raw()->get_kind(); - switch(dk){ - case AST_APP: - return cook(to_app(t.raw())->get_arg(i)); - case AST_QUANTIFIER: - return cook(to_quantifier(t.raw())->get_expr()); - default:; - } - assert(0); - return ast(); - } - - void get_args(const ast &t, std::vector &res){ - res.resize(num_args(t)); - for(unsigned i = 0; i < res.size(); i++) - res[i] = arg(t,i); - } - - symb sym(ast t){ - raw_ast *_ast = t.raw(); - return is_app(_ast) ? to_app(_ast)->get_decl() : 0; - } - - std::string string_of_symbol(symb s){ - symbol _s = s->get_name(); - if (_s.is_numerical()) { - std::ostringstream buffer; - buffer << _s.get_num(); - return buffer.str(); - } - else { - return _s.bare_str(); - } - } - - type get_type(ast t){ - return m().get_sort(to_expr(t.raw())); - } - - std::string string_of_numeral(const ast& t){ - rational r; - expr* e = to_expr(t.raw()); - assert(e); - if (m_arith_util.is_numeral(e, r)) - return r.to_string(); - assert(0); - return "NaN"; - } - - bool is_numeral(const ast& t, rational &r){ - expr* e = to_expr(t.raw()); - assert(e); - return m_arith_util.is_numeral(e, r); - } - - rational get_coeff(const ast& t){ - rational res; - if(op(t) == Times && is_numeral(arg(t,0),res)) - return res; - return rational(1); - } - - ast get_linear_var(const ast& t){ - rational res; - if(op(t) == Times && is_numeral(arg(t,0),res)) - return arg(t,1); - return t; - } - - int get_quantifier_num_bound(const ast &t) { - return to_quantifier(t.raw())->get_num_decls(); - } - - std::string get_quantifier_bound_name(const ast &t, unsigned i) { - return to_quantifier(t.raw())->get_decl_names()[i].bare_str(); - } - - type get_quantifier_bound_type(const ast &t, unsigned i) { - return to_quantifier(t.raw())->get_decl_sort(i); - } - - ast get_quantifier_body(const ast &t) { - return cook(to_quantifier(t.raw())->get_expr()); - } - - unsigned get_variable_index_value(const ast &t) { - var* va = to_var(t.raw()); - return va->get_idx(); - } - - bool is_bool_type(type t){ - family_id fid = to_sort(t)->get_family_id(); - decl_kind k = to_sort(t)->get_decl_kind(); - return fid == m().get_basic_family_id() && k == BOOL_SORT; - } - - bool is_array_type(type t){ - family_id fid = to_sort(t)->get_family_id(); - decl_kind k = to_sort(t)->get_decl_kind(); - return fid == m_array_fid && k == ARRAY_SORT; - } - - type get_range_type(symb s){ - return to_func_decl(s)->get_range(); - } - - int get_num_parameters(const symb &s){ - return to_func_decl(s)->get_num_parameters(); - } - - ast get_ast_parameter(const symb &s, int idx){ - return cook(to_func_decl(s)->get_parameters()[idx].get_ast()); - } - - enum lemma_theory {ArithTheory,ArrayTheory,UnknownTheory}; - - lemma_theory get_theory_lemma_theory(const ast &proof){ - symb s = sym(proof); - ::symbol p0; - bool ok = s->get_parameter(0).is_symbol(p0); - if(!ok) return UnknownTheory; - std::string foo(p0.bare_str()); - if(foo == "arith") - return ArithTheory; - if(foo == "array") - return ArrayTheory; - return UnknownTheory; - } - - enum lemma_kind {FarkasKind,Leq2EqKind,Eq2LeqKind,GCDTestKind,AssignBoundsKind,EqPropagateKind,ArithMysteryKind,UnknownKind}; - - lemma_kind get_theory_lemma_kind(const ast &proof){ - symb s = sym(proof); - if(s->get_num_parameters() < 2) { - return ArithMysteryKind; // Bad -- Z3 hasn't told us - } - ::symbol p0; - bool ok = s->get_parameter(1).is_symbol(p0); - if(!ok) return UnknownKind; - std::string foo(p0.bare_str()); - if(foo == "farkas") - return FarkasKind; - if(foo == "triangle-eq") - return is_not(arg(conc(proof),0)) ? Eq2LeqKind : Leq2EqKind; - if(foo == "gcd-test") - return GCDTestKind; - if(foo == "assign-bounds") - return AssignBoundsKind; - if(foo == "eq-propagate") - return EqPropagateKind; - return UnknownKind; - } - - void get_farkas_coeffs(const ast &proof, std::vector& coeffs); - - void get_farkas_coeffs(const ast &proof, std::vector& rats); - - void get_assign_bounds_coeffs(const ast &proof, std::vector& rats); - - void get_assign_bounds_coeffs(const ast &proof, std::vector& rats); - - void get_assign_bounds_rule_coeffs(const ast &proof, std::vector& rats); - - void get_assign_bounds_rule_coeffs(const ast &proof, std::vector& rats); - - bool is_farkas_coefficient_negative(const ast &proof, int n); - - bool is_true(ast t){ - return op(t) == True; - } - - bool is_false(ast t){ - return op(t) == False; - } - - bool is_iff(ast t){ - return op(t) == Iff; - } - - bool is_or(ast t){ - return op(t) == Or; - } - - bool is_not(ast t){ - return op(t) == Not; - } - - /** Simplify an expression using z3 simplifier */ - - ast z3_simplify(const ast& e); - - /** Simplify, sorting sums */ - ast z3_really_simplify(const ast &e); - - - // Some constructors that simplify things - - ast mk_not(ast x){ - opr o = op(x); - if(o == True) return make(False); - if(o == False) return make(True); - if(o == Not) return arg(x,0); - return make(Not,x); - } - - ast mk_and(ast x, ast y){ - opr ox = op(x); - opr oy = op(y); - if(ox == True) return y; - if(oy == True) return x; - if(ox == False) return x; - if(oy == False) return y; - if(x == y) return x; - return make(And,x,y); - } - - ast mk_or(ast x, ast y){ - opr ox = op(x); - opr oy = op(y); - if(ox == False) return y; - if(oy == False) return x; - if(ox == True) return x; - if(oy == True) return y; - if(x == y) return x; - return make(Or,x,y); - } - - ast mk_implies(ast x, ast y){ - opr ox = op(x); - opr oy = op(y); - if(ox == True) return y; - if(oy == False) return mk_not(x); - if(ox == False) return mk_true(); - if(oy == True) return y; - if(x == y) return mk_true(); - return make(Implies,x,y); - } - - ast mk_or(const std::vector &x){ - ast res = mk_false(); - for(unsigned i = 0; i < x.size(); i++) - res = mk_or(res,x[i]); - return res; - } - - ast mk_and(const std::vector &x){ - std::vector conjs; - for(unsigned i = 0; i < x.size(); i++){ - const ast &e = x[i]; - opr o = op(e); - if(o == False) - return mk_false(); - if(o != True) - conjs.push_back(e); - } - if(conjs.size() == 0) - return mk_true(); - if(conjs.size() == 1) - return conjs[0]; - return make(And,conjs); - } - - ast mk_equal(ast x, ast y){ - if(x == y) return make(True); - opr ox = op(x); - opr oy = op(y); - if(ox == True) return y; - if(oy == True) return x; - if(ox == False) return mk_not(y); - if(oy == False) return mk_not(x); - if(ox == False && oy == True) return make(False); - if(oy == False && ox == True) return make(False); - return make(Equal,x,y); - } - - ast z3_ite(ast x, ast y, ast z){ - opr ox = op(x); - opr oy = op(y); - opr oz = op(z); - if(ox == True) return y; - if(ox == False) return z; - if(y == z) return y; - if(oy == True && oz == False) return x; - if(oz == True && oy == False) return mk_not(x); - return make(Ite,x,y,z); - } - - ast make_int(const std::string &s) { - sort *r = m().mk_sort(m_arith_fid, INT_SORT); - return cook(m_arith_util.mk_numeral(rational(s.c_str()),r)); - } - - ast make_int(const rational &s) { - sort *r = m().mk_sort(m_arith_fid, INT_SORT); - return cook(m_arith_util.mk_numeral(s,r)); - } - - ast make_real(const std::string &s) { - sort *r = m().mk_sort(m_arith_fid, REAL_SORT); - return cook(m_arith_util.mk_numeral(rational(s.c_str()),r)); - } - - ast make_real(const rational &s) { - sort *r = m().mk_sort(m_arith_fid, REAL_SORT); - return cook(m_arith_util.mk_numeral(s,r)); - } - - ast mk_false() { return make(False); } - - ast mk_true() { return make(True); } - - ast mk_fresh_constant(char const * prefix, type s){ - return cook(m().mk_fresh_const(prefix, s)); - } - - type bool_type() { - ::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT); - return s; - } - - type int_type() { - ::sort *s = m().mk_sort(m_arith_fid, INT_SORT); - return s; - } - - type real_type() { - ::sort *s = m().mk_sort(m_arith_fid, REAL_SORT); - return s; - } - - type array_type(type d, type r) { - parameter params[2] = { parameter(d), parameter(to_sort(r)) }; - ::sort * s = m().mk_sort(m_array_fid, ARRAY_SORT, 2, params); - return s; - } - - symb function(const std::string &str_name, unsigned arity, type *domain, type range) { - ::symbol name = ::symbol(str_name.c_str()); - std::vector< ::sort *> sv(arity); - for(unsigned i = 0; i < arity; i++) - sv[i] = domain[i]; - ::func_decl* d = m().mk_func_decl(name,arity,&sv[0],range); - return d; - } - - void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false); - - ast sum_inequalities(const std::vector &coeffs, const std::vector &ineqs, bool round_off = false); - - ast simplify_ineq(const ast &ineq){ - ast res = make(op(ineq),arg(ineq,0),z3_simplify(arg(ineq,1))); - return res; - } - - void mk_idiv(const ast& t, const rational &d, ast &whole, ast &frac); - - ast mk_idiv(const ast& t, const rational &d); - - ast mk_idiv(const ast& t, const ast &d); - - /** methods for destructing proof terms */ - - pfrule pr(const z3pf &t); - - int num_prems(const z3pf &t){return to_app(t.raw())->get_num_args()-1;} - - z3pf prem(const z3pf &t, int n){return arg(t,n);} - - z3pf conc(const z3pf &t){return arg(t,num_prems(t));} - - - /* quantifier handling */ - - // substitute a term t for unbound occurrences of variable v in e - - ast subst(ast var, ast t, ast e); - - // apply a substitution defined by a map - ast subst(stl_ext::hash_map &map, ast e); - - // apply a quantifier to a formula, with some optimizations - // 1) bound variable does not occur -> no quantifier - // 2) bound variable must be equal to some term -> substitute - - ast apply_quant(opr quantifier, ast var, ast e); - - - /** For debugging */ - void show(ast); - - void show_symb(symb s); - - /** Constructor */ - - void print_lit(ast lit); - - void print_expr(std::ostream &s, const ast &e); - - void print_clause(std::ostream &s, std::vector &cls); - - void print_sat_problem(std::ostream &out, const ast &t); - - void show_clause(std::vector &cls); - - static void pretty_print(std::ostream &f, const std::string &s); - - iz3mgr(ast_manager &_m_manager) - : m_manager(_m_manager), - m_arith_util(_m_manager) + typedef ast_r ast; + // typedef decl_kind opr; + typedef func_decl *symb; + typedef sort *type; + typedef ast_r z3pf; + typedef decl_kind pfrule; + + enum opr { + True, + False, + And, + Or, + Not, + Iff, + Ite, + Equal, + Implies, + Distinct, + Xor, + Oeq, + Interp, + Leq, + Geq, + Lt, + Gt, + Plus, + Sub, + Uminus, + Times, + Div, + Idiv, + Rem, + Mod, + Power, + ToReal, + ToInt, + IsInt, + Select, + Store, + ConstArray, + ArrayDefault, + ArrayMap, + SetUnion, + SetIntersect, + SetDifference, + SetComplement, + SetSubSet, + AsArray, + Numeral, + Forall, + Exists, + Variable, + Uninterpreted, + Other + }; + + opr op(const ast &t); + + unsigned ast_id(const ast &x) { - m_basic_fid = m().get_basic_family_id(); - m_arith_fid = m().mk_family_id("arith"); - m_bv_fid = m().mk_family_id("bv"); - m_array_fid = m().mk_family_id("array"); - m_dt_fid = m().mk_family_id("datatype"); - m_datalog_fid = m().mk_family_id("datalog_relation"); + return to_expr(x.raw())->get_id(); } + + /** Overloads for constructing ast. */ + + ast make_var(const std::string &name, type ty); + ast make(opr op, const std::vector &args); + ast make(opr op); + ast make(opr op, const ast &arg0); + ast make(opr op, const ast &arg0, const ast &arg1); + ast make(opr op, const ast &arg0, const ast &arg1, const ast &arg2); + ast make(symb sym, const std::vector &args); + ast make(symb sym); + ast make(symb sym, const ast &arg0); + ast make(symb sym, const ast &arg0, const ast &arg1); + ast make(symb sym, const ast &arg0, const ast &arg1, const ast &arg2); + ast make_quant(opr op, const std::vector &bvs, ast &body); + ast clone(const ast &t, const std::vector &args); + + ast_manager &m() {return m_manager;} + + ast cook(raw_ast *a) {return ast(&m_manager,a);} + + std::vector cook(ptr_vector v) { + std::vector _v(v.size()); + for(unsigned i = 0; i < v.size(); i++) + _v[i] = cook(v[i]); + return _v; + } + + raw_ast *uncook(const ast &a) { + m_manager.inc_ref(a.raw()); + return a.raw(); + } + + /** Methods for destructing ast. */ + + + int num_args(ast t){ + ast_kind dk = t.raw()->get_kind(); + switch(dk){ + case AST_APP: + return to_app(t.raw())->get_num_args(); + case AST_QUANTIFIER: + return 1; + case AST_VAR: + return 0; + default:; + } + assert(0); + return 0; + } + + ast arg(const ast &t, int i){ + ast_kind dk = t.raw()->get_kind(); + switch(dk){ + case AST_APP: + return cook(to_app(t.raw())->get_arg(i)); + case AST_QUANTIFIER: + return cook(to_quantifier(t.raw())->get_expr()); + default:; + } + assert(0); + return ast(); + } + + void get_args(const ast &t, std::vector &res){ + res.resize(num_args(t)); + for(unsigned i = 0; i < res.size(); i++) + res[i] = arg(t,i); + } + + symb sym(ast t){ + raw_ast *_ast = t.raw(); + return is_app(_ast) ? to_app(_ast)->get_decl() : 0; + } + + std::string string_of_symbol(symb s){ + symbol _s = s->get_name(); + if (_s.is_numerical()) { + std::ostringstream buffer; + buffer << _s.get_num(); + return buffer.str(); + } + else { + return _s.bare_str(); + } + } + + type get_type(ast t){ + return m().get_sort(to_expr(t.raw())); + } + + std::string string_of_numeral(const ast& t){ + rational r; + expr* e = to_expr(t.raw()); + assert(e); + if (m_arith_util.is_numeral(e, r)) + return r.to_string(); + assert(0); + return "NaN"; + } + + bool is_numeral(const ast& t, rational &r){ + expr* e = to_expr(t.raw()); + assert(e); + return m_arith_util.is_numeral(e, r); + } + + rational get_coeff(const ast& t){ + rational res; + if(op(t) == Times && is_numeral(arg(t,0),res)) + return res; + return rational(1); + } + + ast get_linear_var(const ast& t){ + rational res; + if(op(t) == Times && is_numeral(arg(t,0),res)) + return arg(t,1); + return t; + } + + int get_quantifier_num_bound(const ast &t) { + return to_quantifier(t.raw())->get_num_decls(); + } + + std::string get_quantifier_bound_name(const ast &t, unsigned i) { + return to_quantifier(t.raw())->get_decl_names()[i].bare_str(); + } + + type get_quantifier_bound_type(const ast &t, unsigned i) { + return to_quantifier(t.raw())->get_decl_sort(i); + } + + ast get_quantifier_body(const ast &t) { + return cook(to_quantifier(t.raw())->get_expr()); + } + + unsigned get_variable_index_value(const ast &t) { + var* va = to_var(t.raw()); + return va->get_idx(); + } + + bool is_bool_type(type t){ + family_id fid = to_sort(t)->get_family_id(); + decl_kind k = to_sort(t)->get_decl_kind(); + return fid == m().get_basic_family_id() && k == BOOL_SORT; + } + + bool is_array_type(type t){ + family_id fid = to_sort(t)->get_family_id(); + decl_kind k = to_sort(t)->get_decl_kind(); + return fid == m_array_fid && k == ARRAY_SORT; + } + + type get_range_type(symb s){ + return to_func_decl(s)->get_range(); + } + + int get_num_parameters(const symb &s){ + return to_func_decl(s)->get_num_parameters(); + } + + ast get_ast_parameter(const symb &s, int idx){ + return cook(to_func_decl(s)->get_parameters()[idx].get_ast()); + } + + enum lemma_theory {ArithTheory,ArrayTheory,UnknownTheory}; + + lemma_theory get_theory_lemma_theory(const ast &proof){ + symb s = sym(proof); + ::symbol p0; + bool ok = s->get_parameter(0).is_symbol(p0); + if(!ok) return UnknownTheory; + std::string foo(p0.bare_str()); + if(foo == "arith") + return ArithTheory; + if(foo == "array") + return ArrayTheory; + return UnknownTheory; + } + + enum lemma_kind {FarkasKind,Leq2EqKind,Eq2LeqKind,GCDTestKind,AssignBoundsKind,EqPropagateKind,ArithMysteryKind,UnknownKind}; + + lemma_kind get_theory_lemma_kind(const ast &proof){ + symb s = sym(proof); + if(s->get_num_parameters() < 2) { + return ArithMysteryKind; // Bad -- Z3 hasn't told us + } + ::symbol p0; + bool ok = s->get_parameter(1).is_symbol(p0); + if(!ok) return UnknownKind; + std::string foo(p0.bare_str()); + if(foo == "farkas") + return FarkasKind; + if(foo == "triangle-eq") + return is_not(arg(conc(proof),0)) ? Eq2LeqKind : Leq2EqKind; + if(foo == "gcd-test") + return GCDTestKind; + if(foo == "assign-bounds") + return AssignBoundsKind; + if(foo == "eq-propagate") + return EqPropagateKind; + return UnknownKind; + } + + void get_farkas_coeffs(const ast &proof, std::vector& coeffs); + + void get_farkas_coeffs(const ast &proof, std::vector& rats); + + void get_assign_bounds_coeffs(const ast &proof, std::vector& rats); + + void get_assign_bounds_coeffs(const ast &proof, std::vector& rats); + + void get_assign_bounds_rule_coeffs(const ast &proof, std::vector& rats); + + void get_assign_bounds_rule_coeffs(const ast &proof, std::vector& rats); + + bool is_farkas_coefficient_negative(const ast &proof, int n); + + bool is_true(ast t){ + return op(t) == True; + } + + bool is_false(ast t){ + return op(t) == False; + } + + bool is_iff(ast t){ + return op(t) == Iff; + } + + bool is_or(ast t){ + return op(t) == Or; + } + + bool is_not(ast t){ + return op(t) == Not; + } + + /** Simplify an expression using z3 simplifier */ + + ast z3_simplify(const ast& e); + + /** Simplify, sorting sums */ + ast z3_really_simplify(const ast &e); + + + // Some constructors that simplify things + + ast mk_not(ast x){ + opr o = op(x); + if(o == True) return make(False); + if(o == False) return make(True); + if(o == Not) return arg(x,0); + return make(Not,x); + } + + ast mk_and(ast x, ast y){ + opr ox = op(x); + opr oy = op(y); + if(ox == True) return y; + if(oy == True) return x; + if(ox == False) return x; + if(oy == False) return y; + if(x == y) return x; + return make(And,x,y); + } + + ast mk_or(ast x, ast y){ + opr ox = op(x); + opr oy = op(y); + if(ox == False) return y; + if(oy == False) return x; + if(ox == True) return x; + if(oy == True) return y; + if(x == y) return x; + return make(Or,x,y); + } + + ast mk_implies(ast x, ast y){ + opr ox = op(x); + opr oy = op(y); + if(ox == True) return y; + if(oy == False) return mk_not(x); + if(ox == False) return mk_true(); + if(oy == True) return y; + if(x == y) return mk_true(); + return make(Implies,x,y); + } + + ast mk_or(const std::vector &x){ + ast res = mk_false(); + for(unsigned i = 0; i < x.size(); i++) + res = mk_or(res,x[i]); + return res; + } + + ast mk_and(const std::vector &x){ + std::vector conjs; + for(unsigned i = 0; i < x.size(); i++){ + const ast &e = x[i]; + opr o = op(e); + if(o == False) + return mk_false(); + if(o != True) + conjs.push_back(e); + } + if(conjs.size() == 0) + return mk_true(); + if(conjs.size() == 1) + return conjs[0]; + return make(And,conjs); + } + + ast mk_equal(ast x, ast y){ + if(x == y) return make(True); + opr ox = op(x); + opr oy = op(y); + if(ox == True) return y; + if(oy == True) return x; + if(ox == False) return mk_not(y); + if(oy == False) return mk_not(x); + if(ox == False && oy == True) return make(False); + if(oy == False && ox == True) return make(False); + return make(Equal,x,y); + } + + ast z3_ite(ast x, ast y, ast z){ + opr ox = op(x); + opr oy = op(y); + opr oz = op(z); + if(ox == True) return y; + if(ox == False) return z; + if(y == z) return y; + if(oy == True && oz == False) return x; + if(oz == True && oy == False) return mk_not(x); + return make(Ite,x,y,z); + } + + ast make_int(const std::string &s) { + sort *r = m().mk_sort(m_arith_fid, INT_SORT); + return cook(m_arith_util.mk_numeral(rational(s.c_str()),r)); + } + + ast make_int(const rational &s) { + sort *r = m().mk_sort(m_arith_fid, INT_SORT); + return cook(m_arith_util.mk_numeral(s,r)); + } + + ast make_real(const std::string &s) { + sort *r = m().mk_sort(m_arith_fid, REAL_SORT); + return cook(m_arith_util.mk_numeral(rational(s.c_str()),r)); + } + + ast make_real(const rational &s) { + sort *r = m().mk_sort(m_arith_fid, REAL_SORT); + return cook(m_arith_util.mk_numeral(s,r)); + } + + ast mk_false() { return make(False); } + + ast mk_true() { return make(True); } + + ast mk_fresh_constant(char const * prefix, type s){ + return cook(m().mk_fresh_const(prefix, s)); + } + + type bool_type() { + ::sort *s = m().mk_sort(m_basic_fid, BOOL_SORT); + return s; + } + + type int_type() { + ::sort *s = m().mk_sort(m_arith_fid, INT_SORT); + return s; + } + + type real_type() { + ::sort *s = m().mk_sort(m_arith_fid, REAL_SORT); + return s; + } + + type array_type(type d, type r) { + parameter params[2] = { parameter(d), parameter(to_sort(r)) }; + ::sort * s = m().mk_sort(m_array_fid, ARRAY_SORT, 2, params); + return s; + } + + symb function(const std::string &str_name, unsigned arity, type *domain, type range) { + ::symbol name = ::symbol(str_name.c_str()); + std::vector< ::sort *> sv(arity); + for(unsigned i = 0; i < arity; i++) + sv[i] = domain[i]; + ::func_decl* d = m().mk_func_decl(name,arity,&sv[0],range); + return d; + } + + void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false); + + ast sum_inequalities(const std::vector &coeffs, const std::vector &ineqs, bool round_off = false); + + ast simplify_ineq(const ast &ineq){ + ast res = make(op(ineq),arg(ineq,0),z3_simplify(arg(ineq,1))); + return res; + } + + void mk_idiv(const ast& t, const rational &d, ast &whole, ast &frac); + + ast mk_idiv(const ast& t, const rational &d); + + ast mk_idiv(const ast& t, const ast &d); + + /** methods for destructing proof terms */ + + pfrule pr(const z3pf &t); + + int num_prems(const z3pf &t){return to_app(t.raw())->get_num_args()-1;} + + z3pf prem(const z3pf &t, int n){return arg(t,n);} + + z3pf conc(const z3pf &t){return arg(t,num_prems(t));} + + + /* quantifier handling */ + + // substitute a term t for unbound occurrences of variable v in e + + ast subst(ast var, ast t, ast e); + + // apply a substitution defined by a map + ast subst(stl_ext::hash_map &map, ast e); + + // apply a quantifier to a formula, with some optimizations + // 1) bound variable does not occur -> no quantifier + // 2) bound variable must be equal to some term -> substitute + + ast apply_quant(opr quantifier, ast var, ast e); + + + /** For debugging */ + void show(ast); + + void show_symb(symb s); + + /** Constructor */ + + void print_lit(ast lit); + + void print_expr(std::ostream &s, const ast &e); + + void print_clause(std::ostream &s, std::vector &cls); + + void print_sat_problem(std::ostream &out, const ast &t); + + void show_clause(std::vector &cls); + + static void pretty_print(std::ostream &f, const std::string &s); + + iz3mgr(ast_manager &_m_manager) + : m_manager(_m_manager), + m_arith_util(_m_manager) + { + m_basic_fid = m().get_basic_family_id(); + m_arith_fid = m().mk_family_id("arith"); + m_bv_fid = m().mk_family_id("bv"); + m_array_fid = m().mk_family_id("array"); + m_dt_fid = m().mk_family_id("datatype"); + m_datalog_fid = m().mk_family_id("datalog_relation"); + } iz3mgr(const iz3mgr& other) - : m_manager(other.m_manager), - m_arith_util(other.m_manager) - { - m_basic_fid = m().get_basic_family_id(); - m_arith_fid = m().mk_family_id("arith"); - m_bv_fid = m().mk_family_id("bv"); - m_array_fid = m().mk_family_id("array"); - m_dt_fid = m().mk_family_id("datatype"); - m_datalog_fid = m().mk_family_id("datalog_relation"); - } + : m_manager(other.m_manager), + m_arith_util(other.m_manager) + { + m_basic_fid = m().get_basic_family_id(); + m_arith_fid = m().mk_family_id("arith"); + m_bv_fid = m().mk_family_id("bv"); + m_array_fid = m().mk_family_id("array"); + m_dt_fid = m().mk_family_id("datatype"); + m_datalog_fid = m().mk_family_id("datalog_relation"); + } protected: - ast_manager &m_manager; - int occurs_in(ast var, ast e); + ast_manager &m_manager; + int occurs_in(ast var, ast e); private: - ast mki(family_id fid, decl_kind sk, int n, raw_ast **args); - ast make(opr op, int n, raw_ast **args); - ast make(symb sym, int n, raw_ast **args); - int occurs_in1(stl_ext::hash_map &occurs_in_memo, ast var, ast e); - bool solve_arith(const ast &v, const ast &x, const ast &y, ast &res); - ast cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, ast v, ast e); - ast subst(stl_ext::hash_map &subst_memo, ast var, ast t, ast e); + ast mki(family_id fid, decl_kind sk, int n, raw_ast **args); + ast make(opr op, int n, raw_ast **args); + ast make(symb sym, int n, raw_ast **args); + int occurs_in1(stl_ext::hash_map &occurs_in_memo, ast var, ast e); + bool solve_arith(const ast &v, const ast &x, const ast &y, ast &res); + ast cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, ast v, ast e); + ast subst(stl_ext::hash_map &subst_memo, ast var, ast t, ast e); - 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; - arith_util m_arith_util; + 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; + arith_util m_arith_util; }; #endif diff --git a/src/interp/iz3pp.cpp b/src/interp/iz3pp.cpp index d530a3bc6..26cefedb3 100644 --- a/src/interp/iz3pp.cpp +++ b/src/interp/iz3pp.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2013 Microsoft Corporation + Copyright (c) 2013 Microsoft Corporation -Module Name: + Module Name: - iz3pp.cpp + iz3pp.cpp -Abstract: + Abstract: - Pretty-print interpolation problems + Pretty-print interpolation problems -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ /* Copyright 2011 Microsoft Research. */ #include @@ -40,70 +40,70 @@ using namespace stl_ext; // We promise not to use this for hash_map with range destructor namespace stl_ext { - template <> + template <> class hash { - public: - size_t operator()(const expr *p) const { - return (size_t) p; - } - }; + public: + size_t operator()(const expr *p) const { + return (size_t) p; + } + }; } // TBD: algebraic data-types declarations will not be printed. class free_func_visitor { - ast_manager& m; - func_decl_set m_funcs; - obj_hashtable m_sorts; + ast_manager& m; + func_decl_set m_funcs; + obj_hashtable m_sorts; public: - free_func_visitor(ast_manager& m): m(m) {} - void operator()(var * n) { } - void operator()(app * n) { - m_funcs.insert(n->get_decl()); - class sort* s = m.get_sort(n); - if (s->get_family_id() == null_family_id) { - m_sorts.insert(s); + free_func_visitor(ast_manager& m): m(m) {} + void operator()(var * n) { } + void operator()(app * n) { + m_funcs.insert(n->get_decl()); + class sort* s = m.get_sort(n); + if (s->get_family_id() == null_family_id) { + m_sorts.insert(s); + } } - } - void operator()(quantifier * n) { } - func_decl_set& funcs() { return m_funcs; } - obj_hashtable& sorts() { return m_sorts; } + void operator()(quantifier * n) { } + func_decl_set& funcs() { return m_funcs; } + obj_hashtable& sorts() { return m_sorts; } }; class iz3pp_helper : public iz3mgr { public: - void print_tree(const ast &tree, hash_map &cnames, std::ostream &out){ - hash_map::iterator foo = cnames.find(to_expr(tree.raw())); - if(foo != cnames.end()){ - symbol nm = foo->second; - if (is_smt2_quoted_symbol(nm)) { - out << mk_smt2_quoted_symbol(nm); - } - else { - out << nm; - } + void print_tree(const ast &tree, hash_map &cnames, std::ostream &out){ + hash_map::iterator foo = cnames.find(to_expr(tree.raw())); + if(foo != cnames.end()){ + symbol nm = foo->second; + if (is_smt2_quoted_symbol(nm)) { + out << mk_smt2_quoted_symbol(nm); + } + else { + out << nm; + } + } + else if(op(tree) == And){ + out << "(and"; + int nargs = num_args(tree); + for(int i = 0; i < nargs; i++){ + out << " "; + print_tree(arg(tree,i), cnames, out); + } + out << ")"; + } + else if(op(tree) == Interp){ + out << "(interp "; + print_tree(arg(tree,0), cnames, out); + out << ")"; + } + else throw iz3pp_bad_tree(); } - else if(op(tree) == And){ - out << "(and"; - int nargs = num_args(tree); - for(int i = 0; i < nargs; i++){ - out << " "; - print_tree(arg(tree,i), cnames, out); - } - out << ")"; - } - else if(op(tree) == Interp){ - out << "(interp "; - print_tree(arg(tree,0), cnames, out); - out << ")"; - } - else throw iz3pp_bad_tree(); - } - iz3pp_helper(ast_manager &_m_manager) - : iz3mgr(_m_manager) {} + iz3pp_helper(ast_manager &_m_manager) + : iz3mgr(_m_manager) {} }; void iz3pp(ast_manager &m, @@ -111,75 +111,75 @@ void iz3pp(ast_manager &m, expr *tree, std::ostream& out) { - unsigned sz = cnsts_vec.size(); - expr* const* cnsts = &cnsts_vec[0]; + unsigned sz = cnsts_vec.size(); + expr* const* cnsts = &cnsts_vec[0]; - out << "(set-option :produce-interpolants true)\n"; + out << "(set-option :produce-interpolants true)\n"; - free_func_visitor visitor(m); - expr_mark visited; - bool print_low_level = true; // m_params.print_low_level_smt2(); + free_func_visitor visitor(m); + expr_mark visited; + bool print_low_level = true; // m_params.print_low_level_smt2(); #define PP(_e_) if (print_low_level) out << mk_smt_pp(_e_, m); else ast_smt2_pp(out, _e_, env); - smt2_pp_environment_dbg env(m); + smt2_pp_environment_dbg env(m); - for (unsigned i = 0; i < sz; ++i) { - expr* e = cnsts[i]; - for_each_expr(visitor, visited, e); - } + for (unsigned i = 0; i < sz; ++i) { + expr* e = cnsts[i]; + for_each_expr(visitor, visited, e); + } - // name all the constraints - hash_map cnames; - int ctr = 1; - for(unsigned i = 0; i < sz; i++){ - symbol nm; - std::ostringstream s; - s << "f!" << (ctr++); - cnames[cnsts[i]] = symbol(s.str().c_str()); - } + // name all the constraints + hash_map cnames; + int ctr = 1; + for(unsigned i = 0; i < sz; i++){ + symbol nm; + std::ostringstream s; + s << "f!" << (ctr++); + cnames[cnsts[i]] = symbol(s.str().c_str()); + } - func_decl_set &funcs = visitor.funcs(); - func_decl_set::iterator it = funcs.begin(), end = funcs.end(); + func_decl_set &funcs = visitor.funcs(); + func_decl_set::iterator it = funcs.begin(), end = funcs.end(); - obj_hashtable& sorts = visitor.sorts(); - obj_hashtable::iterator sit = sorts.begin(), send = sorts.end(); + obj_hashtable& sorts = visitor.sorts(); + obj_hashtable::iterator sit = sorts.begin(), send = sorts.end(); - for (; sit != send; ++sit) { - PP(*sit); - } + for (; sit != send; ++sit) { + PP(*sit); + } - for (; it != end; ++it) { - func_decl* f = *it; - if(f->get_family_id() == null_family_id){ - PP(f); - out << "\n"; + for (; it != end; ++it) { + func_decl* f = *it; + if(f->get_family_id() == null_family_id){ + PP(f); + out << "\n"; + } } - } - for (unsigned i = 0; i < sz; ++i) { - out << "(assert "; - expr* r = cnsts[i]; - symbol nm = cnames[r]; - out << "(! "; - PP(r); - out << " :named "; - if (is_smt2_quoted_symbol(nm)) { - out << mk_smt2_quoted_symbol(nm); + for (unsigned i = 0; i < sz; ++i) { + out << "(assert "; + expr* r = cnsts[i]; + symbol nm = cnames[r]; + out << "(! "; + PP(r); + out << " :named "; + if (is_smt2_quoted_symbol(nm)) { + out << mk_smt2_quoted_symbol(nm); + } + else { + out << nm; + } + out << ")"; + out << ")\n"; } - else { - out << nm; - } - out << ")"; + out << "(check-sat)\n"; + out << "(get-interpolant "; + iz3pp_helper pp(m); + pp.print_tree(pp.cook(tree),cnames,out); out << ")\n"; - } - out << "(check-sat)\n"; - out << "(get-interpolant "; - iz3pp_helper pp(m); - pp.print_tree(pp.cook(tree),cnames,out); - out << ")\n"; } diff --git a/src/interp/iz3pp.h b/src/interp/iz3pp.h index 3ea5925e8..bbb10a785 100644 --- a/src/interp/iz3pp.h +++ b/src/interp/iz3pp.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2013 Microsoft Corporation + Copyright (c) 2013 Microsoft Corporation -Module Name: + Module Name: - iz3pp.cpp + iz3pp.cpp -Abstract: + Abstract: - Pretty-print interpolation problems + Pretty-print interpolation problems -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3_PP_H #define IZ3_PP_H diff --git a/src/interp/iz3profiling.cpp b/src/interp/iz3profiling.cpp index 3237b7cd8..f3b3d0efc 100755 --- a/src/interp/iz3profiling.cpp +++ b/src/interp/iz3profiling.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3profiling.h + iz3profiling.h -Abstract: + Abstract: - Some routines for measuring performance. + Some routines for measuring performance. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -40,114 +40,114 @@ Revision History: static double current_time() { - static stopwatch sw; - static bool started = false; - if(!started){ - sw.start(); - started = true; - } - return sw.get_current_seconds(); + static stopwatch sw; + static bool started = false; + if(!started){ + sw.start(); + started = true; + } + return sw.get_current_seconds(); } static void output_time(std::ostream &os, clock_t time){ - os << time; + os << time; } namespace profiling { - void show_time(){ - output_time(std::cout,current_time()); - std::cout << "\n"; - } + void show_time(){ + output_time(std::cout,current_time()); + std::cout << "\n"; + } - typedef std::map nmap; + typedef std::map nmap; - struct node { - std::string name; - clock_t time; - clock_t start_time; - nmap sub; - struct node *parent; + struct node { + std::string name; + clock_t time; + clock_t start_time; + nmap sub; + struct node *parent; - node(); - } top; + node(); + } top; - node::node(){ - time = 0; - parent = 0; - } - - struct node *current; - - struct init { - init(){ - top.name = "TOTAL"; - current = ⊤ + node::node(){ + time = 0; + parent = 0; } - } initializer; - struct time_entry { - clock_t t; - time_entry(){t = 0;}; - void add(clock_t incr){t += incr;} - }; + struct node *current; - struct ltstr - { - bool operator()(const char* s1, const char* s2) const + struct init { + init(){ + top.name = "TOTAL"; + current = ⊤ + } + } initializer; + + struct time_entry { + clock_t t; + time_entry(){t = 0;}; + void add(clock_t incr){t += incr;} + }; + + struct ltstr { - return strcmp(s1, s2) < 0; - } - }; + bool operator()(const char* s1, const char* s2) const + { + return strcmp(s1, s2) < 0; + } + }; - typedef std::map tmap; + typedef std::map tmap; - static std::ostream *pfs; + static std::ostream *pfs; - void print_node(node &top, int indent, tmap &totals){ - for(int i = 0; i < indent; i++) (*pfs) << " "; - (*pfs) << top.name; - int dots = 70 - 2 * indent - top.name.size(); - for(int i = 0; i second,indent+1,totals); - } + void print_node(node &top, int indent, tmap &totals){ + for(int i = 0; i < indent; i++) (*pfs) << " "; + (*pfs) << top.name; + int dots = 70 - 2 * indent - top.name.size(); + for(int i = 0; i second,indent+1,totals); + } - void print(std::ostream &os) { - pfs = &os; - top.time = 0; - for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) - top.time += it->second.time; - tmap totals; - print_node(top,0,totals); - (*pfs) << "TOTALS:" << std::endl; - for(tmap::iterator it = totals.begin(); it != totals.end(); it++){ - (*pfs) << (it->first) << " "; - output_time(*pfs, it->second.t); - (*pfs) << std::endl; + void print(std::ostream &os) { + pfs = &os; + top.time = 0; + for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) + top.time += it->second.time; + tmap totals; + print_node(top,0,totals); + (*pfs) << "TOTALS:" << std::endl; + for(tmap::iterator it = totals.begin(); it != totals.end(); it++){ + (*pfs) << (it->first) << " "; + output_time(*pfs, it->second.t); + (*pfs) << std::endl; + } } - } - void timer_start(const char *name){ - node &child = current->sub[name]; - if(child.name.empty()){ // a new node - child.parent = current; - child.name = name; + void timer_start(const char *name){ + node &child = current->sub[name]; + if(child.name.empty()){ // a new node + child.parent = current; + child.name = name; + } + child.start_time = current_time(); + current = &child; } - child.start_time = current_time(); - current = &child; - } - void timer_stop(const char *name){ - if(current->name != name || !current->parent){ - std::cerr << "imbalanced timer_start and timer_stop"; - exit(1); + void timer_stop(const char *name){ + if(current->name != name || !current->parent){ + std::cerr << "imbalanced timer_start and timer_stop"; + exit(1); + } + current->time += (current_time() - current->start_time); + current = current->parent; } - current->time += (current_time() - current->start_time); - current = current->parent; - } } diff --git a/src/interp/iz3profiling.h b/src/interp/iz3profiling.h index cdb7066e3..6b9b07f25 100755 --- a/src/interp/iz3profiling.h +++ b/src/interp/iz3profiling.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3profiling.h + iz3profiling.h -Abstract: + Abstract: - Some routines for measuring performance. + Some routines for measuring performance. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3PROFILING_H #define IZ3PROFILING_H @@ -23,14 +23,14 @@ Revision History: #include namespace profiling { - /** Start a timer with given name */ - void timer_start(const char *); - /** Stop a timer with given name */ - void timer_stop(const char *); - /** Print out timings */ - void print(std::ostream &s); - /** Show the current time. */ - void show_time(); + /** Start a timer with given name */ + void timer_start(const char *); + /** Stop a timer with given name */ + void timer_stop(const char *); + /** Print out timings */ + void print(std::ostream &s); + /** Show the current time. */ + void show_time(); } #endif diff --git a/src/interp/iz3proof.cpp b/src/interp/iz3proof.cpp index f806cd792..9adcce3c3 100755 --- a/src/interp/iz3proof.cpp +++ b/src/interp/iz3proof.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3proof.cpp + iz3proof.cpp -Abstract: + Abstract: - This class defines a simple interpolating proof system. + This class defines a simple interpolating proof system. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS @@ -39,178 +39,178 @@ Revision History: void iz3proof::resolve(ast pivot, std::vector &cls1, const std::vector &cls2){ #ifdef CHECK_PROOFS - std::vector orig_cls1 = cls1; + std::vector orig_cls1 = cls1; #endif - ast neg_pivot = pv->mk_not(pivot); - bool found_pivot1 = false, found_pivot2 = false; - for(unsigned i = 0; i < cls1.size(); i++){ - if(cls1[i] == neg_pivot){ - cls1[i] = cls1.back(); - cls1.pop_back(); - found_pivot1 = true; - break; + ast neg_pivot = pv->mk_not(pivot); + bool found_pivot1 = false, found_pivot2 = false; + for(unsigned i = 0; i < cls1.size(); i++){ + if(cls1[i] == neg_pivot){ + cls1[i] = cls1.back(); + cls1.pop_back(); + found_pivot1 = true; + break; + } } - } - { - std::set memo; - memo.insert(cls1.begin(),cls1.end()); - for(unsigned j = 0; j < cls2.size(); j++){ - if(cls2[j] == pivot) - found_pivot2 = true; - else - if(memo.find(cls2[j]) == memo.end()) - cls1.push_back(cls2[j]); - } - } - if(found_pivot1 && found_pivot2) - return; + { + std::set memo; + memo.insert(cls1.begin(),cls1.end()); + for(unsigned j = 0; j < cls2.size(); j++){ + if(cls2[j] == pivot) + found_pivot2 = true; + else + if(memo.find(cls2[j]) == memo.end()) + cls1.push_back(cls2[j]); + } + } + if(found_pivot1 && found_pivot2) + return; #ifdef CHECK_PROOFS - std::cerr << "resolution anomaly: " << nodes.size()-1 << "\n"; + std::cerr << "resolution anomaly: " << nodes.size()-1 << "\n"; #if 0 - std::cerr << "pivot: "; {pv->print_lit(pivot); std::cout << "\n";} - std::cerr << "left clause:\n"; - for(unsigned i = 0; i < orig_cls1.size(); i++) - {pv->print_lit(orig_cls1[i]); std::cout << "\n";} - std::cerr << "right clause:\n"; - for(unsigned i = 0; i < cls2.size(); i++) - {pv->print_lit(cls2[i]); std::cout << "\n";} - throw proof_error(); + std::cerr << "pivot: "; {pv->print_lit(pivot); std::cout << "\n";} + std::cerr << "left clause:\n"; + for(unsigned i = 0; i < orig_cls1.size(); i++) + {pv->print_lit(orig_cls1[i]); std::cout << "\n";} + std::cerr << "right clause:\n"; + for(unsigned i = 0; i < cls2.size(); i++) + {pv->print_lit(cls2[i]); std::cout << "\n";} + throw proof_error(); #endif #endif } iz3proof::node iz3proof::make_resolution(ast pivot, node premise1, node premise2) { - if(nodes[premise1].rl == Hypothesis) return premise2; // resolve with hyp is noop - if(nodes[premise2].rl == Hypothesis) return premise1; - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Resolution; - n.aux = pivot; - n.premises.resize(2); - n.premises[0] = (premise1); - n.premises[1] = (premise2); + if(nodes[premise1].rl == Hypothesis) return premise2; // resolve with hyp is noop + if(nodes[premise2].rl == Hypothesis) return premise1; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Resolution; + n.aux = pivot; + n.premises.resize(2); + n.premises[0] = (premise1); + n.premises[1] = (premise2); #ifdef CHECK_PROOFS - n.conclusion = nodes[premise1].conclusion; - resolve(pivot,n.conclusion,nodes[premise2].conclusion); - n.frame = 1; + n.conclusion = nodes[premise1].conclusion; + resolve(pivot,n.conclusion,nodes[premise2].conclusion); + n.frame = 1; #else - n.frame = 0; // compute conclusion lazily + n.frame = 0; // compute conclusion lazily #endif - return res; + return res; } iz3proof::node iz3proof::resolve_lemmas(ast pivot, node premise1, node premise2) { - std::vector lits(nodes[premise1].conclusion), itp; // no interpolant - resolve(pivot,lits,nodes[premise2].conclusion); - return make_lemma(lits,itp); + std::vector lits(nodes[premise1].conclusion), itp; // no interpolant + resolve(pivot,lits,nodes[premise2].conclusion); + return make_lemma(lits,itp); } iz3proof::node iz3proof::make_assumption(int frame, const std::vector &assumption){ #if 0 - std::cout << "assumption: \n"; - for(unsigned i = 0; i < assumption.size(); i++) - pv->show(assumption[i]); - std::cout << "\n"; + std::cout << "assumption: \n"; + for(unsigned i = 0; i < assumption.size(); i++) + pv->show(assumption[i]); + std::cout << "\n"; #endif - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Assumption; - n.conclusion.resize(1); - n.conclusion = assumption; - n.frame = frame; - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Assumption; + n.conclusion.resize(1); + n.conclusion = assumption; + n.frame = frame; + return res; } iz3proof::node iz3proof::make_hypothesis(ast hypothesis){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Hypothesis; - n.conclusion.resize(2); - n.conclusion[0] = hypothesis; - n.conclusion[1] = pv->mk_not(hypothesis); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Hypothesis; + n.conclusion.resize(2); + n.conclusion[0] = hypothesis; + n.conclusion[1] = pv->mk_not(hypothesis); + return res; } iz3proof::node iz3proof::make_theory(const std::vector &conclusion, std::vector premises){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Theory; - n.conclusion = conclusion; - n.premises = premises; - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Theory; + n.conclusion = conclusion; + n.premises = premises; + return res; } iz3proof::node iz3proof::make_axiom(const std::vector &conclusion){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Axiom; - n.conclusion = conclusion; - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Axiom; + n.conclusion = conclusion; + return res; } iz3proof::node iz3proof::make_contra(node prem, const std::vector &conclusion){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Contra; - n.conclusion = conclusion; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Contra; + n.conclusion = conclusion; #ifdef CHECK_PROOFS - //if(!(conclusion == nodes[prem].conclusion)){ - //std::cerr << "internal error: proof error\n"; - //assert(0 && "proof error"); - //} + //if(!(conclusion == nodes[prem].conclusion)){ + //std::cerr << "internal error: proof error\n"; + //assert(0 && "proof error"); + //} #endif - n.premises.push_back(prem); - return res; + n.premises.push_back(prem); + return res; } iz3proof::node iz3proof::make_lemma(const std::vector &conclusion, const std::vector &interpolation){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Lemma; - n.conclusion = conclusion; - n.frame = interps.size(); - interps.push_back(interpolation); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Lemma; + n.conclusion = conclusion; + n.frame = interps.size(); + interps.push_back(interpolation); + return res; } /** Make a Reflexivity node. This rule produces |- x = x */ iz3proof::node iz3proof::make_reflexivity(ast con){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Reflexivity; - n.conclusion.push_back(con); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Reflexivity; + n.conclusion.push_back(con); + return res; } /** Make a Symmetry node. This takes a derivation of |- x = y and produces | y = x */ iz3proof::node iz3proof::make_symmetry(ast con, node prem){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Reflexivity; - n.conclusion.push_back(con); - n.premises.push_back(prem); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Reflexivity; + n.conclusion.push_back(con); + n.premises.push_back(prem); + return res; } /** Make a transitivity node. This takes derivations of |- x = y and |- y = z produces | x = z */ iz3proof::node iz3proof::make_transitivity(ast con, node prem1, node prem2){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Transitivity; - n.conclusion.push_back(con); - n.premises.push_back(prem1); - n.premises.push_back(prem2); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Transitivity; + n.conclusion.push_back(con); + n.premises.push_back(prem1); + n.premises.push_back(prem2); + return res; } @@ -218,12 +218,12 @@ iz3proof::node iz3proof::make_transitivity(ast con, node prem1, node prem2){ and produces |- f(x_1,...,x_n) = f(y_1,...,y_n) */ iz3proof::node iz3proof::make_congruence(ast con, const std::vector &prems){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = Congruence; - n.conclusion.push_back(con); - n.premises = prems; - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = Congruence; + n.conclusion.push_back(con); + n.premises = prems; + return res; } @@ -231,398 +231,398 @@ iz3proof::node iz3proof::make_congruence(ast con, const std::vector &prems and |- !(x = y) and produces false. */ iz3proof::node iz3proof::make_eqcontra(node prem1, node prem2){ - node res = make_node(); - node_struct &n = nodes[res]; - n.rl = EqContra; - n.premises.push_back(prem1); - n.premises.push_back(prem2); - return res; + node res = make_node(); + node_struct &n = nodes[res]; + n.rl = EqContra; + n.premises.push_back(prem1); + n.premises.push_back(prem2); + return res; } iz3proof::node iz3proof::copy_rec(stl_ext::hash_map &memo, iz3proof &src, node n){ - stl_ext::hash_map::iterator it = memo.find(n); - if(it != memo.end()) return (*it).second; - node_struct &ns = src.nodes[n]; - std::vector prems(ns.premises.size()); - for(unsigned i = 0; i < prems.size(); i++) - prems[i] = copy_rec(memo,src,ns.premises[i]); - nodes.push_back(ns); - nodes.back().premises.swap(prems); - if(ns.rl == Lemma){ - nodes.back().frame = interps.size(); - interps.push_back(src.interps[ns.frame]); - } - int res = nodes.size()-1; - memo[n] = res; - return res; + stl_ext::hash_map::iterator it = memo.find(n); + if(it != memo.end()) return (*it).second; + node_struct &ns = src.nodes[n]; + std::vector prems(ns.premises.size()); + for(unsigned i = 0; i < prems.size(); i++) + prems[i] = copy_rec(memo,src,ns.premises[i]); + nodes.push_back(ns); + nodes.back().premises.swap(prems); + if(ns.rl == Lemma){ + nodes.back().frame = interps.size(); + interps.push_back(src.interps[ns.frame]); + } + int res = nodes.size()-1; + memo[n] = res; + return res; } iz3proof::node iz3proof::copy(iz3proof &src, node n){ - stl_ext::hash_map memo; - return copy_rec(memo, src, n); + stl_ext::hash_map memo; + return copy_rec(memo, src, n); } bool iz3proof::pred_in_A(ast id){ - return weak - ? pv->ranges_intersect(pv->ast_range(id),rng) : - pv->range_contained(pv->ast_range(id),rng); + return weak + ? pv->ranges_intersect(pv->ast_range(id),rng) : + pv->range_contained(pv->ast_range(id),rng); } bool iz3proof::term_in_B(ast id){ - prover::range r = pv->ast_scope(id); - if(weak) { - if(pv->range_min(r) == SHRT_MIN) - return !pv->range_contained(r,rng); + prover::range r = pv->ast_scope(id); + if(weak) { + if(pv->range_min(r) == SHRT_MIN) + return !pv->range_contained(r,rng); + else + return !pv->ranges_intersect(r,rng); + } else - return !pv->ranges_intersect(r,rng); - } - else - return !pv->range_contained(r,rng); + return !pv->range_contained(r,rng); } bool iz3proof::frame_in_A(int frame){ - return pv->in_range(frame,rng); + return pv->in_range(frame,rng); } bool iz3proof::lit_in_B(ast lit){ - return - b_lits.find(lit) != b_lits.end() - || b_lits.find(pv->mk_not(lit)) != b_lits.end(); + return + b_lits.find(lit) != b_lits.end() + || b_lits.find(pv->mk_not(lit)) != b_lits.end(); } iz3proof::ast iz3proof::my_or(ast x, ast y){ - return pv->mk_not(pv->mk_and(pv->mk_not(x),pv->mk_not(y))); + return pv->mk_not(pv->mk_and(pv->mk_not(x),pv->mk_not(y))); } iz3proof::ast iz3proof::get_A_lits(std::vector &cls){ - ast foo = pv->mk_false(); - for(unsigned i = 0; i < cls.size(); i++){ - ast lit = cls[i]; - if(b_lits.find(pv->mk_not(lit)) == b_lits.end()){ - if(pv->range_max(pv->ast_scope(lit)) == pv->range_min(pv->ast_scope(lit))){ - std::cout << "bad lit: " << pv->range_max(rng) << " : " << pv->range_max(pv->ast_scope(lit)) << " : " << (pv->ast_id(lit)) << " : "; - pv->show(lit); - } - foo = my_or(foo,lit); + ast foo = pv->mk_false(); + for(unsigned i = 0; i < cls.size(); i++){ + ast lit = cls[i]; + if(b_lits.find(pv->mk_not(lit)) == b_lits.end()){ + if(pv->range_max(pv->ast_scope(lit)) == pv->range_min(pv->ast_scope(lit))){ + std::cout << "bad lit: " << pv->range_max(rng) << " : " << pv->range_max(pv->ast_scope(lit)) << " : " << (pv->ast_id(lit)) << " : "; + pv->show(lit); + } + foo = my_or(foo,lit); + } } - } - return foo; + return foo; } iz3proof::ast iz3proof::get_B_lits(std::vector &cls){ - ast foo = pv->mk_false(); - for(unsigned i = 0; i < cls.size(); i++){ - ast lit = cls[i]; - if(b_lits.find(pv->mk_not(lit)) != b_lits.end()) - foo = my_or(foo,lit); - } - return foo; + ast foo = pv->mk_false(); + for(unsigned i = 0; i < cls.size(); i++){ + ast lit = cls[i]; + if(b_lits.find(pv->mk_not(lit)) != b_lits.end()) + foo = my_or(foo,lit); + } + return foo; } void iz3proof::set_of_B_lits(std::vector &cls, std::set &res){ - for(unsigned i = 0; i < cls.size(); i++){ - ast lit = cls[i]; - if(b_lits.find(pv->mk_not(lit)) != b_lits.end()) - res.insert(lit); - } + for(unsigned i = 0; i < cls.size(); i++){ + ast lit = cls[i]; + if(b_lits.find(pv->mk_not(lit)) != b_lits.end()) + res.insert(lit); + } } void iz3proof::set_of_A_lits(std::vector &cls, std::set &res){ - for(unsigned i = 0; i < cls.size(); i++){ - ast lit = cls[i]; - if(b_lits.find(pv->mk_not(lit)) == b_lits.end()) - res.insert(lit); - } + for(unsigned i = 0; i < cls.size(); i++){ + ast lit = cls[i]; + if(b_lits.find(pv->mk_not(lit)) == b_lits.end()) + res.insert(lit); + } } void iz3proof::find_B_lits(){ - b_lits.clear(); - for(unsigned i = 0; i < nodes.size(); i++){ - node_struct &n = nodes[i]; - std::vector &cls = n.conclusion; - if(n.rl == Assumption){ - if(weak) goto lemma; - if(!frame_in_A(n.frame)) - for(unsigned j = 0; j < cls.size(); j++) - b_lits.insert(cls[j]); + b_lits.clear(); + for(unsigned i = 0; i < nodes.size(); i++){ + node_struct &n = nodes[i]; + std::vector &cls = n.conclusion; + if(n.rl == Assumption){ + if(weak) goto lemma; + if(!frame_in_A(n.frame)) + for(unsigned j = 0; j < cls.size(); j++) + b_lits.insert(cls[j]); + } + else if(n.rl == Lemma) { + lemma: + for(unsigned j = 0; j < cls.size(); j++) + if(term_in_B(cls[j])) + b_lits.insert(cls[j]); + } } - else if(n.rl == Lemma) { - lemma: - for(unsigned j = 0; j < cls.size(); j++) - if(term_in_B(cls[j])) - b_lits.insert(cls[j]); - } - } } iz3proof::ast iz3proof::disj_of_set(std::set &s){ - ast res = pv->mk_false(); - for(std::set::iterator it = s.begin(), en = s.end(); it != en; ++it) - res = my_or(*it,res); - return res; + ast res = pv->mk_false(); + for(std::set::iterator it = s.begin(), en = s.end(); it != en; ++it) + res = my_or(*it,res); + return res; } void iz3proof::mk_and_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs){ #ifdef FACTOR_INTERPS - std::set &d1 = disjs[p1]; - std::set &d2 = disjs[p2]; - if(!weak){ - if(pv->is_true(itps[p1])){ - itps[i] = itps[p2]; - disjs[i] = disjs[p2]; - } - else if(pv->is_true(itps[p2])){ - itps[i] = itps[p1]; - disjs[i] = disjs[p1]; + std::set &d1 = disjs[p1]; + std::set &d2 = disjs[p2]; + if(!weak){ + if(pv->is_true(itps[p1])){ + itps[i] = itps[p2]; + disjs[i] = disjs[p2]; + } + else if(pv->is_true(itps[p2])){ + itps[i] = itps[p1]; + disjs[i] = disjs[p1]; + } + else { + std::set p1only,p2only; + std::insert_iterator > p1o(p1only,p1only.begin()); + std::insert_iterator > p2o(p2only,p2only.begin()); + std::insert_iterator > dio(disjs[i],disjs[i].begin()); + std::set_difference(d1.begin(),d1.end(),d2.begin(),d2.end(),p1o); + std::set_difference(d2.begin(),d2.end(),d1.begin(),d1.end(),p2o); + std::set_intersection(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); + ast p1i = my_or(itps[p1],disj_of_set(p1only)); + ast p2i = my_or(itps[p2],disj_of_set(p2only)); + itps[i] = pv->mk_and(p1i,p2i); + } } else { - std::set p1only,p2only; - std::insert_iterator > p1o(p1only,p1only.begin()); - std::insert_iterator > p2o(p2only,p2only.begin()); - std::insert_iterator > dio(disjs[i],disjs[i].begin()); - std::set_difference(d1.begin(),d1.end(),d2.begin(),d2.end(),p1o); - std::set_difference(d2.begin(),d2.end(),d1.begin(),d1.end(),p2o); - std::set_intersection(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); - ast p1i = my_or(itps[p1],disj_of_set(p1only)); - ast p2i = my_or(itps[p2],disj_of_set(p2only)); - itps[i] = pv->mk_and(p1i,p2i); + itps[i] = pv->mk_and(itps[p1],itps[p2]); + std::insert_iterator > dio(disjs[i],disjs[i].begin()); + std::set_union(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); } - } - else { - itps[i] = pv->mk_and(itps[p1],itps[p2]); - std::insert_iterator > dio(disjs[i],disjs[i].begin()); - std::set_union(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); - } #endif } void iz3proof::mk_or_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs){ #ifdef FACTOR_INTERPS - std::set &d1 = disjs[p1]; - std::set &d2 = disjs[p2]; - if(weak){ - if(pv->is_false(itps[p1])){ - itps[i] = itps[p2]; - disjs[i] = disjs[p2]; - } - else if(pv->is_false(itps[p2])){ - itps[i] = itps[p1]; - disjs[i] = disjs[p1]; + std::set &d1 = disjs[p1]; + std::set &d2 = disjs[p2]; + if(weak){ + if(pv->is_false(itps[p1])){ + itps[i] = itps[p2]; + disjs[i] = disjs[p2]; + } + else if(pv->is_false(itps[p2])){ + itps[i] = itps[p1]; + disjs[i] = disjs[p1]; + } + else { + std::set p1only,p2only; + std::insert_iterator > p1o(p1only,p1only.begin()); + std::insert_iterator > p2o(p2only,p2only.begin()); + std::insert_iterator > dio(disjs[i],disjs[i].begin()); + std::set_difference(d1.begin(),d1.end(),d2.begin(),d2.end(),p1o); + std::set_difference(d2.begin(),d2.end(),d1.begin(),d1.end(),p2o); + std::set_intersection(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); + ast p1i = pv->mk_and(itps[p1],pv->mk_not(disj_of_set(p1only))); + ast p2i = pv->mk_and(itps[p2],pv->mk_not(disj_of_set(p2only))); + itps[i] = my_or(p1i,p2i); + } } else { - std::set p1only,p2only; - std::insert_iterator > p1o(p1only,p1only.begin()); - std::insert_iterator > p2o(p2only,p2only.begin()); - std::insert_iterator > dio(disjs[i],disjs[i].begin()); - std::set_difference(d1.begin(),d1.end(),d2.begin(),d2.end(),p1o); - std::set_difference(d2.begin(),d2.end(),d1.begin(),d1.end(),p2o); - std::set_intersection(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); - ast p1i = pv->mk_and(itps[p1],pv->mk_not(disj_of_set(p1only))); - ast p2i = pv->mk_and(itps[p2],pv->mk_not(disj_of_set(p2only))); - itps[i] = my_or(p1i,p2i); + itps[i] = my_or(itps[p1],itps[p2]); + std::insert_iterator > dio(disjs[i],disjs[i].begin()); + std::set_union(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); } - } - else { - itps[i] = my_or(itps[p1],itps[p2]); - std::insert_iterator > dio(disjs[i],disjs[i].begin()); - std::set_union(d1.begin(),d1.end(),d2.begin(),d2.end(),dio); - } #endif } void iz3proof::interpolate_lemma(node_struct &n){ - if(interps[n.frame].size()) - return; // already computed - pv->interpolate_clause(n.conclusion,interps[n.frame]); + if(interps[n.frame].size()) + return; // already computed + pv->interpolate_clause(n.conclusion,interps[n.frame]); } - iz3proof::ast iz3proof::interpolate(const prover::range &_rng, bool _weak +iz3proof::ast iz3proof::interpolate(const prover::range &_rng, bool _weak #ifdef CHECK_PROOFS - , ast assump - , std::vector *parents + , ast assump + , std::vector *parents #endif -){ - // std::cout << "proof size: " << nodes.size() << "\n"; - rng = _rng; - weak = _weak; + ){ + // std::cout << "proof size: " << nodes.size() << "\n"; + rng = _rng; + weak = _weak; #ifdef CHECK_PROOFS - if(nodes[nodes.size()-1].conclusion.size() != 0) - std::cerr << "internal error: proof conclusion is not empty clause\n"; - if(!child_interps.size()){ - child_interps.resize(nodes.size()); - for(unsigned j = 0; j < nodes.size(); j++) - child_interps[j] = pv->mk_true(); - } + if(nodes[nodes.size()-1].conclusion.size() != 0) + std::cerr << "internal error: proof conclusion is not empty clause\n"; + if(!child_interps.size()){ + child_interps.resize(nodes.size()); + for(unsigned j = 0; j < nodes.size(); j++) + child_interps[j] = pv->mk_true(); + } #endif - std::vector itps(nodes.size()); + std::vector itps(nodes.size()); #ifdef FACTOR_INTERPS - std::vector > disjs(nodes.size()); + std::vector > disjs(nodes.size()); #endif - profiling::timer_start("Blits"); - find_B_lits(); - profiling::timer_stop("Blits"); - profiling::timer_start("interp_proof"); - // strengthen(); - for(unsigned i = 0; i < nodes.size(); i++){ - node_struct &n = nodes[i]; - ast &q = itps[i]; - switch(n.rl){ - case Assumption: { + profiling::timer_start("Blits"); + find_B_lits(); + profiling::timer_stop("Blits"); + profiling::timer_start("interp_proof"); + // strengthen(); + for(unsigned i = 0; i < nodes.size(); i++){ + node_struct &n = nodes[i]; + ast &q = itps[i]; + switch(n.rl){ + case Assumption: { - if(frame_in_A(n.frame)){ - /* HypC-A */ - if(!weak) + if(frame_in_A(n.frame)){ + /* HypC-A */ + if(!weak) #ifdef FACTOR_INTERPS - { - q = pv->mk_false(); - set_of_B_lits(n.conclusion,disjs[i]); - } + { + q = pv->mk_false(); + set_of_B_lits(n.conclusion,disjs[i]); + } #else - q = get_B_lits(n.conclusion); + q = get_B_lits(n.conclusion); #endif - else - q = pv->mk_false(); - } - else { - /* HypEq-B */ - if(!weak) - q = pv->mk_true(); - else + else + q = pv->mk_false(); + } + else { + /* HypEq-B */ + if(!weak) + q = pv->mk_true(); + else #ifdef FACTOR_INTERPS - { - q = pv->mk_true(); - set_of_A_lits(n.conclusion,disjs[i]); - } + { + q = pv->mk_true(); + set_of_A_lits(n.conclusion,disjs[i]); + } #else - q = pv->mk_not(get_A_lits(n.conclusion)); + q = pv->mk_not(get_A_lits(n.conclusion)); #endif - } - break; - } - case Resolution: { - ast p = n.aux; - p = pv->is_not(p) ? pv->mk_not(p) : p; // should be positive, but just in case - if(lit_in_B(p)) -#ifdef FACTOR_INTERPS - mk_and_factor(n.premises[0],n.premises[1],i,itps,disjs); -#else - q = pv->mk_and(itps[n.premises[0]],itps[n.premises[1]]); -#endif - else -#ifdef FACTOR_INTERPS - mk_or_factor(n.premises[0],n.premises[1],i,itps,disjs); -#else - q = my_or(itps[n.premises[0]],itps[n.premises[1]]); -#endif - break; - } - case Lemma: { - interpolate_lemma(n); // make sure lemma interpolants have been computed - q = interps[n.frame][pv->range_max(rng)]; - break; - } - case Contra: { - q = itps[n.premises[0]]; -#ifdef FACTOR_INTERPS - disjs[i] = disjs[n.premises[0]]; -#endif - break; - } - default: - assert(0 && "rule not allowed in interpolated proof"); - } -#ifdef CHECK_PROOFS - int this_frame = pv->range_max(rng); - if(0 && this_frame == 39) { - std::vector alits; - ast s = pv->mk_true(); - for(unsigned j = 0; j < n.conclusion.size(); j++) - if(pred_in_A(n.conclusion[j])){ - int scpmax = pv->range_max(pv->ast_scope(n.conclusion[j])); - if(scpmax == this_frame) - s = pv->mk_and(s,pv->mk_not(n.conclusion[j])); + } + break; } - ast ci = child_interps[i]; - s = pv->mk_and(pv->mk_and(s,pv->mk_and(assump,pv->mk_not(q))),ci); - if(pv->is_sat(s)){ - std::cout << "interpolation invariant violated at step " << i << "\n"; - assert(0 && "interpolation invariant violated"); - } - } - if((*parents)[this_frame] == 39) - child_interps[i] = pv->mk_and(child_interps[i],q); -#endif - } - ast &bar = itps[nodes.size()-1]; + case Resolution: { + ast p = n.aux; + p = pv->is_not(p) ? pv->mk_not(p) : p; // should be positive, but just in case + if(lit_in_B(p)) #ifdef FACTOR_INTERPS - if(!weak) - bar = my_or(bar,disj_of_set(disjs[nodes.size()-1])); - else - bar = pv->mk_and(bar,pv->mk_not(disj_of_set(disjs[nodes.size()-1]))); + mk_and_factor(n.premises[0],n.premises[1],i,itps,disjs); +#else + q = pv->mk_and(itps[n.premises[0]],itps[n.premises[1]]); #endif - profiling::timer_stop("interp_proof"); - profiling::timer_start("simplifying"); - bar = pv->simplify(bar); - profiling::timer_stop("simplifying"); - return bar; + else +#ifdef FACTOR_INTERPS + mk_or_factor(n.premises[0],n.premises[1],i,itps,disjs); +#else + q = my_or(itps[n.premises[0]],itps[n.premises[1]]); +#endif + break; + } + case Lemma: { + interpolate_lemma(n); // make sure lemma interpolants have been computed + q = interps[n.frame][pv->range_max(rng)]; + break; + } + case Contra: { + q = itps[n.premises[0]]; +#ifdef FACTOR_INTERPS + disjs[i] = disjs[n.premises[0]]; +#endif + break; + } + default: + assert(0 && "rule not allowed in interpolated proof"); + } +#ifdef CHECK_PROOFS + int this_frame = pv->range_max(rng); + if(0 && this_frame == 39) { + std::vector alits; + ast s = pv->mk_true(); + for(unsigned j = 0; j < n.conclusion.size(); j++) + if(pred_in_A(n.conclusion[j])){ + int scpmax = pv->range_max(pv->ast_scope(n.conclusion[j])); + if(scpmax == this_frame) + s = pv->mk_and(s,pv->mk_not(n.conclusion[j])); + } + ast ci = child_interps[i]; + s = pv->mk_and(pv->mk_and(s,pv->mk_and(assump,pv->mk_not(q))),ci); + if(pv->is_sat(s)){ + std::cout << "interpolation invariant violated at step " << i << "\n"; + assert(0 && "interpolation invariant violated"); + } + } + if((*parents)[this_frame] == 39) + child_interps[i] = pv->mk_and(child_interps[i],q); +#endif + } + ast &bar = itps[nodes.size()-1]; +#ifdef FACTOR_INTERPS + if(!weak) + bar = my_or(bar,disj_of_set(disjs[nodes.size()-1])); + else + bar = pv->mk_and(bar,pv->mk_not(disj_of_set(disjs[nodes.size()-1]))); +#endif + profiling::timer_stop("interp_proof"); + profiling::timer_start("simplifying"); + bar = pv->simplify(bar); + profiling::timer_stop("simplifying"); + return bar; } void iz3proof::print(std::ostream &s, int id){ - node_struct &n = nodes[id]; - switch(n.rl){ - case Assumption: - s << "Assumption("; - pv->print_clause(s,n.conclusion); - s << ")"; - break; - case Hypothesis: - s << "Hyp("; pv->print_expr(s,n.conclusion[0]); s << ")"; break; - case Reflexivity: - s << "Refl("; pv->print_expr(s,n.conclusion[0]); s << ")"; break; - case Symmetry: - s << "Symm("; print(s,n.premises[0]); s << ")"; break; - case Transitivity: - s << "Trans("; print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; break; - case Congruence: - s << "Cong("; pv->print_expr(s,n.conclusion[0]); - for(unsigned i = 0; i < n.premises.size(); i++){ - s << ","; - print(s,n.premises[i]); + node_struct &n = nodes[id]; + switch(n.rl){ + case Assumption: + s << "Assumption("; + pv->print_clause(s,n.conclusion); + s << ")"; + break; + case Hypothesis: + s << "Hyp("; pv->print_expr(s,n.conclusion[0]); s << ")"; break; + case Reflexivity: + s << "Refl("; pv->print_expr(s,n.conclusion[0]); s << ")"; break; + case Symmetry: + s << "Symm("; print(s,n.premises[0]); s << ")"; break; + case Transitivity: + s << "Trans("; print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; break; + case Congruence: + s << "Cong("; pv->print_expr(s,n.conclusion[0]); + for(unsigned i = 0; i < n.premises.size(); i++){ + s << ","; + print(s,n.premises[i]); + } + s << ")"; break; + case EqContra: + s << "EqContra("; print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; break; + case Resolution: + s << "Res("; + pv->print_expr(s,n.aux); s << ","; + print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; + break; + case Lemma: + s << "Lemma("; + pv->print_clause(s,n.conclusion); + for(unsigned i = 0; i < n.premises.size(); i++){ + s << ","; + print(s,n.premises[i]); + } + s << ")"; + break; + case Contra: + s << "Contra("; + print(s,n.premises[0]); + s << ")"; + break; + default:; } - s << ")"; break; - case EqContra: - s << "EqContra("; print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; break; - case Resolution: - s << "Res("; - pv->print_expr(s,n.aux); s << ","; - print(s,n.premises[0]); s << ","; print(s,n.premises[1]); s << ")"; - break; - case Lemma: - s << "Lemma("; - pv->print_clause(s,n.conclusion); - for(unsigned i = 0; i < n.premises.size(); i++){ - s << ","; - print(s,n.premises[i]); - } - s << ")"; - break; - case Contra: - s << "Contra("; - print(s,n.premises[0]); - s << ")"; - break; - default:; - } } void iz3proof::show(int id){ - std::ostringstream ss; - print(ss,id); - iz3base::pretty_print(std::cout,ss.str()); - // std::cout << ss.str(); - std::cout << "\n"; + std::ostringstream ss; + print(ss,id); + iz3base::pretty_print(std::cout,ss.str()); + // std::cout << ss.str(); + std::cout << "\n"; } diff --git a/src/interp/iz3proof.h b/src/interp/iz3proof.h index ae08e9d36..be85702a2 100755 --- a/src/interp/iz3proof.h +++ b/src/interp/iz3proof.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3proof.h + iz3proof.h -Abstract: + Abstract: - This class defines a simple interpolating proof system. + This class defines a simple interpolating proof system. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3PROOF_H #define IZ3PROOF_H @@ -40,233 +40,233 @@ Revision History: rules Resolution, Assumption, Contra and Lemma, and that all clauses are strict (i.e., each literal in each clause is local). - */ +*/ class iz3proof { public: - /** The type of proof nodes (nodes in the derivation tree). */ - typedef int node; + /** The type of proof nodes (nodes in the derivation tree). */ + typedef int node; - /** Enumeration of proof rules. */ - enum rule {Resolution,Assumption,Hypothesis,Theory,Axiom,Contra,Lemma,Reflexivity,Symmetry,Transitivity,Congruence,EqContra}; + /** Enumeration of proof rules. */ + enum rule {Resolution,Assumption,Hypothesis,Theory,Axiom,Contra,Lemma,Reflexivity,Symmetry,Transitivity,Congruence,EqContra}; - /** Interface to prover. */ - typedef iz3base prover; + /** Interface to prover. */ + typedef iz3base prover; - /** Ast type. */ - typedef prover::ast ast; + /** Ast type. */ + typedef prover::ast ast; - /** Object thrown in case of a proof error. */ - struct proof_error {}; + /** Object thrown in case of a proof error. */ + struct proof_error {}; - /* Null proof node */ - static const node null = -1; + /* Null proof node */ + static const node null = -1; - /** Make a resolution node with given pivot liter and premises. - The conclusion of premise1 should contain the negation of the - pivot literal, while the conclusion of premise2 should containe the - pivot literal. - */ - node make_resolution(ast pivot, node premise1, node premise2); + /** Make a resolution node with given pivot liter and premises. + The conclusion of premise1 should contain the negation of the + pivot literal, while the conclusion of premise2 should containe the + pivot literal. + */ + node make_resolution(ast pivot, node premise1, node premise2); - /** Make an assumption node. The given clause is assumed in the given frame. */ - node make_assumption(int frame, const std::vector &assumption); + /** Make an assumption node. The given clause is assumed in the given frame. */ + node make_assumption(int frame, const std::vector &assumption); - /** Make a hypothesis node. If phi is the hypothesis, this is - effectively phi |- phi. */ - node make_hypothesis(ast hypothesis); + /** Make a hypothesis node. If phi is the hypothesis, this is + effectively phi |- phi. */ + node make_hypothesis(ast hypothesis); - /** Make a theory node. This can be any inference valid in the theory. */ - node make_theory(const std::vector &conclusion, std::vector premises); + /** Make a theory node. This can be any inference valid in the theory. */ + node make_theory(const std::vector &conclusion, std::vector premises); - /** Make an axiom node. The conclusion must be an instance of an axiom. */ - node make_axiom(const std::vector &conclusion); + /** Make an axiom node. The conclusion must be an instance of an axiom. */ + node make_axiom(const std::vector &conclusion); - /** Make a Contra node. This rule takes a derivation of the form - Gamma |- False and produces |- \/~Gamma. */ + /** Make a Contra node. This rule takes a derivation of the form + Gamma |- False and produces |- \/~Gamma. */ - node make_contra(node prem, const std::vector &conclusion); + node make_contra(node prem, const std::vector &conclusion); - /** Make a lemma node. A lemma node must have an interpolation. */ - node make_lemma(const std::vector &conclusion, const std::vector &interpolation); + /** Make a lemma node. A lemma node must have an interpolation. */ + node make_lemma(const std::vector &conclusion, const std::vector &interpolation); - /** Make a Reflexivity node. This rule produces |- x = x */ + /** Make a Reflexivity node. This rule produces |- x = x */ - node make_reflexivity(ast con); + node make_reflexivity(ast con); - /** Make a Symmetry node. This takes a derivation of |- x = y and - produces | y = x */ + /** Make a Symmetry node. This takes a derivation of |- x = y and + produces | y = x */ - node make_symmetry(ast con, node prem); + node make_symmetry(ast con, node prem); - /** Make a transitivity node. This takes derivations of |- x = y - and |- y = z produces | x = z */ + /** Make a transitivity node. This takes derivations of |- x = y + and |- y = z produces | x = z */ - node make_transitivity(ast con, node prem1, node prem2); + node make_transitivity(ast con, node prem1, node prem2); - /** Make a congruence node. This takes derivations of |- x_i = y_i - and produces |- f(x_1,...,x_n) = f(y_1,...,y_n) */ + /** Make a congruence node. This takes derivations of |- x_i = y_i + and produces |- f(x_1,...,x_n) = f(y_1,...,y_n) */ - node make_congruence(ast con, const std::vector &prems); + node make_congruence(ast con, const std::vector &prems); - /** Make an equality contradicition node. This takes |- x = y - and |- !(x = y) and produces false. */ + /** Make an equality contradicition node. This takes |- x = y + and |- !(x = y) and produces false. */ - node make_eqcontra(node prem1, node prem2); + node make_eqcontra(node prem1, node prem2); - /** Get the rule of a node in a proof. */ - rule get_rule(node n){ - return nodes[n].rl; - } + /** Get the rule of a node in a proof. */ + rule get_rule(node n){ + return nodes[n].rl; + } - /** Get the pivot of a resolution node. */ - ast get_pivot(node n){ - return nodes[n].aux; - } + /** Get the pivot of a resolution node. */ + ast get_pivot(node n){ + return nodes[n].aux; + } - /** Get the frame of an assumption node. */ - int get_frame(node n){ - return nodes[n].frame; - } + /** Get the frame of an assumption node. */ + int get_frame(node n){ + return nodes[n].frame; + } - /** Get the number of literals of the conclusion of a node. */ - int get_num_conclusion_lits(node n){ - return get_conclusion(n).size(); - } + /** Get the number of literals of the conclusion of a node. */ + int get_num_conclusion_lits(node n){ + return get_conclusion(n).size(); + } - /** Get the nth literal of the conclusion of a node. */ - ast get_nth_conclusion_lit(node n, int i){ - return get_conclusion(n)[i]; - } + /** Get the nth literal of the conclusion of a node. */ + ast get_nth_conclusion_lit(node n, int i){ + return get_conclusion(n)[i]; + } - /** Get the conclusion of a node. */ - void get_conclusion(node n, std::vector &result){ - result = get_conclusion(n); - } + /** Get the conclusion of a node. */ + void get_conclusion(node n, std::vector &result){ + result = get_conclusion(n); + } - /** Get the number of premises of a node. */ - int get_num_premises(node n){ - return nodes[n].premises.size(); - } + /** Get the number of premises of a node. */ + int get_num_premises(node n){ + return nodes[n].premises.size(); + } - /** Get the nth premise of a node. */ - int get_nth_premise(node n, int i){ - return nodes[n].premises[i]; - } + /** Get the nth premise of a node. */ + int get_nth_premise(node n, int i){ + return nodes[n].premises[i]; + } - /** Get all the premises of a node. */ - void get_premises(node n, std::vector &result){ - result = nodes[n].premises; - } + /** Get all the premises of a node. */ + void get_premises(node n, std::vector &result){ + result = nodes[n].premises; + } - /** Create a new proof node, replacing the premises of an old - one. */ + /** Create a new proof node, replacing the premises of an old + one. */ - node clone(node n, std::vector &premises){ - if(premises == nodes[n].premises) - return n; - nodes.push_back(nodes[n]); - nodes.back().premises = premises; - return nodes.size()-1; - } + node clone(node n, std::vector &premises){ + if(premises == nodes[n].premises) + return n; + nodes.push_back(nodes[n]); + nodes.back().premises = premises; + return nodes.size()-1; + } - /** Copy a proof node from src */ - node copy(iz3proof &src, node n); + /** Copy a proof node from src */ + node copy(iz3proof &src, node n); - /** Resolve two lemmas on a given literal. */ + /** Resolve two lemmas on a given literal. */ - node resolve_lemmas(ast pivot, node left, node right); + node resolve_lemmas(ast pivot, node left, node right); - /** Swap two proofs. */ - void swap(iz3proof &other){ - std::swap(pv,other.pv); - nodes.swap(other.nodes); - interps.swap(other.interps); - } + /** Swap two proofs. */ + void swap(iz3proof &other){ + std::swap(pv,other.pv); + nodes.swap(other.nodes); + interps.swap(other.interps); + } - /** Compute an interpolant for a proof, where the "A" side is defined by - the given range of frames. Parameter "weak", when true, uses different - interpolation system that resutls in generally weaker interpolants. - */ - ast interpolate(const prover::range &_rng, bool weak = false + /** Compute an interpolant for a proof, where the "A" side is defined by + the given range of frames. Parameter "weak", when true, uses different + interpolation system that resutls in generally weaker interpolants. + */ + ast interpolate(const prover::range &_rng, bool weak = false #ifdef CHECK_PROOFS - , Z3_ast assump = (Z3_ast)0, std::vector *parents = 0 + , Z3_ast assump = (Z3_ast)0, std::vector *parents = 0 #endif - ); + ); - /** print proof node to a stream */ + /** print proof node to a stream */ - void print(std::ostream &s, node n); + void print(std::ostream &s, node n); - /** show proof node on stdout */ - void show(node n); + /** show proof node on stdout */ + void show(node n); - /** Construct a proof, with a given prover. */ - iz3proof(prover *p){ - pv = p; - } + /** Construct a proof, with a given prover. */ + iz3proof(prover *p){ + pv = p; + } - /** Default constructor */ - iz3proof(){pv = 0;} + /** Default constructor */ + iz3proof(){pv = 0;} protected: - struct node_struct { - rule rl; - ast aux; - int frame; - std::vector conclusion; - std::vector premises; - }; + struct node_struct { + rule rl; + ast aux; + int frame; + std::vector conclusion; + std::vector premises; + }; - std::vector nodes; - std::vector > interps; // interpolations of lemmas - prover *pv; + std::vector nodes; + std::vector > interps; // interpolations of lemmas + prover *pv; - node make_node(){ - nodes.push_back(node_struct()); - return nodes.size()-1; - } - - void resolve(ast pivot, std::vector &cls1, const std::vector &cls2); - - node copy_rec(stl_ext::hash_map &memo, iz3proof &src, node n); - - void interpolate_lemma(node_struct &n); - - // lazily compute the result of resolution - // the node member "frame" indicates result is computed - const std::vector &get_conclusion(node x){ - node_struct &n = nodes[x]; - if(n.rl == Resolution && !n.frame){ - n.conclusion = get_conclusion(n.premises[0]); - resolve(n.aux,n.conclusion,get_conclusion(n.premises[1])); - n.frame = 1; + node make_node(){ + nodes.push_back(node_struct()); + return nodes.size()-1; } - return n.conclusion; - } - prover::range rng; - bool weak; - stl_ext::hash_set b_lits; - ast my_or(ast x, ast y); + void resolve(ast pivot, std::vector &cls1, const std::vector &cls2); + + node copy_rec(stl_ext::hash_map &memo, iz3proof &src, node n); + + void interpolate_lemma(node_struct &n); + + // lazily compute the result of resolution + // the node member "frame" indicates result is computed + const std::vector &get_conclusion(node x){ + node_struct &n = nodes[x]; + if(n.rl == Resolution && !n.frame){ + n.conclusion = get_conclusion(n.premises[0]); + resolve(n.aux,n.conclusion,get_conclusion(n.premises[1])); + n.frame = 1; + } + return n.conclusion; + } + + prover::range rng; + bool weak; + stl_ext::hash_set b_lits; + ast my_or(ast x, ast y); #ifdef CHECK_PROOFS - std::vector child_interps; + std::vector child_interps; #endif - bool pred_in_A(ast id); - bool term_in_B(ast id); - bool frame_in_A(int frame); - bool lit_in_B(ast lit); - ast get_A_lits(std::vector &cls); - ast get_B_lits(std::vector &cls); - void find_B_lits(); - ast disj_of_set(std::set &s); - void mk_or_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs); - void mk_and_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs); - void set_of_B_lits(std::vector &cls, std::set &res); - void set_of_A_lits(std::vector &cls, std::set &res); + bool pred_in_A(ast id); + bool term_in_B(ast id); + bool frame_in_A(int frame); + bool lit_in_B(ast lit); + ast get_A_lits(std::vector &cls); + ast get_B_lits(std::vector &cls); + void find_B_lits(); + ast disj_of_set(std::set &s); + void mk_or_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs); + void mk_and_factor(int p1, int p2, int i, std::vector &itps, std::vector > &disjs); + void set_of_B_lits(std::vector &cls, std::set &res); + void set_of_A_lits(std::vector &cls, std::set &res); }; #endif diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 251a56e7a..0bdd51ed8 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3proof.cpp + iz3proof.cpp -Abstract: + Abstract: - This class defines a simple interpolating proof system. + This class defines a simple interpolating proof system. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -32,3062 +32,3062 @@ using namespace stl_ext; class iz3proof_itp_impl : public iz3proof_itp { - prover *pv; - prover::range rng; - bool weak; + prover *pv; + prover::range rng; + bool weak; - enum LitType {LitA,LitB,LitMixed}; + enum LitType {LitA,LitB,LitMixed}; - hash_map placeholders; + hash_map placeholders; - // These symbols represent deduction rules + // These symbols represent deduction rules - /* This symbol represents a proof by contradiction. That is, - contra(p,l1 /\ ... /\ lk) takes a proof p of + /* This symbol represents a proof by contradiction. That is, + contra(p,l1 /\ ... /\ lk) takes a proof p of - l1,...,lk |- false + l1,...,lk |- false - and returns a proof of + and returns a proof of - |- ~l1,...,~l2 - */ - symb contra; + |- ~l1,...,~l2 + */ + symb contra; - /* The summation rule. The term sum(p,c,i) takes a proof p of an - inequality i', an integer coefficient c and an inequality i, and - yieds a proof of i' + ci. */ - symb sum; + /* The summation rule. The term sum(p,c,i) takes a proof p of an + inequality i', an integer coefficient c and an inequality i, and + yieds a proof of i' + ci. */ + symb sum; - /* Proof rotation. The proof term rotate(q,p) takes a - proof p of: + /* Proof rotation. The proof term rotate(q,p) takes a + proof p of: - Gamma, q |- false + Gamma, q |- false - and yields a proof of: + and yields a proof of: - Gamma |- ~q - */ - symb rotate_sum; + Gamma |- ~q + */ + symb rotate_sum; - /* Inequalities to equality. leq2eq(p, q, r) takes a proof - p of ~x=y, a proof q of x <= y and a proof r of y <= x - and yields a proof of false. */ - symb leq2eq; + /* Inequalities to equality. leq2eq(p, q, r) takes a proof + p of ~x=y, a proof q of x <= y and a proof r of y <= x + and yields a proof of false. */ + symb leq2eq; - /* Equality to inequality. eq2leq(p, q) takes a proof p of x=y, and - a proof q ~(x <= y) and and yields a proof of false. */ - symb eq2leq; + /* Equality to inequality. eq2leq(p, q) takes a proof p of x=y, and + a proof q ~(x <= y) and and yields a proof of false. */ + symb eq2leq; - /* Proof term cong(p,q) takes a proof p of x=y and a proof - q of t != t and returns a proof of false. */ - symb cong; + /* Proof term cong(p,q) takes a proof p of x=y and a proof + q of t != t and returns a proof of false. */ + symb cong; - /* Excluded middle. exmid(phi,p,q) takes a proof p of phi and a - proof q of ~\phi and returns a proof of false. */ - symb exmid; + /* Excluded middle. exmid(phi,p,q) takes a proof p of phi and a + proof q of ~\phi and returns a proof of false. */ + symb exmid; - /* Symmetry. symm(p) takes a proof p of x=y and produces - a proof of y=x. */ - symb symm; + /* Symmetry. symm(p) takes a proof p of x=y and produces + a proof of y=x. */ + symb symm; - /* Modus ponens. modpon(p,e,q) takes proofs p of P, e of P=Q - and q of ~Q and returns a proof of false. */ - symb modpon; + /* Modus ponens. modpon(p,e,q) takes proofs p of P, e of P=Q + and q of ~Q and returns a proof of false. */ + symb modpon; - /* This oprerator represents a concatenation of rewrites. The term - a=b;c=d represents an A rewrite from a to b, followed by a B - rewrite fron b to c, followed by an A rewrite from c to d. - */ - symb concat; + /* This oprerator represents a concatenation of rewrites. The term + a=b;c=d represents an A rewrite from a to b, followed by a B + rewrite fron b to c, followed by an A rewrite from c to d. + */ + symb concat; - /* This represents a lack of a proof */ - ast no_proof; + /* This represents a lack of a proof */ + ast no_proof; - // This is used to represent an infinitessimal value - ast epsilon; + // This is used to represent an infinitessimal value + ast epsilon; - // Represents the top position of a term - ast top_pos; + // Represents the top position of a term + ast top_pos; - // add_pos(i,pos) represents position pos if the ith argument - symb add_pos; + // add_pos(i,pos) represents position pos if the ith argument + symb add_pos; - // rewrite proof rules + // rewrite proof rules - /* rewrite_A(pos,cond,x=y) derives A |- cond => t[x]_p = t[y]_p - where t is an arbitrary term */ - symb rewrite_A; + /* rewrite_A(pos,cond,x=y) derives A |- cond => t[x]_p = t[y]_p + where t is an arbitrary term */ + symb rewrite_A; - /* rewrite_B(pos,cond,x=y) derives B |- cond => t[x]_p = t[y]_p, - where t is an arbitrary term */ - symb rewrite_B; + /* rewrite_B(pos,cond,x=y) derives B |- cond => t[x]_p = t[y]_p, + where t is an arbitrary term */ + symb rewrite_B; - /* a normalization step is of the form (lhs=rhs) : proof, where "proof" - is a proof of lhs=rhs and lhs is a mixed term. If rhs is a mixed term - then it must have a greater index than lhs. */ - symb normal_step; + /* a normalization step is of the form (lhs=rhs) : proof, where "proof" + is a proof of lhs=rhs and lhs is a mixed term. If rhs is a mixed term + then it must have a greater index than lhs. */ + symb normal_step; - /* A chain of normalization steps is either "true" (the null chain) - or normal_chain( ), where step is a normalization step - and tail is a normalization chain. The lhs of must have - a less term index than any lhs in the chain. Moreover, the rhs of - may not occur as the lhs of step in . If we wish to - add lhs=rhs to the beginning of and rhs=rhs' occurs in - we must apply transitivity, transforming to lhs=rhs'. */ + /* A chain of normalization steps is either "true" (the null chain) + or normal_chain( ), where step is a normalization step + and tail is a normalization chain. The lhs of must have + a less term index than any lhs in the chain. Moreover, the rhs of + may not occur as the lhs of step in . If we wish to + add lhs=rhs to the beginning of and rhs=rhs' occurs in + we must apply transitivity, transforming to lhs=rhs'. */ - symb normal_chain; + symb normal_chain; - /* If p is a proof of Q and c is a normalization chain, then normal(p,c) - is a proof of Q(c) (that is, Q with all substitutions in c performed). */ + /* If p is a proof of Q and c is a normalization chain, then normal(p,c) + is a proof of Q(c) (that is, Q with all substitutions in c performed). */ - symb normal; + symb normal; - /** Stand-ins for quantifiers */ + /** Stand-ins for quantifiers */ - symb sforall, sexists; + symb sforall, sexists; - ast get_placeholder(ast t){ - hash_map::iterator it = placeholders.find(t); - if(it != placeholders.end()) - return it->second; - ast &res = placeholders[t]; - res = mk_fresh_constant("@p",get_type(t)); + ast get_placeholder(ast t){ + hash_map::iterator it = placeholders.find(t); + if(it != placeholders.end()) + return it->second; + ast &res = placeholders[t]; + res = mk_fresh_constant("@p",get_type(t)); #if 0 - std::cout << "placeholder "; - print_expr(std::cout,res); - std::cout << " = "; - print_expr(std::cout,t); - std::cout << std::endl; + std::cout << "placeholder "; + print_expr(std::cout,res); + std::cout << " = "; + print_expr(std::cout,t); + std::cout << std::endl; #endif - return res; - } - - ast make_contra_node(const ast &pf, const std::vector &lits, int pfok = -1){ - if(lits.size() == 0) - return pf; - std::vector reslits; - reslits.push_back(make(contra,pf,mk_false())); - for(unsigned i = 0; i < lits.size(); i++){ - ast bar; - if(pfok & (1 << i)) bar = make(rotate_sum,lits[i],pf); - else bar = no_proof; - ast foo = make(contra,bar,lits[i]); - reslits.push_back(foo); + return res; } - return make(And,reslits); - } - LitType get_term_type(const ast &lit){ - prover::range r = pv->ast_scope(lit); - if(pv->range_is_empty(r)) - return LitMixed; - if(weak) { - if(pv->range_min(r) == SHRT_MIN) - return pv->range_contained(r,rng) ? LitA : LitB; - else - return pv->ranges_intersect(r,rng) ? LitA : LitB; + ast make_contra_node(const ast &pf, const std::vector &lits, int pfok = -1){ + if(lits.size() == 0) + return pf; + std::vector reslits; + reslits.push_back(make(contra,pf,mk_false())); + for(unsigned i = 0; i < lits.size(); i++){ + ast bar; + if(pfok & (1 << i)) bar = make(rotate_sum,lits[i],pf); + else bar = no_proof; + ast foo = make(contra,bar,lits[i]); + reslits.push_back(foo); + } + return make(And,reslits); } - else - return pv->range_contained(r,rng) ? LitA : LitB; - } - bool term_common(const ast &t){ - prover::range r = pv->ast_scope(t); - return pv->ranges_intersect(r,rng) && !pv->range_contained(r,rng); - } - - bool term_in_vocab(LitType ty, const ast &lit){ - prover::range r = pv->ast_scope(lit); - if(ty == LitA){ - return pv->ranges_intersect(r,rng); + LitType get_term_type(const ast &lit){ + prover::range r = pv->ast_scope(lit); + if(pv->range_is_empty(r)) + return LitMixed; + if(weak) { + if(pv->range_min(r) == SHRT_MIN) + return pv->range_contained(r,rng) ? LitA : LitB; + else + return pv->ranges_intersect(r,rng) ? LitA : LitB; + } + else + return pv->range_contained(r,rng) ? LitA : LitB; } - return !pv->range_contained(r,rng); - } - /** Make a resolution node with given pivot literal and premises. - The conclusion of premise1 should contain the negation of the - pivot literal, while the conclusion of premise2 should contain the - pivot literal. - */ - node make_resolution(ast pivot, const std::vector &conc, node premise1, node premise2) { - LitType lt = get_term_type(pivot); - if(lt == LitA) - return my_or(premise1,premise2); - if(lt == LitB) - return my_and(premise1,premise2); + bool term_common(const ast &t){ + prover::range r = pv->ast_scope(t); + return pv->ranges_intersect(r,rng) && !pv->range_contained(r,rng); + } + + bool term_in_vocab(LitType ty, const ast &lit){ + prover::range r = pv->ast_scope(lit); + if(ty == LitA){ + return pv->ranges_intersect(r,rng); + } + return !pv->range_contained(r,rng); + } + + /** Make a resolution node with given pivot literal and premises. + The conclusion of premise1 should contain the negation of the + pivot literal, while the conclusion of premise2 should contain the + pivot literal. + */ + node make_resolution(ast pivot, const std::vector &conc, node premise1, node premise2) { + LitType lt = get_term_type(pivot); + if(lt == LitA) + return my_or(premise1,premise2); + if(lt == LitB) + return my_and(premise1,premise2); - /* the mixed case is a bit complicated */ + /* the mixed case is a bit complicated */ - static int non_local_count = 0; - ast res = resolve_arith(pivot,conc,premise1,premise2); + static int non_local_count = 0; + ast res = resolve_arith(pivot,conc,premise1,premise2); #ifdef INVARIANT_CHECKING - check_contra(conc,res); + check_contra(conc,res); #endif - non_local_count++; - return res; - } + non_local_count++; + return res; + } - /* Handles the case of resolution on a mixed arith atom. */ + /* Handles the case of resolution on a mixed arith atom. */ - ast resolve_arith(const ast &pivot, const std::vector &conc, node premise1, node premise2){ - ast atom = get_lit_atom(pivot); - hash_map memo; - ast neg_pivot_lit = mk_not(atom); - if(op(pivot) != Not) - std::swap(premise1,premise2); - if(op(pivot) == Equal && op(arg(pivot,0)) == Select && op(arg(pivot,1)) == Select){ - neg_pivot_lit = mk_not(neg_pivot_lit); - std::swap(premise1,premise2); - } - return resolve_arith_rec1(memo, neg_pivot_lit, premise1, premise2); - } + ast resolve_arith(const ast &pivot, const std::vector &conc, node premise1, node premise2){ + ast atom = get_lit_atom(pivot); + hash_map memo; + ast neg_pivot_lit = mk_not(atom); + if(op(pivot) != Not) + std::swap(premise1,premise2); + if(op(pivot) == Equal && op(arg(pivot,0)) == Select && op(arg(pivot,1)) == Select){ + neg_pivot_lit = mk_not(neg_pivot_lit); + std::swap(premise1,premise2); + } + return resolve_arith_rec1(memo, neg_pivot_lit, premise1, premise2); + } - ast apply_coeff(const ast &coeff, const ast &t){ + ast apply_coeff(const ast &coeff, const ast &t){ #if 0 - rational r; - if(!is_integer(coeff,r)) - throw "ack!"; - ast n = make_int(r.numerator()); - ast res = make(Times,n,t); - if(!r.is_int()) { - ast d = make_int(r.numerator()); - res = mk_idiv(res,d); - } - return res; + rational r; + if(!is_integer(coeff,r)) + throw "ack!"; + ast n = make_int(r.numerator()); + ast res = make(Times,n,t); + if(!r.is_int()) { + ast d = make_int(r.numerator()); + res = mk_idiv(res,d); + } + return res; #endif - return make(Times,coeff,t); - } - - ast sum_ineq(const ast &coeff1, const ast &ineq1, const ast &coeff2, const ast &ineq2){ - opr sum_op = Leq; - if(op(ineq1) == Lt || op(ineq2) == Lt) - sum_op = Lt; - ast sum_sides[2]; - for(int i = 0; i < 2; i++){ - sum_sides[i] = make(Plus,apply_coeff(coeff1,arg(ineq1,i)),apply_coeff(coeff2,arg(ineq2,i))); - sum_sides[i] = z3_simplify(sum_sides[i]); + return make(Times,coeff,t); + } + + ast sum_ineq(const ast &coeff1, const ast &ineq1, const ast &coeff2, const ast &ineq2){ + opr sum_op = Leq; + if(op(ineq1) == Lt || op(ineq2) == Lt) + sum_op = Lt; + ast sum_sides[2]; + for(int i = 0; i < 2; i++){ + sum_sides[i] = make(Plus,apply_coeff(coeff1,arg(ineq1,i)),apply_coeff(coeff2,arg(ineq2,i))); + sum_sides[i] = z3_simplify(sum_sides[i]); + } + return make(sum_op,sum_sides[0],sum_sides[1]); } - return make(sum_op,sum_sides[0],sum_sides[1]); - } - void collect_contra_resolvents(int from, const ast &pivot1, const ast &pivot, const ast &conj, std::vector &res){ - int nargs = num_args(conj); - for(int i = from; i < nargs; i++){ - ast f = arg(conj,i); - if(!(f == pivot)){ - ast ph = get_placeholder(mk_not(arg(pivot1,1))); - ast pf = arg(pivot1,0); - ast thing = pf == no_proof ? no_proof : subst_term_and_simp(ph,pf,arg(f,0)); - ast newf = make(contra,thing,arg(f,1)); - res.push_back(newf); - } + void collect_contra_resolvents(int from, const ast &pivot1, const ast &pivot, const ast &conj, std::vector &res){ + int nargs = num_args(conj); + for(int i = from; i < nargs; i++){ + ast f = arg(conj,i); + if(!(f == pivot)){ + ast ph = get_placeholder(mk_not(arg(pivot1,1))); + ast pf = arg(pivot1,0); + ast thing = pf == no_proof ? no_proof : subst_term_and_simp(ph,pf,arg(f,0)); + ast newf = make(contra,thing,arg(f,1)); + res.push_back(newf); + } + } } - } - bool is_negative_equality(const ast &e){ - if(op(e) == Not){ - opr o = op(arg(e,0)); - return o == Equal || o == Iff; + bool is_negative_equality(const ast &e){ + if(op(e) == Not){ + opr o = op(arg(e,0)); + return o == Equal || o == Iff; + } + return false; } - return false; - } - int count_negative_equalities(const std::vector &resolvent){ - int res = 0; - for(unsigned i = 0; i < resolvent.size(); i++) - if(is_negative_equality(arg(resolvent[i],1))) - res++; - return res; - } - - ast resolve_contra_nf(const ast &pivot1, const ast &conj1, - const ast &pivot2, const ast &conj2){ - std::vector resolvent; - collect_contra_resolvents(0,pivot1,pivot2,conj2,resolvent); - collect_contra_resolvents(1,pivot2,pivot1,conj1,resolvent); - if(count_negative_equalities(resolvent) > 1) - throw proof_error(); - if(resolvent.size() == 1) // we have proved a contradiction - return simplify(arg(resolvent[0],0)); // this is the proof -- get interpolant - return make(And,resolvent); - } - - ast resolve_contra(const ast &pivot1, const ast &conj1, - const ast &pivot2, const ast &conj2){ - if(arg(pivot1,0) != no_proof) - return resolve_contra_nf(pivot1, conj1, pivot2, conj2); - if(arg(pivot2,0) != no_proof) - return resolve_contra_nf(pivot2, conj2, pivot1, conj1); - return resolve_with_quantifier(pivot1, conj1, pivot2, conj2); - } - - - bool is_contra_itp(const ast &pivot1, ast itp2, ast &pivot2){ - if(op(itp2) == And){ - int nargs = num_args(itp2); - for(int i = 1; i < nargs; i++){ - ast foo = arg(itp2,i); - if(op(foo) == Uninterpreted && sym(foo) == contra){ - if(arg(foo,1) == pivot1){ - pivot2 = foo; - return true; - } - } - else break; - } + int count_negative_equalities(const std::vector &resolvent){ + int res = 0; + for(unsigned i = 0; i < resolvent.size(); i++) + if(is_negative_equality(arg(resolvent[i],1))) + res++; + return res; } - return false; - } - ast resolve_arith_rec2(hash_map &memo, const ast &pivot1, const ast &conj1, const ast &itp2){ - ast &res = memo[itp2]; - if(!res.null()) - return res; + ast resolve_contra_nf(const ast &pivot1, const ast &conj1, + const ast &pivot2, const ast &conj2){ + std::vector resolvent; + collect_contra_resolvents(0,pivot1,pivot2,conj2,resolvent); + collect_contra_resolvents(1,pivot2,pivot1,conj1,resolvent); + if(count_negative_equalities(resolvent) > 1) + throw proof_error(); + if(resolvent.size() == 1) // we have proved a contradiction + return simplify(arg(resolvent[0],0)); // this is the proof -- get interpolant + return make(And,resolvent); + } + + ast resolve_contra(const ast &pivot1, const ast &conj1, + const ast &pivot2, const ast &conj2){ + if(arg(pivot1,0) != no_proof) + return resolve_contra_nf(pivot1, conj1, pivot2, conj2); + if(arg(pivot2,0) != no_proof) + return resolve_contra_nf(pivot2, conj2, pivot1, conj1); + return resolve_with_quantifier(pivot1, conj1, pivot2, conj2); + } + + + bool is_contra_itp(const ast &pivot1, ast itp2, ast &pivot2){ + if(op(itp2) == And){ + int nargs = num_args(itp2); + for(int i = 1; i < nargs; i++){ + ast foo = arg(itp2,i); + if(op(foo) == Uninterpreted && sym(foo) == contra){ + if(arg(foo,1) == pivot1){ + pivot2 = foo; + return true; + } + } + else break; + } + } + return false; + } + + ast resolve_arith_rec2(hash_map &memo, const ast &pivot1, const ast &conj1, const ast &itp2){ + ast &res = memo[itp2]; + if(!res.null()) + return res; - ast pivot2; - if(is_contra_itp(mk_not(arg(pivot1,1)),itp2,pivot2)) - res = resolve_contra(pivot1,conj1,pivot2,itp2); - else { - switch(op(itp2)){ - case Or: - case And: - case Implies: { - unsigned nargs = num_args(itp2); - std::vector args; args.resize(nargs); - for(unsigned i = 0; i < nargs; i++) - args[i] = resolve_arith_rec2(memo, pivot1, conj1, arg(itp2,i)); - ast foo = itp2; // get rid of const - res = clone(foo,args); - break; - } - default: - { - opr o = op(itp2); - if(o == Uninterpreted){ - symb s = sym(itp2); - if(s == sforall || s == sexists) - res = make(s,arg(itp2,0),resolve_arith_rec2(memo, pivot1, conj1, arg(itp2,1))); - else - res = itp2; - } - else { - res = itp2; - } - } - } + ast pivot2; + if(is_contra_itp(mk_not(arg(pivot1,1)),itp2,pivot2)) + res = resolve_contra(pivot1,conj1,pivot2,itp2); + else { + switch(op(itp2)){ + case Or: + case And: + case Implies: { + unsigned nargs = num_args(itp2); + std::vector args; args.resize(nargs); + for(unsigned i = 0; i < nargs; i++) + args[i] = resolve_arith_rec2(memo, pivot1, conj1, arg(itp2,i)); + ast foo = itp2; // get rid of const + res = clone(foo,args); + break; + } + default: + { + opr o = op(itp2); + if(o == Uninterpreted){ + symb s = sym(itp2); + if(s == sforall || s == sexists) + res = make(s,arg(itp2,0),resolve_arith_rec2(memo, pivot1, conj1, arg(itp2,1))); + else + res = itp2; + } + else { + res = itp2; + } + } + } + } + return res; } - return res; - } - ast resolve_arith_rec1(hash_map &memo, const ast &neg_pivot_lit, const ast &itp1, const ast &itp2){ - ast &res = memo[itp1]; - if(!res.null()) - return res; - ast pivot1; - if(is_contra_itp(neg_pivot_lit,itp1,pivot1)){ - hash_map memo2; - res = resolve_arith_rec2(memo2,pivot1,itp1,itp2); + ast resolve_arith_rec1(hash_map &memo, const ast &neg_pivot_lit, const ast &itp1, const ast &itp2){ + ast &res = memo[itp1]; + if(!res.null()) + return res; + ast pivot1; + if(is_contra_itp(neg_pivot_lit,itp1,pivot1)){ + hash_map memo2; + res = resolve_arith_rec2(memo2,pivot1,itp1,itp2); + } + else { + switch(op(itp1)){ + case Or: + case And: + case Implies: { + unsigned nargs = num_args(itp1); + std::vector args; args.resize(nargs); + for(unsigned i = 0; i < nargs; i++) + args[i] = resolve_arith_rec1(memo, neg_pivot_lit, arg(itp1,i), itp2); + ast foo = itp1; // get rid of const + res = clone(foo,args); + break; + } + default: + { + opr o = op(itp1); + if(o == Uninterpreted){ + symb s = sym(itp1); + if(s == sforall || s == sexists) + res = make(s,arg(itp1,0),resolve_arith_rec1(memo, neg_pivot_lit, arg(itp1,1), itp2)); + else + res = itp1; + } + else { + res = itp1; + } + } + } + } + return res; } - else { - switch(op(itp1)){ - case Or: - case And: - case Implies: { - unsigned nargs = num_args(itp1); - std::vector args; args.resize(nargs); - for(unsigned i = 0; i < nargs; i++) - args[i] = resolve_arith_rec1(memo, neg_pivot_lit, arg(itp1,i), itp2); - ast foo = itp1; // get rid of const - res = clone(foo,args); - break; - } - default: - { - opr o = op(itp1); - if(o == Uninterpreted){ - symb s = sym(itp1); - if(s == sforall || s == sexists) - res = make(s,arg(itp1,0),resolve_arith_rec1(memo, neg_pivot_lit, arg(itp1,1), itp2)); - else - res = itp1; - } - else { - res = itp1; - } - } - } + + void check_contra(hash_set &memo, hash_set &neg_lits, const ast &foo){ + if(memo.find(foo) != memo.end()) + return; + memo.insert(foo); + if(op(foo) == Uninterpreted && sym(foo) == contra){ + ast neg_lit = arg(foo,1); + if(!is_false(neg_lit) && neg_lits.find(neg_lit) == neg_lits.end()) + throw "lost a literal"; + return; + } + else { + switch(op(foo)){ + case Or: + case And: + case Implies: { + unsigned nargs = num_args(foo); + std::vector args; args.resize(nargs); + for(unsigned i = 0; i < nargs; i++) + check_contra(memo, neg_lits, arg(foo,i)); + break; + } + default: break; + } + } } - return res; - } - void check_contra(hash_set &memo, hash_set &neg_lits, const ast &foo){ - if(memo.find(foo) != memo.end()) - return; - memo.insert(foo); - if(op(foo) == Uninterpreted && sym(foo) == contra){ - ast neg_lit = arg(foo,1); - if(!is_false(neg_lit) && neg_lits.find(neg_lit) == neg_lits.end()) - throw "lost a literal"; - return; + void check_contra(const std::vector &neg_lits, const ast &foo){ + hash_set memo; + hash_set neg_lits_set; + for(unsigned i = 0; i < neg_lits.size(); i++) + if(get_term_type(neg_lits[i]) == LitMixed) + neg_lits_set.insert(mk_not(neg_lits[i])); + check_contra(memo,neg_lits_set,foo); } - else { - switch(op(foo)){ - case Or: - case And: - case Implies: { - unsigned nargs = num_args(foo); - std::vector args; args.resize(nargs); - for(unsigned i = 0; i < nargs; i++) - check_contra(memo, neg_lits, arg(foo,i)); - break; - } - default: break; - } + + hash_map subst_memo; // memo of subst function + + ast subst_term_and_simp(const ast &var, const ast &t, const ast &e){ + subst_memo.clear(); + return subst_term_and_simp_rec(var,t,e); } - } - void check_contra(const std::vector &neg_lits, const ast &foo){ - hash_set memo; - hash_set neg_lits_set; - for(unsigned i = 0; i < neg_lits.size(); i++) - if(get_term_type(neg_lits[i]) == LitMixed) - neg_lits_set.insert(mk_not(neg_lits[i])); - check_contra(memo,neg_lits_set,foo); - } - - hash_map subst_memo; // memo of subst function - - ast subst_term_and_simp(const ast &var, const ast &t, const ast &e){ - subst_memo.clear(); - return subst_term_and_simp_rec(var,t,e); - } - - ast subst_term_and_simp_rec(const ast &var, const ast &t, const ast &e){ - if(e == var) return t; - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = subst_memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - if(op(e) == Uninterpreted){ - symb g = sym(e); - if(g == rotate_sum){ - if(var == get_placeholder(arg(e,0))){ - res = e; - } - else - res = make(rotate_sum,arg(e,0),subst_term_and_simp_rec(var,t,arg(e,1))); - return res; - } - if(g == concat){ - res = e; - return res; - } - } - int nargs = num_args(e); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = subst_term_and_simp_rec(var,t,arg(e,i)); - opr f = op(e); - if(f == Equal && args[0] == args[1]) res = mk_true(); - else if(f == And) res = my_and(args); - else if(f == Or) res = my_or(args); - else if(f == Idiv) res = mk_idiv(args[0],args[1]); - else res = clone(e,args); + ast subst_term_and_simp_rec(const ast &var, const ast &t, const ast &e){ + if(e == var) return t; + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = subst_memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + if(op(e) == Uninterpreted){ + symb g = sym(e); + if(g == rotate_sum){ + if(var == get_placeholder(arg(e,0))){ + res = e; + } + else + res = make(rotate_sum,arg(e,0),subst_term_and_simp_rec(var,t,arg(e,1))); + return res; + } + if(g == concat){ + res = e; + return res; + } + } + int nargs = num_args(e); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = subst_term_and_simp_rec(var,t,arg(e,i)); + opr f = op(e); + if(f == Equal && args[0] == args[1]) res = mk_true(); + else if(f == And) res = my_and(args); + else if(f == Or) res = my_or(args); + else if(f == Idiv) res = mk_idiv(args[0],args[1]); + else res = clone(e,args); + } + return res; } - return res; - } - /* This is where the real work happens. Here, we simplify the - proof obtained by cut elimination, obtaining an interpolant. */ + /* This is where the real work happens. Here, we simplify the + proof obtained by cut elimination, obtaining an interpolant. */ - struct cannot_simplify {}; - hash_map simplify_memo; + struct cannot_simplify {}; + hash_map simplify_memo; - ast simplify(const ast &t){ - ast res = normalize(simplify_rec(t)); + ast simplify(const ast &t){ + ast res = normalize(simplify_rec(t)); #ifdef BOGUS_QUANTS - if(localization_vars.size()) - res = add_quants(z3_simplify(res)); + if(localization_vars.size()) + res = add_quants(z3_simplify(res)); #endif - return res; - } + return res; + } - ast simplify_rec(const ast &e){ - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = simplify_memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - int nargs = num_args(e); - std::vector args(nargs); - bool placeholder_arg = false; - symb g = sym(e); - if(g == concat){ - res = e; - return res; - } - for(int i = 0; i < nargs; i++){ - if(i == 0 && g == rotate_sum) - args[i] = arg(e,i); - else - args[i] = simplify_rec(arg(e,i)); - placeholder_arg |= is_placeholder(args[i]); - } - try { - opr f = op(e); - if(f == Equal && args[0] == args[1]) res = mk_true(); - else if(f == And) res = my_and(args); - else if(f == Or) - res = my_or(args); - else if(f == Idiv) res = mk_idiv(args[0],args[1]); - else if(f == Uninterpreted && !placeholder_arg){ - if(g == rotate_sum) res = simplify_rotate(args); - else if(g == symm) res = simplify_symm(args); - else if(g == modpon) res = simplify_modpon(args); - else if(g == sum) res = simplify_sum(args); - else if(g == exmid) res = simplify_exmid(args); - else if(g == cong) res = simplify_cong(args); + ast simplify_rec(const ast &e){ + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = simplify_memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + int nargs = num_args(e); + std::vector args(nargs); + bool placeholder_arg = false; + symb g = sym(e); + if(g == concat){ + res = e; + return res; + } + for(int i = 0; i < nargs; i++){ + if(i == 0 && g == rotate_sum) + args[i] = arg(e,i); + else + args[i] = simplify_rec(arg(e,i)); + placeholder_arg |= is_placeholder(args[i]); + } + try { + opr f = op(e); + if(f == Equal && args[0] == args[1]) res = mk_true(); + else if(f == And) res = my_and(args); + else if(f == Or) + res = my_or(args); + else if(f == Idiv) res = mk_idiv(args[0],args[1]); + else if(f == Uninterpreted && !placeholder_arg){ + if(g == rotate_sum) res = simplify_rotate(args); + else if(g == symm) res = simplify_symm(args); + else if(g == modpon) res = simplify_modpon(args); + else if(g == sum) res = simplify_sum(args); + else if(g == exmid) res = simplify_exmid(args); + else if(g == cong) res = simplify_cong(args); #if 0 - else if(g == modpon) res = simplify_modpon(args); - else if(g == leq2eq) res = simplify_leq2eq(args); - else if(g == eq2leq) res = simplify_eq2leq(args); + else if(g == modpon) res = simplify_modpon(args); + else if(g == leq2eq) res = simplify_leq2eq(args); + else if(g == eq2leq) res = simplify_eq2leq(args); #endif - else res = clone(e,args); - } - else res = clone(e,args); - } - catch (const cannot_simplify &){ - res = clone(e,args); - } + else res = clone(e,args); + } + else res = clone(e,args); + } + catch (const cannot_simplify &){ + res = clone(e,args); + } + } + return res; } - return res; - } - ast simplify_rotate(const std::vector &args){ - const ast &pf = args[1]; - ast pl = get_placeholder(args[0]); - if(op(pf) == Uninterpreted){ - symb g = sym(pf); - if(g == sum) return simplify_rotate_sum(pl,pf); - if(g == leq2eq) return simplify_rotate_leq2eq(pl,args[0],pf); - if(g == eq2leq) return simplify_rotate_eq2leq(pl,args[0],pf); - if(g == cong) return simplify_rotate_cong(pl,args[0],pf); - if(g == modpon) return simplify_rotate_modpon(pl,args[0],pf); - // if(g == symm) return simplify_rotate_symm(pl,args[0],pf); + ast simplify_rotate(const std::vector &args){ + const ast &pf = args[1]; + ast pl = get_placeholder(args[0]); + if(op(pf) == Uninterpreted){ + symb g = sym(pf); + if(g == sum) return simplify_rotate_sum(pl,pf); + if(g == leq2eq) return simplify_rotate_leq2eq(pl,args[0],pf); + if(g == eq2leq) return simplify_rotate_eq2leq(pl,args[0],pf); + if(g == cong) return simplify_rotate_cong(pl,args[0],pf); + if(g == modpon) return simplify_rotate_modpon(pl,args[0],pf); + // if(g == symm) return simplify_rotate_symm(pl,args[0],pf); + } + if(op(pf) == Leq) + throw "foo!"; + throw cannot_simplify(); } - if(op(pf) == Leq) - throw "foo!"; - throw cannot_simplify(); - } - bool is_normal_ineq(const ast &ineq){ - if(sym(ineq) == normal) - return is_ineq(arg(ineq,0)); - return is_ineq(ineq); - } - - ast destruct_cond_ineq(const ast &ineq, ast &Aproves, ast &Bproves){ - ast res = ineq; - opr o = op(res); - if(o == And){ - Aproves = my_and(Aproves,arg(res,0)); - res = arg(res,1); - o = op(res); + bool is_normal_ineq(const ast &ineq){ + if(sym(ineq) == normal) + return is_ineq(arg(ineq,0)); + return is_ineq(ineq); } - if(o == Implies){ - Bproves = my_and(Bproves,arg(res,0)); - res = arg(res,1); + + ast destruct_cond_ineq(const ast &ineq, ast &Aproves, ast &Bproves){ + ast res = ineq; + opr o = op(res); + if(o == And){ + Aproves = my_and(Aproves,arg(res,0)); + res = arg(res,1); + o = op(res); + } + if(o == Implies){ + Bproves = my_and(Bproves,arg(res,0)); + res = arg(res,1); + } + return res; } - return res; - } - ast distribute_coeff(const ast &coeff, const ast &s){ - if(sym(s) == sum){ - if(sym(arg(s,2)) == sum) - return make(sum, - distribute_coeff(coeff,arg(s,0)), - make_int(rational(1)), - distribute_coeff(make(Times,coeff,arg(s,1)), arg(s,2))); - else - return make(sum, - distribute_coeff(coeff,arg(s,0)), - make(Times,coeff,arg(s,1)), - arg(s,2)); + ast distribute_coeff(const ast &coeff, const ast &s){ + if(sym(s) == sum){ + if(sym(arg(s,2)) == sum) + return make(sum, + distribute_coeff(coeff,arg(s,0)), + make_int(rational(1)), + distribute_coeff(make(Times,coeff,arg(s,1)), arg(s,2))); + else + return make(sum, + distribute_coeff(coeff,arg(s,0)), + make(Times,coeff,arg(s,1)), + arg(s,2)); + } + if(op(s) == Leq && arg(s,1) == make_int(rational(0)) && arg(s,2) == make_int(rational(0))) + return s; + return make(sum,make(Leq,make_int(rational(0)),make_int(rational(0))),coeff,s); } - if(op(s) == Leq && arg(s,1) == make_int(rational(0)) && arg(s,2) == make_int(rational(0))) - return s; - return make(sum,make(Leq,make_int(rational(0)),make_int(rational(0))),coeff,s); - } - ast simplify_sum(std::vector &args){ - if(args[1] != make_int(rational(1))){ - if(sym(args[2]) == sum) - return make(sum,args[0],make_int(rational(1)),distribute_coeff(args[1],args[2])); + ast simplify_sum(std::vector &args){ + if(args[1] != make_int(rational(1))){ + if(sym(args[2]) == sum) + return make(sum,args[0],make_int(rational(1)),distribute_coeff(args[1],args[2])); + } + ast Aproves = mk_true(), Bproves = mk_true(); + ast ineq = destruct_cond_ineq(args[0],Aproves,Bproves); + if(!is_normal_ineq(ineq)) throw cannot_simplify(); + sum_cond_ineq(ineq,args[1],args[2],Aproves,Bproves); + return my_and(Aproves,my_implies(Bproves,ineq)); } - ast Aproves = mk_true(), Bproves = mk_true(); - ast ineq = destruct_cond_ineq(args[0],Aproves,Bproves); - if(!is_normal_ineq(ineq)) throw cannot_simplify(); - sum_cond_ineq(ineq,args[1],args[2],Aproves,Bproves); - return my_and(Aproves,my_implies(Bproves,ineq)); - } - ast simplify_rotate_sum(const ast &pl, const ast &pf){ - ast Aproves = mk_true(), Bproves = mk_true(); - ast ineq = make(Leq,make_int("0"),make_int("0")); - ineq = rotate_sum_rec(pl,pf,Aproves,Bproves,ineq); - if(is_true(Aproves) && is_true(Bproves)) - return ineq; - return my_and(Aproves,my_implies(Bproves,ineq)); - } + ast simplify_rotate_sum(const ast &pl, const ast &pf){ + ast Aproves = mk_true(), Bproves = mk_true(); + ast ineq = make(Leq,make_int("0"),make_int("0")); + ineq = rotate_sum_rec(pl,pf,Aproves,Bproves,ineq); + if(is_true(Aproves) && is_true(Bproves)) + return ineq; + return my_and(Aproves,my_implies(Bproves,ineq)); + } - bool is_rewrite_chain(const ast &chain){ - return sym(chain) == concat; - } + bool is_rewrite_chain(const ast &chain){ + return sym(chain) == concat; + } #if 0 - ast ineq_from_chain_simple(const ast &chain, ast &cond){ - if(is_true(chain)) - return chain; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(is_true(rest) && is_rewrite_side(LitA,last) - && is_true(rewrite_lhs(last))){ - cond = my_and(cond,rewrite_cond(last)); - return rewrite_rhs(last); + ast ineq_from_chain_simple(const ast &chain, ast &cond){ + if(is_true(chain)) + return chain; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(is_true(rest) && is_rewrite_side(LitA,last) + && is_true(rewrite_lhs(last))){ + cond = my_and(cond,rewrite_cond(last)); + return rewrite_rhs(last); + } + if(is_rewrite_side(LitB,last) && is_true(rewrite_cond(last))) + return ineq_from_chain_simple(rest,cond); + return chain; } - if(is_rewrite_side(LitB,last) && is_true(rewrite_cond(last))) - return ineq_from_chain_simple(rest,cond); - return chain; - } #endif - ast ineq_from_chain(const ast &chain, ast &Aproves, ast &Bproves){ - if(is_rewrite_chain(chain)) - return rewrite_chain_to_normal_ineq(chain,Aproves,Bproves); - return chain; - } + ast ineq_from_chain(const ast &chain, ast &Aproves, ast &Bproves){ + if(is_rewrite_chain(chain)) + return rewrite_chain_to_normal_ineq(chain,Aproves,Bproves); + return chain; + } - void sum_cond_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){ - opr o = op(ineq2); - if(o == And){ - sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves); - Aproves = my_and(Aproves,arg(ineq2,0)); + void sum_cond_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){ + opr o = op(ineq2); + if(o == And){ + sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves); + Aproves = my_and(Aproves,arg(ineq2,0)); + } + else if(o == Implies){ + sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves); + Bproves = my_and(Bproves,arg(ineq2,0)); + } + else { + ast the_ineq = ineq_from_chain(ineq2,Aproves,Bproves); + if(sym(ineq) == normal || sym(the_ineq) == normal){ + sum_normal_ineq(ineq,coeff2,the_ineq,Aproves,Bproves); + return; + } + if(is_ineq(the_ineq)) + linear_comb(ineq,coeff2,the_ineq); + else + throw cannot_simplify(); + } } - else if(o == Implies){ - sum_cond_ineq(ineq,coeff2,arg(ineq2,1),Aproves,Bproves); - Bproves = my_and(Bproves,arg(ineq2,0)); - } - else { - ast the_ineq = ineq_from_chain(ineq2,Aproves,Bproves); - if(sym(ineq) == normal || sym(the_ineq) == normal){ - sum_normal_ineq(ineq,coeff2,the_ineq,Aproves,Bproves); - return; - } - if(is_ineq(the_ineq)) - linear_comb(ineq,coeff2,the_ineq); - else - throw cannot_simplify(); - } - } - void destruct_normal(const ast &pf, ast &p, ast &n){ - if(sym(pf) == normal){ - p = arg(pf,0); - n = arg(pf,1); + void destruct_normal(const ast &pf, ast &p, ast &n){ + if(sym(pf) == normal){ + p = arg(pf,0); + n = arg(pf,1); + } + else { + p = pf; + n = mk_true(); + } } - else { - p = pf; - n = mk_true(); + + void sum_normal_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){ + ast in1,in2,n1,n2; + destruct_normal(ineq,in1,n1); + destruct_normal(ineq2,in2,n2); + ast dummy1, dummy2; + sum_cond_ineq(in1,coeff2,in2,dummy1,dummy2); + n1 = merge_normal_chains(n1,n2, Aproves, Bproves); + ineq = is_true(n1) ? in1 : make_normal(in1,n1); } - } - void sum_normal_ineq(ast &ineq, const ast &coeff2, const ast &ineq2, ast &Aproves, ast &Bproves){ - ast in1,in2,n1,n2; - destruct_normal(ineq,in1,n1); - destruct_normal(ineq2,in2,n2); - ast dummy1, dummy2; - sum_cond_ineq(in1,coeff2,in2,dummy1,dummy2); - n1 = merge_normal_chains(n1,n2, Aproves, Bproves); - ineq = is_true(n1) ? in1 : make_normal(in1,n1); - } - - bool is_ineq(const ast &ineq){ - opr o = op(ineq); - if(o == Not) o = op(arg(ineq,0)); - return o == Leq || o == Lt || o == Geq || o == Gt; - } - - // divide both sides of inequality by a non-negative integer divisor - ast idiv_ineq(const ast &ineq1, const ast &divisor){ - if(sym(ineq1) == normal){ - ast in1,n1; - destruct_normal(ineq1,in1,n1); - in1 = idiv_ineq(in1,divisor); - return make_normal(in1,n1); + bool is_ineq(const ast &ineq){ + opr o = op(ineq); + if(o == Not) o = op(arg(ineq,0)); + return o == Leq || o == Lt || o == Geq || o == Gt; + } + + // divide both sides of inequality by a non-negative integer divisor + ast idiv_ineq(const ast &ineq1, const ast &divisor){ + if(sym(ineq1) == normal){ + ast in1,n1; + destruct_normal(ineq1,in1,n1); + in1 = idiv_ineq(in1,divisor); + return make_normal(in1,n1); + } + if(divisor == make_int(rational(1))) + return ineq1; + ast ineq = ineq1; + if(op(ineq) == Lt) + ineq = simplify_ineq(make(Leq,arg(ineq,0),make(Sub,arg(ineq,1),make_int("1")))); + return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor)); } - if(divisor == make_int(rational(1))) - return ineq1; - ast ineq = ineq1; - if(op(ineq) == Lt) - ineq = simplify_ineq(make(Leq,arg(ineq,0),make(Sub,arg(ineq,1),make_int("1")))); - return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor)); - } - ast rotate_sum_rec(const ast &pl, const ast &pf, ast &Aproves, ast &Bproves, ast &ineq){ - if(pf == pl){ - if(sym(ineq) == normal) - return ineq; - return simplify_ineq(ineq); + ast rotate_sum_rec(const ast &pl, const ast &pf, ast &Aproves, ast &Bproves, ast &ineq){ + if(pf == pl){ + if(sym(ineq) == normal) + return ineq; + return simplify_ineq(ineq); + } + if(op(pf) == Uninterpreted && sym(pf) == sum){ + if(arg(pf,2) == pl){ + sum_cond_ineq(ineq,make_int("1"),arg(pf,0),Aproves,Bproves); + ineq = idiv_ineq(ineq,arg(pf,1)); + return ineq; + } + sum_cond_ineq(ineq,arg(pf,1),arg(pf,2),Aproves,Bproves); + return rotate_sum_rec(pl,arg(pf,0),Aproves,Bproves,ineq); + } + throw cannot_simplify(); } - if(op(pf) == Uninterpreted && sym(pf) == sum){ - if(arg(pf,2) == pl){ - sum_cond_ineq(ineq,make_int("1"),arg(pf,0),Aproves,Bproves); - ineq = idiv_ineq(ineq,arg(pf,1)); - return ineq; - } - sum_cond_ineq(ineq,arg(pf,1),arg(pf,2),Aproves,Bproves); - return rotate_sum_rec(pl,arg(pf,0),Aproves,Bproves,ineq); + + ast simplify_rotate_leq2eq(const ast &pl, const ast &neg_equality, const ast &pf){ + if(pl == arg(pf,0)){ + ast equality = arg(neg_equality,0); + ast x = arg(equality,0); + ast y = arg(equality,1); + ast Aproves1 = mk_true(), Bproves1 = mk_true(); + ast pf1 = destruct_cond_ineq(arg(pf,1), Aproves1, Bproves1); + ast pf2 = destruct_cond_ineq(arg(pf,2), Aproves1, Bproves1); + ast xleqy = round_ineq(ineq_from_chain(pf1,Aproves1,Bproves1)); + ast yleqx = round_ineq(ineq_from_chain(pf2,Aproves1,Bproves1)); + ast ineq1 = make(Leq,make_int("0"),make_int("0")); + sum_cond_ineq(ineq1,make_int("-1"),xleqy,Aproves1,Bproves1); + sum_cond_ineq(ineq1,make_int("-1"),yleqx,Aproves1,Bproves1); + ast Acond = my_implies(Aproves1,my_and(Bproves1,z3_simplify(ineq1))); + ast Aproves2 = mk_true(), Bproves2 = mk_true(); + ast ineq2 = make(Leq,make_int("0"),make_int("0")); + sum_cond_ineq(ineq2,make_int("1"),xleqy,Aproves2,Bproves2); + sum_cond_ineq(ineq2,make_int("1"),yleqx,Aproves2,Bproves2); + ast Bcond = my_implies(Bproves1,my_and(Aproves1,z3_simplify(ineq2))); + // if(!is_true(Aproves1) || !is_true(Bproves1)) + // std::cout << "foo!\n";; + if(y == make_int(rational(0)) && op(x) == Plus && num_args(x) == 2){ + if(get_term_type(arg(x,0)) == LitA){ + ast iter = z3_simplify(make(Plus,arg(x,0),get_ineq_rhs(xleqy))); + ast rewrite1 = make_rewrite(LitA,pos_add(0,top_pos),Acond,make(Equal,arg(x,0),iter)); + iter = make(Plus,iter,arg(x,1)); + ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); + return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); + } + if(get_term_type(arg(x,1)) == LitA){ + ast iter = z3_simplify(make(Plus,arg(x,1),get_ineq_rhs(xleqy))); + ast rewrite1 = make_rewrite(LitA,pos_add(1,top_pos),Acond,make(Equal,arg(x,1),iter)); + iter = make(Plus,arg(x,0),iter); + ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); + return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); + } + } + if(get_term_type(x) == LitA){ + ast iter = z3_simplify(make(Plus,x,get_ineq_rhs(xleqy))); + ast rewrite1 = make_rewrite(LitA,top_pos,Acond,make(Equal,x,iter)); + ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); + return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); + } + if(get_term_type(y) == LitA){ + ast iter = z3_simplify(make(Plus,y,get_ineq_rhs(yleqx))); + ast rewrite2 = make_rewrite(LitA,top_pos,Acond,make(Equal,iter,y)); + ast rewrite1 = make_rewrite(LitB,top_pos,Bcond,make(Equal,x,iter)); + return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); + } + throw cannot_simplify(); + } + throw cannot_simplify(); } - throw cannot_simplify(); - } - ast simplify_rotate_leq2eq(const ast &pl, const ast &neg_equality, const ast &pf){ - if(pl == arg(pf,0)){ - ast equality = arg(neg_equality,0); - ast x = arg(equality,0); - ast y = arg(equality,1); - ast Aproves1 = mk_true(), Bproves1 = mk_true(); - ast pf1 = destruct_cond_ineq(arg(pf,1), Aproves1, Bproves1); - ast pf2 = destruct_cond_ineq(arg(pf,2), Aproves1, Bproves1); - ast xleqy = round_ineq(ineq_from_chain(pf1,Aproves1,Bproves1)); - ast yleqx = round_ineq(ineq_from_chain(pf2,Aproves1,Bproves1)); - ast ineq1 = make(Leq,make_int("0"),make_int("0")); - sum_cond_ineq(ineq1,make_int("-1"),xleqy,Aproves1,Bproves1); - sum_cond_ineq(ineq1,make_int("-1"),yleqx,Aproves1,Bproves1); - ast Acond = my_implies(Aproves1,my_and(Bproves1,z3_simplify(ineq1))); - ast Aproves2 = mk_true(), Bproves2 = mk_true(); - ast ineq2 = make(Leq,make_int("0"),make_int("0")); - sum_cond_ineq(ineq2,make_int("1"),xleqy,Aproves2,Bproves2); - sum_cond_ineq(ineq2,make_int("1"),yleqx,Aproves2,Bproves2); - ast Bcond = my_implies(Bproves1,my_and(Aproves1,z3_simplify(ineq2))); - // if(!is_true(Aproves1) || !is_true(Bproves1)) - // std::cout << "foo!\n";; - if(y == make_int(rational(0)) && op(x) == Plus && num_args(x) == 2){ - if(get_term_type(arg(x,0)) == LitA){ - ast iter = z3_simplify(make(Plus,arg(x,0),get_ineq_rhs(xleqy))); - ast rewrite1 = make_rewrite(LitA,pos_add(0,top_pos),Acond,make(Equal,arg(x,0),iter)); - iter = make(Plus,iter,arg(x,1)); - ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); - return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); - } - if(get_term_type(arg(x,1)) == LitA){ - ast iter = z3_simplify(make(Plus,arg(x,1),get_ineq_rhs(xleqy))); - ast rewrite1 = make_rewrite(LitA,pos_add(1,top_pos),Acond,make(Equal,arg(x,1),iter)); - iter = make(Plus,arg(x,0),iter); - ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); - return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); - } - } - if(get_term_type(x) == LitA){ - ast iter = z3_simplify(make(Plus,x,get_ineq_rhs(xleqy))); - ast rewrite1 = make_rewrite(LitA,top_pos,Acond,make(Equal,x,iter)); - ast rewrite2 = make_rewrite(LitB,top_pos,Bcond,make(Equal,iter,y)); - return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); - } - if(get_term_type(y) == LitA){ - ast iter = z3_simplify(make(Plus,y,get_ineq_rhs(yleqx))); - ast rewrite2 = make_rewrite(LitA,top_pos,Acond,make(Equal,iter,y)); - ast rewrite1 = make_rewrite(LitB,top_pos,Bcond,make(Equal,x,iter)); - return chain_cons(chain_cons(mk_true(),rewrite1),rewrite2); - } - throw cannot_simplify(); + ast round_ineq(const ast &ineq){ + if(sym(ineq) == normal) + return make_normal(round_ineq(arg(ineq,0)),arg(ineq,1)); + if(!is_ineq(ineq)) + throw cannot_simplify(); + ast res = simplify_ineq(ineq); + if(op(res) == Lt) + res = make(Leq,arg(res,0),make(Sub,arg(res,1),make_int("1"))); + return res; } - throw cannot_simplify(); - } - ast round_ineq(const ast &ineq){ - if(sym(ineq) == normal) - return make_normal(round_ineq(arg(ineq,0)),arg(ineq,1)); - if(!is_ineq(ineq)) - throw cannot_simplify(); - ast res = simplify_ineq(ineq); - if(op(res) == Lt) - res = make(Leq,arg(res,0),make(Sub,arg(res,1),make_int("1"))); - return res; - } - - ast unmixed_eq2ineq(const ast &lhs, const ast &rhs, opr comp_op, const ast &equa, ast &cond){ - ast ineqs= chain_ineqs(comp_op,LitA,equa,lhs,rhs); // chain must be from lhs to rhs - cond = my_and(cond,chain_conditions(LitA,equa)); - ast Bconds = z3_simplify(chain_conditions(LitB,equa)); - if(is_true(Bconds) && op(ineqs) != And) - return my_implies(cond,ineqs); - if(op(ineqs) != And) - return my_and(Bconds,my_implies(cond,ineqs)); - throw "help!"; - } - - ast add_mixed_eq2ineq(const ast &lhs, const ast &rhs, const ast &equa, const ast &itp){ - if(is_true(equa)) - return itp; - std::vector args(3); - args[0] = itp; - args[1] = make_int("1"); - ast ineq = make(Leq,make_int(rational(0)),make_int(rational(0))); - args[2] = make_normal(ineq,cons_normal(fix_normal(lhs,rhs,equa),mk_true())); - return simplify_sum(args); - } - - - ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){ - if(pl == arg(pf,1)){ - ast cond = mk_true(); - ast equa = sep_cond(arg(pf,0),cond); - if(is_equivrel_chain(equa)){ - ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove - if(!rewrites_from_to(equa,lhs,rhs)){ - lhs = arg(arg(neg_equality,0),0); // the equality proved is ambiguous, sadly - rhs = arg(arg(neg_equality,0),1); - } - LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs); - if(lhst != LitMixed && rhst != LitMixed) - return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond); - else { - ast left, left_term, middle, right_term, right; - left = get_left_movers(equa,lhs,middle,left_term); - middle = get_right_movers(middle,rhs,right,right_term); - ast itp = unmixed_eq2ineq(left_term, right_term, op(arg(neg_equality,0)), middle, cond); - // itp = my_implies(cond,itp); - itp = add_mixed_eq2ineq(lhs, left_term, left, itp); - itp = add_mixed_eq2ineq(right_term, rhs, right, itp); - return itp; - } - } + ast unmixed_eq2ineq(const ast &lhs, const ast &rhs, opr comp_op, const ast &equa, ast &cond){ + ast ineqs= chain_ineqs(comp_op,LitA,equa,lhs,rhs); // chain must be from lhs to rhs + cond = my_and(cond,chain_conditions(LitA,equa)); + ast Bconds = z3_simplify(chain_conditions(LitB,equa)); + if(is_true(Bconds) && op(ineqs) != And) + return my_implies(cond,ineqs); + if(op(ineqs) != And) + return my_and(Bconds,my_implies(cond,ineqs)); + throw "help!"; } - throw "help!"; - } - void reverse_modpon(std::vector &args){ - std::vector sargs(1); sargs[0] = args[1]; - args[1] = simplify_symm(sargs); - if(is_equivrel_chain(args[2])) - args[1] = down_chain(args[1]); - std::swap(args[0],args[2]); - } + ast add_mixed_eq2ineq(const ast &lhs, const ast &rhs, const ast &equa, const ast &itp){ + if(is_true(equa)) + return itp; + std::vector args(3); + args[0] = itp; + args[1] = make_int("1"); + ast ineq = make(Leq,make_int(rational(0)),make_int(rational(0))); + args[2] = make_normal(ineq,cons_normal(fix_normal(lhs,rhs,equa),mk_true())); + return simplify_sum(args); + } - ast simplify_rotate_modpon(const ast &pl, const ast &neg_equality, const ast &pf){ - std::vector args; args.resize(3); - args[0] = arg(pf,0); - args[1] = arg(pf,1); - args[2] = arg(pf,2); - if(pl == args[0]) - reverse_modpon(args); - if(pl == args[2]){ - ast cond = mk_true(); - ast chain = simplify_modpon_fwd(args, cond); - return my_implies(cond,chain); - } - throw cannot_simplify(); - } - ast get_ineq_rhs(const ast &ineq2){ - opr o = op(ineq2); - if(o == Implies) - return get_ineq_rhs(arg(ineq2,1)); - else if(o == Leq || o == Lt) - return arg(ineq2,1); - throw cannot_simplify(); - } + ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){ + if(pl == arg(pf,1)){ + ast cond = mk_true(); + ast equa = sep_cond(arg(pf,0),cond); + if(is_equivrel_chain(equa)){ + ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove + if(!rewrites_from_to(equa,lhs,rhs)){ + lhs = arg(arg(neg_equality,0),0); // the equality proved is ambiguous, sadly + rhs = arg(arg(neg_equality,0),1); + } + LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs); + if(lhst != LitMixed && rhst != LitMixed) + return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond); + else { + ast left, left_term, middle, right_term, right; + left = get_left_movers(equa,lhs,middle,left_term); + middle = get_right_movers(middle,rhs,right,right_term); + ast itp = unmixed_eq2ineq(left_term, right_term, op(arg(neg_equality,0)), middle, cond); + // itp = my_implies(cond,itp); + itp = add_mixed_eq2ineq(lhs, left_term, left, itp); + itp = add_mixed_eq2ineq(right_term, rhs, right, itp); + return itp; + } + } + } + throw "help!"; + } - ast simplify_rotate_cong(const ast &pl, const ast &neg_equality, const ast &pf){ - if(pl == arg(pf,2)){ - if(op(arg(pf,0)) == True) - return mk_true(); - rational pos; - if(is_numeral(arg(pf,1),pos)){ - int ipos = pos.get_unsigned(); - ast cond = mk_true(); - ast equa = sep_cond(arg(pf,0),cond); + void reverse_modpon(std::vector &args){ + std::vector sargs(1); sargs[0] = args[1]; + args[1] = simplify_symm(sargs); + if(is_equivrel_chain(args[2])) + args[1] = down_chain(args[1]); + std::swap(args[0],args[2]); + } + + ast simplify_rotate_modpon(const ast &pl, const ast &neg_equality, const ast &pf){ + std::vector args; args.resize(3); + args[0] = arg(pf,0); + args[1] = arg(pf,1); + args[2] = arg(pf,2); + if(pl == args[0]) + reverse_modpon(args); + if(pl == args[2]){ + ast cond = mk_true(); + ast chain = simplify_modpon_fwd(args, cond); + return my_implies(cond,chain); + } + throw cannot_simplify(); + } + + ast get_ineq_rhs(const ast &ineq2){ + opr o = op(ineq2); + if(o == Implies) + return get_ineq_rhs(arg(ineq2,1)); + else if(o == Leq || o == Lt) + return arg(ineq2,1); + throw cannot_simplify(); + } + + ast simplify_rotate_cong(const ast &pl, const ast &neg_equality, const ast &pf){ + if(pl == arg(pf,2)){ + if(op(arg(pf,0)) == True) + return mk_true(); + rational pos; + if(is_numeral(arg(pf,1),pos)){ + int ipos = pos.get_unsigned(); + ast cond = mk_true(); + ast equa = sep_cond(arg(pf,0),cond); #if 0 - if(op(equa) == Equal){ - ast pe = mk_not(neg_equality); - ast lhs = subst_in_arg_pos(ipos,arg(equa,0),arg(pe,0)); - ast rhs = subst_in_arg_pos(ipos,arg(equa,1),arg(pe,1)); - ast res = make(Equal,lhs,rhs); - return my_implies(cond,res); - } + if(op(equa) == Equal){ + ast pe = mk_not(neg_equality); + ast lhs = subst_in_arg_pos(ipos,arg(equa,0),arg(pe,0)); + ast rhs = subst_in_arg_pos(ipos,arg(equa,1),arg(pe,1)); + ast res = make(Equal,lhs,rhs); + return my_implies(cond,res); + } #endif - ast res = chain_pos_add(ipos,equa); - return my_implies(cond,res); - } + ast res = chain_pos_add(ipos,equa); + return my_implies(cond,res); + } + } + throw cannot_simplify(); } - throw cannot_simplify(); - } - ast simplify_symm(const std::vector &args){ - if(op(args[0]) == True) - return mk_true(); - ast cond = mk_true(); - ast equa = sep_cond(args[0],cond); - if(is_equivrel_chain(equa)) - return my_implies(cond,reverse_chain(equa)); - if(is_negation_chain(equa)) - return commute_negation_chain(equa); - throw cannot_simplify(); - } + ast simplify_symm(const std::vector &args){ + if(op(args[0]) == True) + return mk_true(); + ast cond = mk_true(); + ast equa = sep_cond(args[0],cond); + if(is_equivrel_chain(equa)) + return my_implies(cond,reverse_chain(equa)); + if(is_negation_chain(equa)) + return commute_negation_chain(equa); + throw cannot_simplify(); + } - ast simplify_modpon_fwd(const std::vector &args, ast &cond){ - ast P = sep_cond(args[0],cond); - ast PeqQ = sep_cond(args[1],cond); - ast chain; - if(is_equivrel_chain(P)){ - try { - ast split[2]; - split_chain(PeqQ,split); - chain = reverse_chain(split[0]); - chain = concat_rewrite_chain(chain,P); - chain = concat_rewrite_chain(chain,split[1]); - } - catch(const cannot_split &){ - static int this_count = 0; - this_count++; - ast tail, pref = get_head_chain(PeqQ,tail,false); // pref is x=y, tail is x=y -> x'=y' - ast split[2]; split_chain(tail,split); // rewrites from x to x' and y to y' - ast head = chain_last(pref); - ast prem = make_rewrite(rewrite_side(head),top_pos,rewrite_cond(head),make(Iff,mk_true(),mk_not(rewrite_lhs(head)))); - ast back_chain = chain_cons(mk_true(),prem); - back_chain = concat_rewrite_chain(back_chain,chain_pos_add(0,reverse_chain(chain_rest(pref)))); - ast cond = contra_chain(back_chain,P); - if(is_rewrite_side(LitA,head)) - cond = mk_not(cond); - ast fwd_rewrite = make_rewrite(rewrite_side(head),top_pos,cond,rewrite_rhs(head)); - P = chain_cons(mk_true(),fwd_rewrite); - chain = reverse_chain(split[0]); - chain = concat_rewrite_chain(chain,P); - chain = concat_rewrite_chain(chain,split[1]); - } + ast simplify_modpon_fwd(const std::vector &args, ast &cond){ + ast P = sep_cond(args[0],cond); + ast PeqQ = sep_cond(args[1],cond); + ast chain; + if(is_equivrel_chain(P)){ + try { + ast split[2]; + split_chain(PeqQ,split); + chain = reverse_chain(split[0]); + chain = concat_rewrite_chain(chain,P); + chain = concat_rewrite_chain(chain,split[1]); + } + catch(const cannot_split &){ + static int this_count = 0; + this_count++; + ast tail, pref = get_head_chain(PeqQ,tail,false); // pref is x=y, tail is x=y -> x'=y' + ast split[2]; split_chain(tail,split); // rewrites from x to x' and y to y' + ast head = chain_last(pref); + ast prem = make_rewrite(rewrite_side(head),top_pos,rewrite_cond(head),make(Iff,mk_true(),mk_not(rewrite_lhs(head)))); + ast back_chain = chain_cons(mk_true(),prem); + back_chain = concat_rewrite_chain(back_chain,chain_pos_add(0,reverse_chain(chain_rest(pref)))); + ast cond = contra_chain(back_chain,P); + if(is_rewrite_side(LitA,head)) + cond = mk_not(cond); + ast fwd_rewrite = make_rewrite(rewrite_side(head),top_pos,cond,rewrite_rhs(head)); + P = chain_cons(mk_true(),fwd_rewrite); + chain = reverse_chain(split[0]); + chain = concat_rewrite_chain(chain,P); + chain = concat_rewrite_chain(chain,split[1]); + } + } + else { // if not an equivalence, must be of form T <-> pred + chain = concat_rewrite_chain(P,PeqQ); + } + return chain; } - else { // if not an equivalence, must be of form T <-> pred - chain = concat_rewrite_chain(P,PeqQ); - } - return chain; - } - struct subterm_normals_failed {}; + struct subterm_normals_failed {}; - void get_subterm_normals(const ast &ineq1, const ast &ineq2, const ast &chain, ast &normals, - const ast &pos, hash_set &memo, ast &Aproves, ast &Bproves){ - opr o1 = op(ineq1); - opr o2 = op(ineq2); - if(o1 == Not || o1 == Leq || o1 == Lt || o1 == Geq || o1 == Gt || o1 == Plus || o1 == Times){ - int n = num_args(ineq1); - if(o2 != o1 || num_args(ineq2) != n) - throw "bad inequality rewriting"; - for(int i = 0; i < n; i++){ - ast new_pos = add_pos_to_end(pos,i); - get_subterm_normals(arg(ineq1,i), arg(ineq2,i), chain, normals, new_pos, memo, Aproves, Bproves); - } + void get_subterm_normals(const ast &ineq1, const ast &ineq2, const ast &chain, ast &normals, + const ast &pos, hash_set &memo, ast &Aproves, ast &Bproves){ + opr o1 = op(ineq1); + opr o2 = op(ineq2); + if(o1 == Not || o1 == Leq || o1 == Lt || o1 == Geq || o1 == Gt || o1 == Plus || o1 == Times){ + int n = num_args(ineq1); + if(o2 != o1 || num_args(ineq2) != n) + throw "bad inequality rewriting"; + for(int i = 0; i < n; i++){ + ast new_pos = add_pos_to_end(pos,i); + get_subterm_normals(arg(ineq1,i), arg(ineq2,i), chain, normals, new_pos, memo, Aproves, Bproves); + } + } + else if(get_term_type(ineq2) == LitMixed){ + if(memo.find(ineq2) == memo.end()){ + memo.insert(ineq2); + ast sub_chain = extract_rewrites(chain,pos); + if(is_true(sub_chain)) + throw "bad inequality rewriting"; + ast new_normal = make_normal_step(ineq2,ineq1,reverse_chain(sub_chain)); + normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); + } + } + else if(!(ineq1 == ineq2)) + throw subterm_normals_failed(); } - else if(get_term_type(ineq2) == LitMixed){ - if(memo.find(ineq2) == memo.end()){ - memo.insert(ineq2); - ast sub_chain = extract_rewrites(chain,pos); - if(is_true(sub_chain)) - throw "bad inequality rewriting"; - ast new_normal = make_normal_step(ineq2,ineq1,reverse_chain(sub_chain)); - normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); - } - } - else if(!(ineq1 == ineq2)) - throw subterm_normals_failed(); - } - ast rewrites_to_normals(const ast &ineq1, const ast &chain, ast &normals, ast &Aproves, ast &Bproves, ast &Aineqs){ - if(is_true(chain)) - return ineq1; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast new_ineq1 = rewrites_to_normals(ineq1, rest, normals, Aproves, Bproves, Aineqs); - ast p1 = rewrite_pos(last); - ast term1; - ast coeff = arith_rewrite_coeff(new_ineq1,p1,term1); - ast res = subst_in_pos(new_ineq1,rewrite_pos(last),rewrite_rhs(last)); - ast rpos; - pos_diff(p1,rewrite_pos(last),rpos); - ast term2 = subst_in_pos(term1,rpos,rewrite_rhs(last)); - if(get_term_type(term1) != LitMixed && get_term_type(term2) != LitMixed){ - if(is_rewrite_side(LitA,last)) - linear_comb(Aineqs,coeff,make(Leq,make_int(rational(0)),make(Sub,term2,term1))); + ast rewrites_to_normals(const ast &ineq1, const ast &chain, ast &normals, ast &Aproves, ast &Bproves, ast &Aineqs){ + if(is_true(chain)) + return ineq1; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast new_ineq1 = rewrites_to_normals(ineq1, rest, normals, Aproves, Bproves, Aineqs); + ast p1 = rewrite_pos(last); + ast term1; + ast coeff = arith_rewrite_coeff(new_ineq1,p1,term1); + ast res = subst_in_pos(new_ineq1,rewrite_pos(last),rewrite_rhs(last)); + ast rpos; + pos_diff(p1,rewrite_pos(last),rpos); + ast term2 = subst_in_pos(term1,rpos,rewrite_rhs(last)); + if(get_term_type(term1) != LitMixed && get_term_type(term2) != LitMixed){ + if(is_rewrite_side(LitA,last)) + linear_comb(Aineqs,coeff,make(Leq,make_int(rational(0)),make(Sub,term2,term1))); + } + else { + ast pf = extract_rewrites(make(concat,mk_true(),last),p1); + ast new_normal = fix_normal(term1,term2,pf); + normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); + } + return res; } - else { - ast pf = extract_rewrites(make(concat,mk_true(),last),p1); - ast new_normal = fix_normal(term1,term2,pf); - normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); - } - return res; - } - ast arith_rewrite_coeff(const ast &ineq, ast &p1, ast &term){ - ast coeff = make_int(rational(1)); - if(p1 == top_pos){ - term = ineq; - return coeff; + ast arith_rewrite_coeff(const ast &ineq, ast &p1, ast &term){ + ast coeff = make_int(rational(1)); + if(p1 == top_pos){ + term = ineq; + return coeff; + } + int argpos = pos_arg(p1); + opr o = op(ineq); + switch(o){ + case Leq: + case Lt: + coeff = argpos ? make_int(rational(1)) : make_int(rational(-1)); + break; + case Geq: + case Gt: + coeff = argpos ? make_int(rational(-1)) : make_int(rational(1)); + break; + case Not: + coeff = make_int(rational(-1)); + case Plus: + break; + case Times: + coeff = arg(ineq,0); + break; + default: + p1 = top_pos; + term = ineq; + return coeff; + } + p1 = arg(p1,1); + ast res = arith_rewrite_coeff(arg(ineq,argpos),p1,term); + p1 = pos_add(argpos,p1); + return coeff == make_int(rational(1)) ? res : make(Times,coeff,res); } - int argpos = pos_arg(p1); - opr o = op(ineq); - switch(o){ - case Leq: - case Lt: - coeff = argpos ? make_int(rational(1)) : make_int(rational(-1)); - break; - case Geq: - case Gt: - coeff = argpos ? make_int(rational(-1)) : make_int(rational(1)); - break; - case Not: - coeff = make_int(rational(-1)); - case Plus: - break; - case Times: - coeff = arg(ineq,0); - break; - default: - p1 = top_pos; - term = ineq; - return coeff; - } - p1 = arg(p1,1); - ast res = arith_rewrite_coeff(arg(ineq,argpos),p1,term); - p1 = pos_add(argpos,p1); - return coeff == make_int(rational(1)) ? res : make(Times,coeff,res); - } - ast rewrite_chain_to_normal_ineq(const ast &chain, ast &Aproves, ast &Bproves){ - ast tail, pref = get_head_chain(chain,tail,false); // pref is x=y, tail is x=y -> x'=y' - ast head = chain_last(pref); - ast ineq1 = rewrite_rhs(head); - ast ineq2 = apply_rewrite_chain(ineq1,tail); - ast nc = mk_true(); - hash_set memo; - ast itp = make(Leq,make_int(rational(0)),make_int(rational(0))); - ast Aproves_save = Aproves, Bproves_save = Bproves; try { - get_subterm_normals(ineq1,ineq2,tail,nc,top_pos,memo, Aproves, Bproves); + ast rewrite_chain_to_normal_ineq(const ast &chain, ast &Aproves, ast &Bproves){ + ast tail, pref = get_head_chain(chain,tail,false); // pref is x=y, tail is x=y -> x'=y' + ast head = chain_last(pref); + ast ineq1 = rewrite_rhs(head); + ast ineq2 = apply_rewrite_chain(ineq1,tail); + ast nc = mk_true(); + hash_set memo; + ast itp = make(Leq,make_int(rational(0)),make_int(rational(0))); + ast Aproves_save = Aproves, Bproves_save = Bproves; try { + get_subterm_normals(ineq1,ineq2,tail,nc,top_pos,memo, Aproves, Bproves); + } + catch (const subterm_normals_failed &){ Aproves = Aproves_save; Bproves = Bproves_save; nc = mk_true(); + rewrites_to_normals(ineq1, tail, nc, Aproves, Bproves, itp); + } + if(is_rewrite_side(LitA,head)){ + linear_comb(itp,make_int("1"),ineq1); // make sure it is normal form + //itp = ineq1; + ast mc = z3_simplify(chain_side_proves(LitB,pref)); + Bproves = my_and(Bproves,mc); + } + else { + ast mc = z3_simplify(chain_side_proves(LitA,pref)); + Aproves = my_and(Aproves,mc); + } + if(is_true(nc)) + return itp; + return make_normal(itp,nc); } - catch (const subterm_normals_failed &){ Aproves = Aproves_save; Bproves = Bproves_save; nc = mk_true(); - rewrites_to_normals(ineq1, tail, nc, Aproves, Bproves, itp); - } - if(is_rewrite_side(LitA,head)){ - linear_comb(itp,make_int("1"),ineq1); // make sure it is normal form - //itp = ineq1; - ast mc = z3_simplify(chain_side_proves(LitB,pref)); - Bproves = my_and(Bproves,mc); - } - else { - ast mc = z3_simplify(chain_side_proves(LitA,pref)); - Aproves = my_and(Aproves,mc); - } - if(is_true(nc)) - return itp; - return make_normal(itp,nc); - } - /* Given a chain rewrite chain deriving not P and a rewrite chain deriving P, return an interpolant. */ - ast contra_chain(const ast &neg_chain, const ast &pos_chain){ - // equality is a special case. we use the derivation of x=y to rewrite not(x=y) to not(y=y) - if(is_equivrel_chain(pos_chain)){ - ast tail, pref = get_head_chain(neg_chain,tail); // pref is not(x=y), tail is not(x,y) -> not(x',y') - ast split[2]; split_chain(down_chain(tail),split); // rewrites from x to x' and y to y' - ast chain = split[0]; - chain = concat_rewrite_chain(chain,pos_chain); // rewrites from x to y' - chain = concat_rewrite_chain(chain,reverse_chain(split[1])); // rewrites from x to y - chain = concat_rewrite_chain(pref,chain_pos_add(0,chain_pos_add(0,chain))); // rewrites t -> not(y=y) - ast head = chain_last(pref); - if(is_rewrite_side(LitB,head)){ - ast condition = chain_conditions(LitB,chain); - return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),condition); - } - else { - ast condition = chain_conditions(LitA,chain); - return my_and(chain_conditions(LitB,chain),my_implies(condition,mk_not(chain_formulas(LitB,chain)))); - } - // ast chain = concat_rewrite_chain(neg_chain,chain_pos_add(0,chain_pos_add(0,pos_chain))); - // return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),chain_conditions(LitB,chain)); + /* Given a chain rewrite chain deriving not P and a rewrite chain deriving P, return an interpolant. */ + ast contra_chain(const ast &neg_chain, const ast &pos_chain){ + // equality is a special case. we use the derivation of x=y to rewrite not(x=y) to not(y=y) + if(is_equivrel_chain(pos_chain)){ + ast tail, pref = get_head_chain(neg_chain,tail); // pref is not(x=y), tail is not(x,y) -> not(x',y') + ast split[2]; split_chain(down_chain(tail),split); // rewrites from x to x' and y to y' + ast chain = split[0]; + chain = concat_rewrite_chain(chain,pos_chain); // rewrites from x to y' + chain = concat_rewrite_chain(chain,reverse_chain(split[1])); // rewrites from x to y + chain = concat_rewrite_chain(pref,chain_pos_add(0,chain_pos_add(0,chain))); // rewrites t -> not(y=y) + ast head = chain_last(pref); + if(is_rewrite_side(LitB,head)){ + ast condition = chain_conditions(LitB,chain); + return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),condition); + } + else { + ast condition = chain_conditions(LitA,chain); + return my_and(chain_conditions(LitB,chain),my_implies(condition,mk_not(chain_formulas(LitB,chain)))); + } + // ast chain = concat_rewrite_chain(neg_chain,chain_pos_add(0,chain_pos_add(0,pos_chain))); + // return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),chain_conditions(LitB,chain)); + } + // otherwise, we reverse the derivation of t = P and use it to rewrite not(P) to not(t) + ast chain = concat_rewrite_chain(neg_chain,chain_pos_add(0,reverse_chain(pos_chain))); + return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),chain_conditions(LitB,chain)); } - // otherwise, we reverse the derivation of t = P and use it to rewrite not(P) to not(t) - ast chain = concat_rewrite_chain(neg_chain,chain_pos_add(0,reverse_chain(pos_chain))); - return my_and(my_implies(chain_conditions(LitA,chain),chain_formulas(LitA,chain)),chain_conditions(LitB,chain)); - } - ast simplify_modpon(const std::vector &args){ - ast Aproves = mk_true(), Bproves = mk_true(); - ast chain = simplify_modpon_fwd(args,Bproves); - ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); - ast interp; - if(is_normal_ineq(Q2)){ // inequalities are special - ast nQ2 = rewrite_chain_to_normal_ineq(chain,Aproves,Bproves); - sum_cond_ineq(nQ2,make_int(rational(1)),Q2,Aproves,Bproves); - interp = normalize(nQ2); + ast simplify_modpon(const std::vector &args){ + ast Aproves = mk_true(), Bproves = mk_true(); + ast chain = simplify_modpon_fwd(args,Bproves); + ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); + ast interp; + if(is_normal_ineq(Q2)){ // inequalities are special + ast nQ2 = rewrite_chain_to_normal_ineq(chain,Aproves,Bproves); + sum_cond_ineq(nQ2,make_int(rational(1)),Q2,Aproves,Bproves); + interp = normalize(nQ2); + } + else + interp = is_negation_chain(chain) ? contra_chain(chain,Q2) : contra_chain(Q2,chain); + return my_and(Aproves,my_implies(Bproves,interp)); } - else - interp = is_negation_chain(chain) ? contra_chain(chain,Q2) : contra_chain(Q2,chain); - return my_and(Aproves,my_implies(Bproves,interp)); - } - ast simplify_exmid(const std::vector &args){ - if(is_equivrel(args[0])){ - ast Aproves = mk_true(), Bproves = mk_true(); - ast chain = destruct_cond_ineq(args[1],Aproves,Bproves); - ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); - ast interp = contra_chain(Q2,chain); - return my_and(Aproves,my_implies(Bproves,interp)); + ast simplify_exmid(const std::vector &args){ + if(is_equivrel(args[0])){ + ast Aproves = mk_true(), Bproves = mk_true(); + ast chain = destruct_cond_ineq(args[1],Aproves,Bproves); + ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); + ast interp = contra_chain(Q2,chain); + return my_and(Aproves,my_implies(Bproves,interp)); + } + throw "bad exmid"; } - throw "bad exmid"; - } - ast simplify_cong(const std::vector &args){ - ast Aproves = mk_true(), Bproves = mk_true(); - ast chain = destruct_cond_ineq(args[0],Aproves,Bproves); - rational pos; - if(is_numeral(args[1],pos)){ - int ipos = pos.get_unsigned(); - chain = chain_pos_add(ipos,chain); - ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); - ast interp = contra_chain(Q2,chain); - return my_and(Aproves,my_implies(Bproves,interp)); + ast simplify_cong(const std::vector &args){ + ast Aproves = mk_true(), Bproves = mk_true(); + ast chain = destruct_cond_ineq(args[0],Aproves,Bproves); + rational pos; + if(is_numeral(args[1],pos)){ + int ipos = pos.get_unsigned(); + chain = chain_pos_add(ipos,chain); + ast Q2 = destruct_cond_ineq(args[2],Aproves,Bproves); + ast interp = contra_chain(Q2,chain); + return my_and(Aproves,my_implies(Bproves,interp)); + } + throw "bad cong"; } - throw "bad cong"; - } - bool is_equivrel(const ast &p){ - opr o = op(p); - return o == Equal || o == Iff; - } + bool is_equivrel(const ast &p){ + opr o = op(p); + return o == Equal || o == Iff; + } - struct rewrites_failed{}; + struct rewrites_failed{}; - /* Suppose p in Lang(B) and A |- p -> q and B |- q -> r. Return a z in Lang(B) such that - B |- p -> z and A |- z -> q. Collect any side conditions in "rules". */ + /* Suppose p in Lang(B) and A |- p -> q and B |- q -> r. Return a z in Lang(B) such that + B |- p -> z and A |- z -> q. Collect any side conditions in "rules". */ - ast commute_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){ - if(q == r) - return p; - if(p == q) - return r; - else { - ast rew = make(Equal,q,r); - if(get_term_type(rew) == LitB){ - apply_common_rewrites(p,p,q,rules); // A rewrites must be over comon vocab - return r; - } + ast commute_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){ + if(q == r) + return p; + if(p == q) + return r; + else { + ast rew = make(Equal,q,r); + if(get_term_type(rew) == LitB){ + apply_common_rewrites(p,p,q,rules); // A rewrites must be over comon vocab + return r; + } + } + if(sym(p) != sym(q) || sym(q) != sym(r)) + throw rewrites_failed(); + int nargs = num_args(p); + if(nargs != num_args(q) || nargs != num_args(r)) + throw rewrites_failed(); + std::vector args; args.resize(nargs); + for(int i = 0; i < nargs; i++) + args[i] = commute_rewrites(arg(p,i),arg(q,i),arg(r,i),rules); + return clone(p,args); } - if(sym(p) != sym(q) || sym(q) != sym(r)) - throw rewrites_failed(); - int nargs = num_args(p); - if(nargs != num_args(q) || nargs != num_args(r)) - throw rewrites_failed(); - std::vector args; args.resize(nargs); - for(int i = 0; i < nargs; i++) - args[i] = commute_rewrites(arg(p,i),arg(q,i),arg(r,i),rules); - return clone(p,args); - } - ast apply_common_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){ - if(q == r) - return p; - ast rew = make(Equal,q,r); - if(term_common(rew)){ - if(p != q) - throw rewrites_failed(); - rules = my_and(rules,rew); - return r; + ast apply_common_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){ + if(q == r) + return p; + ast rew = make(Equal,q,r); + if(term_common(rew)){ + if(p != q) + throw rewrites_failed(); + rules = my_and(rules,rew); + return r; + } + if(sym(p) != sym(q) || sym(q) != sym(r)) + return p; + int nargs = num_args(p); + if(nargs != num_args(q) || nargs != num_args(r)) + return p; + std::vector args; args.resize(nargs); + for(int i = 0; i < nargs; i++) + args[i] = apply_common_rewrites(arg(p,i),arg(q,i),arg(r,i),rules); + return clone(p,args); } - if(sym(p) != sym(q) || sym(q) != sym(r)) - return p; - int nargs = num_args(p); - if(nargs != num_args(q) || nargs != num_args(r)) - return p; - std::vector args; args.resize(nargs); - for(int i = 0; i < nargs; i++) - args[i] = apply_common_rewrites(arg(p,i),arg(q,i),arg(r,i),rules); - return clone(p,args); - } - ast apply_all_rewrites(const ast &p, const ast &q, const ast &r){ - if(q == r) - return p; - if(p == q) - return r; - if(sym(p) != sym(q) || sym(q) != sym(r)) - throw rewrites_failed(); - int nargs = num_args(p); - if(nargs != num_args(q) || nargs != num_args(r)) - throw rewrites_failed(); - std::vector args; args.resize(nargs); - for(int i = 0; i < nargs; i++) - args[i] = apply_all_rewrites(arg(p,i),arg(q,i),arg(r,i)); - return clone(p,args); - } - - ast delta(const ast &x, const ast &y){ - if(op(x) != op(y) || (op(x) == Uninterpreted && sym(x) != sym(y)) || num_args(x) != num_args(y)) - return make(Equal,x,y); - ast res = mk_true(); - int nargs = num_args(x); - for(int i = 0; i < nargs; i++) - res = my_and(res,delta(arg(x,i),arg(y,i))); - return res; - } - - bool diff_rec(LitType t, const ast &p, const ast &q, ast &pd, ast &qd){ - if(p == q) - return false; - if(term_in_vocab(t,p) && term_in_vocab(t,q)){ - pd = p; - qd = q; - return true; + ast apply_all_rewrites(const ast &p, const ast &q, const ast &r){ + if(q == r) + return p; + if(p == q) + return r; + if(sym(p) != sym(q) || sym(q) != sym(r)) + throw rewrites_failed(); + int nargs = num_args(p); + if(nargs != num_args(q) || nargs != num_args(r)) + throw rewrites_failed(); + std::vector args; args.resize(nargs); + for(int i = 0; i < nargs; i++) + args[i] = apply_all_rewrites(arg(p,i),arg(q,i),arg(r,i)); + return clone(p,args); } - else { - if(sym(p) != sym(q)) return false; - int nargs = num_args(p); - if(num_args(q) != nargs) return false; - for(int i = 0; i < nargs; i++) - if(diff_rec(t,arg(p,i),arg(q,i),pd,qd)) - return true; - return false; + + ast delta(const ast &x, const ast &y){ + if(op(x) != op(y) || (op(x) == Uninterpreted && sym(x) != sym(y)) || num_args(x) != num_args(y)) + return make(Equal,x,y); + ast res = mk_true(); + int nargs = num_args(x); + for(int i = 0; i < nargs; i++) + res = my_and(res,delta(arg(x,i),arg(y,i))); + return res; } - } - void diff(LitType t, const ast &p, const ast &q, ast &pd, ast &qd){ - if(!diff_rec(t,p,q,pd,qd)) - throw cannot_simplify(); - } - - bool apply_diff_rec(LitType t, const ast &inp, const ast &p, const ast &q, ast &out){ - if(p == q) - return false; - if(term_in_vocab(t,p) && term_in_vocab(t,q)){ - if(inp != p) - throw cannot_simplify(); - out = q; - return true; + bool diff_rec(LitType t, const ast &p, const ast &q, ast &pd, ast &qd){ + if(p == q) + return false; + if(term_in_vocab(t,p) && term_in_vocab(t,q)){ + pd = p; + qd = q; + return true; + } + else { + if(sym(p) != sym(q)) return false; + int nargs = num_args(p); + if(num_args(q) != nargs) return false; + for(int i = 0; i < nargs; i++) + if(diff_rec(t,arg(p,i),arg(q,i),pd,qd)) + return true; + return false; + } } - else { - int nargs = num_args(p); - if(sym(p) != sym(q)) throw cannot_simplify(); - if(num_args(q) != nargs) throw cannot_simplify(); - if(sym(p) != sym(inp)) throw cannot_simplify(); - if(num_args(inp) != nargs) throw cannot_simplify(); - for(int i = 0; i < nargs; i++) - if(apply_diff_rec(t,arg(inp,i),arg(p,i),arg(q,i),out)) - return true; - return false; + + void diff(LitType t, const ast &p, const ast &q, ast &pd, ast &qd){ + if(!diff_rec(t,p,q,pd,qd)) + throw cannot_simplify(); } - } - ast apply_diff(LitType t, const ast &inp, const ast &p, const ast &q){ - ast out; - if(!apply_diff_rec(t,inp,p,q,out)) - throw cannot_simplify(); - return out; - } - - bool merge_A_rewrites(const ast &A1, const ast &A2, ast &merged) { - if(arg(A1,1) == arg(A2,0)){ - merged = make(op(A1),arg(A1,0),arg(A2,1)); - return true; + bool apply_diff_rec(LitType t, const ast &inp, const ast &p, const ast &q, ast &out){ + if(p == q) + return false; + if(term_in_vocab(t,p) && term_in_vocab(t,q)){ + if(inp != p) + throw cannot_simplify(); + out = q; + return true; + } + else { + int nargs = num_args(p); + if(sym(p) != sym(q)) throw cannot_simplify(); + if(num_args(q) != nargs) throw cannot_simplify(); + if(sym(p) != sym(inp)) throw cannot_simplify(); + if(num_args(inp) != nargs) throw cannot_simplify(); + for(int i = 0; i < nargs; i++) + if(apply_diff_rec(t,arg(inp,i),arg(p,i),arg(q,i),out)) + return true; + return false; + } } - ast diff1l, diff1r, diff2l, diff2r,diffBl,diffBr; - diff(LitA,arg(A1,0),arg(A1,1),diff1l,diff1r); - diff(LitA,arg(A2,0),arg(A2,1),diff2l,diff2r); - diff(LitB,arg(A1,1),arg(A2,0),diffBl,diffBr); - if(!term_common(diff2l) && !term_common(diffBr)){ - ast A1r = apply_diff(LitB,arg(A2,1),arg(A2,0),arg(A1,1)); - merged = make(op(A1),arg(A1,0),A1r); - return true; + + ast apply_diff(LitType t, const ast &inp, const ast &p, const ast &q){ + ast out; + if(!apply_diff_rec(t,inp,p,q,out)) + throw cannot_simplify(); + return out; } - if(!term_common(diff1r) && !term_common(diffBl)){ - ast A2l = apply_diff(LitB,arg(A1,0),arg(A1,1),arg(A2,0)); - merged = make(op(A1),A2l,arg(A2,1)); - return true; + + bool merge_A_rewrites(const ast &A1, const ast &A2, ast &merged) { + if(arg(A1,1) == arg(A2,0)){ + merged = make(op(A1),arg(A1,0),arg(A2,1)); + return true; + } + ast diff1l, diff1r, diff2l, diff2r,diffBl,diffBr; + diff(LitA,arg(A1,0),arg(A1,1),diff1l,diff1r); + diff(LitA,arg(A2,0),arg(A2,1),diff2l,diff2r); + diff(LitB,arg(A1,1),arg(A2,0),diffBl,diffBr); + if(!term_common(diff2l) && !term_common(diffBr)){ + ast A1r = apply_diff(LitB,arg(A2,1),arg(A2,0),arg(A1,1)); + merged = make(op(A1),arg(A1,0),A1r); + return true; + } + if(!term_common(diff1r) && !term_common(diffBl)){ + ast A2l = apply_diff(LitB,arg(A1,0),arg(A1,1),arg(A2,0)); + merged = make(op(A1),A2l,arg(A2,1)); + return true; + } + return false; } - return false; - } - void collect_A_rewrites(const ast &t, std::vector &res){ - if(is_true(t)) - return; - if(sym(t) == concat){ - res.push_back(arg(t,0)); - collect_A_rewrites(arg(t,0),res); - return; + void collect_A_rewrites(const ast &t, std::vector &res){ + if(is_true(t)) + return; + if(sym(t) == concat){ + res.push_back(arg(t,0)); + collect_A_rewrites(arg(t,0),res); + return; + } + res.push_back(t); } - res.push_back(t); - } - ast concat_A_rewrites(const std::vector &rew){ - if(rew.size() == 0) - return mk_true(); - ast res = rew[0]; - for(unsigned i = 1; i < rew.size(); i++) - res = make(concat,res,rew[i]); - return res; - } - - ast merge_concat_rewrites(const ast &A1, const ast &A2){ - std::vector rew; - collect_A_rewrites(A1,rew); - int first = rew.size(), last = first; // range that might need merging - collect_A_rewrites(A2,rew); - while(first > 0 && first < (int)rew.size() && first <= last){ - ast merged; - if(merge_A_rewrites(rew[first-1],rew[first],merged)){ - rew[first] = merged; - first--; - rew.erase(rew.begin()+first); - last--; - if(first >= last) last = first+1; - } - else - first++; + ast concat_A_rewrites(const std::vector &rew){ + if(rew.size() == 0) + return mk_true(); + ast res = rew[0]; + for(unsigned i = 1; i < rew.size(); i++) + res = make(concat,res,rew[i]); + return res; } - return concat_A_rewrites(rew); - } - ast sep_cond(const ast &t, ast &cond){ - if(op(t) == Implies){ - cond = my_and(cond,arg(t,0)); - return arg(t,1); + ast merge_concat_rewrites(const ast &A1, const ast &A2){ + std::vector rew; + collect_A_rewrites(A1,rew); + int first = rew.size(), last = first; // range that might need merging + collect_A_rewrites(A2,rew); + while(first > 0 && first < (int)rew.size() && first <= last){ + ast merged; + if(merge_A_rewrites(rew[first-1],rew[first],merged)){ + rew[first] = merged; + first--; + rew.erase(rew.begin()+first); + last--; + if(first >= last) last = first+1; + } + else + first++; + } + return concat_A_rewrites(rew); } - return t; - } - - /* operations on term positions */ - - /** Finds the difference between two positions. If p1 < p2 (p1 is a - position below p2), returns -1 and sets diff to p2-p1 (the psath - from position p2 to position p1). If p2 < p1 (p2 is a position - below p1), returns 1 and sets diff to p1-p2 (the psath from - position p1 to position p2). If equal, return 0 and set diff to - top_pos. Else (if p1 and p2 are independent) returns 2 and - leaves diff unchanged. */ - - int pos_diff(const ast &p1, const ast &p2, ast &diff){ - if(p1 == top_pos && p2 != top_pos){ - diff = p2; - return 1; + ast sep_cond(const ast &t, ast &cond){ + if(op(t) == Implies){ + cond = my_and(cond,arg(t,0)); + return arg(t,1); + } + return t; } - if(p2 == top_pos && p1 != top_pos){ - diff = p1; - return -1; + + + /* operations on term positions */ + + /** Finds the difference between two positions. If p1 < p2 (p1 is a + position below p2), returns -1 and sets diff to p2-p1 (the psath + from position p2 to position p1). If p2 < p1 (p2 is a position + below p1), returns 1 and sets diff to p1-p2 (the psath from + position p1 to position p2). If equal, return 0 and set diff to + top_pos. Else (if p1 and p2 are independent) returns 2 and + leaves diff unchanged. */ + + int pos_diff(const ast &p1, const ast &p2, ast &diff){ + if(p1 == top_pos && p2 != top_pos){ + diff = p2; + return 1; + } + if(p2 == top_pos && p1 != top_pos){ + diff = p1; + return -1; + } + if(p1 == top_pos && p2 == top_pos){ + diff = p1; + return 0; + } + if(arg(p1,0) == arg(p2,0)) // same argument position, recur + return pos_diff(arg(p1,1),arg(p2,1),diff); + return 2; } - if(p1 == top_pos && p2 == top_pos){ - diff = p1; - return 0; + + /* return the position of pos in the argth argument */ + ast pos_add(int arg, const ast &pos){ + return make(add_pos,make_int(rational(arg)),pos); } - if(arg(p1,0) == arg(p2,0)) // same argument position, recur - return pos_diff(arg(p1,1),arg(p2,1),diff); - return 2; - } - /* return the position of pos in the argth argument */ - ast pos_add(int arg, const ast &pos){ - return make(add_pos,make_int(rational(arg)),pos); - } - - ast add_pos_to_end(const ast &pos, int i){ - if(pos == top_pos) - return pos_add(i,pos); - return make(add_pos,arg(pos,0),add_pos_to_end(arg(pos,1),i)); - } - - /* return the argument number of position, if not top */ - int pos_arg(const ast &pos){ - rational r; - if(is_numeral(arg(pos,0),r)) - return r.get_unsigned(); - throw "bad position!"; - } - - /* substitute y into position pos in x */ - ast subst_in_pos(const ast &x, const ast &pos, const ast &y){ - if(pos == top_pos) - return y; - int p = pos_arg(pos); - int nargs = num_args(x); - if(p >= 0 && p < nargs){ - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = i == p ? subst_in_pos(arg(x,i),arg(pos,1),y) : arg(x,i); - return clone(x,args); + ast add_pos_to_end(const ast &pos, int i){ + if(pos == top_pos) + return pos_add(i,pos); + return make(add_pos,arg(pos,0),add_pos_to_end(arg(pos,1),i)); } - throw "bad term position!"; - } - ast diff_chain(LitType t, const ast &pos, const ast &x, const ast &y, const ast &prefix){ - int nargs = num_args(x); - if(x == y) return prefix; - if(sym(x) == sym(y) && nargs == num_args(y)){ - ast res = prefix; - for(int i = 0; i < nargs; i++) - res = diff_chain(t,pos_add(i,pos),arg(x,i),arg(y,i),res); - return res; + /* return the argument number of position, if not top */ + int pos_arg(const ast &pos){ + rational r; + if(is_numeral(arg(pos,0),r)) + return r.get_unsigned(); + throw "bad position!"; } - return chain_cons(prefix,make_rewrite(t,pos,mk_true(),make_equiv_rel(x,y))); - } - /* operations on rewrites */ - ast make_rewrite(LitType t, const ast &pos, const ast &cond, const ast &equality){ + /* substitute y into position pos in x */ + ast subst_in_pos(const ast &x, const ast &pos, const ast &y){ + if(pos == top_pos) + return y; + int p = pos_arg(pos); + int nargs = num_args(x); + if(p >= 0 && p < nargs){ + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = i == p ? subst_in_pos(arg(x,i),arg(pos,1),y) : arg(x,i); + return clone(x,args); + } + throw "bad term position!"; + } + + ast diff_chain(LitType t, const ast &pos, const ast &x, const ast &y, const ast &prefix){ + int nargs = num_args(x); + if(x == y) return prefix; + if(sym(x) == sym(y) && nargs == num_args(y)){ + ast res = prefix; + for(int i = 0; i < nargs; i++) + res = diff_chain(t,pos_add(i,pos),arg(x,i),arg(y,i),res); + return res; + } + return chain_cons(prefix,make_rewrite(t,pos,mk_true(),make_equiv_rel(x,y))); + } + + /* operations on rewrites */ + ast make_rewrite(LitType t, const ast &pos, const ast &cond, const ast &equality){ #if 0 - if(pos == top_pos && op(equality) == Iff && !is_true(arg(equality,0))) - throw "bad rewrite"; + if(pos == top_pos && op(equality) == Iff && !is_true(arg(equality,0))) + throw "bad rewrite"; #endif - if(!is_equivrel(equality)) - throw "bad rewrite"; - return make(t == LitA ? rewrite_A : rewrite_B, pos, cond, equality); - } + if(!is_equivrel(equality)) + throw "bad rewrite"; + return make(t == LitA ? rewrite_A : rewrite_B, pos, cond, equality); + } - ast rewrite_pos(const ast &rew){ - return arg(rew,0); - } + ast rewrite_pos(const ast &rew){ + return arg(rew,0); + } - ast rewrite_cond(const ast &rew){ - return arg(rew,1); - } + ast rewrite_cond(const ast &rew){ + return arg(rew,1); + } - ast rewrite_equ(const ast &rew){ - return arg(rew,2); - } + ast rewrite_equ(const ast &rew){ + return arg(rew,2); + } - ast rewrite_lhs(const ast &rew){ - return arg(arg(rew,2),0); - } + ast rewrite_lhs(const ast &rew){ + return arg(arg(rew,2),0); + } - ast rewrite_rhs(const ast &rew){ - return arg(arg(rew,2),1); - } + ast rewrite_rhs(const ast &rew){ + return arg(arg(rew,2),1); + } - /* operations on rewrite chains */ + /* operations on rewrite chains */ - ast chain_cons(const ast &chain, const ast &elem){ - return make(concat,chain,elem); - } + ast chain_cons(const ast &chain, const ast &elem){ + return make(concat,chain,elem); + } - ast chain_rest(const ast &chain){ - return arg(chain,0); - } + ast chain_rest(const ast &chain){ + return arg(chain,0); + } - ast chain_last(const ast &chain){ - return arg(chain,1); - } + ast chain_last(const ast &chain){ + return arg(chain,1); + } - ast rewrite_update_rhs(const ast &rew, const ast &pos, const ast &new_rhs, const ast &new_cond){ - ast foo = subst_in_pos(rewrite_rhs(rew),pos,new_rhs); - ast equality = arg(rew,2); - return make(sym(rew),rewrite_pos(rew),my_and(rewrite_cond(rew),new_cond),make(op(equality),arg(equality,0),foo)); - } + ast rewrite_update_rhs(const ast &rew, const ast &pos, const ast &new_rhs, const ast &new_cond){ + ast foo = subst_in_pos(rewrite_rhs(rew),pos,new_rhs); + ast equality = arg(rew,2); + return make(sym(rew),rewrite_pos(rew),my_and(rewrite_cond(rew),new_cond),make(op(equality),arg(equality,0),foo)); + } - ast rewrite_update_lhs(const ast &rew, const ast &pos, const ast &new_lhs, const ast &new_cond){ - ast foo = subst_in_pos(rewrite_lhs(rew),pos,new_lhs); - ast equality = arg(rew,2); - return make(sym(rew),rewrite_pos(rew),my_and(rewrite_cond(rew),new_cond),make(op(equality),foo,arg(equality,1))); - } + ast rewrite_update_lhs(const ast &rew, const ast &pos, const ast &new_lhs, const ast &new_cond){ + ast foo = subst_in_pos(rewrite_lhs(rew),pos,new_lhs); + ast equality = arg(rew,2); + return make(sym(rew),rewrite_pos(rew),my_and(rewrite_cond(rew),new_cond),make(op(equality),foo,arg(equality,1))); + } - bool is_common_rewrite(const ast &rew){ - return term_common(arg(rew,2)); - } + bool is_common_rewrite(const ast &rew){ + return term_common(arg(rew,2)); + } - bool is_right_mover(const ast &rew){ - return term_common(rewrite_lhs(rew)) && !term_common(rewrite_rhs(rew)); - } + bool is_right_mover(const ast &rew){ + return term_common(rewrite_lhs(rew)) && !term_common(rewrite_rhs(rew)); + } - bool is_left_mover(const ast &rew){ - return term_common(rewrite_rhs(rew)) && !term_common(rewrite_lhs(rew)); - } + bool is_left_mover(const ast &rew){ + return term_common(rewrite_rhs(rew)) && !term_common(rewrite_lhs(rew)); + } - bool same_side(const ast &rew1, const ast &rew2){ - return sym(rew1) == sym(rew2); - } + bool same_side(const ast &rew1, const ast &rew2){ + return sym(rew1) == sym(rew2); + } - bool is_rewrite_side(LitType t, const ast &rew){ - if(t == LitA) - return sym(rew) == rewrite_A; - return sym(rew) == rewrite_B; - } + bool is_rewrite_side(LitType t, const ast &rew){ + if(t == LitA) + return sym(rew) == rewrite_A; + return sym(rew) == rewrite_B; + } - LitType rewrite_side(const ast &rew){ - return (sym(rew) == rewrite_A) ? LitA : LitB; - } + LitType rewrite_side(const ast &rew){ + return (sym(rew) == rewrite_A) ? LitA : LitB; + } - ast rewrite_to_formula(const ast &rew){ - return my_implies(arg(rew,1),arg(rew,2)); - } + ast rewrite_to_formula(const ast &rew){ + return my_implies(arg(rew,1),arg(rew,2)); + } - // make rewrite rew conditon on rewrite cond - ast rewrite_conditional(const ast &cond, const ast &rew){ - ast cf = rewrite_to_formula(cond); - return make(sym(rew),arg(rew,0),my_and(arg(rew,1),cf),arg(rew,2)); - } - - ast reverse_rewrite(const ast &rew){ - ast equ = arg(rew,2); - return make(sym(rew),arg(rew,0),arg(rew,1),make(op(equ),arg(equ,1),arg(equ,0))); - } - - ast rewrite_pos_add(int apos, const ast &rew){ - return make(sym(rew),pos_add(apos,arg(rew,0)),arg(rew,1),arg(rew,2)); - } - - ast rewrite_pos_set(const ast &pos, const ast &rew){ - return make(sym(rew),pos,arg(rew,1),arg(rew,2)); - } - - ast rewrite_up(const ast &rew){ - return make(sym(rew),arg(arg(rew,0),1),arg(rew,1),arg(rew,2)); - } - - /** Adds a rewrite to a chain of rewrites, keeping the chain in - normal form. An empty chain is represented by true.*/ - - ast add_rewrite_to_chain(const ast &chain, const ast &rewrite){ - if(is_true(chain)) - return chain_cons(chain,rewrite); - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(same_side(last,rewrite)){ - ast p1 = rewrite_pos(last); - ast p2 = rewrite_pos(rewrite); - ast diff; - switch(pos_diff(p1,p2,diff)){ - case 1: { - ast absorb = rewrite_update_rhs(last,diff,rewrite_rhs(rewrite),rewrite_cond(rewrite)); - return add_rewrite_to_chain(rest,absorb); - } - case 0: - case -1: { - ast absorb = rewrite_update_lhs(rewrite,diff,rewrite_lhs(last),rewrite_cond(last)); - return add_rewrite_to_chain(rest,absorb); - } - default: {// independent case - bool rm = is_right_mover(last); - bool lm = is_left_mover(rewrite); - if((lm && !rm) || (rm && !lm)) - return chain_swap(rest,last,rewrite); - } - } + // make rewrite rew conditon on rewrite cond + ast rewrite_conditional(const ast &cond, const ast &rew){ + ast cf = rewrite_to_formula(cond); + return make(sym(rew),arg(rew,0),my_and(arg(rew,1),cf),arg(rew,2)); } - else { - if(is_left_mover(rewrite)){ - if(is_common_rewrite(last)) - return add_rewrite_to_chain(chain_cons(rest,flip_rewrite(last)),rewrite); - if(!is_left_mover(last)) - return chain_swap(rest,last,rewrite); - } - if(is_right_mover(last)){ - if(is_common_rewrite(rewrite)) - return add_rewrite_to_chain(chain,flip_rewrite(rewrite)); - if(!is_right_mover(rewrite)) - return chain_swap(rest,last,rewrite); - } + + ast reverse_rewrite(const ast &rew){ + ast equ = arg(rew,2); + return make(sym(rew),arg(rew,0),arg(rew,1),make(op(equ),arg(equ,1),arg(equ,0))); } - return chain_cons(chain,rewrite); - } + + ast rewrite_pos_add(int apos, const ast &rew){ + return make(sym(rew),pos_add(apos,arg(rew,0)),arg(rew,1),arg(rew,2)); + } + + ast rewrite_pos_set(const ast &pos, const ast &rew){ + return make(sym(rew),pos,arg(rew,1),arg(rew,2)); + } + + ast rewrite_up(const ast &rew){ + return make(sym(rew),arg(arg(rew,0),1),arg(rew,1),arg(rew,2)); + } + + /** Adds a rewrite to a chain of rewrites, keeping the chain in + normal form. An empty chain is represented by true.*/ + + ast add_rewrite_to_chain(const ast &chain, const ast &rewrite){ + if(is_true(chain)) + return chain_cons(chain,rewrite); + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(same_side(last,rewrite)){ + ast p1 = rewrite_pos(last); + ast p2 = rewrite_pos(rewrite); + ast diff; + switch(pos_diff(p1,p2,diff)){ + case 1: { + ast absorb = rewrite_update_rhs(last,diff,rewrite_rhs(rewrite),rewrite_cond(rewrite)); + return add_rewrite_to_chain(rest,absorb); + } + case 0: + case -1: { + ast absorb = rewrite_update_lhs(rewrite,diff,rewrite_lhs(last),rewrite_cond(last)); + return add_rewrite_to_chain(rest,absorb); + } + default: {// independent case + bool rm = is_right_mover(last); + bool lm = is_left_mover(rewrite); + if((lm && !rm) || (rm && !lm)) + return chain_swap(rest,last,rewrite); + } + } + } + else { + if(is_left_mover(rewrite)){ + if(is_common_rewrite(last)) + return add_rewrite_to_chain(chain_cons(rest,flip_rewrite(last)),rewrite); + if(!is_left_mover(last)) + return chain_swap(rest,last,rewrite); + } + if(is_right_mover(last)){ + if(is_common_rewrite(rewrite)) + return add_rewrite_to_chain(chain,flip_rewrite(rewrite)); + if(!is_right_mover(rewrite)) + return chain_swap(rest,last,rewrite); + } + } + return chain_cons(chain,rewrite); + } - ast chain_swap(const ast &rest, const ast &last, const ast &rewrite){ - return chain_cons(add_rewrite_to_chain(rest,rewrite),last); - } - - ast flip_rewrite(const ast &rew){ - symb flip_sym = (sym(rew) == rewrite_A) ? rewrite_B : rewrite_A; - ast cf = rewrite_to_formula(rew); - return make(flip_sym,arg(rew,0),my_implies(arg(rew,1),cf),arg(rew,2)); - } - - /** concatenates two rewrite chains, keeping result in normal form. */ - - ast concat_rewrite_chain(const ast &chain1, const ast &chain2){ - if(is_true(chain2)) return chain1; - if(is_true(chain1)) return chain2; - ast foo = concat_rewrite_chain(chain1,chain_rest(chain2)); - return add_rewrite_to_chain(foo,chain_last(chain2)); - } - - /** reverse a chain of rewrites */ - - ast reverse_chain_rec(const ast &chain, const ast &prefix){ - if(is_true(chain)) - return prefix; - ast last = reverse_rewrite(chain_last(chain)); - ast rest = chain_rest(chain); - return reverse_chain_rec(rest,chain_cons(prefix,last)); - } - - ast reverse_chain(const ast &chain){ - return reverse_chain_rec(chain,mk_true()); - } - - bool is_equivrel_chain(const ast &chain){ - if(is_true(chain)) - return true; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(is_true(rest)) - return !is_true(rewrite_lhs(last)); - return is_equivrel_chain(rest); - } - - bool is_negation_chain(const ast &chain){ - if(is_true(chain)) - return false; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(is_true(rest)) - return op(rewrite_rhs(last)) == Not; - return is_negation_chain(rest); - } - - ast commute_negation_chain(const ast &chain){ - if(is_true(chain)) - return chain; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(is_true(rest)){ - ast old = rewrite_rhs(last); - if(!(op(old) == Not)) - throw "bad negative equality chain"; - ast equ = arg(old,0); - if(!is_equivrel(equ)) - throw "bad negative equality chain"; - last = rewrite_update_rhs(last,top_pos,make(Not,make(op(equ),arg(equ,1),arg(equ,0))),make(True)); - return chain_cons(rest,last); + ast chain_swap(const ast &rest, const ast &last, const ast &rewrite){ + return chain_cons(add_rewrite_to_chain(rest,rewrite),last); } - ast pos = rewrite_pos(last); - if(pos == top_pos) - throw "bad negative equality chain"; - int idx = pos_arg(pos); - if(idx != 0) - throw "bad negative equality chain"; - pos = arg(pos,1); - if(pos == top_pos){ - ast lhs = rewrite_lhs(last); - ast rhs = rewrite_rhs(last); - if(op(lhs) != Equal || op(rhs) != Equal) - throw "bad negative equality chain"; - last = make_rewrite(rewrite_side(last),rewrite_pos(last),rewrite_cond(last), - make(Iff,make(Equal,arg(lhs,1),arg(lhs,0)),make(Equal,arg(rhs,1),arg(rhs,0)))); - } - else { - idx = pos_arg(pos); - if(idx == 0) - idx = 1; - else if(idx == 1) - idx = 0; - else - throw "bad negative equality chain"; - pos = pos_add(0,pos_add(idx,arg(pos,1))); - last = make_rewrite(rewrite_side(last),pos,rewrite_cond(last),rewrite_equ(last)); - } - return chain_cons(commute_negation_chain(rest),last); - } - // split a rewrite chain into head and tail at last top-level rewrite - ast get_head_chain(const ast &chain, ast &tail, bool is_not = true){ - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast pos = rewrite_pos(last); - if(pos == top_pos || (is_not && arg(pos,1) == top_pos)){ - tail = mk_true(); - return chain; + ast flip_rewrite(const ast &rew){ + symb flip_sym = (sym(rew) == rewrite_A) ? rewrite_B : rewrite_A; + ast cf = rewrite_to_formula(rew); + return make(flip_sym,arg(rew,0),my_implies(arg(rew,1),cf),arg(rew,2)); } - if(is_true(rest)) - throw "bad rewrite chain"; - ast head = get_head_chain(rest,tail,is_not); - tail = chain_cons(tail,last); - return head; - } - bool has_mixed_summands(const ast &e){ - if(op(e) == Plus){ - int nargs = num_args(e); - for(int i = 0; i < nargs; i++) - if(has_mixed_summands(arg(e,i))) - return true; - return false; + /** concatenates two rewrite chains, keeping result in normal form. */ + + ast concat_rewrite_chain(const ast &chain1, const ast &chain2){ + if(is_true(chain2)) return chain1; + if(is_true(chain1)) return chain2; + ast foo = concat_rewrite_chain(chain1,chain_rest(chain2)); + return add_rewrite_to_chain(foo,chain_last(chain2)); + } + + /** reverse a chain of rewrites */ + + ast reverse_chain_rec(const ast &chain, const ast &prefix){ + if(is_true(chain)) + return prefix; + ast last = reverse_rewrite(chain_last(chain)); + ast rest = chain_rest(chain); + return reverse_chain_rec(rest,chain_cons(prefix,last)); + } + + ast reverse_chain(const ast &chain){ + return reverse_chain_rec(chain,mk_true()); + } + + bool is_equivrel_chain(const ast &chain){ + if(is_true(chain)) + return true; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(is_true(rest)) + return !is_true(rewrite_lhs(last)); + return is_equivrel_chain(rest); + } + + bool is_negation_chain(const ast &chain){ + if(is_true(chain)) + return false; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(is_true(rest)) + return op(rewrite_rhs(last)) == Not; + return is_negation_chain(rest); + } + + ast commute_negation_chain(const ast &chain){ + if(is_true(chain)) + return chain; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(is_true(rest)){ + ast old = rewrite_rhs(last); + if(!(op(old) == Not)) + throw "bad negative equality chain"; + ast equ = arg(old,0); + if(!is_equivrel(equ)) + throw "bad negative equality chain"; + last = rewrite_update_rhs(last,top_pos,make(Not,make(op(equ),arg(equ,1),arg(equ,0))),make(True)); + return chain_cons(rest,last); + } + ast pos = rewrite_pos(last); + if(pos == top_pos) + throw "bad negative equality chain"; + int idx = pos_arg(pos); + if(idx != 0) + throw "bad negative equality chain"; + pos = arg(pos,1); + if(pos == top_pos){ + ast lhs = rewrite_lhs(last); + ast rhs = rewrite_rhs(last); + if(op(lhs) != Equal || op(rhs) != Equal) + throw "bad negative equality chain"; + last = make_rewrite(rewrite_side(last),rewrite_pos(last),rewrite_cond(last), + make(Iff,make(Equal,arg(lhs,1),arg(lhs,0)),make(Equal,arg(rhs,1),arg(rhs,0)))); + } + else { + idx = pos_arg(pos); + if(idx == 0) + idx = 1; + else if(idx == 1) + idx = 0; + else + throw "bad negative equality chain"; + pos = pos_add(0,pos_add(idx,arg(pos,1))); + last = make_rewrite(rewrite_side(last),pos,rewrite_cond(last),rewrite_equ(last)); + } + return chain_cons(commute_negation_chain(rest),last); + } + + // split a rewrite chain into head and tail at last top-level rewrite + ast get_head_chain(const ast &chain, ast &tail, bool is_not = true){ + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast pos = rewrite_pos(last); + if(pos == top_pos || (is_not && arg(pos,1) == top_pos)){ + tail = mk_true(); + return chain; + } + if(is_true(rest)) + throw "bad rewrite chain"; + ast head = get_head_chain(rest,tail,is_not); + tail = chain_cons(tail,last); + return head; + } + + bool has_mixed_summands(const ast &e){ + if(op(e) == Plus){ + int nargs = num_args(e); + for(int i = 0; i < nargs; i++) + if(has_mixed_summands(arg(e,i))) + return true; + return false; + } + return get_term_type(e) == LitMixed; } - return get_term_type(e) == LitMixed; - } - // split a rewrite chain into head and tail at last sum with no mixed sumands - ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){ - if(is_true(chain) || !has_mixed_summands(rhs)){ - mid = rhs; - tail = mk_true(); - return chain; + // split a rewrite chain into head and tail at last sum with no mixed sumands + ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){ + if(is_true(chain) || !has_mixed_summands(rhs)){ + mid = rhs; + tail = mk_true(); + return chain; + } + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast mm = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); + ast res = get_right_movers(rest,mm,tail,mid); + tail = chain_cons(tail,last); + return res; } - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast mm = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); - ast res = get_right_movers(rest,mm,tail,mid); - tail = chain_cons(tail,last); - return res; - } - // split a rewrite chain into head and tail at first sum with no mixed sumands - ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){ - if(is_true(chain)){ - mid = lhs; - if(!has_mixed_summands(lhs)){ - tail = mk_true(); - return chain; - } - return ast(); + // split a rewrite chain into head and tail at first sum with no mixed sumands + ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){ + if(is_true(chain)){ + mid = lhs; + if(!has_mixed_summands(lhs)){ + tail = mk_true(); + return chain; + } + return ast(); + } + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast res = get_left_movers(rest,lhs,tail,mid); + if(res.null()){ + mid = subst_in_pos(mid,rewrite_pos(last),rewrite_rhs(last)); + if(get_term_type(mid) != LitMixed){ + tail = mk_true(); + return chain; + } + return ast(); + } + tail = chain_cons(tail,last); + return res; } - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast res = get_left_movers(rest,lhs,tail,mid); - if(res.null()){ - mid = subst_in_pos(mid,rewrite_pos(last),rewrite_rhs(last)); - if(get_term_type(mid) != LitMixed){ - tail = mk_true(); - return chain; - } - return ast(); - } - tail = chain_cons(tail,last); - return res; - } - struct cannot_split {}; + struct cannot_split {}; - /** Split a chain of rewrites two chains, operating on positions 0 and 1. - Fail if any rewrite in the chain operates on top position. */ - void split_chain_rec(const ast &chain, ast *res){ - if(is_true(chain)) - return; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - split_chain_rec(rest,res); - ast pos = rewrite_pos(last); - if(pos == top_pos){ - if(rewrite_lhs(last) == rewrite_rhs(last)) - return; // skip if it's a noop - throw cannot_split(); + /** Split a chain of rewrites two chains, operating on positions 0 and 1. + Fail if any rewrite in the chain operates on top position. */ + void split_chain_rec(const ast &chain, ast *res){ + if(is_true(chain)) + return; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + split_chain_rec(rest,res); + ast pos = rewrite_pos(last); + if(pos == top_pos){ + if(rewrite_lhs(last) == rewrite_rhs(last)) + return; // skip if it's a noop + throw cannot_split(); + } + int arg = pos_arg(pos); + if(arg<0 || arg > 1) + throw cannot_split(); + res[arg] = chain_cons(res[arg],rewrite_up(last)); } - int arg = pos_arg(pos); - if(arg<0 || arg > 1) - throw cannot_split(); - res[arg] = chain_cons(res[arg],rewrite_up(last)); - } - void split_chain(const ast &chain, ast *res){ - res[0] = res[1] = mk_true(); - split_chain_rec(chain,res); - } - - ast extract_rewrites(const ast &chain, const ast &pos){ - if(is_true(chain)) - return chain; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast new_rest = extract_rewrites(rest,pos); - ast p1 = rewrite_pos(last); - ast diff; - switch(pos_diff(p1,pos,diff)){ - case -1: { - ast new_last = rewrite_pos_set(diff, last); - return chain_cons(new_rest,new_last); + void split_chain(const ast &chain, ast *res){ + res[0] = res[1] = mk_true(); + split_chain_rec(chain,res); } - case 1: - if(rewrite_lhs(last) != rewrite_rhs(last)) - throw "bad rewrite chain"; - break; - default:; + + ast extract_rewrites(const ast &chain, const ast &pos){ + if(is_true(chain)) + return chain; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast new_rest = extract_rewrites(rest,pos); + ast p1 = rewrite_pos(last); + ast diff; + switch(pos_diff(p1,pos,diff)){ + case -1: { + ast new_last = rewrite_pos_set(diff, last); + return chain_cons(new_rest,new_last); + } + case 1: + if(rewrite_lhs(last) != rewrite_rhs(last)) + throw "bad rewrite chain"; + break; + default:; + } + return new_rest; } - return new_rest; - } - ast down_chain(const ast &chain){ - ast split[2]; - split_chain(chain,split); - return split[0]; - } - - ast chain_conditions(LitType t, const ast &chain){ - if(is_true(chain)) - return mk_true(); - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast cond = chain_conditions(t,rest); - if(is_rewrite_side(t,last)) - cond = my_and(cond,rewrite_cond(last)); - return cond; - } - - ast chain_formulas(LitType t, const ast &chain){ - if(is_true(chain)) - return mk_true(); - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast cond = chain_formulas(t,rest); - if(is_rewrite_side(t,last)) - cond = my_and(cond,rewrite_equ(last)); - return cond; - } - - - bool rewrites_from_to(const ast &chain, const ast &lhs, const ast &rhs){ - if(is_true(chain)) - return lhs == rhs; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); - return rewrites_from_to(rest,lhs,mid); - } - - struct bad_ineq_inference {}; - - ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){ - if(is_true(chain)){ - if(lhs != rhs) - throw bad_ineq_inference(); - return make(Leq,make_int(rational(0)),make_int(rational(0))); + ast down_chain(const ast &chain){ + ast split[2]; + split_chain(chain,split); + return split[0]; } - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); - ast cond = chain_ineqs(comp_op,t,rest,lhs,mid); - if(is_rewrite_side(t,last)){ - ast diff; - if(comp_op == Leq) diff = make(Sub,rhs,mid); - else diff = make(Sub,mid,rhs); - ast foo = make(Leq,make_int("0"),z3_simplify(diff)); - if(is_true(cond)) - cond = foo; - else { - linear_comb(cond,make_int(rational(1)),foo); - cond = simplify_ineq(cond); - } + + ast chain_conditions(LitType t, const ast &chain){ + if(is_true(chain)) + return mk_true(); + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast cond = chain_conditions(t,rest); + if(is_rewrite_side(t,last)) + cond = my_and(cond,rewrite_cond(last)); + return cond; } - return cond; - } - ast ineq_to_lhs(const ast &ineq){ - ast s = make(Leq,make_int(rational(0)),make_int(rational(0))); - linear_comb(s,make_int(rational(1)),ineq); - return simplify_ineq(s); - } - - void eq_from_ineq(const ast &ineq, ast &lhs, ast &rhs){ - // ast s = ineq_to_lhs(ineq); - // ast srhs = arg(s,1); - ast srhs = arg(ineq,0); - if(op(srhs) == Plus && num_args(srhs) == 2 && arg(ineq,1) == make_int(rational(0))){ - lhs = arg(srhs,0); - rhs = arg(srhs,1); - // if(op(lhs) == Times) - // std::swap(lhs,rhs); - if(op(rhs) == Times){ - rhs = arg(rhs,1); - // if(op(ineq) == Leq) - // std::swap(lhs,rhs); - return; - } + ast chain_formulas(LitType t, const ast &chain){ + if(is_true(chain)) + return mk_true(); + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast cond = chain_formulas(t,rest); + if(is_rewrite_side(t,last)) + cond = my_and(cond,rewrite_equ(last)); + return cond; } - if(op(ineq) == Leq || op(ineq) == Geq){ - lhs = srhs; - rhs = arg(ineq,1); - return; + + + bool rewrites_from_to(const ast &chain, const ast &lhs, const ast &rhs){ + if(is_true(chain)) + return lhs == rhs; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); + return rewrites_from_to(rest,lhs,mid); } - throw "bad ineq"; - } - ast chain_pos_add(int arg, const ast &chain){ - if(is_true(chain)) - return mk_true(); - ast last = rewrite_pos_add(arg,chain_last(chain)); - ast rest = chain_pos_add(arg,chain_rest(chain)); - return chain_cons(rest,last); - } + struct bad_ineq_inference {}; - ast apply_rewrite_chain(const ast &t, const ast &chain){ - if(is_true(chain)) - return t; - ast last = chain_last(chain); - ast rest = chain_rest(chain); - ast mid = apply_rewrite_chain(t,rest); - ast res = subst_in_pos(mid,rewrite_pos(last),rewrite_rhs(last)); - return res; - } - - ast drop_rewrites(LitType t, const ast &chain, ast &remainder){ - if(!is_true(chain)){ - ast last = chain_last(chain); - ast rest = chain_rest(chain); - if(is_rewrite_side(t,last)){ - ast res = drop_rewrites(t,rest,remainder); - remainder = chain_cons(remainder,last); - return res; - } + ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){ + if(is_true(chain)){ + if(lhs != rhs) + throw bad_ineq_inference(); + return make(Leq,make_int(rational(0)),make_int(rational(0))); + } + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last)); + ast cond = chain_ineqs(comp_op,t,rest,lhs,mid); + if(is_rewrite_side(t,last)){ + ast diff; + if(comp_op == Leq) diff = make(Sub,rhs,mid); + else diff = make(Sub,mid,rhs); + ast foo = make(Leq,make_int("0"),z3_simplify(diff)); + if(is_true(cond)) + cond = foo; + else { + linear_comb(cond,make_int(rational(1)),foo); + cond = simplify_ineq(cond); + } + } + return cond; } - remainder = mk_true(); - return chain; - } - // Normalization chains + ast ineq_to_lhs(const ast &ineq){ + ast s = make(Leq,make_int(rational(0)),make_int(rational(0))); + linear_comb(s,make_int(rational(1)),ineq); + return simplify_ineq(s); + } - ast cons_normal(const ast &first, const ast &rest){ - return make(normal_chain,first,rest); - } + void eq_from_ineq(const ast &ineq, ast &lhs, ast &rhs){ + // ast s = ineq_to_lhs(ineq); + // ast srhs = arg(s,1); + ast srhs = arg(ineq,0); + if(op(srhs) == Plus && num_args(srhs) == 2 && arg(ineq,1) == make_int(rational(0))){ + lhs = arg(srhs,0); + rhs = arg(srhs,1); + // if(op(lhs) == Times) + // std::swap(lhs,rhs); + if(op(rhs) == Times){ + rhs = arg(rhs,1); + // if(op(ineq) == Leq) + // std::swap(lhs,rhs); + return; + } + } + if(op(ineq) == Leq || op(ineq) == Geq){ + lhs = srhs; + rhs = arg(ineq,1); + return; + } + throw "bad ineq"; + } + + ast chain_pos_add(int arg, const ast &chain){ + if(is_true(chain)) + return mk_true(); + ast last = rewrite_pos_add(arg,chain_last(chain)); + ast rest = chain_pos_add(arg,chain_rest(chain)); + return chain_cons(rest,last); + } + + ast apply_rewrite_chain(const ast &t, const ast &chain){ + if(is_true(chain)) + return t; + ast last = chain_last(chain); + ast rest = chain_rest(chain); + ast mid = apply_rewrite_chain(t,rest); + ast res = subst_in_pos(mid,rewrite_pos(last),rewrite_rhs(last)); + return res; + } + + ast drop_rewrites(LitType t, const ast &chain, ast &remainder){ + if(!is_true(chain)){ + ast last = chain_last(chain); + ast rest = chain_rest(chain); + if(is_rewrite_side(t,last)){ + ast res = drop_rewrites(t,rest,remainder); + remainder = chain_cons(remainder,last); + return res; + } + } + remainder = mk_true(); + return chain; + } + + // Normalization chains + + ast cons_normal(const ast &first, const ast &rest){ + return make(normal_chain,first,rest); + } - ast normal_first(const ast &t){ - return arg(t,0); - } - - ast normal_rest(const ast &t){ - return arg(t,1); - } - - ast normal_lhs(const ast &t){ - return arg(arg(t,0),0); - } - - ast normal_rhs(const ast &t){ - return arg(arg(t,0),1); - } - - ast normal_proof(const ast &t){ - return arg(t,1); - } - - ast make_normal_step(const ast &lhs, const ast &rhs, const ast &proof){ - return make(normal_step,make_equiv(lhs,rhs),proof); - } - - ast make_normal(const ast &ineq, const ast &nrml){ - if(!is_ineq(ineq)) - throw "what?"; - return make(normal,ineq,nrml); - } - - ast fix_normal(const ast &lhs, const ast &rhs, const ast &proof){ - LitType lhst = get_term_type(lhs); - LitType rhst = get_term_type(rhs); - if(lhst == LitMixed && (rhst != LitMixed || ast_id(lhs) < ast_id(rhs))) - return make_normal_step(lhs,rhs,proof); - if(rhst == LitMixed && (lhst != LitMixed || ast_id(rhs) < ast_id(lhs))) - return make_normal_step(rhs,lhs,reverse_chain(proof)); - throw "help!"; - } - - ast chain_side_proves(LitType side, const ast &chain){ - LitType other_side = side == LitA ? LitB : LitA; - return my_and(chain_conditions(other_side,chain),my_implies(chain_conditions(side,chain),chain_formulas(side,chain))); - } - - // Merge two normalization chains - ast merge_normal_chains_rec(const ast &chain1, const ast &chain2, hash_map &trans, ast &Aproves, ast &Bproves){ - if(is_true(chain1)) - return chain2; - if(is_true(chain2)) - return chain1; - ast f1 = normal_first(chain1); - ast f2 = normal_first(chain2); - ast lhs1 = normal_lhs(f1); - ast lhs2 = normal_lhs(f2); - int id1 = ast_id(lhs1); - int id2 = ast_id(lhs2); - if(id1 < id2) - return cons_normal(f1,merge_normal_chains_rec(normal_rest(chain1),chain2,trans,Aproves,Bproves)); - if(id2 < id1) - return cons_normal(f2,merge_normal_chains_rec(chain1,normal_rest(chain2),trans,Aproves,Bproves)); - ast rhs1 = normal_rhs(f1); - ast rhs2 = normal_rhs(f2); - LitType t1 = get_term_type(rhs1); - LitType t2 = get_term_type(rhs2); - int tid1 = ast_id(rhs1); - int tid2 = ast_id(rhs2); - ast pf1 = normal_proof(f1); - ast pf2 = normal_proof(f2); - ast new_normal; - if(t1 == LitMixed && (t2 != LitMixed || tid2 > tid1)){ - ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); - new_normal = f2; - trans[rhs1] = make_normal_step(rhs1,rhs2,new_proof); + ast normal_first(const ast &t){ + return arg(t,0); } - else if(t2 == LitMixed && (t1 != LitMixed || tid1 > tid2)) - return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves); - else if(t1 == LitA && t2 == LitB){ - ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); - ast Bproof, Aproof = drop_rewrites(LitB,new_proof,Bproof); - ast mcA = chain_side_proves(LitB,Aproof); - Bproves = my_and(Bproves,mcA); - ast mcB = chain_side_proves(LitA,Bproof); - Aproves = my_and(Aproves,mcB); - ast rep = apply_rewrite_chain(rhs1,Aproof); - new_proof = concat_rewrite_chain(pf1,Aproof); - new_normal = make_normal_step(lhs1,rep,new_proof); - ast A_normal = make_normal_step(rhs1,rep,Aproof); - ast res = cons_normal(new_normal,merge_normal_chains_rec(normal_rest(chain1),normal_rest(chain2),trans,Aproves,Bproves)); - res = merge_normal_chains_rec(res,cons_normal(A_normal,make(True)),trans,Aproves,Bproves); - return res; - } - else if(t1 == LitB && t2 == LitA) - return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves); - else if(t1 == LitA) { - ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); - ast mc = chain_side_proves(LitB,new_proof); - Bproves = my_and(Bproves,mc); - new_normal = f1; // choice is arbitrary - } - else { /* t1 = t2 = LitB */ - ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); - ast mc = chain_side_proves(LitA,new_proof); - Aproves = my_and(Aproves,mc); - new_normal = f1; // choice is arbitrary - } - return cons_normal(new_normal,merge_normal_chains_rec(normal_rest(chain1),normal_rest(chain2),trans,Aproves,Bproves)); - } - ast trans_normal_chain(const ast &chain, hash_map &trans){ - if(is_true(chain)) - return chain; - ast f = normal_first(chain); - ast r = normal_rest(chain); - r = trans_normal_chain(r,trans); - ast rhs = normal_rhs(f); - hash_map::iterator it = trans.find(rhs); - ast new_normal; - if(it != trans.end() && get_term_type(normal_lhs(f)) == LitMixed){ - const ast &f2 = it->second; - ast pf = concat_rewrite_chain(normal_proof(f),normal_proof(f2)); - new_normal = make_normal_step(normal_lhs(f),normal_rhs(f2),pf); + ast normal_rest(const ast &t){ + return arg(t,1); } - else - new_normal = f; - if(get_term_type(normal_lhs(f)) == LitMixed) - trans[normal_lhs(f)] = new_normal; - return cons_normal(new_normal,r); - } - ast merge_normal_chains(const ast &chain1, const ast &chain2, ast &Aproves, ast &Bproves){ - hash_map trans; - ast res = merge_normal_chains_rec(chain1,chain2,trans,Aproves,Bproves); - res = trans_normal_chain(res,trans); - return res; - } + ast normal_lhs(const ast &t){ + return arg(arg(t,0),0); + } + + ast normal_rhs(const ast &t){ + return arg(arg(t,0),1); + } + + ast normal_proof(const ast &t){ + return arg(t,1); + } + + ast make_normal_step(const ast &lhs, const ast &rhs, const ast &proof){ + return make(normal_step,make_equiv(lhs,rhs),proof); + } + + ast make_normal(const ast &ineq, const ast &nrml){ + if(!is_ineq(ineq)) + throw "what?"; + return make(normal,ineq,nrml); + } + + ast fix_normal(const ast &lhs, const ast &rhs, const ast &proof){ + LitType lhst = get_term_type(lhs); + LitType rhst = get_term_type(rhs); + if(lhst == LitMixed && (rhst != LitMixed || ast_id(lhs) < ast_id(rhs))) + return make_normal_step(lhs,rhs,proof); + if(rhst == LitMixed && (lhst != LitMixed || ast_id(rhs) < ast_id(lhs))) + return make_normal_step(rhs,lhs,reverse_chain(proof)); + throw "help!"; + } + + ast chain_side_proves(LitType side, const ast &chain){ + LitType other_side = side == LitA ? LitB : LitA; + return my_and(chain_conditions(other_side,chain),my_implies(chain_conditions(side,chain),chain_formulas(side,chain))); + } + + // Merge two normalization chains + ast merge_normal_chains_rec(const ast &chain1, const ast &chain2, hash_map &trans, ast &Aproves, ast &Bproves){ + if(is_true(chain1)) + return chain2; + if(is_true(chain2)) + return chain1; + ast f1 = normal_first(chain1); + ast f2 = normal_first(chain2); + ast lhs1 = normal_lhs(f1); + ast lhs2 = normal_lhs(f2); + int id1 = ast_id(lhs1); + int id2 = ast_id(lhs2); + if(id1 < id2) + return cons_normal(f1,merge_normal_chains_rec(normal_rest(chain1),chain2,trans,Aproves,Bproves)); + if(id2 < id1) + return cons_normal(f2,merge_normal_chains_rec(chain1,normal_rest(chain2),trans,Aproves,Bproves)); + ast rhs1 = normal_rhs(f1); + ast rhs2 = normal_rhs(f2); + LitType t1 = get_term_type(rhs1); + LitType t2 = get_term_type(rhs2); + int tid1 = ast_id(rhs1); + int tid2 = ast_id(rhs2); + ast pf1 = normal_proof(f1); + ast pf2 = normal_proof(f2); + ast new_normal; + if(t1 == LitMixed && (t2 != LitMixed || tid2 > tid1)){ + ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); + new_normal = f2; + trans[rhs1] = make_normal_step(rhs1,rhs2,new_proof); + } + else if(t2 == LitMixed && (t1 != LitMixed || tid1 > tid2)) + return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves); + else if(t1 == LitA && t2 == LitB){ + ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); + ast Bproof, Aproof = drop_rewrites(LitB,new_proof,Bproof); + ast mcA = chain_side_proves(LitB,Aproof); + Bproves = my_and(Bproves,mcA); + ast mcB = chain_side_proves(LitA,Bproof); + Aproves = my_and(Aproves,mcB); + ast rep = apply_rewrite_chain(rhs1,Aproof); + new_proof = concat_rewrite_chain(pf1,Aproof); + new_normal = make_normal_step(lhs1,rep,new_proof); + ast A_normal = make_normal_step(rhs1,rep,Aproof); + ast res = cons_normal(new_normal,merge_normal_chains_rec(normal_rest(chain1),normal_rest(chain2),trans,Aproves,Bproves)); + res = merge_normal_chains_rec(res,cons_normal(A_normal,make(True)),trans,Aproves,Bproves); + return res; + } + else if(t1 == LitB && t2 == LitA) + return merge_normal_chains_rec(chain2,chain1,trans,Aproves,Bproves); + else if(t1 == LitA) { + ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); + ast mc = chain_side_proves(LitB,new_proof); + Bproves = my_and(Bproves,mc); + new_normal = f1; // choice is arbitrary + } + else { /* t1 = t2 = LitB */ + ast new_proof = concat_rewrite_chain(reverse_chain(pf1),pf2); + ast mc = chain_side_proves(LitA,new_proof); + Aproves = my_and(Aproves,mc); + new_normal = f1; // choice is arbitrary + } + return cons_normal(new_normal,merge_normal_chains_rec(normal_rest(chain1),normal_rest(chain2),trans,Aproves,Bproves)); + } + + ast trans_normal_chain(const ast &chain, hash_map &trans){ + if(is_true(chain)) + return chain; + ast f = normal_first(chain); + ast r = normal_rest(chain); + r = trans_normal_chain(r,trans); + ast rhs = normal_rhs(f); + hash_map::iterator it = trans.find(rhs); + ast new_normal; + if(it != trans.end() && get_term_type(normal_lhs(f)) == LitMixed){ + const ast &f2 = it->second; + ast pf = concat_rewrite_chain(normal_proof(f),normal_proof(f2)); + new_normal = make_normal_step(normal_lhs(f),normal_rhs(f2),pf); + } + else + new_normal = f; + if(get_term_type(normal_lhs(f)) == LitMixed) + trans[normal_lhs(f)] = new_normal; + return cons_normal(new_normal,r); + } + + ast merge_normal_chains(const ast &chain1, const ast &chain2, ast &Aproves, ast &Bproves){ + hash_map trans; + ast res = merge_normal_chains_rec(chain1,chain2,trans,Aproves,Bproves); + res = trans_normal_chain(res,trans); + return res; + } - bool destruct_cond_ineq(ast t, ast &Aproves, ast &Bproves, ast&ineq){ - if(op(t) == And){ - Aproves = arg(t,0); - t = arg(t,1); + bool destruct_cond_ineq(ast t, ast &Aproves, ast &Bproves, ast&ineq){ + if(op(t) == And){ + Aproves = arg(t,0); + t = arg(t,1); + } + else + Aproves = mk_true(); + if(op(t) == Implies){ + Bproves = arg(t,0); + t = arg(t,1); + } + else + Bproves = mk_true(); + if(is_normal_ineq(t)){ + ineq = t; + return true; + } + return false; } - else - Aproves = mk_true(); - if(op(t) == Implies){ - Bproves = arg(t,0); - t = arg(t,1); - } - else - Bproves = mk_true(); - if(is_normal_ineq(t)){ - ineq = t; - return true; - } - return false; - } - ast cons_cond_ineq(const ast &Aproves, const ast &Bproves, const ast &ineq){ - return my_and(Aproves,my_implies(Bproves,ineq)); - } - - ast normalize(const ast &ct){ - ast Aproves,Bproves,t; - if(!destruct_cond_ineq(ct,Aproves,Bproves,t)) - return ct; - if(sym(t) != normal) - return ct; - ast chain = arg(t,1); - hash_map map; - for(ast c = chain; !is_true(c); c = normal_rest(c)){ - ast first = normal_first(c); - ast lhs = normal_lhs(first); - ast rhs = normal_rhs(first); - map[lhs] = rhs; + ast cons_cond_ineq(const ast &Aproves, const ast &Bproves, const ast &ineq){ + return my_and(Aproves,my_implies(Bproves,ineq)); + } + + ast normalize(const ast &ct){ + ast Aproves,Bproves,t; + if(!destruct_cond_ineq(ct,Aproves,Bproves,t)) + return ct; + if(sym(t) != normal) + return ct; + ast chain = arg(t,1); + hash_map map; + for(ast c = chain; !is_true(c); c = normal_rest(c)){ + ast first = normal_first(c); + ast lhs = normal_lhs(first); + ast rhs = normal_rhs(first); + map[lhs] = rhs; + } + ast res = subst(map,arg(t,0)); + return cons_cond_ineq(Aproves,Bproves,res); } - ast res = subst(map,arg(t,0)); - return cons_cond_ineq(Aproves,Bproves,res); - } - /** Make an assumption node. The given clause is assumed in the given frame. */ - virtual node make_assumption(int frame, const std::vector &assumption){ - if(!weak){ - if(pv->in_range(frame,rng)){ - std::vector itp_clause; - for(unsigned i = 0; i < assumption.size(); i++) - if(get_term_type(assumption[i]) != LitA) - itp_clause.push_back(assumption[i]); - ast res = my_or(itp_clause); - return res; - } - else { - return mk_true(); - } + /** Make an assumption node. The given clause is assumed in the given frame. */ + virtual node make_assumption(int frame, const std::vector &assumption){ + if(!weak){ + if(pv->in_range(frame,rng)){ + std::vector itp_clause; + for(unsigned i = 0; i < assumption.size(); i++) + if(get_term_type(assumption[i]) != LitA) + itp_clause.push_back(assumption[i]); + ast res = my_or(itp_clause); + return res; + } + else { + return mk_true(); + } + } + else { + if(pv->in_range(frame,rng)){ + return mk_false(); + } + else { + std::vector itp_clause; + for(unsigned i = 0; i < assumption.size(); i++) + if(get_term_type(assumption[i]) != LitB) + itp_clause.push_back(assumption[i]); + ast res = my_or(itp_clause); + return mk_not(res); + } + } } - else { - if(pv->in_range(frame,rng)){ - return mk_false(); - } - else { - std::vector itp_clause; - for(unsigned i = 0; i < assumption.size(); i++) - if(get_term_type(assumption[i]) != LitB) - itp_clause.push_back(assumption[i]); - ast res = my_or(itp_clause); - return mk_not(res); - } - } - } - ast make_local_rewrite(LitType t, const ast &p){ - ast rew = is_equivrel(p) ? p : make(Iff,mk_true(),p); + ast make_local_rewrite(LitType t, const ast &p){ + ast rew = is_equivrel(p) ? p : make(Iff,mk_true(),p); #if 0 - if(op(rew) == Iff && !is_true(arg(rew,0))) - return diff_chain(t,top_pos,arg(rew,0),arg(rew,1), mk_true()); + if(op(rew) == Iff && !is_true(arg(rew,0))) + return diff_chain(t,top_pos,arg(rew,0),arg(rew,1), mk_true()); #endif - return chain_cons(mk_true(),make_rewrite(t, top_pos, mk_true(), rew)); - } - - ast triv_interp(const symb &rule, const std::vector &premises, int mask_in){ - std::vector ps; ps.resize(premises.size()); - std::vector conjs; - int mask = 0; - for(unsigned i = 0; i < ps.size(); i++){ - ast p = premises[i]; - LitType t = get_term_type(p); - switch(t){ - case LitA: - case LitB: - ps[i] = make_local_rewrite(t,p); - break; - default: - ps[i] = get_placeholder(p); // can only prove consequent! - if(mask_in & (1 << i)) - mask |= (1 << conjs.size()); - conjs.push_back(p); - } + return chain_cons(mk_true(),make_rewrite(t, top_pos, mk_true(), rew)); } - ast ref = make(rule,ps); - ast res = make_contra_node(ref,conjs,mask); - return res; - } - ast triv_interp(const symb &rule, const ast &p0, const ast &p1, const ast &p2, int mask){ - std::vector ps; ps.resize(3); - ps[0] = p0; - ps[1] = p1; - ps[2] = p2; - return triv_interp(rule,ps,mask); - } + ast triv_interp(const symb &rule, const std::vector &premises, int mask_in){ + std::vector ps; ps.resize(premises.size()); + std::vector conjs; + int mask = 0; + for(unsigned i = 0; i < ps.size(); i++){ + ast p = premises[i]; + LitType t = get_term_type(p); + switch(t){ + case LitA: + case LitB: + ps[i] = make_local_rewrite(t,p); + break; + default: + ps[i] = get_placeholder(p); // can only prove consequent! + if(mask_in & (1 << i)) + mask |= (1 << conjs.size()); + conjs.push_back(p); + } + } + ast ref = make(rule,ps); + ast res = make_contra_node(ref,conjs,mask); + return res; + } + + ast triv_interp(const symb &rule, const ast &p0, const ast &p1, const ast &p2, int mask){ + std::vector ps; ps.resize(3); + ps[0] = p0; + ps[1] = p1; + ps[2] = p2; + return triv_interp(rule,ps,mask); + } - /** Make a modus-ponens node. This takes derivations of |- x - and |- x = y and produces |- y */ + /** Make a modus-ponens node. This takes derivations of |- x + and |- x = y and produces |- y */ - virtual node make_mp(const ast &p_eq_q, const ast &prem1, const ast &prem2){ + virtual node make_mp(const ast &p_eq_q, const ast &prem1, const ast &prem2){ - /* Interpolate the axiom p, p=q -> q */ - ast p = arg(p_eq_q,0); - ast q = arg(p_eq_q,1); - ast itp; - if(get_term_type(p_eq_q) == LitMixed){ - int mask = 1 << 2; - if(op(p) == Not && is_equivrel(arg(p,0))) - mask |= 1; // we may need to run this rule backward if first premise is negative equality - itp = triv_interp(modpon,p,p_eq_q,mk_not(q),mask); - } - else { - if(get_term_type(p) == LitA){ - if(get_term_type(q) == LitA) - itp = mk_false(); - else { - if(get_term_type(p_eq_q) == LitA) - itp = q; - else - throw proof_error(); - } - } - else { - if(get_term_type(q) == LitA){ - if(get_term_type(make(Equal,p,q)) == LitA) - itp = mk_not(p); - else - throw proof_error(); - } - else - itp = mk_true(); - } - } + /* Interpolate the axiom p, p=q -> q */ + ast p = arg(p_eq_q,0); + ast q = arg(p_eq_q,1); + ast itp; + if(get_term_type(p_eq_q) == LitMixed){ + int mask = 1 << 2; + if(op(p) == Not && is_equivrel(arg(p,0))) + mask |= 1; // we may need to run this rule backward if first premise is negative equality + itp = triv_interp(modpon,p,p_eq_q,mk_not(q),mask); + } + else { + if(get_term_type(p) == LitA){ + if(get_term_type(q) == LitA) + itp = mk_false(); + else { + if(get_term_type(p_eq_q) == LitA) + itp = q; + else + throw proof_error(); + } + } + else { + if(get_term_type(q) == LitA){ + if(get_term_type(make(Equal,p,q)) == LitA) + itp = mk_not(p); + else + throw proof_error(); + } + else + itp = mk_true(); + } + } - /* Resolve it with the premises */ - std::vector conc; conc.push_back(q); conc.push_back(mk_not(p_eq_q)); - itp = make_resolution(p,conc,itp,prem1); - conc.pop_back(); - itp = make_resolution(p_eq_q,conc,itp,prem2); - return itp; - } + /* Resolve it with the premises */ + std::vector conc; conc.push_back(q); conc.push_back(mk_not(p_eq_q)); + itp = make_resolution(p,conc,itp,prem1); + conc.pop_back(); + itp = make_resolution(p_eq_q,conc,itp,prem2); + return itp; + } - ast capture_localization(ast e){ - // #define CAPTURE_LOCALIZATION + ast capture_localization(ast e){ + // #define CAPTURE_LOCALIZATION #ifdef CAPTURE_LOCALIZATION - for(int i = localization_vars.size() - 1; i >= 0; i--){ - LocVar &lv = localization_vars[i]; - if(occurs_in(lv.var,e)){ - symb q = (pv->in_range(lv.frame,rng)) ? sexists : sforall; - e = make(q,make(Equal,lv.var,lv.term),e); // use Equal because it is polymorphic - } - } + for(int i = localization_vars.size() - 1; i >= 0; i--){ + LocVar &lv = localization_vars[i]; + if(occurs_in(lv.var,e)){ + symb q = (pv->in_range(lv.frame,rng)) ? sexists : sforall; + e = make(q,make(Equal,lv.var,lv.term),e); // use Equal because it is polymorphic + } + } #endif - return e; - } - - /** Make an axiom node. The conclusion must be an instance of an axiom. */ - virtual node make_axiom(const std::vector &conclusion, prover::range frng){ - int nargs = conclusion.size(); - std::vector largs(nargs); - std::vector eqs; - std::vector pfs; - - for(int i = 0; i < nargs; i++){ - ast argpf; - ast lit = conclusion[i]; - largs[i] = localize_term(lit,frng,argpf); - frng = pv->range_glb(frng,pv->ast_scope(largs[i])); - if(largs[i] != lit){ - eqs.push_back(make_equiv(largs[i],lit)); - pfs.push_back(argpf); - } + return e; } + + /** Make an axiom node. The conclusion must be an instance of an axiom. */ + virtual node make_axiom(const std::vector &conclusion, prover::range frng){ + int nargs = conclusion.size(); + std::vector largs(nargs); + std::vector eqs; + std::vector pfs; - int frame = pv->range_max(frng); - ast itp = make_assumption(frame,largs); + for(int i = 0; i < nargs; i++){ + ast argpf; + ast lit = conclusion[i]; + largs[i] = localize_term(lit,frng,argpf); + frng = pv->range_glb(frng,pv->ast_scope(largs[i])); + if(largs[i] != lit){ + eqs.push_back(make_equiv(largs[i],lit)); + pfs.push_back(argpf); + } + } - for(unsigned i = 0; i < eqs.size(); i++) - itp = make_mp(eqs[i],itp,pfs[i]); - return capture_localization(itp); - } - - virtual node make_axiom(const std::vector &conclusion){ - return make_axiom(conclusion,pv->range_full()); - } - - /** Make a Contra node. This rule takes a derivation of the form - Gamma |- False and produces |- \/~Gamma. */ - - virtual node make_contra(node prem, const std::vector &conclusion){ - return prem; - } - - /** Make hypothesis. Creates a node of the form P |- P. */ - - virtual node make_hypothesis(const ast &P){ - if(is_not(P)) - return make_hypothesis(arg(P,0)); - switch(get_term_type(P)){ - case LitA: - return mk_false(); - case LitB: - return mk_true(); - default: // mixed hypothesis - switch(op(P)){ - case Geq: - case Leq: - case Gt: - case Lt: { - ast zleqz = make(Leq,make_int("0"),make_int("0")); - ast fark1 = make(sum,zleqz,make_int("1"),get_placeholder(P)); - ast fark2 = make(sum,fark1,make_int("1"),get_placeholder(mk_not(P))); - ast res = make(And,make(contra,fark2,mk_false()), - make(contra,get_placeholder(mk_not(P)),P), - make(contra,get_placeholder(P),mk_not(P))); - return res; - } - default: { - ast em = make(exmid,P,get_placeholder(P),get_placeholder(mk_not(P))); - ast res = make(And,make(contra,em,mk_false()), - make(contra,get_placeholder(mk_not(P)),P), - make(contra,get_placeholder(P),mk_not(P))); - return res; - } - } + int frame = pv->range_max(frng); + ast itp = make_assumption(frame,largs); + + for(unsigned i = 0; i < eqs.size(); i++) + itp = make_mp(eqs[i],itp,pfs[i]); + return capture_localization(itp); } - } - /** Make a Reflexivity node. This rule produces |- x = x */ - - virtual node make_reflexivity(ast con){ - if(get_term_type(con) == LitA) - return mk_false(); - if(get_term_type(con) == LitB) - return mk_true(); - ast itp = make(And,make(contra,no_proof,mk_false()), - make(contra,mk_true(),mk_not(con))); - return itp; - } - - /** Make a Symmetry node. This takes a derivation of |- x = y and - produces | y = x. Ditto for ~(x=y) */ + virtual node make_axiom(const std::vector &conclusion){ + return make_axiom(conclusion,pv->range_full()); + } - virtual node make_symmetry(ast con, const ast &premcon, node prem){ + /** Make a Contra node. This rule takes a derivation of the form + Gamma |- False and produces |- \/~Gamma. */ + + virtual node make_contra(node prem, const std::vector &conclusion){ + return prem; + } + + /** Make hypothesis. Creates a node of the form P |- P. */ + + virtual node make_hypothesis(const ast &P){ + if(is_not(P)) + return make_hypothesis(arg(P,0)); + switch(get_term_type(P)){ + case LitA: + return mk_false(); + case LitB: + return mk_true(); + default: // mixed hypothesis + switch(op(P)){ + case Geq: + case Leq: + case Gt: + case Lt: { + ast zleqz = make(Leq,make_int("0"),make_int("0")); + ast fark1 = make(sum,zleqz,make_int("1"),get_placeholder(P)); + ast fark2 = make(sum,fark1,make_int("1"),get_placeholder(mk_not(P))); + ast res = make(And,make(contra,fark2,mk_false()), + make(contra,get_placeholder(mk_not(P)),P), + make(contra,get_placeholder(P),mk_not(P))); + return res; + } + default: { + ast em = make(exmid,P,get_placeholder(P),get_placeholder(mk_not(P))); + ast res = make(And,make(contra,em,mk_false()), + make(contra,get_placeholder(mk_not(P)),P), + make(contra,get_placeholder(P),mk_not(P))); + return res; + } + } + } + } + + /** Make a Reflexivity node. This rule produces |- x = x */ + + virtual node make_reflexivity(ast con){ + if(get_term_type(con) == LitA) + return mk_false(); + if(get_term_type(con) == LitB) + return mk_true(); + ast itp = make(And,make(contra,no_proof,mk_false()), + make(contra,mk_true(),mk_not(con))); + return itp; + } + + /** Make a Symmetry node. This takes a derivation of |- x = y and + produces | y = x. Ditto for ~(x=y) */ + + virtual node make_symmetry(ast con, const ast &premcon, node prem){ #if 0 - ast x = arg(con,0); - ast y = arg(con,1); - ast p = make(op(con),y,x); + ast x = arg(con,0); + ast y = arg(con,1); + ast p = make(op(con),y,x); #endif - if(get_term_type(con) != LitMixed) - return prem; // symmetry shmymmetry... - ast em = make(exmid,con,make(symm,get_placeholder(premcon)),get_placeholder(mk_not(con))); - ast itp = make(And,make(contra,em,mk_false()), - make(contra,make(symm,get_placeholder(mk_not(con))),premcon), - make(contra,make(symm,get_placeholder(premcon)),mk_not(con))); + if(get_term_type(con) != LitMixed) + return prem; // symmetry shmymmetry... + ast em = make(exmid,con,make(symm,get_placeholder(premcon)),get_placeholder(mk_not(con))); + ast itp = make(And,make(contra,em,mk_false()), + make(contra,make(symm,get_placeholder(mk_not(con))),premcon), + make(contra,make(symm,get_placeholder(premcon)),mk_not(con))); - std::vector conc; conc.push_back(con); - itp = make_resolution(premcon,conc,itp,prem); - return itp; - } + std::vector conc; conc.push_back(con); + itp = make_resolution(premcon,conc,itp,prem); + return itp; + } - ast make_equiv_rel(const ast &x, const ast &y){ - if(is_bool_type(get_type(x))) - return make(Iff,x,y); - return make(Equal,x,y); - } + ast make_equiv_rel(const ast &x, const ast &y){ + if(is_bool_type(get_type(x))) + return make(Iff,x,y); + return make(Equal,x,y); + } - /** Make a transitivity node. This takes derivations of |- x = y - and |- y = z produces | x = z */ + /** Make a transitivity node. This takes derivations of |- x = y + and |- y = z produces | x = z */ - virtual node make_transitivity(const ast &x, const ast &y, const ast &z, node prem1, node prem2){ + virtual node make_transitivity(const ast &x, const ast &y, const ast &z, node prem1, node prem2){ - /* Interpolate the axiom x=y,y=z,-> x=z */ - ast p = make_equiv_rel(x,y); - ast q = make_equiv_rel(y,z); - ast r = make_equiv_rel(x,z); - ast equiv = make(Iff,p,r); - ast itp; + /* Interpolate the axiom x=y,y=z,-> x=z */ + ast p = make_equiv_rel(x,y); + ast q = make_equiv_rel(y,z); + ast r = make_equiv_rel(x,z); + ast equiv = make(Iff,p,r); + ast itp; - itp = make_congruence(q,equiv,prem2); - itp = make_mp(equiv,prem1,itp); + itp = make_congruence(q,equiv,prem2); + itp = make_mp(equiv,prem1,itp); - return itp; + return itp; - } + } - /** Make a congruence node. This takes derivations of |- x_i = y_i - and produces |- f(x_1,...,x_n) = f(y_1,...,y_n) */ + /** Make a congruence node. This takes derivations of |- x_i = y_i + and produces |- f(x_1,...,x_n) = f(y_1,...,y_n) */ - virtual node make_congruence(const ast &p, const ast &con, const ast &prem1){ - ast x = arg(p,0), y = arg(p,1); - ast itp; - LitType con_t = get_term_type(con); - if(get_term_type(p) == LitA){ - if(con_t == LitA) - itp = mk_false(); - else if(con_t == LitB) - itp = p; - else - itp = make_mixed_congruence(x, y, p, con, prem1); + virtual node make_congruence(const ast &p, const ast &con, const ast &prem1){ + ast x = arg(p,0), y = arg(p,1); + ast itp; + LitType con_t = get_term_type(con); + if(get_term_type(p) == LitA){ + if(con_t == LitA) + itp = mk_false(); + else if(con_t == LitB) + itp = p; + else + itp = make_mixed_congruence(x, y, p, con, prem1); + } + else { + if(con_t == LitA) + itp = mk_not(p); + else{ + if(con_t == LitB) + itp = mk_true(); + else + itp = make_mixed_congruence(x, y, p, con, prem1); + } + } + std::vector conc; conc.push_back(con); + itp = make_resolution(p,conc,itp,prem1); + return itp; } - else { - if(con_t == LitA) - itp = mk_not(p); - else{ - if(con_t == LitB) - itp = mk_true(); - else - itp = make_mixed_congruence(x, y, p, con, prem1); - } + + int find_congruence_position(const ast &p, const ast &con){ + // find the argument position of x and y + const ast &x = arg(p,0); + const ast &y = arg(p,1); + int nargs = num_args(arg(con,0)); + for(int i = 0; i < nargs; i++) + if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i)) + return i; + throw proof_error(); } - std::vector conc; conc.push_back(con); - itp = make_resolution(p,conc,itp,prem1); - return itp; - } - int find_congruence_position(const ast &p, const ast &con){ - // find the argument position of x and y - const ast &x = arg(p,0); - const ast &y = arg(p,1); - int nargs = num_args(arg(con,0)); - for(int i = 0; i < nargs; i++) - if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i)) - return i; - throw proof_error(); - } - - /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,... - and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */ + /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,... + and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */ - node make_congruence(const std::vector &p, const ast &con, const std::vector &prems){ - if(p.size() == 0) - throw proof_error(); - if(p.size() == 1) - return make_congruence(p[0],con,prems[0]); - ast thing = con; - ast res = mk_true(); - for(unsigned i = 0; i < p.size(); i++){ - int pos = find_congruence_position(p[i],thing); - ast next = subst_in_arg_pos(pos,arg(p[i],1),arg(thing,0)); - ast goal = make(op(thing),arg(thing,0),next); - ast equa = make_congruence(p[i],goal,prems[i]); - if(i == 0) - res = equa; - else { - ast trace = make(op(con),arg(con,0),arg(thing,0)); - ast equiv = make(Iff,trace,make(op(trace),arg(trace,0),next)); - ast foo = make_congruence(goal,equiv,equa); - res = make_mp(equiv,res,foo); - } - thing = make(op(thing),next,arg(thing,1)); + node make_congruence(const std::vector &p, const ast &con, const std::vector &prems){ + if(p.size() == 0) + throw proof_error(); + if(p.size() == 1) + return make_congruence(p[0],con,prems[0]); + ast thing = con; + ast res = mk_true(); + for(unsigned i = 0; i < p.size(); i++){ + int pos = find_congruence_position(p[i],thing); + ast next = subst_in_arg_pos(pos,arg(p[i],1),arg(thing,0)); + ast goal = make(op(thing),arg(thing,0),next); + ast equa = make_congruence(p[i],goal,prems[i]); + if(i == 0) + res = equa; + else { + ast trace = make(op(con),arg(con,0),arg(thing,0)); + ast equiv = make(Iff,trace,make(op(trace),arg(trace,0),next)); + ast foo = make_congruence(goal,equiv,equa); + res = make_mp(equiv,res,foo); + } + thing = make(op(thing),next,arg(thing,1)); + } + return res; } - return res; - } - /* Interpolate a mixed congruence axiom. */ + /* Interpolate a mixed congruence axiom. */ - virtual ast make_mixed_congruence(const ast &x, const ast &y, const ast &p, const ast &con, const ast &prem1){ - ast foo = p; - std::vector conjs; - LitType t = get_term_type(foo); - switch(t){ - case LitA: - case LitB: - foo = make_local_rewrite(t,foo); - break; - case LitMixed: - conjs.push_back(foo); - foo = get_placeholder(foo); + virtual ast make_mixed_congruence(const ast &x, const ast &y, const ast &p, const ast &con, const ast &prem1){ + ast foo = p; + std::vector conjs; + LitType t = get_term_type(foo); + switch(t){ + case LitA: + case LitB: + foo = make_local_rewrite(t,foo); + break; + case LitMixed: + conjs.push_back(foo); + foo = get_placeholder(foo); + } + // find the argument position of x and y + int pos = -1; + int nargs = num_args(arg(con,0)); + for(int i = 0; i < nargs; i++) + if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i)) + pos = i; + if(pos == -1) + throw proof_error(); + ast bar = make(cong,foo,make_int(rational(pos)),get_placeholder(mk_not(con))); + conjs.push_back(mk_not(con)); + return make_contra_node(bar,conjs); } - // find the argument position of x and y - int pos = -1; - int nargs = num_args(arg(con,0)); - for(int i = 0; i < nargs; i++) - if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i)) - pos = i; - if(pos == -1) - throw proof_error(); - ast bar = make(cong,foo,make_int(rational(pos)),get_placeholder(mk_not(con))); - conjs.push_back(mk_not(con)); - return make_contra_node(bar,conjs); - } - ast subst_in_arg_pos(int pos, ast term, ast app){ - std::vector args; - get_args(app,args); - args[pos] = term; - return clone(app,args); - } - - /** Make a farkas proof node. */ - - virtual node make_farkas(ast con, const std::vector &prems, const std::vector &prem_cons, - const std::vector &coeffs){ - - /* Compute the interpolant for the clause */ - - ast zero = make_int("0"); - std::vector conjs; - ast thing = make(Leq,zero,zero); - for(unsigned i = 0; i < prem_cons.size(); i++){ - const ast &lit = prem_cons[i]; - if(get_term_type(lit) == LitA) - // Farkas rule seems to assume strict integer inequalities are rounded - linear_comb(thing,coeffs[i],lit,true /*round_off*/); + ast subst_in_arg_pos(int pos, ast term, ast app){ + std::vector args; + get_args(app,args); + args[pos] = term; + return clone(app,args); } - thing = simplify_ineq(thing); - for(unsigned i = 0; i < prem_cons.size(); i++){ - const ast &lit = prem_cons[i]; - if(get_term_type(lit) == LitMixed){ - thing = make(sum,thing,coeffs[i],get_placeholder(lit)); - conjs.push_back(lit); - } - } - thing = make_contra_node(thing,conjs); - /* Resolve it with the premises */ - std::vector conc; conc.resize(prem_cons.size()); - for(unsigned i = 0; i < prem_cons.size(); i++) - conc[prem_cons.size()-i-1] = prem_cons[i]; - for(unsigned i = 0; i < prem_cons.size(); i++){ - thing = make_resolution(prem_cons[i],conc,thing,prems[i]); - conc.pop_back(); - } - return thing; - } + /** Make a farkas proof node. */ - /** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */ + virtual node make_farkas(ast con, const std::vector &prems, const std::vector &prem_cons, + const std::vector &coeffs){ - void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false){ - ast Qrhs; - bool qstrict = false; - if(is_not(Q)){ - ast nQ = arg(Q,0); - switch(op(nQ)){ - case Gt: - Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); - break; - case Lt: - Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); - break; - case Geq: - Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); - qstrict = true; - break; - case Leq: - Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); - qstrict = true; - break; - default: - throw proof_error(); - } - } - else { - switch(op(Q)){ - case Leq: - Qrhs = make(Sub,arg(Q,1),arg(Q,0)); - break; - case Geq: - Qrhs = make(Sub,arg(Q,0),arg(Q,1)); - break; - case Lt: - Qrhs = make(Sub,arg(Q,1),arg(Q,0)); - qstrict = true; - break; - case Gt: - Qrhs = make(Sub,arg(Q,0),arg(Q,1)); - qstrict = true; - break; - default: - throw proof_error(); - } + /* Compute the interpolant for the clause */ + + ast zero = make_int("0"); + std::vector conjs; + ast thing = make(Leq,zero,zero); + for(unsigned i = 0; i < prem_cons.size(); i++){ + const ast &lit = prem_cons[i]; + if(get_term_type(lit) == LitA) + // Farkas rule seems to assume strict integer inequalities are rounded + linear_comb(thing,coeffs[i],lit,true /*round_off*/); + } + thing = simplify_ineq(thing); + for(unsigned i = 0; i < prem_cons.size(); i++){ + const ast &lit = prem_cons[i]; + if(get_term_type(lit) == LitMixed){ + thing = make(sum,thing,coeffs[i],get_placeholder(lit)); + conjs.push_back(lit); + } + } + thing = make_contra_node(thing,conjs); + + /* Resolve it with the premises */ + std::vector conc; conc.resize(prem_cons.size()); + for(unsigned i = 0; i < prem_cons.size(); i++) + conc[prem_cons.size()-i-1] = prem_cons[i]; + for(unsigned i = 0; i < prem_cons.size(); i++){ + thing = make_resolution(prem_cons[i],conc,thing,prems[i]); + conc.pop_back(); + } + return thing; } + + /** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */ + + void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false){ + ast Qrhs; + bool qstrict = false; + if(is_not(Q)){ + ast nQ = arg(Q,0); + switch(op(nQ)){ + case Gt: + Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); + break; + case Lt: + Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); + break; + case Geq: + Qrhs = make(Sub,arg(nQ,1),arg(nQ,0)); + qstrict = true; + break; + case Leq: + Qrhs = make(Sub,arg(nQ,0),arg(nQ,1)); + qstrict = true; + break; + default: + throw proof_error(); + } + } + else { + switch(op(Q)){ + case Leq: + Qrhs = make(Sub,arg(Q,1),arg(Q,0)); + break; + case Geq: + Qrhs = make(Sub,arg(Q,0),arg(Q,1)); + break; + case Lt: + Qrhs = make(Sub,arg(Q,1),arg(Q,0)); + qstrict = true; + break; + case Gt: + Qrhs = make(Sub,arg(Q,0),arg(Q,1)); + qstrict = true; + break; + default: + throw proof_error(); + } + } #if 0 - bool pstrict = op(P) == Lt, strict = pstrict || qstrict; - if(pstrict && qstrict && round_off) - Qrhs = make(Sub,Qrhs,make_int(rational(1))); + bool pstrict = op(P) == Lt, strict = pstrict || qstrict; + if(pstrict && qstrict && round_off) + Qrhs = make(Sub,Qrhs,make_int(rational(1))); #else - bool pstrict = op(P) == Lt; - if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){ - Qrhs = make(Sub,Qrhs,make_int(rational(1))); - qstrict = false; - } - Qrhs = make(Times,c,Qrhs); - bool strict = pstrict || qstrict; + bool pstrict = op(P) == Lt; + if(qstrict && round_off && (pstrict || !(c == make_int(rational(1))))){ + Qrhs = make(Sub,Qrhs,make_int(rational(1))); + qstrict = false; + } + Qrhs = make(Times,c,Qrhs); + bool strict = pstrict || qstrict; #endif - if(strict) - P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs)); - else - P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs)); - } + if(strict) + P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs)); + else + P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs)); + } - /* Make an axiom instance of the form |- x<=y, y<= x -> x =y */ - virtual node make_leq2eq(ast x, ast y, const ast &xleqy, const ast &yleqx){ - ast con = make(Equal,x,y); - ast itp; - switch(get_term_type(con)){ - case LitA: - itp = mk_false(); - break; - case LitB: - itp = mk_true(); - break; - default: { // mixed equality - if(get_term_type(x) == LitMixed || get_term_type(y) == LitMixed){ - if(y == make_int(rational(0)) && op(x) == Plus && num_args(x) == 2){ - // std::cerr << "WARNING: untested case in leq2eq\n"; - } - else { - // std::cerr << "WARNING: mixed term in leq2eq\n"; - std::vector lits; - lits.push_back(con); - lits.push_back(make(Not,xleqy)); - lits.push_back(make(Not,yleqx)); - return make_axiom(lits); - } - } - std::vector conjs; conjs.resize(3); - conjs[0] = mk_not(con); - conjs[1] = xleqy; - conjs[2] = yleqx; - itp = make_contra_node(make(leq2eq, - get_placeholder(mk_not(con)), - get_placeholder(xleqy), - get_placeholder(yleqx)), - conjs,1); + /* Make an axiom instance of the form |- x<=y, y<= x -> x =y */ + virtual node make_leq2eq(ast x, ast y, const ast &xleqy, const ast &yleqx){ + ast con = make(Equal,x,y); + ast itp; + switch(get_term_type(con)){ + case LitA: + itp = mk_false(); + break; + case LitB: + itp = mk_true(); + break; + default: { // mixed equality + if(get_term_type(x) == LitMixed || get_term_type(y) == LitMixed){ + if(y == make_int(rational(0)) && op(x) == Plus && num_args(x) == 2){ + // std::cerr << "WARNING: untested case in leq2eq\n"; + } + else { + // std::cerr << "WARNING: mixed term in leq2eq\n"; + std::vector lits; + lits.push_back(con); + lits.push_back(make(Not,xleqy)); + lits.push_back(make(Not,yleqx)); + return make_axiom(lits); + } + } + std::vector conjs; conjs.resize(3); + conjs[0] = mk_not(con); + conjs[1] = xleqy; + conjs[2] = yleqx; + itp = make_contra_node(make(leq2eq, + get_placeholder(mk_not(con)), + get_placeholder(xleqy), + get_placeholder(yleqx)), + conjs,1); + } + } + return itp; } - } - return itp; - } - /* Make an axiom instance of the form |- x = y -> x <= y */ - virtual node make_eq2leq(ast x, ast y, const ast &xleqy){ - ast itp; - switch(get_term_type(xleqy)){ - case LitA: - itp = mk_false(); - break; - case LitB: - itp = mk_true(); - break; - default: { // mixed equality - std::vector conjs; conjs.resize(2); - conjs[0] = make(Equal,x,y); - conjs[1] = mk_not(xleqy); - itp = make(eq2leq,get_placeholder(conjs[0]),get_placeholder(conjs[1])); - itp = make_contra_node(itp,conjs,2); + /* Make an axiom instance of the form |- x = y -> x <= y */ + virtual node make_eq2leq(ast x, ast y, const ast &xleqy){ + ast itp; + switch(get_term_type(xleqy)){ + case LitA: + itp = mk_false(); + break; + case LitB: + itp = mk_true(); + break; + default: { // mixed equality + std::vector conjs; conjs.resize(2); + conjs[0] = make(Equal,x,y); + conjs[1] = mk_not(xleqy); + itp = make(eq2leq,get_placeholder(conjs[0]),get_placeholder(conjs[1])); + itp = make_contra_node(itp,conjs,2); + } + } + return itp; } - } - return itp; - } - /* Make an inference of the form t <= c |- t/d <= floor(c/d) where t - is an affine term divisble by d and c is an integer constant */ - virtual node make_cut_rule(const ast &tleqc, const ast &d, const ast &con, const ast &prem){ - ast itp = mk_false(); - switch(get_term_type(con)){ - case LitA: - itp = mk_false(); - break; - case LitB: - itp = mk_true(); - break; - default: { - std::vector conjs; conjs.resize(2); - conjs[0] = tleqc; - conjs[1] = mk_not(con); - itp = make(sum,get_placeholder(conjs[0]),d,get_placeholder(conjs[1])); - itp = make_contra_node(itp,conjs); + /* Make an inference of the form t <= c |- t/d <= floor(c/d) where t + is an affine term divisble by d and c is an integer constant */ + virtual node make_cut_rule(const ast &tleqc, const ast &d, const ast &con, const ast &prem){ + ast itp = mk_false(); + switch(get_term_type(con)){ + case LitA: + itp = mk_false(); + break; + case LitB: + itp = mk_true(); + break; + default: { + std::vector conjs; conjs.resize(2); + conjs[0] = tleqc; + conjs[1] = mk_not(con); + itp = make(sum,get_placeholder(conjs[0]),d,get_placeholder(conjs[1])); + itp = make_contra_node(itp,conjs); + } + } + std::vector conc; conc.push_back(con); + itp = make_resolution(tleqc,conc,itp,prem); + return itp; } - } - std::vector conc; conc.push_back(con); - itp = make_resolution(tleqc,conc,itp,prem); - return itp; - } - // create a fresh variable for localization - ast fresh_localization_var(const ast &term, int frame){ - std::ostringstream s; - s << "%" << (localization_vars.size()); - ast var = make_var(s.str().c_str(),get_type(term)); - pv->sym_range(sym(var)) = pv->range_full(); // make this variable global - localization_vars.push_back(LocVar(var,term,frame)); - return var; - } + // create a fresh variable for localization + ast fresh_localization_var(const ast &term, int frame){ + std::ostringstream s; + s << "%" << (localization_vars.size()); + ast var = make_var(s.str().c_str(),get_type(term)); + pv->sym_range(sym(var)) = pv->range_full(); // make this variable global + localization_vars.push_back(LocVar(var,term,frame)); + return var; + } - struct LocVar { // localization vars - ast var; // a fresh variable - ast term; // term it represents - int frame; // frame in which it's defined - LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} - }; + struct LocVar { // localization vars + ast var; // a fresh variable + ast term; // term it represents + int frame; // frame in which it's defined + LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} + }; - std::vector localization_vars; // localization vars in order of creation + std::vector localization_vars; // localization vars in order of creation - struct locmaps { - hash_map localization_map; // maps terms to their localization vars - hash_map localization_pf_map; // maps terms to proofs of their localizations - }; + struct locmaps { + hash_map localization_map; // maps terms to their localization vars + hash_map localization_pf_map; // maps terms to proofs of their localizations + }; - hash_map localization_maps_per_range; + hash_map localization_maps_per_range; - /* "localize" a term e to a given frame range, creating new symbols to - represent non-local subterms. This returns the localized version e_l, - as well as a proof thet e_l = l. - */ + /* "localize" a term e to a given frame range, creating new symbols to + represent non-local subterms. This returns the localized version e_l, + as well as a proof thet e_l = l. + */ - ast make_refl(const ast &e){ - if(get_term_type(e) == LitA) - return mk_false(); - return mk_true(); // TODO: is this right? - } + ast make_refl(const ast &e){ + if(get_term_type(e) == LitA) + return mk_false(); + return mk_true(); // TODO: is this right? + } - ast make_equiv(const ast &x, const ast &y){ - if(get_type(x) == bool_type()) - return make(Iff,x,y); - else - return make(Equal,x,y); - } + ast make_equiv(const ast &x, const ast &y){ + if(get_type(x) == bool_type()) + return make(Iff,x,y); + else + return make(Equal,x,y); + } - bool range_is_global(const prover::range &r){ - if(pv->range_contained(r,rng)) - return false; - if(!pv->ranges_intersect(r,rng)) - return false; - return true; - } + bool range_is_global(const prover::range &r){ + if(pv->range_contained(r,rng)) + return false; + if(!pv->ranges_intersect(r,rng)) + return false; + return true; + } - ast localize_term(ast e, const prover::range &rng, ast &pf){ + ast localize_term(ast e, const prover::range &rng, ast &pf){ - // we need to memoize this function separately for A, B and global - prover::range map_range = rng; - if(range_is_global(map_range)) - map_range = pv->range_full(); - locmaps &maps = localization_maps_per_range[map_range]; - hash_map &localization_map = maps.localization_map; - hash_map &localization_pf_map = maps.localization_pf_map; + // we need to memoize this function separately for A, B and global + prover::range map_range = rng; + if(range_is_global(map_range)) + map_range = pv->range_full(); + locmaps &maps = localization_maps_per_range[map_range]; + hash_map &localization_map = maps.localization_map; + hash_map &localization_pf_map = maps.localization_pf_map; - ast orig_e = e; - pf = make_refl(e); // proof that e = e + ast orig_e = e; + pf = make_refl(e); // proof that e = e - // prover::range erng = - pv->ast_scope(e); + // prover::range erng = + pv->ast_scope(e); #if 0 - if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ - return e; // this term occurs in range, so it's O.K. - } + if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ + return e; // this term occurs in range, so it's O.K. + } #endif - hash_map::iterator it = localization_map.find(e); + hash_map::iterator it = localization_map.find(e); - if(it != localization_map.end() && is_bool_type(get_type(e)) - && !pv->ranges_intersect(pv->ast_scope(it->second),rng)) - it = localization_map.end(); // prevent quantifiers over booleans + if(it != localization_map.end() && is_bool_type(get_type(e)) + && !pv->ranges_intersect(pv->ast_scope(it->second),rng)) + it = localization_map.end(); // prevent quantifiers over booleans - if(it != localization_map.end()){ - pf = localization_pf_map[e]; - e = it->second; - } + if(it != localization_map.end()){ + pf = localization_pf_map[e]; + e = it->second; + } - else { - // if it is non-local, we must first localize the arguments to - // the range of its function symbol + else { + // if it is non-local, we must first localize the arguments to + // the range of its function symbol - int nargs = num_args(e); - if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ - prover::range frng = rng; - opr o = op(e); - if(o == Uninterpreted){ - symb f = sym(e); - prover::range srng = pv->sym_range(f); - if(pv->ranges_intersect(srng,rng)) // localize to desired range if possible - frng = pv->range_glb(srng,rng); - else - frng = srng; // this term will be localized - } - else if(o == Plus || o == Times){ // don't want bound variables inside arith ops - // std::cout << "WARNING: non-local arithmetic\n"; - // frng = erng; // this term will be localized - } - else if(o == Select){ // treat the array term like a function symbol - prover::range srng = pv->ast_scope(arg(e,0)); - if(!(srng.lo > srng.hi) && pv->ranges_intersect(srng,rng)) // localize to desired range if possible - frng = pv->range_glb(srng,rng); - else - frng = srng; // this term will be localized - } - std::vector largs(nargs); - std::vector eqs; - std::vector pfs; - for(int i = 0; i < nargs; i++){ - ast argpf; - largs[i] = localize_term(arg(e,i),frng,argpf); - frng = pv->range_glb(frng,pv->ast_scope(largs[i])); - if(largs[i] != arg(e,i)){ - eqs.push_back(make_equiv(largs[i],arg(e,i))); - pfs.push_back(argpf); - } - } + int nargs = num_args(e); + if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ + prover::range frng = rng; + opr o = op(e); + if(o == Uninterpreted){ + symb f = sym(e); + prover::range srng = pv->sym_range(f); + if(pv->ranges_intersect(srng,rng)) // localize to desired range if possible + frng = pv->range_glb(srng,rng); + else + frng = srng; // this term will be localized + } + else if(o == Plus || o == Times){ // don't want bound variables inside arith ops + // std::cout << "WARNING: non-local arithmetic\n"; + // frng = erng; // this term will be localized + } + else if(o == Select){ // treat the array term like a function symbol + prover::range srng = pv->ast_scope(arg(e,0)); + if(!(srng.lo > srng.hi) && pv->ranges_intersect(srng,rng)) // localize to desired range if possible + frng = pv->range_glb(srng,rng); + else + frng = srng; // this term will be localized + } + std::vector largs(nargs); + std::vector eqs; + std::vector pfs; + for(int i = 0; i < nargs; i++){ + ast argpf; + largs[i] = localize_term(arg(e,i),frng,argpf); + frng = pv->range_glb(frng,pv->ast_scope(largs[i])); + if(largs[i] != arg(e,i)){ + eqs.push_back(make_equiv(largs[i],arg(e,i))); + pfs.push_back(argpf); + } + } - e = clone(e,largs); - if(pfs.size()) - pf = make_congruence(eqs,make_equiv(e,orig_e),pfs); - // assert(is_local(e)); - } + e = clone(e,largs); + if(pfs.size()) + pf = make_congruence(eqs,make_equiv(e,orig_e),pfs); + // assert(is_local(e)); + } - localization_pf_map[orig_e] = pf; - localization_map[orig_e] = e; - } + localization_pf_map[orig_e] = pf; + localization_map[orig_e] = e; + } - if(pv->ranges_intersect(pv->ast_scope(e),rng)) - return e; // this term occurs in range, so it's O.K. + if(pv->ranges_intersect(pv->ast_scope(e),rng)) + return e; // this term occurs in range, so it's O.K. - if(is_array_type(get_type(e))) - std::cerr << "WARNING: array quantifier\n"; + if(is_array_type(get_type(e))) + std::cerr << "WARNING: array quantifier\n"; - // choose a frame for the constraint that is close to range - int frame = pv->range_near(pv->ast_scope(e),rng); + // choose a frame for the constraint that is close to range + int frame = pv->range_near(pv->ast_scope(e),rng); - ast new_var = fresh_localization_var(e,frame); - localization_map[orig_e] = new_var; - std::vector foo; foo.push_back(make_equiv(new_var,e)); - ast bar = make_assumption(frame,foo); - pf = make_transitivity(new_var,e,orig_e,bar,pf); - localization_pf_map[orig_e] = pf; + ast new_var = fresh_localization_var(e,frame); + localization_map[orig_e] = new_var; + std::vector foo; foo.push_back(make_equiv(new_var,e)); + ast bar = make_assumption(frame,foo); + pf = make_transitivity(new_var,e,orig_e,bar,pf); + localization_pf_map[orig_e] = pf; - // HACK: try to bias this term in the future - if(!pv->range_is_full(rng)){ - prover::range rf = pv->range_full(); - locmaps &fmaps = localization_maps_per_range[rf]; - hash_map &flocalization_map = fmaps.localization_map; - hash_map &flocalization_pf_map = fmaps.localization_pf_map; - // if(flocalization_map.find(orig_e) == flocalization_map.end()) - { - flocalization_map[orig_e] = new_var; - flocalization_pf_map[orig_e] = pf; - } - } + // HACK: try to bias this term in the future + if(!pv->range_is_full(rng)){ + prover::range rf = pv->range_full(); + locmaps &fmaps = localization_maps_per_range[rf]; + hash_map &flocalization_map = fmaps.localization_map; + hash_map &flocalization_pf_map = fmaps.localization_pf_map; + // if(flocalization_map.find(orig_e) == flocalization_map.end()) + { + flocalization_map[orig_e] = new_var; + flocalization_pf_map[orig_e] = pf; + } + } - return new_var; - } - - ast delete_quant(hash_map &memo, const ast &v, const ast &e){ - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - opr o = op(e); - switch(o){ - case Or: - case And: - case Implies: { - unsigned nargs = num_args(e); - std::vector args; args.resize(nargs); - for(unsigned i = 0; i < nargs; i++) - args[i] = delete_quant(memo, v, arg(e,i)); - res = make(o,args); - break; - } - case Uninterpreted: { - symb s = sym(e); - ast w = arg(arg(e,0),0); - if(s == sforall || s == sexists){ - res = delete_quant(memo,v,arg(e,1)); - if(w != v) - res = make(s,w,res); - break; - } - } - default: - res = e; - } + return new_var; } - return res; - } - ast insert_quants(hash_map &memo, const ast &e){ - std::pair foo(e,ast()); - std::pair::iterator,bool> bar = memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - opr o = op(e); - switch(o){ - case Or: - case And: - case Implies: { - unsigned nargs = num_args(e); - std::vector args; args.resize(nargs); - for(unsigned i = 0; i < nargs; i++) - args[i] = insert_quants(memo, arg(e,i)); - res = make(o,args); - break; - } - case Uninterpreted: { - symb s = sym(e); - if(s == sforall || s == sexists){ - opr q = (s == sforall) ? Forall : Exists; - ast v = arg(arg(e,0),0); - hash_map dmemo; - ast body = delete_quant(dmemo,v,arg(e,1)); - body = insert_quants(memo,body); - res = apply_quant(q,v,body); - break; - } - } - default: - res = e; - } + ast delete_quant(hash_map &memo, const ast &v, const ast &e){ + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + opr o = op(e); + switch(o){ + case Or: + case And: + case Implies: { + unsigned nargs = num_args(e); + std::vector args; args.resize(nargs); + for(unsigned i = 0; i < nargs; i++) + args[i] = delete_quant(memo, v, arg(e,i)); + res = make(o,args); + break; + } + case Uninterpreted: { + symb s = sym(e); + ast w = arg(arg(e,0),0); + if(s == sforall || s == sexists){ + res = delete_quant(memo,v,arg(e,1)); + if(w != v) + res = make(s,w,res); + break; + } + } + default: + res = e; + } + } + return res; } - return res; - } - ast add_quants(ast e){ + ast insert_quants(hash_map &memo, const ast &e){ + std::pair foo(e,ast()); + std::pair::iterator,bool> bar = memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + opr o = op(e); + switch(o){ + case Or: + case And: + case Implies: { + unsigned nargs = num_args(e); + std::vector args; args.resize(nargs); + for(unsigned i = 0; i < nargs; i++) + args[i] = insert_quants(memo, arg(e,i)); + res = make(o,args); + break; + } + case Uninterpreted: { + symb s = sym(e); + if(s == sforall || s == sexists){ + opr q = (s == sforall) ? Forall : Exists; + ast v = arg(arg(e,0),0); + hash_map dmemo; + ast body = delete_quant(dmemo,v,arg(e,1)); + body = insert_quants(memo,body); + res = apply_quant(q,v,body); + break; + } + } + default: + res = e; + } + } + return res; + } + + ast add_quants(ast e){ #ifdef CAPTURE_LOCALIZATION - if(!localization_vars.empty()){ - hash_map memo; - e = insert_quants(memo,e); - } + if(!localization_vars.empty()){ + hash_map memo; + e = insert_quants(memo,e); + } #else - for(int i = localization_vars.size() - 1; i >= 0; i--){ - LocVar &lv = localization_vars[i]; - opr quantifier = (pv->in_range(lv.frame,rng)) ? Exists : Forall; - e = apply_quant(quantifier,lv.var,e); - } + for(int i = localization_vars.size() - 1; i >= 0; i--){ + LocVar &lv = localization_vars[i]; + opr quantifier = (pv->in_range(lv.frame,rng)) ? Exists : Forall; + e = apply_quant(quantifier,lv.var,e); + } #endif - return e; - } + return e; + } - node make_resolution(ast pivot, node premise1, node premise2) { - std::vector lits; - return make_resolution(pivot,lits,premise1,premise2); - } + node make_resolution(ast pivot, node premise1, node premise2) { + std::vector lits; + return make_resolution(pivot,lits,premise1,premise2); + } - /* Return an interpolant from a proof of false */ - ast interpolate(const node &pf){ - // proof of false must be a formula, with quantified symbols + /* Return an interpolant from a proof of false */ + ast interpolate(const node &pf){ + // proof of false must be a formula, with quantified symbols #ifndef BOGUS_QUANTS - return add_quants(z3_simplify(pf)); + return add_quants(z3_simplify(pf)); #else - return z3_simplify(pf); + return z3_simplify(pf); #endif - } - - ast resolve_with_quantifier(const ast &pivot1, const ast &conj1, - const ast &pivot2, const ast &conj2){ - if(is_not(arg(pivot1,1))) - return resolve_with_quantifier(pivot2,conj2,pivot1,conj1); - ast eqpf; - ast P = arg(pivot1,1); - ast Ploc = localize_term(P, rng, eqpf); - ast pPloc = make_hypothesis(Ploc); - ast pP = make_mp(make(Iff,Ploc,P),pPloc,eqpf); - ast rP = make_resolution(P,conj1,pP); - ast nP = mk_not(P); - ast nPloc = mk_not(Ploc); - ast neqpf = make_congruence(make(Iff,Ploc,P),make(Iff,nPloc,nP),eqpf); - ast npPloc = make_hypothesis(nPloc); - ast npP = make_mp(make(Iff,nPloc,nP),npPloc,neqpf); - ast nrP = make_resolution(nP,conj2,npP); - ast res = make_resolution(Ploc,rP,nrP); - return capture_localization(res); - } - - ast get_contra_coeff(const ast &f){ - ast c = arg(f,0); - // if(!is_not(arg(f,1))) - // c = make(Uminus,c); - return c; - } - - ast my_or(const ast &a, const ast &b){ - return mk_or(a,b); - } - - ast my_and(const ast &a, const ast &b){ - return mk_and(a,b); - } - - ast my_implies(const ast &a, const ast &b){ - return mk_implies(a,b); - } - - ast my_or(const std::vector &a){ - return mk_or(a); - } - - ast my_and(const std::vector &a){ - return mk_and(a); - } - - ast get_lit_atom(const ast &l){ - if(op(l) == Not) - return arg(l,0); - return l; - } - - bool is_placeholder(const ast &e){ - if(op(e) == Uninterpreted){ - std::string name = string_of_symbol(sym(e)); - if(name.size() > 2 && name[0] == '@' && name[1] == 'p') - return true; } - return false; - } + + ast resolve_with_quantifier(const ast &pivot1, const ast &conj1, + const ast &pivot2, const ast &conj2){ + if(is_not(arg(pivot1,1))) + return resolve_with_quantifier(pivot2,conj2,pivot1,conj1); + ast eqpf; + ast P = arg(pivot1,1); + ast Ploc = localize_term(P, rng, eqpf); + ast pPloc = make_hypothesis(Ploc); + ast pP = make_mp(make(Iff,Ploc,P),pPloc,eqpf); + ast rP = make_resolution(P,conj1,pP); + ast nP = mk_not(P); + ast nPloc = mk_not(Ploc); + ast neqpf = make_congruence(make(Iff,Ploc,P),make(Iff,nPloc,nP),eqpf); + ast npPloc = make_hypothesis(nPloc); + ast npP = make_mp(make(Iff,nPloc,nP),npPloc,neqpf); + ast nrP = make_resolution(nP,conj2,npP); + ast res = make_resolution(Ploc,rP,nrP); + return capture_localization(res); + } + + ast get_contra_coeff(const ast &f){ + ast c = arg(f,0); + // if(!is_not(arg(f,1))) + // c = make(Uminus,c); + return c; + } + + ast my_or(const ast &a, const ast &b){ + return mk_or(a,b); + } + + ast my_and(const ast &a, const ast &b){ + return mk_and(a,b); + } + + ast my_implies(const ast &a, const ast &b){ + return mk_implies(a,b); + } + + ast my_or(const std::vector &a){ + return mk_or(a); + } + + ast my_and(const std::vector &a){ + return mk_and(a); + } + + ast get_lit_atom(const ast &l){ + if(op(l) == Not) + return arg(l,0); + return l; + } + + bool is_placeholder(const ast &e){ + if(op(e) == Uninterpreted){ + std::string name = string_of_symbol(sym(e)); + if(name.size() > 2 && name[0] == '@' && name[1] == 'p') + return true; + } + return false; + } public: - iz3proof_itp_impl(prover *p, const prover::range &r, bool w) - : iz3proof_itp(*p) - { - pv = p; - rng = r; - weak = false ; //w; - type boolintbooldom[3] = {bool_type(),int_type(),bool_type()}; - type booldom[1] = {bool_type()}; - type boolbooldom[2] = {bool_type(),bool_type()}; - type boolboolbooldom[3] = {bool_type(),bool_type(),bool_type()}; - type intbooldom[2] = {int_type(),bool_type()}; - contra = function("@contra",2,boolbooldom,bool_type()); - m().inc_ref(contra); - sum = function("@sum",3,boolintbooldom,bool_type()); - m().inc_ref(sum); - rotate_sum = function("@rotsum",2,boolbooldom,bool_type()); - m().inc_ref(rotate_sum); - leq2eq = function("@leq2eq",3,boolboolbooldom,bool_type()); - m().inc_ref(leq2eq); - eq2leq = function("@eq2leq",2,boolbooldom,bool_type()); - m().inc_ref(eq2leq); - cong = function("@cong",3,boolintbooldom,bool_type()); - m().inc_ref(cong); - exmid = function("@exmid",3,boolboolbooldom,bool_type()); - m().inc_ref(exmid); - symm = function("@symm",1,booldom,bool_type()); - m().inc_ref(symm); - epsilon = make_var("@eps",int_type()); - modpon = function("@mp",3,boolboolbooldom,bool_type()); - m().inc_ref(modpon); - no_proof = make_var("@nop",bool_type()); - concat = function("@concat",2,boolbooldom,bool_type()); - m().inc_ref(concat); - top_pos = make_var("@top_pos",bool_type()); - add_pos = function("@add_pos",2,intbooldom,bool_type()); - m().inc_ref(add_pos); - rewrite_A = function("@rewrite_A",3,boolboolbooldom,bool_type()); - m().inc_ref(rewrite_A); - rewrite_B = function("@rewrite_B",3,boolboolbooldom,bool_type()); - m().inc_ref(rewrite_B); - normal_step = function("@normal_step",2,boolbooldom,bool_type()); - m().inc_ref(normal_step); - normal_chain = function("@normal_chain",2,boolbooldom,bool_type()); - m().inc_ref(normal_chain); - normal = function("@normal",2,boolbooldom,bool_type()); - m().inc_ref(normal); - sforall = function("@sforall",2,boolbooldom,bool_type()); - m().inc_ref(sforall); - sexists = function("@sexists",2,boolbooldom,bool_type()); - m().inc_ref(sexists); - } + iz3proof_itp_impl(prover *p, const prover::range &r, bool w) + : iz3proof_itp(*p) + { + pv = p; + rng = r; + weak = false ; //w; + type boolintbooldom[3] = {bool_type(),int_type(),bool_type()}; + type booldom[1] = {bool_type()}; + type boolbooldom[2] = {bool_type(),bool_type()}; + type boolboolbooldom[3] = {bool_type(),bool_type(),bool_type()}; + type intbooldom[2] = {int_type(),bool_type()}; + contra = function("@contra",2,boolbooldom,bool_type()); + m().inc_ref(contra); + sum = function("@sum",3,boolintbooldom,bool_type()); + m().inc_ref(sum); + rotate_sum = function("@rotsum",2,boolbooldom,bool_type()); + m().inc_ref(rotate_sum); + leq2eq = function("@leq2eq",3,boolboolbooldom,bool_type()); + m().inc_ref(leq2eq); + eq2leq = function("@eq2leq",2,boolbooldom,bool_type()); + m().inc_ref(eq2leq); + cong = function("@cong",3,boolintbooldom,bool_type()); + m().inc_ref(cong); + exmid = function("@exmid",3,boolboolbooldom,bool_type()); + m().inc_ref(exmid); + symm = function("@symm",1,booldom,bool_type()); + m().inc_ref(symm); + epsilon = make_var("@eps",int_type()); + modpon = function("@mp",3,boolboolbooldom,bool_type()); + m().inc_ref(modpon); + no_proof = make_var("@nop",bool_type()); + concat = function("@concat",2,boolbooldom,bool_type()); + m().inc_ref(concat); + top_pos = make_var("@top_pos",bool_type()); + add_pos = function("@add_pos",2,intbooldom,bool_type()); + m().inc_ref(add_pos); + rewrite_A = function("@rewrite_A",3,boolboolbooldom,bool_type()); + m().inc_ref(rewrite_A); + rewrite_B = function("@rewrite_B",3,boolboolbooldom,bool_type()); + m().inc_ref(rewrite_B); + normal_step = function("@normal_step",2,boolbooldom,bool_type()); + m().inc_ref(normal_step); + normal_chain = function("@normal_chain",2,boolbooldom,bool_type()); + m().inc_ref(normal_chain); + normal = function("@normal",2,boolbooldom,bool_type()); + m().inc_ref(normal); + sforall = function("@sforall",2,boolbooldom,bool_type()); + m().inc_ref(sforall); + sexists = function("@sexists",2,boolbooldom,bool_type()); + m().inc_ref(sexists); + } - ~iz3proof_itp_impl(){ - m().dec_ref(contra); - m().dec_ref(sum); - m().dec_ref(rotate_sum); - m().dec_ref(leq2eq); - m().dec_ref(eq2leq); - m().dec_ref(cong); - m().dec_ref(exmid); - m().dec_ref(symm); - m().dec_ref(modpon); - m().dec_ref(concat); - m().dec_ref(add_pos); - m().dec_ref(rewrite_A); - m().dec_ref(rewrite_B); - m().dec_ref(normal_step); - m().dec_ref(normal_chain); - m().dec_ref(normal); - m().dec_ref(sforall); - m().dec_ref(sexists); - } + ~iz3proof_itp_impl(){ + m().dec_ref(contra); + m().dec_ref(sum); + m().dec_ref(rotate_sum); + m().dec_ref(leq2eq); + m().dec_ref(eq2leq); + m().dec_ref(cong); + m().dec_ref(exmid); + m().dec_ref(symm); + m().dec_ref(modpon); + m().dec_ref(concat); + m().dec_ref(add_pos); + m().dec_ref(rewrite_A); + m().dec_ref(rewrite_B); + m().dec_ref(normal_step); + m().dec_ref(normal_chain); + m().dec_ref(normal); + m().dec_ref(sforall); + m().dec_ref(sexists); + } }; iz3proof_itp *iz3proof_itp::create(prover *p, const prover::range &r, bool w){ - return new iz3proof_itp_impl(p,r,w); + return new iz3proof_itp_impl(p,r,w); } diff --git a/src/interp/iz3proof_itp.h b/src/interp/iz3proof_itp.h index 4d76e3a92..e1e0de5cc 100644 --- a/src/interp/iz3proof_itp.h +++ b/src/interp/iz3proof_itp.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3proof.h + iz3proof.h -Abstract: + Abstract: - This class defines a simple interpolating proof system. + This class defines a simple interpolating proof system. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3PROOF_ITP_H #define IZ3PROOF_ITP_H @@ -32,110 +32,110 @@ Revision History: As opposed to iz3proof, this class directly computes interpolants, so the proof representation is just the interpolant itself. - */ +*/ class iz3proof_itp : public iz3mgr { public: - /** Enumeration of proof rules. */ - enum rule {Resolution,Assumption,Hypothesis,Theory,Axiom,Contra,Lemma,Reflexivity,Symmetry,Transitivity,Congruence,EqContra}; + /** Enumeration of proof rules. */ + enum rule {Resolution,Assumption,Hypothesis,Theory,Axiom,Contra,Lemma,Reflexivity,Symmetry,Transitivity,Congruence,EqContra}; - /** Interface to prover. */ - typedef iz3base prover; + /** Interface to prover. */ + typedef iz3base prover; - /** Ast type. */ - typedef prover::ast ast; + /** Ast type. */ + typedef prover::ast ast; - /** The type of proof nodes (just interpolants). */ - typedef ast node; + /** The type of proof nodes (just interpolants). */ + typedef ast node; - /** Object thrown in case of a proof error. */ - struct proof_error {}; + /** Object thrown in case of a proof error. */ + struct proof_error {}; - /** Make a resolution node with given pivot literal and premises. - The conclusion of premise1 should contain the negation of the - pivot literal, while the conclusion of premise2 should containe the - pivot literal. - */ - virtual node make_resolution(ast pivot, const std::vector &conc, node premise1, node premise2) = 0; + /** Make a resolution node with given pivot literal and premises. + The conclusion of premise1 should contain the negation of the + pivot literal, while the conclusion of premise2 should containe the + pivot literal. + */ + virtual node make_resolution(ast pivot, const std::vector &conc, node premise1, node premise2) = 0; - /** Make an assumption node. The given clause is assumed in the given frame. */ - virtual node make_assumption(int frame, const std::vector &assumption) = 0; + /** Make an assumption node. The given clause is assumed in the given frame. */ + virtual node make_assumption(int frame, const std::vector &assumption) = 0; - /** Make a hypothesis node. If phi is the hypothesis, this is - effectively phi |- phi. */ - virtual node make_hypothesis(const ast &hypothesis) = 0; + /** Make a hypothesis node. If phi is the hypothesis, this is + effectively phi |- phi. */ + virtual node make_hypothesis(const ast &hypothesis) = 0; - /** Make an axiom node. The conclusion must be an instance of an axiom. */ - virtual node make_axiom(const std::vector &conclusion) = 0; + /** Make an axiom node. The conclusion must be an instance of an axiom. */ + virtual node make_axiom(const std::vector &conclusion) = 0; - /** Make an axiom node. The conclusion must be an instance of an axiom. Localize axiom instance to range*/ - virtual node make_axiom(const std::vector &conclusion, prover::range) = 0; + /** Make an axiom node. The conclusion must be an instance of an axiom. Localize axiom instance to range*/ + virtual node make_axiom(const std::vector &conclusion, prover::range) = 0; - /** Make a Contra node. This rule takes a derivation of the form - Gamma |- False and produces |- \/~Gamma. */ + /** Make a Contra node. This rule takes a derivation of the form + Gamma |- False and produces |- \/~Gamma. */ - virtual node make_contra(node prem, const std::vector &conclusion) = 0; + virtual node make_contra(node prem, const std::vector &conclusion) = 0; - /** Make a Reflexivity node. This rule produces |- x = x */ + /** Make a Reflexivity node. This rule produces |- x = x */ - virtual node make_reflexivity(ast con) = 0; + virtual node make_reflexivity(ast con) = 0; - /** Make a Symmetry node. This takes a derivation of |- x = y and - produces | y = x */ + /** Make a Symmetry node. This takes a derivation of |- x = y and + produces | y = x */ - virtual node make_symmetry(ast con, const ast &premcon, node prem) = 0; + virtual node make_symmetry(ast con, const ast &premcon, node prem) = 0; - /** Make a transitivity node. This takes derivations of |- x = y - and |- y = z produces | x = z */ + /** Make a transitivity node. This takes derivations of |- x = y + and |- y = z produces | x = z */ - virtual node make_transitivity(const ast &x, const ast &y, const ast &z, node prem1, node prem2) = 0; + virtual node make_transitivity(const ast &x, const ast &y, const ast &z, node prem1, node prem2) = 0; - /** Make a congruence node. This takes a derivation of |- x_i = y_i - and produces |- f(...x_i,...) = f(...,y_i,...) */ + /** Make a congruence node. This takes a derivation of |- x_i = y_i + and produces |- f(...x_i,...) = f(...,y_i,...) */ - virtual node make_congruence(const ast &xi_eq_yi, const ast &con, const ast &prem1) = 0; + virtual node make_congruence(const ast &xi_eq_yi, const ast &con, const ast &prem1) = 0; - /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,... - and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */ + /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,... + and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */ - virtual node make_congruence(const std::vector &xi_eq_yi, const ast &con, const std::vector &prems) = 0; + virtual node make_congruence(const std::vector &xi_eq_yi, const ast &con, const std::vector &prems) = 0; - /** Make a modus-ponens node. This takes derivations of |- x - and |- x = y and produces |- y */ + /** Make a modus-ponens node. This takes derivations of |- x + and |- x = y and produces |- y */ - virtual node make_mp(const ast &x_eq_y, const ast &prem1, const ast &prem2) = 0; + virtual node make_mp(const ast &x_eq_y, const ast &prem1, const ast &prem2) = 0; - /** Make a farkas proof node. */ + /** Make a farkas proof node. */ - virtual node make_farkas(ast con, const std::vector &prems, const std::vector &prem_cons, const std::vector &coeffs) = 0; + virtual node make_farkas(ast con, const std::vector &prems, const std::vector &prem_cons, const std::vector &coeffs) = 0; - /* Make an axiom instance of the form |- x<=y, y<= x -> x =y */ - virtual node make_leq2eq(ast x, ast y, const ast &xleqy, const ast &yleqx) = 0; + /* Make an axiom instance of the form |- x<=y, y<= x -> x =y */ + virtual node make_leq2eq(ast x, ast y, const ast &xleqy, const ast &yleqx) = 0; - /* Make an axiom instance of the form |- x = y -> x <= y */ - virtual node make_eq2leq(ast x, ast y, const ast &xeqy) = 0; + /* Make an axiom instance of the form |- x = y -> x <= y */ + virtual node make_eq2leq(ast x, ast y, const ast &xeqy) = 0; - /* Make an inference of the form t <= c |- t/d <= floor(c/d) where t - is an affine term divisble by d and c is an integer constant */ - virtual node make_cut_rule(const ast &tleqc, const ast &d, const ast &con, const ast &prem) = 0; + /* Make an inference of the form t <= c |- t/d <= floor(c/d) where t + is an affine term divisble by d and c is an integer constant */ + virtual node make_cut_rule(const ast &tleqc, const ast &d, const ast &con, const ast &prem) = 0; - /* Return an interpolant from a proof of false */ - virtual ast interpolate(const node &pf) = 0; + /* Return an interpolant from a proof of false */ + virtual ast interpolate(const node &pf) = 0; - /** Create proof object to construct an interpolant. */ - static iz3proof_itp *create(prover *p, const prover::range &r, bool _weak); + /** Create proof object to construct an interpolant. */ + static iz3proof_itp *create(prover *p, const prover::range &r, bool _weak); protected: - iz3proof_itp(iz3mgr &m) - : iz3mgr(m) - { - } + iz3proof_itp(iz3mgr &m) + : iz3mgr(m) + { + } public: - virtual ~iz3proof_itp(){ - } + virtual ~iz3proof_itp(){ + } }; #endif diff --git a/src/interp/iz3scopes.cpp b/src/interp/iz3scopes.cpp index 9c08a0e31..c365619b2 100755 --- a/src/interp/iz3scopes.cpp +++ b/src/interp/iz3scopes.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3scopes.cpp + iz3scopes.cpp -Abstract: + Abstract: - Calculations with scopes, for both sequence and tree interpolation. + Calculations with scopes, for both sequence and tree interpolation. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #include @@ -26,294 +26,294 @@ Revision History: /** computes the least common ancestor of two nodes in the tree, or SHRT_MAX if none */ int scopes::tree_lca(int n1, int n2){ - if(!tree_mode()) - return std::max(n1,n2); - if(n1 == SHRT_MIN) return n2; - if(n2 == SHRT_MIN) return n1; - if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX; - while(n1 != n2){ + if(!tree_mode()) + return std::max(n1,n2); + if(n1 == SHRT_MIN) return n2; + if(n2 == SHRT_MIN) return n1; if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX; - assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size()); - if(n1 < n2) n1 = parents[n1]; - else n2 = parents[n2]; - } - return n1; + while(n1 != n2){ + if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX; + assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size()); + if(n1 < n2) n1 = parents[n1]; + else n2 = parents[n2]; + } + return n1; } /** computes the greatest common descendant two nodes in the tree, or SHRT_MIN if none */ int scopes::tree_gcd(int n1, int n2){ - if(!tree_mode()) - return std::min(n1,n2); - int foo = tree_lca(n1,n2); - if(foo == n1) return n2; - if(foo == n2) return n1; - return SHRT_MIN; + if(!tree_mode()) + return std::min(n1,n2); + int foo = tree_lca(n1,n2); + if(foo == n1) return n2; + if(foo == n2) return n1; + return SHRT_MIN; } #ifndef FULL_TREE /** test whether a tree node is contained in a range */ bool scopes::in_range(int n, const range &rng){ - return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n; + return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n; } /** test whether two ranges of tree nodes intersect */ bool scopes::ranges_intersect(const range &rng1, const range &rng2){ - return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi; + return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi; } bool scopes::range_contained(const range &rng1, const range &rng2){ - return tree_lca(rng2.lo,rng1.lo) == rng1.lo - && tree_lca(rng1.hi,rng2.hi) == rng2.hi; + return tree_lca(rng2.lo,rng1.lo) == rng1.lo + && tree_lca(rng1.hi,rng2.hi) == rng2.hi; } scopes::range scopes::range_lub(const range &rng1, const range &rng2){ - range res; - res.lo = tree_gcd(rng1.lo,rng2.lo); - res.hi = tree_lca(rng1.hi,rng2.hi); - return res; + range res; + res.lo = tree_gcd(rng1.lo,rng2.lo); + res.hi = tree_lca(rng1.hi,rng2.hi); + return res; } scopes::range scopes::range_glb(const range &rng1, const range &rng2){ - range res; - res.lo = tree_lca(rng1.lo,rng2.lo); - res.hi = tree_gcd(rng1.hi,rng2.hi); - return res; + range res; + res.lo = tree_lca(rng1.lo,rng2.lo); + res.hi = tree_gcd(rng1.hi,rng2.hi); + return res; } #else - namespace std { +namespace std { template <> - class hash { - public: - size_t operator()(const scopes::range_lo &p) const { + class hash { + public: + size_t operator()(const scopes::range_lo &p) const { return p.lo + (size_t)p.next; - } - }; - } + } + }; +} - template <> inline - size_t stdext::hash_value(const scopes::range_lo& p) - { - std::hash h; - return h(p); - } +template <> inline +size_t stdext::hash_value(const scopes::range_lo& p) +{ + std::hash h; + return h(p); +} - namespace std { +namespace std { template <> - class less { - public: - bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const { - return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next; - } - }; - } + class less { + public: + bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const { + return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next; + } + }; +} - struct range_op { - scopes::range_lo *x, *y; - int hi; - range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){ - x = _x; y = _y; hi = _hi; - } - }; +struct range_op { + scopes::range_lo *x, *y; + int hi; + range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){ + x = _x; y = _y; hi = _hi; + } +}; - namespace std { +namespace std { template <> - class hash { - public: - size_t operator()(const range_op &p) const { + class hash { + public: + size_t operator()(const range_op &p) const { return (size_t) p.x + (size_t)p.y + p.hi; - } - }; - } + } + }; +} - template <> inline - size_t stdext::hash_value(const range_op& p) - { - std::hash h; - return h(p); - } +template <> inline +size_t stdext::hash_value(const range_op& p) +{ + std::hash h; + return h(p); +} - namespace std { +namespace std { template <> - class less { - public: - bool operator()(const range_op &x, const range_op &y) const { - return (size_t)x.x < (size_t)y.x || x.x == y.x && - ((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi); - } - }; - } + class less { + public: + bool operator()(const range_op &x, const range_op &y) const { + return (size_t)x.x < (size_t)y.x || x.x == y.x && + ((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi); + } + }; +} - struct range_tables { - hash_map unique; - hash_map lub; - hash_map glb; - }; +struct range_tables { + hash_map unique; + hash_map lub; + hash_map glb; +}; - scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){ - range_lo foo(lo,next); - std::pair baz(foo,(range_lo *)0); - std::pair::iterator,bool> bar = rt->unique.insert(baz); - if(bar.second) - bar.first->second = new range_lo(lo,next); - return bar.first->second; - //std::pair::iterator,bool> bar = rt->unique.insert(foo); - // const range_lo *baz = &*(bar.first); - // return (range_lo *)baz; // coerce const - } +scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){ + range_lo foo(lo,next); + std::pair baz(foo,(range_lo *)0); + std::pair::iterator,bool> bar = rt->unique.insert(baz); + if(bar.second) + bar.first->second = new range_lo(lo,next); + return bar.first->second; + //std::pair::iterator,bool> bar = rt->unique.insert(foo); + // const range_lo *baz = &*(bar.first); + // return (range_lo *)baz; // coerce const +} - scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){ +scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){ if(!rng1) return rng2; if(!rng2) return rng1; if(rng1->lo > rng2->lo) - std::swap(rng1,rng2); - std::pair foo(range_op(rng1,rng2,0),(range_lo *)0); - std::pair::iterator,bool> bar = rt->lub.insert(foo); - range_lo *&res = bar.first->second; - if(!bar.second) return res; + std::swap(rng1,rng2); + std::pair foo(range_op(rng1,rng2,0),(range_lo *)0); + std::pair::iterator,bool> bar = rt->lub.insert(foo); + range_lo *&res = bar.first->second; + if(!bar.second) return res; if(!(rng1->next && rng1->next->lo <= rng2->lo)){ - for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo]) - if(lo == rng2->lo) - {rng2 = rng2->next; break;} + for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo]) + if(lo == rng2->lo) + {rng2 = rng2->next; break;} } range_lo *baz = range_lub_lo(rng1->next,rng2); res = find_range_lo(rng1->lo,baz); - return res; - } + return res; +} - scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){ - if(!rng1) return rng1; - if(!rng2) return rng2; - if(rng1->lo > rng2->lo) - std::swap(rng1,rng2); - std::pair cand(range_op(rng1,rng2,hi),(range_lo *)0); - std::pair::iterator,bool> bar = rt->glb.insert(cand); - range_lo *&res = bar.first->second; - if(!bar.second) return res; - range_lo *foo; - if(!(rng1->next && rng1->next->lo <= rng2->lo)){ - int lim = hi; - if(rng1->next) lim = std::min(lim,rng1->next->lo); - int a = rng1->lo, b = rng2->lo; - while(a != b && b <= lim){ - a = parents[a]; - if(a > b)std::swap(a,b); - } - if(a == b && b <= lim){ - foo = range_glb_lo(rng1->next,rng2->next,hi); - foo = find_range_lo(b,foo); - } - else - foo = range_glb_lo(rng2,rng1->next,hi); - } - else foo = range_glb_lo(rng1->next,rng2,hi); - res = foo; - return res; - } +scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){ + if(!rng1) return rng1; + if(!rng2) return rng2; + if(rng1->lo > rng2->lo) + std::swap(rng1,rng2); + std::pair cand(range_op(rng1,rng2,hi),(range_lo *)0); + std::pair::iterator,bool> bar = rt->glb.insert(cand); + range_lo *&res = bar.first->second; + if(!bar.second) return res; + range_lo *foo; + if(!(rng1->next && rng1->next->lo <= rng2->lo)){ + int lim = hi; + if(rng1->next) lim = std::min(lim,rng1->next->lo); + int a = rng1->lo, b = rng2->lo; + while(a != b && b <= lim){ + a = parents[a]; + if(a > b)std::swap(a,b); + } + if(a == b && b <= lim){ + foo = range_glb_lo(rng1->next,rng2->next,hi); + foo = find_range_lo(b,foo); + } + else + foo = range_glb_lo(rng2,rng1->next,hi); + } + else foo = range_glb_lo(rng1->next,rng2,hi); + res = foo; + return res; +} - /** computes the lub (smallest containing subtree) of two ranges */ - scopes::range scopes::range_lub(const range &rng1, const range &rng2){ +/** computes the lub (smallest containing subtree) of two ranges */ +scopes::range scopes::range_lub(const range &rng1, const range &rng2){ int hi = tree_lca(rng1.hi,rng2.hi); - if(hi == SHRT_MAX) return range_full(); + if(hi == SHRT_MAX) return range_full(); range_lo *lo = range_lub_lo(rng1.lo,rng2.lo); return range(hi,lo); - } +} - /** computes the glb (intersection) of two ranges */ - scopes::range scopes::range_glb(const range &rng1, const range &rng2){ - if(rng1.hi == SHRT_MAX) return rng2; - if(rng2.hi == SHRT_MAX) return rng1; +/** computes the glb (intersection) of two ranges */ +scopes::range scopes::range_glb(const range &rng1, const range &rng2){ + if(rng1.hi == SHRT_MAX) return rng2; + if(rng2.hi == SHRT_MAX) return rng1; int hi = tree_gcd(rng1.hi,rng2.hi); range_lo *lo = hi == SHRT_MIN ? 0 : range_glb_lo(rng1.lo,rng2.lo,hi); - if(!lo) hi = SHRT_MIN; + if(!lo) hi = SHRT_MIN; return range(hi,lo); - } +} - /** is this range empty? */ - bool scopes::range_is_empty(const range &rng){ +/** is this range empty? */ +bool scopes::range_is_empty(const range &rng){ return rng.hi == SHRT_MIN; - } +} - /** return an empty range */ - scopes::range scopes::range_empty(){ +/** return an empty range */ +scopes::range scopes::range_empty(){ return range(SHRT_MIN,0); - } +} - /** return a full range */ - scopes::range scopes::range_full(){ +/** return a full range */ +scopes::range scopes::range_full(){ return range(SHRT_MAX,0); - } +} - /** return the maximal element of a range */ - int scopes::range_max(const range &rng){ +/** return the maximal element of a range */ +int scopes::range_max(const range &rng){ return rng.hi; - } +} - /** return a minimal (not necessarily unique) element of a range */ - int scopes::range_min(const range &rng){ - if(rng.hi == SHRT_MAX) return SHRT_MIN; +/** return a minimal (not necessarily unique) element of a range */ +int scopes::range_min(const range &rng){ + if(rng.hi == SHRT_MAX) return SHRT_MIN; return rng.lo ? rng.lo->lo : SHRT_MAX; - } +} - /** return range consisting of downward closure of a point */ - scopes::range scopes::range_downward(int _hi){ +/** return range consisting of downward closure of a point */ +scopes::range scopes::range_downward(int _hi){ std::vector descendants(parents.size()); for(int i = descendants.size() - 1; i >= 0 ; i--) - descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]]; + descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]]; for(unsigned i = 0; i < descendants.size() - 1; i++) - if(parents[i] < parents.size()) - descendants[parents[i]] = false; + if(parents[i] < parents.size()) + descendants[parents[i]] = false; range_lo *foo = 0; for(int i = descendants.size() - 1; i >= 0; --i) - if(descendants[i]) foo = find_range_lo(i,foo); + if(descendants[i]) foo = find_range_lo(i,foo); return range(_hi,foo); - } +} - /** add an element to a range */ - void scopes::range_add(int i, range &n){ +/** add an element to a range */ +void scopes::range_add(int i, range &n){ range foo = range(i, find_range_lo(i,0)); n = range_lub(foo,n); - } +} - /** Choose an element of rng1 that is near to rng2 */ - int scopes::range_near(const range &rng1, const range &rng2){ +/** Choose an element of rng1 that is near to rng2 */ +int scopes::range_near(const range &rng1, const range &rng2){ int frame; int thing = tree_lca(rng1.hi,rng2.hi); - if(thing != rng1.hi) return rng1.hi; - range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0)); - line = range_glb(line,rng1); - return range_min(line); - } + if(thing != rng1.hi) return rng1.hi; + range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0)); + line = range_glb(line,rng1); + return range_min(line); +} - /** test whether a tree node is contained in a range */ - bool scopes::in_range(int n, const range &rng){ - range r = range_empty(); - range_add(n,r); - r = range_glb(rng,r); - return !range_is_empty(r); - } +/** test whether a tree node is contained in a range */ +bool scopes::in_range(int n, const range &rng){ + range r = range_empty(); + range_add(n,r); + r = range_glb(rng,r); + return !range_is_empty(r); +} - /** test whether two ranges of tree nodes intersect */ - bool scopes::ranges_intersect(const range &rng1, const range &rng2){ - range r = range_glb(rng1,rng2); - return !range_is_empty(r); - } +/** test whether two ranges of tree nodes intersect */ +bool scopes::ranges_intersect(const range &rng1, const range &rng2){ + range r = range_glb(rng1,rng2); + return !range_is_empty(r); +} - bool scopes::range_contained(const range &rng1, const range &rng2){ - range r = range_glb(rng1,rng2); - return r.hi == rng1.hi && r.lo == rng1.lo; - } +bool scopes::range_contained(const range &rng1, const range &rng2){ + range r = range_glb(rng1,rng2); + return r.hi == rng1.hi && r.lo == rng1.lo; +} #endif diff --git a/src/interp/iz3scopes.h b/src/interp/iz3scopes.h index bf93f4726..38f9e2292 100755 --- a/src/interp/iz3scopes.h +++ b/src/interp/iz3scopes.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3scopes.h + iz3scopes.h -Abstract: + Abstract: - Calculations with scopes, for both sequence and tree interpolation. + Calculations with scopes, for both sequence and tree interpolation. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3SOPES_H @@ -28,174 +28,174 @@ Revision History: class scopes { public: - /** Construct from parents vector. */ - scopes(const std::vector &_parents){ - parents = _parents; - } - - scopes(){ - } - - void initialize(const std::vector &_parents){ - parents = _parents; - } - - /** The parents vector defining the tree structure */ - std::vector parents; - - // #define FULL_TREE -#ifndef FULL_TREE - struct range { - range(){ - lo = SHRT_MAX; - hi = SHRT_MIN; + /** Construct from parents vector. */ + scopes(const std::vector &_parents){ + parents = _parents; } - short lo, hi; - }; - /** computes the lub (smallest containing subtree) of two ranges */ - range range_lub(const range &rng1, const range &rng2); + scopes(){ + } - /** computes the glb (intersection) of two ranges */ - range range_glb(const range &rng1, const range &rng2); + void initialize(const std::vector &_parents){ + parents = _parents; + } - /** is this range empty? */ - bool range_is_empty(const range &rng){ - return rng.hi < rng.lo; - } + /** The parents vector defining the tree structure */ + std::vector parents; - /** is this range full? */ - bool range_is_full(const range &rng){ - return rng.lo == SHRT_MIN && rng.hi == SHRT_MAX; - } + // #define FULL_TREE +#ifndef FULL_TREE + struct range { + range(){ + lo = SHRT_MAX; + hi = SHRT_MIN; + } + short lo, hi; + }; - /** return an empty range */ - range range_empty(){ - range res; - res.lo = SHRT_MAX; - res.hi = SHRT_MIN; - return res; - } + /** computes the lub (smallest containing subtree) of two ranges */ + range range_lub(const range &rng1, const range &rng2); + + /** computes the glb (intersection) of two ranges */ + range range_glb(const range &rng1, const range &rng2); - /** return an empty range */ - range range_full(){ - range res; - res.lo = SHRT_MIN; - res.hi = SHRT_MAX; - return res; - } + /** is this range empty? */ + bool range_is_empty(const range &rng){ + return rng.hi < rng.lo; + } - /** return the maximal element of a range */ - int range_max(const range &rng){ - return rng.hi; - } + /** is this range full? */ + bool range_is_full(const range &rng){ + return rng.lo == SHRT_MIN && rng.hi == SHRT_MAX; + } - /** return a minimal (not necessarily unique) element of a range */ - int range_min(const range &rng){ - return rng.lo; - } + /** return an empty range */ + range range_empty(){ + range res; + res.lo = SHRT_MAX; + res.hi = SHRT_MIN; + return res; + } - /** return range consisting of downward closure of a point */ - range range_downward(int _hi){ - range foo; - foo.lo = SHRT_MIN; - foo.hi = _hi; - return foo; - } + /** return an empty range */ + range range_full(){ + range res; + res.lo = SHRT_MIN; + res.hi = SHRT_MAX; + return res; + } - void range_add(int i, range &n){ + /** return the maximal element of a range */ + int range_max(const range &rng){ + return rng.hi; + } + + /** return a minimal (not necessarily unique) element of a range */ + int range_min(const range &rng){ + return rng.lo; + } + + /** return range consisting of downward closure of a point */ + range range_downward(int _hi){ + range foo; + foo.lo = SHRT_MIN; + foo.hi = _hi; + return foo; + } + + void range_add(int i, range &n){ #if 0 if(i < n.lo) n.lo = i; - if(i > n.hi) n.hi = i; + if(i > n.hi) n.hi = i; #else - range rng; rng.lo = i; rng.hi = i; - n = range_lub(rng,n); + range rng; rng.lo = i; rng.hi = i; + n = range_lub(rng,n); #endif - } + } - /** Choose an element of rng1 that is near to rng2 */ - int range_near(const range &rng1, const range &rng2){ - int frame; - int thing = tree_lca(rng1.lo,rng2.hi); - if(thing == rng1.lo) frame = rng1.lo; - else frame = tree_gcd(thing,rng1.hi); + /** Choose an element of rng1 that is near to rng2 */ + int range_near(const range &rng1, const range &rng2){ + int frame; + int thing = tree_lca(rng1.lo,rng2.hi); + if(thing == rng1.lo) frame = rng1.lo; + else frame = tree_gcd(thing,rng1.hi); return frame; - } + } #else - struct range_lo { - int lo; - range_lo *next; - range_lo(int _lo, range_lo *_next){ - lo = _lo; - next = _next; - } - }; + struct range_lo { + int lo; + range_lo *next; + range_lo(int _lo, range_lo *_next){ + lo = _lo; + next = _next; + } + }; - struct range { - int hi; - range_lo *lo; - range(int _hi, range_lo *_lo){ - hi = _hi; - lo = _lo; - } - range(){ - hi = SHRT_MIN; - lo = 0; - } - }; + struct range { + int hi; + range_lo *lo; + range(int _hi, range_lo *_lo){ + hi = _hi; + lo = _lo; + } + range(){ + hi = SHRT_MIN; + lo = 0; + } + }; - range_tables *rt; + range_tables *rt; - /** computes the lub (smallest containing subtree) of two ranges */ - range range_lub(const range &rng1, const range &rng2); + /** computes the lub (smallest containing subtree) of two ranges */ + range range_lub(const range &rng1, const range &rng2); - /** computes the glb (intersection) of two ranges */ - range range_glb(const range &rng1, const range &rng2); + /** computes the glb (intersection) of two ranges */ + range range_glb(const range &rng1, const range &rng2); - /** is this range empty? */ - bool range_is_empty(const range &rng); + /** is this range empty? */ + bool range_is_empty(const range &rng); - /** return an empty range */ - range range_empty(); + /** return an empty range */ + range range_empty(); - /** return a full range */ - range range_full(); + /** return a full range */ + range range_full(); - /** return the maximal element of a range */ - int range_max(const range &rng); + /** return the maximal element of a range */ + int range_max(const range &rng); - /** return a minimal (not necessarily unique) element of a range */ - int range_min(const range &rng); + /** return a minimal (not necessarily unique) element of a range */ + int range_min(const range &rng); - /** return range consisting of downward closure of a point */ - range range_downward(int _hi); + /** return range consisting of downward closure of a point */ + range range_downward(int _hi); - /** add an element to a range */ - void range_add(int i, range &n); + /** add an element to a range */ + void range_add(int i, range &n); - /** Choose an element of rng1 that is near to rng2 */ - int range_near(const range &rng1, const range &rng2); + /** Choose an element of rng1 that is near to rng2 */ + int range_near(const range &rng1, const range &rng2); - range_lo *find_range_lo(int lo, range_lo *next); - range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2); - range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim); + range_lo *find_range_lo(int lo, range_lo *next); + range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2); + range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim); #endif - /** test whether a tree node is contained in a range */ - bool in_range(int n, const range &rng); + /** test whether a tree node is contained in a range */ + bool in_range(int n, const range &rng); - /** test whether two ranges of tree nodes intersect */ - bool ranges_intersect(const range &rng1, const range &rng2); + /** test whether two ranges of tree nodes intersect */ + bool ranges_intersect(const range &rng1, const range &rng2); - /** test whether range rng1 contained in range rng2 */ - bool range_contained(const range &rng1, const range &rng2); + /** test whether range rng1 contained in range rng2 */ + bool range_contained(const range &rng1, const range &rng2); private: - int tree_lca(int n1, int n2); - int tree_gcd(int n1, int n2); - bool tree_mode(){return parents.size() != 0;} + int tree_lca(int n1, int n2); + int tree_gcd(int n1, int n2); + bool tree_mode(){return parents.size() != 0;} @@ -205,17 +205,17 @@ class scopes { #ifndef FULL_TREE namespace hash_space { - template <> - class hash { - public: - size_t operator()(const scopes::range &p) const { - return (size_t)p.lo + (size_t)p.hi; - } - }; + template <> + class hash { + public: + size_t operator()(const scopes::range &p) const { + return (size_t)p.lo + (size_t)p.hi; + } + }; } inline bool operator==(const scopes::range &x, const scopes::range &y){ - return x.lo == y.lo && x.hi == y.hi; + return x.lo == y.lo && x.hi == y.hi; } #endif diff --git a/src/interp/iz3secondary.h b/src/interp/iz3secondary.h index 0eb1b9a93..46d080595 100755 --- a/src/interp/iz3secondary.h +++ b/src/interp/iz3secondary.h @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3secondary + iz3secondary -Abstract: + Abstract: - Interface for secondary provers. + Interface for secondary provers. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3SECONDARY_H @@ -28,11 +28,11 @@ Revision History: class iz3secondary : public iz3mgr { public: - virtual int interpolate(const std::vector &frames, std::vector &interpolants) = 0; - virtual ~iz3secondary(){} + virtual int interpolate(const std::vector &frames, std::vector &interpolants) = 0; + virtual ~iz3secondary(){} protected: - iz3secondary(const iz3mgr &mgr) : iz3mgr(mgr) {} + iz3secondary(const iz3mgr &mgr) : iz3mgr(mgr) {} }; diff --git a/src/interp/iz3translate.cpp b/src/interp/iz3translate.cpp index f65ec72d4..5b420673c 100755 --- a/src/interp/iz3translate.cpp +++ b/src/interp/iz3translate.cpp @@ -1,21 +1,21 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3translate.cpp + iz3translate.cpp -Abstract: + Abstract: - Translate a Z3 proof to in interpolated proof. + Translate a Z3 proof to in interpolated proof. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS #pragma warning(disable:4996) @@ -52,1973 +52,1973 @@ class iz3translation_full : public iz3translation { public: - typedef iz3proof_itp Iproof; + typedef iz3proof_itp Iproof; - Iproof *iproof; + Iproof *iproof; - /* Here we have lots of hash tables for memoizing various methods and - other such global data structures. - */ + /* Here we have lots of hash tables for memoizing various methods and + other such global data structures. + */ - typedef hash_map AstToInt; - AstToInt locality; // memoizes locality of Z3 proof terms + typedef hash_map AstToInt; + AstToInt locality; // memoizes locality of Z3 proof terms - typedef std::pair EquivEntry; - typedef hash_map EquivTab; - EquivTab equivs; // maps non-local terms to equivalent local terms, with proof + typedef std::pair EquivEntry; + typedef hash_map EquivTab; + EquivTab equivs; // maps non-local terms to equivalent local terms, with proof - typedef hash_set AstHashSet; - AstHashSet equivs_visited; // proofs already checked for equivalences + typedef hash_set AstHashSet; + AstHashSet equivs_visited; // proofs already checked for equivalences - typedef std::pair, hash_map > AstToIpf; - AstToIpf translation; // Z3 proof nodes to Iproof nodes + typedef std::pair, hash_map > AstToIpf; + AstToIpf translation; // Z3 proof nodes to Iproof nodes - int frames; // number of frames + int frames; // number of frames - typedef std::set AstSet; - typedef hash_map AstToAstSet; - AstToAstSet hyp_map; // map proof terms to hypothesis set + typedef std::set AstSet; + typedef hash_map AstToAstSet; + AstToAstSet hyp_map; // map proof terms to hypothesis set - struct LocVar { // localization vars - ast var; // a fresh variable - ast term; // term it represents - int frame; // frame in which it's defined - LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} - }; + struct LocVar { // localization vars + ast var; // a fresh variable + ast term; // term it represents + int frame; // frame in which it's defined + LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} + }; - std::vector localization_vars; // localization vars in order of creation - typedef hash_map AstToAst; - AstToAst localization_map; // maps terms to their localization vars + std::vector localization_vars; // localization vars in order of creation + typedef hash_map AstToAst; + AstToAst localization_map; // maps terms to their localization vars - typedef hash_map AstToBool; - AstToBool occurs_in_memo; // memo of occurs_in function + typedef hash_map AstToBool; + AstToBool occurs_in_memo; // memo of occurs_in function - AstHashSet cont_eq_memo; // memo of cont_eq function + AstHashSet cont_eq_memo; // memo of cont_eq function - AstToAst subst_memo; // memo of subst function + AstToAst subst_memo; // memo of subst function - symb commute; + symb commute; - public: +public: #define from_ast(x) (x) - // #define NEW_LOCALITY + // #define NEW_LOCALITY #ifdef NEW_LOCALITY - range rng; // the range of frames in the "A" part of the interpolant + range rng; // the range of frames in the "A" part of the interpolant #endif - /* To handle skolemization, we have to scan the proof for skolem - symbols and assign each to a frame. THe assignment is heuristic. - */ + /* To handle skolemization, we have to scan the proof for skolem + symbols and assign each to a frame. THe assignment is heuristic. + */ - int scan_skolems_rec(hash_map &memo, const ast &proof, int frame){ - std::pair foo(proof,INT_MAX); - std::pair bar = memo.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - pfrule dk = pr(proof); - if(dk == PR_ASSERTED){ - ast ass = conc(proof); - res = frame_of_assertion(ass); + int scan_skolems_rec(hash_map &memo, const ast &proof, int frame){ + std::pair foo(proof,INT_MAX); + std::pair bar = memo.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + pfrule dk = pr(proof); + if(dk == PR_ASSERTED){ + ast ass = conc(proof); + res = frame_of_assertion(ass); + } + else if(dk == PR_SKOLEMIZE){ + ast quanted = arg(conc(proof),0); + if(op(quanted) == Not) + quanted = arg(quanted,0); + // range r = ast_range(quanted); + // if(range_is_empty(r)) + range r = ast_scope(quanted); + if(range_is_empty(r)) + throw "can't skolemize"; + if(frame == INT_MAX || !in_range(frame,r)) + frame = range_max(r); // this is desperation -- may fail + if(frame >= frames) frame = frames - 1; + add_frame_range(frame,arg(conc(proof),1)); + r = ast_scope(arg(conc(proof),1)); + } + else if(dk==PR_MODUS_PONENS_OEQ){ + frame = scan_skolems_rec(memo,prem(proof,0),frame); + scan_skolems_rec(memo,prem(proof,1),frame); + } + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + int bar = scan_skolems_rec(memo,prem(proof,i),frame); + if(res == INT_MAX || res == bar) res = bar; + else if(bar != INT_MAX) res = -1; + } + } + return res; } - else if(dk == PR_SKOLEMIZE){ - ast quanted = arg(conc(proof),0); - if(op(quanted) == Not) - quanted = arg(quanted,0); - // range r = ast_range(quanted); - // if(range_is_empty(r)) - range r = ast_scope(quanted); - if(range_is_empty(r)) - throw "can't skolemize"; - if(frame == INT_MAX || !in_range(frame,r)) - frame = range_max(r); // this is desperation -- may fail - if(frame >= frames) frame = frames - 1; - add_frame_range(frame,arg(conc(proof),1)); - r = ast_scope(arg(conc(proof),1)); - } - else if(dk==PR_MODUS_PONENS_OEQ){ - frame = scan_skolems_rec(memo,prem(proof,0),frame); - scan_skolems_rec(memo,prem(proof,1),frame); - } - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - int bar = scan_skolems_rec(memo,prem(proof,i),frame); - if(res == INT_MAX || res == bar) res = bar; - else if(bar != INT_MAX) res = -1; - } - } - return res; - } - void scan_skolems(const ast &proof){ - hash_map memo; - scan_skolems_rec(memo,proof, INT_MAX); - } + void scan_skolems(const ast &proof){ + hash_map memo; + scan_skolems_rec(memo,proof, INT_MAX); + } - // determine locality of a proof term - // return frame of derivation if local, or -1 if not - // result INT_MAX means the proof term is a tautology - // memoized in hash_map "locality" + // determine locality of a proof term + // return frame of derivation if local, or -1 if not + // result INT_MAX means the proof term is a tautology + // memoized in hash_map "locality" - int get_locality_rec(ast proof){ - std::pair foo(proof,INT_MAX); - std::pair bar = locality.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - pfrule dk = pr(proof); - if(dk == PR_ASSERTED){ - ast ass = conc(proof); - res = frame_of_assertion(ass); + int get_locality_rec(ast proof){ + std::pair foo(proof,INT_MAX); + std::pair bar = locality.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + pfrule dk = pr(proof); + if(dk == PR_ASSERTED){ + ast ass = conc(proof); + res = frame_of_assertion(ass); #ifdef NEW_LOCALITY - if(in_range(res,rng)) - res = range_max(rng); - else - res = frames-1; + if(in_range(res,rng)) + res = range_max(rng); + else + res = frames-1; #endif - } - else if(dk == PR_QUANT_INST){ - std::vector lits; - ast con = conc(proof); - get_Z3_lits(con, lits); - iproof->make_axiom(lits); - } + } + else if(dk == PR_QUANT_INST){ + std::vector lits; + ast con = conc(proof); + get_Z3_lits(con, lits); + iproof->make_axiom(lits); + } #ifdef LOCALIZATION_KLUDGE - else if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST - && get_locality_rec(prem(proof,1)) == INT_MAX){ - std::vector lits; - ast con = conc(proof); - get_Z3_lits(con, lits); - iproof->make_axiom(lits); - } + else if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST + && get_locality_rec(prem(proof,1)) == INT_MAX){ + std::vector lits; + ast con = conc(proof); + get_Z3_lits(con, lits); + iproof->make_axiom(lits); + } #endif - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - int bar = get_locality_rec(arg); - if(res == INT_MAX || res == bar) res = bar; - else if(bar != INT_MAX) res = -1; - } + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + int bar = get_locality_rec(arg); + if(res == INT_MAX || res == bar) res = bar; + else if(bar != INT_MAX) res = -1; + } + } + return res; } - return res; - } - int get_locality(ast proof){ - // if(lia_z3_axioms_only) return -1; - int res = get_locality_rec(proof); - if(res != -1){ - ast con = conc(proof); - range rng = ast_scope(con); + int get_locality(ast proof){ + // if(lia_z3_axioms_only) return -1; + int res = get_locality_rec(proof); + if(res != -1){ + ast con = conc(proof); + range rng = ast_scope(con); - // hack: if a clause contains "true", it reduces to "true", - // which means we won't compute the range correctly. we handle - // this case by computing the ranges of the literals separately + // hack: if a clause contains "true", it reduces to "true", + // which means we won't compute the range correctly. we handle + // this case by computing the ranges of the literals separately - if(is_true(con)){ - std::vector lits; - get_Z3_lits(conc(proof),lits); - for(unsigned i = 0; i < lits.size(); i++) - rng = range_glb(rng,ast_scope(lits[i])); - } + if(is_true(con)){ + std::vector lits; + get_Z3_lits(conc(proof),lits); + for(unsigned i = 0; i < lits.size(); i++) + rng = range_glb(rng,ast_scope(lits[i])); + } - if(!range_is_empty(rng)){ - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ - ast hyp = *it; - rng = range_glb(rng,ast_scope(hyp)); - } - } + if(!range_is_empty(rng)){ + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ + ast hyp = *it; + rng = range_glb(rng,ast_scope(hyp)); + } + } - if(res == INT_MAX){ - if(range_is_empty(rng)) - res = -1; - else res = range_max(rng); - } - else { - if(!in_range(res,rng)) - res = -1; - } + if(res == INT_MAX){ + if(range_is_empty(rng)) + res = -1; + else res = range_max(rng); + } + else { + if(!in_range(res,rng)) + res = -1; + } + } + return res; } - return res; - } - AstSet &get_hyps(ast proof){ - std::pair foo(proof,AstSet()); - std::pair bar = hyp_map.insert(foo); - AstSet &res = bar.first->second; - if(!bar.second) return res; - pfrule dk = pr(proof); - if(dk == PR_HYPOTHESIS){ - ast con = conc(proof); - res.insert(con); - } - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - AstSet &arg_hyps = get_hyps(arg); - res.insert(arg_hyps.begin(),arg_hyps.end()); - } - if(dk == PR_LEMMA){ - ast con = conc(proof); - res.erase(mk_not(con)); - if(is_or(con)){ - int clause_size = num_args(con); - for(int i = 0; i < clause_size; i++){ - ast neglit = mk_not(arg(con,i)); - res.erase(neglit); - } - } - } - } + AstSet &get_hyps(ast proof){ + std::pair foo(proof,AstSet()); + std::pair bar = hyp_map.insert(foo); + AstSet &res = bar.first->second; + if(!bar.second) return res; + pfrule dk = pr(proof); + if(dk == PR_HYPOTHESIS){ + ast con = conc(proof); + res.insert(con); + } + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + AstSet &arg_hyps = get_hyps(arg); + res.insert(arg_hyps.begin(),arg_hyps.end()); + } + if(dk == PR_LEMMA){ + ast con = conc(proof); + res.erase(mk_not(con)); + if(is_or(con)){ + int clause_size = num_args(con); + for(int i = 0; i < clause_size; i++){ + ast neglit = mk_not(arg(con,i)); + res.erase(neglit); + } + } + } + } #if 0 - AstSet::iterator it = res.begin(), en = res.end(); - if(it != en){ - AstSet::iterator old = it; - ++it; - for(; it != en; ++it, ++old) - if(!(*old < *it)) - std::cout << "foo!"; - } + AstSet::iterator it = res.begin(), en = res.end(); + if(it != en){ + AstSet::iterator old = it; + ++it; + for(; it != en; ++it, ++old) + if(!(*old < *it)) + std::cout << "foo!"; + } #endif - return res; - } - - // Find all the judgements of the form p <-> q, where - // p is local and q is non-local, recording them in "equivs" - // the map equivs_visited is used to record the already visited proof terms - - void find_equivs(ast proof){ - if(equivs_visited.find(proof) != equivs_visited.end()) - return; - equivs_visited.insert(proof); - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++) // do all the sub_terms - find_equivs(prem(proof,i)); - ast con = conc(proof); // get the conclusion - if(is_iff(con)){ - ast iff = con; - for(int i = 0; i < 2; i++) - if(!is_local(arg(iff,i)) && is_local(arg(iff,1-i))){ - std::pair > foo(arg(iff,i),std::pair(arg(iff,1-i),proof)); - equivs.insert(foo); - } + return res; } - } - // get the lits of a Z3 clause - void get_Z3_lits(ast t, std::vector &lits){ - opr dk = op(t); - if(dk == False) - return; // false = empty clause - if(dk == Or){ - unsigned nargs = num_args(t); - lits.resize(nargs); - for(unsigned i = 0; i < nargs; i++) // do all the sub_terms - lits[i] = arg(t,i); - } - else { - lits.push_back(t); - } - } + // Find all the judgements of the form p <-> q, where + // p is local and q is non-local, recording them in "equivs" + // the map equivs_visited is used to record the already visited proof terms - // resolve two clauses represented as vectors of lits. replace first clause - void resolve(ast pivot, std::vector &cls1, std::vector &cls2){ - ast neg_pivot = mk_not(pivot); - for(unsigned i = 0; i < cls1.size(); i++){ - if(cls1[i] == pivot){ - cls1[i] = cls1.back(); - cls1.pop_back(); - bool found_pivot2 = false; - for(unsigned j = 0; j < cls2.size(); j++){ - if(cls2[j] == neg_pivot) - found_pivot2 = true; - else - cls1.push_back(cls2[j]); - } - assert(found_pivot2); - return; - } + void find_equivs(ast proof){ + if(equivs_visited.find(proof) != equivs_visited.end()) + return; + equivs_visited.insert(proof); + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++) // do all the sub_terms + find_equivs(prem(proof,i)); + ast con = conc(proof); // get the conclusion + if(is_iff(con)){ + ast iff = con; + for(int i = 0; i < 2; i++) + if(!is_local(arg(iff,i)) && is_local(arg(iff,1-i))){ + std::pair > foo(arg(iff,i),std::pair(arg(iff,1-i),proof)); + equivs.insert(foo); + } + } } - assert(0 && "resolve failed"); - } - // get lits resulting from unit resolution up to and including "position" - // TODO: this is quadratic -- fix it - void do_unit_resolution(ast proof, int position, std::vector &lits){ - ast orig_clause = conc(prem(proof,0)); - get_Z3_lits(orig_clause,lits); - for(int i = 1; i <= position; i++){ - std::vector unit(1); - unit[0] = conc(prem(proof,i)); - resolve(mk_not(unit[0]),lits,unit); + // get the lits of a Z3 clause + void get_Z3_lits(ast t, std::vector &lits){ + opr dk = op(t); + if(dk == False) + return; // false = empty clause + if(dk == Or){ + unsigned nargs = num_args(t); + lits.resize(nargs); + for(unsigned i = 0; i < nargs; i++) // do all the sub_terms + lits[i] = arg(t,i); + } + else { + lits.push_back(t); + } + } + + // resolve two clauses represented as vectors of lits. replace first clause + void resolve(ast pivot, std::vector &cls1, std::vector &cls2){ + ast neg_pivot = mk_not(pivot); + for(unsigned i = 0; i < cls1.size(); i++){ + if(cls1[i] == pivot){ + cls1[i] = cls1.back(); + cls1.pop_back(); + bool found_pivot2 = false; + for(unsigned j = 0; j < cls2.size(); j++){ + if(cls2[j] == neg_pivot) + found_pivot2 = true; + else + cls1.push_back(cls2[j]); + } + assert(found_pivot2); + return; + } + } + assert(0 && "resolve failed"); + } + + // get lits resulting from unit resolution up to and including "position" + // TODO: this is quadratic -- fix it + void do_unit_resolution(ast proof, int position, std::vector &lits){ + ast orig_clause = conc(prem(proof,0)); + get_Z3_lits(orig_clause,lits); + for(int i = 1; i <= position; i++){ + std::vector unit(1); + unit[0] = conc(prem(proof,i)); + resolve(mk_not(unit[0]),lits,unit); + } } - } #if 0 - // clear the localization variables - void clear_localization(){ - localization_vars.clear(); - localization_map.clear(); - } + // clear the localization variables + void clear_localization(){ + localization_vars.clear(); + localization_map.clear(); + } - // create a fresh variable for localization - ast fresh_localization_var(ast term, int frame){ - std::ostringstream s; - s << "%" << (localization_vars.size()); - ast var = make_var(s.str().c_str(),get_type(term)); - sym_range(sym(var)) = range_full(); // make this variable global - localization_vars.push_back(LocVar(var,term,frame)); - return var; - } + // create a fresh variable for localization + ast fresh_localization_var(ast term, int frame){ + std::ostringstream s; + s << "%" << (localization_vars.size()); + ast var = make_var(s.str().c_str(),get_type(term)); + sym_range(sym(var)) = range_full(); // make this variable global + localization_vars.push_back(LocVar(var,term,frame)); + return var; + } - // "localize" a term to a given frame range by - // creating new symbols to represent non-local subterms + // "localize" a term to a given frame range by + // creating new symbols to represent non-local subterms - ast localize_term(ast e, const range &rng){ - if(ranges_intersect(ast_scope(e),rng)) - return e; // this term occurs in range, so it's O.K. - AstToAst::iterator it = localization_map.find(e); - if(it != localization_map.end()) - return it->second; + ast localize_term(ast e, const range &rng){ + if(ranges_intersect(ast_scope(e),rng)) + return e; // this term occurs in range, so it's O.K. + AstToAst::iterator it = localization_map.find(e); + if(it != localization_map.end()) + return it->second; - // if is is non-local, we must first localize the arguments to - // the range of its function symbol + // if is is non-local, we must first localize the arguments to + // the range of its function symbol - int nargs = num_args(e); - if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ - range frng = rng; - if(op(e) == Uninterpreted){ - symb f = sym(e); - range srng = sym_range(f); - if(ranges_intersect(srng,rng)) // localize to desired range if possible - frng = range_glb(srng,rng); - } - std::vector largs(nargs); - for(int i = 0; i < nargs; i++){ - largs[i] = localize_term(arg(e,i),frng); - frng = range_glb(frng,ast_scope(largs[i])); - } - e = clone(e,largs); - assert(is_local(e)); + int nargs = num_args(e); + if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ + range frng = rng; + if(op(e) == Uninterpreted){ + symb f = sym(e); + range srng = sym_range(f); + if(ranges_intersect(srng,rng)) // localize to desired range if possible + frng = range_glb(srng,rng); + } + std::vector largs(nargs); + for(int i = 0; i < nargs; i++){ + largs[i] = localize_term(arg(e,i),frng); + frng = range_glb(frng,ast_scope(largs[i])); + } + e = clone(e,largs); + assert(is_local(e)); + } + + + if(ranges_intersect(ast_scope(e),rng)) + return e; // this term occurs in range, so it's O.K. + + // choose a frame for the constraint that is close to range + int frame = range_near(ast_scope(e),rng); + + ast new_var = fresh_localization_var(e,frame); + localization_map[e] = new_var; + ast cnst = make(Equal,new_var,e); + // antes.push_back(std::pair(cnst,frame)); + return new_var; } + // some patterm matching functions - if(ranges_intersect(ast_scope(e),rng)) - return e; // this term occurs in range, so it's O.K. - - // choose a frame for the constraint that is close to range - int frame = range_near(ast_scope(e),rng); - - ast new_var = fresh_localization_var(e,frame); - localization_map[e] = new_var; - ast cnst = make(Equal,new_var,e); - // antes.push_back(std::pair(cnst,frame)); - return new_var; - } - - // some patterm matching functions - - // match logical or with nargs arguments - // assumes AIG form - bool match_or(ast e, ast *args, int nargs){ - if(op(e) != Or) return false; - int n = num_args(e); - if(n != nargs) return false; - for(int i = 0; i < nargs; i++) - args[i] = arg(e,i); - return true; - } - - // match operator f with exactly nargs arguments - bool match_op(ast e, opr f, ast *args, int nargs){ - if(op(e) != f) return false; - int n = num_args(e); - if(n != nargs) return false; - for(int i = 0; i < nargs; i++) - args[i] = arg(e,i); - return true; - } - - // see if the given formula can be interpreted as - // an axiom instance (e.g., an array axiom instance). - // if so, add it to "antes" in an appropriate frame. - // this may require "localization" - - void get_axiom_instance(ast e){ - - // "store" axiom - // (or (= w q) (= (select (store a1 w y) q) (select a1 q))) - // std::cout << "ax: "; show(e); - ast lits[2],eq_ops_l[2],eq_ops_r[2],sel_ops[2], sto_ops[3], sel_ops2[2] ; - if(match_or(e,lits,2)) - if(match_op(lits[0],Equal,eq_ops_l,2)) - if(match_op(lits[1],Equal,eq_ops_r,2)) - for(int i = 0; i < 2; i++){ // try the second equality both ways - if(match_op(eq_ops_r[0],Select,sel_ops,2)) - if(match_op(sel_ops[0],Store,sto_ops,3)) - if(match_op(eq_ops_r[1],Select,sel_ops2,2)) - for(int j = 0; j < 2; j++){ // try the first equality both ways - if(eq_ops_l[0] == sto_ops[1] - && eq_ops_l[1] == sel_ops[1] - && eq_ops_l[1] == sel_ops2[1] - && sto_ops[0] == sel_ops2[0]) - if(is_local(sel_ops[0])) // store term must be local - { - ast sto = sel_ops[0]; - ast addr = localize_term(eq_ops_l[1],ast_scope(sto)); - ast res = make(Or, - make(Equal,eq_ops_l[0],addr), - make(Equal, - make(Select,sto,addr), - make(Select,sel_ops2[0],addr))); - // int frame = range_min(ast_scope(res)); TODO - // antes.push_back(std::pair(res,frame)); - return; - } - std::swap(eq_ops_l[0],eq_ops_l[1]); - } - std::swap(eq_ops_r[0],eq_ops_r[1]); - } - } - - // a quantifier instantation looks like (~ forall x. P) \/ P[z/x] - // we need to find a time frame for P, then localize P[z/x] in this frame - - void get_quantifier_instance(ast e){ - ast disjs[2]; - if(match_or(e,disjs,2)){ - if(is_local(disjs[0])){ - ast res = localize_term(disjs[1], ast_scope(disjs[0])); - // int frame = range_min(ast_scope(res)); TODO - // antes.push_back(std::pair(res,frame)); - return; - } - } - } - - ast get_judgement(ast proof){ - ast con = from_ast(conc(proof)); - AstSet &hyps = get_hyps(proof); - std::vector hyps_vec; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - hyps_vec.push_back(*it); - if(hyps_vec.size() == 0) return con; - con = make(Or,mk_not(make(And,hyps_vec)),con); - return con; - } - - // does variable occur in expression? - int occurs_in1(ast var, ast e){ - std::pair foo(e,false); - std::pair bar = occurs_in_memo.insert(foo); - bool &res = bar.first->second; - if(bar.second){ - if(e == var) res = true; - int nargs = num_args(e); - for(int i = 0; i < nargs; i++) - res |= occurs_in1(var,arg(e,i)); - } - return res; - } - - int occurs_in(ast var, ast e){ - occurs_in_memo.clear(); - return occurs_in1(var,e); - } - - // find a controlling equality for a given variable v in a term - // a controlling equality is of the form v = t, which, being - // false would force the formula to have the specifid truth value - // returns t, or null if no such - - ast cont_eq(bool truth, ast v, ast e){ - if(is_not(e)) return cont_eq(!truth,v,arg(e,0)); - if(cont_eq_memo.find(e) != cont_eq_memo.end()) - return ast(); - cont_eq_memo.insert(e); - if(!truth && op(e) == Equal){ - if(arg(e,0) == v) return(arg(e,1)); - if(arg(e,1) == v) return(arg(e,0)); - } - if((!truth && op(e) == And) || (truth && op(e) == Or)){ - int nargs = num_args(e); - for(int i = 0; i < nargs; i++){ - ast res = cont_eq(truth, v, arg(e,i)); - if(!res.null()) return res; - } - } - return ast(); - } - - // substitute a term t for unbound occurrences of variable v in e - - ast subst(ast var, ast t, ast e){ - if(e == var) return t; - std::pair foo(e,ast()); - std::pair bar = subst_memo.insert(foo); - ast &res = bar.first->second; - if(bar.second){ - int nargs = num_args(e); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = subst(var,t,arg(e,i)); - opr f = op(e); - if(f == Equal && args[0] == args[1]) res = mk_true(); - else res = clone(e,args); - } - return res; - } - - // apply a quantifier to a formula, with some optimizations - // 1) bound variable does not occur -> no quantifier - // 2) bound variable must be equal to some term -> substitute - - ast apply_quant(opr quantifier, ast var, ast e){ - if(!occurs_in(var,e))return e; - cont_eq_memo.clear(); - ast cterm = cont_eq(quantifier == Forall, var, e); - if(!cterm.null()){ - subst_memo.clear(); - return subst(var,cterm,e); - } - std::vector bvs; bvs.push_back(var); - return make_quant(quantifier,bvs,e); - } - - // add quantifiers over the localization vars - // to an interpolant for frames lo-hi - - ast add_quants(ast e, int lo, int hi){ - for(int i = localization_vars.size() - 1; i >= 0; i--){ - LocVar &lv = localization_vars[i]; - opr quantifier = (lv.frame >= lo && lv.frame <= hi) ? Exists : Forall; - e = apply_quant(quantifier,lv.var,e); - } - return e; - } - - int get_lits_locality(std::vector &lits){ - range rng = range_full(); - for(std::vector::iterator it = lits.begin(), en = lits.end(); it != en; ++it){ - ast lit = *it; - rng = range_glb(rng,ast_scope(lit)); - } - if(range_is_empty(rng)) return -1; - int hi = range_max(rng); - if(hi >= frames) return frames - 1; - return hi; - } -#endif - - int num_lits(ast ast){ - opr dk = op(ast); - if(dk == False) - return 0; - if(dk == Or){ - unsigned nargs = num_args(ast); - int n = 0; - for(unsigned i = 0; i < nargs; i++) // do all the sub_terms - n += num_lits(arg(ast,i)); - return n; - } - else - return 1; - } - - void symbols_out_of_scope_rec(hash_set &memo, hash_set &symb_memo, int frame, const ast &t){ - if(memo.find(t) != memo.end()) - return; - memo.insert(t); - if(op(t) == Uninterpreted){ - symb s = sym(t); - range r = sym_range(s); - if(!in_range(frame,r) && symb_memo.find(s) == symb_memo.end()){ - std::cout << string_of_symbol(s) << "\n"; - symb_memo.insert(s); - } - } - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - symbols_out_of_scope_rec(memo,symb_memo,frame,arg(t,i)); - } - - void symbols_out_of_scope(int frame, const ast &t){ - hash_set memo; - hash_set symb_memo; - symbols_out_of_scope_rec(memo,symb_memo,frame,t); - } - - void conc_symbols_out_of_scope(int frame, const ast &t){ - symbols_out_of_scope(frame,conc(t)); - } - - std::vector lit_trace; - hash_set marked_proofs; - - bool proof_has_lit(const ast &proof, const ast &lit){ - AstSet &hyps = get_hyps(proof); - if(hyps.find(mk_not(lit)) != hyps.end()) - return true; - std::vector lits; - ast con = conc(proof); - get_Z3_lits(con, lits); - for(unsigned i = 0; i < lits.size(); i++) - if(lits[i] == lit) + // match logical or with nargs arguments + // assumes AIG form + bool match_or(ast e, ast *args, int nargs){ + if(op(e) != Or) return false; + int n = num_args(e); + if(n != nargs) return false; + for(int i = 0; i < nargs; i++) + args[i] = arg(e,i); return true; - return false; - } - - - void trace_lit_rec(const ast &lit, const ast &proof, AstHashSet &memo){ - if(memo.find(proof) == memo.end()){ - memo.insert(proof); - AstSet &hyps = get_hyps(proof); - std::vector lits; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - lits.push_back(mk_not(*it)); - ast con = conc(proof); - get_Z3_lits(con, lits); - for(unsigned i = 0; i < lits.size(); i++){ - if(lits[i] == lit){ - print_expr(std::cout,proof); - std::cout << "\n"; - marked_proofs.insert(proof); - pfrule dk = pr(proof); - if(dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA){ - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - trace_lit_rec(lit,arg,memo); - } - } - else - lit_trace.push_back(proof); - } - } } - } + + // match operator f with exactly nargs arguments + bool match_op(ast e, opr f, ast *args, int nargs){ + if(op(e) != f) return false; + int n = num_args(e); + if(n != nargs) return false; + for(int i = 0; i < nargs; i++) + args[i] = arg(e,i); + return true; + } + + // see if the given formula can be interpreted as + // an axiom instance (e.g., an array axiom instance). + // if so, add it to "antes" in an appropriate frame. + // this may require "localization" - ast traced_lit; + void get_axiom_instance(ast e){ - int trace_lit(const ast &lit, const ast &proof){ - marked_proofs.clear(); - lit_trace.clear(); - traced_lit = lit; - AstHashSet memo; - trace_lit_rec(lit,proof,memo); - return lit_trace.size(); - } - - bool is_literal_or_lit_iff(const ast &lit){ - if(my_is_literal(lit)) return true; - if(op(lit) == Iff){ - return my_is_literal(arg(lit,0)) && my_is_literal(arg(lit,1)); + // "store" axiom + // (or (= w q) (= (select (store a1 w y) q) (select a1 q))) + // std::cout << "ax: "; show(e); + ast lits[2],eq_ops_l[2],eq_ops_r[2],sel_ops[2], sto_ops[3], sel_ops2[2] ; + if(match_or(e,lits,2)) + if(match_op(lits[0],Equal,eq_ops_l,2)) + if(match_op(lits[1],Equal,eq_ops_r,2)) + for(int i = 0; i < 2; i++){ // try the second equality both ways + if(match_op(eq_ops_r[0],Select,sel_ops,2)) + if(match_op(sel_ops[0],Store,sto_ops,3)) + if(match_op(eq_ops_r[1],Select,sel_ops2,2)) + for(int j = 0; j < 2; j++){ // try the first equality both ways + if(eq_ops_l[0] == sto_ops[1] + && eq_ops_l[1] == sel_ops[1] + && eq_ops_l[1] == sel_ops2[1] + && sto_ops[0] == sel_ops2[0]) + if(is_local(sel_ops[0])) // store term must be local + { + ast sto = sel_ops[0]; + ast addr = localize_term(eq_ops_l[1],ast_scope(sto)); + ast res = make(Or, + make(Equal,eq_ops_l[0],addr), + make(Equal, + make(Select,sto,addr), + make(Select,sel_ops2[0],addr))); + // int frame = range_min(ast_scope(res)); TODO + // antes.push_back(std::pair(res,frame)); + return; + } + std::swap(eq_ops_l[0],eq_ops_l[1]); + } + std::swap(eq_ops_r[0],eq_ops_r[1]); + } } - return false; - } - bool my_is_literal(const ast &lit){ - ast abslit = is_not(lit) ? arg(lit,0) : lit; - int f = op(abslit); - return !(f == And || f == Or || f == Iff); - } + // a quantifier instantation looks like (~ forall x. P) \/ P[z/x] + // we need to find a time frame for P, then localize P[z/x] in this frame - hash_map asts_by_id; - - void print_lit(const ast &lit){ - ast abslit = is_not(lit) ? arg(lit,0) : lit; - if(!is_literal_or_lit_iff(lit)){ - if(is_not(lit)) std::cout << "~"; - int id = ast_id(abslit); - asts_by_id[id] = abslit; - std::cout << "[" << id << "]"; + void get_quantifier_instance(ast e){ + ast disjs[2]; + if(match_or(e,disjs,2)){ + if(is_local(disjs[0])){ + ast res = localize_term(disjs[1], ast_scope(disjs[0])); + // int frame = range_min(ast_scope(res)); TODO + // antes.push_back(std::pair(res,frame)); + return; + } + } } - else - print_expr(std::cout,lit); - } - void expand(int id){ - if(asts_by_id.find(id) == asts_by_id.end()) - std::cout << "undefined\n"; - else { - ast lit = asts_by_id[id]; - std::string s = string_of_symbol(sym(lit)); - std::cout << "(" << s; - unsigned nargs = num_args(lit); - for(unsigned i = 0; i < nargs; i++){ - std::cout << " "; - print_lit(arg(lit,i)); - } - std::cout << ")\n";; + ast get_judgement(ast proof){ + ast con = from_ast(conc(proof)); + AstSet &hyps = get_hyps(proof); + std::vector hyps_vec; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + hyps_vec.push_back(*it); + if(hyps_vec.size() == 0) return con; + con = make(Or,mk_not(make(And,hyps_vec)),con); + return con; } - } - void show_lit(const ast &lit){ - print_lit(lit); - std::cout << "\n"; - } + // does variable occur in expression? + int occurs_in1(ast var, ast e){ + std::pair foo(e,false); + std::pair bar = occurs_in_memo.insert(foo); + bool &res = bar.first->second; + if(bar.second){ + if(e == var) res = true; + int nargs = num_args(e); + for(int i = 0; i < nargs; i++) + res |= occurs_in1(var,arg(e,i)); + } + return res; + } - void print_z3_lit(const ast &a){ - print_lit(from_ast(a)); - } + int occurs_in(ast var, ast e){ + occurs_in_memo.clear(); + return occurs_in1(var,e); + } + + // find a controlling equality for a given variable v in a term + // a controlling equality is of the form v = t, which, being + // false would force the formula to have the specifid truth value + // returns t, or null if no such - void show_z3_lit(const ast &a){ - print_z3_lit(a); - std::cout << "\n"; - } + ast cont_eq(bool truth, ast v, ast e){ + if(is_not(e)) return cont_eq(!truth,v,arg(e,0)); + if(cont_eq_memo.find(e) != cont_eq_memo.end()) + return ast(); + cont_eq_memo.insert(e); + if(!truth && op(e) == Equal){ + if(arg(e,0) == v) return(arg(e,1)); + if(arg(e,1) == v) return(arg(e,0)); + } + if((!truth && op(e) == And) || (truth && op(e) == Or)){ + int nargs = num_args(e); + for(int i = 0; i < nargs; i++){ + ast res = cont_eq(truth, v, arg(e,i)); + if(!res.null()) return res; + } + } + return ast(); + } + + // substitute a term t for unbound occurrences of variable v in e + + ast subst(ast var, ast t, ast e){ + if(e == var) return t; + std::pair foo(e,ast()); + std::pair bar = subst_memo.insert(foo); + ast &res = bar.first->second; + if(bar.second){ + int nargs = num_args(e); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = subst(var,t,arg(e,i)); + opr f = op(e); + if(f == Equal && args[0] == args[1]) res = mk_true(); + else res = clone(e,args); + } + return res; + } + + // apply a quantifier to a formula, with some optimizations + // 1) bound variable does not occur -> no quantifier + // 2) bound variable must be equal to some term -> substitute + + ast apply_quant(opr quantifier, ast var, ast e){ + if(!occurs_in(var,e))return e; + cont_eq_memo.clear(); + ast cterm = cont_eq(quantifier == Forall, var, e); + if(!cterm.null()){ + subst_memo.clear(); + return subst(var,cterm,e); + } + std::vector bvs; bvs.push_back(var); + return make_quant(quantifier,bvs,e); + } + + // add quantifiers over the localization vars + // to an interpolant for frames lo-hi + + ast add_quants(ast e, int lo, int hi){ + for(int i = localization_vars.size() - 1; i >= 0; i--){ + LocVar &lv = localization_vars[i]; + opr quantifier = (lv.frame >= lo && lv.frame <= hi) ? Exists : Forall; + e = apply_quant(quantifier,lv.var,e); + } + return e; + } + + int get_lits_locality(std::vector &lits){ + range rng = range_full(); + for(std::vector::iterator it = lits.begin(), en = lits.end(); it != en; ++it){ + ast lit = *it; + rng = range_glb(rng,ast_scope(lit)); + } + if(range_is_empty(rng)) return -1; + int hi = range_max(rng); + if(hi >= frames) return frames - 1; + return hi; + } +#endif + + int num_lits(ast ast){ + opr dk = op(ast); + if(dk == False) + return 0; + if(dk == Or){ + unsigned nargs = num_args(ast); + int n = 0; + for(unsigned i = 0; i < nargs; i++) // do all the sub_terms + n += num_lits(arg(ast,i)); + return n; + } + else + return 1; + } + + void symbols_out_of_scope_rec(hash_set &memo, hash_set &symb_memo, int frame, const ast &t){ + if(memo.find(t) != memo.end()) + return; + memo.insert(t); + if(op(t) == Uninterpreted){ + symb s = sym(t); + range r = sym_range(s); + if(!in_range(frame,r) && symb_memo.find(s) == symb_memo.end()){ + std::cout << string_of_symbol(s) << "\n"; + symb_memo.insert(s); + } + } + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + symbols_out_of_scope_rec(memo,symb_memo,frame,arg(t,i)); + } + + void symbols_out_of_scope(int frame, const ast &t){ + hash_set memo; + hash_set symb_memo; + symbols_out_of_scope_rec(memo,symb_memo,frame,t); + } + + void conc_symbols_out_of_scope(int frame, const ast &t){ + symbols_out_of_scope(frame,conc(t)); + } + + std::vector lit_trace; + hash_set marked_proofs; + + bool proof_has_lit(const ast &proof, const ast &lit){ + AstSet &hyps = get_hyps(proof); + if(hyps.find(mk_not(lit)) != hyps.end()) + return true; + std::vector lits; + ast con = conc(proof); + get_Z3_lits(con, lits); + for(unsigned i = 0; i < lits.size(); i++) + if(lits[i] == lit) + return true; + return false; + } + + + void trace_lit_rec(const ast &lit, const ast &proof, AstHashSet &memo){ + if(memo.find(proof) == memo.end()){ + memo.insert(proof); + AstSet &hyps = get_hyps(proof); + std::vector lits; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + lits.push_back(mk_not(*it)); + ast con = conc(proof); + get_Z3_lits(con, lits); + for(unsigned i = 0; i < lits.size(); i++){ + if(lits[i] == lit){ + print_expr(std::cout,proof); + std::cout << "\n"; + marked_proofs.insert(proof); + pfrule dk = pr(proof); + if(dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA){ + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + trace_lit_rec(lit,arg,memo); + } + } + else + lit_trace.push_back(proof); + } + } + } + } + + ast traced_lit; + + int trace_lit(const ast &lit, const ast &proof){ + marked_proofs.clear(); + lit_trace.clear(); + traced_lit = lit; + AstHashSet memo; + trace_lit_rec(lit,proof,memo); + return lit_trace.size(); + } + + bool is_literal_or_lit_iff(const ast &lit){ + if(my_is_literal(lit)) return true; + if(op(lit) == Iff){ + return my_is_literal(arg(lit,0)) && my_is_literal(arg(lit,1)); + } + return false; + } + + bool my_is_literal(const ast &lit){ + ast abslit = is_not(lit) ? arg(lit,0) : lit; + int f = op(abslit); + return !(f == And || f == Or || f == Iff); + } + + hash_map asts_by_id; + + void print_lit(const ast &lit){ + ast abslit = is_not(lit) ? arg(lit,0) : lit; + if(!is_literal_or_lit_iff(lit)){ + if(is_not(lit)) std::cout << "~"; + int id = ast_id(abslit); + asts_by_id[id] = abslit; + std::cout << "[" << id << "]"; + } + else + print_expr(std::cout,lit); + } + + void expand(int id){ + if(asts_by_id.find(id) == asts_by_id.end()) + std::cout << "undefined\n"; + else { + ast lit = asts_by_id[id]; + std::string s = string_of_symbol(sym(lit)); + std::cout << "(" << s; + unsigned nargs = num_args(lit); + for(unsigned i = 0; i < nargs; i++){ + std::cout << " "; + print_lit(arg(lit,i)); + } + std::cout << ")\n";; + } + } + + void show_lit(const ast &lit){ + print_lit(lit); + std::cout << "\n"; + } + + void print_z3_lit(const ast &a){ + print_lit(from_ast(a)); + } + + void show_z3_lit(const ast &a){ + print_z3_lit(a); + std::cout << "\n"; + } - void show_con(const ast &proof, bool brief){ - if(!traced_lit.null() && proof_has_lit(proof,traced_lit)) - std::cout << "(*) "; - ast con = conc(proof); - AstSet &hyps = get_hyps(proof); - int count = 0; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ - if(brief && ++count > 5){ - std::cout << "... "; - break; - } - print_lit(*it); - std::cout << " "; + void show_con(const ast &proof, bool brief){ + if(!traced_lit.null() && proof_has_lit(proof,traced_lit)) + std::cout << "(*) "; + ast con = conc(proof); + AstSet &hyps = get_hyps(proof); + int count = 0; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ + if(brief && ++count > 5){ + std::cout << "... "; + break; + } + print_lit(*it); + std::cout << " "; + } + std::cout << "|- "; + std::vector lits; + get_Z3_lits(con,lits); + for(unsigned i = 0; i < lits.size(); i++){ + print_lit(lits[i]); + std::cout << " "; + } + range r = ast_scope(con); + std::cout << " {" << r.lo << "," << r.hi << "}"; + std::cout << "\n"; } - std::cout << "|- "; - std::vector lits; - get_Z3_lits(con,lits); - for(unsigned i = 0; i < lits.size(); i++){ - print_lit(lits[i]); - std::cout << " "; - } - range r = ast_scope(con); - std::cout << " {" << r.lo << "," << r.hi << "}"; - std::cout << "\n"; - } - void show_step(const ast &proof){ - std::cout << "\n"; - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - std::cout << "(" << i << ") "; - ast arg = prem(proof,i); - show_con(arg,true); + void show_step(const ast &proof){ + std::cout << "\n"; + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + std::cout << "(" << i << ") "; + ast arg = prem(proof,i); + show_con(arg,true); + } + std::cout << "|------ "; + std::cout << string_of_symbol(sym(proof)) << "\n"; + show_con(proof,false); } - std::cout << "|------ "; - std::cout << string_of_symbol(sym(proof)) << "\n"; - show_con(proof,false); - } - void show_marked( const ast &proof){ - std::cout << "\n"; - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - if(!traced_lit.null() && proof_has_lit(arg,traced_lit)){ - std::cout << "(" << i << ") "; - show_con(arg,true); - } + void show_marked( const ast &proof){ + std::cout << "\n"; + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + if(!traced_lit.null() && proof_has_lit(arg,traced_lit)){ + std::cout << "(" << i << ") "; + show_con(arg,true); + } + } } - } - std::vector pfhist; - int pfhist_pos; + std::vector pfhist; + int pfhist_pos; - void pfgoto(const ast &proof){ - if(pfhist.size() == 0) - pfhist_pos = 0; - else pfhist_pos++; - pfhist.resize(pfhist_pos); - pfhist.push_back(proof); - show_step(proof); - } + void pfgoto(const ast &proof){ + if(pfhist.size() == 0) + pfhist_pos = 0; + else pfhist_pos++; + pfhist.resize(pfhist_pos); + pfhist.push_back(proof); + show_step(proof); + } - void pfback(){ - if(pfhist_pos > 0){ - pfhist_pos--; - show_step(pfhist[pfhist_pos]); - } - } - - void pffwd(){ - if(pfhist_pos < ((int)pfhist.size()) - 1){ - pfhist_pos++; - show_step(pfhist[pfhist_pos]); - } - } - - void pfprem(int i){ - if(pfhist.size() > 0){ - ast proof = pfhist[pfhist_pos]; - unsigned nprems = num_prems(proof); - if(i >= 0 && i < (int)nprems) - pfgoto(prem(proof,i)); - } - } - - - - // translate a unit resolution sequence - Iproof::node translate_ur(ast proof){ - ast prem0 = prem(proof,0); - Iproof::node itp = translate_main(prem0,true); - std::vector clause; - ast conc0 = conc(prem0); - int nprems = num_prems(proof); - if(nprems == 2 && conc0 == mk_not(conc(prem(proof,1)))) - clause.push_back(conc0); - else - get_Z3_lits(conc0,clause); - for(int position = 1; position < nprems; position++){ - ast ante = prem(proof,position); - ast pnode = conc(ante); - ast pnode_abs = !is_not(pnode) ? pnode : mk_not(pnode); - Iproof::node neg = itp; - Iproof::node pos = translate_main(ante, false); - if(is_not(pnode)){ - pnode = mk_not(pnode); - std::swap(neg,pos); - } - std::vector unit(1); - unit[0] = conc(ante); - resolve(mk_not(conc(ante)),clause,unit); - itp = iproof->make_resolution(pnode,clause,neg,pos); - } - return itp; - } - - // get an inequality in the form 0 <= t where t is a linear term - ast rhs_normalize_inequality(const ast &ineq){ - ast zero = make_int("0"); - ast thing = make(Leq,zero,zero); - linear_comb(thing,make_int("1"),ineq); - thing = simplify_ineq(thing); - return thing; - } - - bool check_farkas(const std::vector &prems, const ast &con){ - ast zero = make_int("0"); - ast thing = make(Leq,zero,zero); - for(unsigned i = 0; i < prems.size(); i++) - linear_comb(thing,make_int(rational(1)),prems[i]); - linear_comb(thing,make_int(rational(-1)),con); - thing = simplify_ineq(thing); - return arg(thing,1) == make_int(rational(0)); - } - - // get an inequality in the form t <= c or t < c, there t is affine and c constant - ast normalize_inequality(const ast &ineq){ - ast zero = make_int("0"); - ast thing = make(Leq,zero,zero); - linear_comb(thing,make_int("1"),ineq); - thing = simplify_ineq(thing); - ast lhs = arg(thing,0); - ast rhs = arg(thing,1); - opr o = op(rhs); - if(o != Numeral){ - if(op(rhs) == Plus){ - int nargs = num_args(rhs); - ast const_term = zero; - int i = 0; - if(nargs > 0 && op(arg(rhs,0)) == Numeral){ - const_term = arg(rhs,0); - i++; - } - if(i < nargs){ - std::vector non_const; - for(; i < nargs; i++) - non_const.push_back(arg(rhs,i)); - lhs = make(Sub,lhs,make(Plus,non_const)); - } - rhs = const_term; - } - else { - lhs = make(Sub,lhs,make(Plus,rhs)); - rhs = zero; - } - lhs = z3_simplify(lhs); - rhs = z3_simplify(rhs); - thing = make(op(thing),lhs,rhs); - } - return thing; - } - - void get_linear_coefficients(const ast &t, std::vector &coeffs){ - if(op(t) == Plus){ - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - coeffs.push_back(get_coeff(arg(t,i))); - } - else - coeffs.push_back(get_coeff(t)); - } - - /* given an affine term t, get the GCD of the coefficients in t. */ - ast gcd_of_coefficients(const ast &t){ - std::vector coeffs; - get_linear_coefficients(t,coeffs); - if(coeffs.size() == 0) - return make_int("1"); // arbitrary - rational d = coeffs[0]; - for(unsigned i = 1; i < coeffs.size(); i++){ - d = gcd(d,coeffs[i]); - } - return make_int(d); - } - - ast get_bounded_variable(const ast &ineq, bool &lb){ - ast nineq = normalize_inequality(ineq); - ast lhs = arg(nineq,0); - switch(op(lhs)){ - case Uninterpreted: - lb = false; - return lhs; - case Times: - if(arg(lhs,0) == make_int(rational(1))) - lb = false; - else if(arg(lhs,0) == make_int(rational(-1))) - lb = true; - else - throw unsupported(); - return arg(lhs,1); - default: - throw unsupported(); - } - } - - rational get_term_coefficient(const ast &t1, const ast &v){ - ast t = arg(normalize_inequality(t1),0); - if(op(t) == Plus){ - int nargs = num_args(t); - for(int i = 0; i < nargs; i++){ - if(get_linear_var(arg(t,i)) == v) - return get_coeff(arg(t,i)); - } - } - else - if(get_linear_var(t) == v) - return get_coeff(t); - return rational(0); - } - - - Iproof::node GCDtoDivRule(const ast &proof, bool pol, std::vector &coeffs, std::vector &prems, ast &cut_con){ - // gather the summands of the desired polarity - std::vector my_prems; - std::vector my_coeffs; - std::vector my_prem_cons; - for(unsigned i = pol ? 0 : 1; i < coeffs.size(); i+= 2){ - rational &c = coeffs[i]; - if(c.is_pos()){ - my_prems.push_back(prems[i]); - my_coeffs.push_back(make_int(c)); - my_prem_cons.push_back(conc(prem(proof,i))); - } - } - ast my_con = sum_inequalities(my_coeffs,my_prem_cons); - - // handle generalized GCD test. sadly, we dont' get the coefficients... - if(coeffs[0].is_zero()){ - bool lb; - int xtra_prem = 0; - ast bv = get_bounded_variable(conc(prem(proof,0)),lb); - rational bv_coeff = get_term_coefficient(my_con,bv); - if(bv_coeff.is_pos() != lb) - xtra_prem = 1; - if(bv_coeff.is_neg()) - bv_coeff = -bv_coeff; - - my_prems.push_back(prems[xtra_prem]); - my_coeffs.push_back(make_int(bv_coeff)); - my_prem_cons.push_back(conc(prem(proof,xtra_prem))); - my_con = sum_inequalities(my_coeffs,my_prem_cons); + void pfback(){ + if(pfhist_pos > 0){ + pfhist_pos--; + show_step(pfhist[pfhist_pos]); + } } - my_con = normalize_inequality(my_con); - Iproof::node hyp = iproof->make_hypothesis(mk_not(my_con)); - my_prems.push_back(hyp); - my_coeffs.push_back(make_int("1")); - my_prem_cons.push_back(mk_not(my_con)); - Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_prem_cons,my_coeffs); - - ast t = arg(my_con,0); - ast c = arg(my_con,1); - ast d = gcd_of_coefficients(t); - t = z3_simplify(mk_idiv(t,d)); - c = z3_simplify(mk_idiv(c,d)); - cut_con = make(op(my_con),t,c); - return iproof->make_cut_rule(my_con,d,cut_con,res); - } - - - rational get_first_coefficient(const ast &t, ast &v){ - if(op(t) == Plus){ - unsigned best_id = UINT_MAX; - rational best_coeff(0); - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - if(op(arg(t,i)) != Numeral){ - ast lv = get_linear_var(arg(t,i)); - unsigned id = ast_id(lv); - if(id < best_id) { - v = lv; - best_id = id; - best_coeff = get_coeff(arg(t,i)); - } - } - return best_coeff; + void pffwd(){ + if(pfhist_pos < ((int)pfhist.size()) - 1){ + pfhist_pos++; + show_step(pfhist[pfhist_pos]); + } } - else - if(op(t) != Numeral) - return(get_coeff(t)); - return rational(0); - } - ast divide_inequalities(const ast &x, const ast&y){ - ast xvar, yvar; - rational xcoeff = get_first_coefficient(arg(x,0),xvar); - rational ycoeff = get_first_coefficient(arg(y,0),yvar); - if(xcoeff == rational(0) || ycoeff == rational(0) || xvar != yvar) - throw "bad assign-bounds lemma"; - rational ratio = xcoeff/ycoeff; - if(denominator(ratio) != rational(1)) - throw "bad assign-bounds lemma"; - return make_int(ratio); // better be integer! - } + void pfprem(int i){ + if(pfhist.size() > 0){ + ast proof = pfhist[pfhist_pos]; + unsigned nprems = num_prems(proof); + if(i >= 0 && i < (int)nprems) + pfgoto(prem(proof,i)); + } + } - ast AssignBounds2Farkas(const ast &proof, const ast &con){ - std::vector farkas_coeffs; - get_assign_bounds_coeffs(proof,farkas_coeffs); - int nargs = num_args(con); - if(nargs != (int)(farkas_coeffs.size())) - throw "bad assign-bounds theory lemma"; + + + // translate a unit resolution sequence + Iproof::node translate_ur(ast proof){ + ast prem0 = prem(proof,0); + Iproof::node itp = translate_main(prem0,true); + std::vector clause; + ast conc0 = conc(prem0); + int nprems = num_prems(proof); + if(nprems == 2 && conc0 == mk_not(conc(prem(proof,1)))) + clause.push_back(conc0); + else + get_Z3_lits(conc0,clause); + for(int position = 1; position < nprems; position++){ + ast ante = prem(proof,position); + ast pnode = conc(ante); + ast pnode_abs = !is_not(pnode) ? pnode : mk_not(pnode); + Iproof::node neg = itp; + Iproof::node pos = translate_main(ante, false); + if(is_not(pnode)){ + pnode = mk_not(pnode); + std::swap(neg,pos); + } + std::vector unit(1); + unit[0] = conc(ante); + resolve(mk_not(conc(ante)),clause,unit); + itp = iproof->make_resolution(pnode,clause,neg,pos); + } + return itp; + } + + // get an inequality in the form 0 <= t where t is a linear term + ast rhs_normalize_inequality(const ast &ineq){ + ast zero = make_int("0"); + ast thing = make(Leq,zero,zero); + linear_comb(thing,make_int("1"),ineq); + thing = simplify_ineq(thing); + return thing; + } + + bool check_farkas(const std::vector &prems, const ast &con){ + ast zero = make_int("0"); + ast thing = make(Leq,zero,zero); + for(unsigned i = 0; i < prems.size(); i++) + linear_comb(thing,make_int(rational(1)),prems[i]); + linear_comb(thing,make_int(rational(-1)),con); + thing = simplify_ineq(thing); + return arg(thing,1) == make_int(rational(0)); + } + + // get an inequality in the form t <= c or t < c, there t is affine and c constant + ast normalize_inequality(const ast &ineq){ + ast zero = make_int("0"); + ast thing = make(Leq,zero,zero); + linear_comb(thing,make_int("1"),ineq); + thing = simplify_ineq(thing); + ast lhs = arg(thing,0); + ast rhs = arg(thing,1); + opr o = op(rhs); + if(o != Numeral){ + if(op(rhs) == Plus){ + int nargs = num_args(rhs); + ast const_term = zero; + int i = 0; + if(nargs > 0 && op(arg(rhs,0)) == Numeral){ + const_term = arg(rhs,0); + i++; + } + if(i < nargs){ + std::vector non_const; + for(; i < nargs; i++) + non_const.push_back(arg(rhs,i)); + lhs = make(Sub,lhs,make(Plus,non_const)); + } + rhs = const_term; + } + else { + lhs = make(Sub,lhs,make(Plus,rhs)); + rhs = zero; + } + lhs = z3_simplify(lhs); + rhs = z3_simplify(rhs); + thing = make(op(thing),lhs,rhs); + } + return thing; + } + + void get_linear_coefficients(const ast &t, std::vector &coeffs){ + if(op(t) == Plus){ + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + coeffs.push_back(get_coeff(arg(t,i))); + } + else + coeffs.push_back(get_coeff(t)); + } + + /* given an affine term t, get the GCD of the coefficients in t. */ + ast gcd_of_coefficients(const ast &t){ + std::vector coeffs; + get_linear_coefficients(t,coeffs); + if(coeffs.size() == 0) + return make_int("1"); // arbitrary + rational d = coeffs[0]; + for(unsigned i = 1; i < coeffs.size(); i++){ + d = gcd(d,coeffs[i]); + } + return make_int(d); + } + + ast get_bounded_variable(const ast &ineq, bool &lb){ + ast nineq = normalize_inequality(ineq); + ast lhs = arg(nineq,0); + switch(op(lhs)){ + case Uninterpreted: + lb = false; + return lhs; + case Times: + if(arg(lhs,0) == make_int(rational(1))) + lb = false; + else if(arg(lhs,0) == make_int(rational(-1))) + lb = true; + else + throw unsupported(); + return arg(lhs,1); + default: + throw unsupported(); + } + } + + rational get_term_coefficient(const ast &t1, const ast &v){ + ast t = arg(normalize_inequality(t1),0); + if(op(t) == Plus){ + int nargs = num_args(t); + for(int i = 0; i < nargs; i++){ + if(get_linear_var(arg(t,i)) == v) + return get_coeff(arg(t,i)); + } + } + else + if(get_linear_var(t) == v) + return get_coeff(t); + return rational(0); + } + + + Iproof::node GCDtoDivRule(const ast &proof, bool pol, std::vector &coeffs, std::vector &prems, ast &cut_con){ + // gather the summands of the desired polarity + std::vector my_prems; + std::vector my_coeffs; + std::vector my_prem_cons; + for(unsigned i = pol ? 0 : 1; i < coeffs.size(); i+= 2){ + rational &c = coeffs[i]; + if(c.is_pos()){ + my_prems.push_back(prems[i]); + my_coeffs.push_back(make_int(c)); + my_prem_cons.push_back(conc(prem(proof,i))); + } + } + ast my_con = sum_inequalities(my_coeffs,my_prem_cons); + + // handle generalized GCD test. sadly, we dont' get the coefficients... + if(coeffs[0].is_zero()){ + bool lb; + int xtra_prem = 0; + ast bv = get_bounded_variable(conc(prem(proof,0)),lb); + rational bv_coeff = get_term_coefficient(my_con,bv); + if(bv_coeff.is_pos() != lb) + xtra_prem = 1; + if(bv_coeff.is_neg()) + bv_coeff = -bv_coeff; + + my_prems.push_back(prems[xtra_prem]); + my_coeffs.push_back(make_int(bv_coeff)); + my_prem_cons.push_back(conc(prem(proof,xtra_prem))); + my_con = sum_inequalities(my_coeffs,my_prem_cons); + } + + my_con = normalize_inequality(my_con); + Iproof::node hyp = iproof->make_hypothesis(mk_not(my_con)); + my_prems.push_back(hyp); + my_coeffs.push_back(make_int("1")); + my_prem_cons.push_back(mk_not(my_con)); + Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_prem_cons,my_coeffs); + + ast t = arg(my_con,0); + ast c = arg(my_con,1); + ast d = gcd_of_coefficients(t); + t = z3_simplify(mk_idiv(t,d)); + c = z3_simplify(mk_idiv(c,d)); + cut_con = make(op(my_con),t,c); + return iproof->make_cut_rule(my_con,d,cut_con,res); + } + + + rational get_first_coefficient(const ast &t, ast &v){ + if(op(t) == Plus){ + unsigned best_id = UINT_MAX; + rational best_coeff(0); + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + if(op(arg(t,i)) != Numeral){ + ast lv = get_linear_var(arg(t,i)); + unsigned id = ast_id(lv); + if(id < best_id) { + v = lv; + best_id = id; + best_coeff = get_coeff(arg(t,i)); + } + } + return best_coeff; + } + else + if(op(t) != Numeral) + return(get_coeff(t)); + return rational(0); + } + + ast divide_inequalities(const ast &x, const ast&y){ + ast xvar, yvar; + rational xcoeff = get_first_coefficient(arg(x,0),xvar); + rational ycoeff = get_first_coefficient(arg(y,0),yvar); + if(xcoeff == rational(0) || ycoeff == rational(0) || xvar != yvar) + throw "bad assign-bounds lemma"; + rational ratio = xcoeff/ycoeff; + if(denominator(ratio) != rational(1)) + throw "bad assign-bounds lemma"; + return make_int(ratio); // better be integer! + } + + ast AssignBounds2Farkas(const ast &proof, const ast &con){ + std::vector farkas_coeffs; + get_assign_bounds_coeffs(proof,farkas_coeffs); + int nargs = num_args(con); + if(nargs != (int)(farkas_coeffs.size())) + throw "bad assign-bounds theory lemma"; #if 0 - if(farkas_coeffs[0] != make_int(rational(1))) - farkas_coeffs[0] = make_int(rational(1)); + if(farkas_coeffs[0] != make_int(rational(1))) + farkas_coeffs[0] = make_int(rational(1)); #else - std::vector lits, lit_coeffs; - for(int i = 1; i < nargs; i++){ - lits.push_back(mk_not(arg(con,i))); - lit_coeffs.push_back(farkas_coeffs[i]); - } - ast sum = normalize_inequality(sum_inequalities(lit_coeffs,lits)); - ast conseq = normalize_inequality(arg(con,0)); - ast d = divide_inequalities(sum,conseq); + std::vector lits, lit_coeffs; + for(int i = 1; i < nargs; i++){ + lits.push_back(mk_not(arg(con,i))); + lit_coeffs.push_back(farkas_coeffs[i]); + } + ast sum = normalize_inequality(sum_inequalities(lit_coeffs,lits)); + ast conseq = normalize_inequality(arg(con,0)); + ast d = divide_inequalities(sum,conseq); #if 0 - if(d != farkas_coeffs[0]) - std::cout << "wow!\n"; + if(d != farkas_coeffs[0]) + std::cout << "wow!\n"; #endif - farkas_coeffs[0] = d; + farkas_coeffs[0] = d; #endif - std::vector my_coeffs; - std::vector my_cons; - for(int i = 1; i < nargs; i++){ - my_cons.push_back(mk_not(arg(con,i))); - my_coeffs.push_back(farkas_coeffs[i]); + std::vector my_coeffs; + std::vector my_cons; + for(int i = 1; i < nargs; i++){ + my_cons.push_back(mk_not(arg(con,i))); + my_coeffs.push_back(farkas_coeffs[i]); + } + ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */)); + my_cons.push_back(mk_not(farkas_con)); + my_coeffs.push_back(make_int("1")); + std::vector my_hyps; + for(int i = 0; i < nargs; i++) + my_hyps.push_back(iproof->make_hypothesis(my_cons[i])); + ast res = iproof->make_farkas(mk_false(),my_hyps,my_cons,my_coeffs); + res = iproof->make_cut_rule(farkas_con,farkas_coeffs[0],arg(con,0),res); + return res; } - ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */)); - my_cons.push_back(mk_not(farkas_con)); - my_coeffs.push_back(make_int("1")); - std::vector my_hyps; - for(int i = 0; i < nargs; i++) - my_hyps.push_back(iproof->make_hypothesis(my_cons[i])); - ast res = iproof->make_farkas(mk_false(),my_hyps,my_cons,my_coeffs); - res = iproof->make_cut_rule(farkas_con,farkas_coeffs[0],arg(con,0),res); - return res; - } - ast AssignBoundsRule2Farkas(const ast &proof, const ast &con, std::vector prems){ - std::vector farkas_coeffs; - get_assign_bounds_rule_coeffs(proof,farkas_coeffs); - int nargs = num_prems(proof)+1; - if(nargs != (int)(farkas_coeffs.size())) - throw "bad assign-bounds theory lemma"; + ast AssignBoundsRule2Farkas(const ast &proof, const ast &con, std::vector prems){ + std::vector farkas_coeffs; + get_assign_bounds_rule_coeffs(proof,farkas_coeffs); + int nargs = num_prems(proof)+1; + if(nargs != (int)(farkas_coeffs.size())) + throw "bad assign-bounds theory lemma"; #if 0 - if(farkas_coeffs[0] != make_int(rational(1))) - farkas_coeffs[0] = make_int(rational(1)); + if(farkas_coeffs[0] != make_int(rational(1))) + farkas_coeffs[0] = make_int(rational(1)); #else - std::vector lits, lit_coeffs; - for(int i = 1; i < nargs; i++){ - lits.push_back(conc(prem(proof,i-1))); - lit_coeffs.push_back(farkas_coeffs[i]); - } - ast sum = normalize_inequality(sum_inequalities(lit_coeffs,lits)); - ast conseq = normalize_inequality(con); - ast d = divide_inequalities(sum,conseq); + std::vector lits, lit_coeffs; + for(int i = 1; i < nargs; i++){ + lits.push_back(conc(prem(proof,i-1))); + lit_coeffs.push_back(farkas_coeffs[i]); + } + ast sum = normalize_inequality(sum_inequalities(lit_coeffs,lits)); + ast conseq = normalize_inequality(con); + ast d = divide_inequalities(sum,conseq); #if 0 - if(d != farkas_coeffs[0]) - std::cout << "wow!\n"; + if(d != farkas_coeffs[0]) + std::cout << "wow!\n"; #endif - farkas_coeffs[0] = d; + farkas_coeffs[0] = d; #endif - std::vector my_coeffs; - std::vector my_cons; - for(int i = 1; i < nargs; i++){ - my_cons.push_back(conc(prem(proof,i-1))); - my_coeffs.push_back(farkas_coeffs[i]); + std::vector my_coeffs; + std::vector my_cons; + for(int i = 1; i < nargs; i++){ + my_cons.push_back(conc(prem(proof,i-1))); + my_coeffs.push_back(farkas_coeffs[i]); + } + ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */)); + std::vector my_hyps; + for(int i = 1; i < nargs; i++) + my_hyps.push_back(prems[i-1]); + my_cons.push_back(mk_not(farkas_con)); + my_coeffs.push_back(make_int("1")); + my_hyps.push_back(iproof->make_hypothesis(mk_not(farkas_con))); + ast res = iproof->make_farkas(mk_false(),my_hyps,my_cons,my_coeffs); + res = iproof->make_cut_rule(farkas_con,farkas_coeffs[0],conc(proof),res); + return res; } - ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */)); - std::vector my_hyps; - for(int i = 1; i < nargs; i++) - my_hyps.push_back(prems[i-1]); - my_cons.push_back(mk_not(farkas_con)); - my_coeffs.push_back(make_int("1")); - my_hyps.push_back(iproof->make_hypothesis(mk_not(farkas_con))); - ast res = iproof->make_farkas(mk_false(),my_hyps,my_cons,my_coeffs); - res = iproof->make_cut_rule(farkas_con,farkas_coeffs[0],conc(proof),res); - return res; - } - Iproof::node RewriteClause(Iproof::node clause, const ast &rew){ - if(pr(rew) == PR_MONOTONICITY){ - int nequivs = num_prems(rew); - for(int i = 0; i < nequivs; i++){ - Iproof::node equiv_pf = translate_main(prem(rew,i),false); - ast equiv = conc(prem(rew,i)); - clause = iproof->make_mp(equiv,clause,equiv_pf); - } - return clause; + Iproof::node RewriteClause(Iproof::node clause, const ast &rew){ + if(pr(rew) == PR_MONOTONICITY){ + int nequivs = num_prems(rew); + for(int i = 0; i < nequivs; i++){ + Iproof::node equiv_pf = translate_main(prem(rew,i),false); + ast equiv = conc(prem(rew,i)); + clause = iproof->make_mp(equiv,clause,equiv_pf); + } + return clause; + } + if(pr(rew) == PR_TRANSITIVITY){ + clause = RewriteClause(clause,prem(rew,0)); + clause = RewriteClause(clause,prem(rew,1)); + return clause; + } + if(pr(rew) == PR_REWRITE){ + return clause; // just hope the rewrite does nothing! + } + throw unsupported(); } - if(pr(rew) == PR_TRANSITIVITY){ - clause = RewriteClause(clause,prem(rew,0)); - clause = RewriteClause(clause,prem(rew,1)); - return clause; + + + // Following code is for elimination of "commutativity" axiom + + Iproof::node make_commuted_modus_ponens(const ast &proof, const std::vector &args){ + ast pf = arg(args[1],0); + ast comm_equiv = arg(args[1],1); // equivalence relation with possible commutations + ast P = conc(prem(proof,0)); + ast Q = conc(proof); + Iproof::node P_pf = args[0]; + ast P_comm = arg(comm_equiv,0); + ast Q_comm = arg(comm_equiv,1); + if(P != P_comm) + P_pf = iproof->make_symmetry(P_comm,P,P_pf); + Iproof::node res = iproof->make_mp(comm_equiv,P_pf,pf); + if(Q != Q_comm) + res = iproof->make_symmetry(Q,Q_comm,res); + return res; } - if(pr(rew) == PR_REWRITE){ - return clause; // just hope the rewrite does nothing! + + Iproof::node make_commuted_monotonicity(const ast &proof, const std::vector &args){ + ast pf = arg(args[0],0); + ast comm_equiv = arg(args[0],1); // equivalence relation with possible commutations + ast con = make(Iff,make(Not,arg(comm_equiv,0)),make(Not,arg(comm_equiv,1))); + std::vector eqs; eqs.push_back(comm_equiv); + std::vector pfs; pfs.push_back(pf); + ast res = iproof->make_congruence(eqs,con,pfs); + res = make(commute,res,con); + return res; } - throw unsupported(); - } - - // Following code is for elimination of "commutativity" axiom - - Iproof::node make_commuted_modus_ponens(const ast &proof, const std::vector &args){ - ast pf = arg(args[1],0); - ast comm_equiv = arg(args[1],1); // equivalence relation with possible commutations - ast P = conc(prem(proof,0)); - ast Q = conc(proof); - Iproof::node P_pf = args[0]; - ast P_comm = arg(comm_equiv,0); - ast Q_comm = arg(comm_equiv,1); - if(P != P_comm) - P_pf = iproof->make_symmetry(P_comm,P,P_pf); - Iproof::node res = iproof->make_mp(comm_equiv,P_pf,pf); - if(Q != Q_comm) - res = iproof->make_symmetry(Q,Q_comm,res); - return res; - } - - Iproof::node make_commuted_monotonicity(const ast &proof, const std::vector &args){ - ast pf = arg(args[0],0); - ast comm_equiv = arg(args[0],1); // equivalence relation with possible commutations - ast con = make(Iff,make(Not,arg(comm_equiv,0)),make(Not,arg(comm_equiv,1))); - std::vector eqs; eqs.push_back(comm_equiv); - std::vector pfs; pfs.push_back(pf); - ast res = iproof->make_congruence(eqs,con,pfs); - res = make(commute,res,con); - return res; - } - - Iproof::node make_commuted_symmetry(const ast &proof, const std::vector &args){ - ast pf = arg(args[0],0); - ast comm_equiv = arg(args[0],1); // equivalence relation with possible commutations - ast con = make(Iff,arg(comm_equiv,1),arg(comm_equiv,0)); - ast res = iproof->make_symmetry(con,comm_equiv,pf); - res = make(commute,res,con); - return res; - } - - void unpack_commuted(const ast &proof, const ast &cm, ast &pf, ast &comm_equiv){ - if(sym(cm) == commute){ - pf = arg(cm,0); - comm_equiv = arg(cm,1); + Iproof::node make_commuted_symmetry(const ast &proof, const std::vector &args){ + ast pf = arg(args[0],0); + ast comm_equiv = arg(args[0],1); // equivalence relation with possible commutations + ast con = make(Iff,arg(comm_equiv,1),arg(comm_equiv,0)); + ast res = iproof->make_symmetry(con,comm_equiv,pf); + res = make(commute,res,con); + return res; } - else { - pf = cm; - comm_equiv = conc(proof); + + void unpack_commuted(const ast &proof, const ast &cm, ast &pf, ast &comm_equiv){ + if(sym(cm) == commute){ + pf = arg(cm,0); + comm_equiv = arg(cm,1); + } + else { + pf = cm; + comm_equiv = conc(proof); + } } - } - Iproof::node make_commuted_transitivity(const ast &proof, const std::vector &args){ - ast pf[2], comm_equiv[2]; - for(int i = 0; i < 2; i++) - unpack_commuted(prem(proof,i),args[i],pf[i],comm_equiv[i]); - if(!(arg(comm_equiv[0],1) == arg(comm_equiv[1],0))){ - ast tw = twist(prem(proof,1)); - ast np = translate_main(tw,false); - unpack_commuted(tw,np,pf[1],comm_equiv[1]); - } - ast con = make(Iff,arg(comm_equiv[0],0),arg(comm_equiv[1],1)); - ast res = iproof->make_transitivity(arg(comm_equiv[0],0),arg(comm_equiv[0],1),arg(comm_equiv[1],1),pf[0],pf[1]); - res = make(commute,res,con); - return res; - } + Iproof::node make_commuted_transitivity(const ast &proof, const std::vector &args){ + ast pf[2], comm_equiv[2]; + for(int i = 0; i < 2; i++) + unpack_commuted(prem(proof,i),args[i],pf[i],comm_equiv[i]); + if(!(arg(comm_equiv[0],1) == arg(comm_equiv[1],0))){ + ast tw = twist(prem(proof,1)); + ast np = translate_main(tw,false); + unpack_commuted(tw,np,pf[1],comm_equiv[1]); + } + ast con = make(Iff,arg(comm_equiv[0],0),arg(comm_equiv[1],1)); + ast res = iproof->make_transitivity(arg(comm_equiv[0],0),arg(comm_equiv[0],1),arg(comm_equiv[1],1),pf[0],pf[1]); + res = make(commute,res,con); + return res; + } - ast commute_equality(const ast &eq){ - return make(Equal,arg(eq,1),arg(eq,0)); - } + ast commute_equality(const ast &eq){ + return make(Equal,arg(eq,1),arg(eq,0)); + } - ast commute_equality_iff(const ast &con){ - if(op(con) != Iff || op(arg(con,0)) != Equal) - throw unsupported(); - return make(Iff,commute_equality(arg(con,0)),commute_equality(arg(con,1))); - } + ast commute_equality_iff(const ast &con){ + if(op(con) != Iff || op(arg(con,0)) != Equal) + throw unsupported(); + return make(Iff,commute_equality(arg(con,0)),commute_equality(arg(con,1))); + } - // convert a proof of a=b <-> c=d into a proof of b=a <-> d=c - // TODO: memoize this? - ast twist(const ast &proof){ - pfrule dk = pr(proof); - ast con = commute_equality_iff(conc(proof)); - int n = num_prems(proof); - std::vector prs(n); - if(dk == PR_MONOTONICITY){ - for(int i = 0; i < n; i++) - prs[i] = prem(proof,i); - } - else - for(int i = 0; i < n; i++) - prs[i] = twist(prem(proof,i)); - switch(dk){ - case PR_MONOTONICITY: - case PR_SYMMETRY: - case PR_TRANSITIVITY: - case PR_COMMUTATIVITY: - prs.push_back(con); - return clone(proof,prs); - default: - throw unsupported(); - } - } - - struct TermLt { - iz3mgr &m; - bool operator()(const ast &x, const ast &y){ - unsigned xid = m.ast_id(x); - unsigned yid = m.ast_id(y); - return xid < yid; - } - TermLt(iz3mgr &_m) : m(_m) {} - }; - - void SortTerms(std::vector &terms){ - TermLt foo(*this); - std::sort(terms.begin(),terms.end(),foo); - } - - ast SortSum(const ast &t){ - if(!(op(t) == Plus)) - return t; - int nargs = num_args(t); - if(nargs < 2) return t; - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = arg(t,i); - SortTerms(args); - return make(Plus,args); - } - - void get_sum_as_vector(const ast &t, std::vector &coeffs, std::vector &vars){ - if(!(op(t) == Plus)){ - coeffs.push_back(get_coeff(t)); - vars.push_back(get_linear_var(t)); - } - else { - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - get_sum_as_vector(arg(t,i),coeffs,vars); - } - } - - ast replace_summands_with_fresh_vars(const ast &t, hash_map &map){ - if(op(t) == Plus){ - int nargs = num_args(t); - std::vector args(nargs); - for(int i = 0; i < nargs; i++) - args[i] = replace_summands_with_fresh_vars(arg(t,i),map); - return make(Plus,args); - } - if(op(t) == Times) - return make(Times,arg(t,0),replace_summands_with_fresh_vars(arg(t,1),map)); - if(map.find(t) == map.end()) - map[t] = mk_fresh_constant("@s",get_type(t)); - return map[t]; - } - - rational lcd(const std::vector &rats){ - rational res = rational(1); - for(unsigned i = 0; i < rats.size(); i++){ - res = lcm(res,denominator(rats[i])); - } - return res; - } - - Iproof::node reconstruct_farkas_with_dual(const std::vector &prems, const std::vector &pfs, const ast &con){ - int nprems = prems.size(); - std::vector npcons(nprems); - hash_map pain_map; // not needed - for(int i = 0; i < nprems; i++){ - npcons[i] = painfully_normalize_ineq(conc(prems[i]),pain_map); - if(op(npcons[i]) == Lt){ - ast constval = z3_simplify(make(Sub,arg(npcons[i],1),make_int(rational(1)))); - npcons[i] = make(Leq,arg(npcons[i],0),constval); - } - } - ast ncon = painfully_normalize_ineq(mk_not(con),pain_map); - npcons.push_back(ncon); - - hash_map dual_map; - std::vector cvec, vars_seen; - ast rhs = make_real(rational(0)); - for(unsigned i = 0; i < npcons.size(); i++){ - ast c= mk_fresh_constant("@c",real_type()); - cvec.push_back(c); - ast lhs = arg(npcons[i],0); - std::vector coeffs; - std::vector vars; - get_sum_as_vector(lhs,coeffs,vars); - for(unsigned j = 0; j < coeffs.size(); j++){ - rational coeff = coeffs[j]; - ast var = vars[j]; - if(dual_map.find(var) == dual_map.end()){ - dual_map[var] = make_real(rational(0)); - vars_seen.push_back(var); - } - ast foo = make(Plus,dual_map[var],make(Times,make_real(coeff),c)); - dual_map[var] = foo; - } - rhs = make(Plus,rhs,make(Times,c,arg(npcons[i],1))); - } - std::vector cnstrs; - for(unsigned i = 0; i < vars_seen.size(); i++) - cnstrs.push_back(make(Equal,dual_map[vars_seen[i]],make_real(rational(0)))); - cnstrs.push_back(make(Leq,rhs,make_real(rational(0)))); - for(unsigned i = 0; i < cvec.size() - 1; i++) - cnstrs.push_back(make(Geq,cvec[i],make_real(rational(0)))); - cnstrs.push_back(make(Equal,cvec.back(),make_real(rational(1)))); - ast new_proof; - - // greedily reduce the core - for(unsigned i = 0; i < cvec.size() - 1; i++){ - std::vector dummy; - cnstrs.push_back(make(Equal,cvec[i],make_real(rational(0)))); - if(!is_sat(cnstrs,new_proof,dummy)) - cnstrs.pop_back(); + // convert a proof of a=b <-> c=d into a proof of b=a <-> d=c + // TODO: memoize this? + ast twist(const ast &proof){ + pfrule dk = pr(proof); + ast con = commute_equality_iff(conc(proof)); + int n = num_prems(proof); + std::vector prs(n); + if(dk == PR_MONOTONICITY){ + for(int i = 0; i < n; i++) + prs[i] = prem(proof,i); + } + else + for(int i = 0; i < n; i++) + prs[i] = twist(prem(proof,i)); + switch(dk){ + case PR_MONOTONICITY: + case PR_SYMMETRY: + case PR_TRANSITIVITY: + case PR_COMMUTATIVITY: + prs.push_back(con); + return clone(proof,prs); + default: + throw unsupported(); + } } - std::vector vals = cvec; - if(!is_sat(cnstrs,new_proof,vals)) - throw "Proof error!"; - std::vector rat_farkas_coeffs; - for(unsigned i = 0; i < cvec.size(); i++){ - ast bar = vals[i]; - rational r; - if(is_numeral(bar,r)) - rat_farkas_coeffs.push_back(r); - else - throw "Proof error!"; + struct TermLt { + iz3mgr &m; + bool operator()(const ast &x, const ast &y){ + unsigned xid = m.ast_id(x); + unsigned yid = m.ast_id(y); + return xid < yid; + } + TermLt(iz3mgr &_m) : m(_m) {} + }; + + void SortTerms(std::vector &terms){ + TermLt foo(*this); + std::sort(terms.begin(),terms.end(),foo); } - rational the_lcd = lcd(rat_farkas_coeffs); - std::vector farkas_coeffs; - std::vector my_prems; - std::vector my_pcons; - for(unsigned i = 0; i < prems.size(); i++){ - ast fc = make_int(rat_farkas_coeffs[i] * the_lcd); - if(!(fc == make_int(rational(0)))){ - farkas_coeffs.push_back(fc); - my_prems.push_back(pfs[i]); - my_pcons.push_back(conc(prems[i])); - } + + ast SortSum(const ast &t){ + if(!(op(t) == Plus)) + return t; + int nargs = num_args(t); + if(nargs < 2) return t; + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = arg(t,i); + SortTerms(args); + return make(Plus,args); } - farkas_coeffs.push_back(make_int(the_lcd)); - my_prems.push_back(iproof->make_hypothesis(mk_not(con))); - my_pcons.push_back(mk_not(con)); + + void get_sum_as_vector(const ast &t, std::vector &coeffs, std::vector &vars){ + if(!(op(t) == Plus)){ + coeffs.push_back(get_coeff(t)); + vars.push_back(get_linear_var(t)); + } + else { + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + get_sum_as_vector(arg(t,i),coeffs,vars); + } + } + + ast replace_summands_with_fresh_vars(const ast &t, hash_map &map){ + if(op(t) == Plus){ + int nargs = num_args(t); + std::vector args(nargs); + for(int i = 0; i < nargs; i++) + args[i] = replace_summands_with_fresh_vars(arg(t,i),map); + return make(Plus,args); + } + if(op(t) == Times) + return make(Times,arg(t,0),replace_summands_with_fresh_vars(arg(t,1),map)); + if(map.find(t) == map.end()) + map[t] = mk_fresh_constant("@s",get_type(t)); + return map[t]; + } + + rational lcd(const std::vector &rats){ + rational res = rational(1); + for(unsigned i = 0; i < rats.size(); i++){ + res = lcm(res,denominator(rats[i])); + } + return res; + } + + Iproof::node reconstruct_farkas_with_dual(const std::vector &prems, const std::vector &pfs, const ast &con){ + int nprems = prems.size(); + std::vector npcons(nprems); + hash_map pain_map; // not needed + for(int i = 0; i < nprems; i++){ + npcons[i] = painfully_normalize_ineq(conc(prems[i]),pain_map); + if(op(npcons[i]) == Lt){ + ast constval = z3_simplify(make(Sub,arg(npcons[i],1),make_int(rational(1)))); + npcons[i] = make(Leq,arg(npcons[i],0),constval); + } + } + ast ncon = painfully_normalize_ineq(mk_not(con),pain_map); + npcons.push_back(ncon); + + hash_map dual_map; + std::vector cvec, vars_seen; + ast rhs = make_real(rational(0)); + for(unsigned i = 0; i < npcons.size(); i++){ + ast c= mk_fresh_constant("@c",real_type()); + cvec.push_back(c); + ast lhs = arg(npcons[i],0); + std::vector coeffs; + std::vector vars; + get_sum_as_vector(lhs,coeffs,vars); + for(unsigned j = 0; j < coeffs.size(); j++){ + rational coeff = coeffs[j]; + ast var = vars[j]; + if(dual_map.find(var) == dual_map.end()){ + dual_map[var] = make_real(rational(0)); + vars_seen.push_back(var); + } + ast foo = make(Plus,dual_map[var],make(Times,make_real(coeff),c)); + dual_map[var] = foo; + } + rhs = make(Plus,rhs,make(Times,c,arg(npcons[i],1))); + } + std::vector cnstrs; + for(unsigned i = 0; i < vars_seen.size(); i++) + cnstrs.push_back(make(Equal,dual_map[vars_seen[i]],make_real(rational(0)))); + cnstrs.push_back(make(Leq,rhs,make_real(rational(0)))); + for(unsigned i = 0; i < cvec.size() - 1; i++) + cnstrs.push_back(make(Geq,cvec[i],make_real(rational(0)))); + cnstrs.push_back(make(Equal,cvec.back(),make_real(rational(1)))); + ast new_proof; + + // greedily reduce the core + for(unsigned i = 0; i < cvec.size() - 1; i++){ + std::vector dummy; + cnstrs.push_back(make(Equal,cvec[i],make_real(rational(0)))); + if(!is_sat(cnstrs,new_proof,dummy)) + cnstrs.pop_back(); + } + + std::vector vals = cvec; + if(!is_sat(cnstrs,new_proof,vals)) + throw "Proof error!"; + std::vector rat_farkas_coeffs; + for(unsigned i = 0; i < cvec.size(); i++){ + ast bar = vals[i]; + rational r; + if(is_numeral(bar,r)) + rat_farkas_coeffs.push_back(r); + else + throw "Proof error!"; + } + rational the_lcd = lcd(rat_farkas_coeffs); + std::vector farkas_coeffs; + std::vector my_prems; + std::vector my_pcons; + for(unsigned i = 0; i < prems.size(); i++){ + ast fc = make_int(rat_farkas_coeffs[i] * the_lcd); + if(!(fc == make_int(rational(0)))){ + farkas_coeffs.push_back(fc); + my_prems.push_back(pfs[i]); + my_pcons.push_back(conc(prems[i])); + } + } + farkas_coeffs.push_back(make_int(the_lcd)); + my_prems.push_back(iproof->make_hypothesis(mk_not(con))); + my_pcons.push_back(mk_not(con)); - Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); - return res; - } - - ast painfully_normalize_ineq(const ast &ineq, hash_map &map){ - ast res = normalize_inequality(ineq); - ast lhs = arg(res,0); - lhs = replace_summands_with_fresh_vars(lhs,map); - res = make(op(res),SortSum(lhs),arg(res,1)); - return res; - } - - Iproof::node painfully_reconstruct_farkas(const std::vector &prems, const std::vector &pfs, const ast &con){ - int nprems = prems.size(); - std::vector pcons(nprems),npcons(nprems); - hash_map pcon_to_pf, npcon_to_pcon, pain_map; - for(int i = 0; i < nprems; i++){ - pcons[i] = conc(prems[i]); - npcons[i] = painfully_normalize_ineq(pcons[i],pain_map); - pcon_to_pf[npcons[i]] = pfs[i]; - npcon_to_pcon[npcons[i]] = pcons[i]; - } - // ast leq = make(Leq,arg(con,0),arg(con,1)); - ast ncon = painfully_normalize_ineq(mk_not(con),pain_map); - pcons.push_back(mk_not(con)); - npcons.push_back(ncon); - // ast assumps = make(And,pcons); - ast new_proof; - std::vector dummy; - if(is_sat(npcons,new_proof,dummy)) - throw "Proof error!"; - pfrule dk = pr(new_proof); - int nnp = num_prems(new_proof); - std::vector my_prems; - std::vector farkas_coeffs, my_pcons; - - if(dk == PR_TH_LEMMA - && get_theory_lemma_theory(new_proof) == ArithTheory - && get_theory_lemma_kind(new_proof) == FarkasKind) - get_farkas_coeffs(new_proof,farkas_coeffs); - else if(dk == PR_UNIT_RESOLUTION && nnp == 2){ - for(int i = 0; i < nprems; i++) - farkas_coeffs.push_back(make_int(rational(1))); - } - else - return reconstruct_farkas_with_dual(prems,pfs,con); - - for(int i = 0; i < nnp; i++){ - ast p = conc(prem(new_proof,i)); - p = really_normalize_ineq(p); - if(pcon_to_pf.find(p) != pcon_to_pf.end()){ - my_prems.push_back(pcon_to_pf[p]); - my_pcons.push_back(npcon_to_pcon[p]); - } - else if(p == ncon){ - my_prems.push_back(iproof->make_hypothesis(mk_not(con))); - my_pcons.push_back(mk_not(con)); - } - else - return reconstruct_farkas_with_dual(prems,pfs,con); - } - Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); - return res; - } - - - - ast really_normalize_ineq(const ast &ineq){ - ast res = normalize_inequality(ineq); - res = make(op(res),SortSum(arg(res,0)),arg(res,1)); - return res; - } - - Iproof::node reconstruct_farkas(const std::vector &prems, const std::vector &pfs, const ast &con){ - int nprems = prems.size(); - std::vector pcons(nprems),npcons(nprems); - hash_map pcon_to_pf, npcon_to_pcon; - for(int i = 0; i < nprems; i++){ - pcons[i] = conc(prems[i]); - npcons[i] = really_normalize_ineq(pcons[i]); - pcon_to_pf[npcons[i]] = pfs[i]; - npcon_to_pcon[npcons[i]] = pcons[i]; - } - // ast leq = make(Leq,arg(con,0),arg(con,1)); - ast ncon = really_normalize_ineq(mk_not(con)); - pcons.push_back(mk_not(con)); - npcons.push_back(ncon); - // ast assumps = make(And,pcons); - ast new_proof; - std::vector dummy; - if(is_sat(npcons,new_proof,dummy)) - throw "Proof error!"; - pfrule dk = pr(new_proof); - int nnp = num_prems(new_proof); - std::vector my_prems; - std::vector farkas_coeffs, my_pcons; - - if(dk == PR_TH_LEMMA - && get_theory_lemma_theory(new_proof) == ArithTheory - && get_theory_lemma_kind(new_proof) == FarkasKind) - get_farkas_coeffs(new_proof,farkas_coeffs); - else if(dk == PR_UNIT_RESOLUTION && nnp == 2){ - for(int i = 0; i < nprems; i++) - farkas_coeffs.push_back(make_int(rational(1))); - } - else - return painfully_reconstruct_farkas(prems,pfs,con); - - for(int i = 0; i < nnp; i++){ - ast p = conc(prem(new_proof,i)); - p = really_normalize_ineq(p); - if(pcon_to_pf.find(p) != pcon_to_pf.end()){ - my_prems.push_back(pcon_to_pf[p]); - my_pcons.push_back(npcon_to_pcon[p]); - } - else if(p == ncon){ - my_prems.push_back(iproof->make_hypothesis(mk_not(con))); - my_pcons.push_back(mk_not(con)); - } - else - return painfully_reconstruct_farkas(prems,pfs,con); - } - Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); - return res; - } - - bool is_eq_propagate(const ast &proof){ - return pr(proof) == PR_TH_LEMMA && get_theory_lemma_theory(proof) == ArithTheory && get_theory_lemma_kind(proof) == EqPropagateKind; - } - - ast EqPropagate(const ast &con, const std::vector &prems, const std::vector &args){ - Iproof::node fps[2]; - ast ineq_con[2]; - for(int i = 0; i < 2; i++){ - opr o = i == 0 ? Leq : Geq; - ineq_con[i] = make(o, arg(con,0), arg(con,1)); - fps[i] = reconstruct_farkas(prems,args,ineq_con[i]); - } - ast res = iproof->make_leq2eq(arg(con,0), arg(con,1), ineq_con[0], ineq_con[1]); - std::vector dummy_clause; - for(int i = 0; i < 2; i++) - res = iproof->make_resolution(ineq_con[i],dummy_clause,res,fps[i]); - return res; - } - - ast ArithMysteryRule(const ast &con, const std::vector &prems, const std::vector &args){ - // Hope for the best! - Iproof::node guess = reconstruct_farkas(prems,args,con); - return guess; - } - - struct CannotCombineEqPropagate {}; - - void CombineEqPropagateRec(const ast &proof, std::vector &prems, std::vector &args, ast &eqprem){ - if(pr(proof) == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){ - CombineEqPropagateRec(prem(proof,0), prems, args, eqprem); - ast dummy; - CombineEqPropagateRec(prem(proof,1), prems, args, dummy); - return; - } - if(is_eq_propagate(proof)){ - int nprems = num_prems(proof); - for(int i = 0; i < nprems; i++){ - prems.push_back(prem(proof,i)); - ast ppf = translate_main(prem(proof,i),false); - args.push_back(ppf); - } - return; - } - eqprem = proof; - } - - ast CombineEqPropagate(const ast &proof){ - std::vector prems, args; - ast eq1; - CombineEqPropagateRec(proof, prems, args, eq1); - ast eq2con = conc(proof); - if(!eq1.null()) - eq2con = make(Equal,arg(conc(eq1),1),arg(conc(proof),1)); - ast eq2 = EqPropagate(eq2con,prems,args); - if(!eq1.null()){ - Iproof::node foo = translate_main(eq1,false); - eq2 = iproof->make_transitivity(arg(conc(eq1),0), arg(conc(eq1),1), arg(conc(proof),1), foo, eq2); - } - return eq2; - } - - bool get_store_array(const ast &t, ast &res){ - if(op(t) == Store){ - res = t; - return true; - } - int nargs = num_args(t); - for(int i = 0; i < nargs; i++) - if(get_store_array(arg(t,i),res)) - return true; - return false; - } - - // translate a Z3 proof term into interpolating proof system - - Iproof::node translate_main(ast proof, bool expect_clause = true){ - AstToIpf &tr = translation; - hash_map &trc = expect_clause ? tr.first : tr.second; - std::pair foo(proof,Iproof::node()); - std::pair::iterator, bool> bar = trc.insert(foo); - Iproof::node &res = bar.first->second; - if(!bar.second) return res; - - // Try the locality rule first - - int frame = get_locality(proof); - if(frame != -1){ - ast e = from_ast(conc(proof)); - if(frame >= frames) frame = frames - 1; - std::vector foo; - if(expect_clause) - get_Z3_lits(conc(proof),foo); - else - foo.push_back(e); - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - foo.push_back(mk_not(*it)); - res = iproof->make_assumption(frame,foo); - return res; + Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); + return res; } - // If the proof is not local, break it down by proof rule - - pfrule dk = pr(proof); - unsigned nprems = num_prems(proof); - if(dk == PR_UNIT_RESOLUTION){ - res = translate_ur(proof); + ast painfully_normalize_ineq(const ast &ineq, hash_map &map){ + ast res = normalize_inequality(ineq); + ast lhs = arg(res,0); + lhs = replace_summands_with_fresh_vars(lhs,map); + res = make(op(res),SortSum(lhs),arg(res,1)); + return res; } - else if(dk == PR_LEMMA){ - ast contra = prem(proof,0); // this is a proof of false from some hyps - res = translate_main(contra); - if(!expect_clause){ - std::vector foo; // the negations of the hyps form a clause - foo.push_back(from_ast(conc(proof))); - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - foo.push_back(mk_not(*it)); - res = iproof->make_contra(res,foo); - } + + Iproof::node painfully_reconstruct_farkas(const std::vector &prems, const std::vector &pfs, const ast &con){ + int nprems = prems.size(); + std::vector pcons(nprems),npcons(nprems); + hash_map pcon_to_pf, npcon_to_pcon, pain_map; + for(int i = 0; i < nprems; i++){ + pcons[i] = conc(prems[i]); + npcons[i] = painfully_normalize_ineq(pcons[i],pain_map); + pcon_to_pf[npcons[i]] = pfs[i]; + npcon_to_pcon[npcons[i]] = pcons[i]; + } + // ast leq = make(Leq,arg(con,0),arg(con,1)); + ast ncon = painfully_normalize_ineq(mk_not(con),pain_map); + pcons.push_back(mk_not(con)); + npcons.push_back(ncon); + // ast assumps = make(And,pcons); + ast new_proof; + std::vector dummy; + if(is_sat(npcons,new_proof,dummy)) + throw "Proof error!"; + pfrule dk = pr(new_proof); + int nnp = num_prems(new_proof); + std::vector my_prems; + std::vector farkas_coeffs, my_pcons; + + if(dk == PR_TH_LEMMA + && get_theory_lemma_theory(new_proof) == ArithTheory + && get_theory_lemma_kind(new_proof) == FarkasKind) + get_farkas_coeffs(new_proof,farkas_coeffs); + else if(dk == PR_UNIT_RESOLUTION && nnp == 2){ + for(int i = 0; i < nprems; i++) + farkas_coeffs.push_back(make_int(rational(1))); + } + else + return reconstruct_farkas_with_dual(prems,pfs,con); + + for(int i = 0; i < nnp; i++){ + ast p = conc(prem(new_proof,i)); + p = really_normalize_ineq(p); + if(pcon_to_pf.find(p) != pcon_to_pf.end()){ + my_prems.push_back(pcon_to_pf[p]); + my_pcons.push_back(npcon_to_pcon[p]); + } + else if(p == ncon){ + my_prems.push_back(iproof->make_hypothesis(mk_not(con))); + my_pcons.push_back(mk_not(con)); + } + else + return reconstruct_farkas_with_dual(prems,pfs,con); + } + Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); + return res; } - else { - std::vector lits; - ast con = conc(proof); - if(expect_clause) - get_Z3_lits(con, lits); - else - lits.push_back(from_ast(con)); - // pattern match some idioms - if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST){ - if(get_locality_rec(prem(proof,1)) == INT_MAX) { - res = iproof->make_axiom(lits); - return res; - } - } - if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or){ - Iproof::node clause = translate_main(prem(proof,0),true); - res = RewriteClause(clause,prem(proof,1)); - return res; - } - if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or) - std::cout << "foo!\n"; - // no idea why this shows up - if(dk == PR_MODUS_PONENS_OEQ){ - if(conc(prem(proof,0)) == con){ - res = translate_main(prem(proof,0),expect_clause); - return res; - } - if(expect_clause && op(con) == Or){ // skolemization does this - Iproof::node clause = translate_main(prem(proof,0),true); - res = RewriteClause(clause,prem(proof,1)); - return res; - } - } + ast really_normalize_ineq(const ast &ineq){ + ast res = normalize_inequality(ineq); + res = make(op(res),SortSum(arg(res,0)),arg(res,1)); + return res; + } + + Iproof::node reconstruct_farkas(const std::vector &prems, const std::vector &pfs, const ast &con){ + int nprems = prems.size(); + std::vector pcons(nprems),npcons(nprems); + hash_map pcon_to_pf, npcon_to_pcon; + for(int i = 0; i < nprems; i++){ + pcons[i] = conc(prems[i]); + npcons[i] = really_normalize_ineq(pcons[i]); + pcon_to_pf[npcons[i]] = pfs[i]; + npcon_to_pcon[npcons[i]] = pcons[i]; + } + // ast leq = make(Leq,arg(con,0),arg(con,1)); + ast ncon = really_normalize_ineq(mk_not(con)); + pcons.push_back(mk_not(con)); + npcons.push_back(ncon); + // ast assumps = make(And,pcons); + ast new_proof; + std::vector dummy; + if(is_sat(npcons,new_proof,dummy)) + throw "Proof error!"; + pfrule dk = pr(new_proof); + int nnp = num_prems(new_proof); + std::vector my_prems; + std::vector farkas_coeffs, my_pcons; + + if(dk == PR_TH_LEMMA + && get_theory_lemma_theory(new_proof) == ArithTheory + && get_theory_lemma_kind(new_proof) == FarkasKind) + get_farkas_coeffs(new_proof,farkas_coeffs); + else if(dk == PR_UNIT_RESOLUTION && nnp == 2){ + for(int i = 0; i < nprems; i++) + farkas_coeffs.push_back(make_int(rational(1))); + } + else + return painfully_reconstruct_farkas(prems,pfs,con); + + for(int i = 0; i < nnp; i++){ + ast p = conc(prem(new_proof,i)); + p = really_normalize_ineq(p); + if(pcon_to_pf.find(p) != pcon_to_pf.end()){ + my_prems.push_back(pcon_to_pf[p]); + my_pcons.push_back(npcon_to_pcon[p]); + } + else if(p == ncon){ + my_prems.push_back(iproof->make_hypothesis(mk_not(con))); + my_pcons.push_back(mk_not(con)); + } + else + return painfully_reconstruct_farkas(prems,pfs,con); + } + Iproof::node res = iproof->make_farkas(mk_false(),my_prems,my_pcons,farkas_coeffs); + return res; + } + + bool is_eq_propagate(const ast &proof){ + return pr(proof) == PR_TH_LEMMA && get_theory_lemma_theory(proof) == ArithTheory && get_theory_lemma_kind(proof) == EqPropagateKind; + } + + ast EqPropagate(const ast &con, const std::vector &prems, const std::vector &args){ + Iproof::node fps[2]; + ast ineq_con[2]; + for(int i = 0; i < 2; i++){ + opr o = i == 0 ? Leq : Geq; + ineq_con[i] = make(o, arg(con,0), arg(con,1)); + fps[i] = reconstruct_farkas(prems,args,ineq_con[i]); + } + ast res = iproof->make_leq2eq(arg(con,0), arg(con,1), ineq_con[0], ineq_con[1]); + std::vector dummy_clause; + for(int i = 0; i < 2; i++) + res = iproof->make_resolution(ineq_con[i],dummy_clause,res,fps[i]); + return res; + } + + ast ArithMysteryRule(const ast &con, const std::vector &prems, const std::vector &args){ + // Hope for the best! + Iproof::node guess = reconstruct_farkas(prems,args,con); + return guess; + } + + struct CannotCombineEqPropagate {}; + + void CombineEqPropagateRec(const ast &proof, std::vector &prems, std::vector &args, ast &eqprem){ + if(pr(proof) == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){ + CombineEqPropagateRec(prem(proof,0), prems, args, eqprem); + ast dummy; + CombineEqPropagateRec(prem(proof,1), prems, args, dummy); + return; + } + if(is_eq_propagate(proof)){ + int nprems = num_prems(proof); + for(int i = 0; i < nprems; i++){ + prems.push_back(prem(proof,i)); + ast ppf = translate_main(prem(proof,i),false); + args.push_back(ppf); + } + return; + } + eqprem = proof; + } + + ast CombineEqPropagate(const ast &proof){ + std::vector prems, args; + ast eq1; + CombineEqPropagateRec(proof, prems, args, eq1); + ast eq2con = conc(proof); + if(!eq1.null()) + eq2con = make(Equal,arg(conc(eq1),1),arg(conc(proof),1)); + ast eq2 = EqPropagate(eq2con,prems,args); + if(!eq1.null()){ + Iproof::node foo = translate_main(eq1,false); + eq2 = iproof->make_transitivity(arg(conc(eq1),0), arg(conc(eq1),1), arg(conc(proof),1), foo, eq2); + } + return eq2; + } + + bool get_store_array(const ast &t, ast &res){ + if(op(t) == Store){ + res = t; + return true; + } + int nargs = num_args(t); + for(int i = 0; i < nargs; i++) + if(get_store_array(arg(t,i),res)) + return true; + return false; + } + + // translate a Z3 proof term into interpolating proof system + + Iproof::node translate_main(ast proof, bool expect_clause = true){ + AstToIpf &tr = translation; + hash_map &trc = expect_clause ? tr.first : tr.second; + std::pair foo(proof,Iproof::node()); + std::pair::iterator, bool> bar = trc.insert(foo); + Iproof::node &res = bar.first->second; + if(!bar.second) return res; + + // Try the locality rule first + + int frame = get_locality(proof); + if(frame != -1){ + ast e = from_ast(conc(proof)); + if(frame >= frames) frame = frames - 1; + std::vector foo; + if(expect_clause) + get_Z3_lits(conc(proof),foo); + else + foo.push_back(e); + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + foo.push_back(mk_not(*it)); + res = iproof->make_assumption(frame,foo); + return res; + } + + // If the proof is not local, break it down by proof rule + + pfrule dk = pr(proof); + unsigned nprems = num_prems(proof); + if(dk == PR_UNIT_RESOLUTION){ + res = translate_ur(proof); + } + else if(dk == PR_LEMMA){ + ast contra = prem(proof,0); // this is a proof of false from some hyps + res = translate_main(contra); + if(!expect_clause){ + std::vector foo; // the negations of the hyps form a clause + foo.push_back(from_ast(conc(proof))); + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + foo.push_back(mk_not(*it)); + res = iproof->make_contra(res,foo); + } + } + else { + std::vector lits; + ast con = conc(proof); + if(expect_clause) + get_Z3_lits(con, lits); + else + lits.push_back(from_ast(con)); + + // pattern match some idioms + if(dk == PR_MODUS_PONENS && pr(prem(proof,0)) == PR_QUANT_INST){ + if(get_locality_rec(prem(proof,1)) == INT_MAX) { + res = iproof->make_axiom(lits); + return res; + } + } + if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or){ + Iproof::node clause = translate_main(prem(proof,0),true); + res = RewriteClause(clause,prem(proof,1)); + return res; + } + + if(dk == PR_MODUS_PONENS && expect_clause && op(con) == Or) + std::cout << "foo!\n"; + + // no idea why this shows up + if(dk == PR_MODUS_PONENS_OEQ){ + if(conc(prem(proof,0)) == con){ + res = translate_main(prem(proof,0),expect_clause); + return res; + } + if(expect_clause && op(con) == Or){ // skolemization does this + Iproof::node clause = translate_main(prem(proof,0),true); + res = RewriteClause(clause,prem(proof,1)); + return res; + } + } #if 0 - if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){ - Iproof::node clause = translate_main(prem(proof,0),true); - res = make(commute,clause,conc(prem(proof,0))); // HACK -- we depend on Iproof::node being same as ast. - return res; - } + if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){ + Iproof::node clause = translate_main(prem(proof,0),true); + res = make(commute,clause,conc(prem(proof,0))); // HACK -- we depend on Iproof::node being same as ast. + return res; + } - if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,0)) == PR_COMMUTATIVITY){ - Iproof::node clause = translate_main(prem(proof,1),true); - res = make(commute,clause,conc(prem(proof,1))); // HACK -- we depend on Iproof::node being same as ast. - return res; - } + if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,0)) == PR_COMMUTATIVITY){ + Iproof::node clause = translate_main(prem(proof,1),true); + res = make(commute,clause,conc(prem(proof,1))); // HACK -- we depend on Iproof::node being same as ast. + return res; + } #endif - if(dk == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){ - try { - res = CombineEqPropagate(proof); - return res; - } - catch(const CannotCombineEqPropagate &){ - } - } + if(dk == PR_TRANSITIVITY && is_eq_propagate(prem(proof,1))){ + try { + res = CombineEqPropagate(proof); + return res; + } + catch(const CannotCombineEqPropagate &){ + } + } - /* this is the symmetry rule for ~=, that is, takes x ~= y and yields y ~= x. - the proof idiom uses commutativity, monotonicity and mp, but we replace it here - with symmtrey and resolution, that is, we prove y = x |- x = y, then resolve - with the proof of ~(x=y) to get ~y=x. */ - if(dk == PR_MODUS_PONENS && pr(prem(proof,1)) == PR_MONOTONICITY && pr(prem(prem(proof,1),0)) == PR_COMMUTATIVITY && num_prems(prem(proof,1)) == 1){ - Iproof::node ante = translate_main(prem(proof,0),false); - ast eq0 = arg(conc(prem(prem(proof,1),0)),0); - ast eq1 = arg(conc(prem(prem(proof,1),0)),1); - Iproof::node eq1hy = iproof->make_hypothesis(eq1); - Iproof::node eq0pf = iproof->make_symmetry(eq0,eq1,eq1hy); - std::vector clause; // just a dummy - res = iproof->make_resolution(eq0,clause,ante,eq0pf); - return res; - } + /* this is the symmetry rule for ~=, that is, takes x ~= y and yields y ~= x. + the proof idiom uses commutativity, monotonicity and mp, but we replace it here + with symmtrey and resolution, that is, we prove y = x |- x = y, then resolve + with the proof of ~(x=y) to get ~y=x. */ + if(dk == PR_MODUS_PONENS && pr(prem(proof,1)) == PR_MONOTONICITY && pr(prem(prem(proof,1),0)) == PR_COMMUTATIVITY && num_prems(prem(proof,1)) == 1){ + Iproof::node ante = translate_main(prem(proof,0),false); + ast eq0 = arg(conc(prem(prem(proof,1),0)),0); + ast eq1 = arg(conc(prem(prem(proof,1),0)),1); + Iproof::node eq1hy = iproof->make_hypothesis(eq1); + Iproof::node eq0pf = iproof->make_symmetry(eq0,eq1,eq1hy); + std::vector clause; // just a dummy + res = iproof->make_resolution(eq0,clause,ante,eq0pf); + return res; + } - /* This idiom takes ~P and Q=P, yielding ~Q. It uses a "rewrite" - (Q=false) = ~Q. We eliminate the rewrite by using symmetry, - congruence and modus ponens. */ + /* This idiom takes ~P and Q=P, yielding ~Q. It uses a "rewrite" + (Q=false) = ~Q. We eliminate the rewrite by using symmetry, + congruence and modus ponens. */ - if(dk == PR_MODUS_PONENS && pr(prem(proof,1)) == PR_REWRITE && pr(prem(proof,0)) == PR_TRANSITIVITY && pr(prem(prem(proof,0),1)) == PR_IFF_FALSE){ - if(op(con) == Not && arg(con,0) == arg(conc(prem(proof,0)),0)){ - Iproof::node ante1 = translate_main(prem(prem(proof,0),0),false); - Iproof::node ante2 = translate_main(prem(prem(prem(proof,0),1),0),false); - ast ante1_con = conc(prem(prem(proof,0),0)); - ast eq0 = arg(ante1_con,0); - ast eq1 = arg(ante1_con,1); - ast symm_con = make(Iff,eq1,eq0); - Iproof::node ante1s = iproof->make_symmetry(symm_con,ante1_con,ante1); - ast cong_con = make(Iff,make(Not,eq1),make(Not,eq0)); - Iproof::node ante1sc = iproof->make_congruence(symm_con,cong_con,ante1s); - res = iproof->make_mp(cong_con,ante2,ante1sc); - return res; - } - } + if(dk == PR_MODUS_PONENS && pr(prem(proof,1)) == PR_REWRITE && pr(prem(proof,0)) == PR_TRANSITIVITY && pr(prem(prem(proof,0),1)) == PR_IFF_FALSE){ + if(op(con) == Not && arg(con,0) == arg(conc(prem(proof,0)),0)){ + Iproof::node ante1 = translate_main(prem(prem(proof,0),0),false); + Iproof::node ante2 = translate_main(prem(prem(prem(proof,0),1),0),false); + ast ante1_con = conc(prem(prem(proof,0),0)); + ast eq0 = arg(ante1_con,0); + ast eq1 = arg(ante1_con,1); + ast symm_con = make(Iff,eq1,eq0); + Iproof::node ante1s = iproof->make_symmetry(symm_con,ante1_con,ante1); + ast cong_con = make(Iff,make(Not,eq1),make(Not,eq0)); + Iproof::node ante1sc = iproof->make_congruence(symm_con,cong_con,ante1s); + res = iproof->make_mp(cong_con,ante2,ante1sc); + return res; + } + } - // translate all the premises - std::vector args(nprems); - for(unsigned i = 0; i < nprems; i++) - args[i] = translate_main(prem(proof,i),false); + // translate all the premises + std::vector args(nprems); + for(unsigned i = 0; i < nprems; i++) + args[i] = translate_main(prem(proof,i),false); - for(unsigned i = 0; i < nprems; i++) - if(sym(args[i]) == commute - && !(dk == PR_TRANSITIVITY || dk == PR_MODUS_PONENS || dk == PR_SYMMETRY || (dk == PR_MONOTONICITY && op(arg(con,0)) == Not))) - throw unsupported(); + for(unsigned i = 0; i < nprems; i++) + if(sym(args[i]) == commute + && !(dk == PR_TRANSITIVITY || dk == PR_MODUS_PONENS || dk == PR_SYMMETRY || (dk == PR_MONOTONICITY && op(arg(con,0)) == Not))) + throw unsupported(); - switch(dk){ - case PR_TRANSITIVITY: { - if(sym(args[0]) == commute || sym(args[1]) == commute) - res = make_commuted_transitivity(proof,args); - else { - // assume the premises are x = y, y = z - ast x = arg(conc(prem(proof,0)),0); - ast y = arg(conc(prem(proof,0)),1); - ast z = arg(conc(prem(proof,1)),1); - res = iproof->make_transitivity(x,y,z,args[0],args[1]); - } - break; - } - case PR_QUANT_INTRO: - case PR_MONOTONICITY: - { - std::vector eqs; eqs.resize(args.size()); - for(unsigned i = 0; i < args.size(); i++) - eqs[i] = conc(prem(proof,i)); - if(op(arg(con,0)) == Not && sym(args[0]) == commute) - res = make_commuted_monotonicity(proof,args); - else - res = iproof->make_congruence(eqs,con,args); - break; - } - case PR_REFLEXIVITY: { - res = iproof->make_reflexivity(con); - break; - } - case PR_SYMMETRY: { - if(sym(args[0]) == commute) - res = make_commuted_symmetry(proof,args); - else - res = iproof->make_symmetry(con,conc(prem(proof,0)),args[0]); - break; - } - case PR_MODUS_PONENS: { - if(sym(args[1]) == commute) - res = make_commuted_modus_ponens(proof,args); - else - res = iproof->make_mp(conc(prem(proof,1)),args[0],args[1]); - break; - } - case PR_TH_LEMMA: { - switch(get_theory_lemma_theory(proof)){ - case ArithTheory: - switch(get_theory_lemma_kind(proof)){ - case FarkasKind: { - std::vector farkas_coeffs, prem_cons; - get_farkas_coeffs(proof,farkas_coeffs); - if(nprems == 0) {// axiom, not rule - int nargs = num_args(con); - if(farkas_coeffs.size() != (unsigned)nargs){ - pfgoto(proof); - throw unsupported(); - } - for(int i = 0; i < nargs; i++){ - ast lit = mk_not(arg(con,i)); - prem_cons.push_back(lit); - args.push_back(iproof->make_hypothesis(lit)); - } - } - else { // rule version (proves false) - prem_cons.resize(nprems); - for(unsigned i = 0; i < nprems; i++) - prem_cons[i] = conc(prem(proof,i)); - } - res = iproof->make_farkas(con,args,prem_cons,farkas_coeffs); - break; - } - case Leq2EqKind: { - // conc should be (or x = y (not (leq x y)) (not(leq y z)) ) - ast xeqy = arg(conc(proof),0); - ast x = arg(xeqy,0); - ast y = arg(xeqy,1); - res = iproof->make_leq2eq(x,y,arg(arg(conc(proof),1),0),arg(arg(conc(proof),2),0)); - break; - } - case Eq2LeqKind: { - // conc should be (or (not (= x y)) (leq x y)) - ast xeqy = arg(arg(conc(proof),0),0); - ast xleqy = arg(conc(proof),1); - ast x = arg(xeqy,0); - ast y = arg(xeqy,1); - res = iproof->make_eq2leq(x,y,xleqy); - break; - } - case GCDTestKind: { - std::vector farkas_coeffs; - get_farkas_coeffs(proof,farkas_coeffs); - if(farkas_coeffs.size() != nprems){ - pfgoto(proof); - throw unsupported(); - } - std::vector my_prems; my_prems.resize(2); - std::vector my_prem_cons; my_prem_cons.resize(2); - std::vector my_farkas_coeffs; my_farkas_coeffs.resize(2); - my_prems[0] = GCDtoDivRule(proof, true, farkas_coeffs, args, my_prem_cons[0]); - my_prems[1] = GCDtoDivRule(proof, false, farkas_coeffs, args, my_prem_cons[1]); - ast con = mk_false(); - my_farkas_coeffs[0] = my_farkas_coeffs[1] = make_int("1"); - res = iproof->make_farkas(con,my_prems,my_prem_cons,my_farkas_coeffs); - break; - } - case AssignBoundsKind: { - if(args.size() > 0) - res = AssignBoundsRule2Farkas(proof, conc(proof), args); - else - res = AssignBounds2Farkas(proof,conc(proof)); - break; - } - case EqPropagateKind: { - std::vector prems(nprems); - for(unsigned i = 0; i < nprems; i++) - prems[i] = prem(proof,i); - res = EqPropagate(con,prems,args); - break; - } - case ArithMysteryKind: { - // Z3 hasn't told us what kind of lemma this is -- maybe we can guess - std::vector prems(nprems); - for(unsigned i = 0; i < nprems; i++) - prems[i] = prem(proof,i); - res = ArithMysteryRule(con,prems,args); - break; - } - default: - throw unsupported(); - } - break; - case ArrayTheory: {// nothing fancy for this - ast store_array; - if(get_store_array(con,store_array)) - res = iproof->make_axiom(lits,ast_scope(store_array)); - else - res = iproof->make_axiom(lits); // for array extensionality axiom - break; - } - default: - throw unsupported(); - } - break; - } - case PR_HYPOTHESIS: { - res = iproof->make_hypothesis(conc(proof)); - break; - } - case PR_QUANT_INST: { - res = iproof->make_axiom(lits); - break; - } - case PR_DEF_AXIOM: { // this should only happen for formulas resulting from quantifier instantiation - res = iproof->make_axiom(lits); - break; - } - case PR_IFF_TRUE: { // turns p into p <-> true, noop for us - res = args[0]; - break; - } - case PR_IFF_FALSE: { // turns ~p into p <-> false, noop for us - if(is_local(con)) - res = args[0]; - else - throw unsupported(); - break; - } - case PR_COMMUTATIVITY: { - ast comm_equiv = make(op(con),arg(con,0),arg(con,0)); - ast pf = iproof->make_reflexivity(comm_equiv); - res = make(commute,pf,comm_equiv); - break; - } - default: - pfgoto(proof); - assert(0 && "translate_main: unsupported proof rule"); - throw unsupported(); - } + switch(dk){ + case PR_TRANSITIVITY: { + if(sym(args[0]) == commute || sym(args[1]) == commute) + res = make_commuted_transitivity(proof,args); + else { + // assume the premises are x = y, y = z + ast x = arg(conc(prem(proof,0)),0); + ast y = arg(conc(prem(proof,0)),1); + ast z = arg(conc(prem(proof,1)),1); + res = iproof->make_transitivity(x,y,z,args[0],args[1]); + } + break; + } + case PR_QUANT_INTRO: + case PR_MONOTONICITY: + { + std::vector eqs; eqs.resize(args.size()); + for(unsigned i = 0; i < args.size(); i++) + eqs[i] = conc(prem(proof,i)); + if(op(arg(con,0)) == Not && sym(args[0]) == commute) + res = make_commuted_monotonicity(proof,args); + else + res = iproof->make_congruence(eqs,con,args); + break; + } + case PR_REFLEXIVITY: { + res = iproof->make_reflexivity(con); + break; + } + case PR_SYMMETRY: { + if(sym(args[0]) == commute) + res = make_commuted_symmetry(proof,args); + else + res = iproof->make_symmetry(con,conc(prem(proof,0)),args[0]); + break; + } + case PR_MODUS_PONENS: { + if(sym(args[1]) == commute) + res = make_commuted_modus_ponens(proof,args); + else + res = iproof->make_mp(conc(prem(proof,1)),args[0],args[1]); + break; + } + case PR_TH_LEMMA: { + switch(get_theory_lemma_theory(proof)){ + case ArithTheory: + switch(get_theory_lemma_kind(proof)){ + case FarkasKind: { + std::vector farkas_coeffs, prem_cons; + get_farkas_coeffs(proof,farkas_coeffs); + if(nprems == 0) {// axiom, not rule + int nargs = num_args(con); + if(farkas_coeffs.size() != (unsigned)nargs){ + pfgoto(proof); + throw unsupported(); + } + for(int i = 0; i < nargs; i++){ + ast lit = mk_not(arg(con,i)); + prem_cons.push_back(lit); + args.push_back(iproof->make_hypothesis(lit)); + } + } + else { // rule version (proves false) + prem_cons.resize(nprems); + for(unsigned i = 0; i < nprems; i++) + prem_cons[i] = conc(prem(proof,i)); + } + res = iproof->make_farkas(con,args,prem_cons,farkas_coeffs); + break; + } + case Leq2EqKind: { + // conc should be (or x = y (not (leq x y)) (not(leq y z)) ) + ast xeqy = arg(conc(proof),0); + ast x = arg(xeqy,0); + ast y = arg(xeqy,1); + res = iproof->make_leq2eq(x,y,arg(arg(conc(proof),1),0),arg(arg(conc(proof),2),0)); + break; + } + case Eq2LeqKind: { + // conc should be (or (not (= x y)) (leq x y)) + ast xeqy = arg(arg(conc(proof),0),0); + ast xleqy = arg(conc(proof),1); + ast x = arg(xeqy,0); + ast y = arg(xeqy,1); + res = iproof->make_eq2leq(x,y,xleqy); + break; + } + case GCDTestKind: { + std::vector farkas_coeffs; + get_farkas_coeffs(proof,farkas_coeffs); + if(farkas_coeffs.size() != nprems){ + pfgoto(proof); + throw unsupported(); + } + std::vector my_prems; my_prems.resize(2); + std::vector my_prem_cons; my_prem_cons.resize(2); + std::vector my_farkas_coeffs; my_farkas_coeffs.resize(2); + my_prems[0] = GCDtoDivRule(proof, true, farkas_coeffs, args, my_prem_cons[0]); + my_prems[1] = GCDtoDivRule(proof, false, farkas_coeffs, args, my_prem_cons[1]); + ast con = mk_false(); + my_farkas_coeffs[0] = my_farkas_coeffs[1] = make_int("1"); + res = iproof->make_farkas(con,my_prems,my_prem_cons,my_farkas_coeffs); + break; + } + case AssignBoundsKind: { + if(args.size() > 0) + res = AssignBoundsRule2Farkas(proof, conc(proof), args); + else + res = AssignBounds2Farkas(proof,conc(proof)); + break; + } + case EqPropagateKind: { + std::vector prems(nprems); + for(unsigned i = 0; i < nprems; i++) + prems[i] = prem(proof,i); + res = EqPropagate(con,prems,args); + break; + } + case ArithMysteryKind: { + // Z3 hasn't told us what kind of lemma this is -- maybe we can guess + std::vector prems(nprems); + for(unsigned i = 0; i < nprems; i++) + prems[i] = prem(proof,i); + res = ArithMysteryRule(con,prems,args); + break; + } + default: + throw unsupported(); + } + break; + case ArrayTheory: {// nothing fancy for this + ast store_array; + if(get_store_array(con,store_array)) + res = iproof->make_axiom(lits,ast_scope(store_array)); + else + res = iproof->make_axiom(lits); // for array extensionality axiom + break; + } + default: + throw unsupported(); + } + break; + } + case PR_HYPOTHESIS: { + res = iproof->make_hypothesis(conc(proof)); + break; + } + case PR_QUANT_INST: { + res = iproof->make_axiom(lits); + break; + } + case PR_DEF_AXIOM: { // this should only happen for formulas resulting from quantifier instantiation + res = iproof->make_axiom(lits); + break; + } + case PR_IFF_TRUE: { // turns p into p <-> true, noop for us + res = args[0]; + break; + } + case PR_IFF_FALSE: { // turns ~p into p <-> false, noop for us + if(is_local(con)) + res = args[0]; + else + throw unsupported(); + break; + } + case PR_COMMUTATIVITY: { + ast comm_equiv = make(op(con),arg(con,0),arg(con,0)); + ast pf = iproof->make_reflexivity(comm_equiv); + res = make(commute,pf,comm_equiv); + break; + } + default: + pfgoto(proof); + assert(0 && "translate_main: unsupported proof rule"); + throw unsupported(); + } + } + + return res; } - return res; - } + void clear_translation(){ + translation.first.clear(); + translation.second.clear(); + } - void clear_translation(){ - translation.first.clear(); - translation.second.clear(); - } + // We actually compute the interpolant here and then produce a proof consisting of just a lemma - // We actually compute the interpolant here and then produce a proof consisting of just a lemma - - iz3proof::node translate(ast proof, iz3proof &dst){ - std::vector itps; - scan_skolems(proof); - for(int i = 0; i < frames -1; i++){ + iz3proof::node translate(ast proof, iz3proof &dst){ + std::vector itps; + scan_skolems(proof); + for(int i = 0; i < frames -1; i++){ #ifdef NEW_LOCALITY - rng = range_downward(i); - locality.clear(); + rng = range_downward(i); + locality.clear(); #endif - iproof = iz3proof_itp::create(this,range_downward(i),weak_mode()); - Iproof::node ipf = translate_main(proof); - ast itp = iproof->interpolate(ipf); - itps.push_back(itp); - delete iproof; - clear_translation(); + iproof = iz3proof_itp::create(this,range_downward(i),weak_mode()); + Iproof::node ipf = translate_main(proof); + ast itp = iproof->interpolate(ipf); + itps.push_back(itp); + delete iproof; + clear_translation(); + } + // Very simple proof -- lemma of the empty clause with computed interpolation + iz3proof::node Ipf = dst.make_lemma(std::vector(),itps); // builds result in dst + return Ipf; } - // Very simple proof -- lemma of the empty clause with computed interpolation - iz3proof::node Ipf = dst.make_lemma(std::vector(),itps); // builds result in dst - return Ipf; - } - iz3translation_full(iz3mgr &mgr, + iz3translation_full(iz3mgr &mgr, iz3secondary *_secondary, - const std::vector > &cnsts, + const std::vector > &cnsts, const std::vector &parents, const std::vector &theory) - : iz3translation(mgr, cnsts, parents, theory) - { - frames = cnsts.size(); - traced_lit = ast(); - type boolbooldom[2] = {bool_type(),bool_type()}; - commute = function("@commute",2,boolbooldom,bool_type()); - m().inc_ref(commute); - } + : iz3translation(mgr, cnsts, parents, theory) + { + frames = cnsts.size(); + traced_lit = ast(); + type boolbooldom[2] = {bool_type(),bool_type()}; + commute = function("@commute",2,boolbooldom,bool_type()); + m().inc_ref(commute); + } - ~iz3translation_full(){ - m().dec_ref(commute); - } + ~iz3translation_full(){ + m().dec_ref(commute); + } }; @@ -2031,7 +2031,7 @@ iz3translation *iz3translation::create(iz3mgr &mgr, const std::vector > &cnsts, const std::vector &parents, const std::vector &theory){ - return new iz3translation_full(mgr,secondary,cnsts,parents,theory); + return new iz3translation_full(mgr,secondary,cnsts,parents,theory); } @@ -2040,58 +2040,58 @@ iz3translation *iz3translation::create(iz3mgr &mgr, // This is just to make sure certain methods are compiled, so we can call then from the debugger. void iz3translation_full_trace_lit(iz3translation_full *p, iz3mgr::ast lit, iz3mgr::ast proof){ - p->trace_lit(lit, proof); + p->trace_lit(lit, proof); } void iz3translation_full_show_step(iz3translation_full *p, iz3mgr::ast proof){ - p->show_step(proof); + p->show_step(proof); } void iz3translation_full_show_marked(iz3translation_full *p, iz3mgr::ast proof){ - p->show_marked(proof); + p->show_marked(proof); } void iz3translation_full_show_lit(iz3translation_full *p, iz3mgr::ast lit){ - p->show_lit(lit); + p->show_lit(lit); } void iz3translation_full_show_z3_lit(iz3translation_full *p, iz3mgr::ast a){ - p->show_z3_lit(a); + p->show_z3_lit(a); } void iz3translation_full_pfgoto(iz3translation_full *p, iz3mgr::ast proof){ - p->pfgoto(proof); + p->pfgoto(proof); } void iz3translation_full_pfback(iz3translation_full *p ){ - p->pfback(); + p->pfback(); } void iz3translation_full_pffwd(iz3translation_full *p ){ - p->pffwd(); + p->pffwd(); } void iz3translation_full_pfprem(iz3translation_full *p, int i){ - p->pfprem(i); + p->pfprem(i); } void iz3translation_full_expand(iz3translation_full *p, int i){ - p->expand(i); + p->expand(i); } void iz3translation_full_symbols_out_of_scope(iz3translation_full *p, int i, const iz3mgr::ast &t){ - p->symbols_out_of_scope(i,t); + p->symbols_out_of_scope(i,t); } void iz3translation_full_conc_symbols_out_of_scope(iz3translation_full *p, int i, const iz3mgr::ast &t){ - p->conc_symbols_out_of_scope(i,t); + p->conc_symbols_out_of_scope(i,t); } struct stdio_fixer { - stdio_fixer(){ - std::cout.rdbuf()->pubsetbuf(0,0); - } + stdio_fixer(){ + std::cout.rdbuf()->pubsetbuf(0,0); + } } my_stdio_fixer; diff --git a/src/interp/iz3translate.h b/src/interp/iz3translate.h index 6dc01dfa7..2fcf406db 100755 --- a/src/interp/iz3translate.h +++ b/src/interp/iz3translate.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3translate.h + iz3translate.h -Abstract: + Abstract: - Interface for proof translations from Z3 proofs to interpolatable - proofs. + Interface for proof translations from Z3 proofs to interpolatable + proofs. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifndef IZ3TRANSLATION_H @@ -29,27 +29,27 @@ Revision History: // an interpolatable proof class iz3translation : public iz3base { -public: - virtual iz3proof::node translate(ast, iz3proof &) = 0; - virtual ast quantify(ast e, const range &rng){return e;} - virtual ~iz3translation(){} + public: + virtual iz3proof::node translate(ast, iz3proof &) = 0; + virtual ast quantify(ast e, const range &rng){return e;} + virtual ~iz3translation(){} - /** This is thrown when the proof cannot be translated. */ - struct unsupported { - }; + /** This is thrown when the proof cannot be translated. */ + struct unsupported { + }; - static iz3translation *create(iz3mgr &mgr, - iz3secondary *secondary, - const std::vector > &frames, - const std::vector &parents, - const std::vector &theory); + static iz3translation *create(iz3mgr &mgr, + iz3secondary *secondary, + const std::vector > &frames, + const std::vector &parents, + const std::vector &theory); protected: iz3translation(iz3mgr &mgr, const std::vector > &_cnsts, const std::vector &_parents, const std::vector &_theory) - : iz3base(mgr,_cnsts,_parents,_theory) {} + : iz3base(mgr,_cnsts,_parents,_theory) {} }; //#define IZ3_TRANSLATE_DIRECT2 diff --git a/src/interp/iz3translate_direct.cpp b/src/interp/iz3translate_direct.cpp index 9cef3a686..c1b751c6f 100755 --- a/src/interp/iz3translate_direct.cpp +++ b/src/interp/iz3translate_direct.cpp @@ -1,23 +1,23 @@ /*++ -Copyright (c) 2011 Microsoft Corporation + Copyright (c) 2011 Microsoft Corporation -Module Name: + Module Name: - iz3translate_direct.cpp + iz3translate_direct.cpp -Abstract: + Abstract: - Translate a Z3 proof into the interpolating proof calculus. - Translation is direct, without transformations on the target proof - representaiton. + Translate a Z3 proof into the interpolating proof calculus. + Translation is direct, without transformations on the target proof + representaiton. -Author: + Author: - Ken McMillan (kenmcmil) + Ken McMillan (kenmcmil) -Revision History: + Revision History: ---*/ + --*/ #ifdef _WINDOWS @@ -47,15 +47,15 @@ using namespace stl_ext; /* This can introduce an address dependency if the range type of hash_map has a destructor. Since the code in this file is not used and only here for historical comparisons, we allow this non-determinism. - */ +*/ namespace stl_ext { - template + template class hash { - public: - size_t operator()(const T *p) const { - return (size_t) p; - } - }; + public: + size_t operator()(const T *p) const { + return (size_t) p; + } + }; } static int lemma_count = 0; @@ -69,29 +69,29 @@ static int nll_lemma_count = 0; // if pivot == conclusion(proof) it is unit. struct Z3_resolvent { - iz3base::ast proof; - bool is_unit; - iz3base::ast pivot; - Z3_resolvent(const iz3base::ast &_proof, bool _is_unit, const iz3base::ast &_pivot){ - proof = _proof; - is_unit = _is_unit; - pivot = _pivot; - } + iz3base::ast proof; + bool is_unit; + iz3base::ast pivot; + Z3_resolvent(const iz3base::ast &_proof, bool _is_unit, const iz3base::ast &_pivot){ + proof = _proof; + is_unit = _is_unit; + pivot = _pivot; + } }; namespace hash_space { - template <> - class hash { - public: - size_t operator()(const Z3_resolvent &p) const { - return (p.proof.hash() + p.pivot.hash()); - } - }; + template <> + class hash { + public: + size_t operator()(const Z3_resolvent &p) const { + return (p.proof.hash() + p.pivot.hash()); + } + }; } bool operator==(const Z3_resolvent &x, const Z3_resolvent &y) { - return x.proof == y.proof && x.pivot == y.pivot; + return x.proof == y.proof && x.pivot == y.pivot; } @@ -99,35 +99,35 @@ bool operator==(const Z3_resolvent &x, const Z3_resolvent &y) { typedef std::vector ResolventAppSet; struct non_local_lits { - ResolventAppSet proofs; // the proof nodes being raised - non_local_lits(ResolventAppSet &_proofs){ - proofs.swap(_proofs); - } + ResolventAppSet proofs; // the proof nodes being raised + non_local_lits(ResolventAppSet &_proofs){ + proofs.swap(_proofs); + } }; namespace hash_space { - template <> - class hash { - public: - size_t operator()(const non_local_lits &p) const { - size_t h = 0; - for(ResolventAppSet::const_iterator it = p.proofs.begin(), en = p.proofs.end(); it != en; ++it) - h += (size_t)*it; - return h; - } - }; + template <> + class hash { + public: + size_t operator()(const non_local_lits &p) const { + size_t h = 0; + for(ResolventAppSet::const_iterator it = p.proofs.begin(), en = p.proofs.end(); it != en; ++it) + h += (size_t)*it; + return h; + } + }; } bool operator==(const non_local_lits &x, const non_local_lits &y) { - ResolventAppSet::const_iterator itx = x.proofs.begin(); - ResolventAppSet::const_iterator ity = y.proofs.begin(); - while(true){ - if(ity == y.proofs.end()) return itx == x.proofs.end(); - if(itx == x.proofs.end()) return ity == y.proofs.end(); - if(*itx != *ity) return false; - ++itx; ++ity; - } + ResolventAppSet::const_iterator itx = x.proofs.begin(); + ResolventAppSet::const_iterator ity = y.proofs.begin(); + while(true){ + if(ity == y.proofs.end()) return itx == x.proofs.end(); + if(itx == x.proofs.end()) return ity == y.proofs.end(); + if(*itx != *ity) return false; + ++itx; ++ity; + } } @@ -137,1573 +137,1573 @@ bool operator==(const non_local_lits &x, const non_local_lits &y) { class iz3translation_direct : public iz3translation { public: - typedef ast Zproof; // type of non-interpolating proofs - typedef iz3proof Iproof; // type of interpolating proofs + typedef ast Zproof; // type of non-interpolating proofs + typedef iz3proof Iproof; // type of interpolating proofs - /* Here we have lots of hash tables for memoizing various methods and - other such global data structures. - */ + /* Here we have lots of hash tables for memoizing various methods and + other such global data structures. + */ - typedef hash_map AstToInt; - AstToInt locality; // memoizes locality of Z3 proof terms + typedef hash_map AstToInt; + AstToInt locality; // memoizes locality of Z3 proof terms - typedef std::pair EquivEntry; - typedef hash_map EquivTab; - EquivTab equivs; // maps non-local terms to equivalent local terms, with proof + typedef std::pair EquivEntry; + typedef hash_map EquivTab; + EquivTab equivs; // maps non-local terms to equivalent local terms, with proof - typedef hash_set AstHashSet; - AstHashSet equivs_visited; // proofs already checked for equivalences + typedef hash_set AstHashSet; + AstHashSet equivs_visited; // proofs already checked for equivalences - typedef std::pair, hash_map > AstToIpf; - AstToIpf translation; // Zproof nodes to Iproof nodes + typedef std::pair, hash_map > AstToIpf; + AstToIpf translation; // Zproof nodes to Iproof nodes - AstHashSet antes_added; // Z3 proof terms whose antecedents have been added to the list - std::vector > antes; // list of antecedent/frame pairs - std::vector local_antes; // list of local antecedents + AstHashSet antes_added; // Z3 proof terms whose antecedents have been added to the list + std::vector > antes; // list of antecedent/frame pairs + std::vector local_antes; // list of local antecedents - Iproof *iproof; // the interpolating proof we are constructing + Iproof *iproof; // the interpolating proof we are constructing - int frames; // number of frames + int frames; // number of frames - typedef std::set AstSet; - typedef hash_map AstToAstSet; - AstToAstSet hyp_map; // map proof terms to hypothesis set + typedef std::set AstSet; + typedef hash_map AstToAstSet; + AstToAstSet hyp_map; // map proof terms to hypothesis set - struct LocVar { // localization vars - ast var; // a fresh variable - ast term; // term it represents - int frame; // frame in which it's defined - LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} - }; + struct LocVar { // localization vars + ast var; // a fresh variable + ast term; // term it represents + int frame; // frame in which it's defined + LocVar(ast v, ast t, int f){var=v;term=t;frame=f;} + }; - std::vector localization_vars; // localization vars in order of creation - typedef hash_map AstToAst; - AstToAst localization_map; // maps terms to their localization vars + std::vector localization_vars; // localization vars in order of creation + typedef hash_map AstToAst; + AstToAst localization_map; // maps terms to their localization vars - typedef hash_map AstToBool; + typedef hash_map AstToBool; - iz3secondary *secondary; // the secondary prover + iz3secondary *secondary; // the secondary prover - // Unique table for sets of non-local resolutions - hash_map non_local_lits_unique; + // Unique table for sets of non-local resolutions + hash_map non_local_lits_unique; - // Unique table for resolvents - hash_map Z3_resolvent_unique; + // Unique table for resolvents + hash_map Z3_resolvent_unique; - // Translation memo for case of non-local resolutions - hash_map non_local_translation; + // Translation memo for case of non-local resolutions + hash_map non_local_translation; - public: +public: #define from_ast(x) (x) - // determine locality of a proof term - // return frame of derivation if local, or -1 if not - // result INT_MAX means the proof term is a tautology - // memoized in hash_map "locality" + // determine locality of a proof term + // return frame of derivation if local, or -1 if not + // result INT_MAX means the proof term is a tautology + // memoized in hash_map "locality" - int get_locality_rec(ast proof){ - std::pair foo(proof,INT_MAX); - std::pair bar = locality.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - if(pr(proof) == PR_ASSERTED){ - ast ass = conc(proof); - res = frame_of_assertion(ass); - } - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - int bar = get_locality_rec(arg); - if(res == INT_MAX || res == bar) res = bar; - else if(bar != INT_MAX) res = -1; - } - } - return res; - } - - - int get_locality(ast proof){ - // if(lia_z3_axioms_only) return -1; - int res = get_locality_rec(proof); - if(res != -1){ - ast con = conc(proof); - range rng = ast_scope(con); - - // hack: if a clause contains "true", it reduces to "true", - // which means we won't compute the range correctly. we handle - // this case by computing the ranges of the literals separately - - if(is_true(con)){ - std::vector lits; - get_Z3_lits(conc(proof),lits); - for(unsigned i = 0; i < lits.size(); i++) - rng = range_glb(rng,ast_scope(lits[i])); - } - - if(!range_is_empty(rng)){ - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ - ast hyp = *it; - rng = range_glb(rng,ast_scope(hyp)); - } - } - - if(res == INT_MAX){ - if(range_is_empty(rng)) - res = -1; - else res = range_max(rng); - } - else { - if(!in_range(res,rng)) - res = -1; - } - } - return res; - } - - AstSet &get_hyps(ast proof){ - std::pair foo(proof,AstSet()); - std::pair bar = hyp_map.insert(foo); - AstSet &res = bar.first->second; - if(!bar.second) return res; - pfrule dk = pr(proof); - if(dk == PR_HYPOTHESIS){ - ast con = conc(proof); - res.insert(con); - } - else { - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - AstSet &arg_hyps = get_hyps(arg); - res.insert(arg_hyps.begin(),arg_hyps.end()); - } - if(dk == PR_LEMMA){ - ast con = conc(proof); - res.erase(mk_not(con)); - if(is_or(con)){ - int clause_size = num_args(con); - for(int i = 0; i < clause_size; i++){ - ast neglit = mk_not(arg(con,i)); - res.erase(neglit); - } - } - } - } -#if 0 - AstSet::iterator it = res.begin(), en = res.end(); - if(it != en){ - AstSet::iterator old = it; - ++it; - for(; it != en; ++it, ++old) - if(!(*old < *it)) - std::cout << "foo!"; - } -#endif - return res; - } - - - // Find all the judgements of the form p <-> q, where - // p is local and q is non-local, recording them in "equivs" - // the map equivs_visited is used to record the already visited proof terms - - void find_equivs(ast proof){ - if(equivs_visited.find(proof) != equivs_visited.end()) - return; - equivs_visited.insert(proof); - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++) // do all the sub_terms - find_equivs(prem(proof,i)); - ast con = conc(proof); // get the conclusion - if(is_iff(con)){ - ast iff = con; - for(int i = 0; i < 2; i++) - if(!is_local(arg(iff,i)) && is_local(arg(iff,1-i))){ - std::pair > foo(arg(iff,i),std::pair(arg(iff,1-i),proof)); - equivs.insert(foo); - } - } - } - - // get the lits of a Z3 clause as foci terms - void get_Z3_lits(ast t, std::vector &lits){ - opr dk = op(t); - if(dk == False) - return; // false = empty clause - if(dk == Or){ - unsigned nargs = num_args(t); - lits.resize(nargs); - for(unsigned i = 0; i < nargs; i++) // do all the sub_terms - lits[i] = arg(t,i); - } - else { - lits.push_back(t); - } - } - - // resolve two clauses represented as vectors of lits. replace first clause - void resolve(ast pivot, std::vector &cls1, std::vector &cls2){ - ast neg_pivot = mk_not(pivot); - for(unsigned i = 0; i < cls1.size(); i++){ - if(cls1[i] == pivot){ - cls1[i] = cls1.back(); - cls1.pop_back(); - bool found_pivot2 = false; - for(unsigned j = 0; j < cls2.size(); j++){ - if(cls2[j] == neg_pivot) - found_pivot2 = true; - else - cls1.push_back(cls2[j]); - } - assert(found_pivot2); - return; - } - } - assert(0 && "resolve failed"); - } - - // get lits resulting from unit resolution up to and including "position" - // TODO: this is quadratic -- fix it - void do_unit_resolution(ast proof, int position, std::vector &lits){ - ast orig_clause = conc(prem(proof,0)); - get_Z3_lits(orig_clause,lits); - for(int i = 1; i <= position; i++){ - std::vector unit(1); - unit[0] = conc(prem(proof,i)); - resolve(mk_not(unit[0]),lits,unit); - } - } - - - // clear the localization variables - void clear_localization(){ - localization_vars.clear(); - localization_map.clear(); - } - - // create a fresh variable for localization - ast fresh_localization_var(ast term, int frame){ - std::ostringstream s; - s << "%" << (localization_vars.size()); - ast var = make_var(s.str().c_str(),get_type(term)); - sym_range(sym(var)) = range_full(); // make this variable global - localization_vars.push_back(LocVar(var,term,frame)); - return var; - } - - - // "localize" a term to a given frame range by - // creating new symbols to represent non-local subterms - - ast localize_term(ast e, const range &rng){ - if(ranges_intersect(ast_scope(e),rng)) - return e; // this term occurs in range, so it's O.K. - AstToAst::iterator it = localization_map.find(e); - if(it != localization_map.end()) - return it->second; - - // if is is non-local, we must first localize the arguments to - // the range of its function symbol - - int nargs = num_args(e); - if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ - range frng = rng; - if(op(e) == Uninterpreted){ - symb f = sym(e); - range srng = sym_range(f); - if(ranges_intersect(srng,rng)) // localize to desired range if possible - frng = range_glb(srng,rng); - } - std::vector largs(nargs); - for(int i = 0; i < nargs; i++){ - largs[i] = localize_term(arg(e,i),frng); - frng = range_glb(frng,ast_scope(largs[i])); - } - e = clone(e,largs); - assert(is_local(e)); - } - - - if(ranges_intersect(ast_scope(e),rng)) - return e; // this term occurs in range, so it's O.K. - - // choose a frame for the constraint that is close to range - int frame = range_near(ast_scope(e),rng); - - ast new_var = fresh_localization_var(e,frame); - localization_map[e] = new_var; - ast cnst = make(Equal,new_var,e); - antes.push_back(std::pair(cnst,frame)); - return new_var; - } - - // some patterm matching functions - - // match logical or with nargs arguments - // assumes AIG form - bool match_or(ast e, ast *args, int nargs){ - if(op(e) != Or) return false; - int n = num_args(e); - if(n != nargs) return false; - for(int i = 0; i < nargs; i++) - args[i] = arg(e,i); - return true; - } - - // match operator f with exactly nargs arguments - bool match_op(ast e, opr f, ast *args, int nargs){ - if(op(e) != f) return false; - int n = num_args(e); - if(n != nargs) return false; - for(int i = 0; i < nargs; i++) - args[i] = arg(e,i); - return true; - } - - // see if the given formula can be interpreted as - // an axiom instance (e.g., an array axiom instance). - // if so, add it to "antes" in an appropriate frame. - // this may require "localization" - - void get_axiom_instance(ast e){ - - // "store" axiom - // (or (= w q) (= (select (store a1 w y) q) (select a1 q))) - // std::cout << "ax: "; show(e); - ast lits[2],eq_ops_l[2],eq_ops_r[2],sel_ops[2], sto_ops[3], sel_ops2[2] ; - if(match_or(e,lits,2)) - if(match_op(lits[0],Equal,eq_ops_l,2)) - if(match_op(lits[1],Equal,eq_ops_r,2)) - for(int i = 0; i < 2; i++){ // try the second equality both ways - if(match_op(eq_ops_r[0],Select,sel_ops,2)) - if(match_op(sel_ops[0],Store,sto_ops,3)) - if(match_op(eq_ops_r[1],Select,sel_ops2,2)) - for(int j = 0; j < 2; j++){ // try the first equality both ways - if(eq_ops_l[0] == sto_ops[1] - && eq_ops_l[1] == sel_ops[1] - && eq_ops_l[1] == sel_ops2[1] - && sto_ops[0] == sel_ops2[0]) - if(is_local(sel_ops[0])) // store term must be local - { - ast sto = sel_ops[0]; - ast addr = localize_term(eq_ops_l[1],ast_scope(sto)); - ast res = make(Or, - make(Equal,eq_ops_l[0],addr), - make(Equal, - make(Select,sto,addr), - make(Select,sel_ops2[0],addr))); - int frame = range_min(ast_scope(res)); - antes.push_back(std::pair(res,frame)); - return; - } - std::swap(eq_ops_l[0],eq_ops_l[1]); - } - std::swap(eq_ops_r[0],eq_ops_r[1]); - } - } - - // a quantifier instantation looks like (~ forall x. P) \/ P[z/x] - // we need to find a time frame for P, then localize P[z/x] in this frame - - void get_quantifier_instance(ast e){ - ast disjs[2]; - if(match_or(e,disjs,2)){ - if(is_local(disjs[0])){ - ast res = localize_term(disjs[1], ast_scope(disjs[0])); - int frame = range_min(ast_scope(res)); - antes.push_back(std::pair(res,frame)); - return; - } - } - } - - ast get_judgement(ast proof){ - ast con = from_ast(conc(proof)); - AstSet &hyps = get_hyps(proof); - std::vector hyps_vec; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - hyps_vec.push_back(*it); - if(hyps_vec.size() == 0) return con; - con = make(Or,mk_not(make(And,hyps_vec)),con); - return con; - } - - // add the premises of a proof term to the "antes" list - - void add_antes(ast proof){ - if(antes_added.find(proof) != antes_added.end()) return; - antes_added.insert(proof); - int frame = get_locality(proof); - if(frame != -1) - if(1){ - ast e = get_judgement(proof); - if(frame >= frames) frame = frames-1; // can happen if there are no symbols - antes.push_back(std::pair(e,frame)); - return; - } - pfrule dk = pr(proof); - if(dk == PR_ASSERTED){ - ast ass = conc(proof); - frame = frame_of_assertion(ass); - if(frame >= frames) frame = frames-1; // can happen if a theory fact - antes.push_back(std::pair(ass,frame)); - return; - } - if(dk == PR_TH_LEMMA && num_prems(proof) == 0){ - get_axiom_instance(conc(proof)); - } - if(dk == PR_QUANT_INST && num_prems(proof) == 0){ - get_quantifier_instance(conc(proof)); - } - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - add_antes(arg); - } - } - - - // add quantifiers over the localization vars - // to an interpolant for frames lo-hi - - ast add_quants(ast e, int lo, int hi){ - for(int i = localization_vars.size() - 1; i >= 0; i--){ - LocVar &lv = localization_vars[i]; - opr quantifier = (lv.frame >= lo && lv.frame <= hi) ? Exists : Forall; - e = apply_quant(quantifier,lv.var,e); - } - return e; - } - - int get_lits_locality(std::vector &lits){ - range rng = range_full(); - for(std::vector::iterator it = lits.begin(), en = lits.end(); it != en; ++it){ - ast lit = *it; - rng = range_glb(rng,ast_scope(lit)); - } - if(range_is_empty(rng)) return -1; - int hi = range_max(rng); - if(hi >= frames) return frames - 1; - return hi; - } - - - struct invalid_lemma {}; - - - - - // prove a lemma (clause) using current antes list - // return proof of the lemma - // use the secondary prover - - int prove_lemma(std::vector &lits){ - - - // first try localization - if(antes.size() == 0){ - int local_frame = get_lits_locality(lits); - if(local_frame != -1) - return iproof->make_assumption(local_frame,lits); // no proof needed for purely local fact - } - - // group the assumptions by frame - std::vector preds(frames); - for(unsigned i = 0; i < preds.size(); i++) - preds[i] = mk_true(); - for(unsigned i = 0; i < antes.size(); i++){ - int frame = antes[i].second; - preds[frame] = mk_and(preds[frame],antes[i].first); // conjoin it to frame - } - - for(unsigned i = 0; i < lits.size(); i++){ - int frame; - if(!weak_mode()){ - frame = range_max(ast_scope(lits[i])); - if(frame >= frames) frame = frames-1; // could happen if contains no symbols - } - else { - frame = range_min(ast_scope(lits[i])); - if(frame < 0){ - frame = range_max(ast_scope(lits[i])); // could happen if contains no symbols - if(frame >= frames) frame = frames-1; + int get_locality_rec(ast proof){ + std::pair foo(proof,INT_MAX); + std::pair bar = locality.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + if(pr(proof) == PR_ASSERTED){ + ast ass = conc(proof); + res = frame_of_assertion(ass); } - } - preds[frame] = mk_and(preds[frame],mk_not(lits[i])); + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + int bar = get_locality_rec(arg); + if(res == INT_MAX || res == bar) res = bar; + else if(bar != INT_MAX) res = -1; + } + } + return res; } - std::vector itps; // holds interpolants + int get_locality(ast proof){ + // if(lia_z3_axioms_only) return -1; + int res = get_locality_rec(proof); + if(res != -1){ + ast con = conc(proof); + range rng = ast_scope(con); + + // hack: if a clause contains "true", it reduces to "true", + // which means we won't compute the range correctly. we handle + // this case by computing the ranges of the literals separately + + if(is_true(con)){ + std::vector lits; + get_Z3_lits(conc(proof),lits); + for(unsigned i = 0; i < lits.size(); i++) + rng = range_glb(rng,ast_scope(lits[i])); + } + + if(!range_is_empty(rng)){ + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ + ast hyp = *it; + rng = range_glb(rng,ast_scope(hyp)); + } + } + + if(res == INT_MAX){ + if(range_is_empty(rng)) + res = -1; + else res = range_max(rng); + } + else { + if(!in_range(res,rng)) + res = -1; + } + } + return res; + } + + AstSet &get_hyps(ast proof){ + std::pair foo(proof,AstSet()); + std::pair bar = hyp_map.insert(foo); + AstSet &res = bar.first->second; + if(!bar.second) return res; + pfrule dk = pr(proof); + if(dk == PR_HYPOTHESIS){ + ast con = conc(proof); + res.insert(con); + } + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + AstSet &arg_hyps = get_hyps(arg); + res.insert(arg_hyps.begin(),arg_hyps.end()); + } + if(dk == PR_LEMMA){ + ast con = conc(proof); + res.erase(mk_not(con)); + if(is_or(con)){ + int clause_size = num_args(con); + for(int i = 0; i < clause_size; i++){ + ast neglit = mk_not(arg(con,i)); + res.erase(neglit); + } + } + } + } +#if 0 + AstSet::iterator it = res.begin(), en = res.end(); + if(it != en){ + AstSet::iterator old = it; + ++it; + for(; it != en; ++it, ++old) + if(!(*old < *it)) + std::cout << "foo!"; + } +#endif + return res; + } + + + // Find all the judgements of the form p <-> q, where + // p is local and q is non-local, recording them in "equivs" + // the map equivs_visited is used to record the already visited proof terms + + void find_equivs(ast proof){ + if(equivs_visited.find(proof) != equivs_visited.end()) + return; + equivs_visited.insert(proof); + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++) // do all the sub_terms + find_equivs(prem(proof,i)); + ast con = conc(proof); // get the conclusion + if(is_iff(con)){ + ast iff = con; + for(int i = 0; i < 2; i++) + if(!is_local(arg(iff,i)) && is_local(arg(iff,1-i))){ + std::pair > foo(arg(iff,i),std::pair(arg(iff,1-i),proof)); + equivs.insert(foo); + } + } + } + + // get the lits of a Z3 clause as foci terms + void get_Z3_lits(ast t, std::vector &lits){ + opr dk = op(t); + if(dk == False) + return; // false = empty clause + if(dk == Or){ + unsigned nargs = num_args(t); + lits.resize(nargs); + for(unsigned i = 0; i < nargs; i++) // do all the sub_terms + lits[i] = arg(t,i); + } + else { + lits.push_back(t); + } + } + + // resolve two clauses represented as vectors of lits. replace first clause + void resolve(ast pivot, std::vector &cls1, std::vector &cls2){ + ast neg_pivot = mk_not(pivot); + for(unsigned i = 0; i < cls1.size(); i++){ + if(cls1[i] == pivot){ + cls1[i] = cls1.back(); + cls1.pop_back(); + bool found_pivot2 = false; + for(unsigned j = 0; j < cls2.size(); j++){ + if(cls2[j] == neg_pivot) + found_pivot2 = true; + else + cls1.push_back(cls2[j]); + } + assert(found_pivot2); + return; + } + } + assert(0 && "resolve failed"); + } + + // get lits resulting from unit resolution up to and including "position" + // TODO: this is quadratic -- fix it + void do_unit_resolution(ast proof, int position, std::vector &lits){ + ast orig_clause = conc(prem(proof,0)); + get_Z3_lits(orig_clause,lits); + for(int i = 1; i <= position; i++){ + std::vector unit(1); + unit[0] = conc(prem(proof,i)); + resolve(mk_not(unit[0]),lits,unit); + } + } + + + // clear the localization variables + void clear_localization(){ + localization_vars.clear(); + localization_map.clear(); + } + + // create a fresh variable for localization + ast fresh_localization_var(ast term, int frame){ + std::ostringstream s; + s << "%" << (localization_vars.size()); + ast var = make_var(s.str().c_str(),get_type(term)); + sym_range(sym(var)) = range_full(); // make this variable global + localization_vars.push_back(LocVar(var,term,frame)); + return var; + } + + + // "localize" a term to a given frame range by + // creating new symbols to represent non-local subterms + + ast localize_term(ast e, const range &rng){ + if(ranges_intersect(ast_scope(e),rng)) + return e; // this term occurs in range, so it's O.K. + AstToAst::iterator it = localization_map.find(e); + if(it != localization_map.end()) + return it->second; + + // if is is non-local, we must first localize the arguments to + // the range of its function symbol + + int nargs = num_args(e); + if(nargs > 0 /* && (!is_local(e) || flo <= hi || fhi >= lo) */){ + range frng = rng; + if(op(e) == Uninterpreted){ + symb f = sym(e); + range srng = sym_range(f); + if(ranges_intersect(srng,rng)) // localize to desired range if possible + frng = range_glb(srng,rng); + } + std::vector largs(nargs); + for(int i = 0; i < nargs; i++){ + largs[i] = localize_term(arg(e,i),frng); + frng = range_glb(frng,ast_scope(largs[i])); + } + e = clone(e,largs); + assert(is_local(e)); + } + + + if(ranges_intersect(ast_scope(e),rng)) + return e; // this term occurs in range, so it's O.K. + + // choose a frame for the constraint that is close to range + int frame = range_near(ast_scope(e),rng); + + ast new_var = fresh_localization_var(e,frame); + localization_map[e] = new_var; + ast cnst = make(Equal,new_var,e); + antes.push_back(std::pair(cnst,frame)); + return new_var; + } + + // some patterm matching functions + + // match logical or with nargs arguments + // assumes AIG form + bool match_or(ast e, ast *args, int nargs){ + if(op(e) != Or) return false; + int n = num_args(e); + if(n != nargs) return false; + for(int i = 0; i < nargs; i++) + args[i] = arg(e,i); + return true; + } + + // match operator f with exactly nargs arguments + bool match_op(ast e, opr f, ast *args, int nargs){ + if(op(e) != f) return false; + int n = num_args(e); + if(n != nargs) return false; + for(int i = 0; i < nargs; i++) + args[i] = arg(e,i); + return true; + } + + // see if the given formula can be interpreted as + // an axiom instance (e.g., an array axiom instance). + // if so, add it to "antes" in an appropriate frame. + // this may require "localization" + + void get_axiom_instance(ast e){ + + // "store" axiom + // (or (= w q) (= (select (store a1 w y) q) (select a1 q))) + // std::cout << "ax: "; show(e); + ast lits[2],eq_ops_l[2],eq_ops_r[2],sel_ops[2], sto_ops[3], sel_ops2[2] ; + if(match_or(e,lits,2)) + if(match_op(lits[0],Equal,eq_ops_l,2)) + if(match_op(lits[1],Equal,eq_ops_r,2)) + for(int i = 0; i < 2; i++){ // try the second equality both ways + if(match_op(eq_ops_r[0],Select,sel_ops,2)) + if(match_op(sel_ops[0],Store,sto_ops,3)) + if(match_op(eq_ops_r[1],Select,sel_ops2,2)) + for(int j = 0; j < 2; j++){ // try the first equality both ways + if(eq_ops_l[0] == sto_ops[1] + && eq_ops_l[1] == sel_ops[1] + && eq_ops_l[1] == sel_ops2[1] + && sto_ops[0] == sel_ops2[0]) + if(is_local(sel_ops[0])) // store term must be local + { + ast sto = sel_ops[0]; + ast addr = localize_term(eq_ops_l[1],ast_scope(sto)); + ast res = make(Or, + make(Equal,eq_ops_l[0],addr), + make(Equal, + make(Select,sto,addr), + make(Select,sel_ops2[0],addr))); + int frame = range_min(ast_scope(res)); + antes.push_back(std::pair(res,frame)); + return; + } + std::swap(eq_ops_l[0],eq_ops_l[1]); + } + std::swap(eq_ops_r[0],eq_ops_r[1]); + } + } + + // a quantifier instantation looks like (~ forall x. P) \/ P[z/x] + // we need to find a time frame for P, then localize P[z/x] in this frame + + void get_quantifier_instance(ast e){ + ast disjs[2]; + if(match_or(e,disjs,2)){ + if(is_local(disjs[0])){ + ast res = localize_term(disjs[1], ast_scope(disjs[0])); + int frame = range_min(ast_scope(res)); + antes.push_back(std::pair(res,frame)); + return; + } + } + } + + ast get_judgement(ast proof){ + ast con = from_ast(conc(proof)); + AstSet &hyps = get_hyps(proof); + std::vector hyps_vec; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + hyps_vec.push_back(*it); + if(hyps_vec.size() == 0) return con; + con = make(Or,mk_not(make(And,hyps_vec)),con); + return con; + } + + // add the premises of a proof term to the "antes" list + + void add_antes(ast proof){ + if(antes_added.find(proof) != antes_added.end()) return; + antes_added.insert(proof); + int frame = get_locality(proof); + if(frame != -1) + if(1){ + ast e = get_judgement(proof); + if(frame >= frames) frame = frames-1; // can happen if there are no symbols + antes.push_back(std::pair(e,frame)); + return; + } + pfrule dk = pr(proof); + if(dk == PR_ASSERTED){ + ast ass = conc(proof); + frame = frame_of_assertion(ass); + if(frame >= frames) frame = frames-1; // can happen if a theory fact + antes.push_back(std::pair(ass,frame)); + return; + } + if(dk == PR_TH_LEMMA && num_prems(proof) == 0){ + get_axiom_instance(conc(proof)); + } + if(dk == PR_QUANT_INST && num_prems(proof) == 0){ + get_quantifier_instance(conc(proof)); + } + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + add_antes(arg); + } + } + + + // add quantifiers over the localization vars + // to an interpolant for frames lo-hi + + ast add_quants(ast e, int lo, int hi){ + for(int i = localization_vars.size() - 1; i >= 0; i--){ + LocVar &lv = localization_vars[i]; + opr quantifier = (lv.frame >= lo && lv.frame <= hi) ? Exists : Forall; + e = apply_quant(quantifier,lv.var,e); + } + return e; + } + + int get_lits_locality(std::vector &lits){ + range rng = range_full(); + for(std::vector::iterator it = lits.begin(), en = lits.end(); it != en; ++it){ + ast lit = *it; + rng = range_glb(rng,ast_scope(lit)); + } + if(range_is_empty(rng)) return -1; + int hi = range_max(rng); + if(hi >= frames) return frames - 1; + return hi; + } + + + struct invalid_lemma {}; + + + + + // prove a lemma (clause) using current antes list + // return proof of the lemma + // use the secondary prover + + int prove_lemma(std::vector &lits){ + + + // first try localization + if(antes.size() == 0){ + int local_frame = get_lits_locality(lits); + if(local_frame != -1) + return iproof->make_assumption(local_frame,lits); // no proof needed for purely local fact + } + + // group the assumptions by frame + std::vector preds(frames); + for(unsigned i = 0; i < preds.size(); i++) + preds[i] = mk_true(); + for(unsigned i = 0; i < antes.size(); i++){ + int frame = antes[i].second; + preds[frame] = mk_and(preds[frame],antes[i].first); // conjoin it to frame + } + + for(unsigned i = 0; i < lits.size(); i++){ + int frame; + if(!weak_mode()){ + frame = range_max(ast_scope(lits[i])); + if(frame >= frames) frame = frames-1; // could happen if contains no symbols + } + else { + frame = range_min(ast_scope(lits[i])); + if(frame < 0){ + frame = range_max(ast_scope(lits[i])); // could happen if contains no symbols + if(frame >= frames) frame = frames-1; + } + } + preds[frame] = mk_and(preds[frame],mk_not(lits[i])); + } + + + std::vector itps; // holds interpolants #if 1 - ++lemma_count; - // std::cout << "lemma: " << lemma_count << std::endl; - if(lemma_count == SHOW_LEMMA_COUNT){ - for(unsigned i = 0; i < lits.size(); i++) - show_lit(lits[i]); - std::cerr << "lemma written to file lemma.smt:\n"; - iz3base foo(*this,preds,std::vector(),std::vector()); - foo.print("lemma.smt"); - throw invalid_lemma(); - } + ++lemma_count; + // std::cout << "lemma: " << lemma_count << std::endl; + if(lemma_count == SHOW_LEMMA_COUNT){ + for(unsigned i = 0; i < lits.size(); i++) + show_lit(lits[i]); + std::cerr << "lemma written to file lemma.smt:\n"; + iz3base foo(*this,preds,std::vector(),std::vector()); + foo.print("lemma.smt"); + throw invalid_lemma(); + } #endif #if 0 - std::cout << "\nLemma:\n"; - for(unsigned i = 0; i < lits.size(); i++) - show_lit(lits[i]); + std::cout << "\nLemma:\n"; + for(unsigned i = 0; i < lits.size(); i++) + show_lit(lits[i]); #endif - // interpolate using secondary prover - profiling::timer_start("foci"); - int sat = secondary->interpolate(preds,itps); - profiling::timer_stop("foci"); + // interpolate using secondary prover + profiling::timer_start("foci"); + int sat = secondary->interpolate(preds,itps); + profiling::timer_stop("foci"); - std::cout << "lemma done" << std::endl; + std::cout << "lemma done" << std::endl; - // if sat, lemma isn't valid, something is wrong - if(sat){ + // if sat, lemma isn't valid, something is wrong + if(sat){ #if 1 - std::cerr << "invalid lemma written to file invalid_lemma.smt:\n"; - iz3base foo(*this,preds,std::vector(),std::vector()); - foo.print("invalid_lemma.smt"); + std::cerr << "invalid lemma written to file invalid_lemma.smt:\n"; + iz3base foo(*this,preds,std::vector(),std::vector()); + foo.print("invalid_lemma.smt"); #endif - throw iz3_incompleteness(); - } - assert(sat == 0); // if sat, lemma doesn't hold! + throw iz3_incompleteness(); + } + assert(sat == 0); // if sat, lemma doesn't hold! - // quantifiy the localization vars - for(unsigned i = 0; i < itps.size(); i++) - itps[i] = add_quants(itps[i],0,i); + // quantifiy the localization vars + for(unsigned i = 0; i < itps.size(); i++) + itps[i] = add_quants(itps[i],0,i); - // Make a lemma, storing interpolants - Iproof::node res = iproof->make_lemma(lits,itps); + // Make a lemma, storing interpolants + Iproof::node res = iproof->make_lemma(lits,itps); #if 0 - std::cout << "Lemma interps\n"; - for(unsigned i = 0; i < itps.size(); i++) - show(itps[i]); + std::cout << "Lemma interps\n"; + for(unsigned i = 0; i < itps.size(); i++) + show(itps[i]); #endif - // Reset state for the next lemma - antes.clear(); - antes_added.clear(); - clear_localization(); // use a fresh localization for each lemma + // Reset state for the next lemma + antes.clear(); + antes_added.clear(); + clear_localization(); // use a fresh localization for each lemma - return res; - } - - // sanity check: make sure that any non-local lit is really resolved - // with something in the non_local_lits set - - void check_non_local(ast lit, non_local_lits *nll){ - if(nll) - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - ast con = (*it)->pivot; - if(con == mk_not(lit)) return; - } - assert(0 && "bug in non-local resolution handling"); - } - - - void get_local_conclusion_lits(ast proof, bool expect_clause, AstSet &lits){ - std::vector reslits; - if(expect_clause) - get_Z3_lits(conc(proof),reslits); - else reslits.push_back(conc(proof)); - for(unsigned i = 0; i < reslits.size(); i++) - if(is_local(reslits[i])) - lits.insert(reslits[i]); - AstSet &pfhyps = get_hyps(proof); - for(AstSet::iterator hit = pfhyps.begin(), hen = pfhyps.end(); hit != hen; ++hit) - if(is_local(*hit)) - lits.insert(mk_not(*hit)); - } - - - void collect_resolvent_lits(Z3_resolvent *res, const AstSet &hyps, std::vector &lits){ - if(!res->is_unit){ - std::vector reslits; - get_Z3_lits(conc(res->proof),reslits); - for(unsigned i = 0; i < reslits.size(); i++) - if(reslits[i] != res->pivot) - lits.push_back(reslits[i]); + return res; } - AstSet &pfhyps = get_hyps(res->proof); - for(AstSet::iterator hit = pfhyps.begin(), hen = pfhyps.end(); hit != hen; ++hit) - if(hyps.find(*hit) == hyps.end()) - lits.push_back(mk_not(*hit)); - } - void filter_resolvent_lits(non_local_lits *nll, std::vector &lits){ - std::vector orig_lits; orig_lits.swap(lits); - std::set pivs; - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - pivs.insert(res->pivot); - pivs.insert(mk_not(res->pivot)); - } - for(unsigned i = 0; i < orig_lits.size(); i++) - if(pivs.find(orig_lits[i]) == pivs.end()) - lits.push_back(orig_lits[i]); - } + // sanity check: make sure that any non-local lit is really resolved + // with something in the non_local_lits set - void collect_all_resolvent_lits(non_local_lits *nll, std::vector &lits){ - if(nll){ - std::vector orig_lits; orig_lits.swap(lits); - std::set pivs; - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - pivs.insert(res->pivot); - pivs.insert(mk_not(res->pivot)); - } - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - { - std::vector reslits; - if(!res->is_unit) get_Z3_lits(conc(res->proof),reslits); - else reslits.push_back(conc(res->proof)); - for(unsigned i = 0; i < reslits.size(); i++) -#if 0 - if(reslits[i] != res->pivot && pivs.find(reslits[i]) == pivs.end()) -#endif + void check_non_local(ast lit, non_local_lits *nll){ + if(nll) + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + ast con = (*it)->pivot; + if(con == mk_not(lit)) return; + } + assert(0 && "bug in non-local resolution handling"); + } + + + void get_local_conclusion_lits(ast proof, bool expect_clause, AstSet &lits){ + std::vector reslits; + if(expect_clause) + get_Z3_lits(conc(proof),reslits); + else reslits.push_back(conc(proof)); + for(unsigned i = 0; i < reslits.size(); i++) if(is_local(reslits[i])) - lits.push_back(reslits[i]); + lits.insert(reslits[i]); + AstSet &pfhyps = get_hyps(proof); + for(AstSet::iterator hit = pfhyps.begin(), hen = pfhyps.end(); hit != hen; ++hit) + if(is_local(*hit)) + lits.insert(mk_not(*hit)); + } + + + void collect_resolvent_lits(Z3_resolvent *res, const AstSet &hyps, std::vector &lits){ + if(!res->is_unit){ + std::vector reslits; + get_Z3_lits(conc(res->proof),reslits); + for(unsigned i = 0; i < reslits.size(); i++) + if(reslits[i] != res->pivot) + lits.push_back(reslits[i]); } - } - for(unsigned i = 0; i < orig_lits.size(); i++) - if(pivs.find(orig_lits[i]) == pivs.end()) - lits.push_back(orig_lits[i]); + AstSet &pfhyps = get_hyps(res->proof); + for(AstSet::iterator hit = pfhyps.begin(), hen = pfhyps.end(); hit != hen; ++hit) + if(hyps.find(*hit) == hyps.end()) + lits.push_back(mk_not(*hit)); } - } - void collect_proof_clause(ast proof, bool expect_clause, std::vector &lits){ - if(expect_clause) - get_Z3_lits(conc(proof),lits); - else - lits.push_back(from_ast(conc(proof))); - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator hit = hyps.begin(), hen = hyps.end(); hit != hen; ++hit) - lits.push_back(mk_not(*hit)); - } - - - // turn a bunch of literals into a lemma, replacing - // non-local lits with their local equivalents - // adds the accumulated antecedents (antes) as - // proof obligations of the lemma - - Iproof::node fix_lemma(std::vector &con_lits, AstSet &hyps, non_local_lits *nll){ - std::vector lits(con_lits); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - lits.push_back(mk_not(*it)); - if(nll){ - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - collect_resolvent_lits(res,hyps,lits); - add_antes(res->proof); - } - filter_resolvent_lits(nll,lits); + void filter_resolvent_lits(non_local_lits *nll, std::vector &lits){ + std::vector orig_lits; orig_lits.swap(lits); + std::set pivs; + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + pivs.insert(res->pivot); + pivs.insert(mk_not(res->pivot)); + } + for(unsigned i = 0; i < orig_lits.size(); i++) + if(pivs.find(orig_lits[i]) == pivs.end()) + lits.push_back(orig_lits[i]); } - for(unsigned int i = 0; i < lits.size(); i++){ - EquivTab::iterator it = equivs.find(lits[i]); - if(it != equivs.end()){ - lits[i] = it->second.first; // replace with local equivalent - add_antes(it->second.second); // collect the premises that prove this - } - else { - if(!is_local(lits[i])){ - check_non_local(lits[i],nll); - lits[i] = mk_false(); - } - } - } - // TODO: should check here that derivation is local? - Iproof::node res = prove_lemma(lits); - return res; - } - int num_lits(ast ast){ - opr dk = op(ast); - if(dk == False) - return 0; - if(dk == Or){ - unsigned nargs = num_args(ast); - int n = 0; - for(unsigned i = 0; i < nargs; i++) // do all the sub_terms - n += num_lits(arg(ast,i)); - return n; - } - else - return 1; - } - - struct non_lit_local_ante {}; - - bool local_antes_simple; - - bool add_local_antes(ast proof, AstSet &hyps, bool expect_clause = false){ - if(antes_added.find(proof) != antes_added.end()) return true; - antes_added.insert(proof); - ast con = from_ast(conc(proof)); - pfrule dk = pr(proof); - if(is_local(con) || equivs.find(con) != equivs.end()){ - if(!expect_clause || num_lits(conc(proof)) == 1){ - AstSet &this_hyps = get_hyps(proof); - if(std::includes(hyps.begin(),hyps.end(),this_hyps.begin(),this_hyps.end())){ - // if(hyps.find(con) == hyps.end()) + void collect_all_resolvent_lits(non_local_lits *nll, std::vector &lits){ + if(nll){ + std::vector orig_lits; orig_lits.swap(lits); + std::set pivs; + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + pivs.insert(res->pivot); + pivs.insert(mk_not(res->pivot)); + } + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + { + std::vector reslits; + if(!res->is_unit) get_Z3_lits(conc(res->proof),reslits); + else reslits.push_back(conc(res->proof)); + for(unsigned i = 0; i < reslits.size(); i++) #if 0 - if(/* lemma_count == SHOW_LEMMA_COUNT - 1 && */ !is_literal_or_lit_iff(conc(proof))){ - std::cout << "\nnon-lit local ante\n"; - show_step(proof); - show(conc(proof)); - throw non_lit_local_ante(); - } + if(reslits[i] != res->pivot && pivs.find(reslits[i]) == pivs.end()) #endif - local_antes.push_back(proof); - return true; - } - else - ; //std::cout << "bar!\n"; - } + if(is_local(reslits[i])) + lits.push_back(reslits[i]); + } + } + for(unsigned i = 0; i < orig_lits.size(); i++) + if(pivs.find(orig_lits[i]) == pivs.end()) + lits.push_back(orig_lits[i]); + } } - if(dk == PR_ASSERTED - //|| dk == PR_HYPOTHESIS - //|| dk == PR_TH_LEMMA - || dk == PR_QUANT_INST - //|| dk == PR_UNIT_RESOLUTION - //|| dk == PR_LEMMA + + void collect_proof_clause(ast proof, bool expect_clause, std::vector &lits){ + if(expect_clause) + get_Z3_lits(conc(proof),lits); + else + lits.push_back(from_ast(conc(proof))); + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator hit = hyps.begin(), hen = hyps.end(); hit != hen; ++hit) + lits.push_back(mk_not(*hit)); + } + + + // turn a bunch of literals into a lemma, replacing + // non-local lits with their local equivalents + // adds the accumulated antecedents (antes) as + // proof obligations of the lemma + + Iproof::node fix_lemma(std::vector &con_lits, AstSet &hyps, non_local_lits *nll){ + std::vector lits(con_lits); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + lits.push_back(mk_not(*it)); + if(nll){ + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + collect_resolvent_lits(res,hyps,lits); + add_antes(res->proof); + } + filter_resolvent_lits(nll,lits); + } + for(unsigned int i = 0; i < lits.size(); i++){ + EquivTab::iterator it = equivs.find(lits[i]); + if(it != equivs.end()){ + lits[i] = it->second.first; // replace with local equivalent + add_antes(it->second.second); // collect the premises that prove this + } + else { + if(!is_local(lits[i])){ + check_non_local(lits[i],nll); + lits[i] = mk_false(); + } + } + } + // TODO: should check here that derivation is local? + Iproof::node res = prove_lemma(lits); + return res; + } + + int num_lits(ast ast){ + opr dk = op(ast); + if(dk == False) + return 0; + if(dk == Or){ + unsigned nargs = num_args(ast); + int n = 0; + for(unsigned i = 0; i < nargs; i++) // do all the sub_terms + n += num_lits(arg(ast,i)); + return n; + } + else + return 1; + } + + struct non_lit_local_ante {}; + + bool local_antes_simple; + + bool add_local_antes(ast proof, AstSet &hyps, bool expect_clause = false){ + if(antes_added.find(proof) != antes_added.end()) return true; + antes_added.insert(proof); + ast con = from_ast(conc(proof)); + pfrule dk = pr(proof); + if(is_local(con) || equivs.find(con) != equivs.end()){ + if(!expect_clause || num_lits(conc(proof)) == 1){ + AstSet &this_hyps = get_hyps(proof); + if(std::includes(hyps.begin(),hyps.end(),this_hyps.begin(),this_hyps.end())){ + // if(hyps.find(con) == hyps.end()) +#if 0 + if(/* lemma_count == SHOW_LEMMA_COUNT - 1 && */ !is_literal_or_lit_iff(conc(proof))){ + std::cout << "\nnon-lit local ante\n"; + show_step(proof); + show(conc(proof)); + throw non_lit_local_ante(); + } +#endif + local_antes.push_back(proof); + return true; + } + else + ; //std::cout << "bar!\n"; + } + } + if(dk == PR_ASSERTED + //|| dk == PR_HYPOTHESIS + //|| dk == PR_TH_LEMMA + || dk == PR_QUANT_INST + //|| dk == PR_UNIT_RESOLUTION + //|| dk == PR_LEMMA ) - return false; - if(dk == PR_HYPOTHESIS && hyps.find(con) != hyps.end()) - ; //std::cout << "blif!\n"; - if(dk == PR_HYPOTHESIS - || dk == PR_LEMMA) - ; //std::cout << "foo!\n"; - if(dk == PR_TH_LEMMA && num_prems(proof) == 0){ - // Check if this is an axiom instance - get_axiom_instance(conc(proof)); - } + return false; + if(dk == PR_HYPOTHESIS && hyps.find(con) != hyps.end()) + ; //std::cout << "blif!\n"; + if(dk == PR_HYPOTHESIS + || dk == PR_LEMMA) + ; //std::cout << "foo!\n"; + if(dk == PR_TH_LEMMA && num_prems(proof) == 0){ + // Check if this is an axiom instance + get_axiom_instance(conc(proof)); + } - // #define SIMPLE_PROOFS + // #define SIMPLE_PROOFS #ifdef SIMPLE_PROOFS - if(!(dk == PR_TRANSITIVITY - || dk == PR_MONOTONICITY)) - local_antes_simple = false; + if(!(dk == PR_TRANSITIVITY + || dk == PR_MONOTONICITY)) + local_antes_simple = false; #endif - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - try { - if(!add_local_antes(arg, hyps, dk == PR_UNIT_RESOLUTION && i == 0)) - return false; - } - catch (non_lit_local_ante) { - std::cout << "\n"; - show_step(proof); - show(conc(proof)); - throw non_lit_local_ante(); - } - } - return true; - } - - std::vector lit_trace; - hash_set marked_proofs; - - bool proof_has_lit(const ast &proof, const ast &lit){ - AstSet &hyps = get_hyps(proof); - if(hyps.find(mk_not(lit)) != hyps.end()) - return true; - std::vector lits; - ast con = conc(proof); - get_Z3_lits(con, lits); - for(unsigned i = 0; i < lits.size(); i++) - if(lits[i] == lit) + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + try { + if(!add_local_antes(arg, hyps, dk == PR_UNIT_RESOLUTION && i == 0)) + return false; + } + catch (non_lit_local_ante) { + std::cout << "\n"; + show_step(proof); + show(conc(proof)); + throw non_lit_local_ante(); + } + } return true; - return false; - } - - - void trace_lit_rec(const ast &lit, const ast &proof, AstHashSet &memo){ - if(memo.find(proof) == memo.end()){ - memo.insert(proof); - AstSet &hyps = get_hyps(proof); - std::vector lits; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - lits.push_back(mk_not(*it)); - ast con = conc(proof); - get_Z3_lits(con, lits); - for(unsigned i = 0; i < lits.size(); i++){ - if(lits[i] == lit){ - print_expr(std::cout,proof); - std::cout << "\n"; - marked_proofs.insert(proof); - pfrule dk = pr(proof); - if(dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA){ - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - trace_lit_rec(lit,arg,memo); - } - } - else - lit_trace.push_back(proof); - } - } - } - } - - ast traced_lit; - - int trace_lit(const ast &lit, const ast &proof){ - marked_proofs.clear(); - lit_trace.clear(); - traced_lit = lit; - AstHashSet memo; - trace_lit_rec(lit,proof,memo); - return lit_trace.size(); - } - - bool is_literal_or_lit_iff(const ast &lit){ - if(my_is_literal(lit)) return true; - if(op(lit) == Iff){ - return my_is_literal(arg(lit,0)) && my_is_literal(arg(lit,1)); - } - return false; - } - - bool my_is_literal(const ast &lit){ - ast abslit = is_not(lit) ? arg(lit,0) : lit; - int f = op(abslit); - return !(f == And || f == Or || f == Iff); - } - - void print_lit(const ast &lit){ - ast abslit = is_not(lit) ? arg(lit,0) : lit; - if(!is_literal_or_lit_iff(lit)){ - if(is_not(lit)) std::cout << "~"; - std::cout << "["; - print_expr(std::cout,abslit); - std::cout << "]"; - } - else - print_expr(std::cout,lit); - } - - void show_lit(const ast &lit){ - print_lit(lit); - std::cout << "\n"; - } - - void print_z3_lit(const ast &a){ - print_lit(from_ast(a)); - } - - void show_z3_lit(const ast &a){ - print_z3_lit(a); - std::cout << "\n"; - } - - - void show_con(const ast &proof, bool brief){ - if(!traced_lit.null() && proof_has_lit(proof,traced_lit)) - std::cout << "(*) "; - ast con = conc(proof); - AstSet &hyps = get_hyps(proof); - int count = 0; - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ - if(brief && ++count > 5){ - std::cout << "... "; - break; - } - print_lit(*it); - std::cout << " "; - } - std::cout << "|- "; - std::vector lits; - get_Z3_lits(con,lits); - for(unsigned i = 0; i < lits.size(); i++){ - print_lit(lits[i]); - std::cout << " "; - } - std::cout << "\n"; - } - - void show_step(const ast &proof){ - std::cout << "\n"; - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - std::cout << "(" << i << ") "; - ast arg = prem(proof,i); - show_con(arg,true); - } - std::cout << "|------ "; - std::cout << string_of_symbol(sym(proof)) << "\n"; - show_con(proof,false); - } - - void show_marked( const ast &proof){ - std::cout << "\n"; - unsigned nprems = num_prems(proof); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - if(!traced_lit.null() && proof_has_lit(arg,traced_lit)){ - std::cout << "(" << i << ") "; - show_con(arg,true); - } - } - } - - std::vector pfhist; - int pfhist_pos; - - void pfgoto(const ast &proof){ - if(pfhist.size() == 0) - pfhist_pos = 0; - else pfhist_pos++; - pfhist.resize(pfhist_pos); - pfhist.push_back(proof); - show_step(proof); - } - - void show_nll(non_local_lits *nll){ - if(!nll)return; - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - show_step(res->proof); - std::cout << "Pivot: "; - show(res->pivot); - std::cout << std::endl; - } - } - - void pfback(){ - if(pfhist_pos > 0){ - pfhist_pos--; - show_step(pfhist[pfhist_pos]); - } - } - - void pffwd(){ - if(pfhist_pos < ((int)pfhist.size()) - 1){ - pfhist_pos++; - show_step(pfhist[pfhist_pos]); - } - } - - void pfprem(int i){ - if(pfhist.size() > 0){ - ast proof = pfhist[pfhist_pos]; - unsigned nprems = num_prems(proof); - if(i >= 0 && i < (int)nprems) - pfgoto(prem(proof,i)); - } - } - - int extract_th_lemma_common(std::vector &lits, non_local_lits *nll, bool lemma_nll = true){ - std::vector la = local_antes; - local_antes.clear(); // clear antecedents for next lemma - antes_added.clear(); - // std::vector lits; - AstSet hyps; // no hyps - for(unsigned i = 0; i < la.size(); i++) - lits.push_back(mk_not(from_ast(conc(la[i])))); - // lits.push_back(from_ast(conc(proof))); - Iproof::node res =fix_lemma(lits,hyps, lemma_nll ? nll : 0); - for(unsigned i = 0; i < la.size(); i++){ - Iproof::node q = translate_main(la[i],nll,false); - ast pnode = from_ast(conc(la[i])); - assert(is_local(pnode) || equivs.find(pnode) != equivs.end()); - Iproof::node neg = res; - Iproof::node pos = q; - if(is_not(pnode)){ - pnode = mk_not(pnode); - std::swap(neg,pos); - } - try { - res = iproof->make_resolution(pnode,neg,pos); - } - catch (const iz3proof::proof_error){ - std::cout << "\nresolution error in theory lemma\n"; - std::cout << "lits:\n"; - for(unsigned j = 0; j < lits.size(); j++) - show_lit(lits[j]); - std::cout << "\nstep:\n"; - show_step(la[i]); - throw invalid_lemma(); - } - } - return res; - } - - Iproof::node extract_simple_proof(const ast &proof, hash_set &leaves){ - if(leaves.find(proof) != leaves.end()) - return iproof->make_hypothesis(conc(proof)); - ast con = from_ast(conc(proof)); - pfrule dk = pr(proof); - unsigned nprems = num_prems(proof); - std::vector args(nprems); - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - args[i] = extract_simple_proof(arg,leaves); } - switch(dk){ - case PR_TRANSITIVITY: - return iproof->make_transitivity(con,args[0],args[1]); - case PR_MONOTONICITY: - return iproof->make_congruence(con,args); - case PR_REFLEXIVITY: - return iproof->make_reflexivity(con); - case PR_SYMMETRY: - return iproof->make_symmetry(con,args[0]); + std::vector lit_trace; + hash_set marked_proofs; + + bool proof_has_lit(const ast &proof, const ast &lit){ + AstSet &hyps = get_hyps(proof); + if(hyps.find(mk_not(lit)) != hyps.end()) + return true; + std::vector lits; + ast con = conc(proof); + get_Z3_lits(con, lits); + for(unsigned i = 0; i < lits.size(); i++) + if(lits[i] == lit) + return true; + return false; } - assert(0 && "extract_simple_proof: unknown op"); - return 0; - } - int extract_th_lemma_simple(const ast &proof, std::vector &lits){ - std::vector la = local_antes; - local_antes.clear(); // clear antecedents for next lemma - antes_added.clear(); - hash_set leaves; - for(unsigned i = 0; i < la.size(); i++) - leaves.insert(la[i]); - - Iproof::node ipf = extract_simple_proof(proof,leaves); - ast con = from_ast(conc(proof)); - Iproof::node hyp = iproof->make_hypothesis(mk_not(con)); - ipf = iproof->make_eqcontra(ipf,hyp); - - // std::vector lits; - AstSet hyps; // no hyps - for(unsigned i = 0; i < la.size(); i++) - lits.push_back(mk_not(from_ast(conc(la[i])))); - // lits.push_back(from_ast(conc(proof))); - - Iproof::node res = iproof->make_contra(ipf,lits); - - for(unsigned i = 0; i < la.size(); i++){ - Iproof::node q = translate_main(la[i],0,false); - ast pnode = from_ast(conc(la[i])); - assert(is_local(pnode) || equivs.find(pnode) != equivs.end()); - Iproof::node neg = res; - Iproof::node pos = q; - if(is_not(pnode)){ - pnode = mk_not(pnode); - std::swap(neg,pos); - } - try { - res = iproof->make_resolution(pnode,neg,pos); - } - catch (const iz3proof::proof_error){ - std::cout << "\nresolution error in theory lemma\n"; - std::cout << "lits:\n"; - for(unsigned j = 0; j < lits.size(); j++) - show_lit(lits[j]); - std::cout << "\nstep:\n"; - show_step(la[i]); - throw invalid_lemma(); - } - } - return res; - } - - // #define NEW_EXTRACT_TH_LEMMA - - void get_local_hyps(const ast &proof, std::set &res){ - std::set hyps = get_hyps(proof); - for(std::set::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ - ast hyp = *it; - if(is_local(hyp)) - res.insert(hyp); - } - } - - int extract_th_lemma(ast proof, std::vector &lits, non_local_lits *nll){ - pfrule dk = pr(proof); - unsigned nprems = num_prems(proof); -#ifdef NEW_EXTRACT_TH_LEMMA - if(nprems == 0 && !nll) -#else - if(nprems == 0) -#endif - return 0; - if(nprems == 0 && dk == PR_TH_LEMMA) - // Check if this is an axiom instance - get_axiom_instance(conc(proof)); - - local_antes_simple = true; - for(unsigned i = 0; i < nprems; i++){ - ast arg = prem(proof,i); - if(!add_local_antes(arg,get_hyps(proof))){ - local_antes.clear(); // clear antecedents for next lemma - antes_added.clear(); - antes.clear(); - return 0; - } - } -#ifdef NEW_EXTRACT_TH_LEMMA - bool lemma_nll = nprems > 1; - if(nll && !lemma_nll){ - lemma_nll = false; - // std::cout << "lemma count = " << nll_lemma_count << "\n"; - for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ - Z3_resolvent *res = *it; - ast arg = res->proof; - std::set loc_hyps; get_local_hyps(arg,loc_hyps); - if(!add_local_antes(arg,loc_hyps)){ - local_antes.clear(); // clear antecedents for next lemma - antes_added.clear(); - antes.clear(); - return 0; + void trace_lit_rec(const ast &lit, const ast &proof, AstHashSet &memo){ + if(memo.find(proof) == memo.end()){ + memo.insert(proof); + AstSet &hyps = get_hyps(proof); + std::vector lits; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + lits.push_back(mk_not(*it)); + ast con = conc(proof); + get_Z3_lits(con, lits); + for(unsigned i = 0; i < lits.size(); i++){ + if(lits[i] == lit){ + print_expr(std::cout,proof); + std::cout << "\n"; + marked_proofs.insert(proof); + pfrule dk = pr(proof); + if(dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA){ + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + trace_lit_rec(lit,arg,memo); + } + } + else + lit_trace.push_back(proof); + } + } } - } - collect_all_resolvent_lits(nll,lits); } - int my_count = nll_lemma_count++; - int res; - try { - res = extract_th_lemma_common(lits,nll,lemma_nll); + + ast traced_lit; + + int trace_lit(const ast &lit, const ast &proof){ + marked_proofs.clear(); + lit_trace.clear(); + traced_lit = lit; + AstHashSet memo; + trace_lit_rec(lit,proof,memo); + return lit_trace.size(); } + + bool is_literal_or_lit_iff(const ast &lit){ + if(my_is_literal(lit)) return true; + if(op(lit) == Iff){ + return my_is_literal(arg(lit,0)) && my_is_literal(arg(lit,1)); + } + return false; + } + + bool my_is_literal(const ast &lit){ + ast abslit = is_not(lit) ? arg(lit,0) : lit; + int f = op(abslit); + return !(f == And || f == Or || f == Iff); + } + + void print_lit(const ast &lit){ + ast abslit = is_not(lit) ? arg(lit,0) : lit; + if(!is_literal_or_lit_iff(lit)){ + if(is_not(lit)) std::cout << "~"; + std::cout << "["; + print_expr(std::cout,abslit); + std::cout << "]"; + } + else + print_expr(std::cout,lit); + } + + void show_lit(const ast &lit){ + print_lit(lit); + std::cout << "\n"; + } + + void print_z3_lit(const ast &a){ + print_lit(from_ast(a)); + } + + void show_z3_lit(const ast &a){ + print_z3_lit(a); + std::cout << "\n"; + } + + + void show_con(const ast &proof, bool brief){ + if(!traced_lit.null() && proof_has_lit(proof,traced_lit)) + std::cout << "(*) "; + ast con = conc(proof); + AstSet &hyps = get_hyps(proof); + int count = 0; + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ + if(brief && ++count > 5){ + std::cout << "... "; + break; + } + print_lit(*it); + std::cout << " "; + } + std::cout << "|- "; + std::vector lits; + get_Z3_lits(con,lits); + for(unsigned i = 0; i < lits.size(); i++){ + print_lit(lits[i]); + std::cout << " "; + } + std::cout << "\n"; + } + + void show_step(const ast &proof){ + std::cout << "\n"; + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + std::cout << "(" << i << ") "; + ast arg = prem(proof,i); + show_con(arg,true); + } + std::cout << "|------ "; + std::cout << string_of_symbol(sym(proof)) << "\n"; + show_con(proof,false); + } + + void show_marked( const ast &proof){ + std::cout << "\n"; + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + if(!traced_lit.null() && proof_has_lit(arg,traced_lit)){ + std::cout << "(" << i << ") "; + show_con(arg,true); + } + } + } + + std::vector pfhist; + int pfhist_pos; + + void pfgoto(const ast &proof){ + if(pfhist.size() == 0) + pfhist_pos = 0; + else pfhist_pos++; + pfhist.resize(pfhist_pos); + pfhist.push_back(proof); + show_step(proof); + } + + void show_nll(non_local_lits *nll){ + if(!nll)return; + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + show_step(res->proof); + std::cout << "Pivot: "; + show(res->pivot); + std::cout << std::endl; + } + } + + void pfback(){ + if(pfhist_pos > 0){ + pfhist_pos--; + show_step(pfhist[pfhist_pos]); + } + } + + void pffwd(){ + if(pfhist_pos < ((int)pfhist.size()) - 1){ + pfhist_pos++; + show_step(pfhist[pfhist_pos]); + } + } + + void pfprem(int i){ + if(pfhist.size() > 0){ + ast proof = pfhist[pfhist_pos]; + unsigned nprems = num_prems(proof); + if(i >= 0 && i < (int)nprems) + pfgoto(prem(proof,i)); + } + } + + int extract_th_lemma_common(std::vector &lits, non_local_lits *nll, bool lemma_nll = true){ + std::vector la = local_antes; + local_antes.clear(); // clear antecedents for next lemma + antes_added.clear(); + // std::vector lits; + AstSet hyps; // no hyps + for(unsigned i = 0; i < la.size(); i++) + lits.push_back(mk_not(from_ast(conc(la[i])))); + // lits.push_back(from_ast(conc(proof))); + Iproof::node res =fix_lemma(lits,hyps, lemma_nll ? nll : 0); + for(unsigned i = 0; i < la.size(); i++){ + Iproof::node q = translate_main(la[i],nll,false); + ast pnode = from_ast(conc(la[i])); + assert(is_local(pnode) || equivs.find(pnode) != equivs.end()); + Iproof::node neg = res; + Iproof::node pos = q; + if(is_not(pnode)){ + pnode = mk_not(pnode); + std::swap(neg,pos); + } + try { + res = iproof->make_resolution(pnode,neg,pos); + } + catch (const iz3proof::proof_error){ + std::cout << "\nresolution error in theory lemma\n"; + std::cout << "lits:\n"; + for(unsigned j = 0; j < lits.size(); j++) + show_lit(lits[j]); + std::cout << "\nstep:\n"; + show_step(la[i]); + throw invalid_lemma(); + } + } + return res; + } + + Iproof::node extract_simple_proof(const ast &proof, hash_set &leaves){ + if(leaves.find(proof) != leaves.end()) + return iproof->make_hypothesis(conc(proof)); + ast con = from_ast(conc(proof)); + pfrule dk = pr(proof); + unsigned nprems = num_prems(proof); + std::vector args(nprems); + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + args[i] = extract_simple_proof(arg,leaves); + } + + switch(dk){ + case PR_TRANSITIVITY: + return iproof->make_transitivity(con,args[0],args[1]); + case PR_MONOTONICITY: + return iproof->make_congruence(con,args); + case PR_REFLEXIVITY: + return iproof->make_reflexivity(con); + case PR_SYMMETRY: + return iproof->make_symmetry(con,args[0]); + } + assert(0 && "extract_simple_proof: unknown op"); + return 0; + } + + int extract_th_lemma_simple(const ast &proof, std::vector &lits){ + std::vector la = local_antes; + local_antes.clear(); // clear antecedents for next lemma + antes_added.clear(); + + hash_set leaves; + for(unsigned i = 0; i < la.size(); i++) + leaves.insert(la[i]); + + Iproof::node ipf = extract_simple_proof(proof,leaves); + ast con = from_ast(conc(proof)); + Iproof::node hyp = iproof->make_hypothesis(mk_not(con)); + ipf = iproof->make_eqcontra(ipf,hyp); + + // std::vector lits; + AstSet hyps; // no hyps + for(unsigned i = 0; i < la.size(); i++) + lits.push_back(mk_not(from_ast(conc(la[i])))); + // lits.push_back(from_ast(conc(proof))); + + Iproof::node res = iproof->make_contra(ipf,lits); + + for(unsigned i = 0; i < la.size(); i++){ + Iproof::node q = translate_main(la[i],0,false); + ast pnode = from_ast(conc(la[i])); + assert(is_local(pnode) || equivs.find(pnode) != equivs.end()); + Iproof::node neg = res; + Iproof::node pos = q; + if(is_not(pnode)){ + pnode = mk_not(pnode); + std::swap(neg,pos); + } + try { + res = iproof->make_resolution(pnode,neg,pos); + } + catch (const iz3proof::proof_error){ + std::cout << "\nresolution error in theory lemma\n"; + std::cout << "lits:\n"; + for(unsigned j = 0; j < lits.size(); j++) + show_lit(lits[j]); + std::cout << "\nstep:\n"; + show_step(la[i]); + throw invalid_lemma(); + } + } + return res; + } + + // #define NEW_EXTRACT_TH_LEMMA + + void get_local_hyps(const ast &proof, std::set &res){ + std::set hyps = get_hyps(proof); + for(std::set::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it){ + ast hyp = *it; + if(is_local(hyp)) + res.insert(hyp); + } + } + + int extract_th_lemma(ast proof, std::vector &lits, non_local_lits *nll){ + pfrule dk = pr(proof); + unsigned nprems = num_prems(proof); +#ifdef NEW_EXTRACT_TH_LEMMA + if(nprems == 0 && !nll) +#else + if(nprems == 0) +#endif + return 0; + if(nprems == 0 && dk == PR_TH_LEMMA) + // Check if this is an axiom instance + get_axiom_instance(conc(proof)); + + local_antes_simple = true; + for(unsigned i = 0; i < nprems; i++){ + ast arg = prem(proof,i); + if(!add_local_antes(arg,get_hyps(proof))){ + local_antes.clear(); // clear antecedents for next lemma + antes_added.clear(); + antes.clear(); + return 0; + } + } +#ifdef NEW_EXTRACT_TH_LEMMA + bool lemma_nll = nprems > 1; + if(nll && !lemma_nll){ + lemma_nll = false; + // std::cout << "lemma count = " << nll_lemma_count << "\n"; + for(ResolventAppSet::iterator it = nll->proofs.begin(), en = nll->proofs.end(); it != en; ++it){ + Z3_resolvent *res = *it; + ast arg = res->proof; + std::set loc_hyps; get_local_hyps(arg,loc_hyps); + if(!add_local_antes(arg,loc_hyps)){ + local_antes.clear(); // clear antecedents for next lemma + antes_added.clear(); + antes.clear(); + return 0; + } + } + collect_all_resolvent_lits(nll,lits); + } + int my_count = nll_lemma_count++; + int res; + try { + res = extract_th_lemma_common(lits,nll,lemma_nll); + } #if 1 - catch (const invalid_lemma &) { - std::cout << "\n\nlemma: " << my_count; - std::cout << "\n\nproof node: \n"; - show_step(proof); - std::cout << "\n\nnon-local: \n"; - show_nll(nll); - pfgoto(nll->proofs[0]->proof); - show(conc(pfhist.back())); - pfprem(1); - show(conc(pfhist.back())); - pfprem(0); - show(conc(pfhist.back())); - pfprem(0); - show(conc(pfhist.back())); - pfprem(0); - show(conc(pfhist.back())); - std::cout << "\n\nliterals: \n"; - for(int i = 0; i < lits.size(); i++) - show_lit(lits[i]); - throw invalid_lemma(); - } + catch (const invalid_lemma &) { + std::cout << "\n\nlemma: " << my_count; + std::cout << "\n\nproof node: \n"; + show_step(proof); + std::cout << "\n\nnon-local: \n"; + show_nll(nll); + pfgoto(nll->proofs[0]->proof); + show(conc(pfhist.back())); + pfprem(1); + show(conc(pfhist.back())); + pfprem(0); + show(conc(pfhist.back())); + pfprem(0); + show(conc(pfhist.back())); + pfprem(0); + show(conc(pfhist.back())); + std::cout << "\n\nliterals: \n"; + for(int i = 0; i < lits.size(); i++) + show_lit(lits[i]); + throw invalid_lemma(); + } #endif - return res; + return res; #else #ifdef SIMPLE_PROOFS - if(local_antes_simple && !nll) - return extract_th_lemma_simple(proof, lits); + if(local_antes_simple && !nll) + return extract_th_lemma_simple(proof, lits); #endif - return extract_th_lemma_common(lits,nll); + return extract_th_lemma_common(lits,nll); #endif - } - - int extract_th_lemma_ur(ast proof, int position, std::vector &lits, non_local_lits *nll){ - for(int i = 0; i <= position; i++){ - ast arg = prem(proof,i); - if(!add_local_antes(arg,get_hyps(proof),i==0)){ - local_antes.clear(); // clear antecedents for next lemma - antes_added.clear(); - antes.clear(); - return 0; - } } - return extract_th_lemma_common(lits,nll); - } - // see if any of the pushed resolvents are resolutions - // push the current proof into the latest such - int push_into_resolvent(ast proof, std::vector &lits, non_local_lits *nll, bool expect_clause){ - if(!nll) return 0; - if(num_args(proof) > 1) return 0; - ResolventAppSet resos = nll->proofs; - int pos = resos.size()-1; - for( ResolventAppSet::reverse_iterator it = resos.rbegin(), en = resos.rend(); it != en; ++it, --pos){ - Z3_resolvent *reso = *it; - ast ante = reso->proof; - ast pivot = reso->pivot; - bool is_unit = reso->is_unit; - pfrule dk = pr(ante); - bool pushable = dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA; - if(!pushable && num_args(ante) > 1){ + int extract_th_lemma_ur(ast proof, int position, std::vector &lits, non_local_lits *nll){ + for(int i = 0; i <= position; i++){ + ast arg = prem(proof,i); + if(!add_local_antes(arg,get_hyps(proof),i==0)){ + local_antes.clear(); // clear antecedents for next lemma + antes_added.clear(); + antes.clear(); + return 0; + } + } + return extract_th_lemma_common(lits,nll); + } + + // see if any of the pushed resolvents are resolutions + // push the current proof into the latest such + int push_into_resolvent(ast proof, std::vector &lits, non_local_lits *nll, bool expect_clause){ + if(!nll) return 0; + if(num_args(proof) > 1) return 0; + ResolventAppSet resos = nll->proofs; + int pos = resos.size()-1; + for( ResolventAppSet::reverse_iterator it = resos.rbegin(), en = resos.rend(); it != en; ++it, --pos){ + Z3_resolvent *reso = *it; + ast ante = reso->proof; + ast pivot = reso->pivot; + bool is_unit = reso->is_unit; + pfrule dk = pr(ante); + bool pushable = dk == PR_UNIT_RESOLUTION || dk == PR_LEMMA; + if(!pushable && num_args(ante) > 1){ #if 0 - if (!is_local(conc(ante))) - std::cout << "non-local "; - std::cout << "pushable!\n"; + if (!is_local(conc(ante))) + std::cout << "non-local "; + std::cout << "pushable!\n"; #endif - pushable = true; - } - if(pushable){ - // remove the resolvent from list and add new clause as resolvent - resos.erase((++it).base()); - for(; pos < (int)resos.size(); pos++){ - Z3_resolvent *r = resos[pos]; - resos[pos] = find_resolvent(r->proof,r->is_unit,mk_not(pivot)); + pushable = true; + } + if(pushable){ + // remove the resolvent from list and add new clause as resolvent + resos.erase((++it).base()); + for(; pos < (int)resos.size(); pos++){ + Z3_resolvent *r = resos[pos]; + resos[pos] = find_resolvent(r->proof,r->is_unit,mk_not(pivot)); + } + resos.push_back(find_resolvent(proof,!expect_clause,mk_not(pivot))); + non_local_lits *new_nll = find_nll(resos); + try { + int res = translate_main(ante,new_nll,!is_unit); + return res; + } + catch (const invalid_lemma &) { + std::cout << "\n\npushing: \n"; + std::cout << "nproof node: \n"; + show_step(proof); + std::cout << "\n\nold non-local: \n"; + show_nll(nll); + std::cout << "\n\nnew non-local: \n"; + show_nll(new_nll); + throw invalid_lemma(); + } + } } - resos.push_back(find_resolvent(proof,!expect_clause,mk_not(pivot))); - non_local_lits *new_nll = find_nll(resos); - try { - int res = translate_main(ante,new_nll,!is_unit); - return res; - } - catch (const invalid_lemma &) { - std::cout << "\n\npushing: \n"; - std::cout << "nproof node: \n"; - show_step(proof); - std::cout << "\n\nold non-local: \n"; - show_nll(nll); - std::cout << "\n\nnew non-local: \n"; - show_nll(new_nll); - throw invalid_lemma(); - } - } + return 0; // no pushed resolvents are resolution steps } - return 0; // no pushed resolvents are resolution steps - } - non_local_lits *find_nll(ResolventAppSet &proofs){ - if(proofs.empty()) - return (non_local_lits *)0; - std::pair foo(non_local_lits(proofs),(non_local_lits *)0); - std::pair::iterator,bool> bar = - non_local_lits_unique.insert(foo); - non_local_lits *&res = bar.first->second; - if(bar.second) - res = new non_local_lits(bar.first->first); - return res; - } - - Z3_resolvent *find_resolvent(ast proof, bool unit, ast pivot){ - std::pair foo(Z3_resolvent(proof,unit,pivot),(Z3_resolvent *)0); - std::pair::iterator,bool> bar = - Z3_resolvent_unique.insert(foo); - Z3_resolvent *&res = bar.first->second; - if(bar.second) - res = new Z3_resolvent(bar.first->first); - return res; - } - - // translate a unit resolution at position pos of given app - int translate_ur(ast proof, int position, non_local_lits *nll){ - ast ante = prem(proof,position); - if(position <= 0) - return translate_main(ante, nll); - ast pnode = conc(ante); - ast pnode_abs = !is_not(pnode) ? pnode : mk_not(pnode); - if(is_local(pnode) || equivs.find(pnode) != equivs.end()){ - Iproof::node neg = translate_ur(proof,position-1,nll); - Iproof::node pos = translate_main(ante, nll, false); - if(is_not(pnode)){ - pnode = mk_not(pnode); - std::swap(neg,pos); - } - try { - return iproof->make_resolution(pnode,neg,pos); - } - catch (const iz3proof::proof_error){ - std::cout << "resolution error in unit_resolution, position" << position << "\n"; - show_step(proof); - throw invalid_lemma(); - } + non_local_lits *find_nll(ResolventAppSet &proofs){ + if(proofs.empty()) + return (non_local_lits *)0; + std::pair foo(non_local_lits(proofs),(non_local_lits *)0); + std::pair::iterator,bool> bar = + non_local_lits_unique.insert(foo); + non_local_lits *&res = bar.first->second; + if(bar.second) + res = new non_local_lits(bar.first->first); + return res; } - else { - // non-local pivot we have no local equivalent for - if(true){ - // try pushing the non-local resolution up - pfrule dk = pr(ante); - non_local_lits *old_nll = nll; - if(dk == PR_HYPOTHESIS) - ; //std::cout << "non-local hyp!\n"; // resolving with a hyp is a no-op + + Z3_resolvent *find_resolvent(ast proof, bool unit, ast pivot){ + std::pair foo(Z3_resolvent(proof,unit,pivot),(Z3_resolvent *)0); + std::pair::iterator,bool> bar = + Z3_resolvent_unique.insert(foo); + Z3_resolvent *&res = bar.first->second; + if(bar.second) + res = new Z3_resolvent(bar.first->first); + return res; + } + + // translate a unit resolution at position pos of given app + int translate_ur(ast proof, int position, non_local_lits *nll){ + ast ante = prem(proof,position); + if(position <= 0) + return translate_main(ante, nll); + ast pnode = conc(ante); + ast pnode_abs = !is_not(pnode) ? pnode : mk_not(pnode); + if(is_local(pnode) || equivs.find(pnode) != equivs.end()){ + Iproof::node neg = translate_ur(proof,position-1,nll); + Iproof::node pos = translate_main(ante, nll, false); + if(is_not(pnode)){ + pnode = mk_not(pnode); + std::swap(neg,pos); + } + try { + return iproof->make_resolution(pnode,neg,pos); + } + catch (const iz3proof::proof_error){ + std::cout << "resolution error in unit_resolution, position" << position << "\n"; + show_step(proof); + throw invalid_lemma(); + } + } else { - ResolventAppSet new_proofs; - if(nll) new_proofs = nll->proofs; - Z3_resolvent *reso = find_resolvent(ante,true,pnode); - new_proofs.push_back(reso); - nll = find_nll(new_proofs); + // non-local pivot we have no local equivalent for + if(true){ + // try pushing the non-local resolution up + pfrule dk = pr(ante); + non_local_lits *old_nll = nll; + if(dk == PR_HYPOTHESIS) + ; //std::cout << "non-local hyp!\n"; // resolving with a hyp is a no-op + else { + ResolventAppSet new_proofs; + if(nll) new_proofs = nll->proofs; + Z3_resolvent *reso = find_resolvent(ante,true,pnode); + new_proofs.push_back(reso); + nll = find_nll(new_proofs); + } + try { + return translate_ur(proof,position-1,nll); + } + catch (const invalid_lemma &) { + if(old_nll != nll){ + std::cout << "\n\nadded_nll: \n"; + std::cout << "nproof node: \n"; + show_step(proof); + std::cout << "\n\new non-local step: \n"; + show_step(nll->proofs.back()->proof); + } + throw invalid_lemma(); + } + + } + else { + // just make a lemma + std::vector lits; + do_unit_resolution(proof,position,lits); + int res; + if(!(res = extract_th_lemma_ur(proof,position,lits,nll))){ + for(int i = 0; i <= position; i++){ + z3pf p = prem(proof,i); + add_antes(p); + } + res = fix_lemma(lits,get_hyps(proof),nll); + } + return res; + } } - try { - return translate_ur(proof,position-1,nll); - } - catch (const invalid_lemma &) { - if(old_nll != nll){ - std::cout << "\n\nadded_nll: \n"; - std::cout << "nproof node: \n"; - show_step(proof); - std::cout << "\n\new non-local step: \n"; - show_step(nll->proofs.back()->proof); - } - throw invalid_lemma(); - } - - } - else { - // just make a lemma - std::vector lits; - do_unit_resolution(proof,position,lits); - int res; - if(!(res = extract_th_lemma_ur(proof,position,lits,nll))){ - for(int i = 0; i <= position; i++){ - z3pf p = prem(proof,i); - add_antes(p); - } - res = fix_lemma(lits,get_hyps(proof),nll); - } - return res; - } - } - } - - non_local_lits *update_nll(ast proof, bool expect_clause, non_local_lits *nll){ - std::vector lits; - collect_proof_clause(proof,expect_clause,lits); - AstSet litset; - litset.insert(lits.begin(),lits.end()); - ResolventAppSet to_keep; - for(int i = nll->proofs.size()-1; i >= 0; --i){ - ast traced_lit = (nll->proofs[i])->pivot; - ast traced_lit_neg = mk_not(traced_lit); - if(litset.find(traced_lit) != litset.end() || litset.find(traced_lit_neg) != litset.end()){ - to_keep.push_back(nll->proofs[i]); - std::vector reslits; - AstSet dummy; - collect_resolvent_lits(nll->proofs[i],dummy,reslits); - litset.insert(reslits.begin(),reslits.end()); - } - } - if(to_keep.size() == nll->proofs.size()) return nll; - ResolventAppSet new_proofs; - for(int i = to_keep.size() - 1; i >= 0; --i) - new_proofs.push_back(to_keep[i]); - return find_nll(new_proofs); - } - - // translate a Z3 proof term into a foci proof term - - Iproof::node translate_main(ast proof, non_local_lits *nll, bool expect_clause = true){ - non_local_lits *old_nll = nll; - if(nll) nll = update_nll(proof,expect_clause,nll); - AstToIpf &tr = nll ? non_local_translation[nll] : translation; - hash_map &trc = expect_clause ? tr.first : tr.second; - std::pair foo(proof,INT_MAX); - std::pair bar = trc.insert(foo); - int &res = bar.first->second; - if(!bar.second) return res; - - - try { - int frame = get_locality(proof); - if(frame != -1){ - ast e = from_ast(conc(proof)); - if(frame >= frames) frame = frames - 1; - std::vector foo; - if(expect_clause) - get_Z3_lits(conc(proof),foo); - else - foo.push_back(e); - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - foo.push_back(mk_not(*it)); - res = iproof->make_assumption(frame,foo); - return res; } - pfrule dk = pr(proof); - unsigned nprems = num_prems(proof); - if(dk == PR_UNIT_RESOLUTION){ - res = translate_ur(proof, nprems - 1, nll); + non_local_lits *update_nll(ast proof, bool expect_clause, non_local_lits *nll){ + std::vector lits; + collect_proof_clause(proof,expect_clause,lits); + AstSet litset; + litset.insert(lits.begin(),lits.end()); + ResolventAppSet to_keep; + for(int i = nll->proofs.size()-1; i >= 0; --i){ + ast traced_lit = (nll->proofs[i])->pivot; + ast traced_lit_neg = mk_not(traced_lit); + if(litset.find(traced_lit) != litset.end() || litset.find(traced_lit_neg) != litset.end()){ + to_keep.push_back(nll->proofs[i]); + std::vector reslits; + AstSet dummy; + collect_resolvent_lits(nll->proofs[i],dummy,reslits); + litset.insert(reslits.begin(),reslits.end()); + } + } + if(to_keep.size() == nll->proofs.size()) return nll; + ResolventAppSet new_proofs; + for(int i = to_keep.size() - 1; i >= 0; --i) + new_proofs.push_back(to_keep[i]); + return find_nll(new_proofs); } - else if(dk == PR_LEMMA){ - ast contra = prem(proof,0); // this is a proof of false from some hyps - res = translate_main(contra, nll); - if(!expect_clause){ - std::vector foo; // the negations of the hyps form a clause - foo.push_back(from_ast(conc(proof))); - AstSet &hyps = get_hyps(proof); - for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) - foo.push_back(mk_not(*it)); - res = iproof->make_contra(res,foo); - } - } - else { - std::vector lits; - ast con = conc(proof); - if(expect_clause) - get_Z3_lits(con, lits); - else - lits.push_back(from_ast(con)); + + // translate a Z3 proof term into a foci proof term + + Iproof::node translate_main(ast proof, non_local_lits *nll, bool expect_clause = true){ + non_local_lits *old_nll = nll; + if(nll) nll = update_nll(proof,expect_clause,nll); + AstToIpf &tr = nll ? non_local_translation[nll] : translation; + hash_map &trc = expect_clause ? tr.first : tr.second; + std::pair foo(proof,INT_MAX); + std::pair bar = trc.insert(foo); + int &res = bar.first->second; + if(!bar.second) return res; + + + try { + int frame = get_locality(proof); + if(frame != -1){ + ast e = from_ast(conc(proof)); + if(frame >= frames) frame = frames - 1; + std::vector foo; + if(expect_clause) + get_Z3_lits(conc(proof),foo); + else + foo.push_back(e); + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + foo.push_back(mk_not(*it)); + res = iproof->make_assumption(frame,foo); + return res; + } + + pfrule dk = pr(proof); + unsigned nprems = num_prems(proof); + if(dk == PR_UNIT_RESOLUTION){ + res = translate_ur(proof, nprems - 1, nll); + } + else if(dk == PR_LEMMA){ + ast contra = prem(proof,0); // this is a proof of false from some hyps + res = translate_main(contra, nll); + if(!expect_clause){ + std::vector foo; // the negations of the hyps form a clause + foo.push_back(from_ast(conc(proof))); + AstSet &hyps = get_hyps(proof); + for(AstSet::iterator it = hyps.begin(), en = hyps.end(); it != en; ++it) + foo.push_back(mk_not(*it)); + res = iproof->make_contra(res,foo); + } + } + else { + std::vector lits; + ast con = conc(proof); + if(expect_clause) + get_Z3_lits(con, lits); + else + lits.push_back(from_ast(con)); #ifdef NEW_EXTRACT_TH_LEMMA - if(!(res = push_into_resolvent(proof,lits,nll,expect_clause))){ - if(!(res = extract_th_lemma(proof,lits,nll))){ + if(!(res = push_into_resolvent(proof,lits,nll,expect_clause))){ + if(!(res = extract_th_lemma(proof,lits,nll))){ #else - if(!(res = extract_th_lemma(proof,lits,nll))){ - if(!(res = push_into_resolvent(proof,lits,nll,expect_clause))){ + if(!(res = extract_th_lemma(proof,lits,nll))){ + if(!(res = push_into_resolvent(proof,lits,nll,expect_clause))){ #endif - // std::cout << "extract theory lemma failed\n"; - add_antes(proof); - res = fix_lemma(lits,get_hyps(proof),nll); - } - } - } + // std::cout << "extract theory lemma failed\n"; + add_antes(proof); + res = fix_lemma(lits,get_hyps(proof),nll); + } + } + } #ifdef CHECK_PROOFS - if(0){ - AstSet zpf_con_lits, ipf_con_lits; - get_local_conclusion_lits(proof, expect_clause, zpf_con_lits); - if(nll){ - for(unsigned i = 0; i < nll->proofs.size(); i++) - get_local_conclusion_lits(nll->proofs[i]->proof,!nll->proofs[i]->is_unit,zpf_con_lits); - } - std::vector ipf_con; - iproof->get_conclusion(res,ipf_con); - for(unsigned i = 0; i < ipf_con.size(); i++) - ipf_con_lits.insert(ipf_con[i]); - if(!(ipf_con_lits == zpf_con_lits)){ - std::cout << "proof error:\n"; - std::cout << "expected lits:\n"; - for(AstSet::iterator hit = zpf_con_lits.begin(), hen = zpf_con_lits.end(); hit != hen; ++hit) - show_lit(*hit); - std::cout << "got lits:\n"; - for(AstSet::iterator hit = ipf_con_lits.begin(), hen = ipf_con_lits.end(); hit != hen; ++hit) - show_lit(*hit); - std::cout << "\nproof step:"; - show_step(proof); - std::cout << "\n"; - throw invalid_lemma(); - } - } + if(0){ + AstSet zpf_con_lits, ipf_con_lits; + get_local_conclusion_lits(proof, expect_clause, zpf_con_lits); + if(nll){ + for(unsigned i = 0; i < nll->proofs.size(); i++) + get_local_conclusion_lits(nll->proofs[i]->proof,!nll->proofs[i]->is_unit,zpf_con_lits); + } + std::vector ipf_con; + iproof->get_conclusion(res,ipf_con); + for(unsigned i = 0; i < ipf_con.size(); i++) + ipf_con_lits.insert(ipf_con[i]); + if(!(ipf_con_lits == zpf_con_lits)){ + std::cout << "proof error:\n"; + std::cout << "expected lits:\n"; + for(AstSet::iterator hit = zpf_con_lits.begin(), hen = zpf_con_lits.end(); hit != hen; ++hit) + show_lit(*hit); + std::cout << "got lits:\n"; + for(AstSet::iterator hit = ipf_con_lits.begin(), hen = ipf_con_lits.end(); hit != hen; ++hit) + show_lit(*hit); + std::cout << "\nproof step:"; + show_step(proof); + std::cout << "\n"; + throw invalid_lemma(); + } + } #endif - return res; - } + return res; + } - catch (const invalid_lemma &) { - if(old_nll != nll){ - std::cout << "\n\nupdated nll: \n"; - std::cout << "nproof node: \n"; - show_step(proof); - std::cout << "\n\new non-local: \n"; - show_nll(nll); - } - throw invalid_lemma(); - } + catch (const invalid_lemma &) { + if(old_nll != nll){ + std::cout << "\n\nupdated nll: \n"; + std::cout << "nproof node: \n"; + show_step(proof); + std::cout << "\n\new non-local: \n"; + show_nll(nll); + } + throw invalid_lemma(); + } - } + } - // Proof translation is in two stages: - // 1) Translate ast proof term to Zproof - // 2) Translate Zproof to Iproof + // Proof translation is in two stages: + // 1) Translate ast proof term to Zproof + // 2) Translate Zproof to Iproof - Iproof::node translate(ast proof, Iproof &dst){ - iproof = &dst; - Iproof::node Ipf = translate_main(proof,0); // builds result in dst - return Ipf; - } + Iproof::node translate(ast proof, Iproof &dst){ + iproof = &dst; + Iproof::node Ipf = translate_main(proof,0); // builds result in dst + return Ipf; + } - iz3translation_direct(iz3mgr &mgr, - iz3secondary *_secondary, - const std::vector > &cnsts, - const std::vector &parents, - const std::vector &theory) - : iz3translation(mgr, cnsts, parents, theory) - { - secondary = _secondary; - frames = cnsts.size(); - traced_lit = ast(); - } + iz3translation_direct(iz3mgr &mgr, + iz3secondary *_secondary, + const std::vector > &cnsts, + const std::vector &parents, + const std::vector &theory) + : iz3translation(mgr, cnsts, parents, theory) + { + secondary = _secondary; + frames = cnsts.size(); + traced_lit = ast(); + } - ~iz3translation_direct(){ - for(hash_map::iterator - it = non_local_lits_unique.begin(), - en = non_local_lits_unique.end(); - it != en; - ++it) - delete it->second; + ~iz3translation_direct(){ + for(hash_map::iterator + it = non_local_lits_unique.begin(), + en = non_local_lits_unique.end(); + it != en; + ++it) + delete it->second; - for(hash_map::iterator - it = Z3_resolvent_unique.begin(), - en = Z3_resolvent_unique.end(); - it != en; - ++it) - delete it->second; - } -}; + for(hash_map::iterator + it = Z3_resolvent_unique.begin(), + en = Z3_resolvent_unique.end(); + it != en; + ++it) + delete it->second; + } + }; #ifdef IZ3_TRANSLATE_DIRECT -iz3translation *iz3translation::create(iz3mgr &mgr, - iz3secondary *secondary, - const std::vector > &cnsts, - const std::vector &parents, - const std::vector &theory){ - return new iz3translation_direct(mgr,secondary,cnsts,parents,theory); -} + iz3translation *iz3translation::create(iz3mgr &mgr, + iz3secondary *secondary, + const std::vector > &cnsts, + const std::vector &parents, + const std::vector &theory){ + return new iz3translation_direct(mgr,secondary,cnsts,parents,theory); + } #if 1 -void iz3translation_direct_trace_lit(iz3translation_direct *p, iz3mgr::ast lit, iz3mgr::ast proof){ - p->trace_lit(lit, proof); -} + void iz3translation_direct_trace_lit(iz3translation_direct *p, iz3mgr::ast lit, iz3mgr::ast proof){ + p->trace_lit(lit, proof); + } -void iz3translation_direct_show_step(iz3translation_direct *p, iz3mgr::ast proof){ - p->show_step(proof); -} + void iz3translation_direct_show_step(iz3translation_direct *p, iz3mgr::ast proof){ + p->show_step(proof); + } -void iz3translation_direct_show_marked(iz3translation_direct *p, iz3mgr::ast proof){ - p->show_marked(proof); -} + void iz3translation_direct_show_marked(iz3translation_direct *p, iz3mgr::ast proof){ + p->show_marked(proof); + } -void iz3translation_direct_show_lit(iz3translation_direct *p, iz3mgr::ast lit){ - p->show_lit(lit); -} + void iz3translation_direct_show_lit(iz3translation_direct *p, iz3mgr::ast lit){ + p->show_lit(lit); + } -void iz3translation_direct_show_z3_lit(iz3translation_direct *p, iz3mgr::ast a){ - p->show_z3_lit(a); -} + void iz3translation_direct_show_z3_lit(iz3translation_direct *p, iz3mgr::ast a){ + p->show_z3_lit(a); + } -void iz3translation_direct_pfgoto(iz3translation_direct *p, iz3mgr::ast proof){ - p->pfgoto(proof); -} + void iz3translation_direct_pfgoto(iz3translation_direct *p, iz3mgr::ast proof){ + p->pfgoto(proof); + } -void iz3translation_direct_show_nll(iz3translation_direct *p, non_local_lits *nll){ - p->show_nll(nll); -} + void iz3translation_direct_show_nll(iz3translation_direct *p, non_local_lits *nll){ + p->show_nll(nll); + } -void iz3translation_direct_pfback(iz3translation_direct *p ){ - p->pfback(); -} + void iz3translation_direct_pfback(iz3translation_direct *p ){ + p->pfback(); + } -void iz3translation_direct_pffwd(iz3translation_direct *p ){ - p->pffwd(); -} + void iz3translation_direct_pffwd(iz3translation_direct *p ){ + p->pffwd(); + } -void iz3translation_direct_pfprem(iz3translation_direct *p, int i){ - p->pfprem(i); -} + void iz3translation_direct_pfprem(iz3translation_direct *p, int i){ + p->pfprem(i); + } -struct stdio_fixer { - stdio_fixer(){ - std::cout.rdbuf()->pubsetbuf(0,0); - } + struct stdio_fixer { + stdio_fixer(){ + std::cout.rdbuf()->pubsetbuf(0,0); + } -} my_stdio_fixer; + } my_stdio_fixer; #endif diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index aa186bd0a..e49ddee81 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2013 Microsoft Corporation + Copyright (c) 2013 Microsoft Corporation -Module Name: + Module Name: - duality_dl_interface.cpp + duality_dl_interface.cpp -Abstract: + Abstract: - SMT2 interface for Duality + SMT2 interface for Duality -Author: + Author: - Krystof Hoder (t-khoder) 2011-9-22. - Modified by Ken McMIllan (kenmcmil) 2013-4-18. + Krystof Hoder (t-khoder) 2011-9-22. + Modified by Ken McMIllan (kenmcmil) 2013-4-18. -Revision History: + Revision History: ---*/ + --*/ #include "dl_context.h" #include "dl_mk_coi_filter.h" @@ -55,568 +55,568 @@ Revision History: namespace Duality { - enum DualityStatus {StatusModel, StatusRefutation, StatusUnknown, StatusNull}; + enum DualityStatus {StatusModel, StatusRefutation, StatusUnknown, StatusNull}; - class duality_data { - public: - context ctx; - RPFP::LogicSolver *ls; - RPFP *rpfp; + class duality_data { + public: + context ctx; + RPFP::LogicSolver *ls; + RPFP *rpfp; - DualityStatus status; - std::vector clauses; - std::vector > clause_labels; - hash_map map; // edges to clauses - Solver *old_rs; - Solver::Counterexample cex; + DualityStatus status; + std::vector clauses; + std::vector > clause_labels; + hash_map map; // edges to clauses + Solver *old_rs; + Solver::Counterexample cex; - duality_data(ast_manager &_m) : ctx(_m,config(params_ref())) { - ls = 0; - rpfp = 0; - status = StatusNull; - old_rs = 0; + duality_data(ast_manager &_m) : ctx(_m,config(params_ref())) { + ls = 0; + rpfp = 0; + status = StatusNull; + old_rs = 0; + } + ~duality_data(){ + if(old_rs) + dealloc(old_rs); + if(rpfp) + dealloc(rpfp); + if(ls) + dealloc(ls); + } + }; + + + dl_interface::dl_interface(datalog::context& dl_ctx) : + engine_base(dl_ctx.get_manager(), "duality"), + m_ctx(dl_ctx) + + { + _d = 0; + // dl_ctx.get_manager().toggle_proof_mode(PGM_FINE); } - ~duality_data(){ - if(old_rs) - dealloc(old_rs); - if(rpfp) - dealloc(rpfp); - if(ls) - dealloc(ls); + + + dl_interface::~dl_interface() { + if(_d) + dealloc(_d); } - }; -dl_interface::dl_interface(datalog::context& dl_ctx) : - engine_base(dl_ctx.get_manager(), "duality"), - m_ctx(dl_ctx) - -{ - _d = 0; - // dl_ctx.get_manager().toggle_proof_mode(PGM_FINE); -} - - -dl_interface::~dl_interface() { - if(_d) - dealloc(_d); -} - - -// -// Check if the new rules are weaker so that we can -// re-use existing context. -// + // + // Check if the new rules are weaker so that we can + // re-use existing context. + // #if 0 -void dl_interface::check_reset() { - // TODO - datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules(); - datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules(); - bool is_subsumed = !old_rules.empty(); - for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) { - is_subsumed = false; - for (unsigned j = 0; !is_subsumed && j < old_rules.size(); ++j) { - if (m_ctx.check_subsumes(*old_rules[j], *new_rules[i])) { - is_subsumed = true; + void dl_interface::check_reset() { + // TODO + datalog::rule_ref_vector const& new_rules = m_ctx.get_rules().get_rules(); + datalog::rule_ref_vector const& old_rules = m_old_rules.get_rules(); + bool is_subsumed = !old_rules.empty(); + for (unsigned i = 0; is_subsumed && i < new_rules.size(); ++i) { + is_subsumed = false; + for (unsigned j = 0; !is_subsumed && j < old_rules.size(); ++j) { + if (m_ctx.check_subsumes(*old_rules[j], *new_rules[i])) { + is_subsumed = true; + } + } + if (!is_subsumed) { + TRACE("pdr", new_rules[i]->display(m_ctx, tout << "Fresh rule ");); + m_context->reset(); } } - if (!is_subsumed) { - TRACE("pdr", new_rules[i]->display(m_ctx, tout << "Fresh rule ");); - m_context->reset(); - } + m_old_rules.reset(); + m_old_rules.add_rules(new_rules.size(), new_rules.c_ptr()); } - m_old_rules.reset(); - m_old_rules.add_rules(new_rules.size(), new_rules.c_ptr()); -} #endif -lbool dl_interface::query(::expr * query) { + lbool dl_interface::query(::expr * query) { - // we restore the initial state in the datalog context - m_ctx.ensure_opened(); + // we restore the initial state in the datalog context + m_ctx.ensure_opened(); - // if there is old data, get the cex and dispose (later) - duality_data *old_data = _d; - Solver *old_rs = 0; - if(old_data){ - old_rs = old_data->old_rs; - old_rs->GetCounterexample().swap(old_data->cex); - } - - scoped_proof generate_proofs_please(m_ctx.get_manager()); - - // make a new problem and solver - _d = alloc(duality_data,m_ctx.get_manager()); - _d->ctx.set("mbqi",m_ctx.get_params().mbqi()); - _d->ls = alloc(RPFP::iZ3LogicSolver,_d->ctx); - _d->rpfp = alloc(RPFP,_d->ls); - - - - expr_ref_vector rules(m_ctx.get_manager()); - svector< ::symbol> names; - vector bounds; - // m_ctx.get_rules_as_formulas(rules, names); - - - // If using SAS 2013 abstractiion, we need to perform some transforms - expr_ref query_ref(m_ctx.get_manager()); - if(m_ctx.quantify_arrays()){ - datalog::rule_manager& rm = m_ctx.get_rule_manager(); - rm.mk_query(query, m_ctx.get_rules()); - apply_default_transformation(m_ctx); - datalog::rule_set &rs = m_ctx.get_rules(); - if(m_ctx.get_rules().get_output_predicates().empty()) - query_ref = m_ctx.get_manager().mk_false(); - else { - func_decl_ref query_pred(m_ctx.get_manager()); - query_pred = m_ctx.get_rules().get_output_predicate(); - ptr_vector sorts; - unsigned nargs = query_pred.get()->get_arity(); - expr_ref_vector vars(m_ctx.get_manager()); - for(unsigned i = 0; i < nargs; i++){ - ::sort *s = query_pred.get()->get_domain(i); - vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s)); + // if there is old data, get the cex and dispose (later) + duality_data *old_data = _d; + Solver *old_rs = 0; + if(old_data){ + old_rs = old_data->old_rs; + old_rs->GetCounterexample().swap(old_data->cex); } - query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr()); - query = query_ref.get(); - } - unsigned nrules = rs.get_num_rules(); - for(unsigned i = 0; i < nrules; i++){ - expr_ref f(m_ctx.get_manager()); - rs.get_rule(i)->to_formula(f); - rules.push_back(f); - } - } - else - m_ctx.get_raw_rule_formulas(rules, names, bounds); - // get all the rules as clauses - std::vector &clauses = _d->clauses; - clauses.clear(); - for (unsigned i = 0; i < rules.size(); ++i) { - expr e(_d->ctx,rules[i].get()); - clauses.push_back(e); - } - - std::vector b_sorts; - std::vector b_names; - used_vars uv; - uv.process(query); - unsigned nuv = uv.get_max_found_var_idx_plus_1(); - for(int i = nuv-1; i >= 0; i--){ // var indices are backward - ::sort * s = uv.get(i); - if(!s) - s = _d->ctx.m().mk_bool_sort(); // missing var, whatever - b_sorts.push_back(sort(_d->ctx,s)); - b_names.push_back(symbol(_d->ctx,::symbol(i))); // names? - } + scoped_proof generate_proofs_please(m_ctx.get_manager()); -#if 0 - // turn the query into a clause - expr q(_d->ctx,m_ctx.bind_variables(query,false)); - - std::vector b_sorts; - std::vector b_names; - if (q.is_quantifier() && !q.is_quantifier_forall()) { - int bound = q.get_quantifier_num_bound(); - for(int j = 0; j < bound; j++){ - b_sorts.push_back(q.get_quantifier_bound_sort(j)); - b_names.push_back(q.get_quantifier_bound_name(j)); - } - q = q.arg(0); - } -#else - expr q(_d->ctx,query); -#endif + // make a new problem and solver + _d = alloc(duality_data,m_ctx.get_manager()); + _d->ctx.set("mbqi",m_ctx.get_params().mbqi()); + _d->ls = alloc(RPFP::iZ3LogicSolver,_d->ctx); + _d->rpfp = alloc(RPFP,_d->ls); - expr qc = implies(q,_d->ctx.bool_val(false)); - qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc); - clauses.push_back(qc); - bounds.push_back(UINT_MAX); - - // get the background axioms - unsigned num_asserts = m_ctx.get_num_assertions(); - for (unsigned i = 0; i < num_asserts; ++i) { - expr e(_d->ctx,m_ctx.get_assertion(i)); - _d->rpfp->AssertAxiom(e); - } - - // make sure each predicate is the head of at least one clause - func_decl_set heads; - for(unsigned i = 0; i < clauses.size(); i++){ - expr cl = clauses[i]; - while(true){ - if(cl.is_app()){ - decl_kind k = cl.decl().get_decl_kind(); - if(k == Implies) - cl = cl.arg(1); + + expr_ref_vector rules(m_ctx.get_manager()); + svector< ::symbol> names; + vector bounds; + // m_ctx.get_rules_as_formulas(rules, names); + + + // If using SAS 2013 abstractiion, we need to perform some transforms + expr_ref query_ref(m_ctx.get_manager()); + if(m_ctx.quantify_arrays()){ + datalog::rule_manager& rm = m_ctx.get_rule_manager(); + rm.mk_query(query, m_ctx.get_rules()); + apply_default_transformation(m_ctx); + datalog::rule_set &rs = m_ctx.get_rules(); + if(m_ctx.get_rules().get_output_predicates().empty()) + query_ref = m_ctx.get_manager().mk_false(); else { - heads.insert(cl.decl()); - break; + func_decl_ref query_pred(m_ctx.get_manager()); + query_pred = m_ctx.get_rules().get_output_predicate(); + ptr_vector sorts; + unsigned nargs = query_pred.get()->get_arity(); + expr_ref_vector vars(m_ctx.get_manager()); + for(unsigned i = 0; i < nargs; i++){ + ::sort *s = query_pred.get()->get_domain(i); + vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s)); + } + query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr()); + query = query_ref.get(); } - } - else if(cl.is_quantifier()) - cl = cl.body(); - else break; - } - } - ast_ref_vector const &pinned = m_ctx.get_pinned(); - for(unsigned i = 0; i < pinned.size(); i++){ - ::ast *fa = pinned[i]; - if(is_func_decl(fa)){ - ::func_decl *fd = to_func_decl(fa); - if (m_ctx.is_predicate(fd)) { - func_decl f(_d->ctx, fd); - if (!heads.contains(fd)) { - int arity = f.arity(); - std::vector args; - for (int j = 0; j < arity; j++) - args.push_back(_d->ctx.fresh_func_decl("X", f.domain(j))()); - expr c = implies(_d->ctx.bool_val(false), f(args)); - c = _d->ctx.make_quant(Forall, args, c); - clauses.push_back(c); - bounds.push_back(UINT_MAX); - } - } - } - } - unsigned rb = m_ctx.get_params().recursion_bound(); - std::vector std_bounds; - for(unsigned i = 0; i < bounds.size(); i++){ - unsigned b = bounds[i]; - if (b == UINT_MAX) b = rb; - std_bounds.push_back(b); - } + unsigned nrules = rs.get_num_rules(); + for(unsigned i = 0; i < nrules; i++){ + expr_ref f(m_ctx.get_manager()); + rs.get_rule(i)->to_formula(f); + rules.push_back(f); + } + } + else + m_ctx.get_raw_rule_formulas(rules, names, bounds); - // creates 1-1 map between clauses and rpfp edges - _d->rpfp->FromClauses(clauses,&std_bounds); + // get all the rules as clauses + std::vector &clauses = _d->clauses; + clauses.clear(); + for (unsigned i = 0; i < rules.size(); ++i) { + expr e(_d->ctx,rules[i].get()); + clauses.push_back(e); + } + + std::vector b_sorts; + std::vector b_names; + used_vars uv; + uv.process(query); + unsigned nuv = uv.get_max_found_var_idx_plus_1(); + for(int i = nuv-1; i >= 0; i--){ // var indices are backward + ::sort * s = uv.get(i); + if(!s) + s = _d->ctx.m().mk_bool_sort(); // missing var, whatever + b_sorts.push_back(sort(_d->ctx,s)); + b_names.push_back(symbol(_d->ctx,::symbol(i))); // names? + } - // populate the edge-to-clause map - for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i) - _d->map[_d->rpfp->edges[i]] = i; +#if 0 + // turn the query into a clause + expr q(_d->ctx,m_ctx.bind_variables(query,false)); + + std::vector b_sorts; + std::vector b_names; + if (q.is_quantifier() && !q.is_quantifier_forall()) { + int bound = q.get_quantifier_num_bound(); + for(int j = 0; j < bound; j++){ + b_sorts.push_back(q.get_quantifier_bound_sort(j)); + b_names.push_back(q.get_quantifier_bound_name(j)); + } + q = q.arg(0); + } +#else + expr q(_d->ctx,query); +#endif + + expr qc = implies(q,_d->ctx.bool_val(false)); + qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc); + clauses.push_back(qc); + bounds.push_back(UINT_MAX); + + // get the background axioms + unsigned num_asserts = m_ctx.get_num_assertions(); + for (unsigned i = 0; i < num_asserts; ++i) { + expr e(_d->ctx,m_ctx.get_assertion(i)); + _d->rpfp->AssertAxiom(e); + } + + // make sure each predicate is the head of at least one clause + func_decl_set heads; + for(unsigned i = 0; i < clauses.size(); i++){ + expr cl = clauses[i]; + + while(true){ + if(cl.is_app()){ + decl_kind k = cl.decl().get_decl_kind(); + if(k == Implies) + cl = cl.arg(1); + else { + heads.insert(cl.decl()); + break; + } + } + else if(cl.is_quantifier()) + cl = cl.body(); + else break; + } + } + ast_ref_vector const &pinned = m_ctx.get_pinned(); + for(unsigned i = 0; i < pinned.size(); i++){ + ::ast *fa = pinned[i]; + if(is_func_decl(fa)){ + ::func_decl *fd = to_func_decl(fa); + if (m_ctx.is_predicate(fd)) { + func_decl f(_d->ctx, fd); + if (!heads.contains(fd)) { + int arity = f.arity(); + std::vector args; + for (int j = 0; j < arity; j++) + args.push_back(_d->ctx.fresh_func_decl("X", f.domain(j))()); + expr c = implies(_d->ctx.bool_val(false), f(args)); + c = _d->ctx.make_quant(Forall, args, c); + clauses.push_back(c); + bounds.push_back(UINT_MAX); + } + } + } + } + unsigned rb = m_ctx.get_params().recursion_bound(); + std::vector std_bounds; + for(unsigned i = 0; i < bounds.size(); i++){ + unsigned b = bounds[i]; + if (b == UINT_MAX) b = rb; + std_bounds.push_back(b); + } + + // creates 1-1 map between clauses and rpfp edges + _d->rpfp->FromClauses(clauses,&std_bounds); + + // populate the edge-to-clause map + for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i) + _d->map[_d->rpfp->edges[i]] = i; - // create a solver object + // create a solver object - Solver *rs = Solver::Create("duality", _d->rpfp); + Solver *rs = Solver::Create("duality", _d->rpfp); - if(old_rs) - rs->LearnFrom(old_rs); // new solver gets hints from old solver + if(old_rs) + rs->LearnFrom(old_rs); // new solver gets hints from old solver - // set its options - IF_VERBOSE(1, rs->SetOption("report","1");); - rs->SetOption("full_expand",m_ctx.get_params().full_expand() ? "1" : "0"); - rs->SetOption("no_conj",m_ctx.get_params().no_conj() ? "1" : "0"); - rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0"); - rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0"); - rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0"); - rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0"); - rs->SetOption("conjecture_file",m_ctx.get_params().conjecture_file()); - rs->SetOption("enable_restarts",m_ctx.get_params().enable_restarts() ? "1" : "0"); + // set its options + IF_VERBOSE(1, rs->SetOption("report","1");); + rs->SetOption("full_expand",m_ctx.get_params().full_expand() ? "1" : "0"); + rs->SetOption("no_conj",m_ctx.get_params().no_conj() ? "1" : "0"); + rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0"); + rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0"); + rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0"); + rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0"); + rs->SetOption("conjecture_file",m_ctx.get_params().conjecture_file()); + rs->SetOption("enable_restarts",m_ctx.get_params().enable_restarts() ? "1" : "0"); #if 0 - if(rb != UINT_MAX){ - std::ostringstream os; os << rb; - rs->SetOption("recursion_bound", os.str()); - } + if(rb != UINT_MAX){ + std::ostringstream os; os << rb; + rs->SetOption("recursion_bound", os.str()); + } #endif - // Solve! - bool ans; - try { - ans = rs->Solve(); - } - catch (Duality::solver::cancel_exception &exn){ - throw default_exception("duality canceled"); - } - catch (Duality::Solver::Incompleteness &exn){ - throw default_exception("incompleteness"); - } + // Solve! + bool ans; + try { + ans = rs->Solve(); + } + catch (Duality::solver::cancel_exception &exn){ + throw default_exception("duality canceled"); + } + catch (Duality::Solver::Incompleteness &exn){ + throw default_exception("incompleteness"); + } - // profile! + // profile! - if(m_ctx.get_params().profile()) - print_profile(std::cout); + if(m_ctx.get_params().profile()) + print_profile(std::cout); - // save the result and counterexample if there is one - _d->status = ans ? StatusModel : StatusRefutation; - _d->cex.swap(rs->GetCounterexample()); // take ownership of cex - _d->old_rs = rs; // save this for later hints + // save the result and counterexample if there is one + _d->status = ans ? StatusModel : StatusRefutation; + _d->cex.swap(rs->GetCounterexample()); // take ownership of cex + _d->old_rs = rs; // save this for later hints - if(old_data){ - dealloc(old_data); // this deallocates the old solver if there is one - } + if(old_data){ + dealloc(old_data); // this deallocates the old solver if there is one + } - // dealloc(rs); this is now owned by data + // dealloc(rs); this is now owned by data - // true means the RPFP problem is SAT, so the query is UNSAT - // but we return undef if the UNSAT result is bounded - if(ans){ - if(rs->IsResultRecursionBounded()){ + // true means the RPFP problem is SAT, so the query is UNSAT + // but we return undef if the UNSAT result is bounded + if(ans){ + if(rs->IsResultRecursionBounded()){ #if 0 - m_ctx.set_status(datalog::BOUNDED); - return l_undef; + m_ctx.set_status(datalog::BOUNDED); + return l_undef; #else - return l_false; + return l_false; #endif + } + return l_false; + } + return l_true; } - return l_false; - } - return l_true; -} -expr_ref dl_interface::get_cover_delta(int level, ::func_decl* pred_orig) { - SASSERT(false); - return expr_ref(m_ctx.get_manager()); -} + expr_ref dl_interface::get_cover_delta(int level, ::func_decl* pred_orig) { + SASSERT(false); + return expr_ref(m_ctx.get_manager()); + } - void dl_interface::add_cover(int level, ::func_decl* pred, ::expr* property) { - SASSERT(false); -} + void dl_interface::add_cover(int level, ::func_decl* pred, ::expr* property) { + SASSERT(false); + } - unsigned dl_interface::get_num_levels(::func_decl* pred) { - SASSERT(false); - return 0; -} + unsigned dl_interface::get_num_levels(::func_decl* pred) { + SASSERT(false); + return 0; + } - void dl_interface::collect_statistics(::statistics& st) const { -} + void dl_interface::collect_statistics(::statistics& st) const { + } -void dl_interface::reset_statistics() { -} + void dl_interface::reset_statistics() { + } -static hash_set *local_func_decls; + static hash_set *local_func_decls; - static void print_proof(dl_interface *d, std::ostream& out, RPFP *tree, RPFP::Node *root) { - context &ctx = d->dd()->ctx; - RPFP::Node &node = *root; - RPFP::Edge &edge = *node.Outgoing; + static void print_proof(dl_interface *d, std::ostream& out, RPFP *tree, RPFP::Node *root) { + context &ctx = d->dd()->ctx; + RPFP::Node &node = *root; + RPFP::Edge &edge = *node.Outgoing; - // first, prove the children (that are actually used) + // first, prove the children (that are actually used) - for(unsigned i = 0; i < edge.Children.size(); i++){ - if(!tree->Empty(edge.Children[i])){ - print_proof(d,out,tree,edge.Children[i]); - } - } + for(unsigned i = 0; i < edge.Children.size(); i++){ + if(!tree->Empty(edge.Children[i])){ + print_proof(d,out,tree,edge.Children[i]); + } + } - // print the label and the proved fact + // print the label and the proved fact - out << "(step s!" << node.number; - out << " (" << node.Name.name(); - for(unsigned i = 0; i < edge.F.IndParams.size(); i++) - out << " " << tree->Eval(&edge,edge.F.IndParams[i]); - out << ")\n"; + out << "(step s!" << node.number; + out << " (" << node.Name.name(); + for(unsigned i = 0; i < edge.F.IndParams.size(); i++) + out << " " << tree->Eval(&edge,edge.F.IndParams[i]); + out << ")\n"; - // print the rule number + // print the rule number - out << " rule!" << node.Outgoing->map->number; + out << " rule!" << node.Outgoing->map->number; - // print the substitution + // print the substitution - out << " (subst\n"; - RPFP::Edge *orig_edge = edge.map; - int orig_clause = d->dd()->map[orig_edge]; - expr &t = d->dd()->clauses[orig_clause]; - if (t.is_quantifier() && t.is_quantifier_forall()) { - int bound = t.get_quantifier_num_bound(); - std::vector sorts; - std::vector names; - hash_map subst; - for(int j = 0; j < bound; j++){ - sort the_sort = t.get_quantifier_bound_sort(j); - symbol name = t.get_quantifier_bound_name(j); - expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); - out << " (= " << skolem << " " << tree->Eval(&edge,skolem) << ")\n"; - expr local_skolem = tree->Localize(&edge,skolem); - (*local_func_decls).insert(local_skolem.decl()); - } - } - out << " )\n"; + out << " (subst\n"; + RPFP::Edge *orig_edge = edge.map; + int orig_clause = d->dd()->map[orig_edge]; + expr &t = d->dd()->clauses[orig_clause]; + if (t.is_quantifier() && t.is_quantifier_forall()) { + int bound = t.get_quantifier_num_bound(); + std::vector sorts; + std::vector names; + hash_map subst; + for(int j = 0; j < bound; j++){ + sort the_sort = t.get_quantifier_bound_sort(j); + symbol name = t.get_quantifier_bound_name(j); + expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); + out << " (= " << skolem << " " << tree->Eval(&edge,skolem) << ")\n"; + expr local_skolem = tree->Localize(&edge,skolem); + (*local_func_decls).insert(local_skolem.decl()); + } + } + out << " )\n"; - out << " (labels"; - std::vector labels; - tree->GetLabels(&edge,labels); - for(unsigned j = 0; j < labels.size(); j++){ - out << " " << labels[j]; - } + out << " (labels"; + std::vector labels; + tree->GetLabels(&edge,labels); + for(unsigned j = 0; j < labels.size(); j++){ + out << " " << labels[j]; + } - out << " )\n"; + out << " )\n"; - // reference the proofs of all the children, in syntactic order - // "true" means the child is not needed + // reference the proofs of all the children, in syntactic order + // "true" means the child is not needed - out << " (ref "; - for(unsigned i = 0; i < edge.Children.size(); i++){ - if(!tree->Empty(edge.Children[i])) - out << " s!" << edge.Children[i]->number; - else - out << " true"; - } - out << " )"; - out << ")\n"; -} - - - void dl_interface::display_certificate(std::ostream& out) const { - ((dl_interface *)this)->display_certificate_non_const(out); - } - -void dl_interface::display_certificate_non_const(std::ostream& out) { - if(_d->status == StatusModel){ - ast_manager &m = m_ctx.get_manager(); - model_ref md = get_model(); - out << "(fixedpoint \n"; - model_smt2_pp(out, m, *md.get(), 0); - out << ")\n"; - } - else if(_d->status == StatusRefutation){ - out << "(derivation\n"; - // negation of the query is the last clause -- prove it - hash_set locals; - local_func_decls = &locals; - print_proof(this,out,_d->cex.get_tree(),_d->cex.get_root()); - out << ")\n"; - out << "(model \n\""; - ::model mod(m_ctx.get_manager()); - model orig_model = _d->cex.get_tree()->dualModel; - for(unsigned i = 0; i < orig_model.num_consts(); i++){ - func_decl cnst = orig_model.get_const_decl(i); - if (locals.find(cnst) == locals.end()) { - expr thing = orig_model.get_const_interp(cnst); - mod.register_decl(to_func_decl(cnst.raw()), to_expr(thing.raw())); - } + out << " (ref "; + for(unsigned i = 0; i < edge.Children.size(); i++){ + if(!tree->Empty(edge.Children[i])) + out << " s!" << edge.Children[i]->number; + else + out << " true"; + } + out << " )"; + out << ")\n"; } - for(unsigned i = 0; i < orig_model.num_funcs(); i++){ - func_decl cnst = orig_model.get_func_decl(i); - if (locals.find(cnst) == locals.end()) { - func_interp thing = orig_model.get_func_interp(cnst); - ::func_interp *thing_raw = thing; - mod.register_decl(to_func_decl(cnst.raw()), thing_raw->copy()); - } + + + void dl_interface::display_certificate(std::ostream& out) const { + ((dl_interface *)this)->display_certificate_non_const(out); } - model_v2_pp(out,mod); - out << "\")\n"; - } -} -expr_ref dl_interface::get_answer() { - SASSERT(false); - return expr_ref(m_ctx.get_manager()); -} + void dl_interface::display_certificate_non_const(std::ostream& out) { + if(_d->status == StatusModel){ + ast_manager &m = m_ctx.get_manager(); + model_ref md = get_model(); + out << "(fixedpoint \n"; + model_smt2_pp(out, m, *md.get(), 0); + out << ")\n"; + } + else if(_d->status == StatusRefutation){ + out << "(derivation\n"; + // negation of the query is the last clause -- prove it + hash_set locals; + local_func_decls = &locals; + print_proof(this,out,_d->cex.get_tree(),_d->cex.get_root()); + out << ")\n"; + out << "(model \n\""; + ::model mod(m_ctx.get_manager()); + model orig_model = _d->cex.get_tree()->dualModel; + for(unsigned i = 0; i < orig_model.num_consts(); i++){ + func_decl cnst = orig_model.get_const_decl(i); + if (locals.find(cnst) == locals.end()) { + expr thing = orig_model.get_const_interp(cnst); + mod.register_decl(to_func_decl(cnst.raw()), to_expr(thing.raw())); + } + } + for(unsigned i = 0; i < orig_model.num_funcs(); i++){ + func_decl cnst = orig_model.get_func_decl(i); + if (locals.find(cnst) == locals.end()) { + func_interp thing = orig_model.get_func_interp(cnst); + ::func_interp *thing_raw = thing; + mod.register_decl(to_func_decl(cnst.raw()), thing_raw->copy()); + } + } + model_v2_pp(out,mod); + out << "\")\n"; + } + } -void dl_interface::cancel() { + expr_ref dl_interface::get_answer() { + SASSERT(false); + return expr_ref(m_ctx.get_manager()); + } + + void dl_interface::cancel() { #if 0 - if(_d && _d->ls) - _d->ls->cancel(); + if(_d && _d->ls) + _d->ls->cancel(); #else - // HACK: duality can't cancel at all times, we just exit here - std::cout << "(error \"duality canceled\")\nunknown\n"; - abort(); + // HACK: duality can't cancel at all times, we just exit here + std::cout << "(error \"duality canceled\")\nunknown\n"; + abort(); #endif -} - -void dl_interface::cleanup() { -} - -void dl_interface::updt_params() { -} - -model_ref dl_interface::get_model() { - ast_manager &m = m_ctx.get_manager(); - model_ref md(alloc(::model, m)); - std::vector &nodes = _d->rpfp->nodes; - expr_ref_vector conjs(m); - for (unsigned i = 0; i < nodes.size(); ++i) { - RPFP::Node *node = nodes[i]; - func_decl &pred = node->Name; - expr_ref prop(m); - prop = to_expr(node->Annotation.Formula); - std::vector ¶ms = node->Annotation.IndParams; - expr_ref q(m); - expr_ref_vector sig_vars(m); - for (unsigned j = 0; j < params.size(); ++j) - sig_vars.push_back(params[params.size()-j-1]); // TODO: why backwards? - expr_abstract(m, 0, sig_vars.size(), sig_vars.c_ptr(), prop, q); - if (params.empty()) { - md->register_decl(pred, q); } - else { - ::func_interp* fi = alloc(::func_interp, m, params.size()); - fi->set_else(q); - md->register_decl(pred, fi); + + void dl_interface::cleanup() { } - } - return md; -} - - static proof_ref extract_proof(dl_interface *d, RPFP *tree, RPFP::Node *root) { - context &ctx = d->dd()->ctx; - ast_manager &mgr = ctx.m(); - RPFP::Node &node = *root; - RPFP::Edge &edge = *node.Outgoing; - RPFP::Edge *orig_edge = edge.map; - - // first, prove the children (that are actually used) - - proof_ref_vector prems(mgr); - ::vector substs; - int orig_clause = d->dd()->map[orig_edge]; - expr &t = d->dd()->clauses[orig_clause]; - prems.push_back(mgr.mk_asserted(ctx.uncook(t))); - - substs.push_back(expr_ref_vector(mgr)); - if (t.is_quantifier() && t.is_quantifier_forall()) { - int bound = t.get_quantifier_num_bound(); - std::vector sorts; - std::vector names; - hash_map subst; - for(int j = 0; j < bound; j++){ - sort the_sort = t.get_quantifier_bound_sort(j); - symbol name = t.get_quantifier_bound_name(j); - expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); - expr val = tree->Eval(&edge,skolem); - expr_ref thing(ctx.uncook(val),mgr); - substs[0].push_back(thing); - expr local_skolem = tree->Localize(&edge,skolem); - (*local_func_decls).insert(local_skolem.decl()); + + void dl_interface::updt_params() { } - } - svector > pos; - for(unsigned i = 0; i < edge.Children.size(); i++){ - if(!tree->Empty(edge.Children[i])){ - pos.push_back(std::pair(i+1,0)); - proof_ref prem = extract_proof(d,tree,edge.Children[i]); - prems.push_back(prem); - substs.push_back(expr_ref_vector(mgr)); + model_ref dl_interface::get_model() { + ast_manager &m = m_ctx.get_manager(); + model_ref md(alloc(::model, m)); + std::vector &nodes = _d->rpfp->nodes; + expr_ref_vector conjs(m); + for (unsigned i = 0; i < nodes.size(); ++i) { + RPFP::Node *node = nodes[i]; + func_decl &pred = node->Name; + expr_ref prop(m); + prop = to_expr(node->Annotation.Formula); + std::vector ¶ms = node->Annotation.IndParams; + expr_ref q(m); + expr_ref_vector sig_vars(m); + for (unsigned j = 0; j < params.size(); ++j) + sig_vars.push_back(params[params.size()-j-1]); // TODO: why backwards? + expr_abstract(m, 0, sig_vars.size(), sig_vars.c_ptr(), prop, q); + if (params.empty()) { + md->register_decl(pred, q); + } + else { + ::func_interp* fi = alloc(::func_interp, m, params.size()); + fi->set_else(q); + md->register_decl(pred, fi); + } + } + return md; } - } + + static proof_ref extract_proof(dl_interface *d, RPFP *tree, RPFP::Node *root) { + context &ctx = d->dd()->ctx; + ast_manager &mgr = ctx.m(); + RPFP::Node &node = *root; + RPFP::Edge &edge = *node.Outgoing; + RPFP::Edge *orig_edge = edge.map; + + // first, prove the children (that are actually used) + + proof_ref_vector prems(mgr); + ::vector substs; + int orig_clause = d->dd()->map[orig_edge]; + expr &t = d->dd()->clauses[orig_clause]; + prems.push_back(mgr.mk_asserted(ctx.uncook(t))); + + substs.push_back(expr_ref_vector(mgr)); + if (t.is_quantifier() && t.is_quantifier_forall()) { + int bound = t.get_quantifier_num_bound(); + std::vector sorts; + std::vector names; + hash_map subst; + for(int j = 0; j < bound; j++){ + sort the_sort = t.get_quantifier_bound_sort(j); + symbol name = t.get_quantifier_bound_name(j); + expr skolem = ctx.constant(symbol(ctx,name),sort(ctx,the_sort)); + expr val = tree->Eval(&edge,skolem); + expr_ref thing(ctx.uncook(val),mgr); + substs[0].push_back(thing); + expr local_skolem = tree->Localize(&edge,skolem); + (*local_func_decls).insert(local_skolem.decl()); + } + } - func_decl f = node.Name; - std::vector args; - for(unsigned i = 0; i < edge.F.IndParams.size(); i++) - args.push_back(tree->Eval(&edge,edge.F.IndParams[i])); - expr conc = f(args); + svector > pos; + for(unsigned i = 0; i < edge.Children.size(); i++){ + if(!tree->Empty(edge.Children[i])){ + pos.push_back(std::pair(i+1,0)); + proof_ref prem = extract_proof(d,tree,edge.Children[i]); + prems.push_back(prem); + substs.push_back(expr_ref_vector(mgr)); + } + } + + func_decl f = node.Name; + std::vector args; + for(unsigned i = 0; i < edge.F.IndParams.size(); i++) + args.push_back(tree->Eval(&edge,edge.F.IndParams[i])); + expr conc = f(args); - ::vector< ::proof *> pprems; - for(unsigned i = 0; i < prems.size(); i++) - pprems.push_back(prems[i].get()); + ::vector< ::proof *> pprems; + for(unsigned i = 0; i < prems.size(); i++) + pprems.push_back(prems[i].get()); - proof_ref res(mgr.mk_hyper_resolve(pprems.size(),&pprems[0], ctx.uncook(conc), pos, substs),mgr); - return res; + proof_ref res(mgr.mk_hyper_resolve(pprems.size(),&pprems[0], ctx.uncook(conc), pos, substs),mgr); + return res; -} + } -proof_ref dl_interface::get_proof() { - if(_d->status == StatusRefutation){ - hash_set locals; - local_func_decls = &locals; - return extract_proof(this,_d->cex.get_tree(),_d->cex.get_root()); - } - else - return proof_ref(m_ctx.get_manager()); -} + proof_ref dl_interface::get_proof() { + if(_d->status == StatusRefutation){ + hash_set locals; + local_func_decls = &locals; + return extract_proof(this,_d->cex.get_tree(),_d->cex.get_root()); + } + else + return proof_ref(m_ctx.get_manager()); + } } diff --git a/src/muz/duality/duality_dl_interface.h b/src/muz/duality/duality_dl_interface.h index 19444ca50..0d739f5cc 100644 --- a/src/muz/duality/duality_dl_interface.h +++ b/src/muz/duality/duality_dl_interface.h @@ -1,22 +1,22 @@ /*++ -Copyright (c) 2013 Microsoft Corporation + Copyright (c) 2013 Microsoft Corporation -Module Name: + Module Name: - duality_dl_interface.h + duality_dl_interface.h -Abstract: + Abstract: - SMT2 interface for Duality + SMT2 interface for Duality -Author: + Author: - Krystof Hoder (t-khoder) 2011-9-22. - Modified by Ken McMIllan (kenmcmil) 2013-4-18. + Krystof Hoder (t-khoder) 2011-9-22. + Modified by Ken McMIllan (kenmcmil) 2013-4-18. -Revision History: + Revision History: ---*/ + --*/ #ifndef _DUALITY_DL_INTERFACE_H_ #define _DUALITY_DL_INTERFACE_H_ From f1a1267d4c6cbdf25e36774f329a892921bd394f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 17 Apr 2015 16:08:53 +0100 Subject: [PATCH 636/646] Added missing notes on fpToIEEEBV in Python. --- src/api/python/z3.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index cf4bcd87c..ce1cc2103 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -8480,7 +8480,13 @@ def fpToReal(x): return ArithRef(Z3_mk_fpa_to_real(x.ctx_ref(), x.ast), x.ctx) def fpToIEEEBV(x): - """Create a Z3 floating-point conversion expression, from floating-point expression to IEEE bit-vector. + """\brief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. + + The size of the resulting bit-vector is automatically determined. + + Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion + knows only one NaN and it will always produce the same bit-vector represenatation of + that NaN. >>> x = FP('x', FPSort(8, 24)) >>> y = fpToIEEEBV(x) From 7d88d045149ae10da2609455be1a608ec82f1564 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 20 Apr 2015 00:55:30 +0200 Subject: [PATCH 637/646] fix crash reported by Jojanovich, github issue 45' Signed-off-by: Nikolaj Bjorner --- src/tactic/arith/fix_dl_var_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/arith/fix_dl_var_tactic.cpp b/src/tactic/arith/fix_dl_var_tactic.cpp index 693066ee1..6d9f98f39 100644 --- a/src/tactic/arith/fix_dl_var_tactic.cpp +++ b/src/tactic/arith/fix_dl_var_tactic.cpp @@ -282,7 +282,7 @@ class fix_dl_var_tactic : public tactic { expr_ref new_curr(m); proof_ref new_pr(m); unsigned size = g->size(); - for (unsigned idx = 0; idx < size; idx++) { + for (unsigned idx = 0; !g->inconsistent() && idx < size; idx++) { expr * curr = g->form(idx); m_rw(curr, new_curr, new_pr); if (produce_proofs) { From 6c1a5390ef202499d86fdb41415dada7db1c9d76 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 20 Apr 2015 10:20:06 +0200 Subject: [PATCH 638/646] fix big-int bug for shift amounts, github issue 44, reported by Dejan Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h index b579d698e..a30c0d32c 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h +++ b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h @@ -902,6 +902,7 @@ template void bit_blaster_tpl::mk_shl(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) { numeral k; if (is_numeral(sz, b_bits, k)) { + if (k > numeral(sz)) k = numeral(sz); unsigned n = static_cast(k.get_int64()); if (n >= sz) n = sz; unsigned pos; @@ -947,6 +948,7 @@ template void bit_blaster_tpl::mk_lshr(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) { numeral k; if (is_numeral(sz, b_bits, k)) { + if (k > numeral(sz)) k = numeral(sz); unsigned n = static_cast(k.get_int64()); unsigned pos = 0; for (unsigned i = n; i < sz; pos++, i++) @@ -989,6 +991,7 @@ template void bit_blaster_tpl::mk_ashr(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref_vector & out_bits) { numeral k; if (is_numeral(sz, b_bits, k)) { + if (k > numeral(sz)) k = numeral(sz); unsigned n = static_cast(k.get_int64()); unsigned pos = 0; for (unsigned i = n; i < sz; pos++, i++) From 5f37b1d32fb3b8a6f3e47e11e17a7724ce3aae1d Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Mon, 20 Apr 2015 12:30:15 -0700 Subject: [PATCH 639/646] fixed interp api bug (github issue #47) --- src/interp/iz3interp.cpp | 24 ++++++++++++++++++++++++ src/interp/iz3interp.h | 6 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/interp/iz3interp.cpp b/src/interp/iz3interp.cpp index 9d90a05c7..c9b5e7920 100755 --- a/src/interp/iz3interp.cpp +++ b/src/interp/iz3interp.cpp @@ -398,10 +398,27 @@ public: s.assert_expr(to_expr(cnsts[i].raw())); } + void get_proof_assumptions(z3pf proof, std::vector &cnsts, hash_set &memo){ + if(memo.find(proof) != memo.end())return; + memo.insert(proof); + pfrule dk = pr(proof); + if(dk == PR_ASSERTED) + cnsts.push_back(conc(proof)); + else { + unsigned nprems = num_prems(proof); + for(unsigned i = 0; i < nprems; i++){ + z3pf arg = prem(proof,i); + get_proof_assumptions(arg,cnsts,memo); + } + } + } + iz3interp(ast_manager &_m_manager) : iz3base(_m_manager) {} }; + + void iz3interpolate(ast_manager &_m_manager, ast *proof, const ptr_vector &cnsts, @@ -475,6 +492,13 @@ void iz3interpolate(ast_manager &_m_manager, _cnsts[i] = itp.cook(cnsts[i]); iz3mgr::ast _proof = itp.cook(proof); iz3mgr::ast _tree = itp.cook(tree); + + // if consts isn't provided, we can reconstruct it + if(_cnsts.empty()){ + hash_set memo; + itp.get_proof_assumptions(_proof,_cnsts,memo); + } + itp.proof_to_interpolant(_proof,_cnsts,_tree,_interps,options); interps.resize(_interps.size()); for(unsigned i = 0; i < interps.size(); i++) diff --git a/src/interp/iz3interp.h b/src/interp/iz3interp.h index 2b1926994..c2668eb56 100644 --- a/src/interp/iz3interp.h +++ b/src/interp/iz3interp.h @@ -67,7 +67,11 @@ void iz3interpolate(ast_manager &_m_manager, interpolation_options_struct * options = 0); /* Compute an interpolant from a proof. This version uses the ast - representation, for compatibility with the new API. */ + representation, for compatibility with the new API. Here, cnsts is + a vector of all the assertions in the proof. This can be + over-approximated by the set of all assertions in the + solver. However, if it is empty it will be reconstructed from the + proof, so it can be considered a hint. */ void iz3interpolate(ast_manager &_m_manager, ast *proof, From 8c3fc574d1a20ea537009394b743d92f80595c39 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Apr 2015 15:37:45 +0100 Subject: [PATCH 640/646] comments fix --- src/api/dotnet/Context.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 917b0a954..b4fb954b8 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -2516,7 +2516,7 @@ namespace Microsoft.Z3 /// Create a bit-vector numeral. /// /// value of the numeral. - /// /// the size of the bit-vector + /// the size of the bit-vector public BitVecNum MkBV(long v, uint size) { Contract.Ensures(Contract.Result() != null); From b58d3f4335714ad32c323bd0f84b394940636ea9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Apr 2015 14:26:18 +0100 Subject: [PATCH 641/646] Bugfix for MPF unpacking --- src/util/mpf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index c96ba594e..9de56773a 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -1475,6 +1475,9 @@ void mpf_manager::mk_ninf(unsigned ebits, unsigned sbits, mpf & o) { void mpf_manager::unpack(mpf & o, bool normalize) { // Insert the hidden bit or adjust the exponent of denormal numbers. + if (is_zero(o)) + return; + if (is_normal(o)) m_mpz_manager.add(o.significand, m_powers2(o.sbits-1), o.significand); else { From 4768a360f8428a2b880928de7016176efa2432dd Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Apr 2015 15:01:20 +0100 Subject: [PATCH 642/646] FP: Fix for conversion functions from non-FP 0 to +0.0 even when the rounding mode is ToNegative. --- src/ast/fpa/fpa2bv_converter.cpp | 195 +++++++++++++++++-------------- 1 file changed, 106 insertions(+), 89 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 69b661589..932451ff5 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2096,79 +2096,89 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * bool is_int; m_util.au().is_numeral(x, q, is_int); - scoped_mpf v(m_mpf_manager); - m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); + if (q.is_zero()) + return mk_pzero(f, result); + else { + scoped_mpf v(m_mpf_manager); + m_util.fm().set(v, ebits, sbits, rm, q.to_mpq()); - expr_ref sgn(m), s(m), e(m), unbiased_exp(m); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits); - mk_bias(unbiased_exp, e); - mk_fp(sgn, e, s, result); + + expr_ref sgn(m), s(m), e(m), unbiased_exp(m); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits); + mk_bias(unbiased_exp, e); + + mk_fp(sgn, e, s, result); + } } else if (m_util.au().is_numeral(x)) { rational q; bool is_int; m_util.au().is_numeral(x, q, is_int); - expr_ref rm_nta(m), rm_nte(m), rm_tp(m), rm_tn(m), rm_tz(m); - mk_is_rm(rm, BV_RM_TIES_TO_AWAY, rm_nta); - mk_is_rm(rm, BV_RM_TIES_TO_EVEN, rm_nte); - mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_tp); - mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_tn); - mk_is_rm(rm, BV_RM_TO_ZERO, rm_tz); + if (m_util.au().is_zero(x)) + mk_pzero(f, result); + else { + expr_ref rm_nta(m), rm_nte(m), rm_tp(m), rm_tn(m), rm_tz(m); + mk_is_rm(rm, BV_RM_TIES_TO_AWAY, rm_nta); + mk_is_rm(rm, BV_RM_TIES_TO_EVEN, rm_nte); + mk_is_rm(rm, BV_RM_TO_POSITIVE, rm_tp); + mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_tn); + mk_is_rm(rm, BV_RM_TO_ZERO, rm_tz); - scoped_mpf v_nta(m_mpf_manager), v_nte(m_mpf_manager), v_tp(m_mpf_manager); - scoped_mpf v_tn(m_mpf_manager), v_tz(m_mpf_manager); - m_util.fm().set(v_nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq()); - m_util.fm().set(v_nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq()); - m_util.fm().set(v_tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq()); - m_util.fm().set(v_tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq()); - m_util.fm().set(v_tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq()); + scoped_mpf v_nta(m_mpf_manager), v_nte(m_mpf_manager), v_tp(m_mpf_manager); + scoped_mpf v_tn(m_mpf_manager), v_tz(m_mpf_manager); + m_util.fm().set(v_nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq()); + m_util.fm().set(v_nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq()); + m_util.fm().set(v_tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq()); + m_util.fm().set(v_tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq()); + m_util.fm().set(v_tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq()); - expr_ref v1(m), v2(m), v3(m), v4(m); + expr_ref v1(m), v2(m), v3(m), v4(m); - expr_ref sgn(m), s(m), e(m), unbiased_exp(m); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nta)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v_nta), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nta), ebits); - mk_bias(unbiased_exp, e); - mk_fp(sgn, e, s, v1); + expr_ref sgn(m), s(m), e(m), unbiased_exp(m); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nta)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_nta), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nta), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v1); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nte)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v_nte), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nte), ebits); - mk_bias(unbiased_exp, e); - mk_fp(sgn, e, s, v2); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_nte)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_nte), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_nte), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v2); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); - mk_bias(unbiased_exp, e); - mk_fp(sgn, e, s, v3); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v3); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tn)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v_tn), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tn), ebits); - mk_bias(unbiased_exp, e); - mk_fp(sgn, e, s, v4); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tn)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tn), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tn), ebits); + mk_bias(unbiased_exp, e); + mk_fp(sgn, e, s, v4); - sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); - s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); - unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); - mk_bias(unbiased_exp, e); - - mk_fp(sgn, e, s, result); - mk_ite(rm_tn, v4, result, result); - mk_ite(rm_tp, v3, result, result); - mk_ite(rm_nte, v2, result, result); - mk_ite(rm_nta, v1, result, result); + sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v_tp)) ? 1 : 0, 1); + s = m_bv_util.mk_numeral(m_util.fm().sig(v_tp), sbits - 1); + unbiased_exp = m_bv_util.mk_numeral(m_util.fm().exp(v_tp), ebits); + mk_bias(unbiased_exp, e); + + mk_fp(sgn, e, s, result); + mk_ite(rm_tn, v4, result, result); + mk_ite(rm_tp, v3, result, result); + mk_ite(rm_nte, v2, result, result); + mk_ite(rm_nta, v1, result, result); + } } else { bv_util & bu = m_bv_util; arith_util & au = m_arith_util; - + expr_ref bv0(m), bv1(m), zero(m), two(m); bv0 = bu.mk_numeral(0, 1); bv1 = bu.mk_numeral(1, 1); @@ -2182,6 +2192,10 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * expr_ref rme(rm, m); round(s, rme, sgn, sig, exp, result); + + expr_ref c0(m); + mk_is_zero(x, c0); + mk_ite(c0, x, result, result); expr * e = m.mk_eq(m_util.mk_to_real(result), x); m_extra_assertions.push_back(e); @@ -2209,38 +2223,43 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con SASSERT(e.is_int64()); SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1)); - scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager); - m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator()); - m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator()); + if (q.is_zero()) + return mk_pzero(f, result); + else { + scoped_mpf nte(m_mpf_manager), nta(m_mpf_manager), tp(m_mpf_manager), tn(m_mpf_manager), tz(m_mpf_manager); + m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator()); + m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator()); - app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); - a_nte = m_plugin->mk_numeral(nte); - a_nta = m_plugin->mk_numeral(nta); - a_tp = m_plugin->mk_numeral(tp); - a_tn = m_plugin->mk_numeral(tn); - a_tz = m_plugin->mk_numeral(tz); + app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); + a_nte = m_plugin->mk_numeral(nte); + a_nta = m_plugin->mk_numeral(nta); + a_tp = m_plugin->mk_numeral(tp); + a_tn = m_plugin->mk_numeral(tn); + a_tz = m_plugin->mk_numeral(tz); - expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); - mk_numeral(a_nte->get_decl(), 0, 0, bv_nte); - mk_numeral(a_nta->get_decl(), 0, 0, bv_nta); - mk_numeral(a_tp->get_decl(), 0, 0, bv_tp); - mk_numeral(a_tn->get_decl(), 0, 0, bv_tn); - mk_numeral(a_tz->get_decl(), 0, 0, bv_tz); + expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); + mk_numeral(a_nte->get_decl(), 0, 0, bv_nte); + mk_numeral(a_nta->get_decl(), 0, 0, bv_nta); + mk_numeral(a_tp->get_decl(), 0, 0, bv_tp); + mk_numeral(a_tn->get_decl(), 0, 0, bv_tn); + mk_numeral(a_tz->get_decl(), 0, 0, bv_tz); - expr_ref c1(m), c2(m), c3(m), c4(m); - c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); - c2 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); - c3 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)); - c4 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)); + expr_ref c1(m), c2(m), c3(m), c4(m); + c1 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c2 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); + c3 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)); + c4 = m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)); - mk_ite(c1, bv_tn, bv_tz, result); - mk_ite(c2, bv_tp, result, result); - mk_ite(c3, bv_nta, result, result); - mk_ite(c4, bv_nte, result, result); + mk_ite(c1, bv_tn, bv_tz, result); + mk_ite(c2, bv_tp, result, result); + mk_ite(c3, bv_nta, result, result); + mk_ite(c4, bv_nte, result, result); + } } + void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { TRACE("fpa2bv_to_real", for (unsigned i = 0; i < num; i++) tout << "arg" << i << " = " << mk_ismt2_pp(args[i], m) << std::endl;); @@ -2367,10 +2386,9 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const mk_pinf(f, pinf); // Special case: x == 0 -> p/n zero - expr_ref c1(m), v1(m), rm_is_to_neg(m); - c1 = is_zero; - mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); - mk_ite(rm_is_to_neg, nzero, pzero, v1); + expr_ref c1(m), v1(m); + c1 = is_zero; + v1 = pzero; // Special case: x != 0 expr_ref is_neg_bit(m), exp_too_large(m), sig_4(m), exp_2(m); @@ -2508,10 +2526,9 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con mk_pinf(f, pinf); // Special case: x == 0 -> p/n zero - expr_ref c1(m), v1(m), rm_is_to_neg(m); + expr_ref c1(m), v1(m); c1 = is_zero; - mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); - mk_ite(rm_is_to_neg, nzero, pzero, v1); + v1 = pzero; // Special case: x != 0 expr_ref exp_too_large(m), sig_4(m), exp_2(m); @@ -3182,7 +3199,7 @@ void fpa2bv_converter::unpack(expr * e, expr_ref & sgn, expr_ref & sig, expr_ref m_simp.mk_ite(m.mk_or(is_normal, is_sig_zero), zero_e, lz_d, lz); dbg_decouple("fpa2bv_unpack_lz", lz); - expr_ref shift(m); + expr_ref shift(m); m_simp.mk_ite(is_sig_zero, zero_e, lz, shift); dbg_decouple("fpa2bv_unpack_shift", shift); SASSERT(is_well_sorted(m, is_sig_zero)); From abe73db7028faa08dfcecc50be813344d94d58b5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Apr 2015 15:19:48 +0100 Subject: [PATCH 643/646] FP: bugfix for get_some_value which couldn't produce rounding-mode values. --- src/ast/fpa_decl_plugin.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ast/fpa_decl_plugin.cpp b/src/ast/fpa_decl_plugin.cpp index 48b7adb8b..e559ee179 100644 --- a/src/ast/fpa_decl_plugin.cpp +++ b/src/ast/fpa_decl_plugin.cpp @@ -879,12 +879,20 @@ void fpa_decl_plugin::get_sort_names(svector & sort_names, symbol } expr * fpa_decl_plugin::get_some_value(sort * s) { - SASSERT(s->is_sort_of(m_family_id, FLOATING_POINT_SORT)); - mpf tmp; - m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp); - expr * res = this->mk_numeral(tmp); - m_fm.del(tmp); - return res; + if (s->is_sort_of(m_family_id, FLOATING_POINT_SORT)) { + mpf tmp; + m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp); + expr * res = mk_numeral(tmp); + m_fm.del(tmp); + return res; + } + else if (s->is_sort_of(m_family_id, ROUNDING_MODE_SORT)) { + func_decl * f = mk_rm_const_decl(OP_FPA_RM_TOWARD_ZERO, 0, 0, 0, 0, s); + return m_manager->mk_const(f); + } + + UNREACHABLE(); + return 0; } bool fpa_decl_plugin::is_value(app * e) const { From f7d9438e7b3270893af5711a7a2ab787f2d68307 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Mon, 27 Apr 2015 17:44:38 +0100 Subject: [PATCH 644/646] add failing test for issue #62 (mk_distinct doesnt type check) Signed-off-by: Nuno Lopes --- src/test/api.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/api.cpp b/src/test/api.cpp index a09371f01..6230528a1 100644 --- a/src/test/api.cpp +++ b/src/test/api.cpp @@ -447,9 +447,27 @@ void test_bvneg() { Z3_del_context(ctx); } +static bool cb_called = false; +static void my_cb(Z3_context, Z3_error_code) { + cb_called = true; +} + +static void test_mk_distinct() { + Z3_config cfg = Z3_mk_config(); + Z3_context ctx = Z3_mk_context(cfg); + Z3_set_error_handler(ctx, my_cb); + + Z3_sort bv8 = Z3_mk_bv_sort(ctx, 8); + Z3_sort bv32 = Z3_mk_bv_sort(ctx, 32); + Z3_ast args[] = { Z3_mk_int64(ctx, 0, bv8), Z3_mk_int64(ctx, 0, bv32) }; + Z3_mk_distinct(ctx, 2, args); + SASSERT(cb_called); +} + void tst_api() { test_apps(); test_bvneg(); + test_mk_distinct(); // bv_invariant(); } #else From 620c11932b10d5218069668c2ef766ffe7c6b84f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 27 Apr 2015 11:10:37 -0700 Subject: [PATCH 645/646] type check distinct operator. fixes #62 Signed-off-by: Nikolaj Bjorner --- src/ast/ast.cpp | 11 +++++++++++ src/ast/ast.h | 2 +- src/test/api.cpp | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 6780145d9..3a6275e33 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1043,6 +1043,13 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_DISTINCT: { func_decl_info info(m_family_id, OP_DISTINCT); info.set_pairwise(); + for (unsigned i = 1; i < arity; i++) { + if (domain[i] != domain[0]) { + std::ostringstream buffer; + buffer << "Sort mismatch between first argument and argument " << (i+1); + throw ast_exception(buffer.str().c_str()); + } + } return m_manager->mk_func_decl(symbol("distinct"), arity, domain, m_bool_sort, info); } default: @@ -2338,6 +2345,10 @@ quantifier * ast_manager::update_quantifier(quantifier * q, bool is_forall, unsi num_patterns == 0 ? q->get_no_patterns() : 0); } +app * ast_manager::mk_distinct(unsigned num_args, expr * const * args) { + return mk_app(m_basic_family_id, OP_DISTINCT, num_args, args); +} + app * ast_manager::mk_distinct_expanded(unsigned num_args, expr * const * args) { if (num_args < 2) return mk_true(); diff --git a/src/ast/ast.h b/src/ast/ast.h index 93f456965..a5f5c286f 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -2000,7 +2000,7 @@ public: app * mk_and(expr * arg1, expr * arg2, expr * arg3) { return mk_app(m_basic_family_id, OP_AND, arg1, arg2, arg3); } app * mk_implies(expr * arg1, expr * arg2) { return mk_app(m_basic_family_id, OP_IMPLIES, arg1, arg2); } app * mk_not(expr * n) { return mk_app(m_basic_family_id, OP_NOT, n); } - app * mk_distinct(unsigned num_args, expr * const * args) { return mk_app(m_basic_family_id, OP_DISTINCT, num_args, args); } + app * mk_distinct(unsigned num_args, expr * const * args); app * mk_distinct_expanded(unsigned num_args, expr * const * args); app * mk_true() { return m_true; } app * mk_false() { return m_false; } diff --git a/src/test/api.cpp b/src/test/api.cpp index 6230528a1..234d1192c 100644 --- a/src/test/api.cpp +++ b/src/test/api.cpp @@ -460,8 +460,9 @@ static void test_mk_distinct() { Z3_sort bv8 = Z3_mk_bv_sort(ctx, 8); Z3_sort bv32 = Z3_mk_bv_sort(ctx, 32); Z3_ast args[] = { Z3_mk_int64(ctx, 0, bv8), Z3_mk_int64(ctx, 0, bv32) }; - Z3_mk_distinct(ctx, 2, args); + Z3_ast d = Z3_mk_distinct(ctx, 2, args); SASSERT(cb_called); + } void tst_api() { From 1abeb825a35a620ff27a409a8d09d676e1395d95 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 28 Apr 2015 14:58:58 +0100 Subject: [PATCH 646/646] Fixed python 3.x problems. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_win_dist.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 33d7a3eab..db4cc48e3 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -47,16 +47,16 @@ def set_build_dir(path): mk_dir(BUILD_X64_DIR) def display_help(): - print "mk_win_dist.py: Z3 Windows distribution generator\n" - print "This script generates the zip files containing executables, dlls, header files for Windows." - print "It must be executed from the Z3 root directory." - print "\nOptions:" - print " -h, --help display this message." - print " -s, --silent do not print verbose messages." - print " -b , --build= subdirectory where x86 and x64 Z3 versions will be built (default: build-dist)." - print " -f, --force force script to regenerate Makefiles." - print " --nojava do not include Java bindings in the binary distribution files." - print " --githash include git hash in the Zip file." + print("mk_win_dist.py: Z3 Windows distribution generator\n") + print("This script generates the zip files containing executables, dlls, header files for Windows.") + print("It must be executed from the Z3 root directory.") + print("\nOptions:") + print(" -h, --help display this message.") + print(" -s, --silent do not print verbose messages.") + print(" -b , --build= subdirectory where x86 and x64 Z3 versions will be built (default: build-dist).") + print(" -f, --force force script to regenerate Makefiles.") + print(" --nojava do not include Java bindings in the binary distribution files.") + print(" --githash include git hash in the Zip file.") exit(0) # Parse configuration option for mk_make script @@ -180,7 +180,7 @@ def mk_dist_dir_core(x64): mk_util.JAVA_ENABLED = JAVA_ENABLED mk_win_dist(build_path, dist_path) if is_verbose(): - print "Generated %s distribution folder at '%s'" % (platform, dist_path) + print("Generated %s distribution folder at '%s'") % (platform, dist_path) def mk_dist_dir(): mk_dist_dir_core(False) @@ -208,7 +208,7 @@ def mk_zip_core(x64): ZIPOUT = zipfile.ZipFile(zfname, 'w', zipfile.ZIP_DEFLATED) os.path.walk(dist_path, mk_zip_visitor, '*') if is_verbose(): - print "Generated '%s'" % zfname + print("Generated '%s'") % zfname except: pass ZIPOUT = None @@ -253,7 +253,7 @@ def cp_vs_runtime_core(x64): for f in VS_RUNTIME_FILES: shutil.copy(f, bin_dist_path) if is_verbose(): - print "Copied '%s' to '%s'" % (f, bin_dist_path) + print("Copied '%s' to '%s'") % (f, bin_dist_path) def cp_vs_runtime(): cp_vs_runtime_core(True)